155714Skris/* apps/apps.c */
255714Skris/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
355714Skris * All rights reserved.
455714Skris *
555714Skris * This package is an SSL implementation written
655714Skris * by Eric Young (eay@cryptsoft.com).
755714Skris * The implementation was written so as to conform with Netscapes SSL.
8296341Sdelphij *
955714Skris * This library is free for commercial and non-commercial use as long as
1055714Skris * the following conditions are aheared to.  The following conditions
1155714Skris * apply to all code found in this distribution, be it the RC4, RSA,
1255714Skris * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
1355714Skris * included with this distribution is covered by the same copyright terms
1455714Skris * except that the holder is Tim Hudson (tjh@cryptsoft.com).
15296341Sdelphij *
1655714Skris * Copyright remains Eric Young's, and as such any Copyright notices in
1755714Skris * the code are not to be removed.
1855714Skris * If this package is used in a product, Eric Young should be given attribution
1955714Skris * as the author of the parts of the library used.
2055714Skris * This can be in the form of a textual message at program startup or
2155714Skris * in documentation (online or textual) provided with the package.
22296341Sdelphij *
2355714Skris * Redistribution and use in source and binary forms, with or without
2455714Skris * modification, are permitted provided that the following conditions
2555714Skris * are met:
2655714Skris * 1. Redistributions of source code must retain the copyright
2755714Skris *    notice, this list of conditions and the following disclaimer.
2855714Skris * 2. Redistributions in binary form must reproduce the above copyright
2955714Skris *    notice, this list of conditions and the following disclaimer in the
3055714Skris *    documentation and/or other materials provided with the distribution.
3155714Skris * 3. All advertising materials mentioning features or use of this software
3255714Skris *    must display the following acknowledgement:
3355714Skris *    "This product includes cryptographic software written by
3455714Skris *     Eric Young (eay@cryptsoft.com)"
3555714Skris *    The word 'cryptographic' can be left out if the rouines from the library
3655714Skris *    being used are not cryptographic related :-).
37296341Sdelphij * 4. If you include any Windows specific code (or a derivative thereof) from
3855714Skris *    the apps directory (application code) you must include an acknowledgement:
3955714Skris *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
40296341Sdelphij *
4155714Skris * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
4255714Skris * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
4355714Skris * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
4455714Skris * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
4555714Skris * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
4655714Skris * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
4755714Skris * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
4855714Skris * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
4955714Skris * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
5055714Skris * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
5155714Skris * SUCH DAMAGE.
52296341Sdelphij *
5355714Skris * The licence and distribution terms for any publically available version or
5455714Skris * derivative of this code cannot be changed.  i.e. this code cannot simply be
5555714Skris * copied and put under another distribution licence
5655714Skris * [including the GNU Public Licence.]
5755714Skris */
58109998Smarkm/* ====================================================================
59109998Smarkm * Copyright (c) 1998-2001 The OpenSSL Project.  All rights reserved.
60109998Smarkm *
61109998Smarkm * Redistribution and use in source and binary forms, with or without
62109998Smarkm * modification, are permitted provided that the following conditions
63109998Smarkm * are met:
64109998Smarkm *
65109998Smarkm * 1. Redistributions of source code must retain the above copyright
66296341Sdelphij *    notice, this list of conditions and the following disclaimer.
67109998Smarkm *
68109998Smarkm * 2. Redistributions in binary form must reproduce the above copyright
69109998Smarkm *    notice, this list of conditions and the following disclaimer in
70109998Smarkm *    the documentation and/or other materials provided with the
71109998Smarkm *    distribution.
72109998Smarkm *
73109998Smarkm * 3. All advertising materials mentioning features or use of this
74109998Smarkm *    software must display the following acknowledgment:
75109998Smarkm *    "This product includes software developed by the OpenSSL Project
76109998Smarkm *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
77109998Smarkm *
78109998Smarkm * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
79109998Smarkm *    endorse or promote products derived from this software without
80109998Smarkm *    prior written permission. For written permission, please contact
81109998Smarkm *    openssl-core@openssl.org.
82109998Smarkm *
83109998Smarkm * 5. Products derived from this software may not be called "OpenSSL"
84109998Smarkm *    nor may "OpenSSL" appear in their names without prior written
85109998Smarkm *    permission of the OpenSSL Project.
86109998Smarkm *
87109998Smarkm * 6. Redistributions of any form whatsoever must retain the following
88109998Smarkm *    acknowledgment:
89109998Smarkm *    "This product includes software developed by the OpenSSL Project
90109998Smarkm *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
91109998Smarkm *
92109998Smarkm * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
93109998Smarkm * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
94109998Smarkm * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
95109998Smarkm * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
96109998Smarkm * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
97109998Smarkm * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
98109998Smarkm * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
99109998Smarkm * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
100109998Smarkm * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
101109998Smarkm * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
102109998Smarkm * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
103109998Smarkm * OF THE POSSIBILITY OF SUCH DAMAGE.
104109998Smarkm * ====================================================================
105109998Smarkm *
106109998Smarkm * This product includes cryptographic software written by Eric Young
107109998Smarkm * (eay@cryptsoft.com).  This product includes software written by Tim
108109998Smarkm * Hudson (tjh@cryptsoft.com).
109109998Smarkm *
110109998Smarkm */
11155714Skris
112238405Sjkim#if !defined(_POSIX_C_SOURCE) && defined(OPENSSL_SYS_VMS)
113296341Sdelphij/*
114296341Sdelphij * On VMS, you need to define this to get the declaration of fileno().  The
115296341Sdelphij * value 2 is to make sure no function defined in POSIX-2 is left undefined.
116296341Sdelphij */
117296341Sdelphij# define _POSIX_C_SOURCE 2
118238405Sjkim#endif
11955714Skris#include <stdio.h>
12055714Skris#include <stdlib.h>
12155714Skris#include <string.h>
122238405Sjkim#if !defined(OPENSSL_SYSNAME_WIN32) && !defined(NETWARE_CLIB)
123296341Sdelphij# include <strings.h>
124238405Sjkim#endif
12555714Skris#include <sys/types.h>
126109998Smarkm#include <ctype.h>
127238405Sjkim#include <errno.h>
128194206Ssimon#include <assert.h>
12968651Skris#include <openssl/err.h>
13068651Skris#include <openssl/x509.h>
131109998Smarkm#include <openssl/x509v3.h>
13268651Skris#include <openssl/pem.h>
13368651Skris#include <openssl/pkcs12.h>
134109998Smarkm#include <openssl/ui.h>
13568651Skris#include <openssl/safestack.h>
136111147Snectar#ifndef OPENSSL_NO_ENGINE
137296341Sdelphij# include <openssl/engine.h>
138111147Snectar#endif
139160814Ssimon#ifndef OPENSSL_NO_RSA
140296341Sdelphij# include <openssl/rsa.h>
141160814Ssimon#endif
142160814Ssimon#include <openssl/bn.h>
143194206Ssimon#ifndef OPENSSL_NO_JPAKE
144296341Sdelphij# include <openssl/jpake.h>
145194206Ssimon#endif
14655714Skris
147109998Smarkm#define NON_MAIN
148109998Smarkm#include "apps.h"
149109998Smarkm#undef NON_MAIN
150109998Smarkm
151238405Sjkim#ifdef _WIN32
152238405Sjkimstatic int WIN32_rename(const char *from, const char *to);
153296341Sdelphij# define rename(from,to) WIN32_rename((from),(to))
154238405Sjkim#endif
155238405Sjkim
156109998Smarkmtypedef struct {
157296341Sdelphij    const char *name;
158296341Sdelphij    unsigned long flag;
159296341Sdelphij    unsigned long mask;
160109998Smarkm} NAME_EX_TBL;
161109998Smarkm
162109998Smarkmstatic UI_METHOD *ui_method = NULL;
163109998Smarkm
164296341Sdelphijstatic int set_table_opts(unsigned long *flags, const char *arg,
165296341Sdelphij                          const NAME_EX_TBL * in_tbl);
166296341Sdelphijstatic int set_multi_opts(unsigned long *flags, const char *arg,
167296341Sdelphij                          const NAME_EX_TBL * in_tbl);
168109998Smarkm
169109998Smarkm#if !defined(OPENSSL_NO_RC4) && !defined(OPENSSL_NO_RSA)
170109998Smarkm/* Looks like this stuff is worth moving into separate function */
171296341Sdelphijstatic EVP_PKEY *load_netscape_key(BIO *err, BIO *key, const char *file,
172296341Sdelphij                                   const char *key_descrip, int format);
173109998Smarkm#endif
174109998Smarkm
17555714Skrisint app_init(long mesgwin);
176296341Sdelphij#ifdef undef                    /* never finished - probably never will be
177296341Sdelphij                                 * :-) */
17855714Skrisint args_from_file(char *file, int *argc, char **argv[])
179296341Sdelphij{
180296341Sdelphij    FILE *fp;
181296341Sdelphij    int num, i;
182296341Sdelphij    unsigned int len;
183296341Sdelphij    static char *buf = NULL;
184296341Sdelphij    static char **arg = NULL;
185296341Sdelphij    char *p;
18655714Skris
187296341Sdelphij    fp = fopen(file, "r");
188296341Sdelphij    if (fp == NULL)
189296341Sdelphij        return (0);
19055714Skris
191296341Sdelphij    if (fseek(fp, 0, SEEK_END) == 0)
192296341Sdelphij        len = ftell(fp), rewind(fp);
193296341Sdelphij    else
194296341Sdelphij        len = -1;
195296341Sdelphij    if (len <= 0) {
196296341Sdelphij        fclose(fp);
197296341Sdelphij        return (0);
198296341Sdelphij    }
199238405Sjkim
200296341Sdelphij    *argc = 0;
201296341Sdelphij    *argv = NULL;
20255714Skris
203296341Sdelphij    if (buf != NULL)
204296341Sdelphij        OPENSSL_free(buf);
205296341Sdelphij    buf = (char *)OPENSSL_malloc(len + 1);
206296341Sdelphij    if (buf == NULL)
207296341Sdelphij        return (0);
20855714Skris
209296341Sdelphij    len = fread(buf, 1, len, fp);
210296341Sdelphij    if (len <= 1)
211296341Sdelphij        return (0);
212296341Sdelphij    buf[len] = '\0';
21355714Skris
214296341Sdelphij    i = 0;
215296341Sdelphij    for (p = buf; *p; p++)
216296341Sdelphij        if (*p == '\n')
217296341Sdelphij            i++;
218296341Sdelphij    if (arg != NULL)
219296341Sdelphij        OPENSSL_free(arg);
220296341Sdelphij    arg = (char **)OPENSSL_malloc(sizeof(char *) * (i * 2));
22155714Skris
222296341Sdelphij    *argv = arg;
223296341Sdelphij    num = 0;
224296341Sdelphij    p = buf;
225296341Sdelphij    for (;;) {
226296341Sdelphij        if (!*p)
227296341Sdelphij            break;
228296341Sdelphij        if (*p == '#') {        /* comment line */
229296341Sdelphij            while (*p && (*p != '\n'))
230296341Sdelphij                p++;
231296341Sdelphij            continue;
232296341Sdelphij        }
233296341Sdelphij        /* else we have a line */
234296341Sdelphij        *(arg++) = p;
235296341Sdelphij        num++;
236296341Sdelphij        while (*p && ((*p != ' ') && (*p != '\t') && (*p != '\n')))
237296341Sdelphij            p++;
238296341Sdelphij        if (!*p)
239296341Sdelphij            break;
240296341Sdelphij        if (*p == '\n') {
241296341Sdelphij            *(p++) = '\0';
242296341Sdelphij            continue;
243296341Sdelphij        }
244296341Sdelphij        /* else it is a tab or space */
245296341Sdelphij        p++;
246296341Sdelphij        while (*p && ((*p == ' ') || (*p == '\t') || (*p == '\n')))
247296341Sdelphij            p++;
248296341Sdelphij        if (!*p)
249296341Sdelphij            break;
250296341Sdelphij        if (*p == '\n') {
251296341Sdelphij            p++;
252296341Sdelphij            continue;
253296341Sdelphij        }
254296341Sdelphij        *(arg++) = p++;
255296341Sdelphij        num++;
256296341Sdelphij        while (*p && (*p != '\n'))
257296341Sdelphij            p++;
258296341Sdelphij        if (!*p)
259296341Sdelphij            break;
260296341Sdelphij        /* else *p == '\n' */
261296341Sdelphij        *(p++) = '\0';
262296341Sdelphij    }
263296341Sdelphij    *argc = num;
264296341Sdelphij    return (1);
265296341Sdelphij}
26655714Skris#endif
26755714Skris
26855714Skrisint str2fmt(char *s)
269296341Sdelphij{
270296341Sdelphij    if (s == NULL)
271296341Sdelphij        return FORMAT_UNDEF;
272296341Sdelphij    if ((*s == 'D') || (*s == 'd'))
273296341Sdelphij        return (FORMAT_ASN1);
274296341Sdelphij    else if ((*s == 'T') || (*s == 't'))
275296341Sdelphij        return (FORMAT_TEXT);
276296341Sdelphij    else if ((*s == 'N') || (*s == 'n'))
277296341Sdelphij        return (FORMAT_NETSCAPE);
278296341Sdelphij    else if ((*s == 'S') || (*s == 's'))
279296341Sdelphij        return (FORMAT_SMIME);
280296341Sdelphij    else if ((*s == 'M') || (*s == 'm'))
281296341Sdelphij        return (FORMAT_MSBLOB);
282296341Sdelphij    else if ((*s == '1')
283296341Sdelphij             || (strcmp(s, "PKCS12") == 0) || (strcmp(s, "pkcs12") == 0)
284296341Sdelphij             || (strcmp(s, "P12") == 0) || (strcmp(s, "p12") == 0))
285296341Sdelphij        return (FORMAT_PKCS12);
286296341Sdelphij    else if ((*s == 'E') || (*s == 'e'))
287296341Sdelphij        return (FORMAT_ENGINE);
288296341Sdelphij    else if ((*s == 'P') || (*s == 'p')) {
289296341Sdelphij        if (s[1] == 'V' || s[1] == 'v')
290296341Sdelphij            return FORMAT_PVK;
291296341Sdelphij        else
292296341Sdelphij            return (FORMAT_PEM);
293296341Sdelphij    } else
294296341Sdelphij        return (FORMAT_UNDEF);
295296341Sdelphij}
29655714Skris
297160814Ssimon#if defined(OPENSSL_SYS_MSDOS) || defined(OPENSSL_SYS_WIN32) || defined(OPENSSL_SYS_WIN16) || defined(OPENSSL_SYS_NETWARE)
29855714Skrisvoid program_name(char *in, char *out, int size)
299296341Sdelphij{
300296341Sdelphij    int i, n;
301296341Sdelphij    char *p = NULL;
30255714Skris
303296341Sdelphij    n = strlen(in);
304296341Sdelphij    /* find the last '/', '\' or ':' */
305296341Sdelphij    for (i = n - 1; i > 0; i--) {
306296341Sdelphij        if ((in[i] == '/') || (in[i] == '\\') || (in[i] == ':')) {
307296341Sdelphij            p = &(in[i + 1]);
308296341Sdelphij            break;
309296341Sdelphij        }
310296341Sdelphij    }
311296341Sdelphij    if (p == NULL)
312296341Sdelphij        p = in;
313296341Sdelphij    n = strlen(p);
314160814Ssimon
315296341Sdelphij# if defined(OPENSSL_SYS_NETWARE)
316296341Sdelphij    /* strip off trailing .nlm if present. */
317296341Sdelphij    if ((n > 4) && (p[n - 4] == '.') &&
318296341Sdelphij        ((p[n - 3] == 'n') || (p[n - 3] == 'N')) &&
319296341Sdelphij        ((p[n - 2] == 'l') || (p[n - 2] == 'L')) &&
320296341Sdelphij        ((p[n - 1] == 'm') || (p[n - 1] == 'M')))
321296341Sdelphij        n -= 4;
322296341Sdelphij# else
323296341Sdelphij    /* strip off trailing .exe if present. */
324296341Sdelphij    if ((n > 4) && (p[n - 4] == '.') &&
325296341Sdelphij        ((p[n - 3] == 'e') || (p[n - 3] == 'E')) &&
326296341Sdelphij        ((p[n - 2] == 'x') || (p[n - 2] == 'X')) &&
327296341Sdelphij        ((p[n - 1] == 'e') || (p[n - 1] == 'E')))
328296341Sdelphij        n -= 4;
329296341Sdelphij# endif
330160814Ssimon
331296341Sdelphij    if (n > size - 1)
332296341Sdelphij        n = size - 1;
33355714Skris
334296341Sdelphij    for (i = 0; i < n; i++) {
335296341Sdelphij        if ((p[i] >= 'A') && (p[i] <= 'Z'))
336296341Sdelphij            out[i] = p[i] - 'A' + 'a';
337296341Sdelphij        else
338296341Sdelphij            out[i] = p[i];
339296341Sdelphij    }
340296341Sdelphij    out[n] = '\0';
341296341Sdelphij}
34255714Skris#else
343296341Sdelphij# ifdef OPENSSL_SYS_VMS
34455714Skrisvoid program_name(char *in, char *out, int size)
345296341Sdelphij{
346296341Sdelphij    char *p = in, *q;
347296341Sdelphij    char *chars = ":]>";
34855714Skris
349296341Sdelphij    while (*chars != '\0') {
350296341Sdelphij        q = strrchr(p, *chars);
351296341Sdelphij        if (q > p)
352296341Sdelphij            p = q + 1;
353296341Sdelphij        chars++;
354296341Sdelphij    }
35555714Skris
356296341Sdelphij    q = strrchr(p, '.');
357296341Sdelphij    if (q == NULL)
358296341Sdelphij        q = p + strlen(p);
359296341Sdelphij    strncpy(out, p, size - 1);
360296341Sdelphij    if (q - p >= size) {
361296341Sdelphij        out[size - 1] = '\0';
362296341Sdelphij    } else {
363296341Sdelphij        out[q - p] = '\0';
364296341Sdelphij    }
365296341Sdelphij}
366296341Sdelphij# else
36755714Skrisvoid program_name(char *in, char *out, int size)
368296341Sdelphij{
369296341Sdelphij    char *p;
37055714Skris
371296341Sdelphij    p = strrchr(in, '/');
372296341Sdelphij    if (p != NULL)
373296341Sdelphij        p++;
374296341Sdelphij    else
375296341Sdelphij        p = in;
376296341Sdelphij    BUF_strlcpy(out, p, size);
377296341Sdelphij}
378296341Sdelphij# endif
37955714Skris#endif
38055714Skris
38155714Skrisint chopup_args(ARGS *arg, char *buf, int *argc, char **argv[])
382296341Sdelphij{
383296341Sdelphij    int num, i;
384296341Sdelphij    char *p;
38555714Skris
386296341Sdelphij    *argc = 0;
387296341Sdelphij    *argv = NULL;
38855714Skris
389296341Sdelphij    i = 0;
390296341Sdelphij    if (arg->count == 0) {
391296341Sdelphij        arg->count = 20;
392296341Sdelphij        arg->data = (char **)OPENSSL_malloc(sizeof(char *) * arg->count);
393296341Sdelphij        if (arg->data == NULL)
394296341Sdelphij            return 0;
395296341Sdelphij    }
396296341Sdelphij    for (i = 0; i < arg->count; i++)
397296341Sdelphij        arg->data[i] = NULL;
39855714Skris
399296341Sdelphij    num = 0;
400296341Sdelphij    p = buf;
401296341Sdelphij    for (;;) {
402296341Sdelphij        /* first scan over white space */
403296341Sdelphij        if (!*p)
404296341Sdelphij            break;
405296341Sdelphij        while (*p && ((*p == ' ') || (*p == '\t') || (*p == '\n')))
406296341Sdelphij            p++;
407296341Sdelphij        if (!*p)
408296341Sdelphij            break;
40955714Skris
410296341Sdelphij        /* The start of something good :-) */
411296341Sdelphij        if (num >= arg->count) {
412296341Sdelphij            char **tmp_p;
413296341Sdelphij            int tlen = arg->count + 20;
414296341Sdelphij            tmp_p = (char **)OPENSSL_realloc(arg->data,
415296341Sdelphij                                             sizeof(char *) * tlen);
416296341Sdelphij            if (tmp_p == NULL)
417296341Sdelphij                return 0;
418296341Sdelphij            arg->data = tmp_p;
419296341Sdelphij            arg->count = tlen;
420296341Sdelphij            /* initialize newly allocated data */
421296341Sdelphij            for (i = num; i < arg->count; i++)
422296341Sdelphij                arg->data[i] = NULL;
423296341Sdelphij        }
424296341Sdelphij        arg->data[num++] = p;
42555714Skris
426296341Sdelphij        /* now look for the end of this */
427296341Sdelphij        if ((*p == '\'') || (*p == '\"')) { /* scan for closing quote */
428296341Sdelphij            i = *(p++);
429296341Sdelphij            arg->data[num - 1]++; /* jump over quote */
430296341Sdelphij            while (*p && (*p != i))
431296341Sdelphij                p++;
432296341Sdelphij            *p = '\0';
433296341Sdelphij        } else {
434296341Sdelphij            while (*p && ((*p != ' ') && (*p != '\t') && (*p != '\n')))
435296341Sdelphij                p++;
43655714Skris
437296341Sdelphij            if (*p == '\0')
438296341Sdelphij                p--;
439296341Sdelphij            else
440296341Sdelphij                *p = '\0';
441296341Sdelphij        }
442296341Sdelphij        p++;
443296341Sdelphij    }
444296341Sdelphij    *argc = num;
445296341Sdelphij    *argv = arg->data;
446296341Sdelphij    return (1);
447296341Sdelphij}
44855714Skris
44955714Skris#ifndef APP_INIT
45055714Skrisint app_init(long mesgwin)
451296341Sdelphij{
452296341Sdelphij    return (1);
453296341Sdelphij}
45455714Skris#endif
45559191Skris
456296341Sdelphijint dump_cert_text(BIO *out, X509 *x)
45759191Skris{
458296341Sdelphij    char *p;
459109998Smarkm
460296341Sdelphij    p = X509_NAME_oneline(X509_get_subject_name(x), NULL, 0);
461296341Sdelphij    BIO_puts(out, "subject=");
462296341Sdelphij    BIO_puts(out, p);
463296341Sdelphij    OPENSSL_free(p);
46459191Skris
465296341Sdelphij    p = X509_NAME_oneline(X509_get_issuer_name(x), NULL, 0);
466296341Sdelphij    BIO_puts(out, "\nissuer=");
467296341Sdelphij    BIO_puts(out, p);
468296341Sdelphij    BIO_puts(out, "\n");
469296341Sdelphij    OPENSSL_free(p);
470109998Smarkm
471296341Sdelphij    return 0;
47259191Skris}
47359191Skris
474109998Smarkmstatic int ui_open(UI *ui)
475296341Sdelphij{
476296341Sdelphij    return UI_method_get_opener(UI_OpenSSL())(ui);
477296341Sdelphij}
478296341Sdelphij
479109998Smarkmstatic int ui_read(UI *ui, UI_STRING *uis)
480296341Sdelphij{
481296341Sdelphij    if (UI_get_input_flags(uis) & UI_INPUT_FLAG_DEFAULT_PWD
482296341Sdelphij        && UI_get0_user_data(ui)) {
483296341Sdelphij        switch (UI_get_string_type(uis)) {
484296341Sdelphij        case UIT_PROMPT:
485296341Sdelphij        case UIT_VERIFY:
486296341Sdelphij            {
487296341Sdelphij                const char *password =
488296341Sdelphij                    ((PW_CB_DATA *)UI_get0_user_data(ui))->password;
489296341Sdelphij                if (password && password[0] != '\0') {
490296341Sdelphij                    UI_set_result(ui, uis, password);
491296341Sdelphij                    return 1;
492296341Sdelphij                }
493296341Sdelphij            }
494296341Sdelphij        default:
495296341Sdelphij            break;
496296341Sdelphij        }
497296341Sdelphij    }
498296341Sdelphij    return UI_method_get_reader(UI_OpenSSL())(ui, uis);
499296341Sdelphij}
500296341Sdelphij
501109998Smarkmstatic int ui_write(UI *ui, UI_STRING *uis)
502296341Sdelphij{
503296341Sdelphij    if (UI_get_input_flags(uis) & UI_INPUT_FLAG_DEFAULT_PWD
504296341Sdelphij        && UI_get0_user_data(ui)) {
505296341Sdelphij        switch (UI_get_string_type(uis)) {
506296341Sdelphij        case UIT_PROMPT:
507296341Sdelphij        case UIT_VERIFY:
508296341Sdelphij            {
509296341Sdelphij                const char *password =
510296341Sdelphij                    ((PW_CB_DATA *)UI_get0_user_data(ui))->password;
511296341Sdelphij                if (password && password[0] != '\0')
512296341Sdelphij                    return 1;
513296341Sdelphij            }
514296341Sdelphij        default:
515296341Sdelphij            break;
516296341Sdelphij        }
517296341Sdelphij    }
518296341Sdelphij    return UI_method_get_writer(UI_OpenSSL())(ui, uis);
519296341Sdelphij}
520296341Sdelphij
521109998Smarkmstatic int ui_close(UI *ui)
522296341Sdelphij{
523296341Sdelphij    return UI_method_get_closer(UI_OpenSSL())(ui);
524296341Sdelphij}
525296341Sdelphij
526109998Smarkmint setup_ui_method(void)
527296341Sdelphij{
528296341Sdelphij    ui_method = UI_create_method("OpenSSL application user interface");
529296341Sdelphij    UI_method_set_opener(ui_method, ui_open);
530296341Sdelphij    UI_method_set_reader(ui_method, ui_read);
531296341Sdelphij    UI_method_set_writer(ui_method, ui_write);
532296341Sdelphij    UI_method_set_closer(ui_method, ui_close);
533296341Sdelphij    return 0;
534296341Sdelphij}
535296341Sdelphij
536109998Smarkmvoid destroy_ui_method(void)
537296341Sdelphij{
538296341Sdelphij    if (ui_method) {
539296341Sdelphij        UI_destroy_method(ui_method);
540296341Sdelphij        ui_method = NULL;
541296341Sdelphij    }
542296341Sdelphij}
543109998Smarkm
544296341Sdelphijint password_callback(char *buf, int bufsiz, int verify, PW_CB_DATA *cb_tmp)
545296341Sdelphij{
546296341Sdelphij    UI *ui = NULL;
547296341Sdelphij    int res = 0;
548296341Sdelphij    const char *prompt_info = NULL;
549296341Sdelphij    const char *password = NULL;
550296341Sdelphij    PW_CB_DATA *cb_data = (PW_CB_DATA *)cb_tmp;
551109998Smarkm
552296341Sdelphij    if (cb_data) {
553296341Sdelphij        if (cb_data->password)
554296341Sdelphij            password = cb_data->password;
555296341Sdelphij        if (cb_data->prompt_info)
556296341Sdelphij            prompt_info = cb_data->prompt_info;
557296341Sdelphij    }
558109998Smarkm
559296341Sdelphij    if (password) {
560296341Sdelphij        res = strlen(password);
561296341Sdelphij        if (res > bufsiz)
562296341Sdelphij            res = bufsiz;
563296341Sdelphij        memcpy(buf, password, res);
564296341Sdelphij        return res;
565296341Sdelphij    }
566109998Smarkm
567296341Sdelphij    ui = UI_new_method(ui_method);
568296341Sdelphij    if (ui) {
569296341Sdelphij        int ok = 0;
570296341Sdelphij        char *buff = NULL;
571296341Sdelphij        int ui_flags = 0;
572296341Sdelphij        char *prompt = NULL;
573109998Smarkm
574296341Sdelphij        prompt = UI_construct_prompt(ui, "pass phrase", prompt_info);
575296341Sdelphij        if (!prompt) {
576296341Sdelphij            BIO_printf(bio_err, "Out of memory\n");
577296341Sdelphij            UI_free(ui);
578296341Sdelphij            return 0;
579296341Sdelphij        }
580109998Smarkm
581296341Sdelphij        ui_flags |= UI_INPUT_FLAG_DEFAULT_PWD;
582296341Sdelphij        UI_ctrl(ui, UI_CTRL_PRINT_ERRORS, 1, 0, 0);
583109998Smarkm
584296341Sdelphij        if (ok >= 0)
585296341Sdelphij            ok = UI_add_input_string(ui, prompt, ui_flags, buf,
586296341Sdelphij                                     PW_MIN_LENGTH, bufsiz - 1);
587296341Sdelphij        if (ok >= 0 && verify) {
588296341Sdelphij            buff = (char *)OPENSSL_malloc(bufsiz);
589296341Sdelphij            if (!buff) {
590296341Sdelphij                BIO_printf(bio_err, "Out of memory\n");
591296341Sdelphij                UI_free(ui);
592296341Sdelphij                OPENSSL_free(prompt);
593296341Sdelphij                return 0;
594296341Sdelphij            }
595296341Sdelphij            ok = UI_add_verify_string(ui, prompt, ui_flags, buff,
596296341Sdelphij                                      PW_MIN_LENGTH, bufsiz - 1, buf);
597296341Sdelphij        }
598296341Sdelphij        if (ok >= 0)
599296341Sdelphij            do {
600296341Sdelphij                ok = UI_process(ui);
601296341Sdelphij            }
602296341Sdelphij            while (ok < 0 && UI_ctrl(ui, UI_CTRL_IS_REDOABLE, 0, 0, 0));
603109998Smarkm
604296341Sdelphij        if (buff) {
605296341Sdelphij            OPENSSL_cleanse(buff, (unsigned int)bufsiz);
606296341Sdelphij            OPENSSL_free(buff);
607296341Sdelphij        }
608109998Smarkm
609296341Sdelphij        if (ok >= 0)
610296341Sdelphij            res = strlen(buf);
611296341Sdelphij        if (ok == -1) {
612296341Sdelphij            BIO_printf(bio_err, "User interface error\n");
613296341Sdelphij            ERR_print_errors(bio_err);
614296341Sdelphij            OPENSSL_cleanse(buf, (unsigned int)bufsiz);
615296341Sdelphij            res = 0;
616296341Sdelphij        }
617296341Sdelphij        if (ok == -2) {
618296341Sdelphij            BIO_printf(bio_err, "aborted!\n");
619296341Sdelphij            OPENSSL_cleanse(buf, (unsigned int)bufsiz);
620296341Sdelphij            res = 0;
621296341Sdelphij        }
622296341Sdelphij        UI_free(ui);
623296341Sdelphij        OPENSSL_free(prompt);
624296341Sdelphij    }
625296341Sdelphij    return res;
626296341Sdelphij}
627296341Sdelphij
62859191Skrisstatic char *app_get_pass(BIO *err, char *arg, int keepbio);
62959191Skris
63059191Skrisint app_passwd(BIO *err, char *arg1, char *arg2, char **pass1, char **pass2)
63159191Skris{
632296341Sdelphij    int same;
633296341Sdelphij    if (!arg2 || !arg1 || strcmp(arg1, arg2))
634296341Sdelphij        same = 0;
635296341Sdelphij    else
636296341Sdelphij        same = 1;
637296341Sdelphij    if (arg1) {
638296341Sdelphij        *pass1 = app_get_pass(err, arg1, same);
639296341Sdelphij        if (!*pass1)
640296341Sdelphij            return 0;
641296341Sdelphij    } else if (pass1)
642296341Sdelphij        *pass1 = NULL;
643296341Sdelphij    if (arg2) {
644296341Sdelphij        *pass2 = app_get_pass(err, arg2, same ? 2 : 0);
645296341Sdelphij        if (!*pass2)
646296341Sdelphij            return 0;
647296341Sdelphij    } else if (pass2)
648296341Sdelphij        *pass2 = NULL;
649296341Sdelphij    return 1;
65059191Skris}
65159191Skris
65259191Skrisstatic char *app_get_pass(BIO *err, char *arg, int keepbio)
65359191Skris{
654296341Sdelphij    char *tmp, tpass[APP_PASS_LEN];
655296341Sdelphij    static BIO *pwdbio = NULL;
656296341Sdelphij    int i;
657296341Sdelphij    if (!strncmp(arg, "pass:", 5))
658296341Sdelphij        return BUF_strdup(arg + 5);
659296341Sdelphij    if (!strncmp(arg, "env:", 4)) {
660296341Sdelphij        tmp = getenv(arg + 4);
661296341Sdelphij        if (!tmp) {
662296341Sdelphij            BIO_printf(err, "Can't read environment variable %s\n", arg + 4);
663296341Sdelphij            return NULL;
664296341Sdelphij        }
665296341Sdelphij        return BUF_strdup(tmp);
666296341Sdelphij    }
667296341Sdelphij    if (!keepbio || !pwdbio) {
668296341Sdelphij        if (!strncmp(arg, "file:", 5)) {
669296341Sdelphij            pwdbio = BIO_new_file(arg + 5, "r");
670296341Sdelphij            if (!pwdbio) {
671296341Sdelphij                BIO_printf(err, "Can't open file %s\n", arg + 5);
672296341Sdelphij                return NULL;
673296341Sdelphij            }
674238405Sjkim#if !defined(_WIN32)
675296341Sdelphij            /*
676296341Sdelphij             * Under _WIN32, which covers even Win64 and CE, file
677296341Sdelphij             * descriptors referenced by BIO_s_fd are not inherited
678296341Sdelphij             * by child process and therefore below is not an option.
679296341Sdelphij             * It could have been an option if bss_fd.c was operating
680296341Sdelphij             * on real Windows descriptors, such as those obtained
681296341Sdelphij             * with CreateFile.
682296341Sdelphij             */
683296341Sdelphij        } else if (!strncmp(arg, "fd:", 3)) {
684296341Sdelphij            BIO *btmp;
685296341Sdelphij            i = atoi(arg + 3);
686296341Sdelphij            if (i >= 0)
687296341Sdelphij                pwdbio = BIO_new_fd(i, BIO_NOCLOSE);
688296341Sdelphij            if ((i < 0) || !pwdbio) {
689296341Sdelphij                BIO_printf(err, "Can't access file descriptor %s\n", arg + 3);
690296341Sdelphij                return NULL;
691296341Sdelphij            }
692296341Sdelphij            /*
693296341Sdelphij             * Can't do BIO_gets on an fd BIO so add a buffering BIO
694296341Sdelphij             */
695296341Sdelphij            btmp = BIO_new(BIO_f_buffer());
696296341Sdelphij            pwdbio = BIO_push(btmp, pwdbio);
697238405Sjkim#endif
698296341Sdelphij        } else if (!strcmp(arg, "stdin")) {
699296341Sdelphij            pwdbio = BIO_new_fp(stdin, BIO_NOCLOSE);
700296341Sdelphij            if (!pwdbio) {
701296341Sdelphij                BIO_printf(err, "Can't open BIO for stdin\n");
702296341Sdelphij                return NULL;
703296341Sdelphij            }
704296341Sdelphij        } else {
705296341Sdelphij            BIO_printf(err, "Invalid password argument \"%s\"\n", arg);
706296341Sdelphij            return NULL;
707296341Sdelphij        }
708296341Sdelphij    }
709296341Sdelphij    i = BIO_gets(pwdbio, tpass, APP_PASS_LEN);
710296341Sdelphij    if (keepbio != 1) {
711296341Sdelphij        BIO_free_all(pwdbio);
712296341Sdelphij        pwdbio = NULL;
713296341Sdelphij    }
714296341Sdelphij    if (i <= 0) {
715296341Sdelphij        BIO_printf(err, "Error reading password from BIO\n");
716296341Sdelphij        return NULL;
717296341Sdelphij    }
718296341Sdelphij    tmp = strchr(tpass, '\n');
719296341Sdelphij    if (tmp)
720296341Sdelphij        *tmp = 0;
721296341Sdelphij    return BUF_strdup(tpass);
72259191Skris}
72368651Skris
724109998Smarkmint add_oid_section(BIO *err, CONF *conf)
725296341Sdelphij{
726296341Sdelphij    char *p;
727296341Sdelphij    STACK_OF(CONF_VALUE) *sktmp;
728296341Sdelphij    CONF_VALUE *cnf;
729296341Sdelphij    int i;
730296341Sdelphij    if (!(p = NCONF_get_string(conf, NULL, "oid_section"))) {
731296341Sdelphij        ERR_clear_error();
732296341Sdelphij        return 1;
733296341Sdelphij    }
734296341Sdelphij    if (!(sktmp = NCONF_get_section(conf, p))) {
735296341Sdelphij        BIO_printf(err, "problem loading oid section %s\n", p);
736296341Sdelphij        return 0;
737296341Sdelphij    }
738296341Sdelphij    for (i = 0; i < sk_CONF_VALUE_num(sktmp); i++) {
739296341Sdelphij        cnf = sk_CONF_VALUE_value(sktmp, i);
740296341Sdelphij        if (OBJ_create(cnf->value, cnf->name, cnf->name) == NID_undef) {
741296341Sdelphij            BIO_printf(err, "problem creating object %s=%s\n",
742296341Sdelphij                       cnf->name, cnf->value);
743296341Sdelphij            return 0;
744296341Sdelphij        }
745296341Sdelphij    }
746296341Sdelphij    return 1;
74768651Skris}
74868651Skris
749160814Ssimonstatic int load_pkcs12(BIO *err, BIO *in, const char *desc,
750296341Sdelphij                       pem_password_cb *pem_cb, void *cb_data,
751296341Sdelphij                       EVP_PKEY **pkey, X509 **cert, STACK_OF(X509) **ca)
752296341Sdelphij{
753296341Sdelphij    const char *pass;
754296341Sdelphij    char tpass[PEM_BUFSIZE];
755296341Sdelphij    int len, ret = 0;
756296341Sdelphij    PKCS12 *p12;
757296341Sdelphij    p12 = d2i_PKCS12_bio(in, NULL);
758296341Sdelphij    if (p12 == NULL) {
759296341Sdelphij        BIO_printf(err, "Error loading PKCS12 file for %s\n", desc);
760296341Sdelphij        goto die;
761296341Sdelphij    }
762296341Sdelphij    /* See if an empty password will do */
763296341Sdelphij    if (PKCS12_verify_mac(p12, "", 0) || PKCS12_verify_mac(p12, NULL, 0))
764296341Sdelphij        pass = "";
765296341Sdelphij    else {
766296341Sdelphij        if (!pem_cb)
767296341Sdelphij            pem_cb = (pem_password_cb *)password_callback;
768296341Sdelphij        len = pem_cb(tpass, PEM_BUFSIZE, 0, cb_data);
769296341Sdelphij        if (len < 0) {
770296341Sdelphij            BIO_printf(err, "Passpharse callback error for %s\n", desc);
771296341Sdelphij            goto die;
772296341Sdelphij        }
773296341Sdelphij        if (len < PEM_BUFSIZE)
774296341Sdelphij            tpass[len] = 0;
775296341Sdelphij        if (!PKCS12_verify_mac(p12, tpass, len)) {
776296341Sdelphij            BIO_printf(err,
777296341Sdelphij                       "Mac verify error (wrong password?) in PKCS12 file for %s\n",
778296341Sdelphij                       desc);
779296341Sdelphij            goto die;
780296341Sdelphij        }
781296341Sdelphij        pass = tpass;
782296341Sdelphij    }
783296341Sdelphij    ret = PKCS12_parse(p12, pass, pkey, cert, ca);
784296341Sdelphij die:
785296341Sdelphij    if (p12)
786296341Sdelphij        PKCS12_free(p12);
787296341Sdelphij    return ret;
788296341Sdelphij}
789160814Ssimon
790109998SmarkmX509 *load_cert(BIO *err, const char *file, int format,
791296341Sdelphij                const char *pass, ENGINE *e, const char *cert_descrip)
792296341Sdelphij{
793296341Sdelphij    X509 *x = NULL;
794296341Sdelphij    BIO *cert;
79568651Skris
796296341Sdelphij    if ((cert = BIO_new(BIO_s_file())) == NULL) {
797296341Sdelphij        ERR_print_errors(err);
798296341Sdelphij        goto end;
799296341Sdelphij    }
80068651Skris
801296341Sdelphij    if (file == NULL) {
802238405Sjkim#ifdef _IONBF
803238405Sjkim# ifndef OPENSSL_NO_SETVBUF_IONBF
804296341Sdelphij        setvbuf(stdin, NULL, _IONBF, 0);
805296341Sdelphij# endif                         /* ndef OPENSSL_NO_SETVBUF_IONBF */
806238405Sjkim#endif
807296341Sdelphij        BIO_set_fp(cert, stdin, BIO_NOCLOSE);
808296341Sdelphij    } else {
809296341Sdelphij        if (BIO_read_filename(cert, file) <= 0) {
810296341Sdelphij            BIO_printf(err, "Error opening %s %s\n", cert_descrip, file);
811296341Sdelphij            ERR_print_errors(err);
812296341Sdelphij            goto end;
813296341Sdelphij        }
814296341Sdelphij    }
81568651Skris
816296341Sdelphij    if (format == FORMAT_ASN1)
817296341Sdelphij        x = d2i_X509_bio(cert, NULL);
818296341Sdelphij    else if (format == FORMAT_NETSCAPE) {
819296341Sdelphij        NETSCAPE_X509 *nx;
820296341Sdelphij        nx = ASN1_item_d2i_bio(ASN1_ITEM_rptr(NETSCAPE_X509), cert, NULL);
821296341Sdelphij        if (nx == NULL)
822296341Sdelphij            goto end;
82368651Skris
824296341Sdelphij        if ((strncmp(NETSCAPE_CERT_HDR, (char *)nx->header->data,
825296341Sdelphij                     nx->header->length) != 0)) {
826296341Sdelphij            NETSCAPE_X509_free(nx);
827296341Sdelphij            BIO_printf(err, "Error reading header on certificate\n");
828296341Sdelphij            goto end;
829296341Sdelphij        }
830296341Sdelphij        x = nx->cert;
831296341Sdelphij        nx->cert = NULL;
832296341Sdelphij        NETSCAPE_X509_free(nx);
833296341Sdelphij    } else if (format == FORMAT_PEM)
834296341Sdelphij        x = PEM_read_bio_X509_AUX(cert, NULL,
835296341Sdelphij                                  (pem_password_cb *)password_callback, NULL);
836296341Sdelphij    else if (format == FORMAT_PKCS12) {
837296341Sdelphij        if (!load_pkcs12(err, cert, cert_descrip, NULL, NULL, NULL, &x, NULL))
838296341Sdelphij            goto end;
839296341Sdelphij    } else {
840296341Sdelphij        BIO_printf(err, "bad input format specified for %s\n", cert_descrip);
841296341Sdelphij        goto end;
842296341Sdelphij    }
843296341Sdelphij end:
844296341Sdelphij    if (x == NULL) {
845296341Sdelphij        BIO_printf(err, "unable to load certificate\n");
846296341Sdelphij        ERR_print_errors(err);
847296341Sdelphij    }
848296341Sdelphij    if (cert != NULL)
849296341Sdelphij        BIO_free(cert);
850296341Sdelphij    return (x);
851296341Sdelphij}
85268651Skris
853109998SmarkmEVP_PKEY *load_key(BIO *err, const char *file, int format, int maybe_stdin,
854296341Sdelphij                   const char *pass, ENGINE *e, const char *key_descrip)
855296341Sdelphij{
856296341Sdelphij    BIO *key = NULL;
857296341Sdelphij    EVP_PKEY *pkey = NULL;
858296341Sdelphij    PW_CB_DATA cb_data;
85968651Skris
860296341Sdelphij    cb_data.password = pass;
861296341Sdelphij    cb_data.prompt_info = file;
862109998Smarkm
863296341Sdelphij    if (file == NULL && (!maybe_stdin || format == FORMAT_ENGINE)) {
864296341Sdelphij        BIO_printf(err, "no keyfile specified\n");
865296341Sdelphij        goto end;
866296341Sdelphij    }
867111147Snectar#ifndef OPENSSL_NO_ENGINE
868296341Sdelphij    if (format == FORMAT_ENGINE) {
869296341Sdelphij        if (!e)
870296341Sdelphij            BIO_printf(err, "no engine specified\n");
871296341Sdelphij        else {
872296341Sdelphij            pkey = ENGINE_load_private_key(e, file, ui_method, &cb_data);
873296341Sdelphij            if (!pkey) {
874296341Sdelphij                BIO_printf(err, "cannot load %s from engine\n", key_descrip);
875296341Sdelphij                ERR_print_errors(err);
876296341Sdelphij            }
877296341Sdelphij        }
878296341Sdelphij        goto end;
879296341Sdelphij    }
880111147Snectar#endif
881296341Sdelphij    key = BIO_new(BIO_s_file());
882296341Sdelphij    if (key == NULL) {
883296341Sdelphij        ERR_print_errors(err);
884296341Sdelphij        goto end;
885296341Sdelphij    }
886296341Sdelphij    if (file == NULL && maybe_stdin) {
887238405Sjkim#ifdef _IONBF
888238405Sjkim# ifndef OPENSSL_NO_SETVBUF_IONBF
889296341Sdelphij        setvbuf(stdin, NULL, _IONBF, 0);
890296341Sdelphij# endif                         /* ndef OPENSSL_NO_SETVBUF_IONBF */
891238405Sjkim#endif
892296341Sdelphij        BIO_set_fp(key, stdin, BIO_NOCLOSE);
893296341Sdelphij    } else if (BIO_read_filename(key, file) <= 0) {
894296341Sdelphij        BIO_printf(err, "Error opening %s %s\n", key_descrip, file);
895296341Sdelphij        ERR_print_errors(err);
896296341Sdelphij        goto end;
897296341Sdelphij    }
898296341Sdelphij    if (format == FORMAT_ASN1) {
899296341Sdelphij        pkey = d2i_PrivateKey_bio(key, NULL);
900296341Sdelphij    } else if (format == FORMAT_PEM) {
901296341Sdelphij        pkey = PEM_read_bio_PrivateKey(key, NULL,
902296341Sdelphij                                       (pem_password_cb *)password_callback,
903296341Sdelphij                                       &cb_data);
904296341Sdelphij    }
905109998Smarkm#if !defined(OPENSSL_NO_RC4) && !defined(OPENSSL_NO_RSA)
906296341Sdelphij    else if (format == FORMAT_NETSCAPE || format == FORMAT_IISSGC)
907296341Sdelphij        pkey = load_netscape_key(err, key, file, key_descrip, format);
908109998Smarkm#endif
909296341Sdelphij    else if (format == FORMAT_PKCS12) {
910296341Sdelphij        if (!load_pkcs12(err, key, key_descrip,
911296341Sdelphij                         (pem_password_cb *)password_callback, &cb_data,
912296341Sdelphij                         &pkey, NULL, NULL))
913296341Sdelphij            goto end;
914296341Sdelphij    }
915238405Sjkim#if !defined(OPENSSL_NO_RSA) && !defined(OPENSSL_NO_DSA) && !defined (OPENSSL_NO_RC4)
916296341Sdelphij    else if (format == FORMAT_MSBLOB)
917296341Sdelphij        pkey = b2i_PrivateKey_bio(key);
918296341Sdelphij    else if (format == FORMAT_PVK)
919296341Sdelphij        pkey = b2i_PVK_bio(key, (pem_password_cb *)password_callback,
920296341Sdelphij                           &cb_data);
921238405Sjkim#endif
922296341Sdelphij    else {
923296341Sdelphij        BIO_printf(err, "bad input format specified for key file\n");
924296341Sdelphij        goto end;
925296341Sdelphij    }
92668651Skris end:
927296341Sdelphij    if (key != NULL)
928296341Sdelphij        BIO_free(key);
929296341Sdelphij    if (pkey == NULL) {
930296341Sdelphij        BIO_printf(err, "unable to load %s\n", key_descrip);
931296341Sdelphij        ERR_print_errors(err);
932296341Sdelphij    }
933296341Sdelphij    return (pkey);
934296341Sdelphij}
93568651Skris
936109998SmarkmEVP_PKEY *load_pubkey(BIO *err, const char *file, int format, int maybe_stdin,
937296341Sdelphij                      const char *pass, ENGINE *e, const char *key_descrip)
938296341Sdelphij{
939296341Sdelphij    BIO *key = NULL;
940296341Sdelphij    EVP_PKEY *pkey = NULL;
941296341Sdelphij    PW_CB_DATA cb_data;
94268651Skris
943296341Sdelphij    cb_data.password = pass;
944296341Sdelphij    cb_data.prompt_info = file;
945109998Smarkm
946296341Sdelphij    if (file == NULL && (!maybe_stdin || format == FORMAT_ENGINE)) {
947296341Sdelphij        BIO_printf(err, "no keyfile specified\n");
948296341Sdelphij        goto end;
949296341Sdelphij    }
950111147Snectar#ifndef OPENSSL_NO_ENGINE
951296341Sdelphij    if (format == FORMAT_ENGINE) {
952296341Sdelphij        if (!e)
953296341Sdelphij            BIO_printf(bio_err, "no engine specified\n");
954296341Sdelphij        else
955296341Sdelphij            pkey = ENGINE_load_public_key(e, file, ui_method, &cb_data);
956296341Sdelphij        goto end;
957296341Sdelphij    }
958111147Snectar#endif
959296341Sdelphij    key = BIO_new(BIO_s_file());
960296341Sdelphij    if (key == NULL) {
961296341Sdelphij        ERR_print_errors(err);
962296341Sdelphij        goto end;
963296341Sdelphij    }
964296341Sdelphij    if (file == NULL && maybe_stdin) {
965238405Sjkim#ifdef _IONBF
966238405Sjkim# ifndef OPENSSL_NO_SETVBUF_IONBF
967296341Sdelphij        setvbuf(stdin, NULL, _IONBF, 0);
968296341Sdelphij# endif                         /* ndef OPENSSL_NO_SETVBUF_IONBF */
969238405Sjkim#endif
970296341Sdelphij        BIO_set_fp(key, stdin, BIO_NOCLOSE);
971296341Sdelphij    } else if (BIO_read_filename(key, file) <= 0) {
972296341Sdelphij        BIO_printf(err, "Error opening %s %s\n", key_descrip, file);
973296341Sdelphij        ERR_print_errors(err);
974296341Sdelphij        goto end;
975296341Sdelphij    }
976296341Sdelphij    if (format == FORMAT_ASN1) {
977296341Sdelphij        pkey = d2i_PUBKEY_bio(key, NULL);
978296341Sdelphij    }
979238405Sjkim#ifndef OPENSSL_NO_RSA
980296341Sdelphij    else if (format == FORMAT_ASN1RSA) {
981296341Sdelphij        RSA *rsa;
982296341Sdelphij        rsa = d2i_RSAPublicKey_bio(key, NULL);
983296341Sdelphij        if (rsa) {
984296341Sdelphij            pkey = EVP_PKEY_new();
985296341Sdelphij            if (pkey)
986296341Sdelphij                EVP_PKEY_set1_RSA(pkey, rsa);
987296341Sdelphij            RSA_free(rsa);
988296341Sdelphij        } else
989296341Sdelphij            pkey = NULL;
990296341Sdelphij    } else if (format == FORMAT_PEMRSA) {
991296341Sdelphij        RSA *rsa;
992296341Sdelphij        rsa = PEM_read_bio_RSAPublicKey(key, NULL,
993296341Sdelphij                                        (pem_password_cb *)password_callback,
994296341Sdelphij                                        &cb_data);
995296341Sdelphij        if (rsa) {
996296341Sdelphij            pkey = EVP_PKEY_new();
997296341Sdelphij            if (pkey)
998296341Sdelphij                EVP_PKEY_set1_RSA(pkey, rsa);
999296341Sdelphij            RSA_free(rsa);
1000296341Sdelphij        } else
1001296341Sdelphij            pkey = NULL;
1002296341Sdelphij    }
1003238405Sjkim#endif
1004296341Sdelphij    else if (format == FORMAT_PEM) {
1005296341Sdelphij        pkey = PEM_read_bio_PUBKEY(key, NULL,
1006296341Sdelphij                                   (pem_password_cb *)password_callback,
1007296341Sdelphij                                   &cb_data);
1008296341Sdelphij    }
1009109998Smarkm#if !defined(OPENSSL_NO_RC4) && !defined(OPENSSL_NO_RSA)
1010296341Sdelphij    else if (format == FORMAT_NETSCAPE || format == FORMAT_IISSGC)
1011296341Sdelphij        pkey = load_netscape_key(err, key, file, key_descrip, format);
1012109998Smarkm#endif
1013238405Sjkim#if !defined(OPENSSL_NO_RSA) && !defined(OPENSSL_NO_DSA)
1014296341Sdelphij    else if (format == FORMAT_MSBLOB)
1015296341Sdelphij        pkey = b2i_PublicKey_bio(key);
1016238405Sjkim#endif
1017296341Sdelphij    else {
1018296341Sdelphij        BIO_printf(err, "bad input format specified for key file\n");
1019296341Sdelphij        goto end;
1020296341Sdelphij    }
102168651Skris end:
1022296341Sdelphij    if (key != NULL)
1023296341Sdelphij        BIO_free(key);
1024296341Sdelphij    if (pkey == NULL)
1025296341Sdelphij        BIO_printf(err, "unable to load %s\n", key_descrip);
1026296341Sdelphij    return (pkey);
1027296341Sdelphij}
102868651Skris
1029109998Smarkm#if !defined(OPENSSL_NO_RC4) && !defined(OPENSSL_NO_RSA)
1030296341Sdelphijstatic EVP_PKEY *load_netscape_key(BIO *err, BIO *key, const char *file,
1031296341Sdelphij                                   const char *key_descrip, int format)
1032296341Sdelphij{
1033296341Sdelphij    EVP_PKEY *pkey;
1034296341Sdelphij    BUF_MEM *buf;
1035296341Sdelphij    RSA *rsa;
1036296341Sdelphij    const unsigned char *p;
1037296341Sdelphij    int size, i;
1038109998Smarkm
1039296341Sdelphij    buf = BUF_MEM_new();
1040296341Sdelphij    pkey = EVP_PKEY_new();
1041296341Sdelphij    size = 0;
1042296341Sdelphij    if (buf == NULL || pkey == NULL)
1043296341Sdelphij        goto error;
1044296341Sdelphij    for (;;) {
1045296341Sdelphij        if (!BUF_MEM_grow_clean(buf, size + 1024 * 10))
1046296341Sdelphij            goto error;
1047296341Sdelphij        i = BIO_read(key, &(buf->data[size]), 1024 * 10);
1048296341Sdelphij        size += i;
1049296341Sdelphij        if (i == 0)
1050296341Sdelphij            break;
1051296341Sdelphij        if (i < 0) {
1052296341Sdelphij            BIO_printf(err, "Error reading %s %s", key_descrip, file);
1053296341Sdelphij            goto error;
1054296341Sdelphij        }
1055296341Sdelphij    }
1056296341Sdelphij    p = (unsigned char *)buf->data;
1057296341Sdelphij    rsa = d2i_RSA_NET(NULL, &p, (long)size, NULL,
1058296341Sdelphij                      (format == FORMAT_IISSGC ? 1 : 0));
1059296341Sdelphij    if (rsa == NULL)
1060296341Sdelphij        goto error;
1061296341Sdelphij    BUF_MEM_free(buf);
1062296341Sdelphij    EVP_PKEY_set1_RSA(pkey, rsa);
1063296341Sdelphij    return pkey;
1064296341Sdelphij error:
1065296341Sdelphij    BUF_MEM_free(buf);
1066296341Sdelphij    EVP_PKEY_free(pkey);
1067296341Sdelphij    return NULL;
1068296341Sdelphij}
1069296341Sdelphij#endif                          /* ndef OPENSSL_NO_RC4 */
1070109998Smarkm
1071238405Sjkimstatic int load_certs_crls(BIO *err, const char *file, int format,
1072296341Sdelphij                           const char *pass, ENGINE *e, const char *desc,
1073296341Sdelphij                           STACK_OF(X509) **pcerts,
1074296341Sdelphij                           STACK_OF(X509_CRL) **pcrls)
1075296341Sdelphij{
1076296341Sdelphij    int i;
1077296341Sdelphij    BIO *bio;
1078296341Sdelphij    STACK_OF(X509_INFO) *xis = NULL;
1079296341Sdelphij    X509_INFO *xi;
1080296341Sdelphij    PW_CB_DATA cb_data;
1081296341Sdelphij    int rv = 0;
108268651Skris
1083296341Sdelphij    cb_data.password = pass;
1084296341Sdelphij    cb_data.prompt_info = file;
1085109998Smarkm
1086296341Sdelphij    if (format != FORMAT_PEM) {
1087296341Sdelphij        BIO_printf(err, "bad input format specified for %s\n", desc);
1088296341Sdelphij        return 0;
1089296341Sdelphij    }
109068651Skris
1091296341Sdelphij    if (file == NULL)
1092296341Sdelphij        bio = BIO_new_fp(stdin, BIO_NOCLOSE);
1093296341Sdelphij    else
1094296341Sdelphij        bio = BIO_new_file(file, "r");
1095238405Sjkim
1096296341Sdelphij    if (bio == NULL) {
1097296341Sdelphij        BIO_printf(err, "Error opening %s %s\n", desc, file ? file : "stdin");
1098296341Sdelphij        ERR_print_errors(err);
1099296341Sdelphij        return 0;
1100296341Sdelphij    }
1101238405Sjkim
1102296341Sdelphij    xis = PEM_X509_INFO_read_bio(bio, NULL,
1103296341Sdelphij                                 (pem_password_cb *)password_callback,
1104296341Sdelphij                                 &cb_data);
1105238405Sjkim
1106296341Sdelphij    BIO_free(bio);
1107238405Sjkim
1108296341Sdelphij    if (pcerts) {
1109296341Sdelphij        *pcerts = sk_X509_new_null();
1110296341Sdelphij        if (!*pcerts)
1111296341Sdelphij            goto end;
1112296341Sdelphij    }
111368651Skris
1114296341Sdelphij    if (pcrls) {
1115296341Sdelphij        *pcrls = sk_X509_CRL_new_null();
1116296341Sdelphij        if (!*pcrls)
1117296341Sdelphij            goto end;
1118296341Sdelphij    }
1119238405Sjkim
1120296341Sdelphij    for (i = 0; i < sk_X509_INFO_num(xis); i++) {
1121296341Sdelphij        xi = sk_X509_INFO_value(xis, i);
1122296341Sdelphij        if (xi->x509 && pcerts) {
1123296341Sdelphij            if (!sk_X509_push(*pcerts, xi->x509))
1124296341Sdelphij                goto end;
1125296341Sdelphij            xi->x509 = NULL;
1126296341Sdelphij        }
1127296341Sdelphij        if (xi->crl && pcrls) {
1128296341Sdelphij            if (!sk_X509_CRL_push(*pcrls, xi->crl))
1129296341Sdelphij                goto end;
1130296341Sdelphij            xi->crl = NULL;
1131296341Sdelphij        }
1132296341Sdelphij    }
1133238405Sjkim
1134296341Sdelphij    if (pcerts && sk_X509_num(*pcerts) > 0)
1135296341Sdelphij        rv = 1;
1136238405Sjkim
1137296341Sdelphij    if (pcrls && sk_X509_CRL_num(*pcrls) > 0)
1138296341Sdelphij        rv = 1;
1139238405Sjkim
1140296341Sdelphij end:
1141238405Sjkim
1142296341Sdelphij    if (xis)
1143296341Sdelphij        sk_X509_INFO_pop_free(xis, X509_INFO_free);
1144238405Sjkim
1145296341Sdelphij    if (rv == 0) {
1146296341Sdelphij        if (pcerts) {
1147296341Sdelphij            sk_X509_pop_free(*pcerts, X509_free);
1148296341Sdelphij            *pcerts = NULL;
1149296341Sdelphij        }
1150296341Sdelphij        if (pcrls) {
1151296341Sdelphij            sk_X509_CRL_pop_free(*pcrls, X509_CRL_free);
1152296341Sdelphij            *pcrls = NULL;
1153296341Sdelphij        }
1154296341Sdelphij        BIO_printf(err, "unable to load %s\n",
1155296341Sdelphij                   pcerts ? "certificates" : "CRLs");
1156296341Sdelphij        ERR_print_errors(err);
1157296341Sdelphij    }
1158296341Sdelphij    return rv;
1159296341Sdelphij}
116068651Skris
1161238405SjkimSTACK_OF(X509) *load_certs(BIO *err, const char *file, int format,
1162296341Sdelphij                           const char *pass, ENGINE *e, const char *desc)
1163296341Sdelphij{
1164296341Sdelphij    STACK_OF(X509) *certs;
1165296341Sdelphij    if (!load_certs_crls(err, file, format, pass, e, desc, &certs, NULL))
1166296341Sdelphij        return NULL;
1167296341Sdelphij    return certs;
1168296341Sdelphij}
116968651Skris
1170238405SjkimSTACK_OF(X509_CRL) *load_crls(BIO *err, const char *file, int format,
1171296341Sdelphij                              const char *pass, ENGINE *e, const char *desc)
1172296341Sdelphij{
1173296341Sdelphij    STACK_OF(X509_CRL) *crls;
1174296341Sdelphij    if (!load_certs_crls(err, file, format, pass, e, desc, NULL, &crls))
1175296341Sdelphij        return NULL;
1176296341Sdelphij    return crls;
1177296341Sdelphij}
1178238405Sjkim
1179296341Sdelphij#define X509V3_EXT_UNKNOWN_MASK         (0xfL << 16)
1180109998Smarkm/* Return error for unknown extensions */
1181296341Sdelphij#define X509V3_EXT_DEFAULT              0
1182109998Smarkm/* Print error for unknown extensions */
1183296341Sdelphij#define X509V3_EXT_ERROR_UNKNOWN        (1L << 16)
1184109998Smarkm/* ASN1 parse unknown extensions */
1185296341Sdelphij#define X509V3_EXT_PARSE_UNKNOWN        (2L << 16)
1186109998Smarkm/* BIO_dump unknown extensions */
1187296341Sdelphij#define X509V3_EXT_DUMP_UNKNOWN         (3L << 16)
1188109998Smarkm
1189109998Smarkm#define X509_FLAG_CA (X509_FLAG_NO_ISSUER | X509_FLAG_NO_PUBKEY | \
1190296341Sdelphij                         X509_FLAG_NO_HEADER | X509_FLAG_NO_VERSION)
1191109998Smarkm
1192109998Smarkmint set_cert_ex(unsigned long *flags, const char *arg)
1193109998Smarkm{
1194296341Sdelphij    static const NAME_EX_TBL cert_tbl[] = {
1195296341Sdelphij        {"compatible", X509_FLAG_COMPAT, 0xffffffffl},
1196296341Sdelphij        {"ca_default", X509_FLAG_CA, 0xffffffffl},
1197296341Sdelphij        {"no_header", X509_FLAG_NO_HEADER, 0},
1198296341Sdelphij        {"no_version", X509_FLAG_NO_VERSION, 0},
1199296341Sdelphij        {"no_serial", X509_FLAG_NO_SERIAL, 0},
1200296341Sdelphij        {"no_signame", X509_FLAG_NO_SIGNAME, 0},
1201296341Sdelphij        {"no_validity", X509_FLAG_NO_VALIDITY, 0},
1202296341Sdelphij        {"no_subject", X509_FLAG_NO_SUBJECT, 0},
1203296341Sdelphij        {"no_issuer", X509_FLAG_NO_ISSUER, 0},
1204296341Sdelphij        {"no_pubkey", X509_FLAG_NO_PUBKEY, 0},
1205296341Sdelphij        {"no_extensions", X509_FLAG_NO_EXTENSIONS, 0},
1206296341Sdelphij        {"no_sigdump", X509_FLAG_NO_SIGDUMP, 0},
1207296341Sdelphij        {"no_aux", X509_FLAG_NO_AUX, 0},
1208296341Sdelphij        {"no_attributes", X509_FLAG_NO_ATTRIBUTES, 0},
1209296341Sdelphij        {"ext_default", X509V3_EXT_DEFAULT, X509V3_EXT_UNKNOWN_MASK},
1210296341Sdelphij        {"ext_error", X509V3_EXT_ERROR_UNKNOWN, X509V3_EXT_UNKNOWN_MASK},
1211296341Sdelphij        {"ext_parse", X509V3_EXT_PARSE_UNKNOWN, X509V3_EXT_UNKNOWN_MASK},
1212296341Sdelphij        {"ext_dump", X509V3_EXT_DUMP_UNKNOWN, X509V3_EXT_UNKNOWN_MASK},
1213296341Sdelphij        {NULL, 0, 0}
1214296341Sdelphij    };
1215296341Sdelphij    return set_multi_opts(flags, arg, cert_tbl);
1216109998Smarkm}
1217109998Smarkm
121868651Skrisint set_name_ex(unsigned long *flags, const char *arg)
121968651Skris{
1220296341Sdelphij    static const NAME_EX_TBL ex_tbl[] = {
1221296341Sdelphij        {"esc_2253", ASN1_STRFLGS_ESC_2253, 0},
1222296341Sdelphij        {"esc_ctrl", ASN1_STRFLGS_ESC_CTRL, 0},
1223296341Sdelphij        {"esc_msb", ASN1_STRFLGS_ESC_MSB, 0},
1224296341Sdelphij        {"use_quote", ASN1_STRFLGS_ESC_QUOTE, 0},
1225296341Sdelphij        {"utf8", ASN1_STRFLGS_UTF8_CONVERT, 0},
1226296341Sdelphij        {"ignore_type", ASN1_STRFLGS_IGNORE_TYPE, 0},
1227296341Sdelphij        {"show_type", ASN1_STRFLGS_SHOW_TYPE, 0},
1228296341Sdelphij        {"dump_all", ASN1_STRFLGS_DUMP_ALL, 0},
1229296341Sdelphij        {"dump_nostr", ASN1_STRFLGS_DUMP_UNKNOWN, 0},
1230296341Sdelphij        {"dump_der", ASN1_STRFLGS_DUMP_DER, 0},
1231296341Sdelphij        {"compat", XN_FLAG_COMPAT, 0xffffffffL},
1232296341Sdelphij        {"sep_comma_plus", XN_FLAG_SEP_COMMA_PLUS, XN_FLAG_SEP_MASK},
1233296341Sdelphij        {"sep_comma_plus_space", XN_FLAG_SEP_CPLUS_SPC, XN_FLAG_SEP_MASK},
1234296341Sdelphij        {"sep_semi_plus_space", XN_FLAG_SEP_SPLUS_SPC, XN_FLAG_SEP_MASK},
1235296341Sdelphij        {"sep_multiline", XN_FLAG_SEP_MULTILINE, XN_FLAG_SEP_MASK},
1236296341Sdelphij        {"dn_rev", XN_FLAG_DN_REV, 0},
1237296341Sdelphij        {"nofname", XN_FLAG_FN_NONE, XN_FLAG_FN_MASK},
1238296341Sdelphij        {"sname", XN_FLAG_FN_SN, XN_FLAG_FN_MASK},
1239296341Sdelphij        {"lname", XN_FLAG_FN_LN, XN_FLAG_FN_MASK},
1240296341Sdelphij        {"align", XN_FLAG_FN_ALIGN, 0},
1241296341Sdelphij        {"oid", XN_FLAG_FN_OID, XN_FLAG_FN_MASK},
1242296341Sdelphij        {"space_eq", XN_FLAG_SPC_EQ, 0},
1243296341Sdelphij        {"dump_unknown", XN_FLAG_DUMP_UNKNOWN_FIELDS, 0},
1244296341Sdelphij        {"RFC2253", XN_FLAG_RFC2253, 0xffffffffL},
1245296341Sdelphij        {"oneline", XN_FLAG_ONELINE, 0xffffffffL},
1246296341Sdelphij        {"multiline", XN_FLAG_MULTILINE, 0xffffffffL},
1247296341Sdelphij        {"ca_default", XN_FLAG_MULTILINE, 0xffffffffL},
1248296341Sdelphij        {NULL, 0, 0}
1249296341Sdelphij    };
1250296341Sdelphij    return set_multi_opts(flags, arg, ex_tbl);
1251109998Smarkm}
125268651Skris
1253109998Smarkmint set_ext_copy(int *copy_type, const char *arg)
1254109998Smarkm{
1255296341Sdelphij    if (!strcasecmp(arg, "none"))
1256296341Sdelphij        *copy_type = EXT_COPY_NONE;
1257296341Sdelphij    else if (!strcasecmp(arg, "copy"))
1258296341Sdelphij        *copy_type = EXT_COPY_ADD;
1259296341Sdelphij    else if (!strcasecmp(arg, "copyall"))
1260296341Sdelphij        *copy_type = EXT_COPY_ALL;
1261296341Sdelphij    else
1262296341Sdelphij        return 0;
1263296341Sdelphij    return 1;
1264109998Smarkm}
1265109998Smarkm
1266109998Smarkmint copy_extensions(X509 *x, X509_REQ *req, int copy_type)
1267109998Smarkm{
1268296341Sdelphij    STACK_OF(X509_EXTENSION) *exts = NULL;
1269296341Sdelphij    X509_EXTENSION *ext, *tmpext;
1270296341Sdelphij    ASN1_OBJECT *obj;
1271296341Sdelphij    int i, idx, ret = 0;
1272296341Sdelphij    if (!x || !req || (copy_type == EXT_COPY_NONE))
1273296341Sdelphij        return 1;
1274296341Sdelphij    exts = X509_REQ_get_extensions(req);
1275109998Smarkm
1276296341Sdelphij    for (i = 0; i < sk_X509_EXTENSION_num(exts); i++) {
1277296341Sdelphij        ext = sk_X509_EXTENSION_value(exts, i);
1278296341Sdelphij        obj = X509_EXTENSION_get_object(ext);
1279296341Sdelphij        idx = X509_get_ext_by_OBJ(x, obj, -1);
1280296341Sdelphij        /* Does extension exist? */
1281296341Sdelphij        if (idx != -1) {
1282296341Sdelphij            /* If normal copy don't override existing extension */
1283296341Sdelphij            if (copy_type == EXT_COPY_ADD)
1284296341Sdelphij                continue;
1285296341Sdelphij            /* Delete all extensions of same type */
1286296341Sdelphij            do {
1287296341Sdelphij                tmpext = X509_get_ext(x, idx);
1288296341Sdelphij                X509_delete_ext(x, idx);
1289296341Sdelphij                X509_EXTENSION_free(tmpext);
1290296341Sdelphij                idx = X509_get_ext_by_OBJ(x, obj, -1);
1291296341Sdelphij            } while (idx != -1);
1292296341Sdelphij        }
1293296341Sdelphij        if (!X509_add_ext(x, ext, -1))
1294296341Sdelphij            goto end;
1295296341Sdelphij    }
1296109998Smarkm
1297296341Sdelphij    ret = 1;
1298109998Smarkm
1299296341Sdelphij end:
1300109998Smarkm
1301296341Sdelphij    sk_X509_EXTENSION_pop_free(exts, X509_EXTENSION_free);
1302109998Smarkm
1303296341Sdelphij    return ret;
1304109998Smarkm}
1305109998Smarkm
1306296341Sdelphijstatic int set_multi_opts(unsigned long *flags, const char *arg,
1307296341Sdelphij                          const NAME_EX_TBL * in_tbl)
1308109998Smarkm{
1309296341Sdelphij    STACK_OF(CONF_VALUE) *vals;
1310296341Sdelphij    CONF_VALUE *val;
1311296341Sdelphij    int i, ret = 1;
1312296341Sdelphij    if (!arg)
1313296341Sdelphij        return 0;
1314296341Sdelphij    vals = X509V3_parse_list(arg);
1315296341Sdelphij    for (i = 0; i < sk_CONF_VALUE_num(vals); i++) {
1316296341Sdelphij        val = sk_CONF_VALUE_value(vals, i);
1317296341Sdelphij        if (!set_table_opts(flags, val->name, in_tbl))
1318296341Sdelphij            ret = 0;
1319296341Sdelphij    }
1320296341Sdelphij    sk_CONF_VALUE_pop_free(vals, X509V3_conf_free);
1321296341Sdelphij    return ret;
1322109998Smarkm}
1323109998Smarkm
1324296341Sdelphijstatic int set_table_opts(unsigned long *flags, const char *arg,
1325296341Sdelphij                          const NAME_EX_TBL * in_tbl)
1326109998Smarkm{
1327296341Sdelphij    char c;
1328296341Sdelphij    const NAME_EX_TBL *ptbl;
1329296341Sdelphij    c = arg[0];
133068651Skris
1331296341Sdelphij    if (c == '-') {
1332296341Sdelphij        c = 0;
1333296341Sdelphij        arg++;
1334296341Sdelphij    } else if (c == '+') {
1335296341Sdelphij        c = 1;
1336296341Sdelphij        arg++;
1337296341Sdelphij    } else
1338296341Sdelphij        c = 1;
133968651Skris
1340296341Sdelphij    for (ptbl = in_tbl; ptbl->name; ptbl++) {
1341296341Sdelphij        if (!strcasecmp(arg, ptbl->name)) {
1342296341Sdelphij            *flags &= ~ptbl->mask;
1343296341Sdelphij            if (c)
1344296341Sdelphij                *flags |= ptbl->flag;
1345296341Sdelphij            else
1346296341Sdelphij                *flags &= ~ptbl->flag;
1347296341Sdelphij            return 1;
1348296341Sdelphij        }
1349296341Sdelphij    }
1350296341Sdelphij    return 0;
135168651Skris}
135268651Skris
1353296341Sdelphijvoid print_name(BIO *out, const char *title, X509_NAME *nm,
1354296341Sdelphij                unsigned long lflags)
135568651Skris{
1356296341Sdelphij    char *buf;
1357296341Sdelphij    char mline = 0;
1358296341Sdelphij    int indent = 0;
1359109998Smarkm
1360296341Sdelphij    if (title)
1361296341Sdelphij        BIO_puts(out, title);
1362296341Sdelphij    if ((lflags & XN_FLAG_SEP_MASK) == XN_FLAG_SEP_MULTILINE) {
1363296341Sdelphij        mline = 1;
1364296341Sdelphij        indent = 4;
1365296341Sdelphij    }
1366296341Sdelphij    if (lflags == XN_FLAG_COMPAT) {
1367296341Sdelphij        buf = X509_NAME_oneline(nm, 0, 0);
1368296341Sdelphij        BIO_puts(out, buf);
1369296341Sdelphij        BIO_puts(out, "\n");
1370296341Sdelphij        OPENSSL_free(buf);
1371296341Sdelphij    } else {
1372296341Sdelphij        if (mline)
1373296341Sdelphij            BIO_puts(out, "\n");
1374296341Sdelphij        X509_NAME_print_ex(out, nm, indent, lflags);
1375296341Sdelphij        BIO_puts(out, "\n");
1376296341Sdelphij    }
137768651Skris}
137868651Skris
1379109998SmarkmX509_STORE *setup_verify(BIO *bp, char *CAfile, char *CApath)
1380109998Smarkm{
1381296341Sdelphij    X509_STORE *store;
1382296341Sdelphij    X509_LOOKUP *lookup;
1383296341Sdelphij    if (!(store = X509_STORE_new()))
1384296341Sdelphij        goto end;
1385296341Sdelphij    lookup = X509_STORE_add_lookup(store, X509_LOOKUP_file());
1386296341Sdelphij    if (lookup == NULL)
1387296341Sdelphij        goto end;
1388296341Sdelphij    if (CAfile) {
1389296341Sdelphij        if (!X509_LOOKUP_load_file(lookup, CAfile, X509_FILETYPE_PEM)) {
1390296341Sdelphij            BIO_printf(bp, "Error loading file %s\n", CAfile);
1391296341Sdelphij            goto end;
1392296341Sdelphij        }
1393296341Sdelphij    } else
1394296341Sdelphij        X509_LOOKUP_load_file(lookup, NULL, X509_FILETYPE_DEFAULT);
1395109998Smarkm
1396296341Sdelphij    lookup = X509_STORE_add_lookup(store, X509_LOOKUP_hash_dir());
1397296341Sdelphij    if (lookup == NULL)
1398296341Sdelphij        goto end;
1399296341Sdelphij    if (CApath) {
1400296341Sdelphij        if (!X509_LOOKUP_add_dir(lookup, CApath, X509_FILETYPE_PEM)) {
1401296341Sdelphij            BIO_printf(bp, "Error loading directory %s\n", CApath);
1402296341Sdelphij            goto end;
1403296341Sdelphij        }
1404296341Sdelphij    } else
1405296341Sdelphij        X509_LOOKUP_add_dir(lookup, NULL, X509_FILETYPE_DEFAULT);
1406296341Sdelphij
1407296341Sdelphij    ERR_clear_error();
1408296341Sdelphij    return store;
1409296341Sdelphij end:
1410296341Sdelphij    X509_STORE_free(store);
1411296341Sdelphij    return NULL;
1412109998Smarkm}
1413109998Smarkm
1414111147Snectar#ifndef OPENSSL_NO_ENGINE
1415109998Smarkm/* Try to load an engine in a shareable library */
1416109998Smarkmstatic ENGINE *try_load_engine(BIO *err, const char *engine, int debug)
1417296341Sdelphij{
1418296341Sdelphij    ENGINE *e = ENGINE_by_id("dynamic");
1419296341Sdelphij    if (e) {
1420296341Sdelphij        if (!ENGINE_ctrl_cmd_string(e, "SO_PATH", engine, 0)
1421296341Sdelphij            || !ENGINE_ctrl_cmd_string(e, "LOAD", NULL, 0)) {
1422296341Sdelphij            ENGINE_free(e);
1423296341Sdelphij            e = NULL;
1424296341Sdelphij        }
1425296341Sdelphij    }
1426296341Sdelphij    return e;
1427296341Sdelphij}
1428109998Smarkm
1429109998SmarkmENGINE *setup_engine(BIO *err, const char *engine, int debug)
1430296341Sdelphij{
1431296341Sdelphij    ENGINE *e = NULL;
1432109998Smarkm
1433296341Sdelphij    if (engine) {
1434296341Sdelphij        if (strcmp(engine, "auto") == 0) {
1435296341Sdelphij            BIO_printf(err, "enabling auto ENGINE support\n");
1436296341Sdelphij            ENGINE_register_all_complete();
1437296341Sdelphij            return NULL;
1438296341Sdelphij        }
1439296341Sdelphij        if ((e = ENGINE_by_id(engine)) == NULL
1440296341Sdelphij            && (e = try_load_engine(err, engine, debug)) == NULL) {
1441296341Sdelphij            BIO_printf(err, "invalid engine \"%s\"\n", engine);
1442296341Sdelphij            ERR_print_errors(err);
1443296341Sdelphij            return NULL;
1444296341Sdelphij        }
1445296341Sdelphij        if (debug) {
1446296341Sdelphij            ENGINE_ctrl(e, ENGINE_CTRL_SET_LOGSTREAM, 0, err, 0);
1447296341Sdelphij        }
1448296341Sdelphij        ENGINE_ctrl_cmd(e, "SET_USER_INTERFACE", 0, ui_method, 0, 1);
1449296341Sdelphij        if (!ENGINE_set_default(e, ENGINE_METHOD_ALL)) {
1450296341Sdelphij            BIO_printf(err, "can't use that engine\n");
1451296341Sdelphij            ERR_print_errors(err);
1452296341Sdelphij            ENGINE_free(e);
1453296341Sdelphij            return NULL;
1454296341Sdelphij        }
1455109998Smarkm
1456296341Sdelphij        BIO_printf(err, "engine \"%s\" set.\n", ENGINE_get_id(e));
1457109998Smarkm
1458296341Sdelphij        /* Free our "structural" reference. */
1459296341Sdelphij        ENGINE_free(e);
1460296341Sdelphij    }
1461296341Sdelphij    return e;
1462296341Sdelphij}
1463111147Snectar#endif
1464109998Smarkm
1465109998Smarkmint load_config(BIO *err, CONF *cnf)
1466296341Sdelphij{
1467296341Sdelphij    static int load_config_called = 0;
1468296341Sdelphij    if (load_config_called)
1469296341Sdelphij        return 1;
1470296341Sdelphij    load_config_called = 1;
1471296341Sdelphij    if (!cnf)
1472296341Sdelphij        cnf = config;
1473296341Sdelphij    if (!cnf)
1474296341Sdelphij        return 1;
1475109998Smarkm
1476296341Sdelphij    OPENSSL_load_builtin_modules();
1477109998Smarkm
1478296341Sdelphij    if (CONF_modules_load(cnf, NULL, 0) <= 0) {
1479296341Sdelphij        BIO_printf(err, "Error configuring OpenSSL\n");
1480296341Sdelphij        ERR_print_errors(err);
1481296341Sdelphij        return 0;
1482296341Sdelphij    }
1483296341Sdelphij    return 1;
1484296341Sdelphij}
1485109998Smarkm
1486109998Smarkmchar *make_config_name()
1487296341Sdelphij{
1488296341Sdelphij    const char *t = X509_get_default_cert_area();
1489296341Sdelphij    size_t len;
1490296341Sdelphij    char *p;
1491109998Smarkm
1492296341Sdelphij    len = strlen(t) + strlen(OPENSSL_CONF) + 2;
1493296341Sdelphij    p = OPENSSL_malloc(len);
1494296341Sdelphij    if (p == NULL)
1495296341Sdelphij        return NULL;
1496296341Sdelphij    BUF_strlcpy(p, t, len);
1497109998Smarkm#ifndef OPENSSL_SYS_VMS
1498296341Sdelphij    BUF_strlcat(p, "/", len);
1499109998Smarkm#endif
1500296341Sdelphij    BUF_strlcat(p, OPENSSL_CONF, len);
1501109998Smarkm
1502296341Sdelphij    return p;
1503296341Sdelphij}
1504127128Snectar
1505238405Sjkimstatic unsigned long index_serial_hash(const OPENSSL_CSTRING *a)
1506296341Sdelphij{
1507296341Sdelphij    const char *n;
1508127128Snectar
1509296341Sdelphij    n = a[DB_serial];
1510296341Sdelphij    while (*n == '0')
1511296341Sdelphij        n++;
1512296341Sdelphij    return (lh_strhash(n));
1513296341Sdelphij}
1514127128Snectar
1515296341Sdelphijstatic int index_serial_cmp(const OPENSSL_CSTRING *a,
1516296341Sdelphij                            const OPENSSL_CSTRING *b)
1517296341Sdelphij{
1518296341Sdelphij    const char *aa, *bb;
1519127128Snectar
1520296341Sdelphij    for (aa = a[DB_serial]; *aa == '0'; aa++) ;
1521296341Sdelphij    for (bb = b[DB_serial]; *bb == '0'; bb++) ;
1522296341Sdelphij    return (strcmp(aa, bb));
1523296341Sdelphij}
1524127128Snectar
1525127128Snectarstatic int index_name_qual(char **a)
1526296341Sdelphij{
1527296341Sdelphij    return (a[0][0] == 'V');
1528296341Sdelphij}
1529127128Snectar
1530238405Sjkimstatic unsigned long index_name_hash(const OPENSSL_CSTRING *a)
1531296341Sdelphij{
1532296341Sdelphij    return (lh_strhash(a[DB_name]));
1533296341Sdelphij}
1534127128Snectar
1535238405Sjkimint index_name_cmp(const OPENSSL_CSTRING *a, const OPENSSL_CSTRING *b)
1536296341Sdelphij{
1537296341Sdelphij    return (strcmp(a[DB_name], b[DB_name]));
1538296341Sdelphij}
1539127128Snectar
1540238405Sjkimstatic IMPLEMENT_LHASH_HASH_FN(index_serial, OPENSSL_CSTRING)
1541238405Sjkimstatic IMPLEMENT_LHASH_COMP_FN(index_serial, OPENSSL_CSTRING)
1542238405Sjkimstatic IMPLEMENT_LHASH_HASH_FN(index_name, OPENSSL_CSTRING)
1543238405Sjkimstatic IMPLEMENT_LHASH_COMP_FN(index_name, OPENSSL_CSTRING)
1544127128Snectar#undef BSIZE
1545127128Snectar#define BSIZE 256
1546127128SnectarBIGNUM *load_serial(char *serialfile, int create, ASN1_INTEGER **retai)
1547296341Sdelphij{
1548296341Sdelphij    BIO *in = NULL;
1549296341Sdelphij    BIGNUM *ret = NULL;
1550296341Sdelphij    MS_STATIC char buf[1024];
1551296341Sdelphij    ASN1_INTEGER *ai = NULL;
1552127128Snectar
1553296341Sdelphij    ai = ASN1_INTEGER_new();
1554296341Sdelphij    if (ai == NULL)
1555296341Sdelphij        goto err;
1556127128Snectar
1557296341Sdelphij    if ((in = BIO_new(BIO_s_file())) == NULL) {
1558296341Sdelphij        ERR_print_errors(bio_err);
1559296341Sdelphij        goto err;
1560296341Sdelphij    }
1561127128Snectar
1562296341Sdelphij    if (BIO_read_filename(in, serialfile) <= 0) {
1563296341Sdelphij        if (!create) {
1564296341Sdelphij            perror(serialfile);
1565296341Sdelphij            goto err;
1566296341Sdelphij        } else {
1567296341Sdelphij            ret = BN_new();
1568296341Sdelphij            if (ret == NULL || !rand_serial(ret, ai))
1569296341Sdelphij                BIO_printf(bio_err, "Out of memory\n");
1570296341Sdelphij        }
1571296341Sdelphij    } else {
1572296341Sdelphij        if (!a2i_ASN1_INTEGER(in, ai, buf, 1024)) {
1573296341Sdelphij            BIO_printf(bio_err, "unable to load number from %s\n",
1574296341Sdelphij                       serialfile);
1575296341Sdelphij            goto err;
1576296341Sdelphij        }
1577296341Sdelphij        ret = ASN1_INTEGER_to_BN(ai, NULL);
1578296341Sdelphij        if (ret == NULL) {
1579296341Sdelphij            BIO_printf(bio_err,
1580296341Sdelphij                       "error converting number from bin to BIGNUM\n");
1581296341Sdelphij            goto err;
1582296341Sdelphij        }
1583296341Sdelphij    }
1584127128Snectar
1585296341Sdelphij    if (ret && retai) {
1586296341Sdelphij        *retai = ai;
1587296341Sdelphij        ai = NULL;
1588296341Sdelphij    }
1589127128Snectar err:
1590296341Sdelphij    if (in != NULL)
1591296341Sdelphij        BIO_free(in);
1592296341Sdelphij    if (ai != NULL)
1593296341Sdelphij        ASN1_INTEGER_free(ai);
1594296341Sdelphij    return (ret);
1595296341Sdelphij}
1596127128Snectar
1597296341Sdelphijint save_serial(char *serialfile, char *suffix, BIGNUM *serial,
1598296341Sdelphij                ASN1_INTEGER **retai)
1599296341Sdelphij{
1600296341Sdelphij    char buf[1][BSIZE];
1601296341Sdelphij    BIO *out = NULL;
1602296341Sdelphij    int ret = 0;
1603296341Sdelphij    ASN1_INTEGER *ai = NULL;
1604296341Sdelphij    int j;
1605127128Snectar
1606296341Sdelphij    if (suffix == NULL)
1607296341Sdelphij        j = strlen(serialfile);
1608296341Sdelphij    else
1609296341Sdelphij        j = strlen(serialfile) + strlen(suffix) + 1;
1610296341Sdelphij    if (j >= BSIZE) {
1611296341Sdelphij        BIO_printf(bio_err, "file name too long\n");
1612296341Sdelphij        goto err;
1613296341Sdelphij    }
1614127128Snectar
1615296341Sdelphij    if (suffix == NULL)
1616296341Sdelphij        BUF_strlcpy(buf[0], serialfile, BSIZE);
1617296341Sdelphij    else {
1618127128Snectar#ifndef OPENSSL_SYS_VMS
1619296341Sdelphij        j = BIO_snprintf(buf[0], sizeof buf[0], "%s.%s", serialfile, suffix);
1620127128Snectar#else
1621296341Sdelphij        j = BIO_snprintf(buf[0], sizeof buf[0], "%s-%s", serialfile, suffix);
1622127128Snectar#endif
1623296341Sdelphij    }
1624127128Snectar#ifdef RL_DEBUG
1625296341Sdelphij    BIO_printf(bio_err, "DEBUG: writing \"%s\"\n", buf[0]);
1626127128Snectar#endif
1627296341Sdelphij    out = BIO_new(BIO_s_file());
1628296341Sdelphij    if (out == NULL) {
1629296341Sdelphij        ERR_print_errors(bio_err);
1630296341Sdelphij        goto err;
1631296341Sdelphij    }
1632296341Sdelphij    if (BIO_write_filename(out, buf[0]) <= 0) {
1633296341Sdelphij        perror(serialfile);
1634296341Sdelphij        goto err;
1635296341Sdelphij    }
1636127128Snectar
1637296341Sdelphij    if ((ai = BN_to_ASN1_INTEGER(serial, NULL)) == NULL) {
1638296341Sdelphij        BIO_printf(bio_err, "error converting serial to ASN.1 format\n");
1639296341Sdelphij        goto err;
1640296341Sdelphij    }
1641296341Sdelphij    i2a_ASN1_INTEGER(out, ai);
1642296341Sdelphij    BIO_puts(out, "\n");
1643296341Sdelphij    ret = 1;
1644296341Sdelphij    if (retai) {
1645296341Sdelphij        *retai = ai;
1646296341Sdelphij        ai = NULL;
1647296341Sdelphij    }
1648296341Sdelphij err:
1649296341Sdelphij    if (out != NULL)
1650296341Sdelphij        BIO_free_all(out);
1651296341Sdelphij    if (ai != NULL)
1652296341Sdelphij        ASN1_INTEGER_free(ai);
1653296341Sdelphij    return (ret);
1654296341Sdelphij}
1655127128Snectar
1656127128Snectarint rotate_serial(char *serialfile, char *new_suffix, char *old_suffix)
1657296341Sdelphij{
1658296341Sdelphij    char buf[5][BSIZE];
1659296341Sdelphij    int i, j;
1660127128Snectar
1661296341Sdelphij    i = strlen(serialfile) + strlen(old_suffix);
1662296341Sdelphij    j = strlen(serialfile) + strlen(new_suffix);
1663296341Sdelphij    if (i > j)
1664296341Sdelphij        j = i;
1665296341Sdelphij    if (j + 1 >= BSIZE) {
1666296341Sdelphij        BIO_printf(bio_err, "file name too long\n");
1667296341Sdelphij        goto err;
1668296341Sdelphij    }
1669127128Snectar#ifndef OPENSSL_SYS_VMS
1670296341Sdelphij    j = BIO_snprintf(buf[0], sizeof buf[0], "%s.%s", serialfile, new_suffix);
1671127128Snectar#else
1672296341Sdelphij    j = BIO_snprintf(buf[0], sizeof buf[0], "%s-%s", serialfile, new_suffix);
1673127128Snectar#endif
1674127128Snectar#ifndef OPENSSL_SYS_VMS
1675296341Sdelphij    j = BIO_snprintf(buf[1], sizeof buf[1], "%s.%s", serialfile, old_suffix);
1676127128Snectar#else
1677296341Sdelphij    j = BIO_snprintf(buf[1], sizeof buf[1], "%s-%s", serialfile, old_suffix);
1678127128Snectar#endif
1679238405Sjkim#ifdef RL_DEBUG
1680296341Sdelphij    BIO_printf(bio_err, "DEBUG: renaming \"%s\" to \"%s\"\n",
1681296341Sdelphij               serialfile, buf[1]);
1682238405Sjkim#endif
1683296341Sdelphij    if (rename(serialfile, buf[1]) < 0 && errno != ENOENT
1684127128Snectar#ifdef ENOTDIR
1685296341Sdelphij        && errno != ENOTDIR
1686127128Snectar#endif
1687296341Sdelphij        ) {
1688296341Sdelphij        BIO_printf(bio_err,
1689296341Sdelphij                   "unable to rename %s to %s\n", serialfile, buf[1]);
1690296341Sdelphij        perror("reason");
1691296341Sdelphij        goto err;
1692296341Sdelphij    }
1693127128Snectar#ifdef RL_DEBUG
1694296341Sdelphij    BIO_printf(bio_err, "DEBUG: renaming \"%s\" to \"%s\"\n",
1695296341Sdelphij               buf[0], serialfile);
1696127128Snectar#endif
1697296341Sdelphij    if (rename(buf[0], serialfile) < 0) {
1698296341Sdelphij        BIO_printf(bio_err,
1699296341Sdelphij                   "unable to rename %s to %s\n", buf[0], serialfile);
1700296341Sdelphij        perror("reason");
1701296341Sdelphij        rename(buf[1], serialfile);
1702296341Sdelphij        goto err;
1703296341Sdelphij    }
1704296341Sdelphij    return 1;
1705127128Snectar err:
1706296341Sdelphij    return 0;
1707296341Sdelphij}
1708127128Snectar
1709142425Snectarint rand_serial(BIGNUM *b, ASN1_INTEGER *ai)
1710296341Sdelphij{
1711296341Sdelphij    BIGNUM *btmp;
1712296341Sdelphij    int ret = 0;
1713296341Sdelphij    if (b)
1714296341Sdelphij        btmp = b;
1715296341Sdelphij    else
1716296341Sdelphij        btmp = BN_new();
1717142425Snectar
1718296341Sdelphij    if (!btmp)
1719296341Sdelphij        return 0;
1720142425Snectar
1721296341Sdelphij    if (!BN_pseudo_rand(btmp, SERIAL_RAND_BITS, 0, 0))
1722296341Sdelphij        goto error;
1723296341Sdelphij    if (ai && !BN_to_ASN1_INTEGER(btmp, ai))
1724296341Sdelphij        goto error;
1725142425Snectar
1726296341Sdelphij    ret = 1;
1727142425Snectar
1728296341Sdelphij error:
1729142425Snectar
1730296341Sdelphij    if (!b)
1731296341Sdelphij        BN_free(btmp);
1732296341Sdelphij
1733296341Sdelphij    return ret;
1734296341Sdelphij}
1735296341Sdelphij
1736127128SnectarCA_DB *load_index(char *dbfile, DB_ATTR *db_attr)
1737296341Sdelphij{
1738296341Sdelphij    CA_DB *retdb = NULL;
1739296341Sdelphij    TXT_DB *tmpdb = NULL;
1740296341Sdelphij    BIO *in = BIO_new(BIO_s_file());
1741296341Sdelphij    CONF *dbattr_conf = NULL;
1742296341Sdelphij    char buf[1][BSIZE];
1743296341Sdelphij    long errorline = -1;
1744127128Snectar
1745296341Sdelphij    if (in == NULL) {
1746296341Sdelphij        ERR_print_errors(bio_err);
1747296341Sdelphij        goto err;
1748296341Sdelphij    }
1749296341Sdelphij    if (BIO_read_filename(in, dbfile) <= 0) {
1750296341Sdelphij        perror(dbfile);
1751296341Sdelphij        BIO_printf(bio_err, "unable to open '%s'\n", dbfile);
1752296341Sdelphij        goto err;
1753296341Sdelphij    }
1754296341Sdelphij    if ((tmpdb = TXT_DB_read(in, DB_NUMBER)) == NULL)
1755296341Sdelphij        goto err;
1756127128Snectar
1757127128Snectar#ifndef OPENSSL_SYS_VMS
1758296341Sdelphij    BIO_snprintf(buf[0], sizeof buf[0], "%s.attr", dbfile);
1759127128Snectar#else
1760296341Sdelphij    BIO_snprintf(buf[0], sizeof buf[0], "%s-attr", dbfile);
1761127128Snectar#endif
1762296341Sdelphij    dbattr_conf = NCONF_new(NULL);
1763296341Sdelphij    if (NCONF_load(dbattr_conf, buf[0], &errorline) <= 0) {
1764296341Sdelphij        if (errorline > 0) {
1765296341Sdelphij            BIO_printf(bio_err,
1766296341Sdelphij                       "error on line %ld of db attribute file '%s'\n",
1767296341Sdelphij                       errorline, buf[0]);
1768296341Sdelphij            goto err;
1769296341Sdelphij        } else {
1770296341Sdelphij            NCONF_free(dbattr_conf);
1771296341Sdelphij            dbattr_conf = NULL;
1772296341Sdelphij        }
1773296341Sdelphij    }
1774127128Snectar
1775296341Sdelphij    if ((retdb = OPENSSL_malloc(sizeof(CA_DB))) == NULL) {
1776296341Sdelphij        fprintf(stderr, "Out of memory\n");
1777296341Sdelphij        goto err;
1778296341Sdelphij    }
1779127128Snectar
1780296341Sdelphij    retdb->db = tmpdb;
1781296341Sdelphij    tmpdb = NULL;
1782296341Sdelphij    if (db_attr)
1783296341Sdelphij        retdb->attributes = *db_attr;
1784296341Sdelphij    else {
1785296341Sdelphij        retdb->attributes.unique_subject = 1;
1786296341Sdelphij    }
1787127128Snectar
1788296341Sdelphij    if (dbattr_conf) {
1789296341Sdelphij        char *p = NCONF_get_string(dbattr_conf, NULL, "unique_subject");
1790296341Sdelphij        if (p) {
1791160814Ssimon#ifdef RL_DEBUG
1792296341Sdelphij            BIO_printf(bio_err,
1793296341Sdelphij                       "DEBUG[load_index]: unique_subject = \"%s\"\n", p);
1794160814Ssimon#endif
1795296341Sdelphij            retdb->attributes.unique_subject = parse_yesno(p, 1);
1796296341Sdelphij        }
1797296341Sdelphij    }
1798127128Snectar
1799127128Snectar err:
1800296341Sdelphij    if (dbattr_conf)
1801296341Sdelphij        NCONF_free(dbattr_conf);
1802296341Sdelphij    if (tmpdb)
1803296341Sdelphij        TXT_DB_free(tmpdb);
1804296341Sdelphij    if (in)
1805296341Sdelphij        BIO_free_all(in);
1806296341Sdelphij    return retdb;
1807296341Sdelphij}
1808127128Snectar
1809127128Snectarint index_index(CA_DB *db)
1810296341Sdelphij{
1811296341Sdelphij    if (!TXT_DB_create_index(db->db, DB_serial, NULL,
1812296341Sdelphij                             LHASH_HASH_FN(index_serial),
1813296341Sdelphij                             LHASH_COMP_FN(index_serial))) {
1814296341Sdelphij        BIO_printf(bio_err,
1815296341Sdelphij                   "error creating serial number index:(%ld,%ld,%ld)\n",
1816296341Sdelphij                   db->db->error, db->db->arg1, db->db->arg2);
1817296341Sdelphij        return 0;
1818296341Sdelphij    }
1819127128Snectar
1820296341Sdelphij    if (db->attributes.unique_subject
1821296341Sdelphij        && !TXT_DB_create_index(db->db, DB_name, index_name_qual,
1822296341Sdelphij                                LHASH_HASH_FN(index_name),
1823296341Sdelphij                                LHASH_COMP_FN(index_name))) {
1824296341Sdelphij        BIO_printf(bio_err, "error creating name index:(%ld,%ld,%ld)\n",
1825296341Sdelphij                   db->db->error, db->db->arg1, db->db->arg2);
1826296341Sdelphij        return 0;
1827296341Sdelphij    }
1828296341Sdelphij    return 1;
1829296341Sdelphij}
1830127128Snectar
1831160814Ssimonint save_index(const char *dbfile, const char *suffix, CA_DB *db)
1832296341Sdelphij{
1833296341Sdelphij    char buf[3][BSIZE];
1834296341Sdelphij    BIO *out = BIO_new(BIO_s_file());
1835296341Sdelphij    int j;
1836127128Snectar
1837296341Sdelphij    if (out == NULL) {
1838296341Sdelphij        ERR_print_errors(bio_err);
1839296341Sdelphij        goto err;
1840296341Sdelphij    }
1841127128Snectar
1842296341Sdelphij    j = strlen(dbfile) + strlen(suffix);
1843296341Sdelphij    if (j + 6 >= BSIZE) {
1844296341Sdelphij        BIO_printf(bio_err, "file name too long\n");
1845296341Sdelphij        goto err;
1846296341Sdelphij    }
1847127128Snectar#ifndef OPENSSL_SYS_VMS
1848296341Sdelphij    j = BIO_snprintf(buf[2], sizeof buf[2], "%s.attr", dbfile);
1849127128Snectar#else
1850296341Sdelphij    j = BIO_snprintf(buf[2], sizeof buf[2], "%s-attr", dbfile);
1851127128Snectar#endif
1852127128Snectar#ifndef OPENSSL_SYS_VMS
1853296341Sdelphij    j = BIO_snprintf(buf[1], sizeof buf[1], "%s.attr.%s", dbfile, suffix);
1854127128Snectar#else
1855296341Sdelphij    j = BIO_snprintf(buf[1], sizeof buf[1], "%s-attr-%s", dbfile, suffix);
1856127128Snectar#endif
1857127128Snectar#ifndef OPENSSL_SYS_VMS
1858296341Sdelphij    j = BIO_snprintf(buf[0], sizeof buf[0], "%s.%s", dbfile, suffix);
1859127128Snectar#else
1860296341Sdelphij    j = BIO_snprintf(buf[0], sizeof buf[0], "%s-%s", dbfile, suffix);
1861127128Snectar#endif
1862127128Snectar#ifdef RL_DEBUG
1863296341Sdelphij    BIO_printf(bio_err, "DEBUG: writing \"%s\"\n", buf[0]);
1864127128Snectar#endif
1865296341Sdelphij    if (BIO_write_filename(out, buf[0]) <= 0) {
1866296341Sdelphij        perror(dbfile);
1867296341Sdelphij        BIO_printf(bio_err, "unable to open '%s'\n", dbfile);
1868296341Sdelphij        goto err;
1869296341Sdelphij    }
1870296341Sdelphij    j = TXT_DB_write(out, db->db);
1871296341Sdelphij    if (j <= 0)
1872296341Sdelphij        goto err;
1873127128Snectar
1874296341Sdelphij    BIO_free(out);
1875296341Sdelphij
1876296341Sdelphij    out = BIO_new(BIO_s_file());
1877127128Snectar#ifdef RL_DEBUG
1878296341Sdelphij    BIO_printf(bio_err, "DEBUG: writing \"%s\"\n", buf[1]);
1879127128Snectar#endif
1880296341Sdelphij    if (BIO_write_filename(out, buf[1]) <= 0) {
1881296341Sdelphij        perror(buf[2]);
1882296341Sdelphij        BIO_printf(bio_err, "unable to open '%s'\n", buf[2]);
1883296341Sdelphij        goto err;
1884296341Sdelphij    }
1885296341Sdelphij    BIO_printf(out, "unique_subject = %s\n",
1886296341Sdelphij               db->attributes.unique_subject ? "yes" : "no");
1887296341Sdelphij    BIO_free(out);
1888127128Snectar
1889296341Sdelphij    return 1;
1890127128Snectar err:
1891296341Sdelphij    return 0;
1892296341Sdelphij}
1893127128Snectar
1894296341Sdelphijint rotate_index(const char *dbfile, const char *new_suffix,
1895296341Sdelphij                 const char *old_suffix)
1896296341Sdelphij{
1897296341Sdelphij    char buf[5][BSIZE];
1898296341Sdelphij    int i, j;
1899127128Snectar
1900296341Sdelphij    i = strlen(dbfile) + strlen(old_suffix);
1901296341Sdelphij    j = strlen(dbfile) + strlen(new_suffix);
1902296341Sdelphij    if (i > j)
1903296341Sdelphij        j = i;
1904296341Sdelphij    if (j + 6 >= BSIZE) {
1905296341Sdelphij        BIO_printf(bio_err, "file name too long\n");
1906296341Sdelphij        goto err;
1907296341Sdelphij    }
1908127128Snectar#ifndef OPENSSL_SYS_VMS
1909296341Sdelphij    j = BIO_snprintf(buf[4], sizeof buf[4], "%s.attr", dbfile);
1910127128Snectar#else
1911296341Sdelphij    j = BIO_snprintf(buf[4], sizeof buf[4], "%s-attr", dbfile);
1912127128Snectar#endif
1913127128Snectar#ifndef OPENSSL_SYS_VMS
1914296341Sdelphij    j = BIO_snprintf(buf[2], sizeof buf[2], "%s.attr.%s", dbfile, new_suffix);
1915127128Snectar#else
1916296341Sdelphij    j = BIO_snprintf(buf[2], sizeof buf[2], "%s-attr-%s", dbfile, new_suffix);
1917127128Snectar#endif
1918127128Snectar#ifndef OPENSSL_SYS_VMS
1919296341Sdelphij    j = BIO_snprintf(buf[0], sizeof buf[0], "%s.%s", dbfile, new_suffix);
1920127128Snectar#else
1921296341Sdelphij    j = BIO_snprintf(buf[0], sizeof buf[0], "%s-%s", dbfile, new_suffix);
1922127128Snectar#endif
1923127128Snectar#ifndef OPENSSL_SYS_VMS
1924296341Sdelphij    j = BIO_snprintf(buf[1], sizeof buf[1], "%s.%s", dbfile, old_suffix);
1925127128Snectar#else
1926296341Sdelphij    j = BIO_snprintf(buf[1], sizeof buf[1], "%s-%s", dbfile, old_suffix);
1927127128Snectar#endif
1928127128Snectar#ifndef OPENSSL_SYS_VMS
1929296341Sdelphij    j = BIO_snprintf(buf[3], sizeof buf[3], "%s.attr.%s", dbfile, old_suffix);
1930127128Snectar#else
1931296341Sdelphij    j = BIO_snprintf(buf[3], sizeof buf[3], "%s-attr-%s", dbfile, old_suffix);
1932127128Snectar#endif
1933238405Sjkim#ifdef RL_DEBUG
1934296341Sdelphij    BIO_printf(bio_err, "DEBUG: renaming \"%s\" to \"%s\"\n", dbfile, buf[1]);
1935238405Sjkim#endif
1936296341Sdelphij    if (rename(dbfile, buf[1]) < 0 && errno != ENOENT
1937127128Snectar#ifdef ENOTDIR
1938296341Sdelphij        && errno != ENOTDIR
1939127128Snectar#endif
1940296341Sdelphij        ) {
1941296341Sdelphij        BIO_printf(bio_err, "unable to rename %s to %s\n", dbfile, buf[1]);
1942296341Sdelphij        perror("reason");
1943296341Sdelphij        goto err;
1944296341Sdelphij    }
1945127128Snectar#ifdef RL_DEBUG
1946296341Sdelphij    BIO_printf(bio_err, "DEBUG: renaming \"%s\" to \"%s\"\n", buf[0], dbfile);
1947127128Snectar#endif
1948296341Sdelphij    if (rename(buf[0], dbfile) < 0) {
1949296341Sdelphij        BIO_printf(bio_err, "unable to rename %s to %s\n", buf[0], dbfile);
1950296341Sdelphij        perror("reason");
1951296341Sdelphij        rename(buf[1], dbfile);
1952296341Sdelphij        goto err;
1953296341Sdelphij    }
1954238405Sjkim#ifdef RL_DEBUG
1955296341Sdelphij    BIO_printf(bio_err, "DEBUG: renaming \"%s\" to \"%s\"\n", buf[4], buf[3]);
1956238405Sjkim#endif
1957296341Sdelphij    if (rename(buf[4], buf[3]) < 0 && errno != ENOENT
1958127128Snectar#ifdef ENOTDIR
1959296341Sdelphij        && errno != ENOTDIR
1960127128Snectar#endif
1961296341Sdelphij        ) {
1962296341Sdelphij        BIO_printf(bio_err, "unable to rename %s to %s\n", buf[4], buf[3]);
1963296341Sdelphij        perror("reason");
1964296341Sdelphij        rename(dbfile, buf[0]);
1965296341Sdelphij        rename(buf[1], dbfile);
1966296341Sdelphij        goto err;
1967296341Sdelphij    }
1968127128Snectar#ifdef RL_DEBUG
1969296341Sdelphij    BIO_printf(bio_err, "DEBUG: renaming \"%s\" to \"%s\"\n", buf[2], buf[4]);
1970127128Snectar#endif
1971296341Sdelphij    if (rename(buf[2], buf[4]) < 0) {
1972296341Sdelphij        BIO_printf(bio_err, "unable to rename %s to %s\n", buf[2], buf[4]);
1973296341Sdelphij        perror("reason");
1974296341Sdelphij        rename(buf[3], buf[4]);
1975296341Sdelphij        rename(dbfile, buf[0]);
1976296341Sdelphij        rename(buf[1], dbfile);
1977296341Sdelphij        goto err;
1978296341Sdelphij    }
1979296341Sdelphij    return 1;
1980127128Snectar err:
1981296341Sdelphij    return 0;
1982296341Sdelphij}
1983127128Snectar
1984127128Snectarvoid free_index(CA_DB *db)
1985296341Sdelphij{
1986296341Sdelphij    if (db) {
1987296341Sdelphij        if (db->db)
1988296341Sdelphij            TXT_DB_free(db->db);
1989296341Sdelphij        OPENSSL_free(db);
1990296341Sdelphij    }
1991296341Sdelphij}
1992142425Snectar
1993160814Ssimonint parse_yesno(const char *str, int def)
1994296341Sdelphij{
1995296341Sdelphij    int ret = def;
1996296341Sdelphij    if (str) {
1997296341Sdelphij        switch (*str) {
1998296341Sdelphij        case 'f':              /* false */
1999296341Sdelphij        case 'F':              /* FALSE */
2000296341Sdelphij        case 'n':              /* no */
2001296341Sdelphij        case 'N':              /* NO */
2002296341Sdelphij        case '0':              /* 0 */
2003296341Sdelphij            ret = 0;
2004296341Sdelphij            break;
2005296341Sdelphij        case 't':              /* true */
2006296341Sdelphij        case 'T':              /* TRUE */
2007296341Sdelphij        case 'y':              /* yes */
2008296341Sdelphij        case 'Y':              /* YES */
2009296341Sdelphij        case '1':              /* 1 */
2010296341Sdelphij            ret = 1;
2011296341Sdelphij            break;
2012296341Sdelphij        default:
2013296341Sdelphij            ret = def;
2014296341Sdelphij            break;
2015296341Sdelphij        }
2016296341Sdelphij    }
2017296341Sdelphij    return ret;
2018296341Sdelphij}
2019160814Ssimon
2020160814Ssimon/*
2021160814Ssimon * subject is expected to be in the format /type0=value0/type1=value1/type2=...
2022160814Ssimon * where characters may be escaped by \
2023160814Ssimon */
2024160814SsimonX509_NAME *parse_name(char *subject, long chtype, int multirdn)
2025296341Sdelphij{
2026296341Sdelphij    size_t buflen = strlen(subject) + 1; /* to copy the types and values
2027296341Sdelphij                                          * into. due to escaping, the copy
2028296341Sdelphij                                          * can only become shorter */
2029296341Sdelphij    char *buf = OPENSSL_malloc(buflen);
2030296341Sdelphij    size_t max_ne = buflen / 2 + 1; /* maximum number of name elements */
2031296341Sdelphij    char **ne_types = OPENSSL_malloc(max_ne * sizeof(char *));
2032296341Sdelphij    char **ne_values = OPENSSL_malloc(max_ne * sizeof(char *));
2033296341Sdelphij    int *mval = OPENSSL_malloc(max_ne * sizeof(int));
2034160814Ssimon
2035296341Sdelphij    char *sp = subject, *bp = buf;
2036296341Sdelphij    int i, ne_num = 0;
2037160814Ssimon
2038296341Sdelphij    X509_NAME *n = NULL;
2039296341Sdelphij    int nid;
2040160814Ssimon
2041296341Sdelphij    if (!buf || !ne_types || !ne_values || !mval) {
2042296341Sdelphij        BIO_printf(bio_err, "malloc error\n");
2043296341Sdelphij        goto error;
2044296341Sdelphij    }
2045160814Ssimon
2046296341Sdelphij    if (*subject != '/') {
2047296341Sdelphij        BIO_printf(bio_err, "Subject does not start with '/'.\n");
2048296341Sdelphij        goto error;
2049296341Sdelphij    }
2050296341Sdelphij    sp++;                       /* skip leading / */
2051160814Ssimon
2052296341Sdelphij    /* no multivalued RDN by default */
2053296341Sdelphij    mval[ne_num] = 0;
2054160814Ssimon
2055296341Sdelphij    while (*sp) {
2056296341Sdelphij        /* collect type */
2057296341Sdelphij        ne_types[ne_num] = bp;
2058296341Sdelphij        while (*sp) {
2059296341Sdelphij            if (*sp == '\\') {  /* is there anything to escape in the
2060296341Sdelphij                                 * type...? */
2061296341Sdelphij                if (*++sp)
2062296341Sdelphij                    *bp++ = *sp++;
2063296341Sdelphij                else {
2064296341Sdelphij                    BIO_printf(bio_err,
2065296341Sdelphij                               "escape character at end of string\n");
2066296341Sdelphij                    goto error;
2067296341Sdelphij                }
2068296341Sdelphij            } else if (*sp == '=') {
2069296341Sdelphij                sp++;
2070296341Sdelphij                *bp++ = '\0';
2071296341Sdelphij                break;
2072296341Sdelphij            } else
2073296341Sdelphij                *bp++ = *sp++;
2074296341Sdelphij        }
2075296341Sdelphij        if (!*sp) {
2076296341Sdelphij            BIO_printf(bio_err,
2077296341Sdelphij                       "end of string encountered while processing type of subject name element #%d\n",
2078296341Sdelphij                       ne_num);
2079296341Sdelphij            goto error;
2080296341Sdelphij        }
2081296341Sdelphij        ne_values[ne_num] = bp;
2082296341Sdelphij        while (*sp) {
2083296341Sdelphij            if (*sp == '\\') {
2084296341Sdelphij                if (*++sp)
2085296341Sdelphij                    *bp++ = *sp++;
2086296341Sdelphij                else {
2087296341Sdelphij                    BIO_printf(bio_err,
2088296341Sdelphij                               "escape character at end of string\n");
2089296341Sdelphij                    goto error;
2090296341Sdelphij                }
2091296341Sdelphij            } else if (*sp == '/') {
2092296341Sdelphij                sp++;
2093296341Sdelphij                /* no multivalued RDN by default */
2094296341Sdelphij                mval[ne_num + 1] = 0;
2095296341Sdelphij                break;
2096296341Sdelphij            } else if (*sp == '+' && multirdn) {
2097296341Sdelphij                /*
2098296341Sdelphij                 * a not escaped + signals a mutlivalued RDN
2099296341Sdelphij                 */
2100296341Sdelphij                sp++;
2101296341Sdelphij                mval[ne_num + 1] = -1;
2102296341Sdelphij                break;
2103296341Sdelphij            } else
2104296341Sdelphij                *bp++ = *sp++;
2105296341Sdelphij        }
2106296341Sdelphij        *bp++ = '\0';
2107296341Sdelphij        ne_num++;
2108296341Sdelphij    }
2109160814Ssimon
2110296341Sdelphij    if (!(n = X509_NAME_new()))
2111296341Sdelphij        goto error;
2112160814Ssimon
2113296341Sdelphij    for (i = 0; i < ne_num; i++) {
2114296341Sdelphij        if ((nid = OBJ_txt2nid(ne_types[i])) == NID_undef) {
2115296341Sdelphij            BIO_printf(bio_err,
2116296341Sdelphij                       "Subject Attribute %s has no known NID, skipped\n",
2117296341Sdelphij                       ne_types[i]);
2118296341Sdelphij            continue;
2119296341Sdelphij        }
2120160814Ssimon
2121296341Sdelphij        if (!*ne_values[i]) {
2122296341Sdelphij            BIO_printf(bio_err,
2123296341Sdelphij                       "No value provided for Subject Attribute %s, skipped\n",
2124296341Sdelphij                       ne_types[i]);
2125296341Sdelphij            continue;
2126296341Sdelphij        }
2127160814Ssimon
2128296341Sdelphij        if (!X509_NAME_add_entry_by_NID
2129296341Sdelphij            (n, nid, chtype, (unsigned char *)ne_values[i], -1, -1, mval[i]))
2130296341Sdelphij            goto error;
2131296341Sdelphij    }
2132160814Ssimon
2133296341Sdelphij    OPENSSL_free(ne_values);
2134296341Sdelphij    OPENSSL_free(ne_types);
2135296341Sdelphij    OPENSSL_free(buf);
2136296341Sdelphij    OPENSSL_free(mval);
2137296341Sdelphij    return n;
2138160814Ssimon
2139296341Sdelphij error:
2140296341Sdelphij    X509_NAME_free(n);
2141296341Sdelphij    if (ne_values)
2142296341Sdelphij        OPENSSL_free(ne_values);
2143296341Sdelphij    if (ne_types)
2144296341Sdelphij        OPENSSL_free(ne_types);
2145296341Sdelphij    if (mval)
2146296341Sdelphij        OPENSSL_free(mval);
2147296341Sdelphij    if (buf)
2148296341Sdelphij        OPENSSL_free(buf);
2149296341Sdelphij    return NULL;
2150160814Ssimon}
2151160814Ssimon
2152160814Ssimonint args_verify(char ***pargs, int *pargc,
2153296341Sdelphij                int *badarg, BIO *err, X509_VERIFY_PARAM **pm)
2154296341Sdelphij{
2155296341Sdelphij    ASN1_OBJECT *otmp = NULL;
2156296341Sdelphij    unsigned long flags = 0;
2157296341Sdelphij    int i;
2158296341Sdelphij    int purpose = 0, depth = -1;
2159296341Sdelphij    char **oldargs = *pargs;
2160296341Sdelphij    char *arg = **pargs, *argn = (*pargs)[1];
2161296341Sdelphij    time_t at_time = 0;
2162296341Sdelphij    if (!strcmp(arg, "-policy")) {
2163296341Sdelphij        if (!argn)
2164296341Sdelphij            *badarg = 1;
2165296341Sdelphij        else {
2166296341Sdelphij            otmp = OBJ_txt2obj(argn, 0);
2167296341Sdelphij            if (!otmp) {
2168296341Sdelphij                BIO_printf(err, "Invalid Policy \"%s\"\n", argn);
2169296341Sdelphij                *badarg = 1;
2170296341Sdelphij            }
2171296341Sdelphij        }
2172296341Sdelphij        (*pargs)++;
2173296341Sdelphij    } else if (strcmp(arg, "-purpose") == 0) {
2174296341Sdelphij        X509_PURPOSE *xptmp;
2175296341Sdelphij        if (!argn)
2176296341Sdelphij            *badarg = 1;
2177296341Sdelphij        else {
2178296341Sdelphij            i = X509_PURPOSE_get_by_sname(argn);
2179296341Sdelphij            if (i < 0) {
2180296341Sdelphij                BIO_printf(err, "unrecognized purpose\n");
2181296341Sdelphij                *badarg = 1;
2182296341Sdelphij            } else {
2183296341Sdelphij                xptmp = X509_PURPOSE_get0(i);
2184296341Sdelphij                purpose = X509_PURPOSE_get_id(xptmp);
2185296341Sdelphij            }
2186296341Sdelphij        }
2187296341Sdelphij        (*pargs)++;
2188296341Sdelphij    } else if (strcmp(arg, "-verify_depth") == 0) {
2189296341Sdelphij        if (!argn)
2190296341Sdelphij            *badarg = 1;
2191296341Sdelphij        else {
2192296341Sdelphij            depth = atoi(argn);
2193296341Sdelphij            if (depth < 0) {
2194296341Sdelphij                BIO_printf(err, "invalid depth\n");
2195296341Sdelphij                *badarg = 1;
2196296341Sdelphij            }
2197296341Sdelphij        }
2198296341Sdelphij        (*pargs)++;
2199296341Sdelphij    } else if (strcmp(arg, "-attime") == 0) {
2200296341Sdelphij        if (!argn)
2201296341Sdelphij            *badarg = 1;
2202296341Sdelphij        else {
2203296341Sdelphij            long timestamp;
2204296341Sdelphij            /*
2205296341Sdelphij             * interpret the -attime argument as seconds since Epoch
2206296341Sdelphij             */
2207296341Sdelphij            if (sscanf(argn, "%li", &timestamp) != 1) {
2208296341Sdelphij                BIO_printf(bio_err, "Error parsing timestamp %s\n", argn);
2209296341Sdelphij                *badarg = 1;
2210296341Sdelphij            }
2211296341Sdelphij            /* on some platforms time_t may be a float */
2212296341Sdelphij            at_time = (time_t)timestamp;
2213296341Sdelphij        }
2214296341Sdelphij        (*pargs)++;
2215296341Sdelphij    } else if (!strcmp(arg, "-ignore_critical"))
2216296341Sdelphij        flags |= X509_V_FLAG_IGNORE_CRITICAL;
2217296341Sdelphij    else if (!strcmp(arg, "-issuer_checks"))
2218296341Sdelphij        flags |= X509_V_FLAG_CB_ISSUER_CHECK;
2219296341Sdelphij    else if (!strcmp(arg, "-crl_check"))
2220296341Sdelphij        flags |= X509_V_FLAG_CRL_CHECK;
2221296341Sdelphij    else if (!strcmp(arg, "-crl_check_all"))
2222296341Sdelphij        flags |= X509_V_FLAG_CRL_CHECK | X509_V_FLAG_CRL_CHECK_ALL;
2223296341Sdelphij    else if (!strcmp(arg, "-policy_check"))
2224296341Sdelphij        flags |= X509_V_FLAG_POLICY_CHECK;
2225296341Sdelphij    else if (!strcmp(arg, "-explicit_policy"))
2226296341Sdelphij        flags |= X509_V_FLAG_EXPLICIT_POLICY;
2227296341Sdelphij    else if (!strcmp(arg, "-inhibit_any"))
2228296341Sdelphij        flags |= X509_V_FLAG_INHIBIT_ANY;
2229296341Sdelphij    else if (!strcmp(arg, "-inhibit_map"))
2230296341Sdelphij        flags |= X509_V_FLAG_INHIBIT_MAP;
2231296341Sdelphij    else if (!strcmp(arg, "-x509_strict"))
2232296341Sdelphij        flags |= X509_V_FLAG_X509_STRICT;
2233296341Sdelphij    else if (!strcmp(arg, "-extended_crl"))
2234296341Sdelphij        flags |= X509_V_FLAG_EXTENDED_CRL_SUPPORT;
2235296341Sdelphij    else if (!strcmp(arg, "-use_deltas"))
2236296341Sdelphij        flags |= X509_V_FLAG_USE_DELTAS;
2237296341Sdelphij    else if (!strcmp(arg, "-policy_print"))
2238296341Sdelphij        flags |= X509_V_FLAG_NOTIFY_POLICY;
2239296341Sdelphij    else if (!strcmp(arg, "-check_ss_sig"))
2240296341Sdelphij        flags |= X509_V_FLAG_CHECK_SS_SIGNATURE;
2241296341Sdelphij    else if (!strcmp(arg, "-no_alt_chains"))
2242296341Sdelphij        flags |= X509_V_FLAG_NO_ALT_CHAINS;
2243296341Sdelphij    else
2244296341Sdelphij        return 0;
2245160814Ssimon
2246296341Sdelphij    if (*badarg) {
2247296341Sdelphij        if (*pm)
2248296341Sdelphij            X509_VERIFY_PARAM_free(*pm);
2249296341Sdelphij        *pm = NULL;
2250296341Sdelphij        goto end;
2251296341Sdelphij    }
2252160814Ssimon
2253296341Sdelphij    if (!*pm && !(*pm = X509_VERIFY_PARAM_new())) {
2254296341Sdelphij        *badarg = 1;
2255296341Sdelphij        goto end;
2256296341Sdelphij    }
2257160814Ssimon
2258296341Sdelphij    if (otmp)
2259296341Sdelphij        X509_VERIFY_PARAM_add0_policy(*pm, otmp);
2260296341Sdelphij    if (flags)
2261296341Sdelphij        X509_VERIFY_PARAM_set_flags(*pm, flags);
2262160814Ssimon
2263296341Sdelphij    if (purpose)
2264296341Sdelphij        X509_VERIFY_PARAM_set_purpose(*pm, purpose);
2265160814Ssimon
2266296341Sdelphij    if (depth >= 0)
2267296341Sdelphij        X509_VERIFY_PARAM_set_depth(*pm, depth);
2268238405Sjkim
2269296341Sdelphij    if (at_time)
2270296341Sdelphij        X509_VERIFY_PARAM_set_time(*pm, at_time);
2271238405Sjkim
2272296341Sdelphij end:
2273160814Ssimon
2274296341Sdelphij    (*pargs)++;
2275160814Ssimon
2276296341Sdelphij    if (pargc)
2277296341Sdelphij        *pargc -= *pargs - oldargs;
2278160814Ssimon
2279296341Sdelphij    return 1;
2280160814Ssimon
2281296341Sdelphij}
2282160814Ssimon
2283296341Sdelphij/*
2284296341Sdelphij * Read whole contents of a BIO into an allocated memory buffer and return
2285296341Sdelphij * it.
2286238405Sjkim */
2287238405Sjkim
2288238405Sjkimint bio_to_mem(unsigned char **out, int maxlen, BIO *in)
2289296341Sdelphij{
2290296341Sdelphij    BIO *mem;
2291296341Sdelphij    int len, ret;
2292296341Sdelphij    unsigned char tbuf[1024];
2293296341Sdelphij    mem = BIO_new(BIO_s_mem());
2294296341Sdelphij    if (!mem)
2295296341Sdelphij        return -1;
2296296341Sdelphij    for (;;) {
2297296341Sdelphij        if ((maxlen != -1) && maxlen < 1024)
2298296341Sdelphij            len = maxlen;
2299296341Sdelphij        else
2300296341Sdelphij            len = 1024;
2301296341Sdelphij        len = BIO_read(in, tbuf, len);
2302296341Sdelphij        if (len <= 0)
2303296341Sdelphij            break;
2304296341Sdelphij        if (BIO_write(mem, tbuf, len) != len) {
2305296341Sdelphij            BIO_free(mem);
2306296341Sdelphij            return -1;
2307296341Sdelphij        }
2308296341Sdelphij        maxlen -= len;
2309238405Sjkim
2310296341Sdelphij        if (maxlen == 0)
2311296341Sdelphij            break;
2312296341Sdelphij    }
2313296341Sdelphij    ret = BIO_get_mem_data(mem, (char **)out);
2314296341Sdelphij    BIO_set_flags(mem, BIO_FLAGS_MEM_RDONLY);
2315296341Sdelphij    BIO_free(mem);
2316296341Sdelphij    return ret;
2317296341Sdelphij}
2318238405Sjkim
2319238405Sjkimint pkey_ctrl_string(EVP_PKEY_CTX *ctx, char *value)
2320296341Sdelphij{
2321296341Sdelphij    int rv;
2322296341Sdelphij    char *stmp, *vtmp = NULL;
2323296341Sdelphij    stmp = BUF_strdup(value);
2324296341Sdelphij    if (!stmp)
2325296341Sdelphij        return -1;
2326296341Sdelphij    vtmp = strchr(stmp, ':');
2327296341Sdelphij    if (vtmp) {
2328296341Sdelphij        *vtmp = 0;
2329296341Sdelphij        vtmp++;
2330296341Sdelphij    }
2331296341Sdelphij    rv = EVP_PKEY_CTX_ctrl_str(ctx, stmp, vtmp);
2332296341Sdelphij    OPENSSL_free(stmp);
2333296341Sdelphij    return rv;
2334296341Sdelphij}
2335238405Sjkim
2336160814Ssimonstatic void nodes_print(BIO *out, const char *name,
2337296341Sdelphij                        STACK_OF(X509_POLICY_NODE) *nodes)
2338296341Sdelphij{
2339296341Sdelphij    X509_POLICY_NODE *node;
2340296341Sdelphij    int i;
2341296341Sdelphij    BIO_printf(out, "%s Policies:", name);
2342296341Sdelphij    if (nodes) {
2343296341Sdelphij        BIO_puts(out, "\n");
2344296341Sdelphij        for (i = 0; i < sk_X509_POLICY_NODE_num(nodes); i++) {
2345296341Sdelphij            node = sk_X509_POLICY_NODE_value(nodes, i);
2346296341Sdelphij            X509_POLICY_NODE_print(out, node, 2);
2347296341Sdelphij        }
2348296341Sdelphij    } else
2349296341Sdelphij        BIO_puts(out, " <empty>\n");
2350296341Sdelphij}
2351160814Ssimon
2352160814Ssimonvoid policies_print(BIO *out, X509_STORE_CTX *ctx)
2353296341Sdelphij{
2354296341Sdelphij    X509_POLICY_TREE *tree;
2355296341Sdelphij    int explicit_policy;
2356296341Sdelphij    int free_out = 0;
2357296341Sdelphij    if (out == NULL) {
2358296341Sdelphij        out = BIO_new_fp(stderr, BIO_NOCLOSE);
2359296341Sdelphij        free_out = 1;
2360296341Sdelphij    }
2361296341Sdelphij    tree = X509_STORE_CTX_get0_policy_tree(ctx);
2362296341Sdelphij    explicit_policy = X509_STORE_CTX_get_explicit_policy(ctx);
2363160814Ssimon
2364296341Sdelphij    BIO_printf(out, "Require explicit Policy: %s\n",
2365296341Sdelphij               explicit_policy ? "True" : "False");
2366160814Ssimon
2367296341Sdelphij    nodes_print(out, "Authority", X509_policy_tree_get0_policies(tree));
2368296341Sdelphij    nodes_print(out, "User", X509_policy_tree_get0_user_policies(tree));
2369296341Sdelphij    if (free_out)
2370296341Sdelphij        BIO_free(out);
2371296341Sdelphij}
2372194206Ssimon
2373238405Sjkim#if !defined(OPENSSL_NO_JPAKE) && !defined(OPENSSL_NO_PSK)
2374194206Ssimon
2375194206Ssimonstatic JPAKE_CTX *jpake_init(const char *us, const char *them,
2376296341Sdelphij                             const char *secret)
2377296341Sdelphij{
2378296341Sdelphij    BIGNUM *p = NULL;
2379296341Sdelphij    BIGNUM *g = NULL;
2380296341Sdelphij    BIGNUM *q = NULL;
2381296341Sdelphij    BIGNUM *bnsecret = BN_new();
2382296341Sdelphij    JPAKE_CTX *ctx;
2383194206Ssimon
2384296341Sdelphij    /* Use a safe prime for p (that we found earlier) */
2385296341Sdelphij    BN_hex2bn(&p,
2386296341Sdelphij              "F9E5B365665EA7A05A9C534502780FEE6F1AB5BD4F49947FD036DBD7E905269AF46EF28B0FC07487EE4F5D20FB3C0AF8E700F3A2FA3414970CBED44FEDFF80CE78D800F184BB82435D137AADA2C6C16523247930A63B85661D1FC817A51ACD96168E95898A1F83A79FFB529368AA7833ABD1B0C3AEDDB14D2E1A2F71D99F763F");
2387296341Sdelphij    g = BN_new();
2388296341Sdelphij    BN_set_word(g, 2);
2389296341Sdelphij    q = BN_new();
2390296341Sdelphij    BN_rshift1(q, p);
2391194206Ssimon
2392296341Sdelphij    BN_bin2bn((const unsigned char *)secret, strlen(secret), bnsecret);
2393194206Ssimon
2394296341Sdelphij    ctx = JPAKE_CTX_new(us, them, p, g, q, bnsecret);
2395296341Sdelphij    BN_free(bnsecret);
2396296341Sdelphij    BN_free(q);
2397296341Sdelphij    BN_free(g);
2398296341Sdelphij    BN_free(p);
2399194206Ssimon
2400296341Sdelphij    return ctx;
2401296341Sdelphij}
2402194206Ssimon
2403194206Ssimonstatic void jpake_send_part(BIO *conn, const JPAKE_STEP_PART *p)
2404296341Sdelphij{
2405296341Sdelphij    BN_print(conn, p->gx);
2406296341Sdelphij    BIO_puts(conn, "\n");
2407296341Sdelphij    BN_print(conn, p->zkpx.gr);
2408296341Sdelphij    BIO_puts(conn, "\n");
2409296341Sdelphij    BN_print(conn, p->zkpx.b);
2410296341Sdelphij    BIO_puts(conn, "\n");
2411296341Sdelphij}
2412194206Ssimon
2413194206Ssimonstatic void jpake_send_step1(BIO *bconn, JPAKE_CTX *ctx)
2414296341Sdelphij{
2415296341Sdelphij    JPAKE_STEP1 s1;
2416194206Ssimon
2417296341Sdelphij    JPAKE_STEP1_init(&s1);
2418296341Sdelphij    JPAKE_STEP1_generate(&s1, ctx);
2419296341Sdelphij    jpake_send_part(bconn, &s1.p1);
2420296341Sdelphij    jpake_send_part(bconn, &s1.p2);
2421296341Sdelphij    (void)BIO_flush(bconn);
2422296341Sdelphij    JPAKE_STEP1_release(&s1);
2423296341Sdelphij}
2424194206Ssimon
2425194206Ssimonstatic void jpake_send_step2(BIO *bconn, JPAKE_CTX *ctx)
2426296341Sdelphij{
2427296341Sdelphij    JPAKE_STEP2 s2;
2428194206Ssimon
2429296341Sdelphij    JPAKE_STEP2_init(&s2);
2430296341Sdelphij    JPAKE_STEP2_generate(&s2, ctx);
2431296341Sdelphij    jpake_send_part(bconn, &s2);
2432296341Sdelphij    (void)BIO_flush(bconn);
2433296341Sdelphij    JPAKE_STEP2_release(&s2);
2434296341Sdelphij}
2435194206Ssimon
2436194206Ssimonstatic void jpake_send_step3a(BIO *bconn, JPAKE_CTX *ctx)
2437296341Sdelphij{
2438296341Sdelphij    JPAKE_STEP3A s3a;
2439194206Ssimon
2440296341Sdelphij    JPAKE_STEP3A_init(&s3a);
2441296341Sdelphij    JPAKE_STEP3A_generate(&s3a, ctx);
2442296341Sdelphij    BIO_write(bconn, s3a.hhk, sizeof s3a.hhk);
2443296341Sdelphij    (void)BIO_flush(bconn);
2444296341Sdelphij    JPAKE_STEP3A_release(&s3a);
2445296341Sdelphij}
2446194206Ssimon
2447194206Ssimonstatic void jpake_send_step3b(BIO *bconn, JPAKE_CTX *ctx)
2448296341Sdelphij{
2449296341Sdelphij    JPAKE_STEP3B s3b;
2450194206Ssimon
2451296341Sdelphij    JPAKE_STEP3B_init(&s3b);
2452296341Sdelphij    JPAKE_STEP3B_generate(&s3b, ctx);
2453296341Sdelphij    BIO_write(bconn, s3b.hk, sizeof s3b.hk);
2454296341Sdelphij    (void)BIO_flush(bconn);
2455296341Sdelphij    JPAKE_STEP3B_release(&s3b);
2456296341Sdelphij}
2457194206Ssimon
2458194206Ssimonstatic void readbn(BIGNUM **bn, BIO *bconn)
2459296341Sdelphij{
2460296341Sdelphij    char buf[10240];
2461296341Sdelphij    int l;
2462194206Ssimon
2463296341Sdelphij    l = BIO_gets(bconn, buf, sizeof buf);
2464296341Sdelphij    assert(l > 0);
2465296341Sdelphij    assert(buf[l - 1] == '\n');
2466296341Sdelphij    buf[l - 1] = '\0';
2467296341Sdelphij    BN_hex2bn(bn, buf);
2468296341Sdelphij}
2469194206Ssimon
2470194206Ssimonstatic void jpake_receive_part(JPAKE_STEP_PART *p, BIO *bconn)
2471296341Sdelphij{
2472296341Sdelphij    readbn(&p->gx, bconn);
2473296341Sdelphij    readbn(&p->zkpx.gr, bconn);
2474296341Sdelphij    readbn(&p->zkpx.b, bconn);
2475296341Sdelphij}
2476194206Ssimon
2477194206Ssimonstatic void jpake_receive_step1(JPAKE_CTX *ctx, BIO *bconn)
2478296341Sdelphij{
2479296341Sdelphij    JPAKE_STEP1 s1;
2480194206Ssimon
2481296341Sdelphij    JPAKE_STEP1_init(&s1);
2482296341Sdelphij    jpake_receive_part(&s1.p1, bconn);
2483296341Sdelphij    jpake_receive_part(&s1.p2, bconn);
2484296341Sdelphij    if (!JPAKE_STEP1_process(ctx, &s1)) {
2485296341Sdelphij        ERR_print_errors(bio_err);
2486296341Sdelphij        exit(1);
2487296341Sdelphij    }
2488296341Sdelphij    JPAKE_STEP1_release(&s1);
2489296341Sdelphij}
2490194206Ssimon
2491194206Ssimonstatic void jpake_receive_step2(JPAKE_CTX *ctx, BIO *bconn)
2492296341Sdelphij{
2493296341Sdelphij    JPAKE_STEP2 s2;
2494194206Ssimon
2495296341Sdelphij    JPAKE_STEP2_init(&s2);
2496296341Sdelphij    jpake_receive_part(&s2, bconn);
2497296341Sdelphij    if (!JPAKE_STEP2_process(ctx, &s2)) {
2498296341Sdelphij        ERR_print_errors(bio_err);
2499296341Sdelphij        exit(1);
2500296341Sdelphij    }
2501296341Sdelphij    JPAKE_STEP2_release(&s2);
2502296341Sdelphij}
2503194206Ssimon
2504194206Ssimonstatic void jpake_receive_step3a(JPAKE_CTX *ctx, BIO *bconn)
2505296341Sdelphij{
2506296341Sdelphij    JPAKE_STEP3A s3a;
2507296341Sdelphij    int l;
2508194206Ssimon
2509296341Sdelphij    JPAKE_STEP3A_init(&s3a);
2510296341Sdelphij    l = BIO_read(bconn, s3a.hhk, sizeof s3a.hhk);
2511296341Sdelphij    assert(l == sizeof s3a.hhk);
2512296341Sdelphij    if (!JPAKE_STEP3A_process(ctx, &s3a)) {
2513296341Sdelphij        ERR_print_errors(bio_err);
2514296341Sdelphij        exit(1);
2515296341Sdelphij    }
2516296341Sdelphij    JPAKE_STEP3A_release(&s3a);
2517296341Sdelphij}
2518194206Ssimon
2519194206Ssimonstatic void jpake_receive_step3b(JPAKE_CTX *ctx, BIO *bconn)
2520296341Sdelphij{
2521296341Sdelphij    JPAKE_STEP3B s3b;
2522296341Sdelphij    int l;
2523194206Ssimon
2524296341Sdelphij    JPAKE_STEP3B_init(&s3b);
2525296341Sdelphij    l = BIO_read(bconn, s3b.hk, sizeof s3b.hk);
2526296341Sdelphij    assert(l == sizeof s3b.hk);
2527296341Sdelphij    if (!JPAKE_STEP3B_process(ctx, &s3b)) {
2528296341Sdelphij        ERR_print_errors(bio_err);
2529296341Sdelphij        exit(1);
2530296341Sdelphij    }
2531296341Sdelphij    JPAKE_STEP3B_release(&s3b);
2532296341Sdelphij}
2533194206Ssimon
2534194206Ssimonvoid jpake_client_auth(BIO *out, BIO *conn, const char *secret)
2535296341Sdelphij{
2536296341Sdelphij    JPAKE_CTX *ctx;
2537296341Sdelphij    BIO *bconn;
2538194206Ssimon
2539296341Sdelphij    BIO_puts(out, "Authenticating with JPAKE\n");
2540194206Ssimon
2541296341Sdelphij    ctx = jpake_init("client", "server", secret);
2542194206Ssimon
2543296341Sdelphij    bconn = BIO_new(BIO_f_buffer());
2544296341Sdelphij    BIO_push(bconn, conn);
2545194206Ssimon
2546296341Sdelphij    jpake_send_step1(bconn, ctx);
2547296341Sdelphij    jpake_receive_step1(ctx, bconn);
2548296341Sdelphij    jpake_send_step2(bconn, ctx);
2549296341Sdelphij    jpake_receive_step2(ctx, bconn);
2550296341Sdelphij    jpake_send_step3a(bconn, ctx);
2551296341Sdelphij    jpake_receive_step3b(ctx, bconn);
2552194206Ssimon
2553296341Sdelphij    BIO_puts(out, "JPAKE authentication succeeded, setting PSK\n");
2554194206Ssimon
2555296341Sdelphij    psk_key = BN_bn2hex(JPAKE_get_shared_key(ctx));
2556238405Sjkim
2557296341Sdelphij    BIO_pop(bconn);
2558296341Sdelphij    BIO_free(bconn);
2559238405Sjkim
2560296341Sdelphij    JPAKE_CTX_free(ctx);
2561296341Sdelphij}
2562194206Ssimon
2563194206Ssimonvoid jpake_server_auth(BIO *out, BIO *conn, const char *secret)
2564296341Sdelphij{
2565296341Sdelphij    JPAKE_CTX *ctx;
2566296341Sdelphij    BIO *bconn;
2567194206Ssimon
2568296341Sdelphij    BIO_puts(out, "Authenticating with JPAKE\n");
2569194206Ssimon
2570296341Sdelphij    ctx = jpake_init("server", "client", secret);
2571194206Ssimon
2572296341Sdelphij    bconn = BIO_new(BIO_f_buffer());
2573296341Sdelphij    BIO_push(bconn, conn);
2574194206Ssimon
2575296341Sdelphij    jpake_receive_step1(ctx, bconn);
2576296341Sdelphij    jpake_send_step1(bconn, ctx);
2577296341Sdelphij    jpake_receive_step2(ctx, bconn);
2578296341Sdelphij    jpake_send_step2(bconn, ctx);
2579296341Sdelphij    jpake_receive_step3a(ctx, bconn);
2580296341Sdelphij    jpake_send_step3b(bconn, ctx);
2581194206Ssimon
2582296341Sdelphij    BIO_puts(out, "JPAKE authentication succeeded, setting PSK\n");
2583194206Ssimon
2584296341Sdelphij    psk_key = BN_bn2hex(JPAKE_get_shared_key(ctx));
2585238405Sjkim
2586296341Sdelphij    BIO_pop(bconn);
2587296341Sdelphij    BIO_free(bconn);
2588238405Sjkim
2589296341Sdelphij    JPAKE_CTX_free(ctx);
2590296341Sdelphij}
2591194206Ssimon
2592194206Ssimon#endif
2593238405Sjkim
2594238405Sjkim#if !defined(OPENSSL_NO_TLSEXT) && !defined(OPENSSL_NO_NEXTPROTONEG)
2595296341Sdelphij/*-
2596296341Sdelphij * next_protos_parse parses a comma separated list of strings into a string
2597238405Sjkim * in a format suitable for passing to SSL_CTX_set_next_protos_advertised.
2598238405Sjkim *   outlen: (output) set to the length of the resulting buffer on success.
2599238405Sjkim *   err: (maybe NULL) on failure, an error message line is written to this BIO.
2600238405Sjkim *   in: a NUL termianted string like "abc,def,ghi"
2601238405Sjkim *
2602238405Sjkim *   returns: a malloced buffer or NULL on failure.
2603238405Sjkim */
2604238405Sjkimunsigned char *next_protos_parse(unsigned short *outlen, const char *in)
2605296341Sdelphij{
2606296341Sdelphij    size_t len;
2607296341Sdelphij    unsigned char *out;
2608296341Sdelphij    size_t i, start = 0;
2609238405Sjkim
2610296341Sdelphij    len = strlen(in);
2611296341Sdelphij    if (len >= 65535)
2612296341Sdelphij        return NULL;
2613238405Sjkim
2614296341Sdelphij    out = OPENSSL_malloc(strlen(in) + 1);
2615296341Sdelphij    if (!out)
2616296341Sdelphij        return NULL;
2617238405Sjkim
2618296341Sdelphij    for (i = 0; i <= len; ++i) {
2619296341Sdelphij        if (i == len || in[i] == ',') {
2620296341Sdelphij            if (i - start > 255) {
2621296341Sdelphij                OPENSSL_free(out);
2622296341Sdelphij                return NULL;
2623296341Sdelphij            }
2624296341Sdelphij            out[start] = i - start;
2625296341Sdelphij            start = i + 1;
2626296341Sdelphij        } else
2627296341Sdelphij            out[i + 1] = in[i];
2628296341Sdelphij    }
2629238405Sjkim
2630296341Sdelphij    *outlen = len + 1;
2631296341Sdelphij    return out;
2632296341Sdelphij}
2633296341Sdelphij#endif                          /* !OPENSSL_NO_TLSEXT &&
2634296341Sdelphij                                 * !OPENSSL_NO_NEXTPROTONEG */
2635238405Sjkim
2636238405Sjkim/*
2637238405Sjkim * Platform-specific sections
2638238405Sjkim */
2639238405Sjkim#if defined(_WIN32)
2640238405Sjkim# ifdef fileno
2641238405Sjkim#  undef fileno
2642238405Sjkim#  define fileno(a) (int)_fileno(a)
2643238405Sjkim# endif
2644238405Sjkim
2645238405Sjkim# include <windows.h>
2646238405Sjkim# include <tchar.h>
2647238405Sjkim
2648238405Sjkimstatic int WIN32_rename(const char *from, const char *to)
2649296341Sdelphij{
2650296341Sdelphij    TCHAR *tfrom = NULL, *tto;
2651296341Sdelphij    DWORD err;
2652296341Sdelphij    int ret = 0;
2653238405Sjkim
2654296341Sdelphij    if (sizeof(TCHAR) == 1) {
2655296341Sdelphij        tfrom = (TCHAR *)from;
2656296341Sdelphij        tto = (TCHAR *)to;
2657296341Sdelphij    } else {                    /* UNICODE path */
2658238405Sjkim
2659296341Sdelphij        size_t i, flen = strlen(from) + 1, tlen = strlen(to) + 1;
2660296341Sdelphij        tfrom = (TCHAR *)malloc(sizeof(TCHAR) * (flen + tlen));
2661296341Sdelphij        if (tfrom == NULL)
2662296341Sdelphij            goto err;
2663296341Sdelphij        tto = tfrom + flen;
2664296341Sdelphij# if !defined(_WIN32_WCE) || _WIN32_WCE>=101
2665296341Sdelphij        if (!MultiByteToWideChar(CP_ACP, 0, from, flen, (WCHAR *)tfrom, flen))
2666296341Sdelphij# endif
2667296341Sdelphij            for (i = 0; i < flen; i++)
2668296341Sdelphij                tfrom[i] = (TCHAR)from[i];
2669296341Sdelphij# if !defined(_WIN32_WCE) || _WIN32_WCE>=101
2670296341Sdelphij        if (!MultiByteToWideChar(CP_ACP, 0, to, tlen, (WCHAR *)tto, tlen))
2671296341Sdelphij# endif
2672296341Sdelphij            for (i = 0; i < tlen; i++)
2673296341Sdelphij                tto[i] = (TCHAR)to[i];
2674296341Sdelphij    }
2675296341Sdelphij
2676296341Sdelphij    if (MoveFile(tfrom, tto))
2677296341Sdelphij        goto ok;
2678296341Sdelphij    err = GetLastError();
2679296341Sdelphij    if (err == ERROR_ALREADY_EXISTS || err == ERROR_FILE_EXISTS) {
2680296341Sdelphij        if (DeleteFile(tto) && MoveFile(tfrom, tto))
2681296341Sdelphij            goto ok;
2682296341Sdelphij        err = GetLastError();
2683296341Sdelphij    }
2684296341Sdelphij    if (err == ERROR_FILE_NOT_FOUND || err == ERROR_PATH_NOT_FOUND)
2685296341Sdelphij        errno = ENOENT;
2686296341Sdelphij    else if (err == ERROR_ACCESS_DENIED)
2687296341Sdelphij        errno = EACCES;
2688296341Sdelphij    else
2689296341Sdelphij        errno = EINVAL;         /* we could map more codes... */
2690296341Sdelphij err:
2691296341Sdelphij    ret = -1;
2692296341Sdelphij ok:
2693296341Sdelphij    if (tfrom != NULL && tfrom != (TCHAR *)from)
2694296341Sdelphij        free(tfrom);
2695296341Sdelphij    return ret;
2696296341Sdelphij}
2697238405Sjkim#endif
2698238405Sjkim
2699238405Sjkim/* app_tminterval section */
2700238405Sjkim#if defined(_WIN32)
2701296341Sdelphijdouble app_tminterval(int stop, int usertime)
2702296341Sdelphij{
2703296341Sdelphij    FILETIME now;
2704296341Sdelphij    double ret = 0;
2705296341Sdelphij    static ULARGE_INTEGER tmstart;
2706296341Sdelphij    static int warning = 1;
2707296341Sdelphij# ifdef _WIN32_WINNT
2708296341Sdelphij    static HANDLE proc = NULL;
2709238405Sjkim
2710296341Sdelphij    if (proc == NULL) {
2711296341Sdelphij        if (check_winnt())
2712296341Sdelphij            proc = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE,
2713296341Sdelphij                               GetCurrentProcessId());
2714296341Sdelphij        if (proc == NULL)
2715296341Sdelphij            proc = (HANDLE) - 1;
2716296341Sdelphij    }
2717238405Sjkim
2718296341Sdelphij    if (usertime && proc != (HANDLE) - 1) {
2719296341Sdelphij        FILETIME junk;
2720296341Sdelphij        GetProcessTimes(proc, &junk, &junk, &junk, &now);
2721296341Sdelphij    } else
2722296341Sdelphij# endif
2723296341Sdelphij    {
2724296341Sdelphij        SYSTEMTIME systime;
2725238405Sjkim
2726296341Sdelphij        if (usertime && warning) {
2727296341Sdelphij            BIO_printf(bio_err, "To get meaningful results, run "
2728296341Sdelphij                       "this program on idle system.\n");
2729296341Sdelphij            warning = 0;
2730296341Sdelphij        }
2731296341Sdelphij        GetSystemTime(&systime);
2732296341Sdelphij        SystemTimeToFileTime(&systime, &now);
2733296341Sdelphij    }
2734238405Sjkim
2735296341Sdelphij    if (stop == TM_START) {
2736296341Sdelphij        tmstart.u.LowPart = now.dwLowDateTime;
2737296341Sdelphij        tmstart.u.HighPart = now.dwHighDateTime;
2738296341Sdelphij    } else {
2739296341Sdelphij        ULARGE_INTEGER tmstop;
2740238405Sjkim
2741296341Sdelphij        tmstop.u.LowPart = now.dwLowDateTime;
2742296341Sdelphij        tmstop.u.HighPart = now.dwHighDateTime;
2743238405Sjkim
2744296341Sdelphij        ret = (__int64)(tmstop.QuadPart - tmstart.QuadPart) * 1e-7;
2745296341Sdelphij    }
2746238405Sjkim
2747296341Sdelphij    return (ret);
2748296341Sdelphij}
2749238405Sjkim
2750238405Sjkim#elif defined(OPENSSL_SYS_NETWARE)
2751296341Sdelphij# include <time.h>
2752238405Sjkim
2753296341Sdelphijdouble app_tminterval(int stop, int usertime)
2754296341Sdelphij{
2755296341Sdelphij    double ret = 0;
2756296341Sdelphij    static clock_t tmstart;
2757296341Sdelphij    static int warning = 1;
2758238405Sjkim
2759296341Sdelphij    if (usertime && warning) {
2760296341Sdelphij        BIO_printf(bio_err, "To get meaningful results, run "
2761296341Sdelphij                   "this program on idle system.\n");
2762296341Sdelphij        warning = 0;
2763296341Sdelphij    }
2764238405Sjkim
2765296341Sdelphij    if (stop == TM_START)
2766296341Sdelphij        tmstart = clock();
2767296341Sdelphij    else
2768296341Sdelphij        ret = (clock() - tmstart) / (double)CLOCKS_PER_SEC;
2769238405Sjkim
2770296341Sdelphij    return (ret);
2771296341Sdelphij}
2772238405Sjkim
2773238405Sjkim#elif defined(OPENSSL_SYSTEM_VXWORKS)
2774296341Sdelphij# include <time.h>
2775238405Sjkim
2776296341Sdelphijdouble app_tminterval(int stop, int usertime)
2777296341Sdelphij{
2778296341Sdelphij    double ret = 0;
2779296341Sdelphij# ifdef CLOCK_REALTIME
2780296341Sdelphij    static struct timespec tmstart;
2781296341Sdelphij    struct timespec now;
2782296341Sdelphij# else
2783296341Sdelphij    static unsigned long tmstart;
2784296341Sdelphij    unsigned long now;
2785296341Sdelphij# endif
2786296341Sdelphij    static int warning = 1;
2787238405Sjkim
2788296341Sdelphij    if (usertime && warning) {
2789296341Sdelphij        BIO_printf(bio_err, "To get meaningful results, run "
2790296341Sdelphij                   "this program on idle system.\n");
2791296341Sdelphij        warning = 0;
2792296341Sdelphij    }
2793296341Sdelphij# ifdef CLOCK_REALTIME
2794296341Sdelphij    clock_gettime(CLOCK_REALTIME, &now);
2795296341Sdelphij    if (stop == TM_START)
2796296341Sdelphij        tmstart = now;
2797296341Sdelphij    else
2798296341Sdelphij        ret = ((now.tv_sec + now.tv_nsec * 1e-9)
2799296341Sdelphij               - (tmstart.tv_sec + tmstart.tv_nsec * 1e-9));
2800296341Sdelphij# else
2801296341Sdelphij    now = tickGet();
2802296341Sdelphij    if (stop == TM_START)
2803296341Sdelphij        tmstart = now;
2804296341Sdelphij    else
2805296341Sdelphij        ret = (now - tmstart) / (double)sysClkRateGet();
2806296341Sdelphij# endif
2807296341Sdelphij    return (ret);
2808296341Sdelphij}
2809238405Sjkim
2810238405Sjkim#elif defined(OPENSSL_SYSTEM_VMS)
2811296341Sdelphij# include <time.h>
2812296341Sdelphij# include <times.h>
2813238405Sjkim
2814296341Sdelphijdouble app_tminterval(int stop, int usertime)
2815296341Sdelphij{
2816296341Sdelphij    static clock_t tmstart;
2817296341Sdelphij    double ret = 0;
2818296341Sdelphij    clock_t now;
2819296341Sdelphij# ifdef __TMS
2820296341Sdelphij    struct tms rus;
2821238405Sjkim
2822296341Sdelphij    now = times(&rus);
2823296341Sdelphij    if (usertime)
2824296341Sdelphij        now = rus.tms_utime;
2825296341Sdelphij# else
2826296341Sdelphij    if (usertime)
2827296341Sdelphij        now = clock();          /* sum of user and kernel times */
2828296341Sdelphij    else {
2829296341Sdelphij        struct timeval tv;
2830296341Sdelphij        gettimeofday(&tv, NULL);
2831296341Sdelphij        now = (clock_t)((unsigned long long)tv.tv_sec * CLK_TCK +
2832296341Sdelphij                        (unsigned long long)tv.tv_usec * (1000000 / CLK_TCK)
2833296341Sdelphij            );
2834296341Sdelphij    }
2835296341Sdelphij# endif
2836296341Sdelphij    if (stop == TM_START)
2837296341Sdelphij        tmstart = now;
2838296341Sdelphij    else
2839296341Sdelphij        ret = (now - tmstart) / (double)(CLK_TCK);
2840238405Sjkim
2841296341Sdelphij    return (ret);
2842296341Sdelphij}
2843238405Sjkim
2844296341Sdelphij#elif defined(_SC_CLK_TCK)      /* by means of unistd.h */
2845296341Sdelphij# include <sys/times.h>
2846238405Sjkim
2847296341Sdelphijdouble app_tminterval(int stop, int usertime)
2848296341Sdelphij{
2849296341Sdelphij    double ret = 0;
2850296341Sdelphij    struct tms rus;
2851296341Sdelphij    clock_t now = times(&rus);
2852296341Sdelphij    static clock_t tmstart;
2853238405Sjkim
2854296341Sdelphij    if (usertime)
2855296341Sdelphij        now = rus.tms_utime;
2856238405Sjkim
2857296341Sdelphij    if (stop == TM_START)
2858296341Sdelphij        tmstart = now;
2859296341Sdelphij    else {
2860296341Sdelphij        long int tck = sysconf(_SC_CLK_TCK);
2861296341Sdelphij        ret = (now - tmstart) / (double)tck;
2862296341Sdelphij    }
2863238405Sjkim
2864296341Sdelphij    return (ret);
2865296341Sdelphij}
2866238405Sjkim
2867238405Sjkim#else
2868296341Sdelphij# include <sys/time.h>
2869296341Sdelphij# include <sys/resource.h>
2870238405Sjkim
2871296341Sdelphijdouble app_tminterval(int stop, int usertime)
2872296341Sdelphij{
2873296341Sdelphij    double ret = 0;
2874296341Sdelphij    struct rusage rus;
2875296341Sdelphij    struct timeval now;
2876296341Sdelphij    static struct timeval tmstart;
2877238405Sjkim
2878296341Sdelphij    if (usertime)
2879296341Sdelphij        getrusage(RUSAGE_SELF, &rus), now = rus.ru_utime;
2880296341Sdelphij    else
2881296341Sdelphij        gettimeofday(&now, NULL);
2882238405Sjkim
2883296341Sdelphij    if (stop == TM_START)
2884296341Sdelphij        tmstart = now;
2885296341Sdelphij    else
2886296341Sdelphij        ret = ((now.tv_sec + now.tv_usec * 1e-6)
2887296341Sdelphij               - (tmstart.tv_sec + tmstart.tv_usec * 1e-6));
2888238405Sjkim
2889296341Sdelphij    return ret;
2890296341Sdelphij}
2891238405Sjkim#endif
2892238405Sjkim
2893238405Sjkim/* app_isdir section */
2894238405Sjkim#ifdef _WIN32
2895238405Sjkimint app_isdir(const char *name)
2896296341Sdelphij{
2897296341Sdelphij    HANDLE hList;
2898296341Sdelphij    WIN32_FIND_DATA FileData;
2899296341Sdelphij# if defined(UNICODE) || defined(_UNICODE)
2900296341Sdelphij    size_t i, len_0 = strlen(name) + 1;
2901238405Sjkim
2902296341Sdelphij    if (len_0 > sizeof(FileData.cFileName) / sizeof(FileData.cFileName[0]))
2903296341Sdelphij        return -1;
2904238405Sjkim
2905296341Sdelphij#  if !defined(_WIN32_WCE) || _WIN32_WCE>=101
2906296341Sdelphij    if (!MultiByteToWideChar
2907296341Sdelphij        (CP_ACP, 0, name, len_0, FileData.cFileName, len_0))
2908296341Sdelphij#  endif
2909296341Sdelphij        for (i = 0; i < len_0; i++)
2910296341Sdelphij            FileData.cFileName[i] = (WCHAR)name[i];
2911238405Sjkim
2912296341Sdelphij    hList = FindFirstFile(FileData.cFileName, &FileData);
2913296341Sdelphij# else
2914296341Sdelphij    hList = FindFirstFile(name, &FileData);
2915296341Sdelphij# endif
2916296341Sdelphij    if (hList == INVALID_HANDLE_VALUE)
2917296341Sdelphij        return -1;
2918296341Sdelphij    FindClose(hList);
2919296341Sdelphij    return ((FileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0);
2920296341Sdelphij}
2921238405Sjkim#else
2922296341Sdelphij# include <sys/stat.h>
2923296341Sdelphij# ifndef S_ISDIR
2924296341Sdelphij#  if defined(_S_IFMT) && defined(_S_IFDIR)
2925296341Sdelphij#   define S_ISDIR(a)   (((a) & _S_IFMT) == _S_IFDIR)
2926296341Sdelphij#  else
2927296341Sdelphij#   define S_ISDIR(a)   (((a) & S_IFMT) == S_IFDIR)
2928296341Sdelphij#  endif
2929296341Sdelphij# endif
2930238405Sjkim
2931238405Sjkimint app_isdir(const char *name)
2932296341Sdelphij{
2933296341Sdelphij# if defined(S_ISDIR)
2934296341Sdelphij    struct stat st;
2935238405Sjkim
2936296341Sdelphij    if (stat(name, &st) == 0)
2937296341Sdelphij        return S_ISDIR(st.st_mode);
2938296341Sdelphij    else
2939296341Sdelphij        return -1;
2940296341Sdelphij# else
2941296341Sdelphij    return -1;
2942296341Sdelphij# endif
2943296341Sdelphij}
2944238405Sjkim#endif
2945238405Sjkim
2946238405Sjkim/* raw_read|write section */
2947238405Sjkim#if defined(_WIN32) && defined(STD_INPUT_HANDLE)
2948296341Sdelphijint raw_read_stdin(void *buf, int siz)
2949296341Sdelphij{
2950296341Sdelphij    DWORD n;
2951296341Sdelphij    if (ReadFile(GetStdHandle(STD_INPUT_HANDLE), buf, siz, &n, NULL))
2952296341Sdelphij        return (n);
2953296341Sdelphij    else
2954296341Sdelphij        return (-1);
2955296341Sdelphij}
2956238405Sjkim#else
2957296341Sdelphijint raw_read_stdin(void *buf, int siz)
2958296341Sdelphij{
2959296341Sdelphij    return read(fileno(stdin), buf, siz);
2960296341Sdelphij}
2961238405Sjkim#endif
2962238405Sjkim
2963238405Sjkim#if defined(_WIN32) && defined(STD_OUTPUT_HANDLE)
2964296341Sdelphijint raw_write_stdout(const void *buf, int siz)
2965296341Sdelphij{
2966296341Sdelphij    DWORD n;
2967296341Sdelphij    if (WriteFile(GetStdHandle(STD_OUTPUT_HANDLE), buf, siz, &n, NULL))
2968296341Sdelphij        return (n);
2969296341Sdelphij    else
2970296341Sdelphij        return (-1);
2971296341Sdelphij}
2972238405Sjkim#else
2973296341Sdelphijint raw_write_stdout(const void *buf, int siz)
2974296341Sdelphij{
2975296341Sdelphij    return write(fileno(stdout), buf, siz);
2976296341Sdelphij}
2977238405Sjkim#endif
2978