1 |
|
|
/* $OpenBSD: ca.c,v 1.27 2017/05/17 14:00:06 deraadt Exp $ */ |
2 |
|
|
|
3 |
|
|
/* |
4 |
|
|
* Copyright (c) 2014 Reyk Floeter <reyk@openbsd.org> |
5 |
|
|
* Copyright (c) 2012 Gilles Chehade <gilles@poolp.org> |
6 |
|
|
* |
7 |
|
|
* Permission to use, copy, modify, and distribute this software for any |
8 |
|
|
* purpose with or without fee is hereby granted, provided that the above |
9 |
|
|
* copyright notice and this permission notice appear in all copies. |
10 |
|
|
* |
11 |
|
|
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES |
12 |
|
|
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF |
13 |
|
|
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR |
14 |
|
|
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES |
15 |
|
|
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN |
16 |
|
|
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF |
17 |
|
|
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
18 |
|
|
*/ |
19 |
|
|
|
20 |
|
|
#include <sys/types.h> |
21 |
|
|
#include <sys/queue.h> |
22 |
|
|
#include <sys/socket.h> |
23 |
|
|
#include <sys/tree.h> |
24 |
|
|
|
25 |
|
|
#include <err.h> |
26 |
|
|
#include <imsg.h> |
27 |
|
|
#include <limits.h> |
28 |
|
|
#include <pwd.h> |
29 |
|
|
#include <signal.h> |
30 |
|
|
#include <stdlib.h> |
31 |
|
|
#include <string.h> |
32 |
|
|
#include <unistd.h> |
33 |
|
|
|
34 |
|
|
#include <openssl/ssl.h> |
35 |
|
|
#include <openssl/pem.h> |
36 |
|
|
#include <openssl/evp.h> |
37 |
|
|
#include <openssl/rsa.h> |
38 |
|
|
#include <openssl/engine.h> |
39 |
|
|
#include <openssl/err.h> |
40 |
|
|
|
41 |
|
|
#include "smtpd.h" |
42 |
|
|
#include "log.h" |
43 |
|
|
#include "ssl.h" |
44 |
|
|
|
45 |
|
|
static int ca_verify_cb(int, X509_STORE_CTX *); |
46 |
|
|
|
47 |
|
|
static int rsae_send_imsg(int, const unsigned char *, unsigned char *, |
48 |
|
|
RSA *, int, unsigned int); |
49 |
|
|
static int rsae_pub_enc(int, const unsigned char *, unsigned char *, |
50 |
|
|
RSA *, int); |
51 |
|
|
static int rsae_pub_dec(int,const unsigned char *, unsigned char *, |
52 |
|
|
RSA *, int); |
53 |
|
|
static int rsae_priv_enc(int, const unsigned char *, unsigned char *, |
54 |
|
|
RSA *, int); |
55 |
|
|
static int rsae_priv_dec(int, const unsigned char *, unsigned char *, |
56 |
|
|
RSA *, int); |
57 |
|
|
static int rsae_mod_exp(BIGNUM *, const BIGNUM *, RSA *, BN_CTX *); |
58 |
|
|
static int rsae_bn_mod_exp(BIGNUM *, const BIGNUM *, const BIGNUM *, |
59 |
|
|
const BIGNUM *, BN_CTX *, BN_MONT_CTX *); |
60 |
|
|
static int rsae_init(RSA *); |
61 |
|
|
static int rsae_finish(RSA *); |
62 |
|
|
static int rsae_keygen(RSA *, int, BIGNUM *, BN_GENCB *); |
63 |
|
|
|
64 |
|
|
static uint64_t rsae_reqid = 0; |
65 |
|
|
|
66 |
|
|
static void |
67 |
|
|
ca_shutdown(void) |
68 |
|
|
{ |
69 |
|
|
log_debug("debug: ca agent exiting"); |
70 |
|
|
_exit(0); |
71 |
|
|
} |
72 |
|
|
|
73 |
|
|
int |
74 |
|
|
ca(void) |
75 |
|
|
{ |
76 |
|
|
struct passwd *pw; |
77 |
|
|
|
78 |
|
|
purge_config(PURGE_LISTENERS|PURGE_TABLES|PURGE_RULES); |
79 |
|
|
|
80 |
|
|
if ((pw = getpwnam(SMTPD_USER)) == NULL) |
81 |
|
|
fatalx("unknown user " SMTPD_USER); |
82 |
|
|
|
83 |
|
|
if (chroot(PATH_CHROOT) == -1) |
84 |
|
|
fatal("ca: chroot"); |
85 |
|
|
if (chdir("/") == -1) |
86 |
|
|
fatal("ca: chdir(\"/\")"); |
87 |
|
|
|
88 |
|
|
config_process(PROC_CA); |
89 |
|
|
|
90 |
|
|
if (setgroups(1, &pw->pw_gid) || |
91 |
|
|
setresgid(pw->pw_gid, pw->pw_gid, pw->pw_gid) || |
92 |
|
|
setresuid(pw->pw_uid, pw->pw_uid, pw->pw_uid)) |
93 |
|
|
fatal("ca: cannot drop privileges"); |
94 |
|
|
|
95 |
|
|
imsg_callback = ca_imsg; |
96 |
|
|
event_init(); |
97 |
|
|
|
98 |
|
|
signal(SIGINT, SIG_IGN); |
99 |
|
|
signal(SIGTERM, SIG_IGN); |
100 |
|
|
signal(SIGPIPE, SIG_IGN); |
101 |
|
|
signal(SIGHUP, SIG_IGN); |
102 |
|
|
|
103 |
|
|
config_peer(PROC_CONTROL); |
104 |
|
|
config_peer(PROC_PARENT); |
105 |
|
|
config_peer(PROC_PONY); |
106 |
|
|
|
107 |
|
|
/* Ignore them until we get our config */ |
108 |
|
|
mproc_disable(p_pony); |
109 |
|
|
|
110 |
|
|
if (pledge("stdio flock rpath cpath wpath", NULL) == -1) |
111 |
|
|
err(1, "pledge"); |
112 |
|
|
|
113 |
|
|
event_dispatch(); |
114 |
|
|
fatalx("exited event loop"); |
115 |
|
|
|
116 |
|
|
return (0); |
117 |
|
|
} |
118 |
|
|
|
119 |
|
|
void |
120 |
|
|
ca_init(void) |
121 |
|
|
{ |
122 |
|
|
BIO *in = NULL; |
123 |
|
|
EVP_PKEY *pkey = NULL; |
124 |
|
|
struct pki *pki; |
125 |
|
|
const char *k; |
126 |
|
|
void *iter_dict; |
127 |
|
|
|
128 |
|
|
log_debug("debug: init private ssl-tree"); |
129 |
|
|
iter_dict = NULL; |
130 |
|
|
while (dict_iter(env->sc_pki_dict, &iter_dict, &k, (void **)&pki)) { |
131 |
|
|
if (pki->pki_key == NULL) |
132 |
|
|
continue; |
133 |
|
|
|
134 |
|
|
if ((in = BIO_new_mem_buf(pki->pki_key, |
135 |
|
|
pki->pki_key_len)) == NULL) |
136 |
|
|
fatalx("ca_launch: key"); |
137 |
|
|
|
138 |
|
|
if ((pkey = PEM_read_bio_PrivateKey(in, |
139 |
|
|
NULL, NULL, NULL)) == NULL) |
140 |
|
|
fatalx("ca_launch: PEM"); |
141 |
|
|
BIO_free(in); |
142 |
|
|
|
143 |
|
|
pki->pki_pkey = pkey; |
144 |
|
|
|
145 |
|
|
freezero(pki->pki_key, pki->pki_key_len); |
146 |
|
|
pki->pki_key = NULL; |
147 |
|
|
} |
148 |
|
|
} |
149 |
|
|
|
150 |
|
|
static int |
151 |
|
|
ca_verify_cb(int ok, X509_STORE_CTX *ctx) |
152 |
|
|
{ |
153 |
|
|
switch (X509_STORE_CTX_get_error(ctx)) { |
154 |
|
|
case X509_V_OK: |
155 |
|
|
break; |
156 |
|
|
case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT: |
157 |
|
|
break; |
158 |
|
|
case X509_V_ERR_CERT_NOT_YET_VALID: |
159 |
|
|
case X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD: |
160 |
|
|
break; |
161 |
|
|
case X509_V_ERR_CERT_HAS_EXPIRED: |
162 |
|
|
case X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD: |
163 |
|
|
break; |
164 |
|
|
case X509_V_ERR_NO_EXPLICIT_POLICY: |
165 |
|
|
break; |
166 |
|
|
} |
167 |
|
|
return ok; |
168 |
|
|
} |
169 |
|
|
|
170 |
|
|
int |
171 |
|
|
ca_X509_verify(void *certificate, void *chain, const char *CAfile, |
172 |
|
|
const char *CRLfile, const char **errstr) |
173 |
|
|
{ |
174 |
|
|
X509_STORE *store = NULL; |
175 |
|
|
X509_STORE_CTX *xsc = NULL; |
176 |
|
|
int ret = 0; |
177 |
|
|
|
178 |
|
|
if ((store = X509_STORE_new()) == NULL) |
179 |
|
|
goto end; |
180 |
|
|
|
181 |
|
|
if (!X509_STORE_load_locations(store, CAfile, NULL)) { |
182 |
|
|
log_warn("warn: unable to load CA file %s", CAfile); |
183 |
|
|
goto end; |
184 |
|
|
} |
185 |
|
|
X509_STORE_set_default_paths(store); |
186 |
|
|
|
187 |
|
|
if ((xsc = X509_STORE_CTX_new()) == NULL) |
188 |
|
|
goto end; |
189 |
|
|
|
190 |
|
|
if (X509_STORE_CTX_init(xsc, store, certificate, chain) != 1) |
191 |
|
|
goto end; |
192 |
|
|
|
193 |
|
|
X509_STORE_CTX_set_verify_cb(xsc, ca_verify_cb); |
194 |
|
|
|
195 |
|
|
ret = X509_verify_cert(xsc); |
196 |
|
|
|
197 |
|
|
end: |
198 |
|
|
*errstr = NULL; |
199 |
|
|
if (ret != 1) { |
200 |
|
|
if (xsc) |
201 |
|
|
*errstr = X509_verify_cert_error_string(xsc->error); |
202 |
|
|
else if (ERR_peek_last_error()) |
203 |
|
|
*errstr = ERR_error_string(ERR_peek_last_error(), NULL); |
204 |
|
|
} |
205 |
|
|
|
206 |
|
|
X509_STORE_CTX_free(xsc); |
207 |
|
|
X509_STORE_free(store); |
208 |
|
|
|
209 |
|
|
return ret > 0 ? 1 : 0; |
210 |
|
|
} |
211 |
|
|
|
212 |
|
|
void |
213 |
|
|
ca_imsg(struct mproc *p, struct imsg *imsg) |
214 |
|
|
{ |
215 |
|
|
RSA *rsa; |
216 |
|
|
const void *from = NULL; |
217 |
|
|
unsigned char *to = NULL; |
218 |
|
|
struct msg m; |
219 |
|
|
const char *pkiname; |
220 |
|
|
size_t flen, tlen, padding; |
221 |
|
|
struct pki *pki; |
222 |
|
|
int ret = 0; |
223 |
|
|
uint64_t id; |
224 |
|
|
int v; |
225 |
|
|
|
226 |
|
|
if (imsg == NULL) |
227 |
|
|
ca_shutdown(); |
228 |
|
|
|
229 |
|
|
if (p->proc == PROC_PARENT) { |
230 |
|
|
switch (imsg->hdr.type) { |
231 |
|
|
case IMSG_CONF_START: |
232 |
|
|
return; |
233 |
|
|
case IMSG_CONF_END: |
234 |
|
|
ca_init(); |
235 |
|
|
|
236 |
|
|
/* Start fulfilling requests */ |
237 |
|
|
mproc_enable(p_pony); |
238 |
|
|
return; |
239 |
|
|
} |
240 |
|
|
} |
241 |
|
|
|
242 |
|
|
if (p->proc == PROC_CONTROL) { |
243 |
|
|
switch (imsg->hdr.type) { |
244 |
|
|
case IMSG_CTL_VERBOSE: |
245 |
|
|
m_msg(&m, imsg); |
246 |
|
|
m_get_int(&m, &v); |
247 |
|
|
m_end(&m); |
248 |
|
|
log_trace_verbose(v); |
249 |
|
|
return; |
250 |
|
|
case IMSG_CTL_PROFILE: |
251 |
|
|
m_msg(&m, imsg); |
252 |
|
|
m_get_int(&m, &v); |
253 |
|
|
m_end(&m); |
254 |
|
|
profiling = v; |
255 |
|
|
return; |
256 |
|
|
} |
257 |
|
|
} |
258 |
|
|
|
259 |
|
|
if (p->proc == PROC_PONY) { |
260 |
|
|
switch (imsg->hdr.type) { |
261 |
|
|
case IMSG_CA_PRIVENC: |
262 |
|
|
case IMSG_CA_PRIVDEC: |
263 |
|
|
m_msg(&m, imsg); |
264 |
|
|
m_get_id(&m, &id); |
265 |
|
|
m_get_string(&m, &pkiname); |
266 |
|
|
m_get_data(&m, &from, &flen); |
267 |
|
|
m_get_size(&m, &tlen); |
268 |
|
|
m_get_size(&m, &padding); |
269 |
|
|
m_end(&m); |
270 |
|
|
|
271 |
|
|
pki = dict_get(env->sc_pki_dict, pkiname); |
272 |
|
|
if (pki == NULL || pki->pki_pkey == NULL || |
273 |
|
|
(rsa = EVP_PKEY_get1_RSA(pki->pki_pkey)) == NULL) |
274 |
|
|
fatalx("ca_imsg: invalid pki"); |
275 |
|
|
|
276 |
|
|
if ((to = calloc(1, tlen)) == NULL) |
277 |
|
|
fatalx("ca_imsg: calloc"); |
278 |
|
|
|
279 |
|
|
switch (imsg->hdr.type) { |
280 |
|
|
case IMSG_CA_PRIVENC: |
281 |
|
|
ret = RSA_private_encrypt(flen, from, to, rsa, |
282 |
|
|
padding); |
283 |
|
|
break; |
284 |
|
|
case IMSG_CA_PRIVDEC: |
285 |
|
|
ret = RSA_private_decrypt(flen, from, to, rsa, |
286 |
|
|
padding); |
287 |
|
|
break; |
288 |
|
|
} |
289 |
|
|
|
290 |
|
|
m_create(p, imsg->hdr.type, 0, 0, -1); |
291 |
|
|
m_add_id(p, id); |
292 |
|
|
m_add_int(p, ret); |
293 |
|
|
if (ret > 0) |
294 |
|
|
m_add_data(p, to, (size_t)ret); |
295 |
|
|
m_close(p); |
296 |
|
|
|
297 |
|
|
free(to); |
298 |
|
|
RSA_free(rsa); |
299 |
|
|
|
300 |
|
|
return; |
301 |
|
|
} |
302 |
|
|
} |
303 |
|
|
|
304 |
|
|
errx(1, "ca_imsg: unexpected %s imsg", imsg_to_str(imsg->hdr.type)); |
305 |
|
|
} |
306 |
|
|
|
307 |
|
|
/* |
308 |
|
|
* RSA privsep engine (called from unprivileged processes) |
309 |
|
|
*/ |
310 |
|
|
|
311 |
|
|
const RSA_METHOD *rsa_default = NULL; |
312 |
|
|
|
313 |
|
|
static RSA_METHOD rsae_method = { |
314 |
|
|
"RSA privsep engine", |
315 |
|
|
rsae_pub_enc, |
316 |
|
|
rsae_pub_dec, |
317 |
|
|
rsae_priv_enc, |
318 |
|
|
rsae_priv_dec, |
319 |
|
|
rsae_mod_exp, |
320 |
|
|
rsae_bn_mod_exp, |
321 |
|
|
rsae_init, |
322 |
|
|
rsae_finish, |
323 |
|
|
0, |
324 |
|
|
NULL, |
325 |
|
|
NULL, |
326 |
|
|
NULL, |
327 |
|
|
rsae_keygen |
328 |
|
|
}; |
329 |
|
|
|
330 |
|
|
static int |
331 |
|
|
rsae_send_imsg(int flen, const unsigned char *from, unsigned char *to, |
332 |
|
|
RSA *rsa, int padding, unsigned int cmd) |
333 |
|
|
{ |
334 |
|
|
int ret = 0; |
335 |
|
|
struct imsgbuf *ibuf; |
336 |
|
|
struct imsg imsg; |
337 |
|
|
int n, done = 0; |
338 |
|
|
const void *toptr; |
339 |
|
|
char *pkiname; |
340 |
|
|
size_t tlen; |
341 |
|
|
struct msg m; |
342 |
|
|
uint64_t id; |
343 |
|
|
|
344 |
|
|
if ((pkiname = RSA_get_ex_data(rsa, 0)) == NULL) |
345 |
|
|
return (0); |
346 |
|
|
|
347 |
|
|
/* |
348 |
|
|
* Send a synchronous imsg because we cannot defer the RSA |
349 |
|
|
* operation in OpenSSL's engine layer. |
350 |
|
|
*/ |
351 |
|
|
m_create(p_ca, cmd, 0, 0, -1); |
352 |
|
|
rsae_reqid++; |
353 |
|
|
m_add_id(p_ca, rsae_reqid); |
354 |
|
|
m_add_string(p_ca, pkiname); |
355 |
|
|
m_add_data(p_ca, (const void *)from, (size_t)flen); |
356 |
|
|
m_add_size(p_ca, (size_t)RSA_size(rsa)); |
357 |
|
|
m_add_size(p_ca, (size_t)padding); |
358 |
|
|
m_flush(p_ca); |
359 |
|
|
|
360 |
|
|
ibuf = &p_ca->imsgbuf; |
361 |
|
|
|
362 |
|
|
while (!done) { |
363 |
|
|
if ((n = imsg_read(ibuf)) == -1 && errno != EAGAIN) |
364 |
|
|
fatalx("imsg_read"); |
365 |
|
|
if (n == 0) |
366 |
|
|
fatalx("pipe closed"); |
367 |
|
|
|
368 |
|
|
while (!done) { |
369 |
|
|
if ((n = imsg_get(ibuf, &imsg)) == -1) |
370 |
|
|
fatalx("imsg_get error"); |
371 |
|
|
if (n == 0) |
372 |
|
|
break; |
373 |
|
|
|
374 |
|
|
log_imsg(PROC_PONY, PROC_CA, &imsg); |
375 |
|
|
|
376 |
|
|
switch (imsg.hdr.type) { |
377 |
|
|
case IMSG_CA_PRIVENC: |
378 |
|
|
case IMSG_CA_PRIVDEC: |
379 |
|
|
break; |
380 |
|
|
default: |
381 |
|
|
/* Another imsg is queued up in the buffer */ |
382 |
|
|
pony_imsg(p_ca, &imsg); |
383 |
|
|
imsg_free(&imsg); |
384 |
|
|
continue; |
385 |
|
|
} |
386 |
|
|
|
387 |
|
|
m_msg(&m, &imsg); |
388 |
|
|
m_get_id(&m, &id); |
389 |
|
|
if (id != rsae_reqid) |
390 |
|
|
fatalx("invalid response id"); |
391 |
|
|
m_get_int(&m, &ret); |
392 |
|
|
if (ret > 0) |
393 |
|
|
m_get_data(&m, &toptr, &tlen); |
394 |
|
|
m_end(&m); |
395 |
|
|
|
396 |
|
|
if (ret > 0) |
397 |
|
|
memcpy(to, toptr, tlen); |
398 |
|
|
done = 1; |
399 |
|
|
|
400 |
|
|
imsg_free(&imsg); |
401 |
|
|
} |
402 |
|
|
} |
403 |
|
|
mproc_event_add(p_ca); |
404 |
|
|
|
405 |
|
|
return (ret); |
406 |
|
|
} |
407 |
|
|
|
408 |
|
|
static int |
409 |
|
|
rsae_pub_enc(int flen,const unsigned char *from, unsigned char *to, RSA *rsa, |
410 |
|
|
int padding) |
411 |
|
|
{ |
412 |
|
|
log_debug("debug: %s: %s", proc_name(smtpd_process), __func__); |
413 |
|
|
return (rsa_default->rsa_pub_enc(flen, from, to, rsa, padding)); |
414 |
|
|
} |
415 |
|
|
|
416 |
|
|
static int |
417 |
|
|
rsae_pub_dec(int flen,const unsigned char *from, unsigned char *to, RSA *rsa, |
418 |
|
|
int padding) |
419 |
|
|
{ |
420 |
|
|
log_debug("debug: %s: %s", proc_name(smtpd_process), __func__); |
421 |
|
|
return (rsa_default->rsa_pub_dec(flen, from, to, rsa, padding)); |
422 |
|
|
} |
423 |
|
|
|
424 |
|
|
static int |
425 |
|
|
rsae_priv_enc(int flen, const unsigned char *from, unsigned char *to, RSA *rsa, |
426 |
|
|
int padding) |
427 |
|
|
{ |
428 |
|
|
log_debug("debug: %s: %s", proc_name(smtpd_process), __func__); |
429 |
|
|
if (RSA_get_ex_data(rsa, 0) != NULL) { |
430 |
|
|
return (rsae_send_imsg(flen, from, to, rsa, padding, |
431 |
|
|
IMSG_CA_PRIVENC)); |
432 |
|
|
} |
433 |
|
|
return (rsa_default->rsa_priv_enc(flen, from, to, rsa, padding)); |
434 |
|
|
} |
435 |
|
|
|
436 |
|
|
static int |
437 |
|
|
rsae_priv_dec(int flen, const unsigned char *from, unsigned char *to, RSA *rsa, |
438 |
|
|
int padding) |
439 |
|
|
{ |
440 |
|
|
log_debug("debug: %s: %s", proc_name(smtpd_process), __func__); |
441 |
|
|
if (RSA_get_ex_data(rsa, 0) != NULL) { |
442 |
|
|
return (rsae_send_imsg(flen, from, to, rsa, padding, |
443 |
|
|
IMSG_CA_PRIVDEC)); |
444 |
|
|
} |
445 |
|
|
return (rsa_default->rsa_priv_dec(flen, from, to, rsa, padding)); |
446 |
|
|
} |
447 |
|
|
|
448 |
|
|
static int |
449 |
|
|
rsae_mod_exp(BIGNUM *r0, const BIGNUM *I, RSA *rsa, BN_CTX *ctx) |
450 |
|
|
{ |
451 |
|
|
log_debug("debug: %s: %s", proc_name(smtpd_process), __func__); |
452 |
|
|
return (rsa_default->rsa_mod_exp(r0, I, rsa, ctx)); |
453 |
|
|
} |
454 |
|
|
|
455 |
|
|
static int |
456 |
|
|
rsae_bn_mod_exp(BIGNUM *r, const BIGNUM *a, const BIGNUM *p, |
457 |
|
|
const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx) |
458 |
|
|
{ |
459 |
|
|
log_debug("debug: %s: %s", proc_name(smtpd_process), __func__); |
460 |
|
|
return (rsa_default->bn_mod_exp(r, a, p, m, ctx, m_ctx)); |
461 |
|
|
} |
462 |
|
|
|
463 |
|
|
static int |
464 |
|
|
rsae_init(RSA *rsa) |
465 |
|
|
{ |
466 |
|
|
log_debug("debug: %s: %s", proc_name(smtpd_process), __func__); |
467 |
|
|
if (rsa_default->init == NULL) |
468 |
|
|
return (1); |
469 |
|
|
return (rsa_default->init(rsa)); |
470 |
|
|
} |
471 |
|
|
|
472 |
|
|
static int |
473 |
|
|
rsae_finish(RSA *rsa) |
474 |
|
|
{ |
475 |
|
|
log_debug("debug: %s: %s", proc_name(smtpd_process), __func__); |
476 |
|
|
if (rsa_default->finish == NULL) |
477 |
|
|
return (1); |
478 |
|
|
return (rsa_default->finish(rsa)); |
479 |
|
|
} |
480 |
|
|
|
481 |
|
|
static int |
482 |
|
|
rsae_keygen(RSA *rsa, int bits, BIGNUM *e, BN_GENCB *cb) |
483 |
|
|
{ |
484 |
|
|
log_debug("debug: %s: %s", proc_name(smtpd_process), __func__); |
485 |
|
|
return (rsa_default->rsa_keygen(rsa, bits, e, cb)); |
486 |
|
|
} |
487 |
|
|
|
488 |
|
|
void |
489 |
|
|
ca_engine_init(void) |
490 |
|
|
{ |
491 |
|
|
ENGINE *e; |
492 |
|
|
const char *errstr, *name; |
493 |
|
|
|
494 |
|
|
if ((e = ENGINE_get_default_RSA()) == NULL) { |
495 |
|
|
if ((e = ENGINE_new()) == NULL) { |
496 |
|
|
errstr = "ENGINE_new"; |
497 |
|
|
goto fail; |
498 |
|
|
} |
499 |
|
|
if (!ENGINE_set_name(e, rsae_method.name)) { |
500 |
|
|
errstr = "ENGINE_set_name"; |
501 |
|
|
goto fail; |
502 |
|
|
} |
503 |
|
|
if ((rsa_default = RSA_get_default_method()) == NULL) { |
504 |
|
|
errstr = "RSA_get_default_method"; |
505 |
|
|
goto fail; |
506 |
|
|
} |
507 |
|
|
} else if ((rsa_default = ENGINE_get_RSA(e)) == NULL) { |
508 |
|
|
errstr = "ENGINE_get_RSA"; |
509 |
|
|
goto fail; |
510 |
|
|
} |
511 |
|
|
|
512 |
|
|
if ((name = ENGINE_get_name(e)) == NULL) |
513 |
|
|
name = "unknown RSA engine"; |
514 |
|
|
|
515 |
|
|
log_debug("debug: %s: using %s", __func__, name); |
516 |
|
|
|
517 |
|
|
if (rsa_default->flags & RSA_FLAG_SIGN_VER) |
518 |
|
|
fatalx("unsupported RSA engine"); |
519 |
|
|
|
520 |
|
|
if (rsa_default->rsa_mod_exp == NULL) |
521 |
|
|
rsae_method.rsa_mod_exp = NULL; |
522 |
|
|
if (rsa_default->bn_mod_exp == NULL) |
523 |
|
|
rsae_method.bn_mod_exp = NULL; |
524 |
|
|
if (rsa_default->rsa_keygen == NULL) |
525 |
|
|
rsae_method.rsa_keygen = NULL; |
526 |
|
|
rsae_method.flags = rsa_default->flags | |
527 |
|
|
RSA_METHOD_FLAG_NO_CHECK; |
528 |
|
|
rsae_method.app_data = rsa_default->app_data; |
529 |
|
|
|
530 |
|
|
if (!ENGINE_set_RSA(e, &rsae_method)) { |
531 |
|
|
errstr = "ENGINE_set_RSA"; |
532 |
|
|
goto fail; |
533 |
|
|
} |
534 |
|
|
if (!ENGINE_set_default_RSA(e)) { |
535 |
|
|
errstr = "ENGINE_set_default_RSA"; |
536 |
|
|
goto fail; |
537 |
|
|
} |
538 |
|
|
|
539 |
|
|
return; |
540 |
|
|
|
541 |
|
|
fail: |
542 |
|
|
ssl_error(errstr); |
543 |
|
|
fatalx("%s", errstr); |
544 |
|
|
} |