]> git.ipfire.org Git - thirdparty/openssl.git/blame - apps/apps.c
Eliminate dependency on read/write/stat in apps under _WIN32.
[thirdparty/openssl.git] / apps / apps.c
CommitLineData
d02b48c6 1/* apps/apps.c */
58964a49 2/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
d02b48c6
RE
3 * All rights reserved.
4 *
5 * This package is an SSL implementation written
6 * by Eric Young (eay@cryptsoft.com).
7 * The implementation was written so as to conform with Netscapes SSL.
8 *
9 * This library is free for commercial and non-commercial use as long as
10 * the following conditions are aheared to. The following conditions
11 * apply to all code found in this distribution, be it the RC4, RSA,
12 * lhash, DES, etc., code; not just the SSL code. The SSL documentation
13 * included with this distribution is covered by the same copyright terms
14 * except that the holder is Tim Hudson (tjh@cryptsoft.com).
15 *
16 * Copyright remains Eric Young's, and as such any Copyright notices in
17 * the code are not to be removed.
18 * If this package is used in a product, Eric Young should be given attribution
19 * as the author of the parts of the library used.
20 * This can be in the form of a textual message at program startup or
21 * in documentation (online or textual) provided with the package.
22 *
23 * Redistribution and use in source and binary forms, with or without
24 * modification, are permitted provided that the following conditions
25 * are met:
26 * 1. Redistributions of source code must retain the copyright
27 * notice, this list of conditions and the following disclaimer.
28 * 2. Redistributions in binary form must reproduce the above copyright
29 * notice, this list of conditions and the following disclaimer in the
30 * documentation and/or other materials provided with the distribution.
31 * 3. All advertising materials mentioning features or use of this software
32 * must display the following acknowledgement:
33 * "This product includes cryptographic software written by
34 * Eric Young (eay@cryptsoft.com)"
35 * The word 'cryptographic' can be left out if the rouines from the library
36 * being used are not cryptographic related :-).
37 * 4. If you include any Windows specific code (or a derivative thereof) from
38 * the apps directory (application code) you must include an acknowledgement:
39 * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
40 *
41 * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
42 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
43 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
44 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
45 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
46 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
47 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
48 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
49 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
50 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
51 * SUCH DAMAGE.
52 *
53 * The licence and distribution terms for any publically available version or
54 * derivative of this code cannot be changed. i.e. this code cannot simply be
55 * copied and put under another distribution licence
56 * [including the GNU Public Licence.]
57 */
a661b653
BM
58/* ====================================================================
59 * Copyright (c) 1998-2001 The OpenSSL Project. All rights reserved.
60 *
61 * Redistribution and use in source and binary forms, with or without
62 * modification, are permitted provided that the following conditions
63 * are met:
64 *
65 * 1. Redistributions of source code must retain the above copyright
66 * notice, this list of conditions and the following disclaimer.
67 *
68 * 2. Redistributions in binary form must reproduce the above copyright
69 * notice, this list of conditions and the following disclaimer in
70 * the documentation and/or other materials provided with the
71 * distribution.
72 *
73 * 3. All advertising materials mentioning features or use of this
74 * software must display the following acknowledgment:
75 * "This product includes software developed by the OpenSSL Project
76 * for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
77 *
78 * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
79 * endorse or promote products derived from this software without
80 * prior written permission. For written permission, please contact
81 * openssl-core@openssl.org.
82 *
83 * 5. Products derived from this software may not be called "OpenSSL"
84 * nor may "OpenSSL" appear in their names without prior written
85 * permission of the OpenSSL Project.
86 *
87 * 6. Redistributions of any form whatsoever must retain the following
88 * acknowledgment:
89 * "This product includes software developed by the OpenSSL Project
90 * for use in the OpenSSL Toolkit (http://www.openssl.org/)"
91 *
92 * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
93 * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
94 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
95 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
96 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
97 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
98 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
99 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
100 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
101 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
102 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
103 * OF THE POSSIBILITY OF SUCH DAMAGE.
104 * ====================================================================
105 *
106 * This product includes cryptographic software written by Eric Young
107 * (eay@cryptsoft.com). This product includes software written by Tim
108 * Hudson (tjh@cryptsoft.com).
109 *
110 */
d02b48c6
RE
111
112#include <stdio.h>
113#include <stdlib.h>
114#include <string.h>
115#include <sys/types.h>
116#include <sys/stat.h>
d652a095 117#include <ctype.h>
90ae4673
RL
118#include <openssl/err.h>
119#include <openssl/x509.h>
535d79da 120#include <openssl/x509v3.h>
90ae4673
RL
121#include <openssl/pem.h>
122#include <openssl/pkcs12.h>
2fe5adc3 123#include <openssl/ui.h>
90ae4673 124#include <openssl/safestack.h>
0b13e9f0 125#ifndef OPENSSL_NO_ENGINE
1372965e 126#include <openssl/engine.h>
0b13e9f0 127#endif
3eeaab4b 128#ifndef OPENSSL_NO_RSA
823a67b0 129#include <openssl/rsa.h>
3eeaab4b 130#endif
f0eae953 131#include <openssl/bn.h>
d02b48c6 132
ffa10187
AP
133#ifdef _WIN32
134#include <windows.h>
135#ifdef fileno
136#undef fileno
137#define fileno(a) (int)_fileno(a)
138#endif
139#endif
140
d610d27f
RL
141#define NON_MAIN
142#include "apps.h"
143#undef NON_MAIN
144
8ca533e3 145typedef struct {
7d727231 146 const char *name;
8ca533e3
DSH
147 unsigned long flag;
148 unsigned long mask;
149} NAME_EX_TBL;
150
2fe5adc3
RL
151static UI_METHOD *ui_method = NULL;
152
8ca533e3 153static int set_table_opts(unsigned long *flags, const char *arg, const NAME_EX_TBL *in_tbl);
535d79da 154static int set_multi_opts(unsigned long *flags, const char *arg, const NAME_EX_TBL *in_tbl);
8ca533e3 155
690ecff7 156#if !defined(OPENSSL_NO_RC4) && !defined(OPENSSL_NO_RSA)
80bb905d
RL
157/* Looks like this stuff is worth moving into separate function */
158static EVP_PKEY *
159load_netscape_key(BIO *err, BIO *key, const char *file,
160 const char *key_descrip, int format);
161#endif
162
d02b48c6 163int app_init(long mesgwin);
d02b48c6 164#ifdef undef /* never finished - probably never will be :-) */
6b691a5c 165int args_from_file(char *file, int *argc, char **argv[])
d02b48c6
RE
166 {
167 FILE *fp;
168 int num,i;
169 unsigned int len;
170 static char *buf=NULL;
171 static char **arg=NULL;
172 char *p;
173 struct stat stbuf;
174
175 if (stat(file,&stbuf) < 0) return(0);
176
177 fp=fopen(file,"r");
178 if (fp == NULL)
179 return(0);
180
181 *argc=0;
182 *argv=NULL;
183
184 len=(unsigned int)stbuf.st_size;
26a3a48d
RL
185 if (buf != NULL) OPENSSL_free(buf);
186 buf=(char *)OPENSSL_malloc(len+1);
d02b48c6
RE
187 if (buf == NULL) return(0);
188
189 len=fread(buf,1,len,fp);
190 if (len <= 1) return(0);
191 buf[len]='\0';
192
193 i=0;
194 for (p=buf; *p; p++)
195 if (*p == '\n') i++;
26a3a48d
RL
196 if (arg != NULL) OPENSSL_free(arg);
197 arg=(char **)OPENSSL_malloc(sizeof(char *)*(i*2));
d02b48c6
RE
198
199 *argv=arg;
200 num=0;
201 p=buf;
202 for (;;)
203 {
204 if (!*p) break;
205 if (*p == '#') /* comment line */
206 {
207 while (*p && (*p != '\n')) p++;
208 continue;
209 }
210 /* else we have a line */
211 *(arg++)=p;
212 num++;
213 while (*p && ((*p != ' ') && (*p != '\t') && (*p != '\n')))
214 p++;
215 if (!*p) break;
216 if (*p == '\n')
217 {
218 *(p++)='\0';
219 continue;
220 }
221 /* else it is a tab or space */
222 p++;
223 while (*p && ((*p == ' ') || (*p == '\t') || (*p == '\n')))
224 p++;
225 if (!*p) break;
226 if (*p == '\n')
227 {
228 p++;
229 continue;
230 }
231 *(arg++)=p++;
232 num++;
233 while (*p && (*p != '\n')) p++;
234 if (!*p) break;
235 /* else *p == '\n' */
236 *(p++)='\0';
237 }
238 *argc=num;
239 return(1);
240 }
241#endif
242
6b691a5c 243int str2fmt(char *s)
d02b48c6
RE
244 {
245 if ((*s == 'D') || (*s == 'd'))
246 return(FORMAT_ASN1);
247 else if ((*s == 'T') || (*s == 't'))
248 return(FORMAT_TEXT);
249 else if ((*s == 'P') || (*s == 'p'))
a0156a92
DSH
250 {
251 if (s[1] == 'V' || s[1] == 'v')
252 return FORMAT_PVK;
253 else
254 return(FORMAT_PEM);
255 }
256 else if ((*s == 'N') || (*s == 'n'))
257 return(FORMAT_NETSCAPE);
258 else if ((*s == 'S') || (*s == 's'))
259 return(FORMAT_SMIME);
260 else if ((*s == 'M') || (*s == 'm'))
261 return(FORMAT_MSBLOB);
90ae4673
RL
262 else if ((*s == '1')
263 || (strcmp(s,"PKCS12") == 0) || (strcmp(s,"pkcs12") == 0)
264 || (strcmp(s,"P12") == 0) || (strcmp(s,"p12") == 0))
265 return(FORMAT_PKCS12);
5270e702
RL
266 else if ((*s == 'E') || (*s == 'e'))
267 return(FORMAT_ENGINE);
d02b48c6
RE
268 else
269 return(FORMAT_UNDEF);
270 }
271
4d8743f4 272#if defined(OPENSSL_SYS_MSDOS) || defined(OPENSSL_SYS_WIN32) || defined(OPENSSL_SYS_WIN16) || defined(OPENSSL_SYS_NETWARE)
6b691a5c 273void program_name(char *in, char *out, int size)
d02b48c6
RE
274 {
275 int i,n;
276 char *p=NULL;
277
278 n=strlen(in);
279 /* find the last '/', '\' or ':' */
280 for (i=n-1; i>0; i--)
281 {
282 if ((in[i] == '/') || (in[i] == '\\') || (in[i] == ':'))
283 {
284 p= &(in[i+1]);
285 break;
286 }
287 }
288 if (p == NULL)
289 p=in;
290 n=strlen(p);
4d8743f4
RL
291
292#if defined(OPENSSL_SYS_NETWARE)
293 /* strip off trailing .nlm if present. */
294 if ((n > 4) && (p[n-4] == '.') &&
295 ((p[n-3] == 'n') || (p[n-3] == 'N')) &&
296 ((p[n-2] == 'l') || (p[n-2] == 'L')) &&
297 ((p[n-1] == 'm') || (p[n-1] == 'M')))
298 n-=4;
299#else
d02b48c6
RE
300 /* strip off trailing .exe if present. */
301 if ((n > 4) && (p[n-4] == '.') &&
302 ((p[n-3] == 'e') || (p[n-3] == 'E')) &&
303 ((p[n-2] == 'x') || (p[n-2] == 'X')) &&
304 ((p[n-1] == 'e') || (p[n-1] == 'E')))
305 n-=4;
4d8743f4
RL
306#endif
307
d02b48c6
RE
308 if (n > size-1)
309 n=size-1;
310
311 for (i=0; i<n; i++)
312 {
313 if ((p[i] >= 'A') && (p[i] <= 'Z'))
314 out[i]=p[i]-'A'+'a';
315 else
316 out[i]=p[i];
317 }
318 out[n]='\0';
319 }
320#else
bc36ee62 321#ifdef OPENSSL_SYS_VMS
7d7d2cbc
UM
322void program_name(char *in, char *out, int size)
323 {
324 char *p=in, *q;
325 char *chars=":]>";
326
327 while(*chars != '\0')
328 {
329 q=strrchr(p,*chars);
330 if (q > p)
331 p = q + 1;
332 chars++;
333 }
334
335 q=strrchr(p,'.');
336 if (q == NULL)
6298bf90
RL
337 q = p + strlen(p);
338 strncpy(out,p,size-1);
339 if (q-p >= size)
340 {
341 out[size-1]='\0';
342 }
343 else
344 {
345 out[q-p]='\0';
346 }
7d7d2cbc
UM
347 }
348#else
6b691a5c 349void program_name(char *in, char *out, int size)
d02b48c6
RE
350 {
351 char *p;
352
353 p=strrchr(in,'/');
354 if (p != NULL)
355 p++;
356 else
357 p=in;
54a656ef 358 BUF_strlcpy(out,p,size);
d02b48c6
RE
359 }
360#endif
7d7d2cbc 361#endif
d02b48c6 362
6b691a5c 363int chopup_args(ARGS *arg, char *buf, int *argc, char **argv[])
d02b48c6
RE
364 {
365 int num,len,i;
366 char *p;
367
368 *argc=0;
369 *argv=NULL;
370
371 len=strlen(buf);
372 i=0;
373 if (arg->count == 0)
374 {
375 arg->count=20;
26a3a48d 376 arg->data=(char **)OPENSSL_malloc(sizeof(char *)*arg->count);
d02b48c6
RE
377 }
378 for (i=0; i<arg->count; i++)
379 arg->data[i]=NULL;
380
381 num=0;
382 p=buf;
383 for (;;)
384 {
385 /* first scan over white space */
386 if (!*p) break;
387 while (*p && ((*p == ' ') || (*p == '\t') || (*p == '\n')))
388 p++;
389 if (!*p) break;
390
391 /* The start of something good :-) */
392 if (num >= arg->count)
393 {
9e1a1123
NL
394 char **tmp_p;
395 int tlen = arg->count + 20;
396 tmp_p = (char **)OPENSSL_realloc(arg->data,
397 sizeof(char *)*tlen);
398 if (tmp_p == NULL)
399 return 0;
400 arg->data = tmp_p;
401 arg->count = tlen;
402 /* initialize newly allocated data */
403 for (i = num; i < arg->count; i++)
404 arg->data[i] = NULL;
d02b48c6
RE
405 }
406 arg->data[num++]=p;
407
408 /* now look for the end of this */
409 if ((*p == '\'') || (*p == '\"')) /* scan for closing quote */
410 {
411 i= *(p++);
412 arg->data[num-1]++; /* jump over quote */
413 while (*p && (*p != i))
414 p++;
415 *p='\0';
416 }
417 else
418 {
419 while (*p && ((*p != ' ') &&
420 (*p != '\t') && (*p != '\n')))
421 p++;
422
423 if (*p == '\0')
424 p--;
425 else
426 *p='\0';
427 }
428 p++;
429 }
430 *argc=num;
431 *argv=arg->data;
432 return(1);
433 }
434
435#ifndef APP_INIT
6b691a5c 436int app_init(long mesgwin)
d02b48c6
RE
437 {
438 return(1);
439 }
440#endif
53b1899e 441
a3fe382e 442
954ef7ef
DSH
443int dump_cert_text (BIO *out, X509 *x)
444{
54a656ef
BL
445 char *p;
446
447 p=X509_NAME_oneline(X509_get_subject_name(x),NULL,0);
954ef7ef 448 BIO_puts(out,"subject=");
54a656ef
BL
449 BIO_puts(out,p);
450 OPENSSL_free(p);
954ef7ef 451
54a656ef
BL
452 p=X509_NAME_oneline(X509_get_issuer_name(x),NULL,0);
453 BIO_puts(out,"\nissuer=");
454 BIO_puts(out,p);
954ef7ef 455 BIO_puts(out,"\n");
54a656ef
BL
456 OPENSSL_free(p);
457
458 return 0;
954ef7ef 459}
a3fe382e 460
2fe5adc3
RL
461static int ui_open(UI *ui)
462 {
463 return UI_method_get_opener(UI_OpenSSL())(ui);
464 }
465static int ui_read(UI *ui, UI_STRING *uis)
466 {
467 if (UI_get_input_flags(uis) & UI_INPUT_FLAG_DEFAULT_PWD
468 && UI_get0_user_data(ui))
469 {
470 switch(UI_get_string_type(uis))
471 {
472 case UIT_PROMPT:
473 case UIT_VERIFY:
474 {
475 const char *password =
476 ((PW_CB_DATA *)UI_get0_user_data(ui))->password;
f35232e6 477 if (password && password[0] != '\0')
2fe5adc3 478 {
4f272c17 479 UI_set_result(ui, uis, password);
2fe5adc3
RL
480 return 1;
481 }
482 }
483 default:
484 break;
485 }
486 }
487 return UI_method_get_reader(UI_OpenSSL())(ui, uis);
488 }
489static int ui_write(UI *ui, UI_STRING *uis)
490 {
491 if (UI_get_input_flags(uis) & UI_INPUT_FLAG_DEFAULT_PWD
492 && UI_get0_user_data(ui))
493 {
494 switch(UI_get_string_type(uis))
495 {
496 case UIT_PROMPT:
497 case UIT_VERIFY:
498 {
499 const char *password =
500 ((PW_CB_DATA *)UI_get0_user_data(ui))->password;
f35232e6 501 if (password && password[0] != '\0')
2fe5adc3
RL
502 return 1;
503 }
504 default:
505 break;
506 }
507 }
508 return UI_method_get_writer(UI_OpenSSL())(ui, uis);
509 }
510static int ui_close(UI *ui)
511 {
512 return UI_method_get_closer(UI_OpenSSL())(ui);
513 }
40889b9c 514int setup_ui_method(void)
2fe5adc3
RL
515 {
516 ui_method = UI_create_method("OpenSSL application user interface");
517 UI_method_set_opener(ui_method, ui_open);
518 UI_method_set_reader(ui_method, ui_read);
519 UI_method_set_writer(ui_method, ui_write);
520 UI_method_set_closer(ui_method, ui_close);
521 return 0;
522 }
40889b9c 523void destroy_ui_method(void)
2c7bc88d
DSH
524 {
525 if(ui_method)
526 {
527 UI_destroy_method(ui_method);
528 ui_method = NULL;
529 }
530 }
30b4c272 531int password_callback(char *buf, int bufsiz, int verify,
2fe5adc3 532 PW_CB_DATA *cb_tmp)
30b4c272 533 {
2fe5adc3
RL
534 UI *ui = NULL;
535 int res = 0;
30b4c272
RL
536 const char *prompt_info = NULL;
537 const char *password = NULL;
2fe5adc3 538 PW_CB_DATA *cb_data = (PW_CB_DATA *)cb_tmp;
30b4c272
RL
539
540 if (cb_data)
541 {
542 if (cb_data->password)
543 password = cb_data->password;
544 if (cb_data->prompt_info)
545 prompt_info = cb_data->prompt_info;
546 }
547
b65f8513
DSH
548 if (password)
549 {
550 res = strlen(password);
551 if (res > bufsiz)
552 res = bufsiz;
553 memcpy(buf, password, res);
554 return res;
555 }
556
2fe5adc3
RL
557 ui = UI_new_method(ui_method);
558 if (ui)
559 {
2fe5adc3
RL
560 int ok = 0;
561 char *buff = NULL;
562 int ui_flags = 0;
563 char *prompt = NULL;
30b4c272 564
2fe5adc3 565 prompt = UI_construct_prompt(ui, "pass phrase",
151368cc 566 prompt_info);
30b4c272 567
2fe5adc3 568 ui_flags |= UI_INPUT_FLAG_DEFAULT_PWD;
4f272c17 569 UI_ctrl(ui, UI_CTRL_PRINT_ERRORS, 1, 0, 0);
2fe5adc3
RL
570
571 if (ok >= 0)
4f272c17
RL
572 ok = UI_add_input_string(ui,prompt,ui_flags,buf,
573 PW_MIN_LENGTH,BUFSIZ-1);
2fe5adc3
RL
574 if (ok >= 0 && verify)
575 {
576 buff = (char *)OPENSSL_malloc(bufsiz);
4f272c17
RL
577 ok = UI_add_verify_string(ui,prompt,ui_flags,buff,
578 PW_MIN_LENGTH,BUFSIZ-1, buf);
2fe5adc3
RL
579 }
580 if (ok >= 0)
4f272c17 581 do
2fe5adc3 582 {
4f272c17 583 ok = UI_process(ui);
2fe5adc3 584 }
4f272c17
RL
585 while (ok < 0 && UI_ctrl(ui, UI_CTRL_IS_REDOABLE, 0, 0, 0));
586
2fe5adc3 587 if (buff)
30b4c272 588 {
4579924b 589 OPENSSL_cleanse(buff,(unsigned int)bufsiz);
2fe5adc3 590 OPENSSL_free(buff);
30b4c272 591 }
2fe5adc3 592
4f272c17
RL
593 if (ok >= 0)
594 res = strlen(buf);
2fe5adc3 595 if (ok == -1)
30b4c272 596 {
2fe5adc3
RL
597 BIO_printf(bio_err, "User interface error\n");
598 ERR_print_errors(bio_err);
4579924b 599 OPENSSL_cleanse(buf,(unsigned int)bufsiz);
2fe5adc3 600 res = 0;
30b4c272 601 }
2fe5adc3
RL
602 if (ok == -2)
603 {
604 BIO_printf(bio_err,"aborted!\n");
4579924b 605 OPENSSL_cleanse(buf,(unsigned int)bufsiz);
2fe5adc3
RL
606 res = 0;
607 }
608 UI_free(ui);
4f272c17 609 OPENSSL_free(prompt);
30b4c272 610 }
2fe5adc3 611 return res;
30b4c272
RL
612 }
613
a3fe382e
DSH
614static char *app_get_pass(BIO *err, char *arg, int keepbio);
615
616int app_passwd(BIO *err, char *arg1, char *arg2, char **pass1, char **pass2)
617{
618 int same;
619 if(!arg2 || !arg1 || strcmp(arg1, arg2)) same = 0;
620 else same = 1;
621 if(arg1) {
622 *pass1 = app_get_pass(err, arg1, same);
623 if(!*pass1) return 0;
624 } else if(pass1) *pass1 = NULL;
625 if(arg2) {
626 *pass2 = app_get_pass(err, arg2, same ? 2 : 0);
627 if(!*pass2) return 0;
628 } else if(pass2) *pass2 = NULL;
629 return 1;
630}
631
632static char *app_get_pass(BIO *err, char *arg, int keepbio)
633{
634 char *tmp, tpass[APP_PASS_LEN];
635 static BIO *pwdbio = NULL;
636 int i;
637 if(!strncmp(arg, "pass:", 5)) return BUF_strdup(arg + 5);
638 if(!strncmp(arg, "env:", 4)) {
639 tmp = getenv(arg + 4);
640 if(!tmp) {
641 BIO_printf(err, "Can't read environment variable %s\n", arg + 4);
642 return NULL;
643 }
644 return BUF_strdup(tmp);
645 }
646 if(!keepbio || !pwdbio) {
647 if(!strncmp(arg, "file:", 5)) {
648 pwdbio = BIO_new_file(arg + 5, "r");
649 if(!pwdbio) {
650 BIO_printf(err, "Can't open file %s\n", arg + 5);
651 return NULL;
652 }
eff7cb41
AP
653#if !defined(_WIN32)
654 /*
655 * Under _WIN32, which covers even Win64 and CE, file
656 * descriptors referenced by BIO_s_fd are not inherited
657 * by child process and therefore below is not an option.
658 * It could have been an option if bss_fd.c was operating
659 * on real Windows descriptors, such as those obtained
660 * with CreateFile.
661 */
a3fe382e
DSH
662 } else if(!strncmp(arg, "fd:", 3)) {
663 BIO *btmp;
664 i = atoi(arg + 3);
665 if(i >= 0) pwdbio = BIO_new_fd(i, BIO_NOCLOSE);
666 if((i < 0) || !pwdbio) {
667 BIO_printf(err, "Can't access file descriptor %s\n", arg + 3);
668 return NULL;
669 }
670 /* Can't do BIO_gets on an fd BIO so add a buffering BIO */
671 btmp = BIO_new(BIO_f_buffer());
672 pwdbio = BIO_push(btmp, pwdbio);
eff7cb41 673#endif
a3fe382e
DSH
674 } else if(!strcmp(arg, "stdin")) {
675 pwdbio = BIO_new_fp(stdin, BIO_NOCLOSE);
676 if(!pwdbio) {
677 BIO_printf(err, "Can't open BIO for stdin\n");
678 return NULL;
679 }
680 } else {
681 BIO_printf(err, "Invalid password argument \"%s\"\n", arg);
682 return NULL;
683 }
684 }
685 i = BIO_gets(pwdbio, tpass, APP_PASS_LEN);
686 if(keepbio != 1) {
687 BIO_free_all(pwdbio);
688 pwdbio = NULL;
689 }
690 if(i <= 0) {
691 BIO_printf(err, "Error reading password from BIO\n");
692 return NULL;
693 }
694 tmp = strchr(tpass, '\n');
695 if(tmp) *tmp = 0;
696 return BUF_strdup(tpass);
697}
90ae4673 698
b7a26e6d 699int add_oid_section(BIO *err, CONF *conf)
431b0cce
RL
700{
701 char *p;
702 STACK_OF(CONF_VALUE) *sktmp;
703 CONF_VALUE *cnf;
704 int i;
b7a26e6d 705 if(!(p=NCONF_get_string(conf,NULL,"oid_section")))
2c0d1012
BM
706 {
707 ERR_clear_error();
708 return 1;
709 }
b7a26e6d 710 if(!(sktmp = NCONF_get_section(conf, p))) {
431b0cce
RL
711 BIO_printf(err, "problem loading oid section %s\n", p);
712 return 0;
713 }
714 for(i = 0; i < sk_CONF_VALUE_num(sktmp); i++) {
715 cnf = sk_CONF_VALUE_value(sktmp, i);
716 if(OBJ_create(cnf->value, cnf->name, cnf->name) == NID_undef) {
717 BIO_printf(err, "problem creating object %s=%s\n",
718 cnf->name, cnf->value);
719 return 0;
720 }
721 }
722 return 1;
723}
724
e90fadda
DSH
725static int load_pkcs12(BIO *err, BIO *in, const char *desc,
726 pem_password_cb *pem_cb, void *cb_data,
727 EVP_PKEY **pkey, X509 **cert, STACK_OF(X509) **ca)
728 {
729 const char *pass;
730 char tpass[PEM_BUFSIZE];
731 int len, ret = 0;
732 PKCS12 *p12;
733 p12 = d2i_PKCS12_bio(in, NULL);
734 if (p12 == NULL)
735 {
736 BIO_printf(err, "Error loading PKCS12 file for %s\n", desc);
3ffb8d42 737 goto die;
e90fadda
DSH
738 }
739 /* See if an empty password will do */
740 if (PKCS12_verify_mac(p12, "", 0) || PKCS12_verify_mac(p12, NULL, 0))
741 pass = "";
742 else
743 {
744 if (!pem_cb)
745 pem_cb = (pem_password_cb *)password_callback;
746 len = pem_cb(tpass, PEM_BUFSIZE, 0, cb_data);
747 if (len < 0)
748 {
749 BIO_printf(err, "Passpharse callback error for %s\n",
750 desc);
3ffb8d42 751 goto die;
e90fadda
DSH
752 }
753 if (len < PEM_BUFSIZE)
754 tpass[len] = 0;
755 if (!PKCS12_verify_mac(p12, tpass, len))
756 {
757 BIO_printf(err,
758 "Mac verify error (wrong password?) in PKCS12 file for %s\n", desc);
3ffb8d42 759 goto die;
e90fadda
DSH
760 }
761 pass = tpass;
762 }
763 ret = PKCS12_parse(p12, pass, pkey, cert, ca);
3ffb8d42 764 die:
e90fadda
DSH
765 if (p12)
766 PKCS12_free(p12);
767 return ret;
768 }
769
30b4c272
RL
770X509 *load_cert(BIO *err, const char *file, int format,
771 const char *pass, ENGINE *e, const char *cert_descrip)
90ae4673 772 {
90ae4673
RL
773 X509 *x=NULL;
774 BIO *cert;
775
776 if ((cert=BIO_new(BIO_s_file())) == NULL)
777 {
431b0cce 778 ERR_print_errors(err);
90ae4673
RL
779 goto end;
780 }
781
782 if (file == NULL)
620cea37 783 {
ffa10187 784#ifdef _IONBF
620cea37 785 setvbuf(stdin, NULL, _IONBF, 0);
ffa10187 786#endif
90ae4673 787 BIO_set_fp(cert,stdin,BIO_NOCLOSE);
620cea37 788 }
90ae4673
RL
789 else
790 {
791 if (BIO_read_filename(cert,file) <= 0)
792 {
30b4c272
RL
793 BIO_printf(err, "Error opening %s %s\n",
794 cert_descrip, file);
795 ERR_print_errors(err);
90ae4673
RL
796 goto end;
797 }
798 }
799
800 if (format == FORMAT_ASN1)
801 x=d2i_X509_bio(cert,NULL);
802 else if (format == FORMAT_NETSCAPE)
803 {
45e27385
DSH
804 NETSCAPE_X509 *nx;
805 nx=ASN1_item_d2i_bio(ASN1_ITEM_rptr(NETSCAPE_X509),cert,NULL);
806 if (nx == NULL)
90ae4673 807 goto end;
90ae4673 808
45e27385
DSH
809 if ((strncmp(NETSCAPE_CERT_HDR,(char *)nx->header->data,
810 nx->header->length) != 0))
90ae4673 811 {
45e27385 812 NETSCAPE_X509_free(nx);
431b0cce 813 BIO_printf(err,"Error reading header on certificate\n");
90ae4673
RL
814 goto end;
815 }
45e27385
DSH
816 x=nx->cert;
817 nx->cert = NULL;
818 NETSCAPE_X509_free(nx);
90ae4673
RL
819 }
820 else if (format == FORMAT_PEM)
30b4c272
RL
821 x=PEM_read_bio_X509_AUX(cert,NULL,
822 (pem_password_cb *)password_callback, NULL);
90ae4673
RL
823 else if (format == FORMAT_PKCS12)
824 {
e90fadda
DSH
825 if (!load_pkcs12(err, cert,cert_descrip, NULL, NULL,
826 NULL, &x, NULL))
827 goto end;
90ae4673
RL
828 }
829 else {
30b4c272
RL
830 BIO_printf(err,"bad input format specified for %s\n",
831 cert_descrip);
90ae4673
RL
832 goto end;
833 }
834end:
835 if (x == NULL)
836 {
431b0cce
RL
837 BIO_printf(err,"unable to load certificate\n");
838 ERR_print_errors(err);
90ae4673 839 }
90ae4673 840 if (cert != NULL) BIO_free(cert);
90ae4673
RL
841 return(x);
842 }
843
da9b9724 844EVP_PKEY *load_key(BIO *err, const char *file, int format, int maybe_stdin,
30b4c272 845 const char *pass, ENGINE *e, const char *key_descrip)
90ae4673
RL
846 {
847 BIO *key=NULL;
848 EVP_PKEY *pkey=NULL;
30b4c272
RL
849 PW_CB_DATA cb_data;
850
851 cb_data.password = pass;
852 cb_data.prompt_info = file;
90ae4673 853
da9b9724 854 if (file == NULL && (!maybe_stdin || format == FORMAT_ENGINE))
90ae4673 855 {
431b0cce 856 BIO_printf(err,"no keyfile specified\n");
90ae4673
RL
857 goto end;
858 }
0b13e9f0 859#ifndef OPENSSL_NO_ENGINE
32d862ed
RL
860 if (format == FORMAT_ENGINE)
861 {
862 if (!e)
863 BIO_printf(bio_err,"no engine specified\n");
864 else
30b4c272 865 pkey = ENGINE_load_private_key(e, file,
2fe5adc3 866 ui_method, &cb_data);
32d862ed
RL
867 goto end;
868 }
0b13e9f0 869#endif
90ae4673
RL
870 key=BIO_new(BIO_s_file());
871 if (key == NULL)
872 {
431b0cce 873 ERR_print_errors(err);
90ae4673
RL
874 goto end;
875 }
da9b9724 876 if (file == NULL && maybe_stdin)
90ae4673 877 {
ffa10187 878#ifdef _IONBF
da9b9724 879 setvbuf(stdin, NULL, _IONBF, 0);
ffa10187 880#endif
da9b9724 881 BIO_set_fp(key,stdin,BIO_NOCLOSE);
90ae4673 882 }
da9b9724
RL
883 else
884 if (BIO_read_filename(key,file) <= 0)
885 {
886 BIO_printf(err, "Error opening %s %s\n",
887 key_descrip, file);
888 ERR_print_errors(err);
889 goto end;
890 }
90ae4673
RL
891 if (format == FORMAT_ASN1)
892 {
893 pkey=d2i_PrivateKey_bio(key, NULL);
894 }
895 else if (format == FORMAT_PEM)
896 {
30b4c272
RL
897 pkey=PEM_read_bio_PrivateKey(key,NULL,
898 (pem_password_cb *)password_callback, &cb_data);
90ae4673 899 }
690ecff7 900#if !defined(OPENSSL_NO_RC4) && !defined(OPENSSL_NO_RSA)
80bb905d
RL
901 else if (format == FORMAT_NETSCAPE || format == FORMAT_IISSGC)
902 pkey = load_netscape_key(err, key, file, key_descrip, format);
903#endif
90ae4673
RL
904 else if (format == FORMAT_PKCS12)
905 {
e90fadda
DSH
906 if (!load_pkcs12(err, key, key_descrip,
907 (pem_password_cb *)password_callback, &cb_data,
908 &pkey, NULL, NULL))
909 goto end;
90ae4673 910 }
a0156a92
DSH
911 else if (format == FORMAT_MSBLOB)
912 pkey = b2i_PrivateKey_bio(key);
913 else if (format == FORMAT_PVK)
914 pkey = b2i_PVK_bio(key, (pem_password_cb *)password_callback,
915 &cb_data);
90ae4673
RL
916 else
917 {
30b4c272 918 BIO_printf(err,"bad input format specified for key file\n");
90ae4673
RL
919 goto end;
920 }
921 end:
922 if (key != NULL) BIO_free(key);
923 if (pkey == NULL)
30b4c272 924 BIO_printf(err,"unable to load %s\n", key_descrip);
90ae4673
RL
925 return(pkey);
926 }
927
da9b9724 928EVP_PKEY *load_pubkey(BIO *err, const char *file, int format, int maybe_stdin,
30b4c272 929 const char *pass, ENGINE *e, const char *key_descrip)
bd08a2bd
DSH
930 {
931 BIO *key=NULL;
932 EVP_PKEY *pkey=NULL;
30b4c272
RL
933 PW_CB_DATA cb_data;
934
935 cb_data.password = pass;
936 cb_data.prompt_info = file;
bd08a2bd 937
da9b9724 938 if (file == NULL && (!maybe_stdin || format == FORMAT_ENGINE))
bd08a2bd
DSH
939 {
940 BIO_printf(err,"no keyfile specified\n");
941 goto end;
942 }
0b13e9f0 943#ifndef OPENSSL_NO_ENGINE
32d862ed
RL
944 if (format == FORMAT_ENGINE)
945 {
946 if (!e)
947 BIO_printf(bio_err,"no engine specified\n");
948 else
30b4c272 949 pkey = ENGINE_load_public_key(e, file,
2fe5adc3 950 ui_method, &cb_data);
32d862ed
RL
951 goto end;
952 }
0b13e9f0 953#endif
bd08a2bd
DSH
954 key=BIO_new(BIO_s_file());
955 if (key == NULL)
956 {
957 ERR_print_errors(err);
958 goto end;
959 }
da9b9724 960 if (file == NULL && maybe_stdin)
bd08a2bd 961 {
ffa10187 962#ifdef _IONBF
da9b9724 963 setvbuf(stdin, NULL, _IONBF, 0);
ffa10187 964#endif
da9b9724
RL
965 BIO_set_fp(key,stdin,BIO_NOCLOSE);
966 }
967 else
968 if (BIO_read_filename(key,file) <= 0)
969 {
970 BIO_printf(err, "Error opening %s %s\n",
971 key_descrip, file);
972 ERR_print_errors(err);
973 goto end;
bd08a2bd
DSH
974 }
975 if (format == FORMAT_ASN1)
976 {
977 pkey=d2i_PUBKEY_bio(key, NULL);
978 }
eea374fd
DSH
979 else if (format == FORMAT_ASN1RSA)
980 {
981 RSA *rsa;
982 rsa = d2i_RSAPublicKey_bio(key, NULL);
983 if (rsa)
984 {
985 pkey = EVP_PKEY_new();
986 if (pkey)
987 EVP_PKEY_set1_RSA(pkey, rsa);
988 RSA_free(rsa);
989 }
990 else
991 pkey = NULL;
992 }
993 else if (format == FORMAT_PEMRSA)
994 {
995 RSA *rsa;
996 rsa = PEM_read_bio_RSAPublicKey(key, NULL,
997 (pem_password_cb *)password_callback, &cb_data);
998 if (rsa)
999 {
1000 pkey = EVP_PKEY_new();
1001 if (pkey)
1002 EVP_PKEY_set1_RSA(pkey, rsa);
1003 RSA_free(rsa);
1004 }
1005 else
1006 pkey = NULL;
1007 }
1008
bd08a2bd
DSH
1009 else if (format == FORMAT_PEM)
1010 {
30b4c272
RL
1011 pkey=PEM_read_bio_PUBKEY(key,NULL,
1012 (pem_password_cb *)password_callback, &cb_data);
bd08a2bd 1013 }
690ecff7 1014#if !defined(OPENSSL_NO_RC4) && !defined(OPENSSL_NO_RSA)
80bb905d
RL
1015 else if (format == FORMAT_NETSCAPE || format == FORMAT_IISSGC)
1016 pkey = load_netscape_key(err, key, file, key_descrip, format);
1017#endif
a0156a92
DSH
1018 else if (format == FORMAT_MSBLOB)
1019 pkey = b2i_PublicKey_bio(key);
bd08a2bd
DSH
1020 else
1021 {
30b4c272 1022 BIO_printf(err,"bad input format specified for key file\n");
bd08a2bd
DSH
1023 goto end;
1024 }
1025 end:
1026 if (key != NULL) BIO_free(key);
1027 if (pkey == NULL)
30b4c272 1028 BIO_printf(err,"unable to load %s\n", key_descrip);
bd08a2bd
DSH
1029 return(pkey);
1030 }
1031
690ecff7 1032#if !defined(OPENSSL_NO_RC4) && !defined(OPENSSL_NO_RSA)
1c02ca53 1033static EVP_PKEY *
80bb905d
RL
1034load_netscape_key(BIO *err, BIO *key, const char *file,
1035 const char *key_descrip, int format)
1036 {
1037 EVP_PKEY *pkey;
1038 BUF_MEM *buf;
1039 RSA *rsa;
1040 const unsigned char *p;
1041 int size, i;
1042
1043 buf=BUF_MEM_new();
1044 pkey = EVP_PKEY_new();
1045 size = 0;
1046 if (buf == NULL || pkey == NULL)
1047 goto error;
1048 for (;;)
1049 {
54a656ef 1050 if (!BUF_MEM_grow_clean(buf,size+1024*10))
80bb905d
RL
1051 goto error;
1052 i = BIO_read(key, &(buf->data[size]), 1024*10);
1053 size += i;
1054 if (i == 0)
1055 break;
1056 if (i < 0)
1057 {
1058 BIO_printf(err, "Error reading %s %s",
1059 key_descrip, file);
1060 goto error;
1061 }
1062 }
1063 p=(unsigned char *)buf->data;
1064 rsa = d2i_RSA_NET(NULL,&p,(long)size,NULL,
1065 (format == FORMAT_IISSGC ? 1 : 0));
1066 if (rsa == NULL)
1067 goto error;
1068 BUF_MEM_free(buf);
1069 EVP_PKEY_set1_RSA(pkey, rsa);
1070 return pkey;
1071error:
1072 BUF_MEM_free(buf);
1073 EVP_PKEY_free(pkey);
1074 return NULL;
1075 }
1076#endif /* ndef OPENSSL_NO_RC4 */
1077
30b4c272
RL
1078STACK_OF(X509) *load_certs(BIO *err, const char *file, int format,
1079 const char *pass, ENGINE *e, const char *cert_descrip)
90ae4673
RL
1080 {
1081 BIO *certs;
1082 int i;
1083 STACK_OF(X509) *othercerts = NULL;
1084 STACK_OF(X509_INFO) *allcerts = NULL;
1085 X509_INFO *xi;
30b4c272
RL
1086 PW_CB_DATA cb_data;
1087
1088 cb_data.password = pass;
1089 cb_data.prompt_info = file;
90ae4673
RL
1090
1091 if((certs = BIO_new(BIO_s_file())) == NULL)
1092 {
431b0cce 1093 ERR_print_errors(err);
90ae4673
RL
1094 goto end;
1095 }
1096
1097 if (file == NULL)
1098 BIO_set_fp(certs,stdin,BIO_NOCLOSE);
1099 else
1100 {
1101 if (BIO_read_filename(certs,file) <= 0)
1102 {
30b4c272
RL
1103 BIO_printf(err, "Error opening %s %s\n",
1104 cert_descrip, file);
1105 ERR_print_errors(err);
90ae4673
RL
1106 goto end;
1107 }
1108 }
1109
1110 if (format == FORMAT_PEM)
1111 {
62324627 1112 othercerts = sk_X509_new_null();
90ae4673
RL
1113 if(!othercerts)
1114 {
1115 sk_X509_free(othercerts);
1116 othercerts = NULL;
1117 goto end;
1118 }
30b4c272
RL
1119 allcerts = PEM_X509_INFO_read_bio(certs, NULL,
1120 (pem_password_cb *)password_callback, &cb_data);
90ae4673
RL
1121 for(i = 0; i < sk_X509_INFO_num(allcerts); i++)
1122 {
1123 xi = sk_X509_INFO_value (allcerts, i);
1124 if (xi->x509)
1125 {
1126 sk_X509_push(othercerts, xi->x509);
1127 xi->x509 = NULL;
1128 }
1129 }
1130 goto end;
1131 }
1132 else {
30b4c272
RL
1133 BIO_printf(err,"bad input format specified for %s\n",
1134 cert_descrip);
90ae4673
RL
1135 goto end;
1136 }
1137end:
1138 if (othercerts == NULL)
1139 {
431b0cce
RL
1140 BIO_printf(err,"unable to load certificates\n");
1141 ERR_print_errors(err);
90ae4673
RL
1142 }
1143 if (allcerts) sk_X509_INFO_pop_free(allcerts, X509_INFO_free);
1144 if (certs != NULL) BIO_free(certs);
1145 return(othercerts);
1146 }
1147
8ca533e3
DSH
1148
1149#define X509V3_EXT_UNKNOWN_MASK (0xfL << 16)
1150/* Return error for unknown extensions */
1151#define X509V3_EXT_DEFAULT 0
1152/* Print error for unknown extensions */
1153#define X509V3_EXT_ERROR_UNKNOWN (1L << 16)
1154/* ASN1 parse unknown extensions */
1155#define X509V3_EXT_PARSE_UNKNOWN (2L << 16)
1156/* BIO_dump unknown extensions */
1157#define X509V3_EXT_DUMP_UNKNOWN (3L << 16)
1158
535d79da
DSH
1159#define X509_FLAG_CA (X509_FLAG_NO_ISSUER | X509_FLAG_NO_PUBKEY | \
1160 X509_FLAG_NO_HEADER | X509_FLAG_NO_VERSION)
1161
8ca533e3
DSH
1162int set_cert_ex(unsigned long *flags, const char *arg)
1163{
1164 static const NAME_EX_TBL cert_tbl[] = {
1165 { "compatible", X509_FLAG_COMPAT, 0xffffffffl},
535d79da 1166 { "ca_default", X509_FLAG_CA, 0xffffffffl},
8ca533e3
DSH
1167 { "no_header", X509_FLAG_NO_HEADER, 0},
1168 { "no_version", X509_FLAG_NO_VERSION, 0},
1169 { "no_serial", X509_FLAG_NO_SERIAL, 0},
1170 { "no_signame", X509_FLAG_NO_SIGNAME, 0},
1171 { "no_validity", X509_FLAG_NO_VALIDITY, 0},
1172 { "no_subject", X509_FLAG_NO_SUBJECT, 0},
0a3ea5d3 1173 { "no_issuer", X509_FLAG_NO_ISSUER, 0},
8ca533e3
DSH
1174 { "no_pubkey", X509_FLAG_NO_PUBKEY, 0},
1175 { "no_extensions", X509_FLAG_NO_EXTENSIONS, 0},
1176 { "no_sigdump", X509_FLAG_NO_SIGDUMP, 0},
1177 { "no_aux", X509_FLAG_NO_AUX, 0},
fc85ac20 1178 { "no_attributes", X509_FLAG_NO_ATTRIBUTES, 0},
8ca533e3
DSH
1179 { "ext_default", X509V3_EXT_DEFAULT, X509V3_EXT_UNKNOWN_MASK},
1180 { "ext_error", X509V3_EXT_ERROR_UNKNOWN, X509V3_EXT_UNKNOWN_MASK},
1181 { "ext_parse", X509V3_EXT_PARSE_UNKNOWN, X509V3_EXT_UNKNOWN_MASK},
1182 { "ext_dump", X509V3_EXT_DUMP_UNKNOWN, X509V3_EXT_UNKNOWN_MASK},
1183 { NULL, 0, 0}
1184 };
535d79da 1185 return set_multi_opts(flags, arg, cert_tbl);
8ca533e3 1186}
a657546f
DSH
1187
1188int set_name_ex(unsigned long *flags, const char *arg)
1189{
8ca533e3 1190 static const NAME_EX_TBL ex_tbl[] = {
a657546f
DSH
1191 { "esc_2253", ASN1_STRFLGS_ESC_2253, 0},
1192 { "esc_ctrl", ASN1_STRFLGS_ESC_CTRL, 0},
1193 { "esc_msb", ASN1_STRFLGS_ESC_MSB, 0},
1194 { "use_quote", ASN1_STRFLGS_ESC_QUOTE, 0},
1195 { "utf8", ASN1_STRFLGS_UTF8_CONVERT, 0},
bd4e1527
DSH
1196 { "ignore_type", ASN1_STRFLGS_IGNORE_TYPE, 0},
1197 { "show_type", ASN1_STRFLGS_SHOW_TYPE, 0},
a657546f
DSH
1198 { "dump_all", ASN1_STRFLGS_DUMP_ALL, 0},
1199 { "dump_nostr", ASN1_STRFLGS_DUMP_UNKNOWN, 0},
1200 { "dump_der", ASN1_STRFLGS_DUMP_DER, 0},
1201 { "compat", XN_FLAG_COMPAT, 0xffffffffL},
1202 { "sep_comma_plus", XN_FLAG_SEP_COMMA_PLUS, XN_FLAG_SEP_MASK},
1203 { "sep_comma_plus_space", XN_FLAG_SEP_CPLUS_SPC, XN_FLAG_SEP_MASK},
1204 { "sep_semi_plus_space", XN_FLAG_SEP_SPLUS_SPC, XN_FLAG_SEP_MASK},
1205 { "sep_multiline", XN_FLAG_SEP_MULTILINE, XN_FLAG_SEP_MASK},
1206 { "dn_rev", XN_FLAG_DN_REV, 0},
1207 { "nofname", XN_FLAG_FN_NONE, XN_FLAG_FN_MASK},
1208 { "sname", XN_FLAG_FN_SN, XN_FLAG_FN_MASK},
1209 { "lname", XN_FLAG_FN_LN, XN_FLAG_FN_MASK},
e890dcdb 1210 { "align", XN_FLAG_FN_ALIGN, 0},
a657546f
DSH
1211 { "oid", XN_FLAG_FN_OID, XN_FLAG_FN_MASK},
1212 { "space_eq", XN_FLAG_SPC_EQ, 0},
1213 { "dump_unknown", XN_FLAG_DUMP_UNKNOWN_FIELDS, 0},
1214 { "RFC2253", XN_FLAG_RFC2253, 0xffffffffL},
1215 { "oneline", XN_FLAG_ONELINE, 0xffffffffL},
1216 { "multiline", XN_FLAG_MULTILINE, 0xffffffffL},
535d79da 1217 { "ca_default", XN_FLAG_MULTILINE, 0xffffffffL},
a657546f
DSH
1218 { NULL, 0, 0}
1219 };
535d79da
DSH
1220 return set_multi_opts(flags, arg, ex_tbl);
1221}
1222
791bd0cd
DSH
1223int set_ext_copy(int *copy_type, const char *arg)
1224{
1225 if (!strcasecmp(arg, "none"))
1226 *copy_type = EXT_COPY_NONE;
1227 else if (!strcasecmp(arg, "copy"))
1228 *copy_type = EXT_COPY_ADD;
1229 else if (!strcasecmp(arg, "copyall"))
1230 *copy_type = EXT_COPY_ALL;
1231 else
1232 return 0;
1233 return 1;
1234}
1235
1236int copy_extensions(X509 *x, X509_REQ *req, int copy_type)
1237{
1238 STACK_OF(X509_EXTENSION) *exts = NULL;
1239 X509_EXTENSION *ext, *tmpext;
1240 ASN1_OBJECT *obj;
1241 int i, idx, ret = 0;
1242 if (!x || !req || (copy_type == EXT_COPY_NONE))
1243 return 1;
1244 exts = X509_REQ_get_extensions(req);
1245
1246 for(i = 0; i < sk_X509_EXTENSION_num(exts); i++) {
1247 ext = sk_X509_EXTENSION_value(exts, i);
1248 obj = X509_EXTENSION_get_object(ext);
1249 idx = X509_get_ext_by_OBJ(x, obj, -1);
1250 /* Does extension exist? */
1251 if (idx != -1) {
1252 /* If normal copy don't override existing extension */
1253 if (copy_type == EXT_COPY_ADD)
1254 continue;
1255 /* Delete all extensions of same type */
1256 do {
1257 tmpext = X509_get_ext(x, idx);
1258 X509_delete_ext(x, idx);
1259 X509_EXTENSION_free(tmpext);
1260 idx = X509_get_ext_by_OBJ(x, obj, -1);
1261 } while (idx != -1);
1262 }
1263 if (!X509_add_ext(x, ext, -1))
1264 goto end;
1265 }
1266
1267 ret = 1;
1268
1269 end:
1270
1271 sk_X509_EXTENSION_pop_free(exts, X509_EXTENSION_free);
1272
1273 return ret;
1274}
1275
1276
1277
1278
535d79da
DSH
1279static int set_multi_opts(unsigned long *flags, const char *arg, const NAME_EX_TBL *in_tbl)
1280{
1281 STACK_OF(CONF_VALUE) *vals;
1282 CONF_VALUE *val;
1283 int i, ret = 1;
1284 if(!arg) return 0;
1285 vals = X509V3_parse_list(arg);
1286 for (i = 0; i < sk_CONF_VALUE_num(vals); i++) {
1287 val = sk_CONF_VALUE_value(vals, i);
1288 if (!set_table_opts(flags, val->name, in_tbl))
1289 ret = 0;
1290 }
1291 sk_CONF_VALUE_pop_free(vals, X509V3_conf_free);
1292 return ret;
8ca533e3 1293}
a657546f 1294
8ca533e3
DSH
1295static int set_table_opts(unsigned long *flags, const char *arg, const NAME_EX_TBL *in_tbl)
1296{
1297 char c;
1298 const NAME_EX_TBL *ptbl;
a657546f
DSH
1299 c = arg[0];
1300
1301 if(c == '-') {
1302 c = 0;
1303 arg++;
1304 } else if (c == '+') {
1305 c = 1;
1306 arg++;
1307 } else c = 1;
1308
8ca533e3 1309 for(ptbl = in_tbl; ptbl->name; ptbl++) {
c15e0363 1310 if(!strcasecmp(arg, ptbl->name)) {
a657546f
DSH
1311 *flags &= ~ptbl->mask;
1312 if(c) *flags |= ptbl->flag;
1313 else *flags &= ~ptbl->flag;
1314 return 1;
1315 }
1316 }
1317 return 0;
1318}
1319
7d727231 1320void print_name(BIO *out, const char *title, X509_NAME *nm, unsigned long lflags)
a657546f 1321{
402bcde8 1322 char *buf;
a657546f
DSH
1323 char mline = 0;
1324 int indent = 0;
54a656ef 1325
a657546f
DSH
1326 if(title) BIO_puts(out, title);
1327 if((lflags & XN_FLAG_SEP_MASK) == XN_FLAG_SEP_MULTILINE) {
1328 mline = 1;
1329 indent = 4;
1330 }
1331 if(lflags == XN_FLAG_COMPAT) {
402bcde8
RL
1332 buf = X509_NAME_oneline(nm, 0, 0);
1333 BIO_puts(out, buf);
a657546f 1334 BIO_puts(out, "\n");
402bcde8 1335 OPENSSL_free(buf);
a657546f
DSH
1336 } else {
1337 if(mline) BIO_puts(out, "\n");
1338 X509_NAME_print_ex(out, nm, indent, lflags);
1339 BIO_puts(out, "\n");
1340 }
1341}
1342
81f169e9
DSH
1343X509_STORE *setup_verify(BIO *bp, char *CAfile, char *CApath)
1344{
1345 X509_STORE *store;
1346 X509_LOOKUP *lookup;
1347 if(!(store = X509_STORE_new())) goto end;
1348 lookup=X509_STORE_add_lookup(store,X509_LOOKUP_file());
1349 if (lookup == NULL) goto end;
1350 if (CAfile) {
1351 if(!X509_LOOKUP_load_file(lookup,CAfile,X509_FILETYPE_PEM)) {
1352 BIO_printf(bp, "Error loading file %s\n", CAfile);
1353 goto end;
1354 }
1355 } else X509_LOOKUP_load_file(lookup,NULL,X509_FILETYPE_DEFAULT);
1356
1357 lookup=X509_STORE_add_lookup(store,X509_LOOKUP_hash_dir());
1358 if (lookup == NULL) goto end;
1359 if (CApath) {
1360 if(!X509_LOOKUP_add_dir(lookup,CApath,X509_FILETYPE_PEM)) {
1361 BIO_printf(bp, "Error loading directory %s\n", CApath);
1362 goto end;
1363 }
1364 } else X509_LOOKUP_add_dir(lookup,NULL,X509_FILETYPE_DEFAULT);
1365
1366 ERR_clear_error();
1367 return store;
1368 end:
1369 X509_STORE_free(store);
1370 return NULL;
1371}
531d630b 1372
0b13e9f0 1373#ifndef OPENSSL_NO_ENGINE
e1a00d7d 1374/* Try to load an engine in a shareable library */
40889b9c 1375static ENGINE *try_load_engine(BIO *err, const char *engine, int debug)
e1a00d7d
RL
1376 {
1377 ENGINE *e = ENGINE_by_id("dynamic");
1378 if (e)
1379 {
1380 if (!ENGINE_ctrl_cmd_string(e, "SO_PATH", engine, 0)
1381 || !ENGINE_ctrl_cmd_string(e, "LOAD", NULL, 0))
1382 {
1383 ENGINE_free(e);
1384 e = NULL;
1385 }
1386 }
1387 return e;
1388 }
1389
531d630b
RL
1390ENGINE *setup_engine(BIO *err, const char *engine, int debug)
1391 {
1392 ENGINE *e = NULL;
1393
1394 if (engine)
1395 {
34c66925
GT
1396 if(strcmp(engine, "auto") == 0)
1397 {
1398 BIO_printf(err,"enabling auto ENGINE support\n");
1399 ENGINE_register_all_complete();
1400 return NULL;
1401 }
e1a00d7d
RL
1402 if((e = ENGINE_by_id(engine)) == NULL
1403 && (e = try_load_engine(err, engine, debug)) == NULL)
531d630b
RL
1404 {
1405 BIO_printf(err,"invalid engine \"%s\"\n", engine);
e1a00d7d 1406 ERR_print_errors(err);
531d630b
RL
1407 return NULL;
1408 }
1409 if (debug)
1410 {
1411 ENGINE_ctrl(e, ENGINE_CTRL_SET_LOGSTREAM,
1412 0, err, 0);
1413 }
2fe5adc3 1414 ENGINE_ctrl_cmd(e, "SET_USER_INTERFACE", 0, ui_method, 0, 1);
531d630b
RL
1415 if(!ENGINE_set_default(e, ENGINE_METHOD_ALL))
1416 {
1417 BIO_printf(err,"can't use that engine\n");
e1a00d7d 1418 ERR_print_errors(err);
308f028e 1419 ENGINE_free(e);
531d630b
RL
1420 return NULL;
1421 }
354c3ace 1422
e1a00d7d 1423 BIO_printf(err,"engine \"%s\" set.\n", ENGINE_get_id(e));
354c3ace 1424
531d630b
RL
1425 /* Free our "structural" reference. */
1426 ENGINE_free(e);
1427 }
1428 return e;
1429 }
0b13e9f0 1430#endif
3647bee2
DSH
1431
1432int load_config(BIO *err, CONF *cnf)
1433 {
1434 if (!cnf)
1435 cnf = config;
1436 if (!cnf)
1437 return 1;
1438
1439 OPENSSL_load_builtin_modules();
1440
1441 if (CONF_modules_load(cnf, NULL, 0) <= 0)
1442 {
1443 BIO_printf(err, "Error configuring OpenSSL\n");
1444 ERR_print_errors(err);
1445 return 0;
1446 }
1447 return 1;
1448 }
54a656ef
BL
1449
1450char *make_config_name()
1451 {
1452 const char *t=X509_get_default_cert_area();
d420ac2c 1453 size_t len;
54a656ef
BL
1454 char *p;
1455
d420ac2c
RL
1456 len=strlen(t)+strlen(OPENSSL_CONF)+2;
1457 p=OPENSSL_malloc(len);
1458 BUF_strlcpy(p,t,len);
54a656ef 1459#ifndef OPENSSL_SYS_VMS
d420ac2c 1460 BUF_strlcat(p,"/",len);
54a656ef 1461#endif
d420ac2c 1462 BUF_strlcat(p,OPENSSL_CONF,len);
54a656ef
BL
1463
1464 return p;
1465 }
f85b68cd
RL
1466
1467static unsigned long index_serial_hash(const char **a)
1468 {
1469 const char *n;
1470
1471 n=a[DB_serial];
1472 while (*n == '0') n++;
1473 return(lh_strhash(n));
1474 }
1475
1476static int index_serial_cmp(const char **a, const char **b)
1477 {
1478 const char *aa,*bb;
1479
1480 for (aa=a[DB_serial]; *aa == '0'; aa++);
1481 for (bb=b[DB_serial]; *bb == '0'; bb++);
1482 return(strcmp(aa,bb));
1483 }
1484
1485static int index_name_qual(char **a)
1486 { return(a[0][0] == 'V'); }
1487
1488static unsigned long index_name_hash(const char **a)
1489 { return(lh_strhash(a[DB_name])); }
1490
1491int index_name_cmp(const char **a, const char **b)
1492 { return(strcmp(a[DB_name],
1493 b[DB_name])); }
1494
1495static IMPLEMENT_LHASH_HASH_FN(index_serial_hash,const char **)
1496static IMPLEMENT_LHASH_COMP_FN(index_serial_cmp,const char **)
1497static IMPLEMENT_LHASH_HASH_FN(index_name_hash,const char **)
1498static IMPLEMENT_LHASH_COMP_FN(index_name_cmp,const char **)
1499
1500#undef BSIZE
1501#define BSIZE 256
1502
1503BIGNUM *load_serial(char *serialfile, int create, ASN1_INTEGER **retai)
1504 {
1505 BIO *in=NULL;
1506 BIGNUM *ret=NULL;
1507 MS_STATIC char buf[1024];
1508 ASN1_INTEGER *ai=NULL;
1509
1510 ai=ASN1_INTEGER_new();
1511 if (ai == NULL) goto err;
1512
1513 if ((in=BIO_new(BIO_s_file())) == NULL)
1514 {
1515 ERR_print_errors(bio_err);
1516 goto err;
1517 }
1518
1519 if (BIO_read_filename(in,serialfile) <= 0)
1520 {
1521 if (!create)
1522 {
1523 perror(serialfile);
1524 goto err;
1525 }
1526 else
1527 {
f85b68cd 1528 ret=BN_new();
64674bcc 1529 if (ret == NULL || !rand_serial(ret, ai))
f85b68cd 1530 BIO_printf(bio_err, "Out of memory\n");
f85b68cd
RL
1531 }
1532 }
1533 else
1534 {
1535 if (!a2i_ASN1_INTEGER(in,ai,buf,1024))
1536 {
1537 BIO_printf(bio_err,"unable to load number from %s\n",
1538 serialfile);
1539 goto err;
1540 }
1541 ret=ASN1_INTEGER_to_BN(ai,NULL);
1542 if (ret == NULL)
1543 {
1544 BIO_printf(bio_err,"error converting number from bin to BIGNUM\n");
1545 goto err;
1546 }
1547 }
1548
1549 if (ret && retai)
1550 {
1551 *retai = ai;
1552 ai = NULL;
1553 }
1554 err:
1555 if (in != NULL) BIO_free(in);
1556 if (ai != NULL) ASN1_INTEGER_free(ai);
1557 return(ret);
1558 }
1559
4c771796 1560int save_serial(char *serialfile, char *suffix, BIGNUM *serial, ASN1_INTEGER **retai)
f85b68cd 1561 {
4c771796
RL
1562 char buf[1][BSIZE];
1563 BIO *out = NULL;
f85b68cd
RL
1564 int ret=0;
1565 ASN1_INTEGER *ai=NULL;
4c771796
RL
1566 int j;
1567
1568 if (suffix == NULL)
1569 j = strlen(serialfile);
1570 else
1571 j = strlen(serialfile) + strlen(suffix) + 1;
1572 if (j >= BSIZE)
1573 {
1574 BIO_printf(bio_err,"file name too long\n");
1575 goto err;
1576 }
f85b68cd 1577
4c771796
RL
1578 if (suffix == NULL)
1579 BUF_strlcpy(buf[0], serialfile, BSIZE);
1580 else
1581 {
1582#ifndef OPENSSL_SYS_VMS
1583 j = BIO_snprintf(buf[0], sizeof buf[0], "%s.%s", serialfile, suffix);
1584#else
1585 j = BIO_snprintf(buf[0], sizeof buf[0], "%s-%s", serialfile, suffix);
1586#endif
1587 }
1588#ifdef RL_DEBUG
1589 BIO_printf(bio_err, "DEBUG: writing \"%s\"\n", buf[0]);
1590#endif
f85b68cd
RL
1591 out=BIO_new(BIO_s_file());
1592 if (out == NULL)
1593 {
1594 ERR_print_errors(bio_err);
1595 goto err;
1596 }
4c771796 1597 if (BIO_write_filename(out,buf[0]) <= 0)
f85b68cd
RL
1598 {
1599 perror(serialfile);
1600 goto err;
1601 }
1602
1603 if ((ai=BN_to_ASN1_INTEGER(serial,NULL)) == NULL)
1604 {
1605 BIO_printf(bio_err,"error converting serial to ASN.1 format\n");
1606 goto err;
1607 }
1608 i2a_ASN1_INTEGER(out,ai);
1609 BIO_puts(out,"\n");
1610 ret=1;
1611 if (retai)
1612 {
1613 *retai = ai;
1614 ai = NULL;
1615 }
1616err:
1617 if (out != NULL) BIO_free_all(out);
1618 if (ai != NULL) ASN1_INTEGER_free(ai);
1619 return(ret);
1620 }
1621
4c771796
RL
1622int rotate_serial(char *serialfile, char *new_suffix, char *old_suffix)
1623 {
1624 char buf[5][BSIZE];
1625 int i,j;
1626 struct stat sb;
1627
1628 i = strlen(serialfile) + strlen(old_suffix);
1629 j = strlen(serialfile) + strlen(new_suffix);
1630 if (i > j) j = i;
1631 if (j + 1 >= BSIZE)
1632 {
1633 BIO_printf(bio_err,"file name too long\n");
1634 goto err;
1635 }
1636
1637#ifndef OPENSSL_SYS_VMS
1638 j = BIO_snprintf(buf[0], sizeof buf[0], "%s.%s",
1639 serialfile, new_suffix);
1640#else
1641 j = BIO_snprintf(buf[0], sizeof buf[0], "%s-%s",
1642 serialfile, new_suffix);
1643#endif
1644#ifndef OPENSSL_SYS_VMS
1645 j = BIO_snprintf(buf[1], sizeof buf[1], "%s.%s",
1646 serialfile, old_suffix);
1647#else
1648 j = BIO_snprintf(buf[1], sizeof buf[1], "%s-%s",
1649 serialfile, old_suffix);
1650#endif
1651 if (stat(serialfile,&sb) < 0)
1652 {
1653 if (errno != ENOENT
1654#ifdef ENOTDIR
53bb3bee 1655 && errno != ENOTDIR
4c771796 1656#endif
53bb3bee 1657 )
4c771796
RL
1658 goto err;
1659 }
1660 else
1661 {
1662#ifdef RL_DEBUG
1663 BIO_printf(bio_err, "DEBUG: renaming \"%s\" to \"%s\"\n",
1664 serialfile, buf[1]);
1665#endif
1666 if (rename(serialfile,buf[1]) < 0)
1667 {
1668 BIO_printf(bio_err,
1669 "unable to rename %s to %s\n",
1670 serialfile, buf[1]);
1671 perror("reason");
1672 goto err;
1673 }
1674 }
1675#ifdef RL_DEBUG
1676 BIO_printf(bio_err, "DEBUG: renaming \"%s\" to \"%s\"\n",
1677 buf[0],serialfile);
1678#endif
1679 if (rename(buf[0],serialfile) < 0)
1680 {
1681 BIO_printf(bio_err,
1682 "unable to rename %s to %s\n",
1683 buf[0],serialfile);
1684 perror("reason");
1685 rename(buf[1],serialfile);
1686 goto err;
1687 }
1688 return 1;
1689 err:
1690 return 0;
1691 }
1692
64674bcc
DSH
1693int rand_serial(BIGNUM *b, ASN1_INTEGER *ai)
1694 {
1695 BIGNUM *btmp;
1696 int ret = 0;
1697 if (b)
1698 btmp = b;
1699 else
1700 btmp = BN_new();
1701
1702 if (!btmp)
1703 return 0;
1704
1705 if (!BN_pseudo_rand(btmp, SERIAL_RAND_BITS, 0, 0))
1706 goto error;
1707 if (ai && !BN_to_ASN1_INTEGER(btmp, ai))
1708 goto error;
1709
1710 ret = 1;
1711
1712 error:
1713
1714 if (!b)
1715 BN_free(btmp);
1716
1717 return ret;
1718 }
1719
f85b68cd
RL
1720CA_DB *load_index(char *dbfile, DB_ATTR *db_attr)
1721 {
1722 CA_DB *retdb = NULL;
1723 TXT_DB *tmpdb = NULL;
1724 BIO *in = BIO_new(BIO_s_file());
1725 CONF *dbattr_conf = NULL;
1726 char buf[1][BSIZE];
1727 long errorline= -1;
1728
1729 if (in == NULL)
1730 {
1731 ERR_print_errors(bio_err);
1732 goto err;
1733 }
1734 if (BIO_read_filename(in,dbfile) <= 0)
1735 {
1736 perror(dbfile);
1737 BIO_printf(bio_err,"unable to open '%s'\n",dbfile);
1738 goto err;
1739 }
1740 if ((tmpdb = TXT_DB_read(in,DB_NUMBER)) == NULL)
1741 {
1742 if (tmpdb != NULL) TXT_DB_free(tmpdb);
1743 goto err;
1744 }
1745
1746#ifndef OPENSSL_SYS_VMS
1747 BIO_snprintf(buf[0], sizeof buf[0], "%s.attr", dbfile);
1748#else
1749 BIO_snprintf(buf[0], sizeof buf[0], "%s-attr", dbfile);
1750#endif
1751 dbattr_conf = NCONF_new(NULL);
1752 if (NCONF_load(dbattr_conf,buf[0],&errorline) <= 0)
1753 {
1754 if (errorline > 0)
1755 {
1756 BIO_printf(bio_err,
1757 "error on line %ld of db attribute file '%s'\n"
1758 ,errorline,buf[0]);
1759 goto err;
1760 }
1761 else
1762 {
1763 NCONF_free(dbattr_conf);
1764 dbattr_conf = NULL;
1765 }
1766 }
1767
1768 if ((retdb = OPENSSL_malloc(sizeof(CA_DB))) == NULL)
1769 {
1770 fprintf(stderr, "Out of memory\n");
1771 goto err;
1772 }
1773
1774 retdb->db = tmpdb;
1775 tmpdb = NULL;
1776 if (db_attr)
1777 retdb->attributes = *db_attr;
1778 else
1779 {
1780 retdb->attributes.unique_subject = 1;
1781 }
1782
1783 if (dbattr_conf)
1784 {
1785 char *p = NCONF_get_string(dbattr_conf,NULL,"unique_subject");
1786 if (p)
1787 {
83b23ed9 1788#ifdef RL_DEBUG
f85b68cd 1789 BIO_printf(bio_err, "DEBUG[load_index]: unique_subject = \"%s\"\n", p);
83b23ed9 1790#endif
03ddbdd9 1791 retdb->attributes.unique_subject = parse_yesno(p,1);
f85b68cd
RL
1792 }
1793 }
1794
1795 err:
1796 if (dbattr_conf) NCONF_free(dbattr_conf);
1797 if (tmpdb) TXT_DB_free(tmpdb);
1798 if (in) BIO_free_all(in);
1799 return retdb;
1800 }
1801
1802int index_index(CA_DB *db)
1803 {
1804 if (!TXT_DB_create_index(db->db, DB_serial, NULL,
1805 LHASH_HASH_FN(index_serial_hash),
1806 LHASH_COMP_FN(index_serial_cmp)))
1807 {
1808 BIO_printf(bio_err,
1809 "error creating serial number index:(%ld,%ld,%ld)\n",
1810 db->db->error,db->db->arg1,db->db->arg2);
1811 return 0;
1812 }
1813
1814 if (db->attributes.unique_subject
1815 && !TXT_DB_create_index(db->db, DB_name, index_name_qual,
1816 LHASH_HASH_FN(index_name_hash),
1817 LHASH_COMP_FN(index_name_cmp)))
1818 {
1819 BIO_printf(bio_err,"error creating name index:(%ld,%ld,%ld)\n",
1820 db->db->error,db->db->arg1,db->db->arg2);
1821 return 0;
1822 }
1823 return 1;
1824 }
1825
7d727231 1826int save_index(const char *dbfile, const char *suffix, CA_DB *db)
f85b68cd
RL
1827 {
1828 char buf[3][BSIZE];
1829 BIO *out = BIO_new(BIO_s_file());
1830 int j;
1831
1832 if (out == NULL)
1833 {
1834 ERR_print_errors(bio_err);
1835 goto err;
1836 }
1837
1838 j = strlen(dbfile) + strlen(suffix);
1839 if (j + 6 >= BSIZE)
1840 {
1841 BIO_printf(bio_err,"file name too long\n");
1842 goto err;
1843 }
1844
1845#ifndef OPENSSL_SYS_VMS
1846 j = BIO_snprintf(buf[2], sizeof buf[2], "%s.attr", dbfile);
1847#else
1848 j = BIO_snprintf(buf[2], sizeof buf[2], "%s-attr", dbfile);
1849#endif
1850#ifndef OPENSSL_SYS_VMS
1851 j = BIO_snprintf(buf[1], sizeof buf[1], "%s.attr.%s", dbfile, suffix);
1852#else
1853 j = BIO_snprintf(buf[1], sizeof buf[1], "%s-attr-%s", dbfile, suffix);
1854#endif
1855#ifndef OPENSSL_SYS_VMS
1856 j = BIO_snprintf(buf[0], sizeof buf[0], "%s.%s", dbfile, suffix);
1857#else
1858 j = BIO_snprintf(buf[0], sizeof buf[0], "%s-%s", dbfile, suffix);
1859#endif
63b6fe2b 1860#ifdef RL_DEBUG
f85b68cd 1861 BIO_printf(bio_err, "DEBUG: writing \"%s\"\n", buf[0]);
63b6fe2b 1862#endif
f85b68cd
RL
1863 if (BIO_write_filename(out,buf[0]) <= 0)
1864 {
1865 perror(dbfile);
1866 BIO_printf(bio_err,"unable to open '%s'\n", dbfile);
1867 goto err;
1868 }
1869 j=TXT_DB_write(out,db->db);
1870 if (j <= 0) goto err;
1871
1872 BIO_free(out);
1873
1874 out = BIO_new(BIO_s_file());
63b6fe2b 1875#ifdef RL_DEBUG
f85b68cd 1876 BIO_printf(bio_err, "DEBUG: writing \"%s\"\n", buf[1]);
63b6fe2b 1877#endif
f85b68cd
RL
1878 if (BIO_write_filename(out,buf[1]) <= 0)
1879 {
1880 perror(buf[2]);
1881 BIO_printf(bio_err,"unable to open '%s'\n", buf[2]);
1882 goto err;
1883 }
1884 BIO_printf(out,"unique_subject = %s\n",
1885 db->attributes.unique_subject ? "yes" : "no");
1886 BIO_free(out);
1887
1888 return 1;
1889 err:
1890 return 0;
1891 }
1892
7d727231 1893int rotate_index(const char *dbfile, const char *new_suffix, const char *old_suffix)
f85b68cd
RL
1894 {
1895 char buf[5][BSIZE];
1896 int i,j;
1897 struct stat sb;
1898
1899 i = strlen(dbfile) + strlen(old_suffix);
1900 j = strlen(dbfile) + strlen(new_suffix);
1901 if (i > j) j = i;
1902 if (j + 6 >= BSIZE)
1903 {
1904 BIO_printf(bio_err,"file name too long\n");
1905 goto err;
1906 }
1907
1908#ifndef OPENSSL_SYS_VMS
1909 j = BIO_snprintf(buf[4], sizeof buf[4], "%s.attr", dbfile);
1910#else
1911 j = BIO_snprintf(buf[4], sizeof buf[4], "%s-attr", dbfile);
1912#endif
1913#ifndef OPENSSL_SYS_VMS
1914 j = BIO_snprintf(buf[2], sizeof buf[2], "%s.attr.%s",
1915 dbfile, new_suffix);
1916#else
1917 j = BIO_snprintf(buf[2], sizeof buf[2], "%s-attr-%s",
1918 dbfile, new_suffix);
1919#endif
1920#ifndef OPENSSL_SYS_VMS
1921 j = BIO_snprintf(buf[0], sizeof buf[0], "%s.%s",
1922 dbfile, new_suffix);
1923#else
1924 j = BIO_snprintf(buf[0], sizeof buf[0], "%s-%s",
1925 dbfile, new_suffix);
1926#endif
1927#ifndef OPENSSL_SYS_VMS
1928 j = BIO_snprintf(buf[1], sizeof buf[1], "%s.%s",
1929 dbfile, old_suffix);
1930#else
1931 j = BIO_snprintf(buf[1], sizeof buf[1], "%s-%s",
1932 dbfile, old_suffix);
1933#endif
1934#ifndef OPENSSL_SYS_VMS
1935 j = BIO_snprintf(buf[3], sizeof buf[3], "%s.attr.%s",
1936 dbfile, old_suffix);
1937#else
1938 j = BIO_snprintf(buf[3], sizeof buf[3], "%s-attr-%s",
1939 dbfile, old_suffix);
1940#endif
1941 if (stat(dbfile,&sb) < 0)
1942 {
1943 if (errno != ENOENT
1944#ifdef ENOTDIR
53bb3bee 1945 && errno != ENOTDIR
f85b68cd 1946#endif
53bb3bee 1947 )
f85b68cd
RL
1948 goto err;
1949 }
1950 else
1951 {
63b6fe2b 1952#ifdef RL_DEBUG
f85b68cd
RL
1953 BIO_printf(bio_err, "DEBUG: renaming \"%s\" to \"%s\"\n",
1954 dbfile, buf[1]);
63b6fe2b 1955#endif
f85b68cd
RL
1956 if (rename(dbfile,buf[1]) < 0)
1957 {
1958 BIO_printf(bio_err,
1959 "unable to rename %s to %s\n",
1960 dbfile, buf[1]);
1961 perror("reason");
1962 goto err;
1963 }
1964 }
63b6fe2b 1965#ifdef RL_DEBUG
f85b68cd
RL
1966 BIO_printf(bio_err, "DEBUG: renaming \"%s\" to \"%s\"\n",
1967 buf[0],dbfile);
63b6fe2b 1968#endif
f85b68cd
RL
1969 if (rename(buf[0],dbfile) < 0)
1970 {
1971 BIO_printf(bio_err,
1972 "unable to rename %s to %s\n",
1973 buf[0],dbfile);
1974 perror("reason");
1975 rename(buf[1],dbfile);
1976 goto err;
1977 }
1978 if (stat(buf[4],&sb) < 0)
1979 {
1980 if (errno != ENOENT
1981#ifdef ENOTDIR
53bb3bee 1982 && errno != ENOTDIR
f85b68cd 1983#endif
53bb3bee 1984 )
f85b68cd
RL
1985 goto err;
1986 }
1987 else
1988 {
63b6fe2b 1989#ifdef RL_DEBUG
f85b68cd
RL
1990 BIO_printf(bio_err, "DEBUG: renaming \"%s\" to \"%s\"\n",
1991 buf[4],buf[3]);
63b6fe2b 1992#endif
f85b68cd
RL
1993 if (rename(buf[4],buf[3]) < 0)
1994 {
1995 BIO_printf(bio_err,
1996 "unable to rename %s to %s\n",
1997 buf[4], buf[3]);
1998 perror("reason");
1999 rename(dbfile,buf[0]);
2000 rename(buf[1],dbfile);
2001 goto err;
2002 }
2003 }
63b6fe2b 2004#ifdef RL_DEBUG
f85b68cd
RL
2005 BIO_printf(bio_err, "DEBUG: renaming \"%s\" to \"%s\"\n",
2006 buf[2],buf[4]);
63b6fe2b 2007#endif
f85b68cd
RL
2008 if (rename(buf[2],buf[4]) < 0)
2009 {
2010 BIO_printf(bio_err,
2011 "unable to rename %s to %s\n",
2012 buf[2],buf[4]);
2013 perror("reason");
2014 rename(buf[3],buf[4]);
2015 rename(dbfile,buf[0]);
2016 rename(buf[1],dbfile);
2017 goto err;
2018 }
2019 return 1;
2020 err:
2021 return 0;
2022 }
2023
2024void free_index(CA_DB *db)
2025 {
db598fbc
RL
2026 if (db)
2027 {
2028 if (db->db) TXT_DB_free(db->db);
2029 OPENSSL_free(db);
2030 }
f85b68cd 2031 }
6d5ffb59 2032
ff990440 2033int parse_yesno(const char *str, int def)
03ddbdd9
RL
2034 {
2035 int ret = def;
2036 if (str)
2037 {
2038 switch (*str)
2039 {
2040 case 'f': /* false */
2041 case 'F': /* FALSE */
2042 case 'n': /* no */
2043 case 'N': /* NO */
2044 case '0': /* 0 */
2045 ret = 0;
2046 break;
2047 case 't': /* true */
2048 case 'T': /* TRUE */
2049 case 'y': /* yes */
2050 case 'Y': /* YES */
2051 case '1': /* 1 */
2052 ret = 0;
2053 break;
2054 default:
2055 ret = def;
2056 break;
2057 }
2058 }
2059 return ret;
2060 }
2061
6d5ffb59
RL
2062/*
2063 * subject is expected to be in the format /type0=value0/type1=value1/type2=...
2064 * where characters may be escaped by \
2065 */
2066X509_NAME *parse_name(char *subject, long chtype, int multirdn)
2067 {
2068 size_t buflen = strlen(subject)+1; /* to copy the types and values into. due to escaping, the copy can only become shorter */
2069 char *buf = OPENSSL_malloc(buflen);
2070 size_t max_ne = buflen / 2 + 1; /* maximum number of name elements */
2071 char **ne_types = OPENSSL_malloc(max_ne * sizeof (char *));
2072 char **ne_values = OPENSSL_malloc(max_ne * sizeof (char *));
2073 int *mval = OPENSSL_malloc (max_ne * sizeof (int));
2074
2075 char *sp = subject, *bp = buf;
2076 int i, ne_num = 0;
2077
2078 X509_NAME *n = NULL;
2079 int nid;
2080
2081 if (!buf || !ne_types || !ne_values)
2082 {
2083 BIO_printf(bio_err, "malloc error\n");
2084 goto error;
2085 }
2086
2087 if (*subject != '/')
2088 {
2089 BIO_printf(bio_err, "Subject does not start with '/'.\n");
2090 goto error;
2091 }
2092 sp++; /* skip leading / */
2093
2094 /* no multivalued RDN by default */
2095 mval[ne_num] = 0;
2096
2097 while (*sp)
2098 {
2099 /* collect type */
2100 ne_types[ne_num] = bp;
2101 while (*sp)
2102 {
2103 if (*sp == '\\') /* is there anything to escape in the type...? */
2104 {
2105 if (*++sp)
2106 *bp++ = *sp++;
2107 else
2108 {
2109 BIO_printf(bio_err, "escape character at end of string\n");
2110 goto error;
2111 }
2112 }
2113 else if (*sp == '=')
2114 {
2115 sp++;
2116 *bp++ = '\0';
2117 break;
2118 }
2119 else
2120 *bp++ = *sp++;
2121 }
2122 if (!*sp)
2123 {
2124 BIO_printf(bio_err, "end of string encountered while processing type of subject name element #%d\n", ne_num);
2125 goto error;
2126 }
2127 ne_values[ne_num] = bp;
2128 while (*sp)
2129 {
2130 if (*sp == '\\')
2131 {
2132 if (*++sp)
2133 *bp++ = *sp++;
2134 else
2135 {
2136 BIO_printf(bio_err, "escape character at end of string\n");
2137 goto error;
2138 }
2139 }
2140 else if (*sp == '/')
2141 {
2142 sp++;
2143 /* no multivalued RDN by default */
2144 mval[ne_num+1] = 0;
2145 break;
2146 }
2147 else if (*sp == '+' && multirdn)
2148 {
2149 /* a not escaped + signals a mutlivalued RDN */
2150 sp++;
2151 mval[ne_num+1] = -1;
2152 break;
2153 }
2154 else
2155 *bp++ = *sp++;
2156 }
2157 *bp++ = '\0';
2158 ne_num++;
2159 }
2160
2161 if (!(n = X509_NAME_new()))
2162 goto error;
2163
2164 for (i = 0; i < ne_num; i++)
2165 {
2166 if ((nid=OBJ_txt2nid(ne_types[i])) == NID_undef)
2167 {
2168 BIO_printf(bio_err, "Subject Attribute %s has no known NID, skipped\n", ne_types[i]);
2169 continue;
2170 }
2171
2172 if (!*ne_values[i])
2173 {
2174 BIO_printf(bio_err, "No value provided for Subject Attribute %s, skipped\n", ne_types[i]);
2175 continue;
2176 }
2177
2178 if (!X509_NAME_add_entry_by_NID(n, nid, chtype, (unsigned char*)ne_values[i], -1,-1,mval[i]))
2179 goto error;
2180 }
2181
2182 OPENSSL_free(ne_values);
2183 OPENSSL_free(ne_types);
2184 OPENSSL_free(buf);
2185 return n;
2186
2187error:
2188 X509_NAME_free(n);
2189 if (ne_values)
2190 OPENSSL_free(ne_values);
2191 if (ne_types)
2192 OPENSSL_free(ne_types);
2193 if (buf)
2194 OPENSSL_free(buf);
2195 return NULL;
2196}
2197
d530017c
RL
2198/* This code MUST COME AFTER anything that uses rename() */
2199#ifdef OPENSSL_SYS_WIN32
f68854b4 2200int WIN32_rename(const char *from, const char *to)
d530017c
RL
2201 {
2202#ifndef OPENSSL_SYS_WINCE
2203 /* Windows rename gives an error if 'to' exists, so delete it
2204 * first and ignore file not found errror
2205 */
2206 if((remove(to) != 0) && (errno != ENOENT))
2207 return -1;
2208#undef rename
2209 return rename(from, to);
2210#else
2211 /* convert strings to UNICODE */
2212 {
2213 BOOL result = FALSE;
2214 WCHAR* wfrom;
2215 WCHAR* wto;
2216 int i;
2217 wfrom = malloc((strlen(from)+1)*2);
2218 wto = malloc((strlen(to)+1)*2);
2219 if (wfrom != NULL && wto != NULL)
2220 {
2221 for (i=0; i<(int)strlen(from)+1; i++)
2222 wfrom[i] = (short)from[i];
2223 for (i=0; i<(int)strlen(to)+1; i++)
2224 wto[i] = (short)to[i];
2225 result = MoveFile(wfrom, wto);
2226 }
2227 if (wfrom != NULL)
2228 free(wfrom);
2229 if (wto != NULL)
2230 free(wto);
2231 return result;
2232 }
2233#endif
2234 }
2235#endif
5d7c222d 2236
c431798e
DSH
2237int args_verify(char ***pargs, int *pargc,
2238 int *badarg, BIO *err, X509_VERIFY_PARAM **pm)
5d7c222d
DSH
2239 {
2240 ASN1_OBJECT *otmp = NULL;
2241 unsigned long flags = 0;
c431798e
DSH
2242 int i;
2243 int purpose = 0;
2244 char **oldargs = *pargs;
5d7c222d
DSH
2245 char *arg = **pargs, *argn = (*pargs)[1];
2246 if (!strcmp(arg, "-policy"))
2247 {
2248 if (!argn)
2249 *badarg = 1;
2250 else
2251 {
2252 otmp = OBJ_txt2obj(argn, 0);
2253 if (!otmp)
2254 {
2255 BIO_printf(err, "Invalid Policy \"%s\"\n",
2256 argn);
2257 *badarg = 1;
2258 }
2259 }
2260 (*pargs)++;
2261 }
c431798e
DSH
2262 else if (strcmp(arg,"-purpose") == 0)
2263 {
2264 X509_PURPOSE *xptmp;
2265 if (!argn)
2266 *badarg = 1;
2267 else
2268 {
2269 i = X509_PURPOSE_get_by_sname(argn);
2270 if(i < 0)
2271 {
2272 BIO_printf(err, "unrecognized purpose\n");
2273 *badarg = 1;
2274 }
2275 else
2276 {
2277 xptmp = X509_PURPOSE_get0(i);
2278 purpose = X509_PURPOSE_get_id(xptmp);
2279 }
2280 }
2281 (*pargs)++;
2282 }
5d7c222d
DSH
2283 else if (!strcmp(arg, "-ignore_critical"))
2284 flags |= X509_V_FLAG_IGNORE_CRITICAL;
2285 else if (!strcmp(arg, "-issuer_checks"))
2286 flags |= X509_V_FLAG_CB_ISSUER_CHECK;
2287 else if (!strcmp(arg, "-crl_check"))
2288 flags |= X509_V_FLAG_CRL_CHECK;
2289 else if (!strcmp(arg, "-crl_check_all"))
2290 flags |= X509_V_FLAG_CRL_CHECK|X509_V_FLAG_CRL_CHECK_ALL;
2291 else if (!strcmp(arg, "-policy_check"))
2292 flags |= X509_V_FLAG_POLICY_CHECK;
2293 else if (!strcmp(arg, "-explicit_policy"))
2294 flags |= X509_V_FLAG_EXPLICIT_POLICY;
2295 else if (!strcmp(arg, "-x509_strict"))
2296 flags |= X509_V_FLAG_X509_STRICT;
2297 else if (!strcmp(arg, "-policy_print"))
2298 flags |= X509_V_FLAG_NOTIFY_POLICY;
2299 else
2300 return 0;
2301
2302 if (*badarg)
2303 {
2304 if (*pm)
2305 X509_VERIFY_PARAM_free(*pm);
2306 *pm = NULL;
c431798e 2307 goto end;
5d7c222d
DSH
2308 }
2309
2310 if (!*pm && !(*pm = X509_VERIFY_PARAM_new()))
2311 {
2312 *badarg = 1;
c431798e 2313 goto end;
5d7c222d
DSH
2314 }
2315
2316 if (otmp)
2317 X509_VERIFY_PARAM_add0_policy(*pm, otmp);
2318 if (flags)
2319 X509_VERIFY_PARAM_set_flags(*pm, flags);
2320
c431798e
DSH
2321 if (purpose)
2322 X509_VERIFY_PARAM_set_purpose(*pm, purpose);
2323
2324 end:
2325
5d7c222d
DSH
2326 (*pargs)++;
2327
c431798e
DSH
2328 if (pargc)
2329 *pargc -= *pargs - oldargs;
2330
5d7c222d
DSH
2331 return 1;
2332
2333 }
c431798e 2334
7d727231
NL
2335static void nodes_print(BIO *out, const char *name,
2336 STACK_OF(X509_POLICY_NODE) *nodes)
c431798e
DSH
2337 {
2338 X509_POLICY_NODE *node;
2339 int i;
2340 BIO_printf(out, "%s Policies:", name);
2341 if (nodes)
2342 {
2343 BIO_puts(out, "\n");
2344 for (i = 0; i < sk_X509_POLICY_NODE_num(nodes); i++)
2345 {
2346 node = sk_X509_POLICY_NODE_value(nodes, i);
2347 X509_POLICY_NODE_print(out, node, 2);
2348 }
2349 }
2350 else
2351 BIO_puts(out, " <empty>\n");
2352 }
2353
2354void policies_print(BIO *out, X509_STORE_CTX *ctx)
2355 {
2356 X509_POLICY_TREE *tree;
2357 int explicit_policy;
2358 int free_out = 0;
2359 if (out == NULL)
2360 {
2361 out = BIO_new_fp(stderr, BIO_NOCLOSE);
2362 free_out = 1;
2363 }
2364 tree = X509_STORE_CTX_get0_policy_tree(ctx);
2365 explicit_policy = X509_STORE_CTX_get_explicit_policy(ctx);
2366
2367 BIO_printf(out, "Require explicit Policy: %s\n",
2368 explicit_policy ? "True" : "False");
2369
2370 nodes_print(out, "Authority", X509_policy_tree_get0_policies(tree));
2371 nodes_print(out, "User", X509_policy_tree_get0_user_policies(tree));
2372 if (free_out)
2373 BIO_free(out);
2374 }
ffa10187
AP
2375
2376#if defined(_WIN32)
2377int app_isdir(const char *name)
2378 {
2379 HANDLE hList;
2380 WIN32_FIND_DATA FileData;
2381#if defined(UNICODE) || defined(_UNICODE)
2382 size_t i, len_0 = strlen(name)+1;
2383
2384 if (len_0 > sizeof(FileData.cFileName)/sizeof(FileData.cFileName[0]))
2385 return -1;
2386
2387#if !defined(_WIN32_WCE) || _WIN32_WCE>=101
2388 if (!MultiByteToWideChar(CP_ACP,0,name,len_0,FileData.cFileName,len_0))
2389#endif
2390 for (i=0;i<len_0;i++)
2391 FileData.cFileName[i] = (WCHAR)name[i];
2392
2393 hList = FindFirstFile(FileData.cFileName,&FileData);
2394#else
2395 hList = FindFirstFile(name,&FileData);
2396#endif
2397 if (hList == INVALID_HANDLE_VALUE) return -1;
2398 FindClose(hList);
2399 return ((FileData.dwFileAttributes&FILE_ATTRIBUTE_DIRECTORY)!=0);
2400 }
2401#else
2402#include <sys/stat.h>
2403#ifndef S_ISDIR
2404# if defined(_S_IFMT) && defined(_S_IFDIR)
2405# define S_ISDIR(a) (((a) & _S_IFMT) == _S_IFDIR)
2406# else
2407# define S_ISDIR(a) (((a) & S_IFMT) == S_IFDIR)
2408# endif
2409#endif
2410
2411int app_isdir(const char *name)
2412 {
2413#if defined(S_ISDIR)
2414 struct stat st;
2415
2416 if (stat(name,&st)==0) return S_ISDIR(st.st_mode);
2417 else return -1;
2418#else
2419 return -1;
2420#endif
2421 }
2422#endif
2423
2424#if defined(_WIN32) && defined(STD_INPUT_HANDLE)
2425int raw_read_stdin(void *buf,int siz)
2426 {
2427 DWORD n;
2428 if (ReadFile(GetStdHandle(STD_INPUT_HANDLE),buf,siz,&n,NULL))
2429 return (n);
2430 else return (-1);
2431 }
2432#else
2433int raw_read_stdin(void *buf,int siz)
2434 { return read(fileno(stdin),buf,siz); }
2435#endif
2436
2437#if defined(_WIN32) && defined(STD_OUTPUT_HANDLE)
2438int raw_write_stdout(void *buf,int siz)
2439 {
2440 DWORD n;
2441 if (WriteFile(GetStdHandle(STD_OUTPUT_HANDLE),buf,siz,&n,NULL))
2442 return (n);
2443 else return (-1);
2444 }
2445#else
2446int raw_write_stdout(const void *buf,int siz)
2447 { return write(fileno(stdout),buf,siz); }
2448#endif
2449