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", ×tamp) != 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