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

version» Context lines:

pike.git/lib/modules/Tools.pmod/X509.pmod:1:   #pike __REAL_VERSION__   //#pragma strict_types      /* -  * $Id: X509.pmod,v 1.26 2004/02/03 13:53:02 nilsson Exp $ +  * $Id: X509.pmod,v 1.27 2004/02/04 20:07:32 bill Exp $    *    * Some random functions for creating RFC-2459 style X.509 certificates.    *    */      #if constant(Standards.ASN1.Types.Sequence)      import Standards.ASN1.Types;   import Standards.PKCS;      // Note: Redump this module if you change X509_DEBUG   #ifdef X509_DEBUG   #define X509_WERR werror   #else   #define X509_WERR   #endif    -  + //! + constant CERT_TOO_OLD = 1; +  + //! + constant CERT_TOO_NEW = 2; +  + //! + constant CERT_INVALID = 3; +  + //! + constant CERT_CHAIN_BROKEN = 4; +  + //! + constant CERT_ROOT_UNTRUSTED = 5; +  + //! + constant CERT_BAD_SIGNATURE = 6; +    //! Creates a @[Standards.ASN1.Types.UTC] object from the posix   //! time @[t].   UTC make_time(int t)   {    Calendar.Second second = Calendar.Second(t)->set_timezone("UTC");       if (second->year_no() >= 2050)    error( "Times later than 2049 not supported yet\n" );       return UTC(sprintf("%02d%02d%02d%02d%02d%02dZ",
pike.git/lib/modules/Tools.pmod/X509.pmod:504:    }    else    v = authorities[tbs->issuer->get_der()];       return v && v->verify(cert->elements[1],    cert->elements[0]->get_der(),    cert->elements[2]->value)    && tbs;   }    - //! Decodes a certificate chain, checks the signatures. Returns a mapping - //! with the following contents, depending on the verification of the - //! certificate chain: + //! Decodes a certificate chain, checks the signatures. Verifies that the + //! chain is unbroken, and that all certificates are in effect + //! (time-wise.)   //! -  + //! Returns a mapping with the following contents, depending + //! on the verification of the certificate chain: + //!   //! @mapping -  + //! @member int "error_code" + //! Error describing type of verification failure, if verification failed. + //! May be one of the following: @[CERT_TOO_NEW], @[CERT_TOO_OLD], + //! @[CERT_ROOT_UNTRUSTED], @[CERT_BAD_SIGNATURE], @[CERT_INVALID] + //! or @[CERT_CHAIN_BROKEN] + //! @member int "error_cert" + //! Index number of the certificate that caused the verification failure.   //! @member int(0..1) "self_signed"   //! Non-zero if the certificate is self-signed.   //! @member int(0..1) "verified"   //! Non-zero if the certificate is verified.   //! @member string "authority"   //! @[Standards.ASN1.Sequence] of the authority RDN that verified the chain.   //! @member string "cn"   //! @[Standards.ASN1.Sequence] of the common name RDN of the leaf certificate.   //! @endmapping   //!
pike.git/lib/modules/Tools.pmod/X509.pmod:535:   //!   //! 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 authorities, int|void require_trust)   {       mapping m = ([ ]);       array chain_obj = ({});    array chain_cert = ({});    -  foreach(cert_chain, string c) +  foreach(cert_chain; int idx; string c)    {    object cert = Standards.ASN1.Decode.simple_der_decode(c);    TBSCertificate tbs = decode_certificate(cert); -  if(!tbs) return m; +  if(!tbs) +  { +  m->error_code = CERT_INVALID; +  m->error_cert = idx; +  return m; +  }    chain_cert += ({cert});    chain_obj += ({tbs});    }       foreach(chain_obj; int idx; TBSCertificate tbs)    {    object v;       if(idx == 0) // The root cert    {    v = authorities[tbs->issuer->get_der()];       // if we don't know the issuer of the root certificate, and we require trust, we're done.    if(!v && require_trust)    {    X509_WERR("we require trust, but haven't got it.\n"); -  +  m->error_code = CERT_ROOT_UNTRUSTED; +  m->error_cert = idx;    return m;    }       // is the root self signed?    if (tbs->issuer->get_der() == tbs->subject->get_der())    {    /* A self signed certificate */    m->self_signed = 1;    X509_WERR("Self signed certificate\n");       // always trust our own authority first, even if it is self signed.    if(!v)    v = tbs->public_key;    }    }       else // otherwise, we make sure the chain is unbroken.    { -  +  // is the certificate in effect (time-wise)? +  int my_time = time(); +  +  // first check not_before. we want the current time to be later. +  if(my_time < mktime(tbs->not_before)) +  { +  m->verified = 0; +  m->error_code = CERT_TOO_NEW; +  m->error_cert = idx; +  return m; +  } +  +  // first check not_after. we want the current time to be earlier. +  if(my_time > mktime(tbs->not_after)) +  { +  m->verified = 0; +  m->error_code = CERT_TOO_OLD; +  m->error_cert = idx; +  return m; +  } +     // is the issuer of this certificate the subject of the previous (more rootward) certificate?    if(tbs->issuer->get_der() != chain_obj[idx-1]->subject->get_der())    {    X509_WERR("issuer chain is broken!\n"); -  +  m->verified = 0; +  m->error_code = CERT_CHAIN_BROKEN; +  m->error_cert = idx;    return m;    }    // the verifier for this certificate should be the public key of the previous certificate in the chain.    v = chain_obj[idx-1]->public_key;    }       if (v && v->verify(chain_cert[idx]->elements[1],    chain_cert[idx]->elements[0]->get_der(),    chain_cert[idx]->elements[2]->value)    && tbs)
pike.git/lib/modules/Tools.pmod/X509.pmod:600:    m->verified = 1;       if(idx == 0) // if we're the root of the chain and we've verified, this is the authority.    m->authority = tbs->issuer;       if(idx == sizeof(chain_cert)-1) m->cn = tbs->subject;    }    else    {    X509_WERR("signature _not_ verified...\n"); +  m->error_code = CERT_BAD_SIGNATURE; +  m->error_cert = idx;    m->verified = 0;    return m;    }    }    return m;   }      #endif