in src/Microsoft.IIS.Administration.WebServer.Sites/SiteHelper.cs [521:675]
private static void SetBinding(Binding binding, dynamic obj) {
string protocol = DynamicHelper.Value(obj.protocol);
string bindingInformation = DynamicHelper.Value(obj.binding_information);
bool? requireSni = DynamicHelper.To<bool>(obj.require_sni);
if (protocol == null) {
throw new ApiArgumentException("binding.protocol");
}
binding.Protocol = protocol;
bool isHttp = protocol.Equals("http") || protocol.Equals("https");
if (isHttp) {
//
// HTTP Binding information provides port, ip address, and hostname
UInt16 port;
string hostname;
IPAddress ipAddress = null;
if (bindingInformation == null) {
var ip = DynamicHelper.Value(obj.ip_address);
if (ip == "*") {
ipAddress = IPAddress.Any;
}
else if (!IPAddress.TryParse(ip, out ipAddress)) {
throw new ApiArgumentException("binding.ip_address");
}
UInt16? p = (UInt16?)DynamicHelper.To(obj.port, 1, UInt16.MaxValue);
if (p == null) {
throw new ApiArgumentException("binding.port");
}
port = p.Value;
hostname = DynamicHelper.Value(obj.hostname) ?? string.Empty;
}
else {
var parts = bindingInformation.Split(':');
if (parts.Length != 3) {
throw new ApiArgumentException("binding.binding_information");
}
if (parts[0] == "*") {
ipAddress = IPAddress.Any;
}
else if (!IPAddress.TryParse(parts[0], out ipAddress)) {
throw new ApiArgumentException("binding.binding_information");
}
if (!UInt16.TryParse(parts[1], out port)) {
throw new ApiArgumentException("binding.binding_information");
}
hostname = parts[2];
}
binding.Protocol = protocol;
// HTTPS
if (protocol.Equals("https")) {
if (string.IsNullOrEmpty(hostname) && requireSni.HasValue && requireSni.Value) {
throw new ApiArgumentException("binding.require_sni");
}
if (obj.certificate == null || !(obj.certificate is JObject)) {
throw new ApiArgumentException("binding.certificate");
}
dynamic certificate = obj.certificate;
string uuid = DynamicHelper.Value(certificate.id);
if (string.IsNullOrEmpty(uuid)) {
throw new ApiArgumentException("binding.certificate.id");
}
CertificateId id = new CertificateId(uuid);
ICertificateStore store = CertificateStoreProviderAccessor.Instance?.Stores
.FirstOrDefault(s => s.Name.Equals(id.StoreName, StringComparison.OrdinalIgnoreCase));
ICertificate cert = null;
if (store != null) {
cert = store.GetCertificate(id.Id).Result;
}
if (cert == null) {
throw new NotFoundException("binding.certificate");
}
if (!cert.PurposesOID.Contains(OIDServerAuth)) {
throw new ApiArgumentException("binding.certificate", "Certificate does not support server authentication");
}
//
// Windows builtin store
if (store is IWindowsCertificateStore) {
// The specified certificate must be in the store with a private key or else there will be an exception when we commit
if (cert == null) {
throw new NotFoundException("binding.certificate");
}
if (!cert.HasPrivateKey) {
throw new ApiArgumentException("binding.certificate", "Certificate must have a private key");
}
List<byte> bytes = new List<byte>();
// Decode the hex string of the certificate hash into bytes
for (int i = 0; i < id.Id.Length; i += 2) {
bytes.Add(Convert.ToByte(id.Id.Substring(i, 2), 16));
}
binding.CertificateStoreName = id.StoreName;
binding.CertificateHash = bytes.ToArray();
}
//
// IIS Central Certificate store
else if (store is ICentralCertificateStore) {
string name = Path.GetFileNameWithoutExtension(cert.Alias);
if (string.IsNullOrEmpty(hostname) || !hostname.Replace('*', '_').Equals(name)) {
throw new ApiArgumentException("binding.hostname", "Hostname must match certificate file name for central certificate store");
}
binding.SslFlags |= SslFlags.CentralCertStore;
}
if (requireSni.HasValue) {
if (!binding.Schema.HasAttribute(sslFlagsAttribute)) {
// throw on IIS 7.5 which does not have SNI support
throw new ApiArgumentException("binding.require_sni", "SNI not supported on this machine");
}
if (requireSni.Value) {
binding.SslFlags |= SslFlags.Sni;
}
else {
binding.SslFlags &= ~SslFlags.Sni;
}
}
}
var ipModel = ipAddress.Equals(IPAddress.Any) ? "*" : ipAddress.ToString();
binding.BindingInformation = $"{ipModel}:{port}:{hostname}";
}
else {
//
// Custom protocol
if (string.IsNullOrEmpty(bindingInformation)) {
throw new ApiArgumentException("binding.binding_information");
}
binding.BindingInformation = bindingInformation;
}
}