From: Marcel Poul Date: Sat, 25 Aug 2012 15:37:07 +0000 (+0000) Subject: use caNl in RSTx509MakeProxyCert() X-Git-Tag: gridsite-core_R_2_0_0~24 X-Git-Url: http://scientific.zcu.cz/git/?a=commitdiff_plain;h=fa8efb1212b48d2eb4a4b8a1f9e06411f68d03e9;p=jra1mw.git use caNl in RSTx509MakeProxyCert() --- diff --git a/org.gridsite.core/src/grst_canl_x509.c b/org.gridsite.core/src/grst_canl_x509.c index 3fbba0f..9b29aa2 100644 --- a/org.gridsite.core/src/grst_canl_x509.c +++ b/org.gridsite.core/src/grst_canl_x509.c @@ -1695,7 +1695,7 @@ int GRSTx509MakeProxyCert(char **proxychain, FILE *debugfp, /// errors are output to that file pointer. The proxy will expired in /// the given number of minutes starting from the current time. { - char *ptr, *certchain, s[41]; + char *ptr = NULL, *certchain = NULL; static unsigned char pci_str[] = { 0x30, 0x0c, 0x30, 0x0a, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x15, 0x01, 0 }, kyu_str[] = { 0x03, 0x02, 0x03, @@ -1703,325 +1703,266 @@ int GRSTx509MakeProxyCert(char **proxychain, FILE *debugfp, X509v3_KU_KEY_ENCIPHERMENT | X509v3_KU_KEY_AGREEMENT, 0 }; - int i, ncerts, any_rfc_proxies = 0; - long serial = 1234, ptrlen; - EVP_PKEY *pkey, *CApkey; - const EVP_MD *digest; - X509 *certs[GRST_MAX_CHAIN_LEN]; - X509_REQ *req; - X509_NAME *name, *CAsubject, *newsubject; - X509_NAME_ENTRY *ent; - ASN1_OBJECT *pci_obj = NULL, *kyu_obj; - ASN1_OCTET_STRING *pci_oct, *kyu_oct; - X509_EXTENSION *pci_ex, *kyu_ex; - FILE *fp; - BIO *reqmem, *certmem; - time_t notAfter; - - /* read in the request */ - reqmem = BIO_new(BIO_s_mem()); - BIO_puts(reqmem, reqtxt); - - if (!(req = PEM_read_bio_X509_REQ(reqmem, NULL, NULL, NULL))) - { - mpcerror(debugfp, - "GRSTx509MakeProxyCert(): error reading request from BIO memory\n"); - BIO_free(reqmem); - return GRST_RET_FAILED; + int i = 0, ncerts = 0, any_rfc_proxies = 0; + long ptrlen = 0; + EVP_PKEY *pkey = NULL, *signer_pkey = NULL; + X509 *certs[GRST_MAX_CHAIN_LEN]; + X509_REQ *req = NULL; + ASN1_OBJECT *pci_obj = NULL, *kyu_obj = NULL; + ASN1_OCTET_STRING *pci_oct = NULL, *kyu_oct = NULL; + FILE *fp = NULL; + BIO *reqmem = NULL, *certmem = NULL; + time_t notAfter; + canl_ctx ctx = NULL; + int retval = 1, ret = 0; + canl_cred proxy_cert = NULL, signer = NULL; + + ctx = canl_create_ctx(); + if (ctx == NULL) { + fprintf(debugfp, "GRSTx509MakeProxyCert(): Failed to create" + " caNl library context\n"); + return 1; } - BIO_free(reqmem); - - /* verify signature on the request */ - if (!(pkey = X509_REQ_get_pubkey(req))) - { - mpcerror(debugfp, - "GRSTx509MakeProxyCert(): error getting public key from request\n"); - - X509_REQ_free(req); - return GRST_RET_FAILED; - } - - if (X509_REQ_verify(req, pkey) != 1) - { - mpcerror(debugfp, - "GRSTx509MakeProxyCert(): error verifying signature on certificate\n"); + /* read in the request */ + reqmem = BIO_new(BIO_s_mem()); + BIO_puts(reqmem, reqtxt); - X509_REQ_free(req); - return GRST_RET_FAILED; + if (!(req = PEM_read_bio_X509_REQ(reqmem, NULL, NULL, NULL))) { + fprintf(debugfp, "GRSTx509MakeProxyCert(): error reading" + " request from BIO memory\n"); + goto end; } + BIO_free(reqmem); + reqmem = NULL; - /* read in the signing certificate */ - if (!(fp = fopen(cert, "r"))) - { - mpcerror(debugfp, - "GRSTx509MakeProxyCert(): error opening signing certificate file\n"); - - X509_REQ_free(req); - return GRST_RET_FAILED; - } - - for (ncerts = 1; ncerts < GRST_MAX_CHAIN_LEN; ++ncerts) - if ((certs[ncerts] = PEM_read_X509(fp, NULL, NULL, NULL)) == NULL) break; - - if (ncerts == 1) /* zeroth cert with be new proxy cert */ - { - mpcerror(debugfp, - "GRSTx509MakeProxyCert(): error reading signing certificate file\n"); - - X509_REQ_free(req); - return GRST_RET_FAILED; - } - - fclose(fp); - - CAsubject = X509_get_subject_name(certs[1]); - - /* read in the CA private key */ - if (!(fp = fopen(key, "r"))) - { - mpcerror(debugfp, - "GRSTx509MakeProxyCert(): error reading signing private key file\n"); - - X509_REQ_free(req); - return GRST_RET_FAILED; - } - - if (!(CApkey = PEM_read_PrivateKey(fp, NULL, NULL, NULL))) - { - mpcerror(debugfp, - "GRSTx509MakeProxyCert(): error reading signing private key in file\n"); - - X509_REQ_free(req); - return GRST_RET_FAILED; - } - - fclose(fp); - - /* get subject name */ - if (!(name = X509_REQ_get_subject_name(req))) - { - mpcerror(debugfp, - "GRSTx509MakeProxyCert(): error getting subject name from request\n"); - - X509_REQ_free(req); - return GRST_RET_FAILED; - } - - /* create new certificate */ - if (!(certs[0] = X509_new())) - { - mpcerror(debugfp, - "GRSTx509MakeProxyCert(): error creating X509 object\n"); + /* load req into canl cred. context */ + ret = canl_cred_new(ctx, &proxy_cert); + if (ret) { + fprintf(debugfp, "GRSTx509MakeProxyCert(): caNl cred. context" + " cannot be created: %s\n", canl_get_error_message(ctx)); + goto end; + } + ret = canl_cred_load_req(ctx, proxy_cert, req); + if (ret) { + fprintf(stderr, "GRSTx509MakeProxyCert(): Failed to load certificate " + "request container: %s\n", canl_get_error_message(ctx)); + goto end; + } - X509_REQ_free(req); - return GRST_RET_FAILED; - } + /*TODO MP Should proxy sognature verification be in caN???*/ + /* verify signature on the request */ + if (!(pkey = X509_REQ_get_pubkey(req))) { + mpcerror(debugfp, "GRSTx509MakeProxyCert(): error getting public" + " key from request\n"); + } - /* set version number for the certificate (X509v3) and the serial number - - We now use 2 = v3 for the GSI proxy, rather than the old Globus - behaviour of 3 = v4. See Savannah Bug #53721 */ - - if (X509_set_version(certs[0], 2L) != 1) - { - mpcerror(debugfp, - "GRSTx509MakeProxyCert(): error setting certificate version\n"); + if (X509_REQ_verify(req, pkey) != 1) { + mpcerror(debugfp, "GRSTx509MakeProxyCert(): error verifying signature" + " on certificate\n"); + goto end; + } + EVP_PKEY_free(pkey); + pkey = NULL; + X509_REQ_free(req); + req = NULL; + + /* read in the signing certificate */ + if (!(fp = fopen(cert, "r"))) { + mpcerror(debugfp, "GRSTx509MakeProxyCert(): error opening" + " signing certificate file\n"); + goto end; + } + /* load req signer cert into caNl cred. context*/ + ret = canl_cred_new(ctx, &signer); + if (ret) { + fprintf(debugfp, "GRSTx509MakeProxyCert(): caNl cred. context" + " cannot be created: %s\n", canl_get_error_message(ctx)); + goto end; + } - X509_REQ_free(req); - return GRST_RET_FAILED; - } + for (ncerts = 1; ncerts < GRST_MAX_CHAIN_LEN; ++ncerts) + if ((certs[ncerts] = PEM_read_X509(fp, NULL, NULL, NULL)) == NULL) + break; + /* zeroth cert will be new proxy cert */ + if (ncerts == 1) { + mpcerror(debugfp, "GRSTx509MakeProxyCert(): error reading" + " signing certificate file\n"); + goto end; + } + fclose(fp); + fp = NULL; - ASN1_INTEGER_set(X509_get_serialNumber(certs[0]), (long) time(NULL)); + /* read in the signer certificate*/ + ret = canl_cred_load_cert_file(ctx, signer, certs[1]); + if (ret){ + fprintf(stderr, "[DELEGATION] Cannot load signer's certificate" + ": %s\n", canl_get_error_message(ctx)); + goto end; + } - if (!(name = X509_get_subject_name(certs[1]))) - { - mpcerror(debugfp, - "GRSTx509MakeProxyCert(): error getting subject name from CA certificate\n"); - X509_REQ_free(req); - return GRST_RET_FAILED; + /* read in the signer private key */ + if (!(fp = fopen(key, "r"))) { + mpcerror(debugfp, "GRSTx509MakeProxyCert(): error reading" + " signing private key file\n"); + goto end; } - if (X509_set_issuer_name(certs[0], name) != 1) - { - mpcerror(debugfp, - "GRSTx509MakeProxyCert(): error setting issuer name of certificate\n"); - - X509_REQ_free(req); - return GRST_RET_FAILED; + if (!(signer_pkey = PEM_read_PrivateKey(fp, NULL, NULL, NULL))) { + mpcerror(debugfp, "GRSTx509MakeProxyCert(): error reading " + "signing private key in file\n"); + goto end; } + fclose(fp); + fp = NULL; + canl_cred_load_priv_key(ctx, signer, signer_pkey); + EVP_PKEY_free(signer_pkey); + signer_pkey = NULL; + + /*TODO MP Compare with VOMS in caNl (orig gridsite proxyver = 2L)*/ + /* set version number for the certificate (X509v3) and the serial number + We now use 2 = v3 for the GSI proxy, rather than the old Globus + behaviour of 3 = v4. See Savannah Bug #53721 */ + + /* TODO MP what about serial numbers? Should caNl provide API function for + * setting custom serial number?*/ + /* ASN1_INTEGER_set(X509_get_serialNumber(certs[0]), (long) time(NULL));*/ + + /* TODO MP use some default timeout?*/ + if (minutes >= 0) { + ret = canl_cred_set_lifetime(ctx, proxy_cert, 60 * minutes); + if (ret) + fprintf(debugfp, "[DELEGATION] Failed set new cert lifetime" + ": %s\n", canl_get_error_message(ctx)); + } - /* set public key in the certificate */ - if (X509_set_pubkey(certs[0], pkey) != 1) - { - mpcerror(debugfp, - "GRSTx509MakeProxyCert(): error setting public key of the certificate\n"); - - X509_REQ_free(req); - return GRST_RET_FAILED; - } + /* go through chain making sure this proxy is not longer lived */ - /* set duration for the certificate */ - if (!(X509_gmtime_adj(X509_get_notBefore(certs[0]), -GRST_BACKDATE_SECONDS))) - { - mpcerror(debugfp, - "GRSTx509MakeProxyCert(): error setting beginning time of the certificate\n"); + pci_obj = OBJ_txt2obj(GRST_PROXYCERTINFO_OID, 0); - X509_REQ_free(req); - return GRST_RET_FAILED; - } + /* TODO MP is this necessary? caNl test if new proxy timeout + * is longer than signer cert proxy timeout */ + notAfter = + GRSTasn1TimeToTimeT(ASN1_STRING_data(X509_get_notAfter(certs[0])), 0); - if (!(X509_gmtime_adj(X509_get_notAfter(certs[0]), 60 * minutes))) - { - mpcerror(debugfp, - "GRSTx509MakeProxyCert(): error setting ending time of the certificate\n"); + for (i=1; i < ncerts; ++i) { + if (notAfter > GRSTasn1TimeToTimeT(ASN1_STRING_data( + X509_get_notAfter(certs[i])),0)) { + notAfter = GRSTasn1TimeToTimeT(ASN1_STRING_data( + X509_get_notAfter(certs[i])),0); - X509_REQ_free(req); - return GRST_RET_FAILED; + ASN1_UTCTIME_set(X509_get_notAfter(certs[0]), notAfter); + } + if (X509_get_ext_by_OBJ(certs[i], pci_obj, -1) > 0) + any_rfc_proxies = 1; } - - /* go through chain making sure this proxy is not longer lived */ - - pci_obj = OBJ_txt2obj(GRST_PROXYCERTINFO_OID, 0); - - notAfter = - GRSTasn1TimeToTimeT(ASN1_STRING_data(X509_get_notAfter(certs[0])), 0); - - for (i=1; i < ncerts; ++i) - { - if (notAfter > - GRSTasn1TimeToTimeT(ASN1_STRING_data(X509_get_notAfter(certs[i])), - 0)) - { - notAfter = - GRSTasn1TimeToTimeT(ASN1_STRING_data(X509_get_notAfter(certs[i])), - 0); - - ASN1_UTCTIME_set(X509_get_notAfter(certs[0]), notAfter); - } - - if (X509_get_ext_by_OBJ(certs[i], pci_obj, -1) > 0) - any_rfc_proxies = 1; - } /* if any earlier proxies are RFC 3820, then new proxy must be an RFC 3820 proxy too with the required extensions */ - if (any_rfc_proxies) - { - /* key usage */ - kyu_obj = OBJ_txt2obj(GRST_KEYUSAGE_OID, 0); - kyu_ex = X509_EXTENSION_new(); - - X509_EXTENSION_set_object(kyu_ex, kyu_obj); - ASN1_OBJECT_free(kyu_obj); - X509_EXTENSION_set_critical(kyu_ex, 1); - - kyu_oct = ASN1_OCTET_STRING_new(); - ASN1_OCTET_STRING_set(kyu_oct, kyu_str, strlen(kyu_str)); - X509_EXTENSION_set_data(kyu_ex, kyu_oct); - ASN1_OCTET_STRING_free(kyu_oct); - - X509_add_ext(certs[0], kyu_ex, -1); - X509_EXTENSION_free(kyu_ex); - - /* proxy certificate info */ - pci_ex = X509_EXTENSION_new(); - - X509_EXTENSION_set_object(pci_ex, pci_obj); - X509_EXTENSION_set_critical(pci_ex, 1); - - pci_oct = ASN1_OCTET_STRING_new(); - ASN1_OCTET_STRING_set(pci_oct, pci_str, strlen(pci_str)); - X509_EXTENSION_set_data(pci_ex, pci_oct); - ASN1_OCTET_STRING_free(pci_oct); - - X509_add_ext(certs[0], pci_ex, -1); - X509_EXTENSION_free(pci_ex); + if (any_rfc_proxies) { + X509_EXTENSION *pci_ex = NULL, *kyu_ex = NULL; + /* key usage */ + kyu_obj = OBJ_txt2obj(GRST_KEYUSAGE_OID, 0); + kyu_ex = X509_EXTENSION_new(); + + X509_EXTENSION_set_object(kyu_ex, kyu_obj); + ASN1_OBJECT_free(kyu_obj); + X509_EXTENSION_set_critical(kyu_ex, 1); + + kyu_oct = ASN1_OCTET_STRING_new(); + ASN1_OCTET_STRING_set(kyu_oct, kyu_str, strlen(kyu_str)); + X509_EXTENSION_set_data(kyu_ex, kyu_oct); + ASN1_OCTET_STRING_free(kyu_oct); + + X509_add_ext(certs[0], kyu_ex, -1); + canl_cred_set_extension(ctx, proxy_cert, kyu_ex); + X509_EXTENSION_free(kyu_ex); + + /* proxy certificate info */ + pci_ex = X509_EXTENSION_new(); + X509_EXTENSION_set_object(pci_ex, pci_obj); + X509_EXTENSION_set_critical(pci_ex, 1); + + pci_oct = ASN1_OCTET_STRING_new(); + ASN1_OCTET_STRING_set(pci_oct, pci_str, strlen(pci_str)); + X509_EXTENSION_set_data(pci_ex, pci_oct); + ASN1_OCTET_STRING_free(pci_oct); + + canl_cred_set_extension(ctx, proxy_cert, kyu_ex); + X509_EXTENSION_free(pci_ex); } - ASN1_OBJECT_free(pci_obj); - - /* set issuer and subject name of the cert from the req and the CA */ - - if (any_rfc_proxies) /* user CN=number rather than CN=proxy */ - { - snprintf(s, sizeof(s), "%ld", (long) time(NULL)); - ent = X509_NAME_ENTRY_create_by_NID(NULL, OBJ_txt2nid("commonName"), - MBSTRING_ASC, s, -1); - } - else ent = X509_NAME_ENTRY_create_by_NID(NULL, OBJ_txt2nid("commonName"), - MBSTRING_ASC, "proxy", -1); - - newsubject = X509_NAME_dup(CAsubject); + ASN1_OBJECT_free(pci_obj); + pci_obj = NULL; - X509_NAME_add_entry(newsubject, ent, -1, 0); - - if (X509_set_subject_name(certs[0], newsubject) != 1) - { - mpcerror(debugfp, - "GRSTx509MakeProxyCert(): error setting subject name of certificate\n"); - - X509_REQ_free(req); - return GRST_RET_FAILED; - } - - X509_NAME_free(newsubject); - X509_NAME_ENTRY_free(ent); - - /* sign the certificate with the signing private key */ - if (EVP_PKEY_type(CApkey->type) == EVP_PKEY_RSA) - digest = EVP_md5(); - else - { - mpcerror(debugfp, - "GRSTx509MakeProxyCert(): error checking signing private key for a valid digest\n"); - - X509_REQ_free(req); - return GRST_RET_FAILED; - } - - if (!(X509_sign(certs[0], CApkey, digest))) - { - mpcerror(debugfp, - "GRSTx509MakeProxyCert(): error signing certificate\n"); - - X509_REQ_free(req); - return GRST_RET_FAILED; - } - - /* store the completed certificate chain */ - - certchain = strdup(""); - - for (i=0; i < ncerts; ++i) - { - certmem = BIO_new(BIO_s_mem()); - - if (PEM_write_bio_X509(certmem, certs[i]) != 1) - { - mpcerror(debugfp, - "GRSTx509MakeProxyCert(): error writing certificate to memory BIO\n"); + /* Sign the proxy */ + ret = canl_cred_sign_proxy(ctx, signer, proxy_cert); + if (ret){ + fprintf(stderr, "[DELEGATION] Cannot sign new proxy" + ": %s\n", canl_get_error_message(ctx)); + goto end; + } - X509_REQ_free(req); - return GRST_RET_FAILED; - } + ret = canl_cred_save_cert(ctx, proxy_cert, &certs[0]); + if (ret) { + fprintf(stderr, "GRSTx509MakeProxyCert(): Cannot save new cert file" + ": %s\n", canl_get_error_message(ctx)); + goto end; + } + canl_free_ctx(ctx); + ctx = NULL; + + /* store the completed certificate chain */ + certchain = strdup(""); + for (i=0; i < ncerts; ++i) { + certmem = BIO_new(BIO_s_mem()); + + if (PEM_write_bio_X509(certmem, certs[i]) != 1) { + mpcerror(debugfp, "GRSTx509MakeProxyCert(): error writing" + " certificate to memory BIO\n"); + goto end; + } + ptrlen = BIO_get_mem_data(certmem, &ptr); + certchain = realloc(certchain, strlen(certchain) + ptrlen + 1); + strncat(certchain, ptr, ptrlen); + + BIO_free(certmem); + certmem = NULL; + X509_free(certs[i]); + certs[i] = NULL; + } + ncerts = 0; + *proxychain = certchain; + retval = GRST_RET_OK; - ptrlen = BIO_get_mem_data(certmem, &ptr); - - certchain = realloc(certchain, strlen(certchain) + ptrlen + 1); - - strncat(certchain, ptr, ptrlen); - - BIO_free(certmem); - X509_free(certs[i]); - } - - EVP_PKEY_free(pkey); - EVP_PKEY_free(CApkey); - X509_REQ_free(req); - - *proxychain = certchain; - return GRST_RET_OK; +end: + if (reqmem) + BIO_free(reqmem); + if (pkey) + EVP_PKEY_free(pkey); + if (signer_pkey) + EVP_PKEY_free(signer_pkey); + if (req) + X509_REQ_free(req); + if (pci_obj) + ASN1_OBJECT_free(pci_obj); + if (fp) { + fclose(fp); + fp = NULL; + } + if (certmem) + BIO_free(certmem); + if (ctx) + canl_free_ctx(ctx); + for (i=0; i < ncerts; ++i) { + if (certs[i]) + X509_free(certs[i]); + } + if (proxy_cert) + canl_cred_free(ctx, proxy_cert); + if (signer) + canl_cred_free(ctx, signer); + return retval; } /// Find a proxy file in the proxy cache