private static void SetBinding()

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;
            }
        }