⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ssl_utils.c

📁 代理服务器源代码 供大家学习使用,希望大家喜欢
💻 C
📖 第 1 页 / 共 3 页
字号:
/* * ssl_utils.c * * Routines for interacting directly with SSL, X509 certificates, etc. */#include "myproxy_common.h"	/* all needed headers included here */#define PEM_CALLBACK(func)	func, NULL#define PEM_NO_CALLBACK		NULL, NULL/********************************************************************** * * Constants * */#define PROXY_DEFAULT_LIFETIME		-1L /* magic # for lifetime */                                            /*   of signing cert    *//********************************************************************** * * Internal data structures * */struct _ssl_credentials{    X509		*certificate;    EVP_PKEY		*private_key;    STACK		*certificate_chain;    globus_gsi_proxy_handle_t	proxy_req;};struct _ssl_proxy_restrictions{    /* 0 = unrestricted, 1 = limited */    int			limited_proxy;    /* Proxy lifetime in seconds, 0 means default, -1 means maximum */    long		lifetime;};/********************************************************************** * * Internal variables. * *//* * Holder for pass phrase so callback function can find it. */static const char *_ssl_pass_phrase = NULL;/********************************************************************** * * Internal functions. * *//* * ssl_error_to_verror() * * Transfer an error description out of the ssl error handler to verror. */voidssl_error_to_verror(){    while (ERR_peek_error() != 0)    {	unsigned long error;	ERR_STATE *error_state;	const char *error_data;	int error_number;		/* Find data for last error */	error_state = ERR_get_state();	error_number = (error_state->bottom + 1) % ERR_NUM_ERRORS;		error_data = error_state->err_data[error_number];	/* Pop error off of stack */	error = ERR_get_error();		/* Now add to verror state */	verror_put_string(ERR_error_string(error, NULL));	if (error_data != NULL)	{	    verror_put_string(error_data);	}    }        ERR_clear_error();}/* * bio_from_buffer() * * Given a buffer of length buffer_len, return a memory bio with the * contents of the buffer. * * Returns pointer to bio on success, NULL on error. */static BIO *bio_from_buffer(const unsigned char		*buffer,		int				buffer_len){    BIO			*bio = NULL;    assert(buffer != NULL);        bio = BIO_new(BIO_s_mem());    if (bio == NULL)    {	verror_put_string("Failed creating memory BIO");	ssl_error_to_verror();	goto error;    }    if (BIO_write(bio, (unsigned char *) buffer, buffer_len) == SSL_ERROR)    {	verror_put_string("Failed writing buffer to BIO");	ssl_error_to_verror();	BIO_free(bio);	bio = NULL;	goto error;    }  error:    return bio;}/* * bio_to_buffer() * * Given a bio return the contents of the bio in a buffer. * pbuffer is set to point to the allocated buffer, and pbuffer_len * is filled in with the buffer length. Caller should free *pbuffer. * * Returns SSL_SUCCESS or SSL_ERROR. */static intbio_to_buffer(BIO				*bio,	      unsigned char			**pbuffer,	      int				*pbuffer_len){    char 		*buffer = NULL;    int			buffer_len;    int			return_status = SSL_ERROR;        assert(bio != NULL);        buffer_len = BIO_pending(bio);        buffer = malloc(buffer_len);        if (buffer == NULL)    {	verror_put_string("Failed dumping BIO to buffer (malloc() failed)");	verror_put_errno(errno);	goto error;    }        if (BIO_read(bio, buffer, buffer_len) == SSL_ERROR)    {	verror_put_string("Failed dumping BIO to buffer (BIO_read() failed)");	ssl_error_to_verror();	goto error;    }    /* Success */    *pbuffer = (unsigned char *)buffer;    *pbuffer_len = buffer_len;    return_status = SSL_SUCCESS;      error:    if (return_status == SSL_ERROR)    {	if (buffer != NULL)	{	    free(buffer);	}    }        return return_status;} /* * ssl_cert_chain_free() * * Free the given certificate chain and all it contents. */static voidssl_cert_chain_free(STACK			*cert_chain){    if (cert_chain != NULL)    {	sk_pop_free(cert_chain, (void (*)(void *))X509_free);    }}/* * ssl_credentials_free_contents() * * Free all the contents of the given credentials without freeing * the credentials structure itself. */static voidssl_credentials_free_contents(SSL_CREDENTIALS	*creds){    if (creds != NULL)    {	if (creds->certificate != NULL) 	{	    X509_free(creds->certificate);	}		if (creds->private_key != NULL)	{	    EVP_PKEY_free(creds->private_key);	}		if (creds->certificate_chain != NULL)	{	    ssl_cert_chain_free(creds->certificate_chain);	}    }}static intcreds_from_bio(BIO *bio, SSL_CREDENTIALS **creds){   STACK               *cert_chain = NULL;   X509                *cert = NULL;   unsigned char       number_of_certs;   int                 cert_index;   int                 return_status = SSL_ERROR;    if (BIO_read(bio, &number_of_certs, sizeof(number_of_certs)) == SSL_ERROR) {      verror_put_string("Failed unpacking chain from buffer"                        "(reading number of certificates)");      ssl_error_to_verror();      return SSL_ERROR;   }   if (number_of_certs == 0) {      verror_put_string("Failed unpacking chain from buffer"                        "(number of certificates is zero)");      ssl_error_to_verror();      return SSL_ERROR;   }   cert = d2i_X509_bio(bio, NULL /* make new cert */);   if (cert == NULL) {      verror_put_string("Failed unpacking chain from buffer"                        "(reading user's certificate)");      ssl_error_to_verror();      goto end;   }   /* Now read the certificate chain */   cert_chain = sk_new_null();   for (cert_index = 1; cert_index < number_of_certs; cert_index++) {      X509  *x509;      x509 = d2i_X509_bio(bio, NULL /* make new cert */);      if (x509 == NULL) {         verror_put_string("Failed unpacking chain from buffer"                           "(reading certificate)");         ssl_error_to_verror();         goto end;      }      if (sk_push(cert_chain, (char *) x509) == SSL_ERROR) {         verror_put_string("Failed unpacking chain from buffer"                           "(building a new chain)");         ssl_error_to_verror();         X509_free(x509);         goto end;      }   }   *creds = ssl_credentials_new();   if (*creds == NULL) {       verror_put_string("Failed unpacking chain from buffer"                         "(building a new chain)");       goto end;   }   (*creds)->certificate_chain = cert_chain;   cert_chain = NULL;   (*creds)->certificate = cert;   cert = NULL;   return_status = SSL_SUCCESS;end:   if (cert)      X509_free(cert);   if (cert_chain)      ssl_cert_chain_free(cert_chain);   return return_status;}static intcreds_to_bio(SSL_CREDENTIALS *chain, BIO **bio){    unsigned char number_of_certs;    BIO  *output_bio = NULL;    int index;    int return_status = SSL_ERROR;    output_bio = BIO_new(BIO_s_mem());    if (output_bio == NULL) {       verror_put_string("BIO_new() failed");       ssl_error_to_verror();       return SSL_ERROR;    }    number_of_certs = sk_num(chain->certificate_chain) + 1;    if (BIO_write(output_bio, &number_of_certs,sizeof(number_of_certs)) == SSL_ERROR) {       verror_put_string("Failed dumping chain to buffer"                         "(BIO_write() failed)");       ssl_error_to_verror();       goto end;    }    if (i2d_X509_bio(output_bio, chain->certificate) == SSL_ERROR) {       verror_put_string("Failed dumping chain to buffer "                         "(write of user's certificate failed)");       ssl_error_to_verror();       goto end;    }    for (index = 0; index < sk_num(chain->certificate_chain); index++) {       X509  *cert;       cert = (X509 *) sk_value(chain->certificate_chain, index);       if (i2d_X509_bio(output_bio, cert) == SSL_ERROR) {          verror_put_string("Failed dumping chain to buffer "                            "(write of cert chain failed)");          ssl_error_to_verror();          goto end;       }    }    *bio = output_bio;    output_bio = NULL;    return_status = SSL_SUCCESS;    end:    if (output_bio)       BIO_free(output_bio);    return return_status;}/* * my_init() * * Do any needed initialization for these routines. * Should be called first. Can be called multiple times. */static voidmy_init(){    static int my_inited = 0;        if (my_inited == 0)    {	my_inited = 1;	/* Initialize the ssleay libraries */	SSL_load_error_strings();	SSLeay_add_ssl_algorithms();	globus_module_activate(GLOBUS_GSI_PROXY_MODULE);	globus_module_activate(GLOBUS_GSI_CREDENTIAL_MODULE);	globus_module_activate(GLOBUS_GSI_SYSCONFIG_MODULE);	globus_module_activate(GLOBUS_GSI_CERT_UTILS_MODULE);    }}	/* * my_pass_phrase_callback() * * Callback from PEM_read_PrivateKey() in ssl_load_user_key() * to return the passphrase stored in _ssl_pass_phrase. */static intmy_pass_phrase_callback(char			*buffer,			 int			buffer_len,			 int			verify /* Ignored */,			void                    *u){    /* SSL libs supply these, make sure they are reasonable */    assert(buffer != NULL);    assert(buffer_len > 0);        if (_ssl_pass_phrase == NULL)    {	strcpy(buffer, "");    }    else    {	strncpy(buffer, _ssl_pass_phrase, buffer_len);	buffer[buffer_len - 1] = '\0';    }    return strlen(buffer);}	     /********************************************************************** * * API Functions * */voidssl_credentials_destroy(SSL_CREDENTIALS		*creds){    my_init();        if (creds != NULL)    {	ssl_credentials_free_contents(creds);		free(creds);    }}intssl_proxy_file_destroy(const char *proxyfile){    FILE *fp;    long offset, i;    char zero = '\0';    struct stat s;    int return_status = SSL_ERROR;        assert(proxyfile != NULL);    fp = fopen(proxyfile, "r+");    if (!fp) {	verror_put_string("fopen(%s): %s\n", proxyfile, strerror(errno));	goto error;    }    /* Don't get fooled into zeroing out the wrong file via tricks       with links and the like. */    if (fstat(fileno(fp), &s) < 0) {	verror_put_string("fstat(%s): %s\n", proxyfile, strerror(errno));	goto error;    }    if (S_ISDIR(s.st_mode)) {	verror_put_string("proxy file %s is a directory!\n", proxyfile);	goto error;    }    if (!S_ISREG(s.st_mode)) {	verror_put_string("proxy file %s is not a regular file!\n",			  proxyfile);	goto error;    }    if (s.st_nlink != 1) {	verror_put_string("proxy file %s has links!\n", proxyfile);	goto error;    }    if (fseek(fp, 0L, SEEK_END) < 0) {	verror_put_string("fseek(%s): %s\n", proxyfile, strerror(errno));	goto error;    }    offset = ftell(fp);    if (offset < 0) {	verror_put_string("ftell(%s): %s\n", proxyfile, strerror(errno));	goto error;    }    if (fseek(fp, 0L, SEEK_SET) < 0) {	verror_put_string("fseek(%s): %s\n", proxyfile, strerror(errno));	goto error;    }    for (i=0; i < offset; i++) {	if (fwrite(&zero, 1, 1, fp) != 1) {	    verror_put_string("fwrite(%s): %s\n", proxyfile,			      strerror(errno));	    goto error;	}    }    return_status = SSL_SUCCESS; error:    if (fp) fclose(fp);    if (unlink(proxyfile) < 0) { /* always try to unlink it, even on error */	verror_put_string("unlink: %s\n", strerror(errno));	return SSL_ERROR;    }    return return_status;}			     		     intssl_certificate_load_from_file(SSL_CREDENTIALS	*creds,			       const char	*path){    FILE		*cert_file = NULL;    X509		*cert = NULL;    int			return_status = SSL_ERROR;    STACK		*cert_chain = NULL;        assert(creds != NULL);    assert(path != NULL);    my_init();        cert_file = fopen(path, "r");        if (cert_file == NULL)     {	verror_put_string("Error opening certificate file %s", path);	verror_put_errno(errno);	goto error;    }        if ((cert = PEM_read_X509(cert_file, NULL, PEM_NO_CALLBACK)) == NULL)    {	verror_put_string("Error reading certificate %s", path);	ssl_error_to_verror();	goto error;    }    if (creds->certificate != NULL)    {	X509_free(creds->certificate);    }        creds->certificate = cert;    /* Ok, now read the certificate chain */    /* Create empty stack */    cert_chain = sk_new_null();        while (1)    {	cert = NULL;		if ((cert = PEM_read_X509(cert_file, NULL, PEM_NO_CALLBACK)) == NULL)	{	    /*	     * If we just can't find a start line then we've reached EOF.	     */	    if (ERR_GET_REASON(ERR_peek_error()) == PEM_R_NO_START_LINE)	    {		/* Just EOF, clear error and break out of loop */		ERR_clear_error();		break;	    }	    /* Actual error */	    verror_put_string("Error parsing certificate chain");	    ssl_error_to_verror();	    goto error;	}	/* Add to chain */	if (sk_insert(cert_chain, (char *) cert,		      sk_num(cert_chain)) == SSL_ERROR)	{	    verror_put_string("Error parsing certificate chain");	    ssl_error_to_verror();	    goto error;	}    } /* while(1) */    creds->certificate_chain = cert_chain;        /* Success */    return_status = SSL_SUCCESS;      error:    if (cert_file != NULL)     {	fclose(cert_file);    }        return return_status;}intssl_private_key_load_from_file(SSL_CREDENTIALS	*creds,			       const char	*path,			       const char	*pass_phrase,			       const char	*pass_phrase_prompt){    FILE		*key_file = NULL;    EVP_PKEY		*key = NULL;    int			return_status = SSL_ERROR;        assert(creds != NULL);    assert(path != NULL);        my_init();        /*      * Put pass phrase where the callback function can find it.     */    _ssl_pass_phrase = pass_phrase;    if (pass_phrase_prompt) EVP_set_pw_prompt((char *)pass_phrase_prompt);    key_file = fopen(path, "r");        if (key_file == NULL)    {	verror_put_string("Error opening key file %s", path);	verror_put_errno(errno);	goto error;    }    if (PEM_read_PrivateKey(key_file, &(key), (pass_phrase_prompt) ? 			    NULL : my_pass_phrase_callback, NULL) == NULL)    {	unsigned long error, reason;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -