ssl-bozo.c revision 1.1.1.4 1 /* $eterna: ssl-bozo.c,v 1.11 2010/05/10 02:51:28 mrg Exp $ */
2
3 /*
4 * Copyright (c) 1997-2010 Matthew R. Green
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer and
14 * dedication in the documentation and/or other materials provided
15 * with the distribution.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
22 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
24 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
25 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 *
29 */
30
31 /* this code implements SSL for bozohttpd */
32
33 #include <stdarg.h>
34 #include <stdio.h>
35 #include <unistd.h>
36
37 #include "bozohttpd.h"
38
39 #ifndef NO_SSL_SUPPORT
40
41 #include <openssl/ssl.h>
42 #include <openssl/err.h>
43
44 #ifndef USE_ARG
45 #define USE_ARG(x) /*LINTED*/(void)&(x)
46 #endif
47
48 /* this structure encapsulates the ssl info */
49 typedef struct sslinfo_t {
50 SSL_CTX *ssl_context;
51 const SSL_METHOD *ssl_method;
52 SSL *bozossl;
53 char *certificate_file;
54 char *privatekey_file;
55 } sslinfo_t;
56
57 static int
58 bozo_ssl_printf(bozohttpd_t *httpd, const char * fmt, ...)
59 {
60 sslinfo_t *sslinfo;
61 va_list ap;
62 char *buf;
63 int nbytes;
64
65 sslinfo = httpd->sslinfo;
66 /* XXX we need more elegant/proper handling of SSL_write return */
67 va_start(ap, fmt);
68 if ((nbytes = vasprintf(&buf, fmt, ap)) != -1)
69 SSL_write(sslinfo->bozossl, buf, nbytes);
70 va_end(ap);
71
72 free(buf);
73
74 return nbytes;
75 }
76
77 static ssize_t
78 bozo_ssl_read(bozohttpd_t *httpd, int fd, void *buf, size_t nbytes)
79 {
80 sslinfo_t *sslinfo;
81 ssize_t rbytes;
82
83 USE_ARG(fd);
84 sslinfo = httpd->sslinfo;
85 /* XXX we need elegant/proper handling of SSL_read return */
86 rbytes = (ssize_t)SSL_read(sslinfo->bozossl, buf, (int)nbytes);
87 if (rbytes < 1) {
88 if (SSL_get_error(sslinfo->bozossl, rbytes) ==
89 SSL_ERROR_WANT_READ)
90 bozo_warn(httpd, "SSL_ERROR_WANT_READ");
91 else
92 bozo_warn(httpd, "SSL_ERROR OTHER");
93 }
94
95 return rbytes;
96 }
97
98 static ssize_t
99 bozo_ssl_write(bozohttpd_t *httpd, int fd, const void *buf, size_t nbytes)
100 {
101 sslinfo_t *sslinfo;
102 ssize_t wbytes;
103
104 USE_ARG(fd);
105 sslinfo = httpd->sslinfo;
106 /* XXX we need elegant/proper handling of SSL_write return */
107 wbytes = (ssize_t)SSL_write(sslinfo->bozossl, buf, (int)nbytes);
108
109 return wbytes;
110 }
111
112 static int
113 bozo_ssl_flush(bozohttpd_t *httpd, FILE *fp)
114 {
115 USE_ARG(httpd);
116 USE_ARG(fp);
117 /* nothing to see here, move right along */
118 return 0;
119 }
120
121 void
122 bozo_ssl_init(bozohttpd_t *httpd)
123 {
124 sslinfo_t *sslinfo;
125
126 sslinfo = httpd->sslinfo;
127 if (sslinfo == NULL || !sslinfo->certificate_file)
128 return;
129 SSL_library_init();
130 SSL_load_error_strings();
131
132 sslinfo->ssl_method = SSLv23_server_method();
133 sslinfo->ssl_context = SSL_CTX_new(sslinfo->ssl_method);
134
135 /* XXX we need to learn how to check the SSL stack for more info */
136 if (sslinfo->ssl_context == NULL)
137 bozo_err(httpd, 1, "SSL context initialization failed.");
138
139 SSL_CTX_use_certificate_file(sslinfo->ssl_context,
140 sslinfo->certificate_file, SSL_FILETYPE_PEM);
141 SSL_CTX_use_PrivateKey_file(sslinfo->ssl_context,
142 sslinfo->privatekey_file, SSL_FILETYPE_PEM);
143
144 /* check consistency of key vs certificate */
145 if (!SSL_CTX_check_private_key(sslinfo->ssl_context))
146 bozo_err(httpd, 1, "check private key failed");
147 }
148
149 void
150 bozo_ssl_accept(bozohttpd_t *httpd)
151 {
152 sslinfo_t *sslinfo;
153
154 sslinfo = httpd->sslinfo;
155 if (sslinfo != NULL && sslinfo->ssl_context) {
156 sslinfo->bozossl = SSL_new(sslinfo->ssl_context);
157 SSL_set_rfd(sslinfo->bozossl, 0);
158 SSL_set_wfd(sslinfo->bozossl, 1);
159 SSL_accept(sslinfo->bozossl);
160 }
161 }
162
163 void
164 bozo_ssl_destroy(bozohttpd_t *httpd)
165 {
166 sslinfo_t *sslinfo;
167
168 sslinfo = httpd->sslinfo;
169 if (sslinfo && sslinfo->bozossl)
170 SSL_free(sslinfo->bozossl);
171 }
172
173 void
174 bozo_ssl_set_opts(bozohttpd_t *httpd, const char *cert, const char *priv)
175 {
176 sslinfo_t *sslinfo;
177
178 if ((sslinfo = httpd->sslinfo) == NULL) {
179 sslinfo = bozomalloc(httpd, sizeof(*sslinfo));
180 if (sslinfo == NULL) {
181 bozo_err(httpd, 1, "sslinfo allocation failed");
182 }
183 httpd->sslinfo = sslinfo;
184 }
185 sslinfo->certificate_file = strdup(cert);
186 sslinfo->privatekey_file = strdup(priv);
187 debug((httpd, DEBUG_NORMAL, "using cert/priv files: %s & %s",
188 sslinfo->certificate_file,
189 sslinfo->privatekey_file));
190 if (!httpd->bindport) {
191 httpd->bindport = strdup("https");
192 }
193 }
194
195 #endif /* NO_SSL_SUPPORT */
196
197 int
198 bozo_printf(bozohttpd_t *httpd, const char *fmt, ...)
199 {
200 va_list args;
201 int cc;
202
203 va_start(args, fmt);
204 #ifndef NO_SSL_SUPPORT
205 if (httpd->sslinfo) {
206 cc = bozo_ssl_printf(httpd, fmt, args);
207 va_end(args);
208 return cc;
209 }
210 #endif
211 cc = vprintf(fmt, args);
212 va_end(args);
213 return cc;
214 }
215
216 ssize_t
217 bozo_read(bozohttpd_t *httpd, int fd, void *buf, size_t len)
218 {
219 #ifndef NO_SSL_SUPPORT
220 if (httpd->sslinfo) {
221 return bozo_ssl_read(httpd, fd, buf, len);
222 }
223 #endif
224 return read(fd, buf, len);
225 }
226
227 ssize_t
228 bozo_write(bozohttpd_t *httpd, int fd, const void *buf, size_t len)
229 {
230 #ifndef NO_SSL_SUPPORT
231 if (httpd->sslinfo) {
232 return bozo_ssl_write(httpd, fd, buf, len);
233 }
234 #endif
235 return write(fd, buf, len);
236 }
237
238 int
239 bozo_flush(bozohttpd_t *httpd, FILE *fp)
240 {
241 #ifndef NO_SSL_SUPPORT
242 if (httpd->sslinfo) {
243 return bozo_ssl_flush(httpd, fp);
244 }
245 #endif
246 return fflush(fp);
247 }
248