No fprintf in the txt_db component
[openssl.git] / ssl / ssl_conf.c
1 /*
2  * ! \file ssl/ssl_conf.c \brief SSL configuration functions
3  */
4 /* ====================================================================
5  * Copyright (c) 2012 The OpenSSL Project.  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  *
11  * 1. Redistributions of source code must retain the above copyright
12  *    notice, this list of conditions and the following disclaimer.
13  *
14  * 2. Redistributions in binary form must reproduce the above copyright
15  *    notice, this list of conditions and the following disclaimer in
16  *    the documentation and/or other materials provided with the
17  *    distribution.
18  *
19  * 3. All advertising materials mentioning features or use of this
20  *    software must display the following acknowledgment:
21  *    "This product includes software developed by the OpenSSL Project
22  *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
23  *
24  * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
25  *    endorse or promote products derived from this software without
26  *    prior written permission. For written permission, please contact
27  *    openssl-core@openssl.org.
28  *
29  * 5. Products derived from this software may not be called "OpenSSL"
30  *    nor may "OpenSSL" appear in their names without prior written
31  *    permission of the OpenSSL Project.
32  *
33  * 6. Redistributions of any form whatsoever must retain the following
34  *    acknowledgment:
35  *    "This product includes software developed by the OpenSSL Project
36  *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
37  *
38  * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
39  * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
40  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
41  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
42  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
43  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
44  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
45  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
46  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
47  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
48  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
49  * OF THE POSSIBILITY OF SUCH DAMAGE.
50  * ====================================================================
51  *
52  * This product includes cryptographic software written by Eric Young
53  * (eay@cryptsoft.com).  This product includes software written by Tim
54  * Hudson (tjh@cryptsoft.com).
55  *
56  */
57
58 #ifdef REF_CHECK
59 # include <assert.h>
60 #endif
61 #include <stdio.h>
62 #include "ssl_locl.h"
63 #include <openssl/conf.h>
64 #include <openssl/objects.h>
65 #ifndef OPENSSL_NO_DH
66 # include <openssl/dh.h>
67 #endif
68
69 /*
70  * structure holding name tables. This is used for pemitted elements in lists
71  * such as TLSv1.
72  */
73
74 typedef struct {
75     const char *name;
76     int namelen;
77     unsigned int name_flags;
78     unsigned long option_value;
79 } ssl_flag_tbl;
80
81 /* Switch table: use for single command line switches like no_tls2 */
82 typedef struct {
83     unsigned long option_value;
84     unsigned int name_flags;
85 } ssl_switch_tbl;
86
87 /* Sense of name is inverted e.g. "TLSv1" will clear SSL_OP_NO_TLSv1 */
88 #define SSL_TFLAG_INV   0x1
89 /* Flags refers to cert_flags not options */
90 #define SSL_TFLAG_CERT  0x2
91 /* Option can only be used for clients */
92 #define SSL_TFLAG_CLIENT SSL_CONF_FLAG_CLIENT
93 /* Option can only be used for servers */
94 #define SSL_TFLAG_SERVER SSL_CONF_FLAG_SERVER
95 #define SSL_TFLAG_BOTH (SSL_TFLAG_CLIENT|SSL_TFLAG_SERVER)
96
97 #define SSL_FLAG_TBL(str, flag) \
98         {str, (int)(sizeof(str) - 1), SSL_TFLAG_BOTH, flag}
99 #define SSL_FLAG_TBL_SRV(str, flag) \
100         {str, (int)(sizeof(str) - 1), SSL_TFLAG_SERVER, flag}
101 #define SSL_FLAG_TBL_CLI(str, flag) \
102         {str, (int)(sizeof(str) - 1), SSL_TFLAG_CLIENT, flag}
103 #define SSL_FLAG_TBL_INV(str, flag) \
104         {str, (int)(sizeof(str) - 1), SSL_TFLAG_INV|SSL_TFLAG_BOTH, flag}
105 #define SSL_FLAG_TBL_SRV_INV(str, flag) \
106         {str, (int)(sizeof(str) - 1), SSL_TFLAG_INV|SSL_TFLAG_SERVER, flag}
107 #define SSL_FLAG_TBL_CERT(str, flag) \
108         {str, (int)(sizeof(str) - 1), SSL_TFLAG_CERT|SSL_TFLAG_BOTH, flag}
109
110 /*
111  * Opaque structure containing SSL configuration context.
112  */
113
114 struct ssl_conf_ctx_st {
115     /*
116      * Various flags indicating (among other things) which options we will
117      * recognise.
118      */
119     unsigned int flags;
120     /* Prefix and length of commands */
121     char *prefix;
122     size_t prefixlen;
123     /* SSL_CTX or SSL structure to perform operations on */
124     SSL_CTX *ctx;
125     SSL *ssl;
126     /* Pointer to SSL or SSL_CTX options field or NULL if none */
127     unsigned long *poptions;
128     /* Certificate filenames for each type */
129     char *cert_filename[SSL_PKEY_NUM];
130     /* Pointer to SSL or SSL_CTX cert_flags or NULL if none */
131     unsigned int *pcert_flags;
132     /* Current flag table being worked on */
133     const ssl_flag_tbl *tbl;
134     /* Size of table */
135     size_t ntbl;
136 };
137
138 static void ssl_set_option(SSL_CONF_CTX *cctx, unsigned int name_flags,
139                            unsigned long option_value, int onoff)
140 {
141     if (cctx->poptions == NULL)
142         return;
143     if (name_flags & SSL_TFLAG_INV)
144         onoff ^= 1;
145     if (name_flags & SSL_TFLAG_CERT) {
146         if (onoff)
147             *cctx->pcert_flags |= option_value;
148         else
149             *cctx->pcert_flags &= ~option_value;
150     } else {
151         if (onoff)
152             *cctx->poptions |= option_value;
153         else
154             *cctx->poptions &= ~option_value;
155     }
156 }
157
158 static int ssl_match_option(SSL_CONF_CTX *cctx, const ssl_flag_tbl *tbl,
159                             const char *name, int namelen, int onoff)
160 {
161     /* If name not relevant for context skip */
162     if (!(cctx->flags & tbl->name_flags & SSL_TFLAG_BOTH))
163         return 0;
164     if (namelen == -1) {
165         if (strcmp(tbl->name, name))
166             return 0;
167     } else if (tbl->namelen != namelen
168                || strncasecmp(tbl->name, name, namelen))
169         return 0;
170     ssl_set_option(cctx, tbl->name_flags, tbl->option_value, onoff);
171     return 1;
172 }
173
174 static int ssl_set_option_list(const char *elem, int len, void *usr)
175 {
176     SSL_CONF_CTX *cctx = usr;
177     size_t i;
178     const ssl_flag_tbl *tbl;
179     int onoff = 1;
180     /*
181      * len == -1 indicates not being called in list context, just for single
182      * command line switches, so don't allow +, -.
183      */
184     if (elem == NULL)
185         return 0;
186     if (len != -1) {
187         if (*elem == '+') {
188             elem++;
189             len--;
190             onoff = 1;
191         } else if (*elem == '-') {
192             elem++;
193             len--;
194             onoff = 0;
195         }
196     }
197     for (i = 0, tbl = cctx->tbl; i < cctx->ntbl; i++, tbl++) {
198         if (ssl_match_option(cctx, tbl, elem, len, onoff))
199             return 1;
200     }
201     return 0;
202 }
203
204 /* Set supported signature algorithms */
205 static int cmd_SignatureAlgorithms(SSL_CONF_CTX *cctx, const char *value)
206 {
207     int rv;
208     if (cctx->ssl)
209         rv = SSL_set1_sigalgs_list(cctx->ssl, value);
210     /* NB: ctx == NULL performs syntax checking only */
211     else
212         rv = SSL_CTX_set1_sigalgs_list(cctx->ctx, value);
213     return rv > 0;
214 }
215
216 /* Set supported client signature algorithms */
217 static int cmd_ClientSignatureAlgorithms(SSL_CONF_CTX *cctx,
218                                          const char *value)
219 {
220     int rv;
221     if (cctx->ssl)
222         rv = SSL_set1_client_sigalgs_list(cctx->ssl, value);
223     /* NB: ctx == NULL performs syntax checking only */
224     else
225         rv = SSL_CTX_set1_client_sigalgs_list(cctx->ctx, value);
226     return rv > 0;
227 }
228
229 static int cmd_Curves(SSL_CONF_CTX *cctx, const char *value)
230 {
231     int rv;
232     if (cctx->ssl)
233         rv = SSL_set1_curves_list(cctx->ssl, value);
234     /* NB: ctx == NULL performs syntax checking only */
235     else
236         rv = SSL_CTX_set1_curves_list(cctx->ctx, value);
237     return rv > 0;
238 }
239
240 #ifndef OPENSSL_NO_EC
241 /* ECDH temporary parameters */
242 static int cmd_ECDHParameters(SSL_CONF_CTX *cctx, const char *value)
243 {
244     int onoff = -1, rv = 1;
245     if (cctx->flags & SSL_CONF_FLAG_FILE) {
246         if (*value == '+') {
247             onoff = 1;
248             value++;
249         }
250         if (*value == '-') {
251             onoff = 0;
252             value++;
253         }
254         if (strcasecmp(value, "automatic") == 0) {
255             if (onoff == -1)
256                 onoff = 1;
257         } else if (onoff != -1)
258             return 0;
259     } else if (cctx->flags & SSL_CONF_FLAG_CMDLINE) {
260         if (strcmp(value, "auto") == 0)
261             onoff = 1;
262     }
263
264     if (onoff != -1) {
265         if (cctx->ctx)
266             rv = SSL_CTX_set_ecdh_auto(cctx->ctx, onoff);
267         else if (cctx->ssl)
268             rv = SSL_set_ecdh_auto(cctx->ssl, onoff);
269     } else {
270         EC_KEY *ecdh;
271         int nid;
272         nid = EC_curve_nist2nid(value);
273         if (nid == NID_undef)
274             nid = OBJ_sn2nid(value);
275         if (nid == 0)
276             return 0;
277         ecdh = EC_KEY_new_by_curve_name(nid);
278         if (!ecdh)
279             return 0;
280         if (cctx->ctx)
281             rv = SSL_CTX_set_tmp_ecdh(cctx->ctx, ecdh);
282         else if (cctx->ssl)
283             rv = SSL_set_tmp_ecdh(cctx->ssl, ecdh);
284         EC_KEY_free(ecdh);
285     }
286
287     return rv > 0;
288 }
289 #endif
290 static int cmd_CipherString(SSL_CONF_CTX *cctx, const char *value)
291 {
292     int rv = 1;
293     if (cctx->ctx)
294         rv = SSL_CTX_set_cipher_list(cctx->ctx, value);
295     if (cctx->ssl)
296         rv = SSL_set_cipher_list(cctx->ssl, value);
297     return rv > 0;
298 }
299
300 static int cmd_Protocol(SSL_CONF_CTX *cctx, const char *value)
301 {
302     static const ssl_flag_tbl ssl_protocol_list[] = {
303         SSL_FLAG_TBL_INV("ALL", SSL_OP_NO_SSL_MASK),
304         SSL_FLAG_TBL_INV("SSLv2", SSL_OP_NO_SSLv2),
305         SSL_FLAG_TBL_INV("SSLv3", SSL_OP_NO_SSLv3),
306         SSL_FLAG_TBL_INV("TLSv1", SSL_OP_NO_TLSv1),
307         SSL_FLAG_TBL_INV("TLSv1.1", SSL_OP_NO_TLSv1_1),
308         SSL_FLAG_TBL_INV("TLSv1.2", SSL_OP_NO_TLSv1_2)
309     };
310     cctx->tbl = ssl_protocol_list;
311     cctx->ntbl = OSSL_NELEM(ssl_protocol_list);
312     return CONF_parse_list(value, ',', 1, ssl_set_option_list, cctx);
313 }
314
315 static int cmd_Options(SSL_CONF_CTX *cctx, const char *value)
316 {
317     static const ssl_flag_tbl ssl_option_list[] = {
318         SSL_FLAG_TBL_INV("SessionTicket", SSL_OP_NO_TICKET),
319         SSL_FLAG_TBL_INV("EmptyFragments",
320                          SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS),
321         SSL_FLAG_TBL("Bugs", SSL_OP_ALL),
322         SSL_FLAG_TBL_INV("Compression", SSL_OP_NO_COMPRESSION),
323         SSL_FLAG_TBL_SRV("ServerPreference", SSL_OP_CIPHER_SERVER_PREFERENCE),
324         SSL_FLAG_TBL_SRV("NoResumptionOnRenegotiation",
325                          SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION),
326         SSL_FLAG_TBL_SRV("DHSingle", SSL_OP_SINGLE_DH_USE),
327         SSL_FLAG_TBL_SRV("ECDHSingle", SSL_OP_SINGLE_ECDH_USE),
328         SSL_FLAG_TBL("UnsafeLegacyRenegotiation",
329                      SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION),
330     };
331     if (value == NULL)
332         return -3;
333     cctx->tbl = ssl_option_list;
334     cctx->ntbl = OSSL_NELEM(ssl_option_list);
335     return CONF_parse_list(value, ',', 1, ssl_set_option_list, cctx);
336 }
337
338 static int cmd_Certificate(SSL_CONF_CTX *cctx, const char *value)
339 {
340     int rv = 1;
341     CERT *c = NULL;
342     if (cctx->ctx) {
343         rv = SSL_CTX_use_certificate_chain_file(cctx->ctx, value);
344         c = cctx->ctx->cert;
345     }
346     if (cctx->ssl) {
347         rv = SSL_use_certificate_chain_file(cctx->ssl, value);
348         c = cctx->ssl->cert;
349     }
350     if (rv > 0 && c && cctx->flags & SSL_CONF_FLAG_REQUIRE_PRIVATE) {
351         char **pfilename = &cctx->cert_filename[c->key - c->pkeys];
352         OPENSSL_free(*pfilename);
353         *pfilename = BUF_strdup(value);
354         if (!*pfilename)
355             rv = 0;
356     }
357
358     return rv > 0;
359 }
360
361 static int cmd_PrivateKey(SSL_CONF_CTX *cctx, const char *value)
362 {
363     int rv = 1;
364     if (!(cctx->flags & SSL_CONF_FLAG_CERTIFICATE))
365         return -2;
366     if (cctx->ctx)
367         rv = SSL_CTX_use_PrivateKey_file(cctx->ctx, value, SSL_FILETYPE_PEM);
368     if (cctx->ssl)
369         rv = SSL_use_PrivateKey_file(cctx->ssl, value, SSL_FILETYPE_PEM);
370     return rv > 0;
371 }
372
373 static int cmd_ServerInfoFile(SSL_CONF_CTX *cctx, const char *value)
374 {
375     int rv = 1;
376     if (cctx->ctx)
377         rv = SSL_CTX_use_serverinfo_file(cctx->ctx, value);
378     return rv > 0;
379 }
380
381 #ifndef OPENSSL_NO_DH
382 static int cmd_DHParameters(SSL_CONF_CTX *cctx, const char *value)
383 {
384     int rv = 0;
385     DH *dh = NULL;
386     BIO *in = NULL;
387     if (cctx->ctx || cctx->ssl) {
388         in = BIO_new(BIO_s_file_internal());
389         if (!in)
390             goto end;
391         if (BIO_read_filename(in, value) <= 0)
392             goto end;
393         dh = PEM_read_bio_DHparams(in, NULL, NULL, NULL);
394         if (!dh)
395             goto end;
396     } else
397         return 1;
398     if (cctx->ctx)
399         rv = SSL_CTX_set_tmp_dh(cctx->ctx, dh);
400     if (cctx->ssl)
401         rv = SSL_set_tmp_dh(cctx->ssl, dh);
402  end:
403     DH_free(dh);
404     BIO_free(in);
405     return rv > 0;
406 }
407 #endif
408 typedef struct {
409     int (*cmd) (SSL_CONF_CTX *cctx, const char *value);
410     const char *str_file;
411     const char *str_cmdline;
412     unsigned short flags;
413     unsigned short value_type;
414 } ssl_conf_cmd_tbl;
415
416 /* Table of supported parameters */
417
418 #define SSL_CONF_CMD(name, cmdopt, flags, type) \
419         {cmd_##name, #name, cmdopt, flags, type}
420
421 #define SSL_CONF_CMD_STRING(name, cmdopt, flags) \
422         SSL_CONF_CMD(name, cmdopt, flags, SSL_CONF_TYPE_STRING)
423
424 #define SSL_CONF_CMD_SWITCH(name, flags) \
425         {0, NULL, name, flags, SSL_CONF_TYPE_NONE}
426
427 /* See apps/apps.h if you change this table. */
428 static const ssl_conf_cmd_tbl ssl_conf_cmds[] = {
429     SSL_CONF_CMD_SWITCH("no_ssl3", 0),
430     SSL_CONF_CMD_SWITCH("no_tls1", 0),
431     SSL_CONF_CMD_SWITCH("no_tls1_1", 0),
432     SSL_CONF_CMD_SWITCH("no_tls1_2", 0),
433     SSL_CONF_CMD_SWITCH("bugs", 0),
434     SSL_CONF_CMD_SWITCH("no_comp", 0),
435     SSL_CONF_CMD_SWITCH("ecdh_single", SSL_CONF_FLAG_SERVER),
436     SSL_CONF_CMD_SWITCH("no_ticket", 0),
437     SSL_CONF_CMD_SWITCH("serverpref", SSL_CONF_FLAG_SERVER),
438     SSL_CONF_CMD_SWITCH("legacy_renegotiation", 0),
439     SSL_CONF_CMD_SWITCH("legacy_server_connect", SSL_CONF_FLAG_SERVER),
440     SSL_CONF_CMD_SWITCH("no_resumption_on_reneg", SSL_CONF_FLAG_SERVER),
441     SSL_CONF_CMD_SWITCH("no_legacy_server_connect", SSL_CONF_FLAG_SERVER),
442     SSL_CONF_CMD_SWITCH("strict", 0),
443 #ifdef OPENSSL_SSL_DEBUG_BROKEN_PROTOCOL
444     SSL_CONF_CMD_SWITCH("debug_broken_protocol", 0),
445 #endif
446     SSL_CONF_CMD_STRING(SignatureAlgorithms, "sigalgs", 0),
447     SSL_CONF_CMD_STRING(ClientSignatureAlgorithms, "client_sigalgs", 0),
448     SSL_CONF_CMD_STRING(Curves, "curves", 0),
449 #ifndef OPENSSL_NO_EC
450     SSL_CONF_CMD_STRING(ECDHParameters, "named_curve", SSL_CONF_FLAG_SERVER),
451 #endif
452     SSL_CONF_CMD_STRING(CipherString, "cipher", 0),
453     SSL_CONF_CMD_STRING(Protocol, NULL, 0),
454     SSL_CONF_CMD_STRING(Options, NULL, 0),
455     SSL_CONF_CMD(Certificate, "cert", SSL_CONF_FLAG_CERTIFICATE,
456                  SSL_CONF_TYPE_FILE),
457     SSL_CONF_CMD(PrivateKey, "key", SSL_CONF_FLAG_CERTIFICATE,
458                  SSL_CONF_TYPE_FILE),
459     SSL_CONF_CMD(ServerInfoFile, NULL,
460                  SSL_CONF_FLAG_SERVER | SSL_CONF_FLAG_CERTIFICATE,
461                  SSL_CONF_TYPE_FILE),
462 #ifndef OPENSSL_NO_DH
463     SSL_CONF_CMD(DHParameters, "dhparam",
464                  SSL_CONF_FLAG_SERVER | SSL_CONF_FLAG_CERTIFICATE,
465                  SSL_CONF_TYPE_FILE)
466 #endif
467 };
468
469 /* Supported switches: must match order of switches in ssl_conf_cmds */
470 static const ssl_switch_tbl ssl_cmd_switches[] = {
471     {SSL_OP_NO_SSLv3, 0},       /* no_ssl3 */
472     {SSL_OP_NO_TLSv1, 0},       /* no_tls1 */
473     {SSL_OP_NO_TLSv1_1, 0},     /* no_tls1_1 */
474     {SSL_OP_NO_TLSv1_2, 0},     /* no_tls1_2 */
475     {SSL_OP_ALL, 0},            /* bugs */
476     {SSL_OP_NO_COMPRESSION, 0}, /* no_comp */
477     {SSL_OP_SINGLE_ECDH_USE, 0}, /* ecdh_single */
478     {SSL_OP_NO_TICKET, 0},      /* no_ticket */
479     {SSL_OP_CIPHER_SERVER_PREFERENCE, 0}, /* serverpref */
480     /* legacy_renegotiation */
481     {SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION, 0},
482     /* legacy_server_connect */
483     {SSL_OP_LEGACY_SERVER_CONNECT, 0},
484     /* no_resumption_on_reneg */
485     {SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION, 0},
486     /* no_legacy_server_connect */
487     {SSL_OP_LEGACY_SERVER_CONNECT, SSL_TFLAG_INV},
488     {SSL_CERT_FLAG_TLS_STRICT, SSL_TFLAG_CERT}, /* strict */
489 #ifdef OPENSSL_SSL_DEBUG_BROKEN_PROTOCOL
490     {SSL_CERT_FLAG_BROKEN_PROTOCOL, SSL_TFLAG_CERT} /* debug_broken_protocol */
491 #endif
492 };
493
494 static int ssl_conf_cmd_skip_prefix(SSL_CONF_CTX *cctx, const char **pcmd)
495 {
496     if (!pcmd || !*pcmd)
497         return 0;
498     /* If a prefix is set, check and skip */
499     if (cctx->prefix) {
500         if (strlen(*pcmd) <= cctx->prefixlen)
501             return 0;
502         if (cctx->flags & SSL_CONF_FLAG_CMDLINE &&
503             strncmp(*pcmd, cctx->prefix, cctx->prefixlen))
504             return 0;
505         if (cctx->flags & SSL_CONF_FLAG_FILE &&
506             strncasecmp(*pcmd, cctx->prefix, cctx->prefixlen))
507             return 0;
508         *pcmd += cctx->prefixlen;
509     } else if (cctx->flags & SSL_CONF_FLAG_CMDLINE) {
510         if (**pcmd != '-' || !(*pcmd)[1])
511             return 0;
512         *pcmd += 1;
513     }
514     return 1;
515 }
516
517 /* Determine if a command is allowed according to cctx flags */
518 static int ssl_conf_cmd_allowed(SSL_CONF_CTX *cctx,
519                                 const ssl_conf_cmd_tbl * t)
520 {
521     unsigned int tfl = t->flags;
522     unsigned int cfl = cctx->flags;
523     if ((tfl & SSL_CONF_FLAG_SERVER) && !(cfl & SSL_CONF_FLAG_SERVER))
524         return 0;
525     if ((tfl & SSL_CONF_FLAG_CLIENT) && !(cfl & SSL_CONF_FLAG_CLIENT))
526         return 0;
527     if ((tfl & SSL_CONF_FLAG_CERTIFICATE)
528         && !(cfl & SSL_CONF_FLAG_CERTIFICATE))
529         return 0;
530     return 1;
531 }
532
533 static const ssl_conf_cmd_tbl *ssl_conf_cmd_lookup(SSL_CONF_CTX *cctx,
534                                                    const char *cmd)
535 {
536     const ssl_conf_cmd_tbl *t;
537     size_t i;
538     if (cmd == NULL)
539         return NULL;
540
541     /* Look for matching parameter name in table */
542     for (i = 0, t = ssl_conf_cmds; i < OSSL_NELEM(ssl_conf_cmds); i++, t++) {
543         if (ssl_conf_cmd_allowed(cctx, t)) {
544             if (cctx->flags & SSL_CONF_FLAG_CMDLINE) {
545                 if (t->str_cmdline && strcmp(t->str_cmdline, cmd) == 0)
546                     return t;
547             }
548             if (cctx->flags & SSL_CONF_FLAG_FILE) {
549                 if (t->str_file && strcasecmp(t->str_file, cmd) == 0)
550                     return t;
551             }
552         }
553     }
554     return NULL;
555 }
556
557 static int ctrl_switch_option(SSL_CONF_CTX *cctx,
558                               const ssl_conf_cmd_tbl * cmd)
559 {
560     /* Find index of command in table */
561     size_t idx = cmd - ssl_conf_cmds;
562     const ssl_switch_tbl *scmd;
563     /* Sanity check index */
564     if (idx >= OSSL_NELEM(ssl_cmd_switches))
565         return 0;
566     /* Obtain switches entry with same index */
567     scmd = ssl_cmd_switches + idx;
568     ssl_set_option(cctx, scmd->name_flags, scmd->option_value, 1);
569     return 1;
570 }
571
572 int SSL_CONF_cmd(SSL_CONF_CTX *cctx, const char *cmd, const char *value)
573 {
574     const ssl_conf_cmd_tbl *runcmd;
575     if (cmd == NULL) {
576         SSLerr(SSL_F_SSL_CONF_CMD, SSL_R_INVALID_NULL_CMD_NAME);
577         return 0;
578     }
579
580     if (!ssl_conf_cmd_skip_prefix(cctx, &cmd))
581         return -2;
582
583     runcmd = ssl_conf_cmd_lookup(cctx, cmd);
584
585     if (runcmd) {
586         int rv;
587         if (runcmd->value_type == SSL_CONF_TYPE_NONE) {
588             return ctrl_switch_option(cctx, runcmd);
589         }
590         if (value == NULL)
591             return -3;
592         rv = runcmd->cmd(cctx, value);
593         if (rv > 0)
594             return 2;
595         if (rv == -2)
596             return -2;
597         if (cctx->flags & SSL_CONF_FLAG_SHOW_ERRORS) {
598             SSLerr(SSL_F_SSL_CONF_CMD, SSL_R_BAD_VALUE);
599             ERR_add_error_data(4, "cmd=", cmd, ", value=", value);
600         }
601         return 0;
602     }
603
604     if (cctx->flags & SSL_CONF_FLAG_SHOW_ERRORS) {
605         SSLerr(SSL_F_SSL_CONF_CMD, SSL_R_UNKNOWN_CMD_NAME);
606         ERR_add_error_data(2, "cmd=", cmd);
607     }
608
609     return -2;
610 }
611
612 int SSL_CONF_cmd_argv(SSL_CONF_CTX *cctx, int *pargc, char ***pargv)
613 {
614     int rv;
615     const char *arg = NULL, *argn;
616     if (pargc && *pargc == 0)
617         return 0;
618     if (!pargc || *pargc > 0)
619         arg = **pargv;
620     if (arg == NULL)
621         return 0;
622     if (!pargc || *pargc > 1)
623         argn = (*pargv)[1];
624     else
625         argn = NULL;
626     cctx->flags &= ~SSL_CONF_FLAG_FILE;
627     cctx->flags |= SSL_CONF_FLAG_CMDLINE;
628     rv = SSL_CONF_cmd(cctx, arg, argn);
629     if (rv > 0) {
630         /* Success: update pargc, pargv */
631         (*pargv) += rv;
632         if (pargc)
633             (*pargc) -= rv;
634         return rv;
635     }
636     /* Unknown switch: indicate no arguments processed */
637     if (rv == -2)
638         return 0;
639     /* Some error occurred processing command, return fatal error */
640     if (rv == 0)
641         return -1;
642     return rv;
643 }
644
645 int SSL_CONF_cmd_value_type(SSL_CONF_CTX *cctx, const char *cmd)
646 {
647     if (ssl_conf_cmd_skip_prefix(cctx, &cmd)) {
648         const ssl_conf_cmd_tbl *runcmd;
649         runcmd = ssl_conf_cmd_lookup(cctx, cmd);
650         if (runcmd)
651             return runcmd->value_type;
652     }
653     return SSL_CONF_TYPE_UNKNOWN;
654 }
655
656 SSL_CONF_CTX *SSL_CONF_CTX_new(void)
657 {
658     SSL_CONF_CTX *ret = OPENSSL_malloc(sizeof(*ret));
659     size_t i;
660
661     if (ret) {
662         ret->flags = 0;
663         ret->prefix = NULL;
664         ret->prefixlen = 0;
665         ret->ssl = NULL;
666         ret->ctx = NULL;
667         ret->poptions = NULL;
668         ret->pcert_flags = NULL;
669         ret->tbl = NULL;
670         ret->ntbl = 0;
671         for (i = 0; i < SSL_PKEY_NUM; i++)
672             ret->cert_filename[i] = NULL;
673     }
674     return ret;
675 }
676
677 int SSL_CONF_CTX_finish(SSL_CONF_CTX *cctx)
678 {
679     /* See if any certificates are missing private keys */
680     size_t i;
681     CERT *c = NULL;
682     if (cctx->ctx)
683         c = cctx->ctx->cert;
684     else if (cctx->ssl)
685         c = cctx->ssl->cert;
686     if (c && cctx->flags & SSL_CONF_FLAG_REQUIRE_PRIVATE) {
687         for (i = 0; i < SSL_PKEY_NUM; i++) {
688             const char *p = cctx->cert_filename[i];
689             /*
690              * If missing private key try to load one from certificate file
691              */
692             if (p && !c->pkeys[i].privatekey) {
693                 if (!cmd_PrivateKey(cctx, p))
694                     return 0;
695             }
696         }
697     }
698     return 1;
699 }
700
701 void SSL_CONF_CTX_free(SSL_CONF_CTX *cctx)
702 {
703     if (cctx) {
704         size_t i;
705         for (i = 0; i < SSL_PKEY_NUM; i++)
706             OPENSSL_free(cctx->cert_filename[i]);
707         OPENSSL_free(cctx->prefix);
708         OPENSSL_free(cctx);
709     }
710 }
711
712 unsigned int SSL_CONF_CTX_set_flags(SSL_CONF_CTX *cctx, unsigned int flags)
713 {
714     cctx->flags |= flags;
715     return cctx->flags;
716 }
717
718 unsigned int SSL_CONF_CTX_clear_flags(SSL_CONF_CTX *cctx, unsigned int flags)
719 {
720     cctx->flags &= ~flags;
721     return cctx->flags;
722 }
723
724 int SSL_CONF_CTX_set1_prefix(SSL_CONF_CTX *cctx, const char *pre)
725 {
726     char *tmp = NULL;
727     if (pre) {
728         tmp = BUF_strdup(pre);
729         if (tmp == NULL)
730             return 0;
731     }
732     OPENSSL_free(cctx->prefix);
733     cctx->prefix = tmp;
734     if (tmp)
735         cctx->prefixlen = strlen(tmp);
736     else
737         cctx->prefixlen = 0;
738     return 1;
739 }
740
741 void SSL_CONF_CTX_set_ssl(SSL_CONF_CTX *cctx, SSL *ssl)
742 {
743     cctx->ssl = ssl;
744     cctx->ctx = NULL;
745     if (ssl) {
746         cctx->poptions = &ssl->options;
747         cctx->pcert_flags = &ssl->cert->cert_flags;
748     } else {
749         cctx->poptions = NULL;
750         cctx->pcert_flags = NULL;
751     }
752 }
753
754 void SSL_CONF_CTX_set_ssl_ctx(SSL_CONF_CTX *cctx, SSL_CTX *ctx)
755 {
756     cctx->ctx = ctx;
757     cctx->ssl = NULL;
758     if (ctx) {
759         cctx->poptions = &ctx->options;
760         cctx->pcert_flags = &ctx->cert->cert_flags;
761     } else {
762         cctx->poptions = NULL;
763         cctx->pcert_flags = NULL;
764     }
765 }