📄 certauth_extensions.c
字号:
BIO_reset(serialbio); i2a_ASN1_INTEGER(serialbio, next); BIO_puts(serialbio, "\n"); /* the call to BIO_free with the CLOSE flags will take care of * the underlying file stream and close()ing the file descriptor, * which will release the lock. */ BIO_free(serialbio); serialbio = NULL; serialstream = NULL; if (!X509_set_serialNumber(cert, current)) { verror_put_string("Error assigning serialnumber\n"); goto error; } myproxy_debug("serial number assigned"); retval = 0; error: if (serial) BN_free(serial); if (current) ASN1_INTEGER_free(current); if(next) ASN1_INTEGER_free(next); if(serialbio) BIO_free(serialbio); if(serialstream) serialstream = NULL; return(retval);}static voidadd_ext(X509 *cert, int nid, char *value) { X509_EXTENSION *ex; X509V3_CTX ctx, *ctxp; ctxp = &ctx; /* needed for X509V3 macros */ X509V3_set_ctx_nodb(ctxp); X509V3_set_ctx(ctxp, cert, cert, NULL, NULL, 0); ex = X509V3_EXT_conf_nid(NULL, ctxp, nid, value); X509_add_ext(cert,ex,-1); X509_EXTENSION_free(ex);}static int generate_certificate( X509_REQ *request, X509 **certificate, EVP_PKEY *pkey, myproxy_request_t *client_request, myproxy_server_context_t *server_context) { int return_value = 1; int not_after; char * userdn; X509 * cert = NULL; X509_NAME * issuer = NULL; X509_NAME * subject = NULL; EVP_PKEY * cakey = NULL; FILE * inkey = NULL; myproxy_debug("Generating certificate internally."); cert = X509_new(); if (cert == NULL) { verror_put_string("Problem creating new X509."); goto error; } /* issuer info */ issuer = X509_get_issuer_name(cert); if ( tokenize_to_x509_name( server_context->certificate_issuer, issuer ) ) { verror_put_string("tokenize_to_x509_name() failed"); goto error; } /* subject info */ /* this has already been called successfully, but... */ if ( user_dn_lookup( client_request->username, &userdn, server_context ) ) { verror_put_string("User/DN lookup failure: user_dn_lookup()"); goto error; } myproxy_debug("DN for user %s: %s", client_request->username, userdn); subject = X509_get_subject_name(cert); if( tokenize_to_x509_name( userdn, subject ) ) { verror_put_string("tokenize_to_x509_name() failed"); goto error; } /* version, ttl, etc */ X509_set_version(cert, 0x2); /* this is actually version 3 */ if (assign_serial_number(cert, server_context)) { verror_put_string("Error assigning serial number to cert"); goto error; } if (!server_context->max_cert_lifetime) { not_after = MIN(client_request->proxy_lifetime, SECONDS_PER_HOUR * MYPROXY_DEFAULT_DELEG_HOURS); } else { not_after = MIN(client_request->proxy_lifetime, server_context->max_cert_lifetime); } myproxy_debug("cert lifetime: %d", not_after ); X509_gmtime_adj(X509_get_notBefore(cert), 0); X509_gmtime_adj(X509_get_notAfter(cert), (long)not_after); X509_set_pubkey(cert, pkey); /* extensions */ add_ext(cert, NID_key_usage, "critical,Digital Signature, Key Encipherment, Data Encipherment"); add_ext(cert, NID_basic_constraints, "critical,CA:FALSE"); add_ext(cert, NID_subject_key_identifier, "hash"); if (server_context->certificate_issuer_email_domain) { char *email; email = malloc(strlen(client_request->username)+strlen("email:@")+1+ strlen(server_context->certificate_issuer_email_domain)); sprintf(email, "email:%s@%s", client_request->username, server_context->certificate_issuer_email_domain); add_ext(cert, NID_subject_alt_name, email); free(email); } /* load ca key */ inkey = fopen( server_context->certificate_issuer_key, "r"); if (!inkey) { myproxy_debug("Could not open cakey file handle: %s", server_context->certificate_issuer_key); goto error; } /* cakey must be unencrypted */ cakey = PEM_read_PrivateKey( inkey, NULL, NULL, (char *)server_context->certificate_issuer_key_passphrase ); fclose(inkey); if ( cakey == NULL ) { verror_put_string("Could not load cakey for certificate signing."); goto error; } else { myproxy_debug("CAkey: %s", server_context->certificate_issuer_key ); } /* sign it */ myproxy_debug("Signing internally generated certificate."); if (!X509_sign(cert, cakey, EVP_sha1() ) ) { myproxy_debug("Certificate/cakey sign failed."); goto error; } return_value = 0; *certificate = cert; error: if (return_value) { if ( cert != NULL ) { X509_free(cert); } } if (cakey) EVP_PKEY_free( cakey ); if (userdn) { free(userdn); userdn = NULL; } return return_value;}static int handle_certificate(unsigned char *input_buffer, size_t input_buffer_length, unsigned char **output_buffer, int *output_buffer_length, myproxy_request_t *client_request, myproxy_server_context_t *server_context) { int return_value = 1; int verify; unsigned char number_of_certs; char * buf = NULL; int buf_len; BIO * request_bio = NULL; X509_REQ * req = NULL; EVP_PKEY * pkey = NULL; X509 * cert = NULL; BIO * return_bio = NULL; myproxy_debug("handle_certificate()"); /* load proxy request into bio */ request_bio = BIO_new(BIO_s_mem()); if (request_bio == NULL) { verror_put_string("BIO_new() failed"); goto error; } if (BIO_write(request_bio, input_buffer, input_buffer_length) < 0) { verror_put_string("BIO_write() failed"); goto error; } /* feed bio into req structure, extract private key and verify */ req = d2i_X509_REQ_bio(request_bio, NULL); if (req == NULL) { verror_put_string("Request load failed"); goto error; } else { myproxy_debug("Cert request loaded."); } pkey = X509_REQ_get_pubkey(req); if (pkey == NULL) { verror_put_string("Could not extract public key from request."); goto error; } verify = X509_REQ_verify(req, pkey); if ( verify != 1 ) { verror_put_string("Req/key did not verify: %d", verify ); goto error; } /* check to see if the configuration is sound, and call the appropriate * cert generation method based on what has been defined */ if ( ( server_context->certificate_issuer_program != NULL ) && ( server_context->certificate_issuer != NULL ) ) { verror_put_string("CA config error: both issuer and program defined"); goto error; } if ( ( server_context->certificate_issuer_program == NULL ) && ( server_context->certificate_issuer == NULL ) ) { verror_put_string("CA config error: neither issuer or program defined"); goto error; } if ( ( server_context->certificate_issuer != NULL ) && ( server_context->certificate_issuer_key == NULL ) ) { verror_put_string("CA config error: issuer defined but no key defined"); goto error; } if ( ( server_context->certificate_issuer != NULL ) && ( server_context->certificate_issuer_key != NULL ) ) { myproxy_debug("Using internal openssl/generate_certificate() code"); if ( generate_certificate( req, &cert, pkey, client_request, server_context ) ) { verror_put_string("Internal cert generation failed"); goto error; } } else { myproxy_debug("Using external callout interface."); if( external_callout( req, &cert, client_request, server_context ) ) { verror_put_string("External callout failed."); goto error; } } if (cert == NULL) { verror_put_string("Cert pointer NULL - unknown generation failure!"); goto error; } return_bio = BIO_new(BIO_s_mem()); if (return_bio == NULL) { verror_put_string("BIO_new() failed"); goto error; } /* send number of certificates in reply for backward compatibility */ /* NOTE: this "backwards compatibility" issue is a quirk of myproxy. * If this is not set, then it causes a problem when the client * reads the response a writes things back to the bio. Since this * is acting as a CA and returning a short-lived identity certificate * it is currently set up to return "1". */ number_of_certs = 1; /* in this case */ if (BIO_write(return_bio, &number_of_certs, sizeof(number_of_certs)) == SSL_ERROR) { verror_put_string("Failed dumping proxy certificate to buffer (BIO_write() failed)"); goto error; } if (i2d_X509_bio(return_bio, cert) == SSL_ERROR) { verror_put_string("Could not write signed certificate to bio."); goto error; } /* Convert the bio to a buffer and return to the calling function */ /* Basically cribbed from bio_to_buffer from ssl_utils.c - it is not * publically exposed via the ssl_utils.h header and if it were that * would be used. */ buf_len = BIO_pending( return_bio ); buf = malloc( buf_len ); if ( buf == NULL ) { verror_put_string("Return buffer malloc() failed."); goto error; } if ( BIO_read(return_bio, buf, buf_len ) == SSL_ERROR ) { verror_put_string("Failed dumping bio to return buffer."); goto error; } *output_buffer = (unsigned char *)buf; *output_buffer_length = buf_len; /* We're good to go */ return_value = 0; error: if ( request_bio != NULL ) { BIO_free(request_bio); } if ( req != NULL ) { X509_REQ_free( req ); } if ( pkey != NULL ) { EVP_PKEY_free( pkey ); } if ( cert != NULL ) { X509_free( cert ); } if ( return_bio != NULL ) { BIO_free( return_bio ); } if ( return_value ) { if ( buf != NULL ) { free( buf ); } } return return_value;}void get_certificate_authority(myproxy_socket_attrs_t *server_attrs, myproxy_creds_t *creds, myproxy_request_t *client_request, myproxy_response_t *response, myproxy_server_context_t *server_context) { unsigned char * input_buffer = NULL; size_t input_buffer_length; unsigned char * output_buffer = NULL; int output_buffer_length; myproxy_debug("Calling CA Extensions"); response->response_type = MYPROXY_ERROR_RESPONSE; verror_clear(); if ( read_cert_request( server_attrs->gsi_socket, &input_buffer, &input_buffer_length) ) { verror_put_string("Unable to read request from client"); myproxy_log_verror(); response->error_string = \ strdup("Unable to read cert request from client.\n"); goto error; } if ( handle_certificate( input_buffer, input_buffer_length, &output_buffer, &output_buffer_length, client_request, server_context ) ) { verror_put_string("CA failed to generate certificate"); response->error_string = strdup("Certificate generation failure.\n"); myproxy_log_verror(); goto error; } if ( send_certificate( server_attrs->gsi_socket, output_buffer, output_buffer_length ) ) { myproxy_log_verror(); myproxy_debug("Failure to send response to client!"); goto error; } response->response_type = MYPROXY_OK_RESPONSE; error: if ( input_buffer != NULL ) { GSI_SOCKET_free_token( input_buffer ); } if ( output_buffer != NULL ) { ssl_free_buffer( output_buffer ); }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -