ssl.c
changeset 4 cb3d0d99955c
child 43 6903f7870c4c
equal deleted inserted replaced
-1:000000000000 4:cb3d0d99955c
       
     1 /*
       
     2  * Copyright (c) 2013 Sunil Nimmagadda <sunil@nimmagadda.net>
       
     3  * Copyright (c) 2006 Pierre-Yves Ritschard <pyr@openbsd.org>
       
     4  *
       
     5  * Permission to use, copy, modify, and distribute this software for any
       
     6  * purpose with or without fee is hereby granted, provided that the above
       
     7  * copyright notice and this permission notice appear in all copies.
       
     8  *
       
     9  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
       
    10  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
       
    11  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
       
    12  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
       
    13  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
       
    14  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
       
    15  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
       
    16  */
       
    17 
       
    18 #include <sys/types.h>
       
    19 #include <sys/socket.h>
       
    20 #include <sys/uio.h>
       
    21 #include <sys/stat.h>
       
    22 
       
    23 #include <fcntl.h>
       
    24 #include <syslog.h>
       
    25 #include <unistd.h>
       
    26 
       
    27 #include <openssl/ssl.h>
       
    28 #include <openssl/engine.h>
       
    29 #include <openssl/err.h>
       
    30 
       
    31 #include "pop3d.h"
       
    32 #include "ssl.h"
       
    33 
       
    34 #define SSL_CIPHERS		"HIGH"
       
    35 #define SSL_SESSION_TIMEOUT	300
       
    36 #define CERTFILE		"/etc/ssl/server.crt"
       
    37 #define KEYFILE			"/etc/ssl/private/server.key"
       
    38 
       
    39 static char *ssl_load_file(const char *, off_t *);
       
    40 
       
    41 void
       
    42 ssl_init(void)
       
    43 {
       
    44 	/* SSL init */
       
    45 	SSL_library_init();
       
    46 	SSL_load_error_strings();
       
    47 	OpenSSL_add_all_algorithms();
       
    48 
       
    49 	/* Init hardware cryto engines. */
       
    50 	ENGINE_load_builtin_engines();
       
    51 	ENGINE_register_all_complete();
       
    52 }
       
    53 
       
    54 void *
       
    55 ssl_setup(void)
       
    56 {
       
    57 	SSL_CTX *ctx = NULL;
       
    58 	char	*cert, *key;
       
    59 	off_t	cert_len, key_len;
       
    60 
       
    61 	/* SSL context creation */
       
    62 	ctx = SSL_CTX_new(SSLv23_server_method());
       
    63 	if (ctx == NULL) {
       
    64 		ssl_error("ssl_ctx_create");
       
    65 		fatal("ssl_ctx_create: could not create SSL context");
       
    66 	}
       
    67 
       
    68 	SSL_CTX_set_session_cache_mode(ctx, SSL_SESS_CACHE_OFF);
       
    69 	SSL_CTX_set_timeout(ctx, SSL_SESSION_TIMEOUT);
       
    70 	SSL_CTX_set_options(ctx,
       
    71 	    SSL_OP_ALL | SSL_OP_NO_SSLv2 | SSL_OP_NO_TICKET);
       
    72 	SSL_CTX_set_options(ctx,
       
    73 	    SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION);
       
    74 
       
    75 	/* SSL certificate, key loading */
       
    76 	cert = ssl_load_file(CERTFILE, &cert_len);
       
    77 	if (cert == NULL)
       
    78 		fatal("ssl_load_file: Unable to load " CERTFILE);
       
    79 
       
    80 	key = ssl_load_file(KEYFILE, &key_len);
       
    81 	if (key == NULL)
       
    82 		fatal("ssl_load_file: Unable to load " KEYFILE);
       
    83 
       
    84 	if (!SSL_CTX_set_cipher_list(ctx, SSL_CIPHERS))
       
    85 		goto err;
       
    86 
       
    87 	if (!ssl_ctx_use_certificate_chain(ctx, cert, cert_len))
       
    88 		goto err;
       
    89 
       
    90 	else if (!ssl_ctx_use_private_key(ctx, key, key_len))
       
    91 		goto err;
       
    92 
       
    93 	else if (!SSL_CTX_check_private_key(ctx))
       
    94 		goto err;
       
    95 
       
    96 	return (ctx);
       
    97 
       
    98 err:
       
    99 	if (ctx != NULL)
       
   100 		SSL_CTX_free(ctx);
       
   101 	ssl_error("ssl_setup");
       
   102 	fatal("ssl_setup: cannot set SSL up");
       
   103 	return (NULL);
       
   104 }
       
   105 
       
   106 void *
       
   107 pop3s_init(SSL_CTX *ctx, int fd)
       
   108 {
       
   109 	SSL *ssl;
       
   110 
       
   111 	if ((ssl = SSL_new(ctx)) == NULL)
       
   112 		fatal("SSL_new");
       
   113 
       
   114 	if (SSL_set_fd(ssl, fd) == 0)
       
   115 		fatal("SSL_set_fd");
       
   116 
       
   117 	return (ssl);
       
   118 }
       
   119 
       
   120 static char *
       
   121 ssl_load_file(const char *name, off_t *len)
       
   122 {
       
   123 	struct stat	st;
       
   124 	off_t		size;
       
   125 	char		*buf = NULL;
       
   126 	int		fd;
       
   127 
       
   128 	if ((fd = open(name, O_RDONLY)) == -1)
       
   129 		return (NULL);
       
   130 
       
   131 	if (fstat(fd, &st) != 0)
       
   132 		goto fail;
       
   133 
       
   134 	size = st.st_size;
       
   135 	if ((buf = calloc(1, size + 1)) == NULL)
       
   136 		goto fail;
       
   137 	if (read(fd, buf, size) != size)
       
   138 		goto fail;
       
   139 
       
   140 	close(fd);
       
   141 
       
   142 	*len = size;
       
   143 	return (buf);
       
   144 
       
   145 fail:
       
   146 	if (buf != NULL)
       
   147 		free(buf);
       
   148 
       
   149 	close(fd);
       
   150 	return (NULL);
       
   151 }
       
   152 
       
   153 void
       
   154 ssl_error(const char *where)
       
   155 {
       
   156 	unsigned long	code;
       
   157 	char		errbuf[128];
       
   158 	extern int	debug;
       
   159 
       
   160 	if (!debug)
       
   161 		return;
       
   162 
       
   163 	for (; (code = ERR_get_error()) != 0 ;) {
       
   164 		ERR_error_string_n(code, errbuf, sizeof(errbuf));
       
   165 		logit(LOG_DEBUG, "SSL library error: %s: %s", where, errbuf);
       
   166 	}
       
   167 }
       
   168