pike.git / lib / modules / Standards.pmod / X509.pmod

version» Context lines:

pike.git/lib/modules/Standards.pmod/X509.pmod:1487:    // policyConstraints and inhibitAnyPolicy to be processed in    // accordance with RFC 5280.       // One or more critical extensions have not been processed.    if( sizeof(crit) )    return NULL("verify ca: Critical unknown extensions %O.\n", crit);       return tbs;   }    + protected mapping(string:mapping(string:array(Verifier))) +  authorities_cache = ([]); + protected mapping(string:int) +  authorities_cache_expire = ([]); +    //! Convenience function for loading known root certificates.   //!   //! @param root_cert_dirs   //! Directory/directories containing the PEM-encoded root certificates   //! to load. Defaults to a rather long list of directories, including   //! @expr{"/etc/ssl/certs"@}, @expr{"/etc/pki/tls/certs"@} and   //! @expr{"/System/Library/OpenSSL/certs"@}, which seem to be the most   //! common locations.   //! -  + //! @param cache + //! A flag to control if the answer should be given from an internal + //! cache or always scan the directories. If a cache is used, it + //! will refresh when any certificate expires (which typically is + //! measured in years) or when asked for in unchached mode. + //!   //! @returns   //! Returns a mapping from DER-encoded issuer to @[Verifier]s   //! compatible with eg @[verify_certificate()]   //!   //! @note   //! If a certificate directory contains a file named   //! @expr{"ca-certificates.crt"@}, it is assumed to   //! contain a concatenation of all the certificates   //! in the directory.   //!   //! @seealso   //! @[verify_certificate()], @[verify_certificate_chain()] - mapping(string:array(Verifier)) load_authorities(string|array(string)|void root_cert_dirs) + mapping(string:array(Verifier)) +  load_authorities(string|array(string)|void root_cert_dirs, +  int(0..1)|void cache)   { -  +  string key = ""; +  if(stringp(root_cert_dirs)) +  key = root_cert_dirs; +  else if(arrayp(root_cert_dirs)) +  key = root_cert_dirs*":"; +  if( cache && authorities_cache_expire[key] > time() ) +  return authorities_cache[key]; +     root_cert_dirs = root_cert_dirs || ({    // These directories have with some minor modifications    // been taken from the list at    // http://gagravarr.org/writing/openssl-certs/others.shtml       "/etc/ssl/certs",    // This seems to be the default for most current installations    // with the exception of RHEL and MacOS X.    //    // Debian Woody (3.0), OpenSSL 0.9.6
pike.git/lib/modules/Standards.pmod/X509.pmod:1577:    "/usr/local/ssl/certs",    // Normal OpenSSL Tarball Build, OpenSSL 0.9.6       "/opt/local/ssl/certs",    // Common alternative to /usr/local/.    });    if (!arrayp(root_cert_dirs)) {    root_cert_dirs = ({ root_cert_dirs });    }    mapping(string:array(Verifier)) res = ([]); +  int expire; +  void update_expire(TBSCertificate tbs) +  { +  if(!expire) expire=tbs->not_after; +  expire = min(expire, tbs->not_after); +  if(tbs->not_before > time(1)) +  expire = min(expire, tbs->not_before); +  };       foreach(root_cert_dirs, string dir) {    string pem = Stdio.read_bytes(combine_path(dir, "ca-certificates.crt"));    if (pem) {    Standards.PEM.Messages messages = Standards.PEM.Messages(pem);    foreach(messages->get_certificates(), string m) {    TBSCertificate tbs = verify_ca_certificate(m);    if (!tbs) continue;    string subj = tbs->subject->get_der();    if( !res[subj] || !has_value(res[subj], tbs->public_key ) ) -  +  { +  update_expire(tbs);    res[subj] += ({ tbs->public_key });    } -  +  }    continue;    }    foreach(get_dir(dir) || ({}), string fname) {    if (has_suffix(fname, ".0")) {    // Skip OpenSSL hash files for now (as they are duplicates).    continue;    }    fname = combine_path(dir, fname);    if (!Stdio.is_file(fname)) continue;    pem = Stdio.read_bytes(fname);    if (!pem) continue;    string cert = Standards.PEM.simple_decode(pem);    if (!cert) continue;    TBSCertificate tbs = verify_ca_certificate(cert);    if (!tbs) continue;    string subj = tbs->subject->get_der();    if( !res[subj] || !has_value(res[subj], tbs->public_key ) ) -  +  { +  update_expire(tbs);    res[subj] += ({ tbs->public_key });    }    } -  +  } +  +  if( authorities_cache_expire[key] || cache ) +  { +  authorities_cache[key] = res; +  authorities_cache_expire[key] = expire; +  }    return res;   }      //! Decodes a certificate chain, oredered from leaf to root, and   //! checks the signatures. Verifies that the chain can be decoded   //! correctly, is unbroken, and that all certificates are in effect   //! (time-wise.) and allowed to sign it's child certificate.   //!   //! No verifications are done on the leaf certificate to determine   //! what it can and can not be used for.