xref: /dflybsd-src/crypto/libressl/apps/openssl/apps.c (revision 961e30ea7dc61d1112b778ea4981eac68129fb86)
1*de0e0e4dSAntonio Huete Jimenez /* $OpenBSD: apps.c,v 1.62 2022/01/10 12:17:49 tb Exp $ */
2f5b1c8a1SJohn Marino /*
3f5b1c8a1SJohn Marino  * Copyright (c) 2014 Joel Sing <jsing@openbsd.org>
4f5b1c8a1SJohn Marino  *
5f5b1c8a1SJohn Marino  * Permission to use, copy, modify, and distribute this software for any
6f5b1c8a1SJohn Marino  * purpose with or without fee is hereby granted, provided that the above
7f5b1c8a1SJohn Marino  * copyright notice and this permission notice appear in all copies.
8f5b1c8a1SJohn Marino  *
9f5b1c8a1SJohn Marino  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10f5b1c8a1SJohn Marino  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11f5b1c8a1SJohn Marino  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12f5b1c8a1SJohn Marino  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13f5b1c8a1SJohn Marino  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14f5b1c8a1SJohn Marino  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15f5b1c8a1SJohn Marino  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16f5b1c8a1SJohn Marino  */
17f5b1c8a1SJohn Marino /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
18f5b1c8a1SJohn Marino  * All rights reserved.
19f5b1c8a1SJohn Marino  *
20f5b1c8a1SJohn Marino  * This package is an SSL implementation written
21f5b1c8a1SJohn Marino  * by Eric Young (eay@cryptsoft.com).
22f5b1c8a1SJohn Marino  * The implementation was written so as to conform with Netscapes SSL.
23f5b1c8a1SJohn Marino  *
24f5b1c8a1SJohn Marino  * This library is free for commercial and non-commercial use as long as
25f5b1c8a1SJohn Marino  * the following conditions are aheared to.  The following conditions
26f5b1c8a1SJohn Marino  * apply to all code found in this distribution, be it the RC4, RSA,
27f5b1c8a1SJohn Marino  * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
28f5b1c8a1SJohn Marino  * included with this distribution is covered by the same copyright terms
29f5b1c8a1SJohn Marino  * except that the holder is Tim Hudson (tjh@cryptsoft.com).
30f5b1c8a1SJohn Marino  *
31f5b1c8a1SJohn Marino  * Copyright remains Eric Young's, and as such any Copyright notices in
32f5b1c8a1SJohn Marino  * the code are not to be removed.
33f5b1c8a1SJohn Marino  * If this package is used in a product, Eric Young should be given attribution
34f5b1c8a1SJohn Marino  * as the author of the parts of the library used.
35f5b1c8a1SJohn Marino  * This can be in the form of a textual message at program startup or
36f5b1c8a1SJohn Marino  * in documentation (online or textual) provided with the package.
37f5b1c8a1SJohn Marino  *
38f5b1c8a1SJohn Marino  * Redistribution and use in source and binary forms, with or without
39f5b1c8a1SJohn Marino  * modification, are permitted provided that the following conditions
40f5b1c8a1SJohn Marino  * are met:
41f5b1c8a1SJohn Marino  * 1. Redistributions of source code must retain the copyright
42f5b1c8a1SJohn Marino  *    notice, this list of conditions and the following disclaimer.
43f5b1c8a1SJohn Marino  * 2. Redistributions in binary form must reproduce the above copyright
44f5b1c8a1SJohn Marino  *    notice, this list of conditions and the following disclaimer in the
45f5b1c8a1SJohn Marino  *    documentation and/or other materials provided with the distribution.
46f5b1c8a1SJohn Marino  * 3. All advertising materials mentioning features or use of this software
47f5b1c8a1SJohn Marino  *    must display the following acknowledgement:
48f5b1c8a1SJohn Marino  *    "This product includes cryptographic software written by
49f5b1c8a1SJohn Marino  *     Eric Young (eay@cryptsoft.com)"
50f5b1c8a1SJohn Marino  *    The word 'cryptographic' can be left out if the rouines from the library
51f5b1c8a1SJohn Marino  *    being used are not cryptographic related :-).
52f5b1c8a1SJohn Marino  * 4. If you include any Windows specific code (or a derivative thereof) from
53f5b1c8a1SJohn Marino  *    the apps directory (application code) you must include an acknowledgement:
54f5b1c8a1SJohn Marino  *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
55f5b1c8a1SJohn Marino  *
56f5b1c8a1SJohn Marino  * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
57f5b1c8a1SJohn Marino  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
58f5b1c8a1SJohn Marino  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
59f5b1c8a1SJohn Marino  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
60f5b1c8a1SJohn Marino  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
61f5b1c8a1SJohn Marino  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
62f5b1c8a1SJohn Marino  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
63f5b1c8a1SJohn Marino  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
64f5b1c8a1SJohn Marino  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
65f5b1c8a1SJohn Marino  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
66f5b1c8a1SJohn Marino  * SUCH DAMAGE.
67f5b1c8a1SJohn Marino  *
68f5b1c8a1SJohn Marino  * The licence and distribution terms for any publically available version or
69f5b1c8a1SJohn Marino  * derivative of this code cannot be changed.  i.e. this code cannot simply be
70f5b1c8a1SJohn Marino  * copied and put under another distribution licence
71f5b1c8a1SJohn Marino  * [including the GNU Public Licence.]
72f5b1c8a1SJohn Marino  */
73f5b1c8a1SJohn Marino /* ====================================================================
74f5b1c8a1SJohn Marino  * Copyright (c) 1998-2001 The OpenSSL Project.  All rights reserved.
75f5b1c8a1SJohn Marino  *
76f5b1c8a1SJohn Marino  * Redistribution and use in source and binary forms, with or without
77f5b1c8a1SJohn Marino  * modification, are permitted provided that the following conditions
78f5b1c8a1SJohn Marino  * are met:
79f5b1c8a1SJohn Marino  *
80f5b1c8a1SJohn Marino  * 1. Redistributions of source code must retain the above copyright
81f5b1c8a1SJohn Marino  *    notice, this list of conditions and the following disclaimer.
82f5b1c8a1SJohn Marino  *
83f5b1c8a1SJohn Marino  * 2. Redistributions in binary form must reproduce the above copyright
84f5b1c8a1SJohn Marino  *    notice, this list of conditions and the following disclaimer in
85f5b1c8a1SJohn Marino  *    the documentation and/or other materials provided with the
86f5b1c8a1SJohn Marino  *    distribution.
87f5b1c8a1SJohn Marino  *
88f5b1c8a1SJohn Marino  * 3. All advertising materials mentioning features or use of this
89f5b1c8a1SJohn Marino  *    software must display the following acknowledgment:
90f5b1c8a1SJohn Marino  *    "This product includes software developed by the OpenSSL Project
91f5b1c8a1SJohn Marino  *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
92f5b1c8a1SJohn Marino  *
93f5b1c8a1SJohn Marino  * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
94f5b1c8a1SJohn Marino  *    endorse or promote products derived from this software without
95f5b1c8a1SJohn Marino  *    prior written permission. For written permission, please contact
96f5b1c8a1SJohn Marino  *    openssl-core@openssl.org.
97f5b1c8a1SJohn Marino  *
98f5b1c8a1SJohn Marino  * 5. Products derived from this software may not be called "OpenSSL"
99f5b1c8a1SJohn Marino  *    nor may "OpenSSL" appear in their names without prior written
100f5b1c8a1SJohn Marino  *    permission of the OpenSSL Project.
101f5b1c8a1SJohn Marino  *
102f5b1c8a1SJohn Marino  * 6. Redistributions of any form whatsoever must retain the following
103f5b1c8a1SJohn Marino  *    acknowledgment:
104f5b1c8a1SJohn Marino  *    "This product includes software developed by the OpenSSL Project
105f5b1c8a1SJohn Marino  *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
106f5b1c8a1SJohn Marino  *
107f5b1c8a1SJohn Marino  * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
108f5b1c8a1SJohn Marino  * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
109f5b1c8a1SJohn Marino  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
110f5b1c8a1SJohn Marino  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
111f5b1c8a1SJohn Marino  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
112f5b1c8a1SJohn Marino  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
113f5b1c8a1SJohn Marino  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
114f5b1c8a1SJohn Marino  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
115f5b1c8a1SJohn Marino  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
116f5b1c8a1SJohn Marino  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
117f5b1c8a1SJohn Marino  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
118f5b1c8a1SJohn Marino  * OF THE POSSIBILITY OF SUCH DAMAGE.
119f5b1c8a1SJohn Marino  * ====================================================================
120f5b1c8a1SJohn Marino  *
121f5b1c8a1SJohn Marino  * This product includes cryptographic software written by Eric Young
122f5b1c8a1SJohn Marino  * (eay@cryptsoft.com).  This product includes software written by Tim
123f5b1c8a1SJohn Marino  * Hudson (tjh@cryptsoft.com).
124f5b1c8a1SJohn Marino  *
125f5b1c8a1SJohn Marino  */
126f5b1c8a1SJohn Marino 
127f5b1c8a1SJohn Marino #include <sys/types.h>
128f5b1c8a1SJohn Marino #include <sys/stat.h>
129f5b1c8a1SJohn Marino 
130f5b1c8a1SJohn Marino #include <ctype.h>
131f5b1c8a1SJohn Marino #include <errno.h>
132f5b1c8a1SJohn Marino #include <stdio.h>
133f5b1c8a1SJohn Marino #include <stdlib.h>
134f5b1c8a1SJohn Marino #include <limits.h>
135f5b1c8a1SJohn Marino #include <string.h>
136f5b1c8a1SJohn Marino #include <unistd.h>
137f5b1c8a1SJohn Marino 
138f5b1c8a1SJohn Marino #include "apps.h"
139f5b1c8a1SJohn Marino 
140f5b1c8a1SJohn Marino #include <openssl/bn.h>
141f5b1c8a1SJohn Marino #include <openssl/err.h>
142f5b1c8a1SJohn Marino #include <openssl/pem.h>
143f5b1c8a1SJohn Marino #include <openssl/pkcs12.h>
144*de0e0e4dSAntonio Huete Jimenez #include <openssl/rsa.h>
145f5b1c8a1SJohn Marino #include <openssl/safestack.h>
146*de0e0e4dSAntonio Huete Jimenez #include <openssl/ssl.h>
147f5b1c8a1SJohn Marino #include <openssl/x509.h>
148f5b1c8a1SJohn Marino #include <openssl/x509v3.h>
149f5b1c8a1SJohn Marino 
150f5b1c8a1SJohn Marino typedef struct {
151f5b1c8a1SJohn Marino 	const char *name;
152f5b1c8a1SJohn Marino 	unsigned long flag;
153f5b1c8a1SJohn Marino 	unsigned long mask;
154f5b1c8a1SJohn Marino } NAME_EX_TBL;
155f5b1c8a1SJohn Marino 
156f5b1c8a1SJohn Marino UI_METHOD *ui_method = NULL;
157f5b1c8a1SJohn Marino 
158f5b1c8a1SJohn Marino static int set_table_opts(unsigned long *flags, const char *arg,
159f5b1c8a1SJohn Marino     const NAME_EX_TBL *in_tbl);
160f5b1c8a1SJohn Marino static int set_multi_opts(unsigned long *flags, const char *arg,
161f5b1c8a1SJohn Marino     const NAME_EX_TBL *in_tbl);
162f5b1c8a1SJohn Marino 
163f5b1c8a1SJohn Marino int
str2fmt(char * s)164f5b1c8a1SJohn Marino str2fmt(char *s)
165f5b1c8a1SJohn Marino {
166f5b1c8a1SJohn Marino 	if (s == NULL)
167f5b1c8a1SJohn Marino 		return FORMAT_UNDEF;
168f5b1c8a1SJohn Marino 	if ((*s == 'D') || (*s == 'd'))
169f5b1c8a1SJohn Marino 		return (FORMAT_ASN1);
170f5b1c8a1SJohn Marino 	else if ((*s == 'T') || (*s == 't'))
171f5b1c8a1SJohn Marino 		return (FORMAT_TEXT);
172f5b1c8a1SJohn Marino 	else if ((*s == 'S') || (*s == 's'))
173f5b1c8a1SJohn Marino 		return (FORMAT_SMIME);
174f5b1c8a1SJohn Marino 	else if ((*s == 'M') || (*s == 'm'))
175f5b1c8a1SJohn Marino 		return (FORMAT_MSBLOB);
176f5b1c8a1SJohn Marino 	else if ((*s == '1') ||
177f5b1c8a1SJohn Marino 	    (strcmp(s, "PKCS12") == 0) || (strcmp(s, "pkcs12") == 0) ||
178f5b1c8a1SJohn Marino 	    (strcmp(s, "P12") == 0) || (strcmp(s, "p12") == 0))
179f5b1c8a1SJohn Marino 		return (FORMAT_PKCS12);
180f5b1c8a1SJohn Marino 	else if ((*s == 'P') || (*s == 'p')) {
181f5b1c8a1SJohn Marino 		if (s[1] == 'V' || s[1] == 'v')
182f5b1c8a1SJohn Marino 			return FORMAT_PVK;
183f5b1c8a1SJohn Marino 		else
184f5b1c8a1SJohn Marino 			return (FORMAT_PEM);
185f5b1c8a1SJohn Marino 	} else
186f5b1c8a1SJohn Marino 		return (FORMAT_UNDEF);
187f5b1c8a1SJohn Marino }
188f5b1c8a1SJohn Marino 
189f5b1c8a1SJohn Marino void
program_name(char * in,char * out,int size)190f5b1c8a1SJohn Marino program_name(char *in, char *out, int size)
191f5b1c8a1SJohn Marino {
192f5b1c8a1SJohn Marino 	char *p;
193f5b1c8a1SJohn Marino 
194f5b1c8a1SJohn Marino 	p = strrchr(in, '/');
195f5b1c8a1SJohn Marino 	if (p != NULL)
196f5b1c8a1SJohn Marino 		p++;
197f5b1c8a1SJohn Marino 	else
198f5b1c8a1SJohn Marino 		p = in;
199f5b1c8a1SJohn Marino 	strlcpy(out, p, size);
200f5b1c8a1SJohn Marino }
201f5b1c8a1SJohn Marino 
202f5b1c8a1SJohn Marino int
chopup_args(ARGS * arg,char * buf,int * argc,char ** argv[])203f5b1c8a1SJohn Marino chopup_args(ARGS *arg, char *buf, int *argc, char **argv[])
204f5b1c8a1SJohn Marino {
205f5b1c8a1SJohn Marino 	int num, i;
206f5b1c8a1SJohn Marino 	char *p;
207f5b1c8a1SJohn Marino 
208f5b1c8a1SJohn Marino 	*argc = 0;
209f5b1c8a1SJohn Marino 	*argv = NULL;
210f5b1c8a1SJohn Marino 
211f5b1c8a1SJohn Marino 	if (arg->count == 0) {
212f5b1c8a1SJohn Marino 		arg->count = 20;
213f5b1c8a1SJohn Marino 		arg->data = reallocarray(NULL, arg->count, sizeof(char *));
214f5b1c8a1SJohn Marino 		if (arg->data == NULL)
215f5b1c8a1SJohn Marino 			return 0;
216f5b1c8a1SJohn Marino 	}
217f5b1c8a1SJohn Marino 	for (i = 0; i < arg->count; i++)
218f5b1c8a1SJohn Marino 		arg->data[i] = NULL;
219f5b1c8a1SJohn Marino 
220f5b1c8a1SJohn Marino 	num = 0;
221f5b1c8a1SJohn Marino 	p = buf;
222f5b1c8a1SJohn Marino 	for (;;) {
223f5b1c8a1SJohn Marino 		/* first scan over white space */
224f5b1c8a1SJohn Marino 		if (!*p)
225f5b1c8a1SJohn Marino 			break;
226f5b1c8a1SJohn Marino 		while (*p && ((*p == ' ') || (*p == '\t') || (*p == '\n')))
227f5b1c8a1SJohn Marino 			p++;
228f5b1c8a1SJohn Marino 		if (!*p)
229f5b1c8a1SJohn Marino 			break;
230f5b1c8a1SJohn Marino 
231f5b1c8a1SJohn Marino 		/* The start of something good :-) */
232f5b1c8a1SJohn Marino 		if (num >= arg->count) {
233f5b1c8a1SJohn Marino 			char **tmp_p;
234f5b1c8a1SJohn Marino 			int tlen = arg->count + 20;
235f5b1c8a1SJohn Marino 			tmp_p = reallocarray(arg->data, tlen, sizeof(char *));
236f5b1c8a1SJohn Marino 			if (tmp_p == NULL)
237f5b1c8a1SJohn Marino 				return 0;
238f5b1c8a1SJohn Marino 			arg->data = tmp_p;
239f5b1c8a1SJohn Marino 			arg->count = tlen;
240f5b1c8a1SJohn Marino 			/* initialize newly allocated data */
241f5b1c8a1SJohn Marino 			for (i = num; i < arg->count; i++)
242f5b1c8a1SJohn Marino 				arg->data[i] = NULL;
243f5b1c8a1SJohn Marino 		}
244f5b1c8a1SJohn Marino 		arg->data[num++] = p;
245f5b1c8a1SJohn Marino 
246f5b1c8a1SJohn Marino 		/* now look for the end of this */
247f5b1c8a1SJohn Marino 		if ((*p == '\'') || (*p == '\"')) {	/* scan for closing
248f5b1c8a1SJohn Marino 							 * quote */
249f5b1c8a1SJohn Marino 			i = *(p++);
250f5b1c8a1SJohn Marino 			arg->data[num - 1]++;	/* jump over quote */
251f5b1c8a1SJohn Marino 			while (*p && (*p != i))
252f5b1c8a1SJohn Marino 				p++;
253f5b1c8a1SJohn Marino 			*p = '\0';
254f5b1c8a1SJohn Marino 		} else {
255f5b1c8a1SJohn Marino 			while (*p && ((*p != ' ') &&
256f5b1c8a1SJohn Marino 			    (*p != '\t') && (*p != '\n')))
257f5b1c8a1SJohn Marino 				p++;
258f5b1c8a1SJohn Marino 
259f5b1c8a1SJohn Marino 			if (*p == '\0')
260f5b1c8a1SJohn Marino 				p--;
261f5b1c8a1SJohn Marino 			else
262f5b1c8a1SJohn Marino 				*p = '\0';
263f5b1c8a1SJohn Marino 		}
264f5b1c8a1SJohn Marino 		p++;
265f5b1c8a1SJohn Marino 	}
266f5b1c8a1SJohn Marino 	*argc = num;
267f5b1c8a1SJohn Marino 	*argv = arg->data;
268f5b1c8a1SJohn Marino 	return (1);
269f5b1c8a1SJohn Marino }
270f5b1c8a1SJohn Marino 
271f5b1c8a1SJohn Marino int
dump_cert_text(BIO * out,X509 * x)272f5b1c8a1SJohn Marino dump_cert_text(BIO *out, X509 *x)
273f5b1c8a1SJohn Marino {
274f5b1c8a1SJohn Marino 	char *p;
275f5b1c8a1SJohn Marino 
276f5b1c8a1SJohn Marino 	p = X509_NAME_oneline(X509_get_subject_name(x), NULL, 0);
277f5b1c8a1SJohn Marino 	BIO_puts(out, "subject=");
278f5b1c8a1SJohn Marino 	BIO_puts(out, p);
279f5b1c8a1SJohn Marino 	free(p);
280f5b1c8a1SJohn Marino 
281f5b1c8a1SJohn Marino 	p = X509_NAME_oneline(X509_get_issuer_name(x), NULL, 0);
282f5b1c8a1SJohn Marino 	BIO_puts(out, "\nissuer=");
283f5b1c8a1SJohn Marino 	BIO_puts(out, p);
284f5b1c8a1SJohn Marino 	BIO_puts(out, "\n");
285f5b1c8a1SJohn Marino 	free(p);
286f5b1c8a1SJohn Marino 
287f5b1c8a1SJohn Marino 	return 0;
288f5b1c8a1SJohn Marino }
289f5b1c8a1SJohn Marino 
290f5b1c8a1SJohn Marino int
ui_open(UI * ui)291f5b1c8a1SJohn Marino ui_open(UI *ui)
292f5b1c8a1SJohn Marino {
293f5b1c8a1SJohn Marino 	return UI_method_get_opener(UI_OpenSSL()) (ui);
294f5b1c8a1SJohn Marino }
295f5b1c8a1SJohn Marino 
296f5b1c8a1SJohn Marino int
ui_read(UI * ui,UI_STRING * uis)297f5b1c8a1SJohn Marino ui_read(UI *ui, UI_STRING *uis)
298f5b1c8a1SJohn Marino {
299f5b1c8a1SJohn Marino 	const char *password;
300f5b1c8a1SJohn Marino 	int string_type;
301f5b1c8a1SJohn Marino 
302f5b1c8a1SJohn Marino 	if (UI_get_input_flags(uis) & UI_INPUT_FLAG_DEFAULT_PWD &&
303f5b1c8a1SJohn Marino 	    UI_get0_user_data(ui)) {
304f5b1c8a1SJohn Marino 		string_type = UI_get_string_type(uis);
305f5b1c8a1SJohn Marino 		if (string_type == UIT_PROMPT || string_type == UIT_VERIFY) {
306f5b1c8a1SJohn Marino 			password =
307f5b1c8a1SJohn Marino 			    ((PW_CB_DATA *)UI_get0_user_data(ui))->password;
308f5b1c8a1SJohn Marino 			if (password && password[0] != '\0') {
309f5b1c8a1SJohn Marino 				UI_set_result(ui, uis, password);
310f5b1c8a1SJohn Marino 				return 1;
311f5b1c8a1SJohn Marino 			}
312f5b1c8a1SJohn Marino 		}
313f5b1c8a1SJohn Marino 	}
314f5b1c8a1SJohn Marino 	return UI_method_get_reader(UI_OpenSSL()) (ui, uis);
315f5b1c8a1SJohn Marino }
316f5b1c8a1SJohn Marino 
317f5b1c8a1SJohn Marino int
ui_write(UI * ui,UI_STRING * uis)318f5b1c8a1SJohn Marino ui_write(UI *ui, UI_STRING *uis)
319f5b1c8a1SJohn Marino {
320f5b1c8a1SJohn Marino 	const char *password;
321f5b1c8a1SJohn Marino 	int string_type;
322f5b1c8a1SJohn Marino 
323f5b1c8a1SJohn Marino 	if (UI_get_input_flags(uis) & UI_INPUT_FLAG_DEFAULT_PWD &&
324f5b1c8a1SJohn Marino 	    UI_get0_user_data(ui)) {
325f5b1c8a1SJohn Marino 		string_type = UI_get_string_type(uis);
326f5b1c8a1SJohn Marino 		if (string_type == UIT_PROMPT || string_type == UIT_VERIFY) {
327f5b1c8a1SJohn Marino 			password =
328f5b1c8a1SJohn Marino 			    ((PW_CB_DATA *)UI_get0_user_data(ui))->password;
329f5b1c8a1SJohn Marino 			if (password && password[0] != '\0')
330f5b1c8a1SJohn Marino 				return 1;
331f5b1c8a1SJohn Marino 		}
332f5b1c8a1SJohn Marino 	}
333f5b1c8a1SJohn Marino 	return UI_method_get_writer(UI_OpenSSL()) (ui, uis);
334f5b1c8a1SJohn Marino }
335f5b1c8a1SJohn Marino 
336f5b1c8a1SJohn Marino int
ui_close(UI * ui)337f5b1c8a1SJohn Marino ui_close(UI *ui)
338f5b1c8a1SJohn Marino {
339f5b1c8a1SJohn Marino 	return UI_method_get_closer(UI_OpenSSL()) (ui);
340f5b1c8a1SJohn Marino }
341f5b1c8a1SJohn Marino 
342f5b1c8a1SJohn Marino int
password_callback(char * buf,int bufsiz,int verify,void * arg)343f5b1c8a1SJohn Marino password_callback(char *buf, int bufsiz, int verify, void *arg)
344f5b1c8a1SJohn Marino {
345f5b1c8a1SJohn Marino 	PW_CB_DATA *cb_tmp = arg;
346f5b1c8a1SJohn Marino 	UI *ui = NULL;
347f5b1c8a1SJohn Marino 	int res = 0;
348f5b1c8a1SJohn Marino 	const char *prompt_info = NULL;
349f5b1c8a1SJohn Marino 	const char *password = NULL;
350f5b1c8a1SJohn Marino 	PW_CB_DATA *cb_data = (PW_CB_DATA *) cb_tmp;
351f5b1c8a1SJohn Marino 
352f5b1c8a1SJohn Marino 	if (cb_data) {
353f5b1c8a1SJohn Marino 		if (cb_data->password)
354f5b1c8a1SJohn Marino 			password = cb_data->password;
355f5b1c8a1SJohn Marino 		if (cb_data->prompt_info)
356f5b1c8a1SJohn Marino 			prompt_info = cb_data->prompt_info;
357f5b1c8a1SJohn Marino 	}
358f5b1c8a1SJohn Marino 	if (password) {
359f5b1c8a1SJohn Marino 		res = strlen(password);
360f5b1c8a1SJohn Marino 		if (res > bufsiz)
361f5b1c8a1SJohn Marino 			res = bufsiz;
362f5b1c8a1SJohn Marino 		memcpy(buf, password, res);
363f5b1c8a1SJohn Marino 		return res;
364f5b1c8a1SJohn Marino 	}
365f5b1c8a1SJohn Marino 	ui = UI_new_method(ui_method);
366f5b1c8a1SJohn Marino 	if (ui) {
367f5b1c8a1SJohn Marino 		int ok = 0;
368f5b1c8a1SJohn Marino 		char *buff = NULL;
369f5b1c8a1SJohn Marino 		int ui_flags = 0;
370f5b1c8a1SJohn Marino 		char *prompt = NULL;
371f5b1c8a1SJohn Marino 
372f5b1c8a1SJohn Marino 		prompt = UI_construct_prompt(ui, "pass phrase", prompt_info);
373f5b1c8a1SJohn Marino 
374f5b1c8a1SJohn Marino 		ui_flags |= UI_INPUT_FLAG_DEFAULT_PWD;
375f5b1c8a1SJohn Marino 		UI_ctrl(ui, UI_CTRL_PRINT_ERRORS, 1, 0, 0);
376f5b1c8a1SJohn Marino 
377f5b1c8a1SJohn Marino 		if (ok >= 0)
378f5b1c8a1SJohn Marino 			ok = UI_add_input_string(ui, prompt, ui_flags, buf,
379f5b1c8a1SJohn Marino 			    PW_MIN_LENGTH, bufsiz - 1);
380f5b1c8a1SJohn Marino 		if (ok >= 0 && verify) {
381f5b1c8a1SJohn Marino 			buff = malloc(bufsiz);
382f5b1c8a1SJohn Marino 			ok = UI_add_verify_string(ui, prompt, ui_flags, buff,
383f5b1c8a1SJohn Marino 			    PW_MIN_LENGTH, bufsiz - 1, buf);
384f5b1c8a1SJohn Marino 		}
385f5b1c8a1SJohn Marino 		if (ok >= 0)
386f5b1c8a1SJohn Marino 			do {
387f5b1c8a1SJohn Marino 				ok = UI_process(ui);
388f5b1c8a1SJohn Marino 			} while (ok < 0 &&
389f5b1c8a1SJohn Marino 			    UI_ctrl(ui, UI_CTRL_IS_REDOABLE, 0, 0, 0));
390f5b1c8a1SJohn Marino 
39172c33676SMaxim Ag 		freezero(buff, (unsigned int) bufsiz);
392f5b1c8a1SJohn Marino 		if (ok >= 0)
393f5b1c8a1SJohn Marino 			res = strlen(buf);
394f5b1c8a1SJohn Marino 		if (ok == -1) {
395f5b1c8a1SJohn Marino 			BIO_printf(bio_err, "User interface error\n");
396f5b1c8a1SJohn Marino 			ERR_print_errors(bio_err);
397f5b1c8a1SJohn Marino 			explicit_bzero(buf, (unsigned int) bufsiz);
398f5b1c8a1SJohn Marino 			res = 0;
399f5b1c8a1SJohn Marino 		}
400f5b1c8a1SJohn Marino 		if (ok == -2) {
401f5b1c8a1SJohn Marino 			BIO_printf(bio_err, "aborted!\n");
402f5b1c8a1SJohn Marino 			explicit_bzero(buf, (unsigned int) bufsiz);
403f5b1c8a1SJohn Marino 			res = 0;
404f5b1c8a1SJohn Marino 		}
405f5b1c8a1SJohn Marino 		UI_free(ui);
406f5b1c8a1SJohn Marino 		free(prompt);
407f5b1c8a1SJohn Marino 	}
408f5b1c8a1SJohn Marino 	return res;
409f5b1c8a1SJohn Marino }
410f5b1c8a1SJohn Marino 
411f5b1c8a1SJohn Marino static char *app_get_pass(BIO *err, char *arg, int keepbio);
412f5b1c8a1SJohn Marino 
413f5b1c8a1SJohn Marino int
app_passwd(BIO * err,char * arg1,char * arg2,char ** pass1,char ** pass2)414f5b1c8a1SJohn Marino app_passwd(BIO *err, char *arg1, char *arg2, char **pass1, char **pass2)
415f5b1c8a1SJohn Marino {
416f5b1c8a1SJohn Marino 	int same;
417f5b1c8a1SJohn Marino 
418f5b1c8a1SJohn Marino 	if (!arg2 || !arg1 || strcmp(arg1, arg2))
419f5b1c8a1SJohn Marino 		same = 0;
420f5b1c8a1SJohn Marino 	else
421f5b1c8a1SJohn Marino 		same = 1;
422f5b1c8a1SJohn Marino 	if (arg1) {
423f5b1c8a1SJohn Marino 		*pass1 = app_get_pass(err, arg1, same);
424f5b1c8a1SJohn Marino 		if (!*pass1)
425f5b1c8a1SJohn Marino 			return 0;
426f5b1c8a1SJohn Marino 	} else if (pass1)
427f5b1c8a1SJohn Marino 		*pass1 = NULL;
428f5b1c8a1SJohn Marino 	if (arg2) {
429f5b1c8a1SJohn Marino 		*pass2 = app_get_pass(err, arg2, same ? 2 : 0);
430f5b1c8a1SJohn Marino 		if (!*pass2)
431f5b1c8a1SJohn Marino 			return 0;
432f5b1c8a1SJohn Marino 	} else if (pass2)
433f5b1c8a1SJohn Marino 		*pass2 = NULL;
434f5b1c8a1SJohn Marino 	return 1;
435f5b1c8a1SJohn Marino }
436f5b1c8a1SJohn Marino 
437f5b1c8a1SJohn Marino static char *
app_get_pass(BIO * err,char * arg,int keepbio)438f5b1c8a1SJohn Marino app_get_pass(BIO *err, char *arg, int keepbio)
439f5b1c8a1SJohn Marino {
440f5b1c8a1SJohn Marino 	char *tmp, tpass[APP_PASS_LEN];
441f5b1c8a1SJohn Marino 	static BIO *pwdbio = NULL;
442f5b1c8a1SJohn Marino 	const char *errstr = NULL;
443f5b1c8a1SJohn Marino 	int i;
444f5b1c8a1SJohn Marino 
445f5b1c8a1SJohn Marino 	if (!strncmp(arg, "pass:", 5))
446f5b1c8a1SJohn Marino 		return strdup(arg + 5);
447f5b1c8a1SJohn Marino 	if (!strncmp(arg, "env:", 4)) {
448f5b1c8a1SJohn Marino 		tmp = getenv(arg + 4);
449f5b1c8a1SJohn Marino 		if (!tmp) {
450f5b1c8a1SJohn Marino 			BIO_printf(err, "Can't read environment variable %s\n",
451f5b1c8a1SJohn Marino 			    arg + 4);
452f5b1c8a1SJohn Marino 			return NULL;
453f5b1c8a1SJohn Marino 		}
454f5b1c8a1SJohn Marino 		return strdup(tmp);
455f5b1c8a1SJohn Marino 	}
456f5b1c8a1SJohn Marino 	if (!keepbio || !pwdbio) {
457f5b1c8a1SJohn Marino 		if (!strncmp(arg, "file:", 5)) {
458f5b1c8a1SJohn Marino 			pwdbio = BIO_new_file(arg + 5, "r");
459f5b1c8a1SJohn Marino 			if (!pwdbio) {
460f5b1c8a1SJohn Marino 				BIO_printf(err, "Can't open file %s\n",
461f5b1c8a1SJohn Marino 				    arg + 5);
462f5b1c8a1SJohn Marino 				return NULL;
463f5b1c8a1SJohn Marino 			}
464f5b1c8a1SJohn Marino 		} else if (!strncmp(arg, "fd:", 3)) {
465f5b1c8a1SJohn Marino 			BIO *btmp;
466f5b1c8a1SJohn Marino 			i = strtonum(arg + 3, 0, INT_MAX, &errstr);
467f5b1c8a1SJohn Marino 			if (errstr) {
468f5b1c8a1SJohn Marino 				BIO_printf(err,
469f5b1c8a1SJohn Marino 				    "Invalid file descriptor %s: %s\n",
470f5b1c8a1SJohn Marino 				    arg, errstr);
471f5b1c8a1SJohn Marino 				return NULL;
472f5b1c8a1SJohn Marino 			}
473f5b1c8a1SJohn Marino 			pwdbio = BIO_new_fd(i, BIO_NOCLOSE);
474f5b1c8a1SJohn Marino 			if (!pwdbio) {
475f5b1c8a1SJohn Marino 				BIO_printf(err,
476f5b1c8a1SJohn Marino 				    "Can't access file descriptor %s\n",
477f5b1c8a1SJohn Marino 				    arg + 3);
478f5b1c8a1SJohn Marino 				return NULL;
479f5b1c8a1SJohn Marino 			}
480f5b1c8a1SJohn Marino 			/*
481f5b1c8a1SJohn Marino 			 * Can't do BIO_gets on an fd BIO so add a buffering
482f5b1c8a1SJohn Marino 			 * BIO
483f5b1c8a1SJohn Marino 			 */
484f5b1c8a1SJohn Marino 			btmp = BIO_new(BIO_f_buffer());
485f5b1c8a1SJohn Marino 			pwdbio = BIO_push(btmp, pwdbio);
486f5b1c8a1SJohn Marino 		} else if (!strcmp(arg, "stdin")) {
487f5b1c8a1SJohn Marino 			pwdbio = BIO_new_fp(stdin, BIO_NOCLOSE);
488f5b1c8a1SJohn Marino 			if (!pwdbio) {
489f5b1c8a1SJohn Marino 				BIO_printf(err, "Can't open BIO for stdin\n");
490f5b1c8a1SJohn Marino 				return NULL;
491f5b1c8a1SJohn Marino 			}
492f5b1c8a1SJohn Marino 		} else {
493f5b1c8a1SJohn Marino 			BIO_printf(err, "Invalid password argument \"%s\"\n",
494f5b1c8a1SJohn Marino 			    arg);
495f5b1c8a1SJohn Marino 			return NULL;
496f5b1c8a1SJohn Marino 		}
497f5b1c8a1SJohn Marino 	}
498f5b1c8a1SJohn Marino 	i = BIO_gets(pwdbio, tpass, APP_PASS_LEN);
499f5b1c8a1SJohn Marino 	if (keepbio != 1) {
500f5b1c8a1SJohn Marino 		BIO_free_all(pwdbio);
501f5b1c8a1SJohn Marino 		pwdbio = NULL;
502f5b1c8a1SJohn Marino 	}
503f5b1c8a1SJohn Marino 	if (i <= 0) {
504f5b1c8a1SJohn Marino 		BIO_printf(err, "Error reading password from BIO\n");
505f5b1c8a1SJohn Marino 		return NULL;
506f5b1c8a1SJohn Marino 	}
507f5b1c8a1SJohn Marino 	tmp = strchr(tpass, '\n');
508f5b1c8a1SJohn Marino 	if (tmp)
509f5b1c8a1SJohn Marino 		*tmp = 0;
510f5b1c8a1SJohn Marino 	return strdup(tpass);
511f5b1c8a1SJohn Marino }
512f5b1c8a1SJohn Marino 
513f5b1c8a1SJohn Marino int
add_oid_section(BIO * err,CONF * conf)514f5b1c8a1SJohn Marino add_oid_section(BIO *err, CONF *conf)
515f5b1c8a1SJohn Marino {
516f5b1c8a1SJohn Marino 	char *p;
517f5b1c8a1SJohn Marino 	STACK_OF(CONF_VALUE) *sktmp;
518f5b1c8a1SJohn Marino 	CONF_VALUE *cnf;
519f5b1c8a1SJohn Marino 	int i;
520f5b1c8a1SJohn Marino 
521f5b1c8a1SJohn Marino 	if (!(p = NCONF_get_string(conf, NULL, "oid_section"))) {
522f5b1c8a1SJohn Marino 		ERR_clear_error();
523f5b1c8a1SJohn Marino 		return 1;
524f5b1c8a1SJohn Marino 	}
525f5b1c8a1SJohn Marino 	if (!(sktmp = NCONF_get_section(conf, p))) {
526f5b1c8a1SJohn Marino 		BIO_printf(err, "problem loading oid section %s\n", p);
527f5b1c8a1SJohn Marino 		return 0;
528f5b1c8a1SJohn Marino 	}
529f5b1c8a1SJohn Marino 	for (i = 0; i < sk_CONF_VALUE_num(sktmp); i++) {
530f5b1c8a1SJohn Marino 		cnf = sk_CONF_VALUE_value(sktmp, i);
531f5b1c8a1SJohn Marino 		if (OBJ_create(cnf->value, cnf->name, cnf->name) == NID_undef) {
532f5b1c8a1SJohn Marino 			BIO_printf(err, "problem creating object %s=%s\n",
533f5b1c8a1SJohn Marino 			    cnf->name, cnf->value);
534f5b1c8a1SJohn Marino 			return 0;
535f5b1c8a1SJohn Marino 		}
536f5b1c8a1SJohn Marino 	}
537f5b1c8a1SJohn Marino 	return 1;
538f5b1c8a1SJohn Marino }
539f5b1c8a1SJohn Marino 
540f5b1c8a1SJohn Marino static int
load_pkcs12(BIO * err,BIO * in,const char * desc,pem_password_cb * pem_cb,void * cb_data,EVP_PKEY ** pkey,X509 ** cert,STACK_OF (X509)** ca)541f5b1c8a1SJohn Marino load_pkcs12(BIO *err, BIO *in, const char *desc, pem_password_cb *pem_cb,
542f5b1c8a1SJohn Marino     void *cb_data, EVP_PKEY **pkey, X509 **cert, STACK_OF(X509) **ca)
543f5b1c8a1SJohn Marino {
544f5b1c8a1SJohn Marino 	const char *pass;
545f5b1c8a1SJohn Marino 	char tpass[PEM_BUFSIZE];
546f5b1c8a1SJohn Marino 	int len, ret = 0;
547f5b1c8a1SJohn Marino 	PKCS12 *p12;
548f5b1c8a1SJohn Marino 
549f5b1c8a1SJohn Marino 	p12 = d2i_PKCS12_bio(in, NULL);
550f5b1c8a1SJohn Marino 	if (p12 == NULL) {
551f5b1c8a1SJohn Marino 		BIO_printf(err, "Error loading PKCS12 file for %s\n", desc);
552f5b1c8a1SJohn Marino 		goto die;
553f5b1c8a1SJohn Marino 	}
554f5b1c8a1SJohn Marino 	/* See if an empty password will do */
555f5b1c8a1SJohn Marino 	if (PKCS12_verify_mac(p12, "", 0) || PKCS12_verify_mac(p12, NULL, 0))
556f5b1c8a1SJohn Marino 		pass = "";
557f5b1c8a1SJohn Marino 	else {
558f5b1c8a1SJohn Marino 		if (!pem_cb)
559f5b1c8a1SJohn Marino 			pem_cb = password_callback;
560f5b1c8a1SJohn Marino 		len = pem_cb(tpass, PEM_BUFSIZE, 0, cb_data);
561f5b1c8a1SJohn Marino 		if (len < 0) {
562f5b1c8a1SJohn Marino 			BIO_printf(err, "Passpharse callback error for %s\n",
563f5b1c8a1SJohn Marino 			    desc);
564f5b1c8a1SJohn Marino 			goto die;
565f5b1c8a1SJohn Marino 		}
566f5b1c8a1SJohn Marino 		if (len < PEM_BUFSIZE)
567f5b1c8a1SJohn Marino 			tpass[len] = 0;
568f5b1c8a1SJohn Marino 		if (!PKCS12_verify_mac(p12, tpass, len)) {
569f5b1c8a1SJohn Marino 			BIO_printf(err,
570f5b1c8a1SJohn Marino 			    "Mac verify error (wrong password?) in PKCS12 file for %s\n", desc);
571f5b1c8a1SJohn Marino 			goto die;
572f5b1c8a1SJohn Marino 		}
573f5b1c8a1SJohn Marino 		pass = tpass;
574f5b1c8a1SJohn Marino 	}
575f5b1c8a1SJohn Marino 	ret = PKCS12_parse(p12, pass, pkey, cert, ca);
576f5b1c8a1SJohn Marino 
577f5b1c8a1SJohn Marino  die:
578f5b1c8a1SJohn Marino 	PKCS12_free(p12);
579f5b1c8a1SJohn Marino 	return ret;
580f5b1c8a1SJohn Marino }
581f5b1c8a1SJohn Marino 
582f5b1c8a1SJohn Marino X509 *
load_cert(BIO * err,const char * file,int format,const char * pass,const char * cert_descrip)583f5b1c8a1SJohn Marino load_cert(BIO *err, const char *file, int format, const char *pass,
584f5b1c8a1SJohn Marino     const char *cert_descrip)
585f5b1c8a1SJohn Marino {
586f5b1c8a1SJohn Marino 	X509 *x = NULL;
587f5b1c8a1SJohn Marino 	BIO *cert;
588f5b1c8a1SJohn Marino 
589f5b1c8a1SJohn Marino 	if ((cert = BIO_new(BIO_s_file())) == NULL) {
590f5b1c8a1SJohn Marino 		ERR_print_errors(err);
591f5b1c8a1SJohn Marino 		goto end;
592f5b1c8a1SJohn Marino 	}
593f5b1c8a1SJohn Marino 	if (file == NULL) {
594f5b1c8a1SJohn Marino 		setvbuf(stdin, NULL, _IONBF, 0);
595f5b1c8a1SJohn Marino 		BIO_set_fp(cert, stdin, BIO_NOCLOSE);
596f5b1c8a1SJohn Marino 	} else {
597f5b1c8a1SJohn Marino 		if (BIO_read_filename(cert, file) <= 0) {
598f5b1c8a1SJohn Marino 			BIO_printf(err, "Error opening %s %s\n",
599f5b1c8a1SJohn Marino 			    cert_descrip, file);
600f5b1c8a1SJohn Marino 			ERR_print_errors(err);
601f5b1c8a1SJohn Marino 			goto end;
602f5b1c8a1SJohn Marino 		}
603f5b1c8a1SJohn Marino 	}
604f5b1c8a1SJohn Marino 
605f5b1c8a1SJohn Marino 	if (format == FORMAT_ASN1)
606f5b1c8a1SJohn Marino 		x = d2i_X509_bio(cert, NULL);
607*de0e0e4dSAntonio Huete Jimenez 	else if (format == FORMAT_PEM)
608f5b1c8a1SJohn Marino 		x = PEM_read_bio_X509_AUX(cert, NULL, password_callback, NULL);
609f5b1c8a1SJohn Marino 	else if (format == FORMAT_PKCS12) {
610f5b1c8a1SJohn Marino 		if (!load_pkcs12(err, cert, cert_descrip, NULL, NULL,
611f5b1c8a1SJohn Marino 		    NULL, &x, NULL))
612f5b1c8a1SJohn Marino 			goto end;
613f5b1c8a1SJohn Marino 	} else {
614f5b1c8a1SJohn Marino 		BIO_printf(err, "bad input format specified for %s\n",
615f5b1c8a1SJohn Marino 		    cert_descrip);
616f5b1c8a1SJohn Marino 		goto end;
617f5b1c8a1SJohn Marino 	}
618f5b1c8a1SJohn Marino 
619f5b1c8a1SJohn Marino  end:
620f5b1c8a1SJohn Marino 	if (x == NULL) {
621f5b1c8a1SJohn Marino 		BIO_printf(err, "unable to load certificate\n");
622f5b1c8a1SJohn Marino 		ERR_print_errors(err);
623f5b1c8a1SJohn Marino 	}
624f5b1c8a1SJohn Marino 	BIO_free(cert);
625f5b1c8a1SJohn Marino 	return (x);
626f5b1c8a1SJohn Marino }
627f5b1c8a1SJohn Marino 
628f5b1c8a1SJohn Marino EVP_PKEY *
load_key(BIO * err,const char * file,int format,int maybe_stdin,const char * pass,const char * key_descrip)629f5b1c8a1SJohn Marino load_key(BIO *err, const char *file, int format, int maybe_stdin,
630f5b1c8a1SJohn Marino     const char *pass, const char *key_descrip)
631f5b1c8a1SJohn Marino {
632f5b1c8a1SJohn Marino 	BIO *key = NULL;
633f5b1c8a1SJohn Marino 	EVP_PKEY *pkey = NULL;
634f5b1c8a1SJohn Marino 	PW_CB_DATA cb_data;
635f5b1c8a1SJohn Marino 
636f5b1c8a1SJohn Marino 	cb_data.password = pass;
637f5b1c8a1SJohn Marino 	cb_data.prompt_info = file;
638f5b1c8a1SJohn Marino 
639f5b1c8a1SJohn Marino 	if (file == NULL && (!maybe_stdin)) {
640f5b1c8a1SJohn Marino 		BIO_printf(err, "no keyfile specified\n");
641f5b1c8a1SJohn Marino 		goto end;
642f5b1c8a1SJohn Marino 	}
643f5b1c8a1SJohn Marino 	key = BIO_new(BIO_s_file());
644f5b1c8a1SJohn Marino 	if (key == NULL) {
645f5b1c8a1SJohn Marino 		ERR_print_errors(err);
646f5b1c8a1SJohn Marino 		goto end;
647f5b1c8a1SJohn Marino 	}
648f5b1c8a1SJohn Marino 	if (file == NULL && maybe_stdin) {
649f5b1c8a1SJohn Marino 		setvbuf(stdin, NULL, _IONBF, 0);
650f5b1c8a1SJohn Marino 		BIO_set_fp(key, stdin, BIO_NOCLOSE);
651f5b1c8a1SJohn Marino 	} else if (BIO_read_filename(key, file) <= 0) {
652f5b1c8a1SJohn Marino 		BIO_printf(err, "Error opening %s %s\n",
653f5b1c8a1SJohn Marino 		    key_descrip, file);
654f5b1c8a1SJohn Marino 		ERR_print_errors(err);
655f5b1c8a1SJohn Marino 		goto end;
656f5b1c8a1SJohn Marino 	}
657f5b1c8a1SJohn Marino 	if (format == FORMAT_ASN1) {
658f5b1c8a1SJohn Marino 		pkey = d2i_PrivateKey_bio(key, NULL);
659f5b1c8a1SJohn Marino 	} else if (format == FORMAT_PEM) {
660f5b1c8a1SJohn Marino 		pkey = PEM_read_bio_PrivateKey(key, NULL, password_callback, &cb_data);
661f5b1c8a1SJohn Marino 	}
662f5b1c8a1SJohn Marino 	else if (format == FORMAT_PKCS12) {
663f5b1c8a1SJohn Marino 		if (!load_pkcs12(err, key, key_descrip, password_callback, &cb_data,
664f5b1c8a1SJohn Marino 		    &pkey, NULL, NULL))
665f5b1c8a1SJohn Marino 			goto end;
666f5b1c8a1SJohn Marino 	}
667f5b1c8a1SJohn Marino #if !defined(OPENSSL_NO_RSA) && !defined(OPENSSL_NO_DSA) && !defined (OPENSSL_NO_RC4)
668f5b1c8a1SJohn Marino 	else if (format == FORMAT_MSBLOB)
669f5b1c8a1SJohn Marino 		pkey = b2i_PrivateKey_bio(key);
670f5b1c8a1SJohn Marino 	else if (format == FORMAT_PVK)
671f5b1c8a1SJohn Marino 		pkey = b2i_PVK_bio(key, password_callback,
672f5b1c8a1SJohn Marino 		    &cb_data);
673f5b1c8a1SJohn Marino #endif
674f5b1c8a1SJohn Marino 	else {
675f5b1c8a1SJohn Marino 		BIO_printf(err, "bad input format specified for key file\n");
676f5b1c8a1SJohn Marino 		goto end;
677f5b1c8a1SJohn Marino 	}
678f5b1c8a1SJohn Marino  end:
679f5b1c8a1SJohn Marino 	BIO_free(key);
680f5b1c8a1SJohn Marino 	if (pkey == NULL) {
681f5b1c8a1SJohn Marino 		BIO_printf(err, "unable to load %s\n", key_descrip);
682f5b1c8a1SJohn Marino 		ERR_print_errors(err);
683f5b1c8a1SJohn Marino 	}
684f5b1c8a1SJohn Marino 	return (pkey);
685f5b1c8a1SJohn Marino }
686f5b1c8a1SJohn Marino 
687f5b1c8a1SJohn Marino EVP_PKEY *
load_pubkey(BIO * err,const char * file,int format,int maybe_stdin,const char * pass,const char * key_descrip)688f5b1c8a1SJohn Marino load_pubkey(BIO *err, const char *file, int format, int maybe_stdin,
689f5b1c8a1SJohn Marino     const char *pass, const char *key_descrip)
690f5b1c8a1SJohn Marino {
691f5b1c8a1SJohn Marino 	BIO *key = NULL;
692f5b1c8a1SJohn Marino 	EVP_PKEY *pkey = NULL;
693f5b1c8a1SJohn Marino 	PW_CB_DATA cb_data;
694f5b1c8a1SJohn Marino 
695f5b1c8a1SJohn Marino 	cb_data.password = pass;
696f5b1c8a1SJohn Marino 	cb_data.prompt_info = file;
697f5b1c8a1SJohn Marino 
698f5b1c8a1SJohn Marino 	if (file == NULL && !maybe_stdin) {
699f5b1c8a1SJohn Marino 		BIO_printf(err, "no keyfile specified\n");
700f5b1c8a1SJohn Marino 		goto end;
701f5b1c8a1SJohn Marino 	}
702f5b1c8a1SJohn Marino 	key = BIO_new(BIO_s_file());
703f5b1c8a1SJohn Marino 	if (key == NULL) {
704f5b1c8a1SJohn Marino 		ERR_print_errors(err);
705f5b1c8a1SJohn Marino 		goto end;
706f5b1c8a1SJohn Marino 	}
707f5b1c8a1SJohn Marino 	if (file == NULL && maybe_stdin) {
708f5b1c8a1SJohn Marino 		setvbuf(stdin, NULL, _IONBF, 0);
709f5b1c8a1SJohn Marino 		BIO_set_fp(key, stdin, BIO_NOCLOSE);
710f5b1c8a1SJohn Marino 	} else if (BIO_read_filename(key, file) <= 0) {
711f5b1c8a1SJohn Marino 		BIO_printf(err, "Error opening %s %s\n", key_descrip, file);
712f5b1c8a1SJohn Marino 		ERR_print_errors(err);
713f5b1c8a1SJohn Marino 		goto end;
714f5b1c8a1SJohn Marino 	}
715f5b1c8a1SJohn Marino 	if (format == FORMAT_ASN1) {
716f5b1c8a1SJohn Marino 		pkey = d2i_PUBKEY_bio(key, NULL);
717f5b1c8a1SJohn Marino 	}
718f5b1c8a1SJohn Marino 	else if (format == FORMAT_ASN1RSA) {
719f5b1c8a1SJohn Marino 		RSA *rsa;
720f5b1c8a1SJohn Marino 		rsa = d2i_RSAPublicKey_bio(key, NULL);
721f5b1c8a1SJohn Marino 		if (rsa) {
722f5b1c8a1SJohn Marino 			pkey = EVP_PKEY_new();
723f5b1c8a1SJohn Marino 			if (pkey)
724f5b1c8a1SJohn Marino 				EVP_PKEY_set1_RSA(pkey, rsa);
725f5b1c8a1SJohn Marino 			RSA_free(rsa);
726f5b1c8a1SJohn Marino 		} else
727f5b1c8a1SJohn Marino 			pkey = NULL;
728f5b1c8a1SJohn Marino 	} else if (format == FORMAT_PEMRSA) {
729f5b1c8a1SJohn Marino 		RSA *rsa;
730f5b1c8a1SJohn Marino 		rsa = PEM_read_bio_RSAPublicKey(key, NULL, password_callback, &cb_data);
731f5b1c8a1SJohn Marino 		if (rsa) {
732f5b1c8a1SJohn Marino 			pkey = EVP_PKEY_new();
733f5b1c8a1SJohn Marino 			if (pkey)
734f5b1c8a1SJohn Marino 				EVP_PKEY_set1_RSA(pkey, rsa);
735f5b1c8a1SJohn Marino 			RSA_free(rsa);
736f5b1c8a1SJohn Marino 		} else
737f5b1c8a1SJohn Marino 			pkey = NULL;
738f5b1c8a1SJohn Marino 	}
739f5b1c8a1SJohn Marino 	else if (format == FORMAT_PEM) {
740f5b1c8a1SJohn Marino 		pkey = PEM_read_bio_PUBKEY(key, NULL, password_callback, &cb_data);
741f5b1c8a1SJohn Marino 	}
742f5b1c8a1SJohn Marino #if !defined(OPENSSL_NO_RSA) && !defined(OPENSSL_NO_DSA)
743f5b1c8a1SJohn Marino 	else if (format == FORMAT_MSBLOB)
744f5b1c8a1SJohn Marino 		pkey = b2i_PublicKey_bio(key);
745f5b1c8a1SJohn Marino #endif
746f5b1c8a1SJohn Marino 	else {
747f5b1c8a1SJohn Marino 		BIO_printf(err, "bad input format specified for key file\n");
748f5b1c8a1SJohn Marino 		goto end;
749f5b1c8a1SJohn Marino 	}
750f5b1c8a1SJohn Marino 
751f5b1c8a1SJohn Marino  end:
752f5b1c8a1SJohn Marino 	BIO_free(key);
753f5b1c8a1SJohn Marino 	if (pkey == NULL)
754f5b1c8a1SJohn Marino 		BIO_printf(err, "unable to load %s\n", key_descrip);
755f5b1c8a1SJohn Marino 	return (pkey);
756f5b1c8a1SJohn Marino }
757f5b1c8a1SJohn Marino 
758f5b1c8a1SJohn Marino static int
load_certs_crls(BIO * err,const char * file,int format,const char * pass,const char * desc,STACK_OF (X509)** pcerts,STACK_OF (X509_CRL)** pcrls)759f5b1c8a1SJohn Marino load_certs_crls(BIO *err, const char *file, int format, const char *pass,
760f5b1c8a1SJohn Marino     const char *desc, STACK_OF(X509) **pcerts,
761f5b1c8a1SJohn Marino     STACK_OF(X509_CRL) **pcrls)
762f5b1c8a1SJohn Marino {
763f5b1c8a1SJohn Marino 	int i;
764f5b1c8a1SJohn Marino 	BIO *bio;
765f5b1c8a1SJohn Marino 	STACK_OF(X509_INFO) *xis = NULL;
766f5b1c8a1SJohn Marino 	X509_INFO *xi;
767f5b1c8a1SJohn Marino 	PW_CB_DATA cb_data;
768f5b1c8a1SJohn Marino 	int rv = 0;
769f5b1c8a1SJohn Marino 
770f5b1c8a1SJohn Marino 	cb_data.password = pass;
771f5b1c8a1SJohn Marino 	cb_data.prompt_info = file;
772f5b1c8a1SJohn Marino 
773f5b1c8a1SJohn Marino 	if (format != FORMAT_PEM) {
774f5b1c8a1SJohn Marino 		BIO_printf(err, "bad input format specified for %s\n", desc);
775f5b1c8a1SJohn Marino 		return 0;
776f5b1c8a1SJohn Marino 	}
777f5b1c8a1SJohn Marino 	if (file == NULL)
778f5b1c8a1SJohn Marino 		bio = BIO_new_fp(stdin, BIO_NOCLOSE);
779f5b1c8a1SJohn Marino 	else
780f5b1c8a1SJohn Marino 		bio = BIO_new_file(file, "r");
781f5b1c8a1SJohn Marino 
782f5b1c8a1SJohn Marino 	if (bio == NULL) {
783f5b1c8a1SJohn Marino 		BIO_printf(err, "Error opening %s %s\n",
784f5b1c8a1SJohn Marino 		    desc, file ? file : "stdin");
785f5b1c8a1SJohn Marino 		ERR_print_errors(err);
786f5b1c8a1SJohn Marino 		return 0;
787f5b1c8a1SJohn Marino 	}
788f5b1c8a1SJohn Marino 	xis = PEM_X509_INFO_read_bio(bio, NULL, password_callback, &cb_data);
789f5b1c8a1SJohn Marino 
790f5b1c8a1SJohn Marino 	BIO_free(bio);
791f5b1c8a1SJohn Marino 
792f5b1c8a1SJohn Marino 	if (pcerts) {
793f5b1c8a1SJohn Marino 		*pcerts = sk_X509_new_null();
794f5b1c8a1SJohn Marino 		if (!*pcerts)
795f5b1c8a1SJohn Marino 			goto end;
796f5b1c8a1SJohn Marino 	}
797f5b1c8a1SJohn Marino 	if (pcrls) {
798f5b1c8a1SJohn Marino 		*pcrls = sk_X509_CRL_new_null();
799f5b1c8a1SJohn Marino 		if (!*pcrls)
800f5b1c8a1SJohn Marino 			goto end;
801f5b1c8a1SJohn Marino 	}
802f5b1c8a1SJohn Marino 	for (i = 0; i < sk_X509_INFO_num(xis); i++) {
803f5b1c8a1SJohn Marino 		xi = sk_X509_INFO_value(xis, i);
804f5b1c8a1SJohn Marino 		if (xi->x509 && pcerts) {
805f5b1c8a1SJohn Marino 			if (!sk_X509_push(*pcerts, xi->x509))
806f5b1c8a1SJohn Marino 				goto end;
807f5b1c8a1SJohn Marino 			xi->x509 = NULL;
808f5b1c8a1SJohn Marino 		}
809f5b1c8a1SJohn Marino 		if (xi->crl && pcrls) {
810f5b1c8a1SJohn Marino 			if (!sk_X509_CRL_push(*pcrls, xi->crl))
811f5b1c8a1SJohn Marino 				goto end;
812f5b1c8a1SJohn Marino 			xi->crl = NULL;
813f5b1c8a1SJohn Marino 		}
814f5b1c8a1SJohn Marino 	}
815f5b1c8a1SJohn Marino 
816f5b1c8a1SJohn Marino 	if (pcerts && sk_X509_num(*pcerts) > 0)
817f5b1c8a1SJohn Marino 		rv = 1;
818f5b1c8a1SJohn Marino 
819f5b1c8a1SJohn Marino 	if (pcrls && sk_X509_CRL_num(*pcrls) > 0)
820f5b1c8a1SJohn Marino 		rv = 1;
821f5b1c8a1SJohn Marino 
822f5b1c8a1SJohn Marino  end:
823f5b1c8a1SJohn Marino 	sk_X509_INFO_pop_free(xis, X509_INFO_free);
824f5b1c8a1SJohn Marino 
825f5b1c8a1SJohn Marino 	if (rv == 0) {
826f5b1c8a1SJohn Marino 		if (pcerts) {
827f5b1c8a1SJohn Marino 			sk_X509_pop_free(*pcerts, X509_free);
828f5b1c8a1SJohn Marino 			*pcerts = NULL;
829f5b1c8a1SJohn Marino 		}
830f5b1c8a1SJohn Marino 		if (pcrls) {
831f5b1c8a1SJohn Marino 			sk_X509_CRL_pop_free(*pcrls, X509_CRL_free);
832f5b1c8a1SJohn Marino 			*pcrls = NULL;
833f5b1c8a1SJohn Marino 		}
834f5b1c8a1SJohn Marino 		BIO_printf(err, "unable to load %s\n",
835f5b1c8a1SJohn Marino 		    pcerts ? "certificates" : "CRLs");
836f5b1c8a1SJohn Marino 		ERR_print_errors(err);
837f5b1c8a1SJohn Marino 	}
838f5b1c8a1SJohn Marino 	return rv;
839f5b1c8a1SJohn Marino }
840f5b1c8a1SJohn Marino 
STACK_OF(X509)841f5b1c8a1SJohn Marino STACK_OF(X509) *
842f5b1c8a1SJohn Marino load_certs(BIO *err, const char *file, int format, const char *pass,
843f5b1c8a1SJohn Marino     const char *desc)
844f5b1c8a1SJohn Marino {
845f5b1c8a1SJohn Marino 	STACK_OF(X509) *certs;
846f5b1c8a1SJohn Marino 
847f5b1c8a1SJohn Marino 	if (!load_certs_crls(err, file, format, pass, desc, &certs, NULL))
848f5b1c8a1SJohn Marino 		return NULL;
849f5b1c8a1SJohn Marino 	return certs;
850f5b1c8a1SJohn Marino }
851f5b1c8a1SJohn Marino 
STACK_OF(X509_CRL)852f5b1c8a1SJohn Marino STACK_OF(X509_CRL) *
853f5b1c8a1SJohn Marino load_crls(BIO *err, const char *file, int format, const char *pass,
854f5b1c8a1SJohn Marino     const char *desc)
855f5b1c8a1SJohn Marino {
856f5b1c8a1SJohn Marino 	STACK_OF(X509_CRL) *crls;
857f5b1c8a1SJohn Marino 
858f5b1c8a1SJohn Marino 	if (!load_certs_crls(err, file, format, pass, desc, NULL, &crls))
859f5b1c8a1SJohn Marino 		return NULL;
860f5b1c8a1SJohn Marino 	return crls;
861f5b1c8a1SJohn Marino }
862f5b1c8a1SJohn Marino 
863f5b1c8a1SJohn Marino #define X509V3_EXT_UNKNOWN_MASK		(0xfL << 16)
864f5b1c8a1SJohn Marino /* Return error for unknown extensions */
865f5b1c8a1SJohn Marino #define X509V3_EXT_DEFAULT		0
866f5b1c8a1SJohn Marino /* Print error for unknown extensions */
867f5b1c8a1SJohn Marino #define X509V3_EXT_ERROR_UNKNOWN	(1L << 16)
868f5b1c8a1SJohn Marino /* ASN1 parse unknown extensions */
869f5b1c8a1SJohn Marino #define X509V3_EXT_PARSE_UNKNOWN	(2L << 16)
870f5b1c8a1SJohn Marino /* BIO_dump unknown extensions */
871f5b1c8a1SJohn Marino #define X509V3_EXT_DUMP_UNKNOWN		(3L << 16)
872f5b1c8a1SJohn Marino 
873f5b1c8a1SJohn Marino #define X509_FLAG_CA (X509_FLAG_NO_ISSUER | X509_FLAG_NO_PUBKEY | \
874f5b1c8a1SJohn Marino 			 X509_FLAG_NO_HEADER | X509_FLAG_NO_VERSION)
875f5b1c8a1SJohn Marino 
876f5b1c8a1SJohn Marino int
set_cert_ex(unsigned long * flags,const char * arg)877f5b1c8a1SJohn Marino set_cert_ex(unsigned long *flags, const char *arg)
878f5b1c8a1SJohn Marino {
879f5b1c8a1SJohn Marino 	static const NAME_EX_TBL cert_tbl[] = {
880f5b1c8a1SJohn Marino 		{"compatible", X509_FLAG_COMPAT, 0xffffffffl},
881f5b1c8a1SJohn Marino 		{"ca_default", X509_FLAG_CA, 0xffffffffl},
882f5b1c8a1SJohn Marino 		{"no_header", X509_FLAG_NO_HEADER, 0},
883f5b1c8a1SJohn Marino 		{"no_version", X509_FLAG_NO_VERSION, 0},
884f5b1c8a1SJohn Marino 		{"no_serial", X509_FLAG_NO_SERIAL, 0},
885f5b1c8a1SJohn Marino 		{"no_signame", X509_FLAG_NO_SIGNAME, 0},
886f5b1c8a1SJohn Marino 		{"no_validity", X509_FLAG_NO_VALIDITY, 0},
887f5b1c8a1SJohn Marino 		{"no_subject", X509_FLAG_NO_SUBJECT, 0},
888f5b1c8a1SJohn Marino 		{"no_issuer", X509_FLAG_NO_ISSUER, 0},
889f5b1c8a1SJohn Marino 		{"no_pubkey", X509_FLAG_NO_PUBKEY, 0},
890f5b1c8a1SJohn Marino 		{"no_extensions", X509_FLAG_NO_EXTENSIONS, 0},
891f5b1c8a1SJohn Marino 		{"no_sigdump", X509_FLAG_NO_SIGDUMP, 0},
892f5b1c8a1SJohn Marino 		{"no_aux", X509_FLAG_NO_AUX, 0},
893f5b1c8a1SJohn Marino 		{"no_attributes", X509_FLAG_NO_ATTRIBUTES, 0},
894f5b1c8a1SJohn Marino 		{"ext_default", X509V3_EXT_DEFAULT, X509V3_EXT_UNKNOWN_MASK},
895f5b1c8a1SJohn Marino 		{"ext_error", X509V3_EXT_ERROR_UNKNOWN, X509V3_EXT_UNKNOWN_MASK},
896f5b1c8a1SJohn Marino 		{"ext_parse", X509V3_EXT_PARSE_UNKNOWN, X509V3_EXT_UNKNOWN_MASK},
897f5b1c8a1SJohn Marino 		{"ext_dump", X509V3_EXT_DUMP_UNKNOWN, X509V3_EXT_UNKNOWN_MASK},
898f5b1c8a1SJohn Marino 		{NULL, 0, 0}
899f5b1c8a1SJohn Marino 	};
900f5b1c8a1SJohn Marino 	return set_multi_opts(flags, arg, cert_tbl);
901f5b1c8a1SJohn Marino }
902f5b1c8a1SJohn Marino 
903f5b1c8a1SJohn Marino int
set_name_ex(unsigned long * flags,const char * arg)904f5b1c8a1SJohn Marino set_name_ex(unsigned long *flags, const char *arg)
905f5b1c8a1SJohn Marino {
906f5b1c8a1SJohn Marino 	static const NAME_EX_TBL ex_tbl[] = {
907f5b1c8a1SJohn Marino 		{"esc_2253", ASN1_STRFLGS_ESC_2253, 0},
908f5b1c8a1SJohn Marino 		{"esc_ctrl", ASN1_STRFLGS_ESC_CTRL, 0},
909f5b1c8a1SJohn Marino 		{"esc_msb", ASN1_STRFLGS_ESC_MSB, 0},
910f5b1c8a1SJohn Marino 		{"use_quote", ASN1_STRFLGS_ESC_QUOTE, 0},
911f5b1c8a1SJohn Marino 		{"utf8", ASN1_STRFLGS_UTF8_CONVERT, 0},
912f5b1c8a1SJohn Marino 		{"ignore_type", ASN1_STRFLGS_IGNORE_TYPE, 0},
913f5b1c8a1SJohn Marino 		{"show_type", ASN1_STRFLGS_SHOW_TYPE, 0},
914f5b1c8a1SJohn Marino 		{"dump_all", ASN1_STRFLGS_DUMP_ALL, 0},
915f5b1c8a1SJohn Marino 		{"dump_nostr", ASN1_STRFLGS_DUMP_UNKNOWN, 0},
916f5b1c8a1SJohn Marino 		{"dump_der", ASN1_STRFLGS_DUMP_DER, 0},
917f5b1c8a1SJohn Marino 		{"compat", XN_FLAG_COMPAT, 0xffffffffL},
918f5b1c8a1SJohn Marino 		{"sep_comma_plus", XN_FLAG_SEP_COMMA_PLUS, XN_FLAG_SEP_MASK},
919f5b1c8a1SJohn Marino 		{"sep_comma_plus_space", XN_FLAG_SEP_CPLUS_SPC, XN_FLAG_SEP_MASK},
920f5b1c8a1SJohn Marino 		{"sep_semi_plus_space", XN_FLAG_SEP_SPLUS_SPC, XN_FLAG_SEP_MASK},
921f5b1c8a1SJohn Marino 		{"sep_multiline", XN_FLAG_SEP_MULTILINE, XN_FLAG_SEP_MASK},
922f5b1c8a1SJohn Marino 		{"dn_rev", XN_FLAG_DN_REV, 0},
923f5b1c8a1SJohn Marino 		{"nofname", XN_FLAG_FN_NONE, XN_FLAG_FN_MASK},
924f5b1c8a1SJohn Marino 		{"sname", XN_FLAG_FN_SN, XN_FLAG_FN_MASK},
925f5b1c8a1SJohn Marino 		{"lname", XN_FLAG_FN_LN, XN_FLAG_FN_MASK},
926f5b1c8a1SJohn Marino 		{"align", XN_FLAG_FN_ALIGN, 0},
927f5b1c8a1SJohn Marino 		{"oid", XN_FLAG_FN_OID, XN_FLAG_FN_MASK},
928f5b1c8a1SJohn Marino 		{"space_eq", XN_FLAG_SPC_EQ, 0},
929f5b1c8a1SJohn Marino 		{"dump_unknown", XN_FLAG_DUMP_UNKNOWN_FIELDS, 0},
930f5b1c8a1SJohn Marino 		{"RFC2253", XN_FLAG_RFC2253, 0xffffffffL},
931f5b1c8a1SJohn Marino 		{"oneline", XN_FLAG_ONELINE, 0xffffffffL},
932f5b1c8a1SJohn Marino 		{"multiline", XN_FLAG_MULTILINE, 0xffffffffL},
933f5b1c8a1SJohn Marino 		{"ca_default", XN_FLAG_MULTILINE, 0xffffffffL},
934f5b1c8a1SJohn Marino 		{NULL, 0, 0}
935f5b1c8a1SJohn Marino 	};
936f5b1c8a1SJohn Marino 	return set_multi_opts(flags, arg, ex_tbl);
937f5b1c8a1SJohn Marino }
938f5b1c8a1SJohn Marino 
939f5b1c8a1SJohn Marino int
set_ext_copy(int * copy_type,const char * arg)940f5b1c8a1SJohn Marino set_ext_copy(int *copy_type, const char *arg)
941f5b1c8a1SJohn Marino {
942f5b1c8a1SJohn Marino 	if (!strcasecmp(arg, "none"))
943f5b1c8a1SJohn Marino 		*copy_type = EXT_COPY_NONE;
944f5b1c8a1SJohn Marino 	else if (!strcasecmp(arg, "copy"))
945f5b1c8a1SJohn Marino 		*copy_type = EXT_COPY_ADD;
946f5b1c8a1SJohn Marino 	else if (!strcasecmp(arg, "copyall"))
947f5b1c8a1SJohn Marino 		*copy_type = EXT_COPY_ALL;
948f5b1c8a1SJohn Marino 	else
949f5b1c8a1SJohn Marino 		return 0;
950f5b1c8a1SJohn Marino 	return 1;
951f5b1c8a1SJohn Marino }
952f5b1c8a1SJohn Marino 
953f5b1c8a1SJohn Marino int
copy_extensions(X509 * x,X509_REQ * req,int copy_type)954f5b1c8a1SJohn Marino copy_extensions(X509 *x, X509_REQ *req, int copy_type)
955f5b1c8a1SJohn Marino {
956f5b1c8a1SJohn Marino 	STACK_OF(X509_EXTENSION) *exts = NULL;
957f5b1c8a1SJohn Marino 	X509_EXTENSION *ext, *tmpext;
958f5b1c8a1SJohn Marino 	ASN1_OBJECT *obj;
959f5b1c8a1SJohn Marino 	int i, idx, ret = 0;
960f5b1c8a1SJohn Marino 
961f5b1c8a1SJohn Marino 	if (!x || !req || (copy_type == EXT_COPY_NONE))
962f5b1c8a1SJohn Marino 		return 1;
963f5b1c8a1SJohn Marino 	exts = X509_REQ_get_extensions(req);
964f5b1c8a1SJohn Marino 
965f5b1c8a1SJohn Marino 	for (i = 0; i < sk_X509_EXTENSION_num(exts); i++) {
966f5b1c8a1SJohn Marino 		ext = sk_X509_EXTENSION_value(exts, i);
967f5b1c8a1SJohn Marino 		obj = X509_EXTENSION_get_object(ext);
968f5b1c8a1SJohn Marino 		idx = X509_get_ext_by_OBJ(x, obj, -1);
969f5b1c8a1SJohn Marino 		/* Does extension exist? */
970f5b1c8a1SJohn Marino 		if (idx != -1) {
971f5b1c8a1SJohn Marino 			/* If normal copy don't override existing extension */
972f5b1c8a1SJohn Marino 			if (copy_type == EXT_COPY_ADD)
973f5b1c8a1SJohn Marino 				continue;
974f5b1c8a1SJohn Marino 			/* Delete all extensions of same type */
975f5b1c8a1SJohn Marino 			do {
976f5b1c8a1SJohn Marino 				tmpext = X509_get_ext(x, idx);
977f5b1c8a1SJohn Marino 				X509_delete_ext(x, idx);
978f5b1c8a1SJohn Marino 				X509_EXTENSION_free(tmpext);
979f5b1c8a1SJohn Marino 				idx = X509_get_ext_by_OBJ(x, obj, -1);
980f5b1c8a1SJohn Marino 			} while (idx != -1);
981f5b1c8a1SJohn Marino 		}
982f5b1c8a1SJohn Marino 		if (!X509_add_ext(x, ext, -1))
983f5b1c8a1SJohn Marino 			goto end;
984f5b1c8a1SJohn Marino 	}
985f5b1c8a1SJohn Marino 
986f5b1c8a1SJohn Marino 	ret = 1;
987f5b1c8a1SJohn Marino 
988f5b1c8a1SJohn Marino  end:
989f5b1c8a1SJohn Marino 	sk_X509_EXTENSION_pop_free(exts, X509_EXTENSION_free);
990f5b1c8a1SJohn Marino 
991f5b1c8a1SJohn Marino 	return ret;
992f5b1c8a1SJohn Marino }
993f5b1c8a1SJohn Marino 
994f5b1c8a1SJohn Marino static int
set_multi_opts(unsigned long * flags,const char * arg,const NAME_EX_TBL * in_tbl)995f5b1c8a1SJohn Marino set_multi_opts(unsigned long *flags, const char *arg,
996f5b1c8a1SJohn Marino     const NAME_EX_TBL *in_tbl)
997f5b1c8a1SJohn Marino {
998f5b1c8a1SJohn Marino 	STACK_OF(CONF_VALUE) *vals;
999f5b1c8a1SJohn Marino 	CONF_VALUE *val;
1000f5b1c8a1SJohn Marino 	int i, ret = 1;
1001f5b1c8a1SJohn Marino 
1002f5b1c8a1SJohn Marino 	if (!arg)
1003f5b1c8a1SJohn Marino 		return 0;
1004f5b1c8a1SJohn Marino 	vals = X509V3_parse_list(arg);
1005f5b1c8a1SJohn Marino 	for (i = 0; i < sk_CONF_VALUE_num(vals); i++) {
1006f5b1c8a1SJohn Marino 		val = sk_CONF_VALUE_value(vals, i);
1007f5b1c8a1SJohn Marino 		if (!set_table_opts(flags, val->name, in_tbl))
1008f5b1c8a1SJohn Marino 			ret = 0;
1009f5b1c8a1SJohn Marino 	}
1010f5b1c8a1SJohn Marino 	sk_CONF_VALUE_pop_free(vals, X509V3_conf_free);
1011f5b1c8a1SJohn Marino 	return ret;
1012f5b1c8a1SJohn Marino }
1013f5b1c8a1SJohn Marino 
1014f5b1c8a1SJohn Marino static int
set_table_opts(unsigned long * flags,const char * arg,const NAME_EX_TBL * in_tbl)1015f5b1c8a1SJohn Marino set_table_opts(unsigned long *flags, const char *arg,
1016f5b1c8a1SJohn Marino     const NAME_EX_TBL *in_tbl)
1017f5b1c8a1SJohn Marino {
1018f5b1c8a1SJohn Marino 	char c;
1019f5b1c8a1SJohn Marino 	const NAME_EX_TBL *ptbl;
1020f5b1c8a1SJohn Marino 
1021f5b1c8a1SJohn Marino 	c = arg[0];
1022f5b1c8a1SJohn Marino 	if (c == '-') {
1023f5b1c8a1SJohn Marino 		c = 0;
1024f5b1c8a1SJohn Marino 		arg++;
1025f5b1c8a1SJohn Marino 	} else if (c == '+') {
1026f5b1c8a1SJohn Marino 		c = 1;
1027f5b1c8a1SJohn Marino 		arg++;
1028f5b1c8a1SJohn Marino 	} else
1029f5b1c8a1SJohn Marino 		c = 1;
1030f5b1c8a1SJohn Marino 
1031f5b1c8a1SJohn Marino 	for (ptbl = in_tbl; ptbl->name; ptbl++) {
1032f5b1c8a1SJohn Marino 		if (!strcasecmp(arg, ptbl->name)) {
1033f5b1c8a1SJohn Marino 			*flags &= ~ptbl->mask;
1034f5b1c8a1SJohn Marino 			if (c)
1035f5b1c8a1SJohn Marino 				*flags |= ptbl->flag;
1036f5b1c8a1SJohn Marino 			else
1037f5b1c8a1SJohn Marino 				*flags &= ~ptbl->flag;
1038f5b1c8a1SJohn Marino 			return 1;
1039f5b1c8a1SJohn Marino 		}
1040f5b1c8a1SJohn Marino 	}
1041f5b1c8a1SJohn Marino 	return 0;
1042f5b1c8a1SJohn Marino }
1043f5b1c8a1SJohn Marino 
1044f5b1c8a1SJohn Marino void
print_name(BIO * out,const char * title,X509_NAME * nm,unsigned long lflags)1045f5b1c8a1SJohn Marino print_name(BIO *out, const char *title, X509_NAME *nm, unsigned long lflags)
1046f5b1c8a1SJohn Marino {
1047f5b1c8a1SJohn Marino 	char *buf;
1048f5b1c8a1SJohn Marino 	char mline = 0;
1049f5b1c8a1SJohn Marino 	int indent = 0;
1050f5b1c8a1SJohn Marino 
1051f5b1c8a1SJohn Marino 	if (title)
1052f5b1c8a1SJohn Marino 		BIO_puts(out, title);
1053f5b1c8a1SJohn Marino 	if ((lflags & XN_FLAG_SEP_MASK) == XN_FLAG_SEP_MULTILINE) {
1054f5b1c8a1SJohn Marino 		mline = 1;
1055f5b1c8a1SJohn Marino 		indent = 4;
1056f5b1c8a1SJohn Marino 	}
1057f5b1c8a1SJohn Marino 	if (lflags == XN_FLAG_COMPAT) {
1058f5b1c8a1SJohn Marino 		buf = X509_NAME_oneline(nm, 0, 0);
1059f5b1c8a1SJohn Marino 		BIO_puts(out, buf);
1060f5b1c8a1SJohn Marino 		BIO_puts(out, "\n");
1061f5b1c8a1SJohn Marino 		free(buf);
1062f5b1c8a1SJohn Marino 	} else {
1063f5b1c8a1SJohn Marino 		if (mline)
1064f5b1c8a1SJohn Marino 			BIO_puts(out, "\n");
1065f5b1c8a1SJohn Marino 		X509_NAME_print_ex(out, nm, indent, lflags);
1066f5b1c8a1SJohn Marino 		BIO_puts(out, "\n");
1067f5b1c8a1SJohn Marino 	}
1068f5b1c8a1SJohn Marino }
1069f5b1c8a1SJohn Marino 
1070f5b1c8a1SJohn Marino X509_STORE *
setup_verify(BIO * bp,char * CAfile,char * CApath)1071f5b1c8a1SJohn Marino setup_verify(BIO *bp, char *CAfile, char *CApath)
1072f5b1c8a1SJohn Marino {
1073f5b1c8a1SJohn Marino 	X509_STORE *store;
1074f5b1c8a1SJohn Marino 	X509_LOOKUP *lookup;
1075f5b1c8a1SJohn Marino 
1076f5b1c8a1SJohn Marino 	if (!(store = X509_STORE_new()))
1077f5b1c8a1SJohn Marino 		goto end;
1078f5b1c8a1SJohn Marino 	lookup = X509_STORE_add_lookup(store, X509_LOOKUP_file());
1079f5b1c8a1SJohn Marino 	if (lookup == NULL)
1080f5b1c8a1SJohn Marino 		goto end;
1081f5b1c8a1SJohn Marino 	if (CAfile) {
1082f5b1c8a1SJohn Marino 		if (!X509_LOOKUP_load_file(lookup, CAfile, X509_FILETYPE_PEM)) {
1083f5b1c8a1SJohn Marino 			BIO_printf(bp, "Error loading file %s\n", CAfile);
1084f5b1c8a1SJohn Marino 			goto end;
1085f5b1c8a1SJohn Marino 		}
1086f5b1c8a1SJohn Marino 	} else
1087f5b1c8a1SJohn Marino 		X509_LOOKUP_load_file(lookup, NULL, X509_FILETYPE_DEFAULT);
1088f5b1c8a1SJohn Marino 
1089f5b1c8a1SJohn Marino 	lookup = X509_STORE_add_lookup(store, X509_LOOKUP_hash_dir());
1090f5b1c8a1SJohn Marino 	if (lookup == NULL)
1091f5b1c8a1SJohn Marino 		goto end;
1092f5b1c8a1SJohn Marino 	if (CApath) {
1093f5b1c8a1SJohn Marino 		if (!X509_LOOKUP_add_dir(lookup, CApath, X509_FILETYPE_PEM)) {
1094f5b1c8a1SJohn Marino 			BIO_printf(bp, "Error loading directory %s\n", CApath);
1095f5b1c8a1SJohn Marino 			goto end;
1096f5b1c8a1SJohn Marino 		}
1097f5b1c8a1SJohn Marino 	} else
1098f5b1c8a1SJohn Marino 		X509_LOOKUP_add_dir(lookup, NULL, X509_FILETYPE_DEFAULT);
1099f5b1c8a1SJohn Marino 
1100f5b1c8a1SJohn Marino 	ERR_clear_error();
1101f5b1c8a1SJohn Marino 	return store;
1102f5b1c8a1SJohn Marino 
1103f5b1c8a1SJohn Marino  end:
1104f5b1c8a1SJohn Marino 	X509_STORE_free(store);
1105f5b1c8a1SJohn Marino 	return NULL;
1106f5b1c8a1SJohn Marino }
1107f5b1c8a1SJohn Marino 
1108f5b1c8a1SJohn Marino int
load_config(BIO * err,CONF * cnf)1109f5b1c8a1SJohn Marino load_config(BIO *err, CONF *cnf)
1110f5b1c8a1SJohn Marino {
1111f5b1c8a1SJohn Marino 	static int load_config_called = 0;
1112f5b1c8a1SJohn Marino 
1113f5b1c8a1SJohn Marino 	if (load_config_called)
1114f5b1c8a1SJohn Marino 		return 1;
1115f5b1c8a1SJohn Marino 	load_config_called = 1;
1116f5b1c8a1SJohn Marino 	if (cnf == NULL)
1117f5b1c8a1SJohn Marino 		cnf = config;
1118f5b1c8a1SJohn Marino 	if (cnf == NULL)
1119f5b1c8a1SJohn Marino 		return 1;
1120f5b1c8a1SJohn Marino 
1121f5b1c8a1SJohn Marino 	OPENSSL_load_builtin_modules();
1122f5b1c8a1SJohn Marino 
1123f5b1c8a1SJohn Marino 	if (CONF_modules_load(cnf, NULL, 0) <= 0) {
1124f5b1c8a1SJohn Marino 		BIO_printf(err, "Error configuring OpenSSL\n");
1125f5b1c8a1SJohn Marino 		ERR_print_errors(err);
1126f5b1c8a1SJohn Marino 		return 0;
1127f5b1c8a1SJohn Marino 	}
1128f5b1c8a1SJohn Marino 	return 1;
1129f5b1c8a1SJohn Marino }
1130f5b1c8a1SJohn Marino 
1131f5b1c8a1SJohn Marino char *
make_config_name()1132f5b1c8a1SJohn Marino make_config_name()
1133f5b1c8a1SJohn Marino {
1134f5b1c8a1SJohn Marino 	const char *t = X509_get_default_cert_area();
1135f5b1c8a1SJohn Marino 	char *p;
1136f5b1c8a1SJohn Marino 
1137f5b1c8a1SJohn Marino 	if (asprintf(&p, "%s/openssl.cnf", t) == -1)
1138f5b1c8a1SJohn Marino 		return NULL;
1139f5b1c8a1SJohn Marino 	return p;
1140f5b1c8a1SJohn Marino }
1141f5b1c8a1SJohn Marino 
1142f5b1c8a1SJohn Marino static unsigned long
index_serial_hash(const OPENSSL_CSTRING * a)1143f5b1c8a1SJohn Marino index_serial_hash(const OPENSSL_CSTRING *a)
1144f5b1c8a1SJohn Marino {
1145f5b1c8a1SJohn Marino 	const char *n;
1146f5b1c8a1SJohn Marino 
1147f5b1c8a1SJohn Marino 	n = a[DB_serial];
1148f5b1c8a1SJohn Marino 	while (*n == '0')
1149f5b1c8a1SJohn Marino 		n++;
1150f5b1c8a1SJohn Marino 	return (lh_strhash(n));
1151f5b1c8a1SJohn Marino }
1152f5b1c8a1SJohn Marino 
1153f5b1c8a1SJohn Marino static int
index_serial_cmp(const OPENSSL_CSTRING * a,const OPENSSL_CSTRING * b)1154f5b1c8a1SJohn Marino index_serial_cmp(const OPENSSL_CSTRING *a, const OPENSSL_CSTRING *b)
1155f5b1c8a1SJohn Marino {
1156f5b1c8a1SJohn Marino 	const char *aa, *bb;
1157f5b1c8a1SJohn Marino 
1158f5b1c8a1SJohn Marino 	for (aa = a[DB_serial]; *aa == '0'; aa++)
1159f5b1c8a1SJohn Marino 		;
1160f5b1c8a1SJohn Marino 	for (bb = b[DB_serial]; *bb == '0'; bb++)
1161f5b1c8a1SJohn Marino 		;
1162f5b1c8a1SJohn Marino 	return (strcmp(aa, bb));
1163f5b1c8a1SJohn Marino }
1164f5b1c8a1SJohn Marino 
1165f5b1c8a1SJohn Marino static int
index_name_qual(char ** a)1166f5b1c8a1SJohn Marino index_name_qual(char **a)
1167f5b1c8a1SJohn Marino {
1168f5b1c8a1SJohn Marino 	return (a[0][0] == 'V');
1169f5b1c8a1SJohn Marino }
1170f5b1c8a1SJohn Marino 
1171f5b1c8a1SJohn Marino static unsigned long
index_name_hash(const OPENSSL_CSTRING * a)1172f5b1c8a1SJohn Marino index_name_hash(const OPENSSL_CSTRING *a)
1173f5b1c8a1SJohn Marino {
1174f5b1c8a1SJohn Marino 	return (lh_strhash(a[DB_name]));
1175f5b1c8a1SJohn Marino }
1176f5b1c8a1SJohn Marino 
1177f5b1c8a1SJohn Marino int
index_name_cmp(const OPENSSL_CSTRING * a,const OPENSSL_CSTRING * b)1178f5b1c8a1SJohn Marino index_name_cmp(const OPENSSL_CSTRING *a, const OPENSSL_CSTRING *b)
1179f5b1c8a1SJohn Marino {
1180f5b1c8a1SJohn Marino 	return (strcmp(a[DB_name], b[DB_name]));
1181f5b1c8a1SJohn Marino }
1182f5b1c8a1SJohn Marino 
IMPLEMENT_LHASH_HASH_FN(index_serial,OPENSSL_CSTRING)1183f5b1c8a1SJohn Marino static IMPLEMENT_LHASH_HASH_FN(index_serial, OPENSSL_CSTRING)
1184f5b1c8a1SJohn Marino static IMPLEMENT_LHASH_COMP_FN(index_serial, OPENSSL_CSTRING)
1185f5b1c8a1SJohn Marino static IMPLEMENT_LHASH_HASH_FN(index_name, OPENSSL_CSTRING)
1186f5b1c8a1SJohn Marino static IMPLEMENT_LHASH_COMP_FN(index_name, OPENSSL_CSTRING)
1187f5b1c8a1SJohn Marino 
1188f5b1c8a1SJohn Marino BIGNUM *
1189f5b1c8a1SJohn Marino load_serial(char *serialfile, int create, ASN1_INTEGER **retai)
1190f5b1c8a1SJohn Marino {
1191f5b1c8a1SJohn Marino 	BIO *in = NULL;
1192f5b1c8a1SJohn Marino 	BIGNUM *ret = NULL;
1193f5b1c8a1SJohn Marino 	char buf[1024];
1194f5b1c8a1SJohn Marino 	ASN1_INTEGER *ai = NULL;
1195f5b1c8a1SJohn Marino 
1196f5b1c8a1SJohn Marino 	ai = ASN1_INTEGER_new();
1197f5b1c8a1SJohn Marino 	if (ai == NULL)
1198f5b1c8a1SJohn Marino 		goto err;
1199f5b1c8a1SJohn Marino 
1200f5b1c8a1SJohn Marino 	if ((in = BIO_new(BIO_s_file())) == NULL) {
1201f5b1c8a1SJohn Marino 		ERR_print_errors(bio_err);
1202f5b1c8a1SJohn Marino 		goto err;
1203f5b1c8a1SJohn Marino 	}
1204f5b1c8a1SJohn Marino 	if (BIO_read_filename(in, serialfile) <= 0) {
1205f5b1c8a1SJohn Marino 		if (!create) {
1206f5b1c8a1SJohn Marino 			perror(serialfile);
1207f5b1c8a1SJohn Marino 			goto err;
1208f5b1c8a1SJohn Marino 		} else {
1209f5b1c8a1SJohn Marino 			ret = BN_new();
1210f5b1c8a1SJohn Marino 			if (ret == NULL || !rand_serial(ret, ai))
1211f5b1c8a1SJohn Marino 				BIO_printf(bio_err, "Out of memory\n");
1212f5b1c8a1SJohn Marino 		}
1213f5b1c8a1SJohn Marino 	} else {
121472c33676SMaxim Ag 		if (!a2i_ASN1_INTEGER(in, ai, buf, sizeof buf)) {
1215f5b1c8a1SJohn Marino 			BIO_printf(bio_err, "unable to load number from %s\n",
1216f5b1c8a1SJohn Marino 			    serialfile);
1217f5b1c8a1SJohn Marino 			goto err;
1218f5b1c8a1SJohn Marino 		}
1219f5b1c8a1SJohn Marino 		ret = ASN1_INTEGER_to_BN(ai, NULL);
1220f5b1c8a1SJohn Marino 		if (ret == NULL) {
1221f5b1c8a1SJohn Marino 			BIO_printf(bio_err,
1222f5b1c8a1SJohn Marino 			    "error converting number from bin to BIGNUM\n");
1223f5b1c8a1SJohn Marino 			goto err;
1224f5b1c8a1SJohn Marino 		}
1225f5b1c8a1SJohn Marino 	}
1226f5b1c8a1SJohn Marino 
1227f5b1c8a1SJohn Marino 	if (ret && retai) {
1228f5b1c8a1SJohn Marino 		*retai = ai;
1229f5b1c8a1SJohn Marino 		ai = NULL;
1230f5b1c8a1SJohn Marino 	}
1231f5b1c8a1SJohn Marino 
1232f5b1c8a1SJohn Marino  err:
1233f5b1c8a1SJohn Marino 	BIO_free(in);
1234f5b1c8a1SJohn Marino 	ASN1_INTEGER_free(ai);
1235f5b1c8a1SJohn Marino 	return (ret);
1236f5b1c8a1SJohn Marino }
1237f5b1c8a1SJohn Marino 
1238f5b1c8a1SJohn Marino int
save_serial(char * serialfile,char * suffix,BIGNUM * serial,ASN1_INTEGER ** retai)1239f5b1c8a1SJohn Marino save_serial(char *serialfile, char *suffix, BIGNUM *serial,
1240f5b1c8a1SJohn Marino     ASN1_INTEGER **retai)
1241f5b1c8a1SJohn Marino {
124272c33676SMaxim Ag 	char serialpath[PATH_MAX];
1243f5b1c8a1SJohn Marino 	BIO *out = NULL;
1244f5b1c8a1SJohn Marino 	int ret = 0, n;
1245f5b1c8a1SJohn Marino 	ASN1_INTEGER *ai = NULL;
1246f5b1c8a1SJohn Marino 
1247f5b1c8a1SJohn Marino 	if (suffix == NULL)
124872c33676SMaxim Ag 		n = strlcpy(serialpath, serialfile, sizeof serialpath);
1249f5b1c8a1SJohn Marino 	else
125072c33676SMaxim Ag 		n = snprintf(serialpath, sizeof serialpath, "%s.%s",
1251f5b1c8a1SJohn Marino 		    serialfile, suffix);
1252cca6fc52SDaniel Fojt 	if (n < 0 || n >= sizeof(serialpath)) {
1253f5b1c8a1SJohn Marino 		BIO_printf(bio_err, "serial too long\n");
1254f5b1c8a1SJohn Marino 		goto err;
1255f5b1c8a1SJohn Marino 	}
1256f5b1c8a1SJohn Marino 	out = BIO_new(BIO_s_file());
1257f5b1c8a1SJohn Marino 	if (out == NULL) {
1258f5b1c8a1SJohn Marino 		ERR_print_errors(bio_err);
1259f5b1c8a1SJohn Marino 		goto err;
1260f5b1c8a1SJohn Marino 	}
126172c33676SMaxim Ag 	if (BIO_write_filename(out, serialpath) <= 0) {
1262f5b1c8a1SJohn Marino 		perror(serialfile);
1263f5b1c8a1SJohn Marino 		goto err;
1264f5b1c8a1SJohn Marino 	}
1265f5b1c8a1SJohn Marino 	if ((ai = BN_to_ASN1_INTEGER(serial, NULL)) == NULL) {
1266f5b1c8a1SJohn Marino 		BIO_printf(bio_err,
1267f5b1c8a1SJohn Marino 		    "error converting serial to ASN.1 format\n");
1268f5b1c8a1SJohn Marino 		goto err;
1269f5b1c8a1SJohn Marino 	}
1270f5b1c8a1SJohn Marino 	i2a_ASN1_INTEGER(out, ai);
1271f5b1c8a1SJohn Marino 	BIO_puts(out, "\n");
1272f5b1c8a1SJohn Marino 	ret = 1;
1273f5b1c8a1SJohn Marino 	if (retai) {
1274f5b1c8a1SJohn Marino 		*retai = ai;
1275f5b1c8a1SJohn Marino 		ai = NULL;
1276f5b1c8a1SJohn Marino 	}
1277f5b1c8a1SJohn Marino 
1278f5b1c8a1SJohn Marino  err:
1279f5b1c8a1SJohn Marino 	BIO_free_all(out);
1280f5b1c8a1SJohn Marino 	ASN1_INTEGER_free(ai);
1281f5b1c8a1SJohn Marino 	return (ret);
1282f5b1c8a1SJohn Marino }
1283f5b1c8a1SJohn Marino 
1284f5b1c8a1SJohn Marino int
rotate_serial(char * serialfile,char * new_suffix,char * old_suffix)1285f5b1c8a1SJohn Marino rotate_serial(char *serialfile, char *new_suffix, char *old_suffix)
1286f5b1c8a1SJohn Marino {
128772c33676SMaxim Ag 	char opath[PATH_MAX], npath[PATH_MAX];
1288f5b1c8a1SJohn Marino 
128972c33676SMaxim Ag 	if (snprintf(npath, sizeof npath, "%s.%s", serialfile,
129072c33676SMaxim Ag 	    new_suffix) >= sizeof npath) {
1291f5b1c8a1SJohn Marino 		BIO_printf(bio_err, "file name too long\n");
1292f5b1c8a1SJohn Marino 		goto err;
1293f5b1c8a1SJohn Marino 	}
1294f5b1c8a1SJohn Marino 
129572c33676SMaxim Ag 	if (snprintf(opath, sizeof opath, "%s.%s", serialfile,
129672c33676SMaxim Ag 	    old_suffix) >= sizeof opath) {
129772c33676SMaxim Ag 		BIO_printf(bio_err, "file name too long\n");
129872c33676SMaxim Ag 		goto err;
129972c33676SMaxim Ag 	}
1300f5b1c8a1SJohn Marino 
1301cca6fc52SDaniel Fojt 	if (rename(serialfile, opath) == -1 &&
1302f5b1c8a1SJohn Marino 	    errno != ENOENT && errno != ENOTDIR) {
1303f5b1c8a1SJohn Marino 		BIO_printf(bio_err, "unable to rename %s to %s\n",
130472c33676SMaxim Ag 		    serialfile, opath);
1305f5b1c8a1SJohn Marino 		perror("reason");
1306f5b1c8a1SJohn Marino 		goto err;
1307f5b1c8a1SJohn Marino 	}
1308f5b1c8a1SJohn Marino 
1309f5b1c8a1SJohn Marino 
1310cca6fc52SDaniel Fojt 	if (rename(npath, serialfile) == -1) {
1311f5b1c8a1SJohn Marino 		BIO_printf(bio_err, "unable to rename %s to %s\n",
131272c33676SMaxim Ag 		    npath, serialfile);
1313f5b1c8a1SJohn Marino 		perror("reason");
1314cca6fc52SDaniel Fojt 		if (rename(opath, serialfile) == -1) {
1315f5b1c8a1SJohn Marino 			BIO_printf(bio_err, "unable to rename %s to %s\n",
131672c33676SMaxim Ag 			    opath, serialfile);
1317f5b1c8a1SJohn Marino 			perror("reason");
1318f5b1c8a1SJohn Marino 		}
1319f5b1c8a1SJohn Marino 		goto err;
1320f5b1c8a1SJohn Marino 	}
1321f5b1c8a1SJohn Marino 	return 1;
1322f5b1c8a1SJohn Marino 
1323f5b1c8a1SJohn Marino  err:
1324f5b1c8a1SJohn Marino 	return 0;
1325f5b1c8a1SJohn Marino }
1326f5b1c8a1SJohn Marino 
1327f5b1c8a1SJohn Marino int
rand_serial(BIGNUM * b,ASN1_INTEGER * ai)1328f5b1c8a1SJohn Marino rand_serial(BIGNUM *b, ASN1_INTEGER *ai)
1329f5b1c8a1SJohn Marino {
1330f5b1c8a1SJohn Marino 	BIGNUM *btmp;
1331f5b1c8a1SJohn Marino 	int ret = 0;
1332f5b1c8a1SJohn Marino 
1333f5b1c8a1SJohn Marino 	if (b)
1334f5b1c8a1SJohn Marino 		btmp = b;
1335f5b1c8a1SJohn Marino 	else
1336f5b1c8a1SJohn Marino 		btmp = BN_new();
1337f5b1c8a1SJohn Marino 
1338f5b1c8a1SJohn Marino 	if (!btmp)
1339f5b1c8a1SJohn Marino 		return 0;
1340f5b1c8a1SJohn Marino 
1341f5b1c8a1SJohn Marino 	if (!BN_pseudo_rand(btmp, SERIAL_RAND_BITS, 0, 0))
1342f5b1c8a1SJohn Marino 		goto error;
1343f5b1c8a1SJohn Marino 	if (ai && !BN_to_ASN1_INTEGER(btmp, ai))
1344f5b1c8a1SJohn Marino 		goto error;
1345f5b1c8a1SJohn Marino 
1346f5b1c8a1SJohn Marino 	ret = 1;
1347f5b1c8a1SJohn Marino 
1348f5b1c8a1SJohn Marino  error:
134972c33676SMaxim Ag 	if (b != btmp)
1350f5b1c8a1SJohn Marino 		BN_free(btmp);
1351f5b1c8a1SJohn Marino 
1352f5b1c8a1SJohn Marino 	return ret;
1353f5b1c8a1SJohn Marino }
1354f5b1c8a1SJohn Marino 
1355f5b1c8a1SJohn Marino CA_DB *
load_index(char * dbfile,DB_ATTR * db_attr)1356f5b1c8a1SJohn Marino load_index(char *dbfile, DB_ATTR *db_attr)
1357f5b1c8a1SJohn Marino {
1358f5b1c8a1SJohn Marino 	CA_DB *retdb = NULL;
1359f5b1c8a1SJohn Marino 	TXT_DB *tmpdb = NULL;
1360f5b1c8a1SJohn Marino 	BIO *in = BIO_new(BIO_s_file());
1361f5b1c8a1SJohn Marino 	CONF *dbattr_conf = NULL;
136272c33676SMaxim Ag 	char attrpath[PATH_MAX];
1363f5b1c8a1SJohn Marino 	long errorline = -1;
1364f5b1c8a1SJohn Marino 
1365f5b1c8a1SJohn Marino 	if (in == NULL) {
1366f5b1c8a1SJohn Marino 		ERR_print_errors(bio_err);
1367f5b1c8a1SJohn Marino 		goto err;
1368f5b1c8a1SJohn Marino 	}
1369f5b1c8a1SJohn Marino 	if (BIO_read_filename(in, dbfile) <= 0) {
1370f5b1c8a1SJohn Marino 		perror(dbfile);
1371f5b1c8a1SJohn Marino 		BIO_printf(bio_err, "unable to open '%s'\n", dbfile);
1372f5b1c8a1SJohn Marino 		goto err;
1373f5b1c8a1SJohn Marino 	}
1374f5b1c8a1SJohn Marino 	if ((tmpdb = TXT_DB_read(in, DB_NUMBER)) == NULL)
1375f5b1c8a1SJohn Marino 		goto err;
1376f5b1c8a1SJohn Marino 
137772c33676SMaxim Ag 	if (snprintf(attrpath, sizeof attrpath, "%s.attr", dbfile)
137872c33676SMaxim Ag 	    >= sizeof attrpath) {
137972c33676SMaxim Ag 		BIO_printf(bio_err, "attr filename too long\n");
138072c33676SMaxim Ag 		goto err;
138172c33676SMaxim Ag 	}
138272c33676SMaxim Ag 
1383f5b1c8a1SJohn Marino 	dbattr_conf = NCONF_new(NULL);
138472c33676SMaxim Ag 	if (NCONF_load(dbattr_conf, attrpath, &errorline) <= 0) {
1385f5b1c8a1SJohn Marino 		if (errorline > 0) {
1386f5b1c8a1SJohn Marino 			BIO_printf(bio_err,
1387f5b1c8a1SJohn Marino 			    "error on line %ld of db attribute file '%s'\n",
138872c33676SMaxim Ag 			    errorline, attrpath);
1389f5b1c8a1SJohn Marino 			goto err;
1390f5b1c8a1SJohn Marino 		} else {
1391f5b1c8a1SJohn Marino 			NCONF_free(dbattr_conf);
1392f5b1c8a1SJohn Marino 			dbattr_conf = NULL;
1393f5b1c8a1SJohn Marino 		}
1394f5b1c8a1SJohn Marino 	}
1395f5b1c8a1SJohn Marino 	if ((retdb = malloc(sizeof(CA_DB))) == NULL) {
1396f5b1c8a1SJohn Marino 		fprintf(stderr, "Out of memory\n");
1397f5b1c8a1SJohn Marino 		goto err;
1398f5b1c8a1SJohn Marino 	}
1399f5b1c8a1SJohn Marino 	retdb->db = tmpdb;
1400f5b1c8a1SJohn Marino 	tmpdb = NULL;
1401f5b1c8a1SJohn Marino 	if (db_attr)
1402f5b1c8a1SJohn Marino 		retdb->attributes = *db_attr;
1403f5b1c8a1SJohn Marino 	else {
1404f5b1c8a1SJohn Marino 		retdb->attributes.unique_subject = 1;
1405f5b1c8a1SJohn Marino 	}
1406f5b1c8a1SJohn Marino 
1407f5b1c8a1SJohn Marino 	if (dbattr_conf) {
1408f5b1c8a1SJohn Marino 		char *p = NCONF_get_string(dbattr_conf, NULL, "unique_subject");
1409f5b1c8a1SJohn Marino 		if (p) {
1410f5b1c8a1SJohn Marino 			retdb->attributes.unique_subject = parse_yesno(p, 1);
1411f5b1c8a1SJohn Marino 		}
1412f5b1c8a1SJohn Marino 	}
1413f5b1c8a1SJohn Marino 
1414f5b1c8a1SJohn Marino  err:
1415f5b1c8a1SJohn Marino 	NCONF_free(dbattr_conf);
1416f5b1c8a1SJohn Marino 	TXT_DB_free(tmpdb);
1417f5b1c8a1SJohn Marino 	BIO_free_all(in);
1418f5b1c8a1SJohn Marino 	return retdb;
1419f5b1c8a1SJohn Marino }
1420f5b1c8a1SJohn Marino 
1421f5b1c8a1SJohn Marino int
index_index(CA_DB * db)1422f5b1c8a1SJohn Marino index_index(CA_DB *db)
1423f5b1c8a1SJohn Marino {
1424f5b1c8a1SJohn Marino 	if (!TXT_DB_create_index(db->db, DB_serial, NULL,
1425f5b1c8a1SJohn Marino 	    LHASH_HASH_FN(index_serial), LHASH_COMP_FN(index_serial))) {
1426f5b1c8a1SJohn Marino 		BIO_printf(bio_err,
1427f5b1c8a1SJohn Marino 		    "error creating serial number index:(%ld,%ld,%ld)\n",
1428f5b1c8a1SJohn Marino 		    db->db->error, db->db->arg1, db->db->arg2);
1429f5b1c8a1SJohn Marino 		return 0;
1430f5b1c8a1SJohn Marino 	}
1431f5b1c8a1SJohn Marino 	if (db->attributes.unique_subject &&
1432f5b1c8a1SJohn Marino 	    !TXT_DB_create_index(db->db, DB_name, index_name_qual,
1433f5b1c8a1SJohn Marino 	    LHASH_HASH_FN(index_name), LHASH_COMP_FN(index_name))) {
1434f5b1c8a1SJohn Marino 		BIO_printf(bio_err, "error creating name index:(%ld,%ld,%ld)\n",
1435f5b1c8a1SJohn Marino 		    db->db->error, db->db->arg1, db->db->arg2);
1436f5b1c8a1SJohn Marino 		return 0;
1437f5b1c8a1SJohn Marino 	}
1438f5b1c8a1SJohn Marino 	return 1;
1439f5b1c8a1SJohn Marino }
1440f5b1c8a1SJohn Marino 
1441f5b1c8a1SJohn Marino int
save_index(const char * file,const char * suffix,CA_DB * db)144272c33676SMaxim Ag save_index(const char *file, const char *suffix, CA_DB *db)
1443f5b1c8a1SJohn Marino {
144472c33676SMaxim Ag 	char attrpath[PATH_MAX], dbfile[PATH_MAX];
1445f5b1c8a1SJohn Marino 	BIO *out = BIO_new(BIO_s_file());
1446f5b1c8a1SJohn Marino 	int j;
1447f5b1c8a1SJohn Marino 
1448f5b1c8a1SJohn Marino 	if (out == NULL) {
1449f5b1c8a1SJohn Marino 		ERR_print_errors(bio_err);
1450f5b1c8a1SJohn Marino 		goto err;
1451f5b1c8a1SJohn Marino 	}
145272c33676SMaxim Ag 	if (snprintf(attrpath, sizeof attrpath, "%s.attr.%s",
145372c33676SMaxim Ag 	    file, suffix) >= sizeof attrpath) {
1454f5b1c8a1SJohn Marino 		BIO_printf(bio_err, "file name too long\n");
1455f5b1c8a1SJohn Marino 		goto err;
1456f5b1c8a1SJohn Marino 	}
145772c33676SMaxim Ag 	if (snprintf(dbfile, sizeof dbfile, "%s.%s",
145872c33676SMaxim Ag 	    file, suffix) >= sizeof dbfile) {
145972c33676SMaxim Ag 		BIO_printf(bio_err, "file name too long\n");
146072c33676SMaxim Ag 		goto err;
146172c33676SMaxim Ag 	}
1462f5b1c8a1SJohn Marino 
146372c33676SMaxim Ag 	if (BIO_write_filename(out, dbfile) <= 0) {
1464f5b1c8a1SJohn Marino 		perror(dbfile);
1465f5b1c8a1SJohn Marino 		BIO_printf(bio_err, "unable to open '%s'\n", dbfile);
1466f5b1c8a1SJohn Marino 		goto err;
1467f5b1c8a1SJohn Marino 	}
1468f5b1c8a1SJohn Marino 	j = TXT_DB_write(out, db->db);
1469f5b1c8a1SJohn Marino 	if (j <= 0)
1470f5b1c8a1SJohn Marino 		goto err;
1471f5b1c8a1SJohn Marino 
1472f5b1c8a1SJohn Marino 	BIO_free(out);
1473f5b1c8a1SJohn Marino 
1474f5b1c8a1SJohn Marino 	out = BIO_new(BIO_s_file());
1475f5b1c8a1SJohn Marino 
147672c33676SMaxim Ag 	if (BIO_write_filename(out, attrpath) <= 0) {
147772c33676SMaxim Ag 		perror(attrpath);
147872c33676SMaxim Ag 		BIO_printf(bio_err, "unable to open '%s'\n", attrpath);
1479f5b1c8a1SJohn Marino 		goto err;
1480f5b1c8a1SJohn Marino 	}
1481f5b1c8a1SJohn Marino 	BIO_printf(out, "unique_subject = %s\n",
1482f5b1c8a1SJohn Marino 	    db->attributes.unique_subject ? "yes" : "no");
1483f5b1c8a1SJohn Marino 	BIO_free(out);
1484f5b1c8a1SJohn Marino 
1485f5b1c8a1SJohn Marino 	return 1;
1486f5b1c8a1SJohn Marino 
1487f5b1c8a1SJohn Marino  err:
1488f5b1c8a1SJohn Marino 	return 0;
1489f5b1c8a1SJohn Marino }
1490f5b1c8a1SJohn Marino 
1491f5b1c8a1SJohn Marino int
rotate_index(const char * dbfile,const char * new_suffix,const char * old_suffix)1492f5b1c8a1SJohn Marino rotate_index(const char *dbfile, const char *new_suffix, const char *old_suffix)
1493f5b1c8a1SJohn Marino {
149472c33676SMaxim Ag 	char attrpath[PATH_MAX], nattrpath[PATH_MAX], oattrpath[PATH_MAX];
149572c33676SMaxim Ag 	char dbpath[PATH_MAX], odbpath[PATH_MAX];
1496f5b1c8a1SJohn Marino 
149772c33676SMaxim Ag 	if (snprintf(attrpath, sizeof attrpath, "%s.attr",
149872c33676SMaxim Ag 	    dbfile) >= sizeof attrpath) {
1499f5b1c8a1SJohn Marino 		BIO_printf(bio_err, "file name too long\n");
1500f5b1c8a1SJohn Marino 		goto err;
1501f5b1c8a1SJohn Marino 	}
150272c33676SMaxim Ag 	if (snprintf(nattrpath, sizeof nattrpath, "%s.attr.%s",
150372c33676SMaxim Ag 	    dbfile, new_suffix) >= sizeof nattrpath) {
150472c33676SMaxim Ag 		BIO_printf(bio_err, "file name too long\n");
150572c33676SMaxim Ag 		goto err;
150672c33676SMaxim Ag 	}
150772c33676SMaxim Ag 	if (snprintf(oattrpath, sizeof oattrpath, "%s.attr.%s",
150872c33676SMaxim Ag 	    dbfile, old_suffix) >= sizeof oattrpath) {
150972c33676SMaxim Ag 		BIO_printf(bio_err, "file name too long\n");
151072c33676SMaxim Ag 		goto err;
151172c33676SMaxim Ag 	}
151272c33676SMaxim Ag 	if (snprintf(dbpath, sizeof dbpath, "%s.%s",
151372c33676SMaxim Ag 	    dbfile, new_suffix) >= sizeof dbpath) {
151472c33676SMaxim Ag 		BIO_printf(bio_err, "file name too long\n");
151572c33676SMaxim Ag 		goto err;
151672c33676SMaxim Ag 	}
151772c33676SMaxim Ag 	if (snprintf(odbpath, sizeof odbpath, "%s.%s",
151872c33676SMaxim Ag 	    dbfile, old_suffix) >= sizeof odbpath) {
151972c33676SMaxim Ag 		BIO_printf(bio_err, "file name too long\n");
152072c33676SMaxim Ag 		goto err;
152172c33676SMaxim Ag 	}
1522f5b1c8a1SJohn Marino 
1523cca6fc52SDaniel Fojt 	if (rename(dbfile, odbpath) == -1 && errno != ENOENT && errno != ENOTDIR) {
1524f5b1c8a1SJohn Marino 		BIO_printf(bio_err, "unable to rename %s to %s\n",
152572c33676SMaxim Ag 		    dbfile, odbpath);
1526f5b1c8a1SJohn Marino 		perror("reason");
1527f5b1c8a1SJohn Marino 		goto err;
1528f5b1c8a1SJohn Marino 	}
1529f5b1c8a1SJohn Marino 
1530cca6fc52SDaniel Fojt 	if (rename(dbpath, dbfile) == -1) {
1531f5b1c8a1SJohn Marino 		BIO_printf(bio_err, "unable to rename %s to %s\n",
153272c33676SMaxim Ag 		    dbpath, dbfile);
1533f5b1c8a1SJohn Marino 		perror("reason");
1534cca6fc52SDaniel Fojt 		if (rename(odbpath, dbfile) == -1) {
1535f5b1c8a1SJohn Marino 			BIO_printf(bio_err, "unable to rename %s to %s\n",
153672c33676SMaxim Ag 			    odbpath, dbfile);
1537f5b1c8a1SJohn Marino 			perror("reason");
1538f5b1c8a1SJohn Marino 		}
1539f5b1c8a1SJohn Marino 		goto err;
1540f5b1c8a1SJohn Marino 	}
1541f5b1c8a1SJohn Marino 
1542cca6fc52SDaniel Fojt 	if (rename(attrpath, oattrpath) == -1 && errno != ENOENT && errno != ENOTDIR) {
1543f5b1c8a1SJohn Marino 		BIO_printf(bio_err, "unable to rename %s to %s\n",
154472c33676SMaxim Ag 		    attrpath, oattrpath);
1545f5b1c8a1SJohn Marino 		perror("reason");
1546cca6fc52SDaniel Fojt 		if (rename(dbfile, dbpath) == -1) {
1547f5b1c8a1SJohn Marino 			BIO_printf(bio_err, "unable to rename %s to %s\n",
154872c33676SMaxim Ag 			    dbfile, dbpath);
1549f5b1c8a1SJohn Marino 			perror("reason");
1550f5b1c8a1SJohn Marino 		}
1551cca6fc52SDaniel Fojt 		if (rename(odbpath, dbfile) == -1) {
1552f5b1c8a1SJohn Marino 			BIO_printf(bio_err, "unable to rename %s to %s\n",
155372c33676SMaxim Ag 			    odbpath, dbfile);
1554f5b1c8a1SJohn Marino 			perror("reason");
1555f5b1c8a1SJohn Marino 		}
1556f5b1c8a1SJohn Marino 		goto err;
1557f5b1c8a1SJohn Marino 	}
1558f5b1c8a1SJohn Marino 
1559cca6fc52SDaniel Fojt 	if (rename(nattrpath, attrpath) == -1) {
1560f5b1c8a1SJohn Marino 		BIO_printf(bio_err, "unable to rename %s to %s\n",
156172c33676SMaxim Ag 		    nattrpath, attrpath);
1562f5b1c8a1SJohn Marino 		perror("reason");
1563cca6fc52SDaniel Fojt 		if (rename(oattrpath, attrpath) == -1) {
1564f5b1c8a1SJohn Marino 			BIO_printf(bio_err, "unable to rename %s to %s\n",
156572c33676SMaxim Ag 			    oattrpath, attrpath);
1566f5b1c8a1SJohn Marino 			perror("reason");
1567f5b1c8a1SJohn Marino 		}
1568cca6fc52SDaniel Fojt 		if (rename(dbfile, dbpath) == -1) {
1569f5b1c8a1SJohn Marino 			BIO_printf(bio_err, "unable to rename %s to %s\n",
157072c33676SMaxim Ag 			    dbfile, dbpath);
1571f5b1c8a1SJohn Marino 			perror("reason");
1572f5b1c8a1SJohn Marino 		}
1573cca6fc52SDaniel Fojt 		if (rename(odbpath, dbfile) == -1) {
1574f5b1c8a1SJohn Marino 			BIO_printf(bio_err, "unable to rename %s to %s\n",
157572c33676SMaxim Ag 			    odbpath, dbfile);
1576f5b1c8a1SJohn Marino 			perror("reason");
1577f5b1c8a1SJohn Marino 		}
1578f5b1c8a1SJohn Marino 		goto err;
1579f5b1c8a1SJohn Marino 	}
1580f5b1c8a1SJohn Marino 	return 1;
1581f5b1c8a1SJohn Marino 
1582f5b1c8a1SJohn Marino  err:
1583f5b1c8a1SJohn Marino 	return 0;
1584f5b1c8a1SJohn Marino }
1585f5b1c8a1SJohn Marino 
1586f5b1c8a1SJohn Marino void
free_index(CA_DB * db)1587f5b1c8a1SJohn Marino free_index(CA_DB *db)
1588f5b1c8a1SJohn Marino {
1589f5b1c8a1SJohn Marino 	if (db) {
1590f5b1c8a1SJohn Marino 		TXT_DB_free(db->db);
1591f5b1c8a1SJohn Marino 		free(db);
1592f5b1c8a1SJohn Marino 	}
1593f5b1c8a1SJohn Marino }
1594f5b1c8a1SJohn Marino 
1595f5b1c8a1SJohn Marino int
parse_yesno(const char * str,int def)1596f5b1c8a1SJohn Marino parse_yesno(const char *str, int def)
1597f5b1c8a1SJohn Marino {
1598f5b1c8a1SJohn Marino 	int ret = def;
1599f5b1c8a1SJohn Marino 
1600f5b1c8a1SJohn Marino 	if (str) {
1601f5b1c8a1SJohn Marino 		switch (*str) {
1602f5b1c8a1SJohn Marino 		case 'f':	/* false */
1603f5b1c8a1SJohn Marino 		case 'F':	/* FALSE */
1604f5b1c8a1SJohn Marino 		case 'n':	/* no */
1605f5b1c8a1SJohn Marino 		case 'N':	/* NO */
1606f5b1c8a1SJohn Marino 		case '0':	/* 0 */
1607f5b1c8a1SJohn Marino 			ret = 0;
1608f5b1c8a1SJohn Marino 			break;
1609f5b1c8a1SJohn Marino 		case 't':	/* true */
1610f5b1c8a1SJohn Marino 		case 'T':	/* TRUE */
1611f5b1c8a1SJohn Marino 		case 'y':	/* yes */
1612f5b1c8a1SJohn Marino 		case 'Y':	/* YES */
1613f5b1c8a1SJohn Marino 		case '1':	/* 1 */
1614f5b1c8a1SJohn Marino 			ret = 1;
1615f5b1c8a1SJohn Marino 			break;
1616f5b1c8a1SJohn Marino 		default:
1617f5b1c8a1SJohn Marino 			ret = def;
1618f5b1c8a1SJohn Marino 			break;
1619f5b1c8a1SJohn Marino 		}
1620f5b1c8a1SJohn Marino 	}
1621f5b1c8a1SJohn Marino 	return ret;
1622f5b1c8a1SJohn Marino }
1623f5b1c8a1SJohn Marino 
1624f5b1c8a1SJohn Marino /*
1625f5b1c8a1SJohn Marino  * subject is expected to be in the format /type0=value0/type1=value1/type2=...
1626f5b1c8a1SJohn Marino  * where characters may be escaped by \
1627f5b1c8a1SJohn Marino  */
1628f5b1c8a1SJohn Marino X509_NAME *
parse_name(char * subject,long chtype,int multirdn)1629f5b1c8a1SJohn Marino parse_name(char *subject, long chtype, int multirdn)
1630f5b1c8a1SJohn Marino {
1631f5b1c8a1SJohn Marino 	X509_NAME *name = NULL;
1632f5b1c8a1SJohn Marino 	size_t buflen, max_ne;
1633f5b1c8a1SJohn Marino 	char **ne_types, **ne_values;
1634f5b1c8a1SJohn Marino 	char *buf, *bp, *sp;
1635f5b1c8a1SJohn Marino 	int i, nid, ne_num = 0;
1636f5b1c8a1SJohn Marino 	int *mval;
1637f5b1c8a1SJohn Marino 
1638f5b1c8a1SJohn Marino 	/*
1639f5b1c8a1SJohn Marino 	 * Buffer to copy the types and values into. Due to escaping the
1640f5b1c8a1SJohn Marino 	 * copy can only become shorter.
1641f5b1c8a1SJohn Marino 	 */
1642f5b1c8a1SJohn Marino 	buflen = strlen(subject) + 1;
1643f5b1c8a1SJohn Marino 	buf = malloc(buflen);
1644f5b1c8a1SJohn Marino 
1645f5b1c8a1SJohn Marino 	/* Maximum number of name elements. */
1646f5b1c8a1SJohn Marino 	max_ne = buflen / 2 + 1;
1647f5b1c8a1SJohn Marino 	ne_types = reallocarray(NULL, max_ne, sizeof(char *));
1648f5b1c8a1SJohn Marino 	ne_values = reallocarray(NULL, max_ne, sizeof(char *));
1649f5b1c8a1SJohn Marino 	mval = reallocarray(NULL, max_ne, sizeof(int));
1650f5b1c8a1SJohn Marino 
1651f5b1c8a1SJohn Marino 	if (buf == NULL || ne_types == NULL || ne_values == NULL ||
1652f5b1c8a1SJohn Marino 	    mval == NULL) {
1653f5b1c8a1SJohn Marino 		BIO_printf(bio_err, "malloc error\n");
1654f5b1c8a1SJohn Marino 		goto error;
1655f5b1c8a1SJohn Marino 	}
1656f5b1c8a1SJohn Marino 
1657f5b1c8a1SJohn Marino 	bp = buf;
1658f5b1c8a1SJohn Marino 	sp = subject;
1659f5b1c8a1SJohn Marino 
1660f5b1c8a1SJohn Marino 	if (*subject != '/') {
1661f5b1c8a1SJohn Marino 		BIO_printf(bio_err, "Subject does not start with '/'.\n");
1662f5b1c8a1SJohn Marino 		goto error;
1663f5b1c8a1SJohn Marino 	}
1664f5b1c8a1SJohn Marino 
1665f5b1c8a1SJohn Marino 	/* Skip leading '/'. */
1666f5b1c8a1SJohn Marino 	sp++;
1667f5b1c8a1SJohn Marino 
1668f5b1c8a1SJohn Marino 	/* No multivalued RDN by default. */
1669f5b1c8a1SJohn Marino 	mval[ne_num] = 0;
1670f5b1c8a1SJohn Marino 
1671f5b1c8a1SJohn Marino 	while (*sp) {
1672f5b1c8a1SJohn Marino 		/* Collect type. */
1673f5b1c8a1SJohn Marino 		ne_types[ne_num] = bp;
1674f5b1c8a1SJohn Marino 		while (*sp) {
1675f5b1c8a1SJohn Marino 			/* is there anything to escape in the type...? */
1676f5b1c8a1SJohn Marino 			if (*sp == '\\') {
1677f5b1c8a1SJohn Marino 				if (*++sp)
1678f5b1c8a1SJohn Marino 					*bp++ = *sp++;
1679f5b1c8a1SJohn Marino 				else {
1680f5b1c8a1SJohn Marino 					BIO_printf(bio_err, "escape character "
1681f5b1c8a1SJohn Marino 					    "at end of string\n");
1682f5b1c8a1SJohn Marino 					goto error;
1683f5b1c8a1SJohn Marino 				}
1684f5b1c8a1SJohn Marino 			} else if (*sp == '=') {
1685f5b1c8a1SJohn Marino 				sp++;
1686f5b1c8a1SJohn Marino 				*bp++ = '\0';
1687f5b1c8a1SJohn Marino 				break;
1688f5b1c8a1SJohn Marino 			} else
1689f5b1c8a1SJohn Marino 				*bp++ = *sp++;
1690f5b1c8a1SJohn Marino 		}
1691f5b1c8a1SJohn Marino 		if (!*sp) {
1692f5b1c8a1SJohn Marino 			BIO_printf(bio_err, "end of string encountered while "
1693f5b1c8a1SJohn Marino 			    "processing type of subject name element #%d\n",
1694f5b1c8a1SJohn Marino 			    ne_num);
1695f5b1c8a1SJohn Marino 			goto error;
1696f5b1c8a1SJohn Marino 		}
1697f5b1c8a1SJohn Marino 		ne_values[ne_num] = bp;
1698f5b1c8a1SJohn Marino 		while (*sp) {
1699f5b1c8a1SJohn Marino 			if (*sp == '\\') {
1700f5b1c8a1SJohn Marino 				if (*++sp)
1701f5b1c8a1SJohn Marino 					*bp++ = *sp++;
1702f5b1c8a1SJohn Marino 				else {
1703f5b1c8a1SJohn Marino 					BIO_printf(bio_err, "escape character "
1704f5b1c8a1SJohn Marino 					    "at end of string\n");
1705f5b1c8a1SJohn Marino 					goto error;
1706f5b1c8a1SJohn Marino 				}
1707f5b1c8a1SJohn Marino 			} else if (*sp == '/') {
1708f5b1c8a1SJohn Marino 				sp++;
1709f5b1c8a1SJohn Marino 				/* no multivalued RDN by default */
1710f5b1c8a1SJohn Marino 				mval[ne_num + 1] = 0;
1711f5b1c8a1SJohn Marino 				break;
1712f5b1c8a1SJohn Marino 			} else if (*sp == '+' && multirdn) {
1713f5b1c8a1SJohn Marino 				/* a not escaped + signals a multivalued RDN */
1714f5b1c8a1SJohn Marino 				sp++;
1715f5b1c8a1SJohn Marino 				mval[ne_num + 1] = -1;
1716f5b1c8a1SJohn Marino 				break;
1717f5b1c8a1SJohn Marino 			} else
1718f5b1c8a1SJohn Marino 				*bp++ = *sp++;
1719f5b1c8a1SJohn Marino 		}
1720f5b1c8a1SJohn Marino 		*bp++ = '\0';
1721f5b1c8a1SJohn Marino 		ne_num++;
1722f5b1c8a1SJohn Marino 	}
1723f5b1c8a1SJohn Marino 
1724f5b1c8a1SJohn Marino 	if ((name = X509_NAME_new()) == NULL)
1725f5b1c8a1SJohn Marino 		goto error;
1726f5b1c8a1SJohn Marino 
1727f5b1c8a1SJohn Marino 	for (i = 0; i < ne_num; i++) {
1728f5b1c8a1SJohn Marino 		if ((nid = OBJ_txt2nid(ne_types[i])) == NID_undef) {
1729f5b1c8a1SJohn Marino 			BIO_printf(bio_err,
1730f5b1c8a1SJohn Marino 			    "Subject Attribute %s has no known NID, skipped\n",
1731f5b1c8a1SJohn Marino 			    ne_types[i]);
1732f5b1c8a1SJohn Marino 			continue;
1733f5b1c8a1SJohn Marino 		}
1734f5b1c8a1SJohn Marino 		if (!*ne_values[i]) {
1735f5b1c8a1SJohn Marino 			BIO_printf(bio_err, "No value provided for Subject "
1736f5b1c8a1SJohn Marino 			    "Attribute %s, skipped\n", ne_types[i]);
1737f5b1c8a1SJohn Marino 			continue;
1738f5b1c8a1SJohn Marino 		}
1739f5b1c8a1SJohn Marino 		if (!X509_NAME_add_entry_by_NID(name, nid, chtype,
1740f5b1c8a1SJohn Marino 		    (unsigned char *) ne_values[i], -1, -1, mval[i]))
1741f5b1c8a1SJohn Marino 			goto error;
1742f5b1c8a1SJohn Marino 	}
1743f5b1c8a1SJohn Marino 	goto done;
1744f5b1c8a1SJohn Marino 
1745f5b1c8a1SJohn Marino  error:
1746f5b1c8a1SJohn Marino 	X509_NAME_free(name);
1747f5b1c8a1SJohn Marino 	name = NULL;
1748f5b1c8a1SJohn Marino 
1749f5b1c8a1SJohn Marino  done:
1750f5b1c8a1SJohn Marino 	free(ne_values);
1751f5b1c8a1SJohn Marino 	free(ne_types);
1752f5b1c8a1SJohn Marino 	free(mval);
1753f5b1c8a1SJohn Marino 	free(buf);
1754f5b1c8a1SJohn Marino 
1755f5b1c8a1SJohn Marino 	return name;
1756f5b1c8a1SJohn Marino }
1757f5b1c8a1SJohn Marino 
1758f5b1c8a1SJohn Marino int
args_verify(char *** pargs,int * pargc,int * badarg,BIO * err,X509_VERIFY_PARAM ** pm)1759f5b1c8a1SJohn Marino args_verify(char ***pargs, int *pargc, int *badarg, BIO *err,
1760f5b1c8a1SJohn Marino     X509_VERIFY_PARAM **pm)
1761f5b1c8a1SJohn Marino {
1762f5b1c8a1SJohn Marino 	ASN1_OBJECT *otmp = NULL;
1763f5b1c8a1SJohn Marino 	unsigned long flags = 0;
1764f5b1c8a1SJohn Marino 	int i;
1765f5b1c8a1SJohn Marino 	int purpose = 0, depth = -1;
1766f5b1c8a1SJohn Marino 	char **oldargs = *pargs;
1767f5b1c8a1SJohn Marino 	char *arg = **pargs, *argn = (*pargs)[1];
1768f5b1c8a1SJohn Marino 	time_t at_time = 0;
1769f5b1c8a1SJohn Marino 	const char *errstr = NULL;
1770f5b1c8a1SJohn Marino 
1771f5b1c8a1SJohn Marino 	if (!strcmp(arg, "-policy")) {
1772f5b1c8a1SJohn Marino 		if (!argn)
1773f5b1c8a1SJohn Marino 			*badarg = 1;
1774f5b1c8a1SJohn Marino 		else {
1775f5b1c8a1SJohn Marino 			otmp = OBJ_txt2obj(argn, 0);
1776f5b1c8a1SJohn Marino 			if (!otmp) {
1777f5b1c8a1SJohn Marino 				BIO_printf(err, "Invalid Policy \"%s\"\n",
1778f5b1c8a1SJohn Marino 				    argn);
1779f5b1c8a1SJohn Marino 				*badarg = 1;
1780f5b1c8a1SJohn Marino 			}
1781f5b1c8a1SJohn Marino 		}
1782f5b1c8a1SJohn Marino 		(*pargs)++;
1783f5b1c8a1SJohn Marino 	} else if (strcmp(arg, "-purpose") == 0) {
1784f5b1c8a1SJohn Marino 		X509_PURPOSE *xptmp;
1785f5b1c8a1SJohn Marino 		if (!argn)
1786f5b1c8a1SJohn Marino 			*badarg = 1;
1787f5b1c8a1SJohn Marino 		else {
1788f5b1c8a1SJohn Marino 			i = X509_PURPOSE_get_by_sname(argn);
1789f5b1c8a1SJohn Marino 			if (i < 0) {
1790f5b1c8a1SJohn Marino 				BIO_printf(err, "unrecognized purpose\n");
1791f5b1c8a1SJohn Marino 				*badarg = 1;
1792f5b1c8a1SJohn Marino 			} else {
1793f5b1c8a1SJohn Marino 				xptmp = X509_PURPOSE_get0(i);
1794f5b1c8a1SJohn Marino 				purpose = X509_PURPOSE_get_id(xptmp);
1795f5b1c8a1SJohn Marino 			}
1796f5b1c8a1SJohn Marino 		}
1797f5b1c8a1SJohn Marino 		(*pargs)++;
1798f5b1c8a1SJohn Marino 	} else if (strcmp(arg, "-verify_depth") == 0) {
1799f5b1c8a1SJohn Marino 		if (!argn)
1800f5b1c8a1SJohn Marino 			*badarg = 1;
1801f5b1c8a1SJohn Marino 		else {
1802f5b1c8a1SJohn Marino 			depth = strtonum(argn, 1, INT_MAX, &errstr);
1803f5b1c8a1SJohn Marino 			if (errstr) {
1804f5b1c8a1SJohn Marino 				BIO_printf(err, "invalid depth %s: %s\n",
1805f5b1c8a1SJohn Marino 				    argn, errstr);
1806f5b1c8a1SJohn Marino 				*badarg = 1;
1807f5b1c8a1SJohn Marino 			}
1808f5b1c8a1SJohn Marino 		}
1809f5b1c8a1SJohn Marino 		(*pargs)++;
1810f5b1c8a1SJohn Marino 	} else if (strcmp(arg, "-attime") == 0) {
1811f5b1c8a1SJohn Marino 		if (!argn)
1812f5b1c8a1SJohn Marino 			*badarg = 1;
1813f5b1c8a1SJohn Marino 		else {
1814f5b1c8a1SJohn Marino 			long long timestamp;
1815f5b1c8a1SJohn Marino 			/*
1816f5b1c8a1SJohn Marino 			 * interpret the -attime argument as seconds since
1817f5b1c8a1SJohn Marino 			 * Epoch
1818f5b1c8a1SJohn Marino 			 */
1819f5b1c8a1SJohn Marino 			if (sscanf(argn, "%lli", &timestamp) != 1) {
1820f5b1c8a1SJohn Marino 				BIO_printf(bio_err,
1821f5b1c8a1SJohn Marino 				    "Error parsing timestamp %s\n",
1822f5b1c8a1SJohn Marino 				    argn);
1823f5b1c8a1SJohn Marino 				*badarg = 1;
1824f5b1c8a1SJohn Marino 			}
1825f5b1c8a1SJohn Marino 			/* XXX 2038 truncation */
1826f5b1c8a1SJohn Marino 			at_time = (time_t) timestamp;
1827f5b1c8a1SJohn Marino 		}
1828f5b1c8a1SJohn Marino 		(*pargs)++;
1829f5b1c8a1SJohn Marino 	} else if (!strcmp(arg, "-ignore_critical"))
1830f5b1c8a1SJohn Marino 		flags |= X509_V_FLAG_IGNORE_CRITICAL;
1831f5b1c8a1SJohn Marino 	else if (!strcmp(arg, "-issuer_checks"))
1832f5b1c8a1SJohn Marino 		flags |= X509_V_FLAG_CB_ISSUER_CHECK;
1833f5b1c8a1SJohn Marino 	else if (!strcmp(arg, "-crl_check"))
1834f5b1c8a1SJohn Marino 		flags |= X509_V_FLAG_CRL_CHECK;
1835f5b1c8a1SJohn Marino 	else if (!strcmp(arg, "-crl_check_all"))
1836f5b1c8a1SJohn Marino 		flags |= X509_V_FLAG_CRL_CHECK | X509_V_FLAG_CRL_CHECK_ALL;
1837f5b1c8a1SJohn Marino 	else if (!strcmp(arg, "-policy_check"))
1838f5b1c8a1SJohn Marino 		flags |= X509_V_FLAG_POLICY_CHECK;
1839f5b1c8a1SJohn Marino 	else if (!strcmp(arg, "-explicit_policy"))
1840f5b1c8a1SJohn Marino 		flags |= X509_V_FLAG_EXPLICIT_POLICY;
1841*de0e0e4dSAntonio Huete Jimenez 	else if (!strcmp(arg, "-legacy_verify"))
1842*de0e0e4dSAntonio Huete Jimenez 		flags |= X509_V_FLAG_LEGACY_VERIFY;
1843f5b1c8a1SJohn Marino 	else if (!strcmp(arg, "-inhibit_any"))
1844f5b1c8a1SJohn Marino 		flags |= X509_V_FLAG_INHIBIT_ANY;
1845f5b1c8a1SJohn Marino 	else if (!strcmp(arg, "-inhibit_map"))
1846f5b1c8a1SJohn Marino 		flags |= X509_V_FLAG_INHIBIT_MAP;
1847f5b1c8a1SJohn Marino 	else if (!strcmp(arg, "-x509_strict"))
1848f5b1c8a1SJohn Marino 		flags |= X509_V_FLAG_X509_STRICT;
1849f5b1c8a1SJohn Marino 	else if (!strcmp(arg, "-extended_crl"))
1850f5b1c8a1SJohn Marino 		flags |= X509_V_FLAG_EXTENDED_CRL_SUPPORT;
1851f5b1c8a1SJohn Marino 	else if (!strcmp(arg, "-use_deltas"))
1852f5b1c8a1SJohn Marino 		flags |= X509_V_FLAG_USE_DELTAS;
1853f5b1c8a1SJohn Marino 	else if (!strcmp(arg, "-policy_print"))
1854f5b1c8a1SJohn Marino 		flags |= X509_V_FLAG_NOTIFY_POLICY;
1855f5b1c8a1SJohn Marino 	else if (!strcmp(arg, "-check_ss_sig"))
1856f5b1c8a1SJohn Marino 		flags |= X509_V_FLAG_CHECK_SS_SIGNATURE;
1857f5b1c8a1SJohn Marino 	else
1858f5b1c8a1SJohn Marino 		return 0;
1859f5b1c8a1SJohn Marino 
1860f5b1c8a1SJohn Marino 	if (*badarg) {
1861f5b1c8a1SJohn Marino 		X509_VERIFY_PARAM_free(*pm);
1862f5b1c8a1SJohn Marino 		*pm = NULL;
1863f5b1c8a1SJohn Marino 		goto end;
1864f5b1c8a1SJohn Marino 	}
1865f5b1c8a1SJohn Marino 	if (!*pm && !(*pm = X509_VERIFY_PARAM_new())) {
1866f5b1c8a1SJohn Marino 		*badarg = 1;
1867f5b1c8a1SJohn Marino 		goto end;
1868f5b1c8a1SJohn Marino 	}
1869f5b1c8a1SJohn Marino 	if (otmp) {
1870f5b1c8a1SJohn Marino 		X509_VERIFY_PARAM_add0_policy(*pm, otmp);
1871f5b1c8a1SJohn Marino 		otmp = NULL;
1872f5b1c8a1SJohn Marino 	}
1873f5b1c8a1SJohn Marino 	if (flags)
1874f5b1c8a1SJohn Marino 		X509_VERIFY_PARAM_set_flags(*pm, flags);
1875f5b1c8a1SJohn Marino 
1876f5b1c8a1SJohn Marino 	if (purpose)
1877f5b1c8a1SJohn Marino 		X509_VERIFY_PARAM_set_purpose(*pm, purpose);
1878f5b1c8a1SJohn Marino 
1879f5b1c8a1SJohn Marino 	if (depth >= 0)
1880f5b1c8a1SJohn Marino 		X509_VERIFY_PARAM_set_depth(*pm, depth);
1881f5b1c8a1SJohn Marino 
1882f5b1c8a1SJohn Marino 	if (at_time)
1883f5b1c8a1SJohn Marino 		X509_VERIFY_PARAM_set_time(*pm, at_time);
1884f5b1c8a1SJohn Marino 
1885f5b1c8a1SJohn Marino  end:
1886f5b1c8a1SJohn Marino 	(*pargs)++;
1887f5b1c8a1SJohn Marino 
1888f5b1c8a1SJohn Marino 	if (pargc)
1889f5b1c8a1SJohn Marino 		*pargc -= *pargs - oldargs;
1890f5b1c8a1SJohn Marino 
1891f5b1c8a1SJohn Marino 	ASN1_OBJECT_free(otmp);
1892f5b1c8a1SJohn Marino 	return 1;
1893f5b1c8a1SJohn Marino }
1894f5b1c8a1SJohn Marino 
1895f5b1c8a1SJohn Marino /* Read whole contents of a BIO into an allocated memory buffer and
1896f5b1c8a1SJohn Marino  * return it.
1897f5b1c8a1SJohn Marino  */
1898f5b1c8a1SJohn Marino 
1899f5b1c8a1SJohn Marino int
bio_to_mem(unsigned char ** out,int maxlen,BIO * in)1900f5b1c8a1SJohn Marino bio_to_mem(unsigned char **out, int maxlen, BIO *in)
1901f5b1c8a1SJohn Marino {
1902f5b1c8a1SJohn Marino 	BIO *mem;
1903f5b1c8a1SJohn Marino 	int len, ret;
1904f5b1c8a1SJohn Marino 	unsigned char tbuf[1024];
1905f5b1c8a1SJohn Marino 
1906f5b1c8a1SJohn Marino 	mem = BIO_new(BIO_s_mem());
1907f5b1c8a1SJohn Marino 	if (!mem)
1908f5b1c8a1SJohn Marino 		return -1;
1909f5b1c8a1SJohn Marino 	for (;;) {
1910f5b1c8a1SJohn Marino 		if ((maxlen != -1) && maxlen < 1024)
1911f5b1c8a1SJohn Marino 			len = maxlen;
1912f5b1c8a1SJohn Marino 		else
1913f5b1c8a1SJohn Marino 			len = 1024;
1914f5b1c8a1SJohn Marino 		len = BIO_read(in, tbuf, len);
1915f5b1c8a1SJohn Marino 		if (len <= 0)
1916f5b1c8a1SJohn Marino 			break;
1917f5b1c8a1SJohn Marino 		if (BIO_write(mem, tbuf, len) != len) {
1918f5b1c8a1SJohn Marino 			BIO_free(mem);
1919f5b1c8a1SJohn Marino 			return -1;
1920f5b1c8a1SJohn Marino 		}
1921f5b1c8a1SJohn Marino 		maxlen -= len;
1922f5b1c8a1SJohn Marino 
1923f5b1c8a1SJohn Marino 		if (maxlen == 0)
1924f5b1c8a1SJohn Marino 			break;
1925f5b1c8a1SJohn Marino 	}
1926f5b1c8a1SJohn Marino 	ret = BIO_get_mem_data(mem, (char **) out);
1927f5b1c8a1SJohn Marino 	BIO_set_flags(mem, BIO_FLAGS_MEM_RDONLY);
1928f5b1c8a1SJohn Marino 	BIO_free(mem);
1929f5b1c8a1SJohn Marino 	return ret;
1930f5b1c8a1SJohn Marino }
1931f5b1c8a1SJohn Marino 
1932f5b1c8a1SJohn Marino int
pkey_ctrl_string(EVP_PKEY_CTX * ctx,char * value)1933f5b1c8a1SJohn Marino pkey_ctrl_string(EVP_PKEY_CTX *ctx, char *value)
1934f5b1c8a1SJohn Marino {
1935f5b1c8a1SJohn Marino 	int rv;
1936f5b1c8a1SJohn Marino 	char *stmp, *vtmp = NULL;
1937f5b1c8a1SJohn Marino 
1938f5b1c8a1SJohn Marino 	if (value == NULL)
1939f5b1c8a1SJohn Marino 		return -1;
1940f5b1c8a1SJohn Marino 	stmp = strdup(value);
1941f5b1c8a1SJohn Marino 	if (!stmp)
1942f5b1c8a1SJohn Marino 		return -1;
1943f5b1c8a1SJohn Marino 	vtmp = strchr(stmp, ':');
1944f5b1c8a1SJohn Marino 	if (vtmp) {
1945f5b1c8a1SJohn Marino 		*vtmp = 0;
1946f5b1c8a1SJohn Marino 		vtmp++;
1947f5b1c8a1SJohn Marino 	}
1948f5b1c8a1SJohn Marino 	rv = EVP_PKEY_CTX_ctrl_str(ctx, stmp, vtmp);
1949f5b1c8a1SJohn Marino 	free(stmp);
1950f5b1c8a1SJohn Marino 
1951f5b1c8a1SJohn Marino 	return rv;
1952f5b1c8a1SJohn Marino }
1953f5b1c8a1SJohn Marino 
1954f5b1c8a1SJohn Marino static void
nodes_print(BIO * out,const char * name,STACK_OF (X509_POLICY_NODE)* nodes)1955f5b1c8a1SJohn Marino nodes_print(BIO *out, const char *name, STACK_OF(X509_POLICY_NODE) *nodes)
1956f5b1c8a1SJohn Marino {
1957f5b1c8a1SJohn Marino 	X509_POLICY_NODE *node;
1958f5b1c8a1SJohn Marino 	int i;
1959f5b1c8a1SJohn Marino 
1960f5b1c8a1SJohn Marino 	BIO_printf(out, "%s Policies:", name);
1961f5b1c8a1SJohn Marino 	if (nodes) {
1962f5b1c8a1SJohn Marino 		BIO_puts(out, "\n");
1963f5b1c8a1SJohn Marino 		for (i = 0; i < sk_X509_POLICY_NODE_num(nodes); i++) {
1964f5b1c8a1SJohn Marino 			node = sk_X509_POLICY_NODE_value(nodes, i);
1965f5b1c8a1SJohn Marino 			X509_POLICY_NODE_print(out, node, 2);
1966f5b1c8a1SJohn Marino 		}
1967f5b1c8a1SJohn Marino 	} else
1968f5b1c8a1SJohn Marino 		BIO_puts(out, " <empty>\n");
1969f5b1c8a1SJohn Marino }
1970f5b1c8a1SJohn Marino 
1971f5b1c8a1SJohn Marino void
policies_print(BIO * out,X509_STORE_CTX * ctx)1972f5b1c8a1SJohn Marino policies_print(BIO *out, X509_STORE_CTX *ctx)
1973f5b1c8a1SJohn Marino {
1974f5b1c8a1SJohn Marino 	X509_POLICY_TREE *tree;
1975f5b1c8a1SJohn Marino 	int explicit_policy;
1976f5b1c8a1SJohn Marino 	int free_out = 0;
1977f5b1c8a1SJohn Marino 
1978f5b1c8a1SJohn Marino 	if (out == NULL) {
1979f5b1c8a1SJohn Marino 		out = BIO_new_fp(stderr, BIO_NOCLOSE);
1980f5b1c8a1SJohn Marino 		free_out = 1;
1981f5b1c8a1SJohn Marino 	}
1982f5b1c8a1SJohn Marino 	tree = X509_STORE_CTX_get0_policy_tree(ctx);
1983f5b1c8a1SJohn Marino 	explicit_policy = X509_STORE_CTX_get_explicit_policy(ctx);
1984f5b1c8a1SJohn Marino 
1985f5b1c8a1SJohn Marino 	BIO_printf(out, "Require explicit Policy: %s\n",
1986f5b1c8a1SJohn Marino 	    explicit_policy ? "True" : "False");
1987f5b1c8a1SJohn Marino 
1988f5b1c8a1SJohn Marino 	nodes_print(out, "Authority", X509_policy_tree_get0_policies(tree));
1989f5b1c8a1SJohn Marino 	nodes_print(out, "User", X509_policy_tree_get0_user_policies(tree));
199072c33676SMaxim Ag 
1991f5b1c8a1SJohn Marino 	if (free_out)
1992f5b1c8a1SJohn Marino 		BIO_free(out);
1993f5b1c8a1SJohn Marino }
1994f5b1c8a1SJohn Marino 
199572c33676SMaxim Ag /*
199672c33676SMaxim Ag  * next_protos_parse parses a comma separated list of strings into a string
1997f5b1c8a1SJohn Marino  * in a format suitable for passing to SSL_CTX_set_next_protos_advertised.
1998f5b1c8a1SJohn Marino  *   outlen: (output) set to the length of the resulting buffer on success.
1999f5b1c8a1SJohn Marino  *   err: (maybe NULL) on failure, an error message line is written to this BIO.
2000f5b1c8a1SJohn Marino  *   in: a NUL termianted string like "abc,def,ghi"
2001f5b1c8a1SJohn Marino  *
2002f5b1c8a1SJohn Marino  *   returns: a malloced buffer or NULL on failure.
2003f5b1c8a1SJohn Marino  */
2004f5b1c8a1SJohn Marino unsigned char *
next_protos_parse(unsigned short * outlen,const char * in)2005f5b1c8a1SJohn Marino next_protos_parse(unsigned short *outlen, const char *in)
2006f5b1c8a1SJohn Marino {
2007f5b1c8a1SJohn Marino 	size_t len;
2008f5b1c8a1SJohn Marino 	unsigned char *out;
2009f5b1c8a1SJohn Marino 	size_t i, start = 0;
2010f5b1c8a1SJohn Marino 
2011f5b1c8a1SJohn Marino 	len = strlen(in);
2012f5b1c8a1SJohn Marino 	if (len >= 65535)
2013f5b1c8a1SJohn Marino 		return NULL;
2014f5b1c8a1SJohn Marino 
2015f5b1c8a1SJohn Marino 	out = malloc(strlen(in) + 1);
2016f5b1c8a1SJohn Marino 	if (!out)
2017f5b1c8a1SJohn Marino 		return NULL;
2018f5b1c8a1SJohn Marino 
2019f5b1c8a1SJohn Marino 	for (i = 0; i <= len; ++i) {
2020f5b1c8a1SJohn Marino 		if (i == len || in[i] == ',') {
2021f5b1c8a1SJohn Marino 			if (i - start > 255) {
2022f5b1c8a1SJohn Marino 				free(out);
2023f5b1c8a1SJohn Marino 				return NULL;
2024f5b1c8a1SJohn Marino 			}
2025f5b1c8a1SJohn Marino 			out[start] = i - start;
2026f5b1c8a1SJohn Marino 			start = i + 1;
2027f5b1c8a1SJohn Marino 		} else
2028f5b1c8a1SJohn Marino 			out[i + 1] = in[i];
2029f5b1c8a1SJohn Marino 	}
2030f5b1c8a1SJohn Marino 
2031f5b1c8a1SJohn Marino 	*outlen = len + 1;
2032f5b1c8a1SJohn Marino 	return out;
2033f5b1c8a1SJohn Marino }
2034f5b1c8a1SJohn Marino 
2035f5b1c8a1SJohn Marino int
app_isdir(const char * name)2036f5b1c8a1SJohn Marino app_isdir(const char *name)
2037f5b1c8a1SJohn Marino {
2038f5b1c8a1SJohn Marino 	struct stat st;
2039f5b1c8a1SJohn Marino 
2040f5b1c8a1SJohn Marino 	if (stat(name, &st) == 0)
2041f5b1c8a1SJohn Marino 		return S_ISDIR(st.st_mode);
2042f5b1c8a1SJohn Marino 	return -1;
2043f5b1c8a1SJohn Marino }
2044f5b1c8a1SJohn Marino 
2045f5b1c8a1SJohn Marino #define OPTION_WIDTH 18
2046f5b1c8a1SJohn Marino 
2047f5b1c8a1SJohn Marino void
options_usage(const struct option * opts)2048cca6fc52SDaniel Fojt options_usage(const struct option *opts)
2049f5b1c8a1SJohn Marino {
2050f5b1c8a1SJohn Marino 	const char *p, *q;
2051f5b1c8a1SJohn Marino 	char optstr[32];
2052f5b1c8a1SJohn Marino 	int i;
2053f5b1c8a1SJohn Marino 
2054f5b1c8a1SJohn Marino 	for (i = 0; opts[i].name != NULL; i++) {
2055f5b1c8a1SJohn Marino 		if (opts[i].desc == NULL)
2056f5b1c8a1SJohn Marino 			continue;
2057f5b1c8a1SJohn Marino 
2058f5b1c8a1SJohn Marino 		snprintf(optstr, sizeof(optstr), "-%s %s", opts[i].name,
2059f5b1c8a1SJohn Marino 		    (opts[i].argname != NULL) ? opts[i].argname : "");
2060f5b1c8a1SJohn Marino 		fprintf(stderr, " %-*s", OPTION_WIDTH, optstr);
2061f5b1c8a1SJohn Marino 		if (strlen(optstr) > OPTION_WIDTH)
2062f5b1c8a1SJohn Marino 			fprintf(stderr, "\n %-*s", OPTION_WIDTH, "");
2063f5b1c8a1SJohn Marino 
2064f5b1c8a1SJohn Marino 		p = opts[i].desc;
2065f5b1c8a1SJohn Marino 		while ((q = strchr(p, '\n')) != NULL) {
2066f5b1c8a1SJohn Marino 			fprintf(stderr, " %.*s", (int)(q - p), p);
2067f5b1c8a1SJohn Marino 			fprintf(stderr, "\n %-*s", OPTION_WIDTH, "");
2068f5b1c8a1SJohn Marino 			p = q + 1;
2069f5b1c8a1SJohn Marino 		}
2070f5b1c8a1SJohn Marino 		fprintf(stderr, " %s\n", p);
2071f5b1c8a1SJohn Marino 	}
2072f5b1c8a1SJohn Marino }
2073f5b1c8a1SJohn Marino 
2074f5b1c8a1SJohn Marino int
options_parse(int argc,char ** argv,const struct option * opts,char ** unnamed,int * argsused)2075cca6fc52SDaniel Fojt options_parse(int argc, char **argv, const struct option *opts, char **unnamed,
2076f5b1c8a1SJohn Marino     int *argsused)
2077f5b1c8a1SJohn Marino {
2078f5b1c8a1SJohn Marino 	const char *errstr;
2079cca6fc52SDaniel Fojt 	const struct option *opt;
2080f5b1c8a1SJohn Marino 	long long val;
2081f5b1c8a1SJohn Marino 	char *arg, *p;
2082f5b1c8a1SJohn Marino 	int fmt, used;
2083f5b1c8a1SJohn Marino 	int ord = 0;
2084f5b1c8a1SJohn Marino 	int i, j;
2085f5b1c8a1SJohn Marino 
2086f5b1c8a1SJohn Marino 	if (unnamed != NULL)
2087f5b1c8a1SJohn Marino 		*unnamed = NULL;
2088f5b1c8a1SJohn Marino 
2089f5b1c8a1SJohn Marino 	for (i = 1; i < argc; i++) {
2090f5b1c8a1SJohn Marino 		p = arg = argv[i];
2091f5b1c8a1SJohn Marino 
2092f5b1c8a1SJohn Marino 		/* Single unnamed argument (without leading hyphen). */
2093f5b1c8a1SJohn Marino 		if (*p++ != '-') {
2094f5b1c8a1SJohn Marino 			if (argsused != NULL)
2095f5b1c8a1SJohn Marino 				goto done;
2096f5b1c8a1SJohn Marino 			if (unnamed == NULL)
2097f5b1c8a1SJohn Marino 				goto unknown;
2098f5b1c8a1SJohn Marino 			if (*unnamed != NULL)
2099f5b1c8a1SJohn Marino 				goto toomany;
2100f5b1c8a1SJohn Marino 			*unnamed = arg;
2101f5b1c8a1SJohn Marino 			continue;
2102f5b1c8a1SJohn Marino 		}
2103f5b1c8a1SJohn Marino 
2104f5b1c8a1SJohn Marino 		/* End of named options (single hyphen). */
2105f5b1c8a1SJohn Marino 		if (*p == '\0') {
2106f5b1c8a1SJohn Marino 			if (++i >= argc)
2107f5b1c8a1SJohn Marino 				goto done;
2108f5b1c8a1SJohn Marino 			if (argsused != NULL)
2109f5b1c8a1SJohn Marino 				goto done;
2110f5b1c8a1SJohn Marino 			if (unnamed != NULL && i == argc - 1) {
2111f5b1c8a1SJohn Marino 				if (*unnamed != NULL)
2112f5b1c8a1SJohn Marino 					goto toomany;
2113f5b1c8a1SJohn Marino 				*unnamed = argv[i];
2114f5b1c8a1SJohn Marino 				continue;
2115f5b1c8a1SJohn Marino 			}
2116f5b1c8a1SJohn Marino 			goto unknown;
2117f5b1c8a1SJohn Marino 		}
2118f5b1c8a1SJohn Marino 
2119f5b1c8a1SJohn Marino 		/* See if there is a matching option... */
2120f5b1c8a1SJohn Marino 		for (j = 0; opts[j].name != NULL; j++) {
2121f5b1c8a1SJohn Marino 			if (strcmp(p, opts[j].name) == 0)
2122f5b1c8a1SJohn Marino 				break;
2123f5b1c8a1SJohn Marino 		}
2124f5b1c8a1SJohn Marino 		opt = &opts[j];
2125f5b1c8a1SJohn Marino 		if (opt->name == NULL && opt->type == 0)
2126f5b1c8a1SJohn Marino 			goto unknown;
2127f5b1c8a1SJohn Marino 
2128f5b1c8a1SJohn Marino 		if (opt->type == OPTION_ARG ||
2129f5b1c8a1SJohn Marino 		    opt->type == OPTION_ARG_FORMAT ||
2130f5b1c8a1SJohn Marino 		    opt->type == OPTION_ARG_FUNC ||
2131f5b1c8a1SJohn Marino 		    opt->type == OPTION_ARG_INT ||
213272c33676SMaxim Ag 		    opt->type == OPTION_ARG_LONG ||
213372c33676SMaxim Ag 		    opt->type == OPTION_ARG_TIME) {
2134f5b1c8a1SJohn Marino 			if (++i >= argc) {
2135f5b1c8a1SJohn Marino 				fprintf(stderr, "missing %s argument for -%s\n",
2136f5b1c8a1SJohn Marino 				    opt->argname, opt->name);
2137f5b1c8a1SJohn Marino 				return (1);
2138f5b1c8a1SJohn Marino 			}
2139f5b1c8a1SJohn Marino 		}
2140f5b1c8a1SJohn Marino 
2141f5b1c8a1SJohn Marino 		switch (opt->type) {
2142f5b1c8a1SJohn Marino 		case OPTION_ARG:
2143f5b1c8a1SJohn Marino 			*opt->opt.arg = argv[i];
2144f5b1c8a1SJohn Marino 			break;
2145f5b1c8a1SJohn Marino 
2146f5b1c8a1SJohn Marino 		case OPTION_ARGV_FUNC:
2147f5b1c8a1SJohn Marino 			if (opt->opt.argvfunc(argc - i, &argv[i], &used) != 0)
2148f5b1c8a1SJohn Marino 				return (1);
2149f5b1c8a1SJohn Marino 			i += used - 1;
2150f5b1c8a1SJohn Marino 			break;
2151f5b1c8a1SJohn Marino 
2152f5b1c8a1SJohn Marino 		case OPTION_ARG_FORMAT:
2153f5b1c8a1SJohn Marino 			fmt = str2fmt(argv[i]);
2154f5b1c8a1SJohn Marino 			if (fmt == FORMAT_UNDEF) {
2155f5b1c8a1SJohn Marino 				fprintf(stderr, "unknown %s '%s' for -%s\n",
2156f5b1c8a1SJohn Marino 				    opt->argname, argv[i], opt->name);
2157f5b1c8a1SJohn Marino 				return (1);
2158f5b1c8a1SJohn Marino 			}
2159f5b1c8a1SJohn Marino 			*opt->opt.value = fmt;
2160f5b1c8a1SJohn Marino 			break;
2161f5b1c8a1SJohn Marino 
2162f5b1c8a1SJohn Marino 		case OPTION_ARG_FUNC:
2163f5b1c8a1SJohn Marino 			if (opt->opt.argfunc(argv[i]) != 0)
2164f5b1c8a1SJohn Marino 				return (1);
2165f5b1c8a1SJohn Marino 			break;
2166f5b1c8a1SJohn Marino 
2167f5b1c8a1SJohn Marino 		case OPTION_ARG_INT:
2168f5b1c8a1SJohn Marino 			val = strtonum(argv[i], 0, INT_MAX, &errstr);
2169f5b1c8a1SJohn Marino 			if (errstr != NULL) {
2170f5b1c8a1SJohn Marino 				fprintf(stderr, "%s %s argument for -%s\n",
2171f5b1c8a1SJohn Marino 				    errstr, opt->argname, opt->name);
2172f5b1c8a1SJohn Marino 				return (1);
2173f5b1c8a1SJohn Marino 			}
2174f5b1c8a1SJohn Marino 			*opt->opt.value = (int)val;
2175f5b1c8a1SJohn Marino 			break;
2176f5b1c8a1SJohn Marino 
2177f5b1c8a1SJohn Marino 		case OPTION_ARG_LONG:
2178f5b1c8a1SJohn Marino 			val = strtonum(argv[i], 0, LONG_MAX, &errstr);
2179f5b1c8a1SJohn Marino 			if (errstr != NULL) {
2180f5b1c8a1SJohn Marino 				fprintf(stderr, "%s %s argument for -%s\n",
2181f5b1c8a1SJohn Marino 				    errstr, opt->argname, opt->name);
2182f5b1c8a1SJohn Marino 				return (1);
2183f5b1c8a1SJohn Marino 			}
2184f5b1c8a1SJohn Marino 			*opt->opt.lvalue = (long)val;
2185f5b1c8a1SJohn Marino 			break;
2186f5b1c8a1SJohn Marino 
218772c33676SMaxim Ag 		case OPTION_ARG_TIME:
218872c33676SMaxim Ag 			val = strtonum(argv[i], 0, LLONG_MAX, &errstr);
218972c33676SMaxim Ag 			if (errstr != NULL) {
219072c33676SMaxim Ag 				fprintf(stderr, "%s %s argument for -%s\n",
219172c33676SMaxim Ag 				    errstr, opt->argname, opt->name);
219272c33676SMaxim Ag 				return (1);
219372c33676SMaxim Ag 			}
219472c33676SMaxim Ag 			*opt->opt.tvalue = val;
219572c33676SMaxim Ag 			break;
219672c33676SMaxim Ag 
2197f5b1c8a1SJohn Marino 		case OPTION_DISCARD:
2198f5b1c8a1SJohn Marino 			break;
2199f5b1c8a1SJohn Marino 
2200f5b1c8a1SJohn Marino 		case OPTION_FUNC:
2201f5b1c8a1SJohn Marino 			if (opt->opt.func() != 0)
2202f5b1c8a1SJohn Marino 				return (1);
2203f5b1c8a1SJohn Marino 			break;
2204f5b1c8a1SJohn Marino 
2205f5b1c8a1SJohn Marino 		case OPTION_FLAG:
2206f5b1c8a1SJohn Marino 			*opt->opt.flag = 1;
2207f5b1c8a1SJohn Marino 			break;
2208f5b1c8a1SJohn Marino 
2209f5b1c8a1SJohn Marino 		case OPTION_FLAG_ORD:
2210f5b1c8a1SJohn Marino 			*opt->opt.flag = ++ord;
2211f5b1c8a1SJohn Marino 			break;
2212f5b1c8a1SJohn Marino 
2213f5b1c8a1SJohn Marino 		case OPTION_VALUE:
2214f5b1c8a1SJohn Marino 			*opt->opt.value = opt->value;
2215f5b1c8a1SJohn Marino 			break;
2216f5b1c8a1SJohn Marino 
2217f5b1c8a1SJohn Marino 		case OPTION_VALUE_AND:
2218f5b1c8a1SJohn Marino 			*opt->opt.value &= opt->value;
2219f5b1c8a1SJohn Marino 			break;
2220f5b1c8a1SJohn Marino 
2221f5b1c8a1SJohn Marino 		case OPTION_VALUE_OR:
2222f5b1c8a1SJohn Marino 			*opt->opt.value |= opt->value;
2223f5b1c8a1SJohn Marino 			break;
2224f5b1c8a1SJohn Marino 
22258edacedfSDaniel Fojt 		case OPTION_UL_VALUE_OR:
22268edacedfSDaniel Fojt 			*opt->opt.ulvalue |= opt->ulvalue;
22278edacedfSDaniel Fojt 			break;
22288edacedfSDaniel Fojt 
2229*de0e0e4dSAntonio Huete Jimenez 		case OPTION_ORDER:
2230*de0e0e4dSAntonio Huete Jimenez 			*opt->opt.order = ++(*opt->order);
2231*de0e0e4dSAntonio Huete Jimenez 			break;
2232*de0e0e4dSAntonio Huete Jimenez 
2233f5b1c8a1SJohn Marino 		default:
2234f5b1c8a1SJohn Marino 			fprintf(stderr, "option %s - unknown type %i\n",
2235f5b1c8a1SJohn Marino 			    opt->name, opt->type);
2236f5b1c8a1SJohn Marino 			return (1);
2237f5b1c8a1SJohn Marino 		}
2238f5b1c8a1SJohn Marino 	}
2239f5b1c8a1SJohn Marino 
2240f5b1c8a1SJohn Marino  done:
2241f5b1c8a1SJohn Marino 	if (argsused != NULL)
2242f5b1c8a1SJohn Marino 		*argsused = i;
2243f5b1c8a1SJohn Marino 
2244f5b1c8a1SJohn Marino 	return (0);
2245f5b1c8a1SJohn Marino 
2246f5b1c8a1SJohn Marino  toomany:
2247f5b1c8a1SJohn Marino 	fprintf(stderr, "too many arguments\n");
2248f5b1c8a1SJohn Marino 	return (1);
2249f5b1c8a1SJohn Marino 
2250f5b1c8a1SJohn Marino  unknown:
2251f5b1c8a1SJohn Marino 	fprintf(stderr, "unknown option '%s'\n", arg);
2252f5b1c8a1SJohn Marino 	return (1);
2253f5b1c8a1SJohn Marino }
225472c33676SMaxim Ag 
225572c33676SMaxim Ag void
show_cipher(const OBJ_NAME * name,void * arg)225672c33676SMaxim Ag show_cipher(const OBJ_NAME *name, void *arg)
225772c33676SMaxim Ag {
225872c33676SMaxim Ag 	int *n = arg;
225972c33676SMaxim Ag 
226072c33676SMaxim Ag 	if (!islower((unsigned char)*name->name))
226172c33676SMaxim Ag 		return;
226272c33676SMaxim Ag 
226372c33676SMaxim Ag 	fprintf(stderr, " -%-24s%s", name->name, (++*n % 3 != 0 ? "" : "\n"));
226472c33676SMaxim Ag }
226572c33676SMaxim Ag 
2266*de0e0e4dSAntonio Huete Jimenez int
pkey_check(BIO * out,EVP_PKEY * pkey,int (check_fn)(EVP_PKEY_CTX *),const char * desc)2267*de0e0e4dSAntonio Huete Jimenez pkey_check(BIO *out, EVP_PKEY *pkey, int (check_fn)(EVP_PKEY_CTX *),
2268*de0e0e4dSAntonio Huete Jimenez     const char *desc)
2269*de0e0e4dSAntonio Huete Jimenez {
2270*de0e0e4dSAntonio Huete Jimenez 	EVP_PKEY_CTX *ctx;
2271*de0e0e4dSAntonio Huete Jimenez 
2272*de0e0e4dSAntonio Huete Jimenez 	if ((ctx = EVP_PKEY_CTX_new(pkey, NULL)) == NULL) {
2273*de0e0e4dSAntonio Huete Jimenez 		ERR_print_errors(bio_err);
2274*de0e0e4dSAntonio Huete Jimenez 		return 0;
2275*de0e0e4dSAntonio Huete Jimenez 	}
2276*de0e0e4dSAntonio Huete Jimenez 
2277*de0e0e4dSAntonio Huete Jimenez 	if (check_fn(ctx) == 1) {
2278*de0e0e4dSAntonio Huete Jimenez 		BIO_printf(out, "%s valid\n", desc);
2279*de0e0e4dSAntonio Huete Jimenez 	} else {
2280*de0e0e4dSAntonio Huete Jimenez 		unsigned long err;
2281*de0e0e4dSAntonio Huete Jimenez 
2282*de0e0e4dSAntonio Huete Jimenez 		BIO_printf(out, "%s invalid\n", desc);
2283*de0e0e4dSAntonio Huete Jimenez 
2284*de0e0e4dSAntonio Huete Jimenez 		while ((err = ERR_get_error()) != 0)
2285*de0e0e4dSAntonio Huete Jimenez 			BIO_printf(out, "Detailed error: %s\n",
2286*de0e0e4dSAntonio Huete Jimenez 			    ERR_reason_error_string(err));
2287*de0e0e4dSAntonio Huete Jimenez 	}
2288*de0e0e4dSAntonio Huete Jimenez 
2289*de0e0e4dSAntonio Huete Jimenez 	EVP_PKEY_CTX_free(ctx);
2290*de0e0e4dSAntonio Huete Jimenez 
2291*de0e0e4dSAntonio Huete Jimenez 	return 1;
2292*de0e0e4dSAntonio Huete Jimenez }
2293