ssl_privsep.c
changeset 0 9e2cb1ed20b1
equal deleted inserted replaced
-1:000000000000 0:9e2cb1ed20b1
       
     1 /*      $OpenBSD: ssl_privsep.c,v 1.1 2014/01/27 15:49:52 sunil Exp $    */
       
     2 
       
     3 /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
       
     4  * All rights reserved.
       
     5  *
       
     6  * This package is an SSL implementation written
       
     7  * by Eric Young (eay@cryptsoft.com).
       
     8  * The implementation was written so as to conform with Netscapes SSL.
       
     9  *
       
    10  * This library is free for commercial and non-commercial use as long as
       
    11  * the following conditions are aheared to.  The following conditions
       
    12  * apply to all code found in this distribution, be it the RC4, RSA,
       
    13  * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
       
    14  * included with this distribution is covered by the same copyright terms
       
    15  * except that the holder is Tim Hudson (tjh@cryptsoft.com).
       
    16  *
       
    17  * Copyright remains Eric Young's, and as such any Copyright notices in
       
    18  * the code are not to be removed.
       
    19  * If this package is used in a product, Eric Young should be given attribution
       
    20  * as the author of the parts of the library used.
       
    21  * This can be in the form of a textual message at program startup or
       
    22  * in documentation (online or textual) provided with the package.
       
    23  *
       
    24  * Redistribution and use in source and binary forms, with or without
       
    25  * modification, are permitted provided that the following conditions
       
    26  * are met:
       
    27  * 1. Redistributions of source code must retain the copyright
       
    28  *    notice, this list of conditions and the following disclaimer.
       
    29  * 2. Redistributions in binary form must reproduce the above copyright
       
    30  *    notice, this list of conditions and the following disclaimer in the
       
    31  *    documentation and/or other materials provided with the distribution.
       
    32  * 3. All advertising materials mentioning features or use of this software
       
    33  *    must display the following acknowledgement:
       
    34  *    "This product includes cryptographic software written by
       
    35  *     Eric Young (eay@cryptsoft.com)"
       
    36  *    The word 'cryptographic' can be left out if the rouines from the library
       
    37  *    being used are not cryptographic related :-).
       
    38  * 4. If you include any Windows specific code (or a derivative thereof) from
       
    39  *    the apps directory (application code) you must include an acknowledgement:
       
    40  *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
       
    41  *
       
    42  * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
       
    43  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
       
    44  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
       
    45  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
       
    46  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
       
    47  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
       
    48  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
       
    49  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
       
    50  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
       
    51  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
       
    52  * SUCH DAMAGE.
       
    53  *
       
    54  * The licence and distribution terms for any publically available version or
       
    55  * derivative of this code cannot be changed.  i.e. this code cannot simply be
       
    56  * copied and put under another distribution licence
       
    57  * [including the GNU Public Licence.]
       
    58  */
       
    59 
       
    60 /*
       
    61  * SSL operations needed when running in a privilege separated environment.
       
    62  * Adapted from openssl's ssl_rsa.c by Pierre-Yves Ritschard .
       
    63  */
       
    64 
       
    65 #include <sys/types.h>
       
    66 #include <sys/uio.h>
       
    67 
       
    68 #include <unistd.h>
       
    69 #include <stdio.h>
       
    70 
       
    71 #include <openssl/err.h>
       
    72 #include <openssl/bio.h>
       
    73 #include <openssl/objects.h>
       
    74 #include <openssl/evp.h>
       
    75 #include <openssl/x509.h>
       
    76 #include <openssl/pem.h>
       
    77 #include <openssl/ssl.h>
       
    78 
       
    79 int	 ssl_ctx_use_private_key(SSL_CTX *, char *, off_t);
       
    80 int	 ssl_ctx_use_certificate_chain(SSL_CTX *, char *, off_t);
       
    81 int	 ssl_ctx_load_verify_memory(SSL_CTX *, char *, off_t);
       
    82 int	 ssl_by_mem_ctrl(X509_LOOKUP *, int, const char *, long, char **);
       
    83 
       
    84 X509_LOOKUP_METHOD x509_mem_lookup = {
       
    85 	"Load cert from memory",
       
    86 	NULL,			/* new */
       
    87 	NULL,			/* free */
       
    88 	NULL,			/* init */
       
    89 	NULL,			/* shutdown */
       
    90 	ssl_by_mem_ctrl,	/* ctrl */
       
    91 	NULL,			/* get_by_subject */
       
    92 	NULL,			/* get_by_issuer_serial */
       
    93 	NULL,			/* get_by_fingerprint */
       
    94 	NULL,			/* get_by_alias */
       
    95 };
       
    96 
       
    97 #define X509_L_ADD_MEM	3
       
    98 
       
    99 int
       
   100 ssl_ctx_use_private_key(SSL_CTX *ctx, char *buf, off_t len)
       
   101 {
       
   102 	int		 ret;
       
   103 	BIO		*in;
       
   104 	EVP_PKEY	*pkey;
       
   105 
       
   106 	ret = 0;
       
   107 
       
   108 	if ((in = BIO_new_mem_buf(buf, len)) == NULL) {
       
   109 		SSLerr(SSL_F_SSL_CTX_USE_PRIVATEKEY_FILE, ERR_R_BUF_LIB);
       
   110 		return 0;
       
   111 	}
       
   112 
       
   113 	pkey = PEM_read_bio_PrivateKey(in, NULL,
       
   114 	    ctx->default_passwd_callback,
       
   115 	    ctx->default_passwd_callback_userdata);
       
   116 
       
   117 	if (pkey == NULL) {
       
   118 		SSLerr(SSL_F_SSL_CTX_USE_PRIVATEKEY_FILE, ERR_R_PEM_LIB);
       
   119 		goto end;
       
   120 	}
       
   121 	ret = SSL_CTX_use_PrivateKey(ctx, pkey);
       
   122 	EVP_PKEY_free(pkey);
       
   123 end:
       
   124 	if (in != NULL)
       
   125 		BIO_free(in);
       
   126 	return ret;
       
   127 }
       
   128 
       
   129 
       
   130 int
       
   131 ssl_ctx_use_certificate_chain(SSL_CTX *ctx, char *buf, off_t len)
       
   132 {
       
   133 	int		 ret;
       
   134 	BIO		*in;
       
   135 	X509		*x;
       
   136 	X509		*ca;
       
   137 	unsigned long	 err;
       
   138 
       
   139 	ret = 0;
       
   140 	x = ca = NULL;
       
   141 
       
   142 	if ((in = BIO_new_mem_buf(buf, len)) == NULL) {
       
   143 		SSLerr(SSL_F_SSL_CTX_USE_CERTIFICATE_CHAIN_FILE, ERR_R_BUF_LIB);
       
   144 		goto end;
       
   145 	}
       
   146 
       
   147 	if ((x = PEM_read_bio_X509(in, NULL,
       
   148 	    ctx->default_passwd_callback,
       
   149 	    ctx->default_passwd_callback_userdata)) == NULL) {
       
   150 		SSLerr(SSL_F_SSL_CTX_USE_CERTIFICATE_CHAIN_FILE, ERR_R_PEM_LIB);
       
   151 		goto end;
       
   152 	}
       
   153 
       
   154 	if (!SSL_CTX_use_certificate(ctx, x) || ERR_peek_error() != 0)
       
   155 		goto end;
       
   156 
       
   157 	/* If we could set up our certificate, now proceed to
       
   158 	 * the CA certificates.
       
   159 	 */
       
   160 
       
   161 	if (ctx->extra_certs != NULL) {
       
   162 		sk_X509_pop_free(ctx->extra_certs, X509_free);
       
   163 		ctx->extra_certs = NULL;
       
   164 	}
       
   165 
       
   166 	while ((ca = PEM_read_bio_X509(in, NULL,
       
   167 	    ctx->default_passwd_callback,
       
   168 	    ctx->default_passwd_callback_userdata)) != NULL) {
       
   169 
       
   170 		if (!SSL_CTX_add_extra_chain_cert(ctx, ca))
       
   171 			goto end;
       
   172 	}
       
   173 
       
   174 	err = ERR_peek_last_error();
       
   175 	if (ERR_GET_LIB(err) == ERR_LIB_PEM &&
       
   176 	    ERR_GET_REASON(err) == PEM_R_NO_START_LINE)
       
   177 		ERR_clear_error();
       
   178 	else
       
   179 		goto end;
       
   180 
       
   181 	ret = 1;
       
   182 end:
       
   183 	if (ca != NULL)
       
   184 		X509_free(ca);
       
   185 	if (x != NULL)
       
   186 		X509_free(x);
       
   187 	if (in != NULL)
       
   188 		BIO_free(in);
       
   189 	return (ret);
       
   190 }
       
   191 
       
   192 int
       
   193 ssl_ctx_load_verify_memory(SSL_CTX *ctx, char *buf, off_t len)
       
   194 {
       
   195 	X509_LOOKUP		*lu;
       
   196 	struct iovec		 iov;
       
   197 
       
   198 	if ((lu = X509_STORE_add_lookup(ctx->cert_store,
       
   199 	    &x509_mem_lookup)) == NULL)
       
   200 		return (0);
       
   201 
       
   202 	iov.iov_base = buf;
       
   203 	iov.iov_len = len;
       
   204 
       
   205 	if (!ssl_by_mem_ctrl(lu, X509_L_ADD_MEM,
       
   206 	    (const char *)&iov, X509_FILETYPE_PEM, NULL))
       
   207 		return (0);
       
   208 
       
   209 	return (1);
       
   210 }
       
   211 
       
   212 int
       
   213 ssl_by_mem_ctrl(X509_LOOKUP *lu, int cmd, const char *buf,
       
   214     long type, char **ret)
       
   215 {
       
   216 	STACK_OF(X509_INFO)	*inf;
       
   217 	const struct iovec	*iov;
       
   218 	X509_INFO		*itmp;
       
   219 	BIO			*in = NULL;
       
   220 	int			 i, count = 0;
       
   221 
       
   222 	iov = (const struct iovec *)buf;
       
   223 
       
   224 	if (type != X509_FILETYPE_PEM)
       
   225 		goto done;
       
   226 
       
   227 	if ((in = BIO_new_mem_buf(iov->iov_base, iov->iov_len)) == NULL)
       
   228 		goto done;
       
   229 
       
   230 	if ((inf = PEM_X509_INFO_read_bio(in, NULL, NULL, NULL)) == NULL)
       
   231 		goto done;
       
   232 
       
   233 	for (i = 0; i < sk_X509_INFO_num(inf); i++) {
       
   234 		itmp = sk_X509_INFO_value(inf, i);
       
   235 		if (itmp->x509) {
       
   236 			X509_STORE_add_cert(lu->store_ctx, itmp->x509);
       
   237 			count++;
       
   238 		}
       
   239 		if (itmp->crl) {
       
   240 			X509_STORE_add_crl(lu->store_ctx, itmp->crl);
       
   241 			count++;
       
   242 		}
       
   243 	}
       
   244 	sk_X509_INFO_pop_free(inf, X509_INFO_free);
       
   245 
       
   246  done:
       
   247 	if (!count)
       
   248 		X509err(X509_F_X509_LOAD_CERT_CRL_FILE,ERR_R_PEM_LIB);
       
   249 
       
   250 	if (in != NULL)
       
   251 		BIO_free(in);
       
   252 	return (count);
       
   253 }