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

version» Context lines:

pike.git/lib/modules/Standards.pmod/X509.pmod:404:       //! Certificate issuer.    void `issuer=(Sequence i)    {    low_set(2, i);    }    Sequence `issuer()    {    return low_get_sequence(2);    } -  // Attempt to create a presentable string from the issuer DER. +  +  //! Return the issuer of the certificate as a human readable string. +  //! Mainly useful for debug.    string issuer_str()    {    return dn_str(issuer);    }       //!    void `validity=(Sequence v)    {    // FIXME: Validate?    low_set(3, v);
pike.git/lib/modules/Standards.pmod/X509.pmod:470:    //!    void `subject=(Sequence s)    {    low_set(4, s);    }    Sequence `subject()    {    return low_get_sequence(4);    }    -  // Attempt to create a presentable string from the subject DER. +  //! Attempt to create a presentable string from the subject DER.    string subject_str()    {    return dn_str(subject);    }    -  +  //! Try to extract a readable name from @[dn]. This is one of +  //! commonName, organizationName or organizationUnitName. The first +  //! that is found is returned. Suitable for subjects and issuer +  //! sequences.    string dn_str(Sequence dn)    {    mapping ids = ([]);    foreach(dn->elements, Compound pair)    {    if(pair->type_name!="SET" || !sizeof(pair)) continue;    pair = pair[0];    if(pair->type_name!="SEQUENCE" || sizeof(pair)!=2)    continue;    if(pair[0]->type_name=="OBJECT IDENTIFIER" &&
pike.git/lib/modules/Standards.pmod/X509.pmod:1673:   //! @endmapping   //!   //! @param cert_chain   //! An array of certificates, with the relative-root last. Each   //! certificate should be a DER-encoded certificate.   //! @param authorities   //! A mapping from (DER-encoded) names to verifiers.   //! @param require_trust   //! Require that the certificate be traced to an authority, even if   //! it is self signed. + //! @param strict + //! By default this function only requires that the certificates are + //! in order, it ignores extra certificates we didn't need to verify + //! the leaf certificate.   //! -  + //! If you specify @[strict], this will change, each certificate has + //! to be signed by the next in the chain. + //! + //! Some https-servers send extraneous intermediate certificates + //! that aren't used to validate the leaf certificate. So strict + //! mode will be incompatible with those srevers. + //!   //! See @[Standards.PKCS.Certificate.get_dn_string] for converting the   //! RDN to an X500 style string.   mapping verify_certificate_chain(array(string) cert_chain,    mapping(string:Verifier|array(Verifier)) authorities, -  int|void require_trust) +  int|void require_trust, bool|void strict)   {    mapping m = ([ ]);      #define ERROR(X) do { \    DBG("Error " #X "\n"); \    m->verified=0; m->error_code|=(X); m->error_cert=idx; \    } while(0)   #define FATAL(X) do { ERROR(X); return m; } while(0)       // Decode all certificates in the chain. Leaf is first and root is    // last.       int len = sizeof(cert_chain);    array chain_obj = ({});    array chain_cert = ({}); -  // Ignore certificates that aren't issuers of the leaf certificate. -  bool ignore_extraneous = true; +        string last_issuer;    foreach(cert_chain; int idx; string c)    {    object cert = Standards.ASN1.Decode.secure_der_decode(c);    TBSCertificate tbs = decode_certificate(cert);    if(!tbs)    FATAL(CERT_INVALID);       string subject = tbs->subject->get_der(); -  if (ignore_extraneous && last_issuer && subject != last_issuer) +  if (!strict && last_issuer && subject != last_issuer)    {    // This doesn't look relevant for validating the previous (closer to    // the leaf) certificate.    DBG("Skipping %q\n", tbs->subject_str());    continue;    }    DBG("Adding %q to chain\n", tbs->subject_str());       // This is the leaf or is needed to validate the previous certificate.    last_issuer = tbs->issuer->get_der();    chain_cert = ({ cert }) + chain_cert;    chain_obj = ({ tbs }) + chain_obj;    -  if (ignore_extraneous && has_index(authorities, last_issuer)) +  if (!strict && has_index(authorities, last_issuer))    {    // We've reached a certificate signed by a root we trust, end here.    DBG("Ending at %q - signed by root %q\n", tbs->subject_str(), tbs->issuer_str());    break;    }    }       // Update length since we've filtered the certificate chain a bit.    len = sizeof(chain_obj);    m->certificates = chain_obj;