roxen.lists.pike.general

Subject Author Date
Appendix (Pike-v7.6.112_v3CSR.patch) to: Extend functionality of Standards.PKCS.CSR.build_csr() to support JCRM <Pike[at]quick-hacks[dot]co[dot]uk> 12-02-2009
 V3 certificate extensions for Pike v7.6 release 112
*** Pike-v7.6.112/lib/modules/Standards.pmod/PKCS.pmod/CSR.pmod.orig	Wed Apr 14
21:19:26 2004
--- Pike-v7.6.112/lib/modules/Standards.pmod/PKCS.pmod/CSR.pmod	Thu Feb 12
12:14:36 2009
***************
*** 1,5 ****
  //
! // $Id: CSR.pmod,v 1.12 2004/04/14 20:19:26 nilsson Exp $
  
  //! Handling of Certifikate Signing Requests (PKCS-10)
  
--- 1,5 ----
  //
! // $Id: $
  
  //! Handling of Certifikate Signing Requests (PKCS-10)
  
***************
*** 17,36 ****
    constant tag = 0;
  }
  
  //!
  Sequence build_csr(Crypto.RSA rsa, object name,
! 		   mapping(string:array(object)) attributes)
  {
!   Sequence info = Sequence( ({ Integer(0), name,
! 			       .RSA.build_rsa_public_key(rsa),
! 			       CSR_Attributes(.Identifiers.attribute_ids,
! 					      attributes) }) );
    return Sequence( ({ info,
! 		      Sequence(
! 			       ({ .Identifiers.rsa_md5_id, Null() }) ),
  		      BitString(rsa->sign(info->get_der(),
! 					  Crypto.MD5)
! 				->digits(256)) }) );
  }
  
  #if 0
--- 17,123 ----
    constant tag = 0;
  }
  
+ private constant v3_extension = "extensionRequest";
+ 
+ //! Creates an ASN.1 Object that represents a
+ //!   PKCS Certificate Signing Request
  //!
+ //! @param rsa is the RSA key for the certificate,
+ //! @param name is the ASN.1 sequence that represents the certificate
Distinguiished
+ //!   name (CN) - as returned
+ //!   by @[Standards.PKCS.Certificate.build_distinguished_name()]
+ //! @param attributes maps certificate attributes as found
+ //!   in @Standards.PKCS.Identifers.attributes to their ASN.1 objects
+ //! @param extensions maps v3 certrificate extgensionnames as found
+ //!   in 'Standards.PKCS.Identifers.ce_ids to the ASN.1 objects. 
+ //! @param critical lists the certificate extensions that should be marked
+ //!   as critical
+ //! @param version is the certificate version to use. If supplied, or set to 0
+ //!   the best guess will be used. If set to a negative value the version
+ //!   will be ommitted from the request (e.g. for RFC4211)
+ //!
+ //! @example 
+ //!   class SubjectAltName {
+ //!     inherit Standards.ASN1.Types.IA5String;
+ //!     constant cls = 2; //context dependant
+ //!     constant tag = 2; // SubjectAltName dNSName
+ //!   };
+ //!
+ //!   Crypto.RSA key = Crypto.RSA()->generate_key(1024);
+ //!
+ //!   array (mapping (string : Standards.ASN1.Types.Object)) name_parts
+ //!     = ({ ([ "countryName"
+ //!	        : Standards.ASN1.Types.PrintableString("gb") ]),
+ //!          ([ "organizationName"
+ //!	        : Standards.ASN1.Types.PrintableString("Example org") ]),
+ //!          ([ "commonName"
+ //!	        : Standards.ASN1.Types.PrintableString("ssl.example.org") ])
+ //!       });
+ //!
+ //!   Standards.ASN1.Types.Sequence distinguished_name
+ //!   = Standards.PKCS.Certificate.build_distinguished_name(@name_parts);
+ //!   // the @ operator expands the array into a parameter list
+ //!
+ //!   mapping (string : array(Standards.ASN1.Types.Object)) cert_attributes
+ //!   = ([ ]);
+ //!
+ //!   mapping (string : Standards.ASN1.Types.Object) v3_extensions
+ //!   = ([ "subjectAltName"
+ //!        :Standards.ASN1.Types.Sequence(
+ //!                                       ({ SubjectAltName("www.example.org"),
+ //!            				     SubjectAltName("www.example.com")
+ //!				          }) )
+ //!     ]);
  Sequence build_csr(Crypto.RSA rsa, object name,
! 		   void | mapping(string:array(object)) attributes,
! 		   void | mapping(string:Object) extensions,
! 		   void | array(string) critical,
! 		   void | int version)
  {
!   Sequence info, v3_ext;
!   array (Object) optional_version;
! 
!   if (!intp(version))
!     version = 0;
!   if (mappingp(extensions)
!       && sizeof(extensions)) {
!     v3_ext = .Certificate.ExtensionRequests(.Identifiers.ce_ids,
! 					    extensions, critical);
!     if (mappingp(attributes)) {
!       if (has_index(attributes, v3_extension))
!         error(v3_extension + " already in attributes");
!       attributes += ([ v3_extension : ({ v3_ext }) ]);
!     } else {
!       attributes = ([ v3_extension : ({ v3_ext }) ]);
!     }
!     if (!version)
!       version = 3;
!   }
! 
! //if (we have subjectUniqueId and/or issuerUniqueID)  {
! //  do_subjectUniqueId_And_Or_issuerUniqueID();
! //  if (!version)
! //    version = 2;
! //}
! 
!   if (!version)
!     version = 1;
! 
!   if (0 < version)
!     optional_version = ({ Integer(version - 1) });
!   else
!     optional_version = ({ });
! 
!   info = Sequence( optional_version
! 		   + ({ name,
! 			.RSA.build_rsa_public_key(rsa),
! 			CSR_Attributes(.Identifiers.attribute_ids,
! 					attributes) }) );
! 
    return Sequence( ({ info,
! 		      Sequence( ({ .Identifiers.rsa_md5_id, Null() }) ),
  		      BitString(rsa->sign(info->get_der(),
! 					  Crypto.MD5)->digits(256)) }) );
  }
  
  #if 0
*** Pike-v7.6.112/lib/modules/Standards.pmod/PKCS.pmod/Certificate.pmod.orig	Wed
Apr 14 21:19:26 2004
--- Pike-v7.6.112/lib/modules/Standards.pmod/PKCS.pmod/Certificate.pmod	Wed Feb
11 13:55:58 2009
***************
*** 1,4 ****
! // $Id: Certificate.pmod,v 1.18 2004/04/14 20:19:26 nilsson Exp $
  
  //! Handle PKCS-6 and PKCS-10 certificates and certificate requests.
  
--- 1,4 ----
! // $Id: $
  
  //! Handle PKCS-6 and PKCS-10 certificates and certificate requests.
  
***************
*** 266,271 ****
--- 266,272 ----
    }
  }
  
+ 
  class Attributes
  {
    inherit Set;
***************
*** 276,281 ****
--- 277,337 ----
  		 lambda(string field, mapping m, mapping t) {
  		   return Attribute(t, field, m[field]);
  		 }, m, types));
+   }
+ }
+ 
+ class ExtensionRequest
+ {
+   inherit Sequence;
+ 
+   void create(mapping(string:Object) types,
+ 	      string type,
+ 	      Object v)
+   {
+     if (!types[type])
+       error( "Unknown attribute type '%s'\n", type);
+     ::create( ({ types[type], OctetString(v->get_der()) }) );
+   }
+ }
+ 
+ class ExtensionRequestCritical
+ {
+   inherit Sequence;
+ 
+   void create(mapping(string:Object) types,
+ 	      string type,
+ 	      array(object) v,
+ 	      array (string) critical)
+   {
+     if (!types[type])
+       error( "Unknown attribute type '%s'\n", type);
+     if (has_value(critical, type)) {
+       ::create( ({ types[type], Boolean(1), OctetString(v->get_der()) }) );
+     } else {
+       ::create( ({ types[type], OctetString(v->get_der()) }) );
+     }
+   }
+ }
+ 
+ class ExtensionRequests
+ {
+   inherit Sequence;
+ 
+   void create(mapping(string:Object) types,
+ 	      mapping(string:Object) m,
+ 	      void | array (string) critical)
+   {
+     if (arrayp(critical) && sizeof(critical)) {
+       ::create(map(indices(m),
+ 	       lambda(string field, mapping m, mapping t, array (string) c) {
+ 		 return ExtensionRequestCritical(t, field, m[field], c);
+ 	       }, m, types, critical));
+     } else {
+       ::create(map(indices(m),
+ 	       lambda(string field, mapping m, mapping t) {
+ 		 return ExtensionRequest(t, field, m[field]);
+ 	       }, m, types));
+     }
    }
  }
  
*** Pike-v7.6.112/lib/modules/Standards.pmod/PKCS.pmod/Identifiers.pmod.orig	Wed
Apr 14 21:19:26 2004
--- Pike-v7.6.112/lib/modules/Standards.pmod/PKCS.pmod/Identifiers.pmod	Thu Feb
12 12:17:10 2009
***************
*** 143,148 ****
--- 143,150 ----
  						       | Universal */
    "unstructuredAddress" : pkcs_9_id->append(8),     /* Printable | T61 */
    "extendedCertificateAttributes" : pkcs_9_id->append(9), /* Attributes */
+   "extensionRequest" : pkcs_9_id->append(14),       /* Sequence of V3(+)
+ 						       Extensions - Altnames */
    "friendlyName" : pkcs_9_id->append(20),           /* BMPString */
    "localKeyID" : pkcs_9_id->append(21)              /* OCTET STRING */
  ]);