pike.git / lib / modules / SSL.pmod / Context.pike

version» Context lines:

pike.git/lib/modules/SSL.pmod/Context.pike:35: Inside #if defined(SSL3_DEBUG)
     #ifdef SSL3_DEBUG   #define SSL3_DEBUG_MSG(X ...) werror(X)   #else /*! SSL3_DEBUG */   #define SSL3_DEBUG_MSG(X ...)   #endif /* SSL3_DEBUG */      import ".";   import Constants;    + protected void create() + { +  SSL3_DEBUG_MSG("SSL.Context->create\n"); +  +  /* Backwards compatibility */ +  preferred_suites = get_suites(128, 1); + } +    //! The minimum supported protocol version.   //!   //! Defaults to @[PROTOCOL_SSL_3_0].   //!   //! @note   //! This value should not be greater than @[max_version].   ProtocolVersion min_version = PROTOCOL_SSL_3_0;      //! The maximum supported protocol version.   //!   //! Defaults to @[PROTOCOL_TLS_MAX].   //!   //! @note   //! This value should not be less than @[min_version].   ProtocolVersion max_version = PROTOCOL_TLS_MAX;    -  + //! List of advertised protocols using using TLS application level + //! protocol negotiation. + array(string(8bit)) advertised_protocols; +  + //! The maximum amount of data that is sent in each SSL packet by + //! @[File]. A value between 1 and @[Constants.PACKET_MAX_SIZE]. + int packet_max_size = PACKET_MAX_SIZE; +  + //! Lists the supported compression algorithms in order of preference. + //! + //! Defaults to @expr{({ COMPRESSION_null, COMPRESSION_deflate })@} + //! (ie avoid compression unless the client requires it) due to + //! SSL attacks that target compression. + array(int) preferred_compressors = ({ +  COMPRESSION_null, + #if constant(Gz) +  COMPRESSION_deflate, + #endif +  }); +    //! @decl Alert alert_factory(SSL.Connection con, int level, int description, @   //! ProtocolVersion version, @   //! string|void message, mixed|void trace)   //!   //! Alert factory.   //!   //! This function may be overloaded to eg obtain logging of   //! generated alerts.   //!   //! @param con
pike.git/lib/modules/SSL.pmod/Context.pike:82:   //! @note   //! Not all alerts are fatal, and some (eg @[ALERT_close_notify]) are used   //! during normal operation.   Alert alert_factory(object con,    int(1..2) level, int(8bit) description,    ProtocolVersion version, string|void message)   {    return Alert(level, description, version, message);   }    - //! Policy for client authentication. One of - //! @[SSL.Constants.AUTHLEVEL_none], @[SSL.Constants.AUTHLEVEL_ask] - //! and @[SSL.Constants.AUTHLEVEL_require]. - int auth_level; +     - //! Array of authorities that are accepted for client certificates. - //! The server will only accept connections from clients whose - //! certificate is signed by one of these authorities. The string is a - //! DER-encoded certificate, which typically must be decoded using - //! @[MIME.decode_base64] or @[Standards.PEM.Messages] first. - //! - //! Note that it is presumed that the issuer will also be trusted by - //! the server. See @[trusted_issuers] for details on specifying - //! trusted issuers. - //! - //! If empty, the server will accept any client certificate whose - //! issuer is trusted by the server. - void set_authorities(array(string) a) - { -  authorities = a; -  update_authorities(); - } + // + // --- Cryptography + //    - //! When set, require the chain to be known, even if the root is self - //! signed. - //! - //! Note that if set, and certificates are set to be verified, trusted - //! issuers must be provided, or no connections will be accepted. - int require_trust=0; -  - //! Get the list of allowed authorities. See @[set_authorities]. - array(string) get_authorities() - { -  return authorities; - } -  - protected array(string) authorities = ({}); - array(string(8bit)) authorities_cache = ({}); -  - //! Sets the list of trusted certificate issuers. - //! - //! @param a - //! - //! An array of certificate chains whose root is self signed (ie a - //! root issuer), and whose final certificate is an issuer that we - //! trust. The root of the certificate should be first certificate in - //! the chain. The string is a DER-encoded certificate, which - //! typically must be decoded using @[MIME.decode_base64] or - //! @[Standards.PEM.Messages] first. - //! - //! If this array is left empty, and the context is set to verify - //! certificates, a certificate chain must have a root that is self - //! signed. - void set_trusted_issuers(array(array(string)) i) - { -  trusted_issuers = i; -  update_trusted_issuers(); - } -  - //! Get the list of trusted issuers. See @[set_trusted_issuers]. - array(array(string)) get_trusted_issuers() - { -  return trusted_issuers; - } -  - protected array(array(string)) trusted_issuers = ({}); - mapping(string:array(Standards.X509.Verifier)) trusted_issuers_cache = ([]); -  - //! Determines whether certificates presented by the peer are - //! verified, or just accepted as being valid. - int verify_certificates = 0; -  +    //! Temporary, non-certified, private keys, used for RSA key exchange   //! in export mode. They are used as follows:   //!   //! @[short_rsa] is a 512-bit RSA key used for the SSL 3.0 and TLS 1.0   //! export cipher suites.   //!   //! @[long_rsa] is a 1024-bit RSA key to be used for the RSA_EXPORT1024   //! suites from draft-ietf-tls-56-bit-ciphersuites-01.txt.   //!   //! They have associated counters @[short_rsa_counter] and @[long_rsa_counter],
pike.git/lib/modules/SSL.pmod/Context.pike:181:   //! Counters for export RSA keys.   int long_rsa_counter;   int short_rsa_counter;      //! Used to generate random cookies for the hello-message. If we use   //! the RSA keyexchange method, and this is a server, this random   //! number generator is not used for generating the master_secret. By   //! default set to @[Crypto.Random.random_string].   function(int(0..):string(8bit)) random = Crypto.Random.random_string;    - //! Certificates and their corresponding keys. - array(CertificatePair) cert_pairs = ({}); + //! Attempt to enable encrypt-then-mac mode. + int encrypt_then_mac = 1;    - protected int(0..1) cert_pairs_sorted = 0; -  - //! Lookup from SNI (Server Name Indication) (server), or Issuer DER - //! (client) to an array of suitable @[CertificatePair]s. - //! - //! Generated on demand from @[cert_pairs]. - mapping(string(8bit):array(CertificatePair)) cert_cache = ([]); -  - //! For client authentication. Used only if auth_level is AUTH_ask or - //! AUTH_require. - array(int) preferred_auth_methods = - ({ AUTH_rsa_sign }); -  +    //! Cipher suites we want to support, in order of preference, best   //! first.   array(int) preferred_suites;      //! Supported elliptical curve cipher curves in order of preference.   array(int) ecc_curves = reverse(sort(indices(ECC_CURVES)));    - //! List of advertised protocols using using TLS application level - //! protocol negotiation. - array(string(8bit)) advertised_protocols; -  - //! The maximum amount of data that is sent in each SSL packet by - //! @[File]. A value between 1 and @[Constants.PACKET_MAX_SIZE]. - int packet_max_size = PACKET_MAX_SIZE; -  +    //! The set of <hash, signature> combinations to use by us.   //!   //! Only used with TLS 1.2 and later.   //!   //! Defaults to all combinations supported by Pike except for MD5.   //!   //! This list is typically filtered by @[get_signature_algorithms()]   //! to get rid of combinations not supported by the runtime.   //!   //! @note
pike.git/lib/modules/SSL.pmod/Context.pike:296: Inside #if !constant(Crypto.SHA224)
  #endif   #if !constant(Crypto.SHA224)    HASH_sha224,   #endif    >)[hash]) return 0;    return 1;    });   #endif   }    - protected int cert_sort_key(CertificatePair cp) - { -  array(HashAlgorithm|SignatureAlgorithm) sign_alg = cp->sign_algs[0]; -  int bits = cp->key->key_size(); -  -  // Adjust the bits to be comparable for the different algorithms. -  switch(sign_alg[1]) { -  case SIGNATURE_rsa: -  // The normative size. -  break; -  case SIGNATURE_dsa: -  // The consensus seems to be that DSA keys are about -  // the same strength as the corresponding RSA length. -  break; -  case SIGNATURE_ecdsa: -  // ECDSA size: NIST says: Our approximation: -  // 160 bits ~1024 bits RSA 960 bits RSA -  // 224 bits ~2048 bits RSA 2240 bits RSA -  // 256 bits ~4096 bits RSA 3072 bits RSA -  // 384 bits ~7680 bits RSA 7680 bits RSA -  // 521 bits ~15360 bits RSA 14881 bits RSA -  bits = (bits * (bits - 64))>>4; -  if (bits < 0) bits = 128; -  break; -  } -  -  // NB: Returns negative to get the largest values sorted first. -  return -((bits<<16)|(sign_alg[1]<<8)|sign_alg[0]); - } -  - //! Order the @[cps] in priority order. - protected array(CertificatePair) sort_certs(array(CertificatePair) cps) - { -  if (sizeof(cps) > 1) { -  sort(map(cps, cert_sort_key), cps); -  } -  return cps; - } -  - //! Look up a suitable set of certificates for the specified SNI (server) - //! or issuer (client). - //! - //! @param is_issuer - //! Indicates whether to @[glob]-match against the common name (server), - //! or against the DER for the issuer (client). - array(CertificatePair) find_cert(array(string)|void sni_or_issuer, -  int(0..1)|void is_issuer) - { -  if (!cert_pairs_sorted) { -  cert_pairs = sort_certs(cert_pairs); -  cert_pairs_sorted = 1; -  } -  -  if (!sizeof(sni_or_issuer || ({}))) { -  // Either no/empty SNI, or empty certificate_authorities list. -  -  if (!is_issuer) { -  // First check if there's a set of default certs. -  // Note: This doubles as a cache lookup of the -  // fallback entry set further below. -  array(CertificatePair) res = find_cert(({ "" }), is_issuer); -  if (res && sizeof(res)) return res; -  -  // Fall back to returning the entire set, since -  // they are presumably all valid for the server. -  } -  -  // RFC 4346 7.4.4 -  // If the certificate_authorities list is empty then the client MAY -  // send any certificate of the appropriate ClientCertificateType, -  // unless there is some external arrangement to the contrary. -  return cert_cache[""] = cert_pairs; -  } -  -  mapping(string(8bit):array(CertificatePair)) certs = ([]); -  array(string(8bit)) maybes = ({}); -  -  if (!is_issuer) { -  sni_or_issuer = [array(string(8bit))]map(sni_or_issuer, lower_case); -  } -  -  foreach(sni_or_issuer, string name) { -  array(CertificatePair) res; -  if (res = cert_cache[name]) { -  certs[name] = res; -  continue; -  } -  if (zero_type(res)) { -  // Not known bad. -  certs[name] = ({}); -  maybes += ({ name }); -  } -  } -  -  if (sizeof(maybes)) { -  // There were some unknown names. Check them. -  if (is_issuer) { -  foreach(cert_pairs, CertificatePair cp) { -  foreach(maybes, string(8bit) i) { -  if (has_value(cp->issuers, i)) { -  certs[i] += ({ cp }); -  } -  } -  } -  } else { -  foreach(cert_pairs, CertificatePair cp) { -  foreach(cp->globs, string(8bit) g) { -  foreach(glob(g, maybes), string name) { -  certs[name] += ({ cp }); -  } -  } -  } -  } -  -  if (sizeof(cert_cache) > (sizeof(cert_pairs) * 10 + 10)) { -  // It seems the cache has been poisoned. Clean it. -  cert_cache = ([]); -  } -  -  // Update the cache. -  foreach(maybes, string name) { -  cert_cache[name] = certs[name]; -  } -  } -  -  // No certificate found. -  if (!sizeof(certs)) return UNDEFINED; -  -  if (sizeof(certs) == 1) { -  // Just a single matching name. -  return values(certs)[0]; -  } -  -  return sort_certs(values(certs) * ({})); - } -  - //! Add a certificate. - //! - //! This function is used on both servers and clients to add - //! a key and chain of certificates to the set of certificate - //! candidates to use in @[find_cert()]. - //! - //! On a server these are used in the normal initial handshake, - //! while on a client they are only used if a server requests - //! client certificate authentication. - //! - //! @param key - //! Private key matching the first certificate in @[certs]. - //! - //! Supported key types are currently: - //! @mixed - //! @type Crypto.RSA - //! Rivest-Shamir-Adelman. - //! @type Crypto.DSA - //! Digital Signing Algorithm. - //! @type Crypto.ECC.Curve.ECDSA - //! Elliptic Curve Digital Signing Algorithm. - //! @endmixed - //! - //! This key MUST match the public key in the first certificate - //! in @[certs]. - //! - //! @param certs - //! A chain of X509.v1 or X509.v3 certificates, with the local - //! certificate first and root-most certificate last. - //! - //! @param extra_name_globs - //! Further SNI globs (than the ones in the first certificate), that - //! this certificate should be selected for. Typically used to set - //! the default certificate(s) by specifying @expr{({ "*" })@}. - //! - //! The SNI globs are only relevant for server-side certificates. - //! - //! @param cp - //! An alternative is to send an initialized @[CertificatePair]. - //! - //! @throws - //! The function performs various validation of the @[key] - //! and @[certs], and throws errors if the validation fails. - //! - //! @seealso - //! @[find_cert()] - void add_cert(Crypto.Sign key, array(string(8bit)) certs, -  array(string(8bit))|void extra_name_globs) - { -  CertificatePair cp = CertificatePair(key, certs, extra_name_globs); -  -  cert_pairs += ({ cp }); -  -  cert_pairs_sorted = 0; -  -  cert_cache = ([]); - } - variant void add_cert(CertificatePair cp) - { -  cert_pairs += ({ cp }); -  -  cert_pairs_sorted = 0; -  -  cert_cache = ([]); - } -  +    // Generate a sort key for a cipher suite.   //   // The larger the value, the stronger the cipher suite.   protected int cipher_suite_sort_key(int suite)   {    array(int) info = [array(int)] (CIPHER_SUITES[suite] || ({ 0, 0, 0 }));       int keylength = CIPHER_effective_keylengths[info[1]];       // NB: Currently the hash algorithms are allocated in a suitable order.
pike.git/lib/modules/SSL.pmod/Context.pike:811: Inside #if constant(Crypto.ECC.Curve) && constant(Crypto.AES.GCM) && constant(Crypto.SHA384)
   if (strictness_level < 1) {    // Permissive mode. Add the remaining suites of    // the required strength.    preferred_suites += get_suites(min_keylength) - preferred_suites;    }    }   }      #endif /* Crypto.ECC.Curve && Crypto.AES.GCM && Crypto.SHA384 */    - //! Lists the supported compression algorithms in order of preference. +  + // + // --- Certificates and authentication + // +  + //! Policy for client authentication. One of + //! @[SSL.Constants.AUTHLEVEL_none], @[SSL.Constants.AUTHLEVEL_ask] + //! and @[SSL.Constants.AUTHLEVEL_require]. + int auth_level; +  + //! Array of authorities that are accepted for client certificates. + //! The server will only accept connections from clients whose + //! certificate is signed by one of these authorities. The string is a + //! DER-encoded certificate, which typically must be decoded using + //! @[MIME.decode_base64] or @[Standards.PEM.Messages] first.   //! - //! Defaults to @expr{({ COMPRESSION_null, COMPRESSION_deflate })@} - //! (ie avoid compression unless the client requires it) due to - //! SSL attacks that target compression. - array(int) preferred_compressors = ({ -  COMPRESSION_null, - #if constant(Gz) -  COMPRESSION_deflate, - #endif -  }); + //! Note that it is presumed that the issuer will also be trusted by + //! the server. See @[trusted_issuers] for details on specifying + //! trusted issuers. + //! + //! If empty, the server will accept any client certificate whose + //! issuer is trusted by the server. + void set_authorities(array(string) a) + { +  authorities = a; +  update_authorities(); + }    - //! Attempt to enable encrypt-then-mac mode. - int encrypt_then_mac = 1; + //! When set, require the chain to be known, even if the root is self + //! signed. + //! + //! Note that if set, and certificates are set to be verified, trusted + //! issuers must be provided, or no connections will be accepted. + int require_trust=0;    -  + //! Get the list of allowed authorities. See @[set_authorities]. + array(string) get_authorities() + { +  return authorities; + } +  + protected array(string) authorities = ({}); + array(string(8bit)) authorities_cache = ({}); +  + //! Sets the list of trusted certificate issuers. + //! + //! @param a + //! + //! An array of certificate chains whose root is self signed (ie a + //! root issuer), and whose final certificate is an issuer that we + //! trust. The root of the certificate should be first certificate in + //! the chain. The string is a DER-encoded certificate, which + //! typically must be decoded using @[MIME.decode_base64] or + //! @[Standards.PEM.Messages] first. + //! + //! If this array is left empty, and the context is set to verify + //! certificates, a certificate chain must have a root that is self + //! signed. + void set_trusted_issuers(array(array(string)) i) + { +  trusted_issuers = i; +  update_trusted_issuers(); + } +  + //! Get the list of trusted issuers. See @[set_trusted_issuers]. + array(array(string)) get_trusted_issuers() + { +  return trusted_issuers; + } +  + protected array(array(string)) trusted_issuers = ({}); + mapping(string:array(Standards.X509.Verifier)) trusted_issuers_cache = ([]); +  + //! Determines whether certificates presented by the peer are + //! verified, or just accepted as being valid. + int verify_certificates = 0; +  + //! Certificates and their corresponding keys. + array(CertificatePair) cert_pairs = ({}); +  + protected int(0..1) cert_pairs_sorted = 0; +  + //! Lookup from SNI (Server Name Indication) (server), or Issuer DER + //! (client) to an array of suitable @[CertificatePair]s. + //! + //! Generated on demand from @[cert_pairs]. + mapping(string(8bit):array(CertificatePair)) cert_cache = ([]); +  + //! For client authentication. Used only if auth_level is AUTH_ask or + //! AUTH_require. + array(int) preferred_auth_methods = + ({ AUTH_rsa_sign }); +  + protected int cert_sort_key(CertificatePair cp) + { +  array(HashAlgorithm|SignatureAlgorithm) sign_alg = cp->sign_algs[0]; +  int bits = cp->key->key_size(); +  +  // Adjust the bits to be comparable for the different algorithms. +  switch(sign_alg[1]) { +  case SIGNATURE_rsa: +  // The normative size. +  break; +  case SIGNATURE_dsa: +  // The consensus seems to be that DSA keys are about +  // the same strength as the corresponding RSA length. +  break; +  case SIGNATURE_ecdsa: +  // ECDSA size: NIST says: Our approximation: +  // 160 bits ~1024 bits RSA 960 bits RSA +  // 224 bits ~2048 bits RSA 2240 bits RSA +  // 256 bits ~4096 bits RSA 3072 bits RSA +  // 384 bits ~7680 bits RSA 7680 bits RSA +  // 521 bits ~15360 bits RSA 14881 bits RSA +  bits = (bits * (bits - 64))>>4; +  if (bits < 0) bits = 128; +  break; +  } +  +  // NB: Returns negative to get the largest values sorted first. +  return -((bits<<16)|(sign_alg[1]<<8)|sign_alg[0]); + } +  + //! Order the @[cps] in priority order. + protected array(CertificatePair) sort_certs(array(CertificatePair) cps) + { +  if (sizeof(cps) > 1) { +  sort(map(cps, cert_sort_key), cps); +  } +  return cps; + } +  + //! Look up a suitable set of certificates for the specified SNI (server) + //! or issuer (client). + //! + //! @param is_issuer + //! Indicates whether to @[glob]-match against the common name (server), + //! or against the DER for the issuer (client). + array(CertificatePair) find_cert(array(string)|void sni_or_issuer, +  int(0..1)|void is_issuer) + { +  if (!cert_pairs_sorted) { +  cert_pairs = sort_certs(cert_pairs); +  cert_pairs_sorted = 1; +  } +  +  if (!sizeof(sni_or_issuer || ({}))) { +  // Either no/empty SNI, or empty certificate_authorities list. +  +  if (!is_issuer) { +  // First check if there's a set of default certs. +  // Note: This doubles as a cache lookup of the +  // fallback entry set further below. +  array(CertificatePair) res = find_cert(({ "" }), is_issuer); +  if (res && sizeof(res)) return res; +  +  // Fall back to returning the entire set, since +  // they are presumably all valid for the server. +  } +  +  // RFC 4346 7.4.4 +  // If the certificate_authorities list is empty then the client MAY +  // send any certificate of the appropriate ClientCertificateType, +  // unless there is some external arrangement to the contrary. +  return cert_cache[""] = cert_pairs; +  } +  +  mapping(string(8bit):array(CertificatePair)) certs = ([]); +  array(string(8bit)) maybes = ({}); +  +  if (!is_issuer) { +  sni_or_issuer = [array(string(8bit))]map(sni_or_issuer, lower_case); +  } +  +  foreach(sni_or_issuer, string name) { +  array(CertificatePair) res; +  if (res = cert_cache[name]) { +  certs[name] = res; +  continue; +  } +  if (zero_type(res)) { +  // Not known bad. +  certs[name] = ({}); +  maybes += ({ name }); +  } +  } +  +  if (sizeof(maybes)) { +  // There were some unknown names. Check them. +  if (is_issuer) { +  foreach(cert_pairs, CertificatePair cp) { +  foreach(maybes, string(8bit) i) { +  if (has_value(cp->issuers, i)) { +  certs[i] += ({ cp }); +  } +  } +  } +  } else { +  foreach(cert_pairs, CertificatePair cp) { +  foreach(cp->globs, string(8bit) g) { +  foreach(glob(g, maybes), string name) { +  certs[name] += ({ cp }); +  } +  } +  } +  } +  +  if (sizeof(cert_cache) > (sizeof(cert_pairs) * 10 + 10)) { +  // It seems the cache has been poisoned. Clean it. +  cert_cache = ([]); +  } +  +  // Update the cache. +  foreach(maybes, string name) { +  cert_cache[name] = certs[name]; +  } +  } +  +  // No certificate found. +  if (!sizeof(certs)) return UNDEFINED; +  +  if (sizeof(certs) == 1) { +  // Just a single matching name. +  return values(certs)[0]; +  } +  +  return sort_certs(values(certs) * ({})); + } +  + //! Add a certificate. + //! + //! This function is used on both servers and clients to add + //! a key and chain of certificates to the set of certificate + //! candidates to use in @[find_cert()]. + //! + //! On a server these are used in the normal initial handshake, + //! while on a client they are only used if a server requests + //! client certificate authentication. + //! + //! @param key + //! Private key matching the first certificate in @[certs]. + //! + //! Supported key types are currently: + //! @mixed + //! @type Crypto.RSA + //! Rivest-Shamir-Adelman. + //! @type Crypto.DSA + //! Digital Signing Algorithm. + //! @type Crypto.ECC.Curve.ECDSA + //! Elliptic Curve Digital Signing Algorithm. + //! @endmixed + //! + //! This key MUST match the public key in the first certificate + //! in @[certs]. + //! + //! @param certs + //! A chain of X509.v1 or X509.v3 certificates, with the local + //! certificate first and root-most certificate last. + //! + //! @param extra_name_globs + //! Further SNI globs (than the ones in the first certificate), that + //! this certificate should be selected for. Typically used to set + //! the default certificate(s) by specifying @expr{({ "*" })@}. + //! + //! The SNI globs are only relevant for server-side certificates. + //! + //! @param cp + //! An alternative is to send an initialized @[CertificatePair]. + //! + //! @throws + //! The function performs various validation of the @[key] + //! and @[certs], and throws errors if the validation fails. + //! + //! @seealso + //! @[find_cert()] + void add_cert(Crypto.Sign key, array(string(8bit)) certs, +  array(string(8bit))|void extra_name_globs) + { +  CertificatePair cp = CertificatePair(key, certs, extra_name_globs); +  +  cert_pairs += ({ cp }); +  +  cert_pairs_sorted = 0; +  +  cert_cache = ([]); + } + variant void add_cert(CertificatePair cp) + { +  cert_pairs += ({ cp }); +  +  cert_pairs_sorted = 0; +  +  cert_cache = ([]); + } +  + // update the cached decoded authorities list + private void update_authorities() + { +  authorities_cache = ({}); +  foreach(authorities, string a) +  authorities_cache += ({ Standards.X509.decode_certificate(a)-> +  subject->get_der() }); + } +  + // update the cached decoded issuers list + private void update_trusted_issuers() + { +  trusted_issuers_cache=([]); +  foreach(trusted_issuers, array(string) i) +  { +  // make sure the chain is valid and intact. +  mapping result = Standards.X509.verify_certificate_chain(i, ([]), 0); +  +  if(!result->verified) +  error("Broken trusted issuer chain!\n"); +  +  // FIXME: The pathLenConstraint does not survive the cache. +  +  // The leaf of the trusted issuer is the root to validate +  // certificate chains against. +  Standards.X509.TBSCertificate cert = +  ([array(object(Standards.X509.TBSCertificate))]result->certificates)[-1]; +  +  if( !cert->ext_basicConstraints_cA || +  !(cert->ext_keyUsage & Standards.X509.KU_keyCertSign) ) +  error("Trusted issuer not allowed to sign other certificates.\n"); +  +  trusted_issuers_cache[cert->subject->get_der()] += ({ cert->public_key }); +  } + } +  +  + // + // --- Sessions + // +    //! Non-zero to enable caching of sessions   int use_cache = 1;      //! Sessions are removed from the cache when they are older than this   //! limit (in seconds). Sessions are also removed from the cache if a   //! connection using the session dies unexpectedly.   int session_lifetime = 600;      //! Maximum number of sessions to keep in the cache.   int max_sessions = 300;
pike.git/lib/modules/SSL.pmod/Context.pike:909:      //! Remove a session from the cache.   void purge_session(Session s)   {    SSL3_DEBUG_MSG("SSL.Context->purge_session: %O\n", s->identity || "");    if (s->identity)    m_delete (session_cache, s->identity);    /* There's no need to remove the id from the active_sessions queue */   }    - protected void create() - { -  SSL3_DEBUG_MSG("SSL.Context->create\n"); +     -  /* Backwards compatibility */ -  preferred_suites = get_suites(128, 1); - } -  - // update the cached decoded authorities list - private void update_authorities() - { -  authorities_cache = ({}); -  foreach(authorities, string a) -  authorities_cache += ({ Standards.X509.decode_certificate(a)-> -  subject->get_der() }); - } -  - // update the cached decoded issuers list - private void update_trusted_issuers() - { -  trusted_issuers_cache=([]); -  foreach(trusted_issuers, array(string) i) -  { -  // make sure the chain is valid and intact. -  mapping result = Standards.X509.verify_certificate_chain(i, ([]), 0); -  -  if(!result->verified) -  error("Broken trusted issuer chain!\n"); -  -  // FIXME: The pathLenConstraint does not survive the cache. -  -  // The leaf of the trusted issuer is the root to validate -  // certificate chains against. -  Standards.X509.TBSCertificate cert = -  ([array(object(Standards.X509.TBSCertificate))]result->certificates)[-1]; -  -  if( !cert->ext_basicConstraints_cA || -  !(cert->ext_keyUsage & Standards.X509.KU_keyCertSign) ) -  error("Trusted issuer not allowed to sign other certificates.\n"); -  -  trusted_issuers_cache[cert->subject->get_der()] += ({ cert->public_key }); -  } - } -  -  +    //   // --- Compat code below   //      protected Crypto.RSA compat_rsa;   protected array(string(8bit)) compat_certificates;      //! The servers default private RSA key.   //!   //! Compatibility, don't use.