diff options
Diffstat (limited to 'tcpd/libcouriergnutls.c')
| -rw-r--r-- | tcpd/libcouriergnutls.c | 80 | 
1 files changed, 73 insertions, 7 deletions
| diff --git a/tcpd/libcouriergnutls.c b/tcpd/libcouriergnutls.c index f3c34d4..da57d1f 100644 --- a/tcpd/libcouriergnutls.c +++ b/tcpd/libcouriergnutls.c @@ -126,6 +126,7 @@ struct ssl_context_t {  	const char *priority_list;  	char *certfile; +	char *keyfile;  	char *dhfile;  	char *trustcerts; @@ -267,6 +268,17 @@ ssl_context tls_create(int isserver, const struct tls_info *info)  			free(certfile);  	} +	if ((certfile=strdup(safe_getenv(p, "TLS_PRIVATE_KEYFILE", ""))) != NULL && +	    *certfile) +	{ +		p->keyfile=certfile; +	} +	else +	{ +		if (certfile) +			free(certfile); +	} +  	switch (*safe_getenv(p, "TLS_VERIFYPEER", "P")) {  	case 'n':  	case 'N': @@ -320,6 +332,8 @@ void tls_destroy(ssl_context p)  {  	if (p->certfile)  		free(p->certfile); +	if (p->keyfile) +		free(p->keyfile);  	if (p->dhfile)  		free(p->dhfile);  	if (p->trustcerts) @@ -749,6 +763,14 @@ static char *check_cert(const char *filename,  	return NULL;  } +static char *check_key(const char *filename, +			gnutls_certificate_type_t cert_type, +			const char *req_dn, +			int isvirtual) +{ +	return check_cert(filename, cert_type, req_dn, isvirtual); +} +  static int read_file(const char *file,  		     gnutls_datum_t *filebuf)  { @@ -790,10 +812,12 @@ static void release_file(gnutls_datum_t *filebuf)  static int set_cert(ssl_handle ssl,  		    gnutls_session_t session,  		    gnutls_retr2_st *st, -		    const char *certfilename) +		    const char *certfilename, +		    const char *keyfilename)  {  	int rc;  	gnutls_datum_t filebuf; +	gnutls_datum_t keyfilebuf;  	unsigned int cert_cnt;  	st->ncerts=0; @@ -803,15 +827,34 @@ static int set_cert(ssl_handle ssl,  	if ((rc=read_file(certfilename, &filebuf)) < 0)  		return rc; +	if (keyfilename) +	{ +		if ((rc=read_file(keyfilename, &keyfilebuf)) < 0) +		{ +			release_file(&filebuf); +			return rc; +		} +	} +  	switch (st->cert_type) {  	case GNUTLS_CRT_X509:  		cert_cnt=0; -		if ((rc=gnutls_x509_privkey_init(&ssl->x509_key)) < 0 || -		    (rc=gnutls_x509_privkey_import(ssl->x509_key, &filebuf, -						   GNUTLS_X509_FMT_PEM)) < 0) -			break; +		if (keyfilename) +		{ +			if ((rc=gnutls_x509_privkey_init(&ssl->x509_key)) < 0 || +			    (rc=gnutls_x509_privkey_import(ssl->x509_key, &keyfilebuf, +							   GNUTLS_X509_FMT_PEM)) < 0) +				break; +		} +		else +		{ +			if ((rc=gnutls_x509_privkey_init(&ssl->x509_key)) < 0 || +			    (rc=gnutls_x509_privkey_import(ssl->x509_key, &filebuf, +							   GNUTLS_X509_FMT_PEM)) < 0) +				break; +		}  		rc=gnutls_x509_crt_list_import(NULL, &cert_cnt,  					       &filebuf, @@ -846,6 +889,8 @@ static int set_cert(ssl_handle ssl,  	}  	release_file(&filebuf); +	if (keyfilename) +		release_file(&keyfilebuf);  	return 0;  } @@ -862,6 +907,7 @@ static int get_server_cert(gnutls_session_t session,  	size_t vhost_size;  	unsigned int type=GNUTLS_NAME_DNS;  	char *certfilename=NULL; +	char *keyfilename=NULL;  	int rc;  	st->cert_type=gnutls_certificate_type_get(session); @@ -897,6 +943,11 @@ static int get_server_cert(gnutls_session_t session,  						st->cert_type,  						vhost_buf, 1); +		if (ssl->ctx->keyfile) +			keyfilename=check_key(ssl->ctx->keyfile, +						st->cert_type, +						vhost_buf, 1); +  		if (certfilename)  			break;  	} @@ -909,6 +960,12 @@ static int get_server_cert(gnutls_session_t session,  						safe_getenv(ssl->ctx,  							    "TCPLOCALIP", ""),  						0); +		if (ssl->ctx->keyfile) +			keyfilename=check_key(ssl->ctx->keyfile, +						st->cert_type, +						safe_getenv(ssl->ctx, +							    "TCPLOCALIP", ""), +						0);  	}  	if (!certfilename) @@ -918,8 +975,10 @@ static int get_server_cert(gnutls_session_t session,  		return 0;  	} -	rc=set_cert(ssl, session, st, certfilename); +	rc=set_cert(ssl, session, st, certfilename, keyfilename);  	free(certfilename); +	if (keyfilename) +		free(keyfilename);  	return rc;  } @@ -1072,6 +1131,7 @@ static int get_client_cert(gnutls_session_t session,  	ssl_handle ssl=(ssl_handle)gnutls_session_get_ptr(session);  	int rc;  	char *certfilename=NULL; +	char *keyfilename=NULL;  	rc= 0;  	st->cert_type=gnutls_certificate_type_get(session); @@ -1080,13 +1140,19 @@ static int get_client_cert(gnutls_session_t session,  		certfilename=check_cert(ssl->ctx->certfile,  					st->cert_type, "", 0); +	if (ssl->ctx->keyfile) +		keyfilename=check_key(ssl->ctx->keyfile, +					st->cert_type, "", 0); +  	st->ncerts=0;  	st->deinit_all=0;  	if (certfilename)  	{ -		rc=set_cert(ssl, session, st, certfilename); +		rc=set_cert(ssl, session, st, certfilename, keyfilename);  		free(certfilename); +		if (keyfilename) +			free(keyfilename);  	}  	else  	{ | 
