Hi all,
Does someone know why custom extensions of an X509 certificate request apparently get stripped when the PEM_write_X509_REQ function is used to dump the request to a file ?
The code (based on demos/x509/mkreq.c) that I use is attached. To compile the code, simply do: gcc -g -Wall -lcrypto -o gcs-add-ext gcs-add-ext.c
To try the code, you can do: cat basic-user.req | ./gcs-add-ext -r user:admin -V | openssl req -text
There, you will see that my extension gets added to the certificate request but is actually missing in the PEM encoded output produced by PEM_write_X509_REQ.
Thanks for any idea for a fix/workaround.
Best, Jacques Thomas
/* * Filename: gcs-add-exts.c * Purpose: program to add extensions for gcs access control in a PEM encoded x509 * certificate request * * Author: Jacques Thomas <[EMAIL PROTECTED]> * Credits: Markus Loch and the OpenSSL demo apps authors */
#include <stdio.h> #include <unistd.h> #include <openssl/err.h> #include <openssl/pem.h> #include <openssl/asn1.h> #include <openssl/evp.h> #include <openssl/x509.h> #include <openssl/x509v3.h> #include "gcs-exts.h" #define false 0 #define true 1 int add_ext(STACK_OF(X509_REQUEST) *sk, int nid, char *value); /* arguments retrieved from the command line */ char *infile = NULL; char *outfile = NULL; char *roles = NULL; int verbose = false; /* to use with sprintf for complicated error messages */ char errmsg[256]; void parse_opts(int argc, char *argv[]){ char *optstring = "hi:o:r:V"; char *usage = "[-h] [-V] [-i <input cert req>] [-o <output cert req>] [-r <role1[:role2 ...]]>"; char *usage_long = "TODO: write detailed usage explanations"; char c; while((c = getopt(argc, argv, optstring))){ switch(c){ case 'h': fprintf(stdout, "Usage:\n\t %s %s\n%s\n", argv[0], usage, usage_long); exit (0); case 'i': infile = optarg; break; case 'o': outfile = optarg; break; case 'r': roles = optarg; break; case 'V': verbose = true; break; case '?': /* unrecognized option */ fprintf(stderr, "Usage:\n\t %s %s\n", argv[0], usage); exit (1); case -1: /* no more options */ return; } } return; /* just to tranquilize the compiler ; we exit straight from the while loop */ } int main (int argc, char *argv[]) { X509_REQ *req=NULL; FILE *infp, *outfp; STACK_OF(X509_EXTENSION) *exts = NULL; int nid; /* parse the options from the command line */ parse_opts(argc, argv); OpenSSL_add_all_algorithms (); ERR_load_crypto_strings (); /* load the certificate request */ if(verbose) fprintf (stderr,"Loading the certificate request now \n"); if (infile == NULL) infp = stdin; else { if (!(infp = fopen (infile, "r"))) perror ("Error accessing certificate file"); } if (!(req = PEM_read_X509_REQ (infp, NULL, NULL, NULL))) perror ("Error reading certificate file" ); fclose (infp); /* if needed, open the output file */ if (outfile == NULL) outfp = stdout; else { if (!(outfp = fopen (outfile, "w"))){ sprintf(errmsg, "Error opening output file %s", outfile); perror (errmsg); } } /* the default role is the user role */ if (roles == NULL) roles = "user"; /* print the certificate request before modification*/ if(verbose){ fprintf(stderr, "Certificate request before modification:\n"); X509_REQ_print_fp(stderr,req); } /* initialize the extensions stack */ exts = sk_X509_EXTENSION_new_null(); /* now add the GCS role extension */ nid = OBJ_create(GCS_ROLE_OID, "GCSRole", "GCS Role Attribute"); X509V3_EXT_add_alias(nid, NID_netscape_comment); add_ext(exts, nid, roles); /* add the extension to the request */ X509_REQ_add_extensions(req, exts); /* cleanup */ sk_X509_EXTENSION_pop_free(exts, X509_EXTENSION_free); /* print the certificate request after modification */ if(verbose){ fprintf(stderr, "\n\n\nCertificate request after modification:\n"); X509_REQ_print_fp(stderr,req); } /* output the PEM encoded certifcate request to the proper output file */ PEM_write_X509_REQ(outfp,req); return(0); } /* Add extension using V3 code: we can set the config file as NULL * because we wont reference any other sections. */ int add_ext(STACK_OF(X509_REQUEST) *sk, int nid, char *value) { X509_EXTENSION *ex; ex = X509V3_EXT_conf_nid(NULL, NULL, nid, value); if (!ex) return 0; sk_X509_EXTENSION_push(sk, ex); return 1; }
-----BEGIN CERTIFICATE REQUEST----- MIIBrTCCARYCAQAwbTELMAkGA1UEBhMCVVMxEDAOBgNVBAgTB0luZGlhbmExFzAV BgNVBAcTDldlc3QgTGFmYXlldHRlMSEwHwYDVQQKExhJbnRlcm5ldCBXaWRnaXRz IFB0eSBMdGQxEDAOBgNVBAMTB0phY3F1ZXMwgZ8wDQYJKoZIhvcNAQEBBQADgY0A MIGJAoGBAMNArsxzS98UZ3OTNlLaBDEfbNBs5/sUp/8WDrk8+a+TBKyhGoD7OIYK HI0Z8FGwGifvNP2VlxHZiDaiqM6j36FCS/SG8lD6JjJXiXVoCTVdOfO3sRFg+mIM fJ3zDcOCFx1PFiR+0273C1OFzDBdWqGBUPwuSMtjIweBBLB/JesLAgMBAAGgADAN BgkqhkiG9w0BAQQFAAOBgQAUyYEitN9DVYQETFqCmRkgm27CrFEcu1P6ayulRJ8f Cs37HMhDHT/0PO1ggH9zLnT8wkQBC+ucMWC0ayEjaRHPjxmTumfBljvxF33VGuPD Q+MIJEHOpl0TsUpreAoGF9CsA+/JJCbbWDI+7vJrrEqw6PvT2Z57q4Vh9dfwuYuu bQ== -----END CERTIFICATE REQUEST-----