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.
8296465Sdelphij *
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).
15296465Sdelphij *
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.
22296465Sdelphij *
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 :-).
37296465Sdelphij * 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)"
40296465Sdelphij *
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.
52296465Sdelphij *
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
66296465Sdelphij *    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
11255714Skris#include <stdio.h>
11355714Skris#include <stdlib.h>
11455714Skris#include <string.h>
11555714Skris#include <sys/types.h>
11655714Skris#include <sys/stat.h>
117109998Smarkm#include <ctype.h>
118194206Ssimon#include <assert.h>
11968651Skris#include <openssl/err.h>
12068651Skris#include <openssl/x509.h>
121109998Smarkm#include <openssl/x509v3.h>
12268651Skris#include <openssl/pem.h>
12368651Skris#include <openssl/pkcs12.h>
124109998Smarkm#include <openssl/ui.h>
12568651Skris#include <openssl/safestack.h>
126111147Snectar#ifndef OPENSSL_NO_ENGINE
127296465Sdelphij# include <openssl/engine.h>
128111147Snectar#endif
129160814Ssimon#ifndef OPENSSL_NO_RSA
130296465Sdelphij# include <openssl/rsa.h>
131160814Ssimon#endif
132160814Ssimon#include <openssl/bn.h>
133194206Ssimon#ifndef OPENSSL_NO_JPAKE
134296465Sdelphij# include <openssl/jpake.h>
135194206Ssimon#endif
13655714Skris
137109998Smarkm#define NON_MAIN
138109998Smarkm#include "apps.h"
139109998Smarkm#undef NON_MAIN
140109998Smarkm
141109998Smarkmtypedef struct {
142296465Sdelphij    const char *name;
143296465Sdelphij    unsigned long flag;
144296465Sdelphij    unsigned long mask;
145109998Smarkm} NAME_EX_TBL;
146109998Smarkm
147109998Smarkmstatic UI_METHOD *ui_method = NULL;
148109998Smarkm
149296465Sdelphijstatic int set_table_opts(unsigned long *flags, const char *arg,
150296465Sdelphij                          const NAME_EX_TBL * in_tbl);
151296465Sdelphijstatic int set_multi_opts(unsigned long *flags, const char *arg,
152296465Sdelphij                          const NAME_EX_TBL * in_tbl);
153109998Smarkm
154109998Smarkm#if !defined(OPENSSL_NO_RC4) && !defined(OPENSSL_NO_RSA)
155109998Smarkm/* Looks like this stuff is worth moving into separate function */
156296465Sdelphijstatic EVP_PKEY *load_netscape_key(BIO *err, BIO *key, const char *file,
157296465Sdelphij                                   const char *key_descrip, int format);
158109998Smarkm#endif
159109998Smarkm
16055714Skrisint app_init(long mesgwin);
161296465Sdelphij#ifdef undef                    /* never finished - probably never will be
162296465Sdelphij                                 * :-) */
16355714Skrisint args_from_file(char *file, int *argc, char **argv[])
164296465Sdelphij{
165296465Sdelphij    FILE *fp;
166296465Sdelphij    int num, i;
167296465Sdelphij    unsigned int len;
168296465Sdelphij    static char *buf = NULL;
169296465Sdelphij    static char **arg = NULL;
170296465Sdelphij    char *p;
171296465Sdelphij    struct stat stbuf;
17255714Skris
173296465Sdelphij    if (stat(file, &stbuf) < 0)
174296465Sdelphij        return (0);
17555714Skris
176296465Sdelphij    fp = fopen(file, "r");
177296465Sdelphij    if (fp == NULL)
178296465Sdelphij        return (0);
17955714Skris
180296465Sdelphij    *argc = 0;
181296465Sdelphij    *argv = NULL;
18255714Skris
183296465Sdelphij    len = (unsigned int)stbuf.st_size;
184296465Sdelphij    if (buf != NULL)
185296465Sdelphij        OPENSSL_free(buf);
186296465Sdelphij    buf = (char *)OPENSSL_malloc(len + 1);
187296465Sdelphij    if (buf == NULL)
188296465Sdelphij        return (0);
18955714Skris
190296465Sdelphij    len = fread(buf, 1, len, fp);
191296465Sdelphij    if (len <= 1)
192296465Sdelphij        return (0);
193296465Sdelphij    buf[len] = '\0';
19455714Skris
195296465Sdelphij    i = 0;
196296465Sdelphij    for (p = buf; *p; p++)
197296465Sdelphij        if (*p == '\n')
198296465Sdelphij            i++;
199296465Sdelphij    if (arg != NULL)
200296465Sdelphij        OPENSSL_free(arg);
201296465Sdelphij    arg = (char **)OPENSSL_malloc(sizeof(char *) * (i * 2));
20255714Skris
203296465Sdelphij    *argv = arg;
204296465Sdelphij    num = 0;
205296465Sdelphij    p = buf;
206296465Sdelphij    for (;;) {
207296465Sdelphij        if (!*p)
208296465Sdelphij            break;
209296465Sdelphij        if (*p == '#') {        /* comment line */
210296465Sdelphij            while (*p && (*p != '\n'))
211296465Sdelphij                p++;
212296465Sdelphij            continue;
213296465Sdelphij        }
214296465Sdelphij        /* else we have a line */
215296465Sdelphij        *(arg++) = p;
216296465Sdelphij        num++;
217296465Sdelphij        while (*p && ((*p != ' ') && (*p != '\t') && (*p != '\n')))
218296465Sdelphij            p++;
219296465Sdelphij        if (!*p)
220296465Sdelphij            break;
221296465Sdelphij        if (*p == '\n') {
222296465Sdelphij            *(p++) = '\0';
223296465Sdelphij            continue;
224296465Sdelphij        }
225296465Sdelphij        /* else it is a tab or space */
226296465Sdelphij        p++;
227296465Sdelphij        while (*p && ((*p == ' ') || (*p == '\t') || (*p == '\n')))
228296465Sdelphij            p++;
229296465Sdelphij        if (!*p)
230296465Sdelphij            break;
231296465Sdelphij        if (*p == '\n') {
232296465Sdelphij            p++;
233296465Sdelphij            continue;
234296465Sdelphij        }
235296465Sdelphij        *(arg++) = p++;
236296465Sdelphij        num++;
237296465Sdelphij        while (*p && (*p != '\n'))
238296465Sdelphij            p++;
239296465Sdelphij        if (!*p)
240296465Sdelphij            break;
241296465Sdelphij        /* else *p == '\n' */
242296465Sdelphij        *(p++) = '\0';
243296465Sdelphij    }
244296465Sdelphij    *argc = num;
245296465Sdelphij    return (1);
246296465Sdelphij}
24755714Skris#endif
24855714Skris
24955714Skrisint str2fmt(char *s)
250296465Sdelphij{
251296465Sdelphij    if ((*s == 'D') || (*s == 'd'))
252296465Sdelphij        return (FORMAT_ASN1);
253296465Sdelphij    else if ((*s == 'T') || (*s == 't'))
254296465Sdelphij        return (FORMAT_TEXT);
255296465Sdelphij    else if ((*s == 'P') || (*s == 'p'))
256296465Sdelphij        return (FORMAT_PEM);
257296465Sdelphij    else if ((*s == 'N') || (*s == 'n'))
258296465Sdelphij        return (FORMAT_NETSCAPE);
259296465Sdelphij    else if ((*s == 'S') || (*s == 's'))
260296465Sdelphij        return (FORMAT_SMIME);
261296465Sdelphij    else if ((*s == '1')
262296465Sdelphij             || (strcmp(s, "PKCS12") == 0) || (strcmp(s, "pkcs12") == 0)
263296465Sdelphij             || (strcmp(s, "P12") == 0) || (strcmp(s, "p12") == 0))
264296465Sdelphij        return (FORMAT_PKCS12);
265296465Sdelphij    else if ((*s == 'E') || (*s == 'e'))
266296465Sdelphij        return (FORMAT_ENGINE);
267296465Sdelphij    else
268296465Sdelphij        return (FORMAT_UNDEF);
269296465Sdelphij}
27055714Skris
271160814Ssimon#if defined(OPENSSL_SYS_MSDOS) || defined(OPENSSL_SYS_WIN32) || defined(OPENSSL_SYS_WIN16) || defined(OPENSSL_SYS_NETWARE)
27255714Skrisvoid program_name(char *in, char *out, int size)
273296465Sdelphij{
274296465Sdelphij    int i, n;
275296465Sdelphij    char *p = NULL;
27655714Skris
277296465Sdelphij    n = strlen(in);
278296465Sdelphij    /* find the last '/', '\' or ':' */
279296465Sdelphij    for (i = n - 1; i > 0; i--) {
280296465Sdelphij        if ((in[i] == '/') || (in[i] == '\\') || (in[i] == ':')) {
281296465Sdelphij            p = &(in[i + 1]);
282296465Sdelphij            break;
283296465Sdelphij        }
284296465Sdelphij    }
285296465Sdelphij    if (p == NULL)
286296465Sdelphij        p = in;
287296465Sdelphij    n = strlen(p);
288160814Ssimon
289296465Sdelphij# if defined(OPENSSL_SYS_NETWARE)
290296465Sdelphij    /* strip off trailing .nlm if present. */
291296465Sdelphij    if ((n > 4) && (p[n - 4] == '.') &&
292296465Sdelphij        ((p[n - 3] == 'n') || (p[n - 3] == 'N')) &&
293296465Sdelphij        ((p[n - 2] == 'l') || (p[n - 2] == 'L')) &&
294296465Sdelphij        ((p[n - 1] == 'm') || (p[n - 1] == 'M')))
295296465Sdelphij        n -= 4;
296296465Sdelphij# else
297296465Sdelphij    /* strip off trailing .exe if present. */
298296465Sdelphij    if ((n > 4) && (p[n - 4] == '.') &&
299296465Sdelphij        ((p[n - 3] == 'e') || (p[n - 3] == 'E')) &&
300296465Sdelphij        ((p[n - 2] == 'x') || (p[n - 2] == 'X')) &&
301296465Sdelphij        ((p[n - 1] == 'e') || (p[n - 1] == 'E')))
302296465Sdelphij        n -= 4;
303296465Sdelphij# endif
304160814Ssimon
305296465Sdelphij    if (n > size - 1)
306296465Sdelphij        n = size - 1;
30755714Skris
308296465Sdelphij    for (i = 0; i < n; i++) {
309296465Sdelphij        if ((p[i] >= 'A') && (p[i] <= 'Z'))
310296465Sdelphij            out[i] = p[i] - 'A' + 'a';
311296465Sdelphij        else
312296465Sdelphij            out[i] = p[i];
313296465Sdelphij    }
314296465Sdelphij    out[n] = '\0';
315296465Sdelphij}
31655714Skris#else
317296465Sdelphij# ifdef OPENSSL_SYS_VMS
31855714Skrisvoid program_name(char *in, char *out, int size)
319296465Sdelphij{
320296465Sdelphij    char *p = in, *q;
321296465Sdelphij    char *chars = ":]>";
32255714Skris
323296465Sdelphij    while (*chars != '\0') {
324296465Sdelphij        q = strrchr(p, *chars);
325296465Sdelphij        if (q > p)
326296465Sdelphij            p = q + 1;
327296465Sdelphij        chars++;
328296465Sdelphij    }
32955714Skris
330296465Sdelphij    q = strrchr(p, '.');
331296465Sdelphij    if (q == NULL)
332296465Sdelphij        q = p + strlen(p);
333296465Sdelphij    strncpy(out, p, size - 1);
334296465Sdelphij    if (q - p >= size) {
335296465Sdelphij        out[size - 1] = '\0';
336296465Sdelphij    } else {
337296465Sdelphij        out[q - p] = '\0';
338296465Sdelphij    }
339296465Sdelphij}
340296465Sdelphij# else
34155714Skrisvoid program_name(char *in, char *out, int size)
342296465Sdelphij{
343296465Sdelphij    char *p;
34455714Skris
345296465Sdelphij    p = strrchr(in, '/');
346296465Sdelphij    if (p != NULL)
347296465Sdelphij        p++;
348296465Sdelphij    else
349296465Sdelphij        p = in;
350296465Sdelphij    BUF_strlcpy(out, p, size);
351296465Sdelphij}
352296465Sdelphij# endif
35355714Skris#endif
35455714Skris
35555714Skrisint chopup_args(ARGS *arg, char *buf, int *argc, char **argv[])
356296465Sdelphij{
357296465Sdelphij    int num, i;
358296465Sdelphij    char *p;
35955714Skris
360296465Sdelphij    *argc = 0;
361296465Sdelphij    *argv = NULL;
36255714Skris
363296465Sdelphij    i = 0;
364296465Sdelphij    if (arg->count == 0) {
365296465Sdelphij        arg->count = 20;
366296465Sdelphij        arg->data = (char **)OPENSSL_malloc(sizeof(char *) * arg->count);
367296465Sdelphij        if (arg->data == NULL)
368296465Sdelphij            return 0;
369296465Sdelphij    }
370296465Sdelphij    for (i = 0; i < arg->count; i++)
371296465Sdelphij        arg->data[i] = NULL;
37255714Skris
373296465Sdelphij    num = 0;
374296465Sdelphij    p = buf;
375296465Sdelphij    for (;;) {
376296465Sdelphij        /* first scan over white space */
377296465Sdelphij        if (!*p)
378296465Sdelphij            break;
379296465Sdelphij        while (*p && ((*p == ' ') || (*p == '\t') || (*p == '\n')))
380296465Sdelphij            p++;
381296465Sdelphij        if (!*p)
382296465Sdelphij            break;
38355714Skris
384296465Sdelphij        /* The start of something good :-) */
385296465Sdelphij        if (num >= arg->count) {
386296465Sdelphij            char **tmp_p;
387296465Sdelphij            int tlen = arg->count + 20;
388296465Sdelphij            tmp_p = (char **)OPENSSL_realloc(arg->data,
389296465Sdelphij                                             sizeof(char *) * tlen);
390296465Sdelphij            if (tmp_p == NULL)
391296465Sdelphij                return 0;
392296465Sdelphij            arg->data = tmp_p;
393296465Sdelphij            arg->count = tlen;
394296465Sdelphij            /* initialize newly allocated data */
395296465Sdelphij            for (i = num; i < arg->count; i++)
396296465Sdelphij                arg->data[i] = NULL;
397296465Sdelphij        }
398296465Sdelphij        arg->data[num++] = p;
39955714Skris
400296465Sdelphij        /* now look for the end of this */
401296465Sdelphij        if ((*p == '\'') || (*p == '\"')) { /* scan for closing quote */
402296465Sdelphij            i = *(p++);
403296465Sdelphij            arg->data[num - 1]++; /* jump over quote */
404296465Sdelphij            while (*p && (*p != i))
405296465Sdelphij                p++;
406296465Sdelphij            *p = '\0';
407296465Sdelphij        } else {
408296465Sdelphij            while (*p && ((*p != ' ') && (*p != '\t') && (*p != '\n')))
409296465Sdelphij                p++;
41055714Skris
411296465Sdelphij            if (*p == '\0')
412296465Sdelphij                p--;
413296465Sdelphij            else
414296465Sdelphij                *p = '\0';
415296465Sdelphij        }
416296465Sdelphij        p++;
417296465Sdelphij    }
418296465Sdelphij    *argc = num;
419296465Sdelphij    *argv = arg->data;
420296465Sdelphij    return (1);
421296465Sdelphij}
42255714Skris
42355714Skris#ifndef APP_INIT
42455714Skrisint app_init(long mesgwin)
425296465Sdelphij{
426296465Sdelphij    return (1);
427296465Sdelphij}
42855714Skris#endif
42959191Skris
430296465Sdelphijint dump_cert_text(BIO *out, X509 *x)
43159191Skris{
432296465Sdelphij    char *p;
433109998Smarkm
434296465Sdelphij    p = X509_NAME_oneline(X509_get_subject_name(x), NULL, 0);
435296465Sdelphij    BIO_puts(out, "subject=");
436296465Sdelphij    BIO_puts(out, p);
437296465Sdelphij    OPENSSL_free(p);
43859191Skris
439296465Sdelphij    p = X509_NAME_oneline(X509_get_issuer_name(x), NULL, 0);
440296465Sdelphij    BIO_puts(out, "\nissuer=");
441296465Sdelphij    BIO_puts(out, p);
442296465Sdelphij    BIO_puts(out, "\n");
443296465Sdelphij    OPENSSL_free(p);
444109998Smarkm
445296465Sdelphij    return 0;
44659191Skris}
44759191Skris
448109998Smarkmstatic int ui_open(UI *ui)
449296465Sdelphij{
450296465Sdelphij    return UI_method_get_opener(UI_OpenSSL())(ui);
451296465Sdelphij}
452296465Sdelphij
453109998Smarkmstatic int ui_read(UI *ui, UI_STRING *uis)
454296465Sdelphij{
455296465Sdelphij    if (UI_get_input_flags(uis) & UI_INPUT_FLAG_DEFAULT_PWD
456296465Sdelphij        && UI_get0_user_data(ui)) {
457296465Sdelphij        switch (UI_get_string_type(uis)) {
458296465Sdelphij        case UIT_PROMPT:
459296465Sdelphij        case UIT_VERIFY:
460296465Sdelphij            {
461296465Sdelphij                const char *password =
462296465Sdelphij                    ((PW_CB_DATA *)UI_get0_user_data(ui))->password;
463296465Sdelphij                if (password && password[0] != '\0') {
464296465Sdelphij                    UI_set_result(ui, uis, password);
465296465Sdelphij                    return 1;
466296465Sdelphij                }
467296465Sdelphij            }
468296465Sdelphij        default:
469296465Sdelphij            break;
470296465Sdelphij        }
471296465Sdelphij    }
472296465Sdelphij    return UI_method_get_reader(UI_OpenSSL())(ui, uis);
473296465Sdelphij}
474296465Sdelphij
475109998Smarkmstatic int ui_write(UI *ui, UI_STRING *uis)
476296465Sdelphij{
477296465Sdelphij    if (UI_get_input_flags(uis) & UI_INPUT_FLAG_DEFAULT_PWD
478296465Sdelphij        && UI_get0_user_data(ui)) {
479296465Sdelphij        switch (UI_get_string_type(uis)) {
480296465Sdelphij        case UIT_PROMPT:
481296465Sdelphij        case UIT_VERIFY:
482296465Sdelphij            {
483296465Sdelphij                const char *password =
484296465Sdelphij                    ((PW_CB_DATA *)UI_get0_user_data(ui))->password;
485296465Sdelphij                if (password && password[0] != '\0')
486296465Sdelphij                    return 1;
487296465Sdelphij            }
488296465Sdelphij        default:
489296465Sdelphij            break;
490296465Sdelphij        }
491296465Sdelphij    }
492296465Sdelphij    return UI_method_get_writer(UI_OpenSSL())(ui, uis);
493296465Sdelphij}
494296465Sdelphij
495109998Smarkmstatic int ui_close(UI *ui)
496296465Sdelphij{
497296465Sdelphij    return UI_method_get_closer(UI_OpenSSL())(ui);
498296465Sdelphij}
499296465Sdelphij
500109998Smarkmint setup_ui_method(void)
501296465Sdelphij{
502296465Sdelphij    ui_method = UI_create_method("OpenSSL application user interface");
503296465Sdelphij    UI_method_set_opener(ui_method, ui_open);
504296465Sdelphij    UI_method_set_reader(ui_method, ui_read);
505296465Sdelphij    UI_method_set_writer(ui_method, ui_write);
506296465Sdelphij    UI_method_set_closer(ui_method, ui_close);
507296465Sdelphij    return 0;
508296465Sdelphij}
509296465Sdelphij
510109998Smarkmvoid destroy_ui_method(void)
511296465Sdelphij{
512296465Sdelphij    if (ui_method) {
513296465Sdelphij        UI_destroy_method(ui_method);
514296465Sdelphij        ui_method = NULL;
515296465Sdelphij    }
516296465Sdelphij}
517109998Smarkm
518296465Sdelphijint password_callback(char *buf, int bufsiz, int verify, PW_CB_DATA *cb_tmp)
519296465Sdelphij{
520296465Sdelphij    UI *ui = NULL;
521296465Sdelphij    int res = 0;
522296465Sdelphij    const char *prompt_info = NULL;
523296465Sdelphij    const char *password = NULL;
524296465Sdelphij    PW_CB_DATA *cb_data = (PW_CB_DATA *)cb_tmp;
525109998Smarkm
526296465Sdelphij    if (cb_data) {
527296465Sdelphij        if (cb_data->password)
528296465Sdelphij            password = cb_data->password;
529296465Sdelphij        if (cb_data->prompt_info)
530296465Sdelphij            prompt_info = cb_data->prompt_info;
531296465Sdelphij    }
532109998Smarkm
533296465Sdelphij    if (password) {
534296465Sdelphij        res = strlen(password);
535296465Sdelphij        if (res > bufsiz)
536296465Sdelphij            res = bufsiz;
537296465Sdelphij        memcpy(buf, password, res);
538296465Sdelphij        return res;
539296465Sdelphij    }
540109998Smarkm
541296465Sdelphij    ui = UI_new_method(ui_method);
542296465Sdelphij    if (ui) {
543296465Sdelphij        int ok = 0;
544296465Sdelphij        char *buff = NULL;
545296465Sdelphij        int ui_flags = 0;
546296465Sdelphij        char *prompt = NULL;
547109998Smarkm
548296465Sdelphij        prompt = UI_construct_prompt(ui, "pass phrase", prompt_info);
549109998Smarkm
550296465Sdelphij        ui_flags |= UI_INPUT_FLAG_DEFAULT_PWD;
551296465Sdelphij        UI_ctrl(ui, UI_CTRL_PRINT_ERRORS, 1, 0, 0);
552109998Smarkm
553296465Sdelphij        if (ok >= 0)
554296465Sdelphij            ok = UI_add_input_string(ui, prompt, ui_flags, buf,
555296465Sdelphij                                     PW_MIN_LENGTH, bufsiz - 1);
556296465Sdelphij        if (ok >= 0 && verify) {
557296465Sdelphij            buff = (char *)OPENSSL_malloc(bufsiz);
558296465Sdelphij            ok = UI_add_verify_string(ui, prompt, ui_flags, buff,
559296465Sdelphij                                      PW_MIN_LENGTH, bufsiz - 1, buf);
560296465Sdelphij        }
561296465Sdelphij        if (ok >= 0)
562296465Sdelphij            do {
563296465Sdelphij                ok = UI_process(ui);
564296465Sdelphij            }
565296465Sdelphij            while (ok < 0 && UI_ctrl(ui, UI_CTRL_IS_REDOABLE, 0, 0, 0));
566109998Smarkm
567296465Sdelphij        if (buff) {
568296465Sdelphij            OPENSSL_cleanse(buff, (unsigned int)bufsiz);
569296465Sdelphij            OPENSSL_free(buff);
570296465Sdelphij        }
571109998Smarkm
572296465Sdelphij        if (ok >= 0)
573296465Sdelphij            res = strlen(buf);
574296465Sdelphij        if (ok == -1) {
575296465Sdelphij            BIO_printf(bio_err, "User interface error\n");
576296465Sdelphij            ERR_print_errors(bio_err);
577296465Sdelphij            OPENSSL_cleanse(buf, (unsigned int)bufsiz);
578296465Sdelphij            res = 0;
579296465Sdelphij        }
580296465Sdelphij        if (ok == -2) {
581296465Sdelphij            BIO_printf(bio_err, "aborted!\n");
582296465Sdelphij            OPENSSL_cleanse(buf, (unsigned int)bufsiz);
583296465Sdelphij            res = 0;
584296465Sdelphij        }
585296465Sdelphij        UI_free(ui);
586296465Sdelphij        OPENSSL_free(prompt);
587296465Sdelphij    }
588296465Sdelphij    return res;
589296465Sdelphij}
590296465Sdelphij
59159191Skrisstatic char *app_get_pass(BIO *err, char *arg, int keepbio);
59259191Skris
59359191Skrisint app_passwd(BIO *err, char *arg1, char *arg2, char **pass1, char **pass2)
59459191Skris{
595296465Sdelphij    int same;
596296465Sdelphij    if (!arg2 || !arg1 || strcmp(arg1, arg2))
597296465Sdelphij        same = 0;
598296465Sdelphij    else
599296465Sdelphij        same = 1;
600296465Sdelphij    if (arg1) {
601296465Sdelphij        *pass1 = app_get_pass(err, arg1, same);
602296465Sdelphij        if (!*pass1)
603296465Sdelphij            return 0;
604296465Sdelphij    } else if (pass1)
605296465Sdelphij        *pass1 = NULL;
606296465Sdelphij    if (arg2) {
607296465Sdelphij        *pass2 = app_get_pass(err, arg2, same ? 2 : 0);
608296465Sdelphij        if (!*pass2)
609296465Sdelphij            return 0;
610296465Sdelphij    } else if (pass2)
611296465Sdelphij        *pass2 = NULL;
612296465Sdelphij    return 1;
61359191Skris}
61459191Skris
61559191Skrisstatic char *app_get_pass(BIO *err, char *arg, int keepbio)
61659191Skris{
617296465Sdelphij    char *tmp, tpass[APP_PASS_LEN];
618296465Sdelphij    static BIO *pwdbio = NULL;
619296465Sdelphij    int i;
620296465Sdelphij    if (!strncmp(arg, "pass:", 5))
621296465Sdelphij        return BUF_strdup(arg + 5);
622296465Sdelphij    if (!strncmp(arg, "env:", 4)) {
623296465Sdelphij        tmp = getenv(arg + 4);
624296465Sdelphij        if (!tmp) {
625296465Sdelphij            BIO_printf(err, "Can't read environment variable %s\n", arg + 4);
626296465Sdelphij            return NULL;
627296465Sdelphij        }
628296465Sdelphij        return BUF_strdup(tmp);
629296465Sdelphij    }
630296465Sdelphij    if (!keepbio || !pwdbio) {
631296465Sdelphij        if (!strncmp(arg, "file:", 5)) {
632296465Sdelphij            pwdbio = BIO_new_file(arg + 5, "r");
633296465Sdelphij            if (!pwdbio) {
634296465Sdelphij                BIO_printf(err, "Can't open file %s\n", arg + 5);
635296465Sdelphij                return NULL;
636296465Sdelphij            }
637296465Sdelphij        } else if (!strncmp(arg, "fd:", 3)) {
638296465Sdelphij            BIO *btmp;
639296465Sdelphij            i = atoi(arg + 3);
640296465Sdelphij            if (i >= 0)
641296465Sdelphij                pwdbio = BIO_new_fd(i, BIO_NOCLOSE);
642296465Sdelphij            if ((i < 0) || !pwdbio) {
643296465Sdelphij                BIO_printf(err, "Can't access file descriptor %s\n", arg + 3);
644296465Sdelphij                return NULL;
645296465Sdelphij            }
646296465Sdelphij            /*
647296465Sdelphij             * Can't do BIO_gets on an fd BIO so add a buffering BIO
648296465Sdelphij             */
649296465Sdelphij            btmp = BIO_new(BIO_f_buffer());
650296465Sdelphij            pwdbio = BIO_push(btmp, pwdbio);
651296465Sdelphij        } else if (!strcmp(arg, "stdin")) {
652296465Sdelphij            pwdbio = BIO_new_fp(stdin, BIO_NOCLOSE);
653296465Sdelphij            if (!pwdbio) {
654296465Sdelphij                BIO_printf(err, "Can't open BIO for stdin\n");
655296465Sdelphij                return NULL;
656296465Sdelphij            }
657296465Sdelphij        } else {
658296465Sdelphij            BIO_printf(err, "Invalid password argument \"%s\"\n", arg);
659296465Sdelphij            return NULL;
660296465Sdelphij        }
661296465Sdelphij    }
662296465Sdelphij    i = BIO_gets(pwdbio, tpass, APP_PASS_LEN);
663296465Sdelphij    if (keepbio != 1) {
664296465Sdelphij        BIO_free_all(pwdbio);
665296465Sdelphij        pwdbio = NULL;
666296465Sdelphij    }
667296465Sdelphij    if (i <= 0) {
668296465Sdelphij        BIO_printf(err, "Error reading password from BIO\n");
669296465Sdelphij        return NULL;
670296465Sdelphij    }
671296465Sdelphij    tmp = strchr(tpass, '\n');
672296465Sdelphij    if (tmp)
673296465Sdelphij        *tmp = 0;
674296465Sdelphij    return BUF_strdup(tpass);
67559191Skris}
67668651Skris
677109998Smarkmint add_oid_section(BIO *err, CONF *conf)
678296465Sdelphij{
679296465Sdelphij    char *p;
680296465Sdelphij    STACK_OF(CONF_VALUE) *sktmp;
681296465Sdelphij    CONF_VALUE *cnf;
682296465Sdelphij    int i;
683296465Sdelphij    if (!(p = NCONF_get_string(conf, NULL, "oid_section"))) {
684296465Sdelphij        ERR_clear_error();
685296465Sdelphij        return 1;
686296465Sdelphij    }
687296465Sdelphij    if (!(sktmp = NCONF_get_section(conf, p))) {
688296465Sdelphij        BIO_printf(err, "problem loading oid section %s\n", p);
689296465Sdelphij        return 0;
690296465Sdelphij    }
691296465Sdelphij    for (i = 0; i < sk_CONF_VALUE_num(sktmp); i++) {
692296465Sdelphij        cnf = sk_CONF_VALUE_value(sktmp, i);
693296465Sdelphij        if (OBJ_create(cnf->value, cnf->name, cnf->name) == NID_undef) {
694296465Sdelphij            BIO_printf(err, "problem creating object %s=%s\n",
695296465Sdelphij                       cnf->name, cnf->value);
696296465Sdelphij            return 0;
697296465Sdelphij        }
698296465Sdelphij    }
699296465Sdelphij    return 1;
70068651Skris}
70168651Skris
702160814Ssimonstatic int load_pkcs12(BIO *err, BIO *in, const char *desc,
703296465Sdelphij                       pem_password_cb *pem_cb, void *cb_data,
704296465Sdelphij                       EVP_PKEY **pkey, X509 **cert, STACK_OF(X509) **ca)
705296465Sdelphij{
706296465Sdelphij    const char *pass;
707296465Sdelphij    char tpass[PEM_BUFSIZE];
708296465Sdelphij    int len, ret = 0;
709296465Sdelphij    PKCS12 *p12;
710296465Sdelphij    p12 = d2i_PKCS12_bio(in, NULL);
711296465Sdelphij    if (p12 == NULL) {
712296465Sdelphij        BIO_printf(err, "Error loading PKCS12 file for %s\n", desc);
713296465Sdelphij        goto die;
714296465Sdelphij    }
715296465Sdelphij    /* See if an empty password will do */
716296465Sdelphij    if (PKCS12_verify_mac(p12, "", 0) || PKCS12_verify_mac(p12, NULL, 0))
717296465Sdelphij        pass = "";
718296465Sdelphij    else {
719296465Sdelphij        if (!pem_cb)
720296465Sdelphij            pem_cb = (pem_password_cb *)password_callback;
721296465Sdelphij        len = pem_cb(tpass, PEM_BUFSIZE, 0, cb_data);
722296465Sdelphij        if (len < 0) {
723296465Sdelphij            BIO_printf(err, "Passpharse callback error for %s\n", desc);
724296465Sdelphij            goto die;
725296465Sdelphij        }
726296465Sdelphij        if (len < PEM_BUFSIZE)
727296465Sdelphij            tpass[len] = 0;
728296465Sdelphij        if (!PKCS12_verify_mac(p12, tpass, len)) {
729296465Sdelphij            BIO_printf(err,
730296465Sdelphij                       "Mac verify error (wrong password?) in PKCS12 file for %s\n",
731296465Sdelphij                       desc);
732296465Sdelphij            goto die;
733296465Sdelphij        }
734296465Sdelphij        pass = tpass;
735296465Sdelphij    }
736296465Sdelphij    ret = PKCS12_parse(p12, pass, pkey, cert, ca);
737296465Sdelphij die:
738296465Sdelphij    if (p12)
739296465Sdelphij        PKCS12_free(p12);
740296465Sdelphij    return ret;
741296465Sdelphij}
742160814Ssimon
743109998SmarkmX509 *load_cert(BIO *err, const char *file, int format,
744296465Sdelphij                const char *pass, ENGINE *e, const char *cert_descrip)
745296465Sdelphij{
746296465Sdelphij    ASN1_HEADER *ah = NULL;
747296465Sdelphij    BUF_MEM *buf = NULL;
748296465Sdelphij    X509 *x = NULL;
749296465Sdelphij    BIO *cert;
75068651Skris
751296465Sdelphij    if ((cert = BIO_new(BIO_s_file())) == NULL) {
752296465Sdelphij        ERR_print_errors(err);
753296465Sdelphij        goto end;
754296465Sdelphij    }
75568651Skris
756296465Sdelphij    if (file == NULL) {
757296465Sdelphij        setvbuf(stdin, NULL, _IONBF, 0);
758296465Sdelphij        BIO_set_fp(cert, stdin, BIO_NOCLOSE);
759296465Sdelphij    } else {
760296465Sdelphij        if (BIO_read_filename(cert, file) <= 0) {
761296465Sdelphij            BIO_printf(err, "Error opening %s %s\n", cert_descrip, file);
762296465Sdelphij            ERR_print_errors(err);
763296465Sdelphij            goto end;
764296465Sdelphij        }
765296465Sdelphij    }
76668651Skris
767296465Sdelphij    if (format == FORMAT_ASN1)
768296465Sdelphij        x = d2i_X509_bio(cert, NULL);
769296465Sdelphij    else if (format == FORMAT_NETSCAPE) {
770296465Sdelphij        const unsigned char *p, *op;
771296465Sdelphij        int size = 0, i;
77268651Skris
773296465Sdelphij        /*
774296465Sdelphij         * We sort of have to do it this way because it is sort of nice to
775296465Sdelphij         * read the header first and check it, then try to read the
776296465Sdelphij         * certificate
777296465Sdelphij         */
778296465Sdelphij        buf = BUF_MEM_new();
779296465Sdelphij        for (;;) {
780296465Sdelphij            if ((buf == NULL) || (!BUF_MEM_grow(buf, size + 1024 * 10)))
781296465Sdelphij                goto end;
782296465Sdelphij            i = BIO_read(cert, &(buf->data[size]), 1024 * 10);
783296465Sdelphij            size += i;
784296465Sdelphij            if (i == 0)
785296465Sdelphij                break;
786296465Sdelphij            if (i < 0) {
787296465Sdelphij                perror("reading certificate");
788296465Sdelphij                goto end;
789296465Sdelphij            }
790296465Sdelphij        }
791296465Sdelphij        p = (unsigned char *)buf->data;
792296465Sdelphij        op = p;
79368651Skris
794296465Sdelphij        /* First load the header */
795296465Sdelphij        if ((ah = d2i_ASN1_HEADER(NULL, &p, (long)size)) == NULL)
796296465Sdelphij            goto end;
797296465Sdelphij        if ((ah->header == NULL) || (ah->header->data == NULL) ||
798296465Sdelphij            (strncmp(NETSCAPE_CERT_HDR, (char *)ah->header->data,
799296465Sdelphij                     ah->header->length) != 0)) {
800296465Sdelphij            BIO_printf(err, "Error reading header on certificate\n");
801296465Sdelphij            goto end;
802296465Sdelphij        }
803296465Sdelphij        /* header is ok, so now read the object */
804296465Sdelphij        p = op;
805296465Sdelphij        ah->meth = X509_asn1_meth();
806296465Sdelphij        if ((ah = d2i_ASN1_HEADER(&ah, &p, (long)size)) == NULL)
807296465Sdelphij            goto end;
808296465Sdelphij        x = (X509 *)ah->data;
809296465Sdelphij        ah->data = NULL;
810296465Sdelphij    } else if (format == FORMAT_PEM)
811296465Sdelphij        x = PEM_read_bio_X509_AUX(cert, NULL,
812296465Sdelphij                                  (pem_password_cb *)password_callback, NULL);
813296465Sdelphij    else if (format == FORMAT_PKCS12) {
814296465Sdelphij        if (!load_pkcs12(err, cert, cert_descrip, NULL, NULL, NULL, &x, NULL))
815296465Sdelphij            goto end;
816296465Sdelphij    } else {
817296465Sdelphij        BIO_printf(err, "bad input format specified for %s\n", cert_descrip);
818296465Sdelphij        goto end;
819296465Sdelphij    }
820296465Sdelphij end:
821296465Sdelphij    if (x == NULL) {
822296465Sdelphij        BIO_printf(err, "unable to load certificate\n");
823296465Sdelphij        ERR_print_errors(err);
824296465Sdelphij    }
825296465Sdelphij    if (ah != NULL)
826296465Sdelphij        ASN1_HEADER_free(ah);
827296465Sdelphij    if (cert != NULL)
828296465Sdelphij        BIO_free(cert);
829296465Sdelphij    if (buf != NULL)
830296465Sdelphij        BUF_MEM_free(buf);
831296465Sdelphij    return (x);
832296465Sdelphij}
83368651Skris
834109998SmarkmEVP_PKEY *load_key(BIO *err, const char *file, int format, int maybe_stdin,
835296465Sdelphij                   const char *pass, ENGINE *e, const char *key_descrip)
836296465Sdelphij{
837296465Sdelphij    BIO *key = NULL;
838296465Sdelphij    EVP_PKEY *pkey = NULL;
839296465Sdelphij    PW_CB_DATA cb_data;
84068651Skris
841296465Sdelphij    cb_data.password = pass;
842296465Sdelphij    cb_data.prompt_info = file;
843109998Smarkm
844296465Sdelphij    if (file == NULL && (!maybe_stdin || format == FORMAT_ENGINE)) {
845296465Sdelphij        BIO_printf(err, "no keyfile specified\n");
846296465Sdelphij        goto end;
847296465Sdelphij    }
848111147Snectar#ifndef OPENSSL_NO_ENGINE
849296465Sdelphij    if (format == FORMAT_ENGINE) {
850296465Sdelphij        if (!e)
851296465Sdelphij            BIO_printf(err, "no engine specified\n");
852296465Sdelphij        else {
853296465Sdelphij            pkey = ENGINE_load_private_key(e, file, ui_method, &cb_data);
854296465Sdelphij            if (!pkey) {
855296465Sdelphij                BIO_printf(err, "cannot load %s from engine\n", key_descrip);
856296465Sdelphij                ERR_print_errors(err);
857296465Sdelphij            }
858296465Sdelphij        }
859296465Sdelphij        goto end;
860296465Sdelphij    }
861111147Snectar#endif
862296465Sdelphij    key = BIO_new(BIO_s_file());
863296465Sdelphij    if (key == NULL) {
864296465Sdelphij        ERR_print_errors(err);
865296465Sdelphij        goto end;
866296465Sdelphij    }
867296465Sdelphij    if (file == NULL && maybe_stdin) {
868296465Sdelphij        setvbuf(stdin, NULL, _IONBF, 0);
869296465Sdelphij        BIO_set_fp(key, stdin, BIO_NOCLOSE);
870296465Sdelphij    } else if (BIO_read_filename(key, file) <= 0) {
871296465Sdelphij        BIO_printf(err, "Error opening %s %s\n", key_descrip, file);
872296465Sdelphij        ERR_print_errors(err);
873296465Sdelphij        goto end;
874296465Sdelphij    }
875296465Sdelphij    if (format == FORMAT_ASN1) {
876296465Sdelphij        pkey = d2i_PrivateKey_bio(key, NULL);
877296465Sdelphij    } else if (format == FORMAT_PEM) {
878296465Sdelphij        pkey = PEM_read_bio_PrivateKey(key, NULL,
879296465Sdelphij                                       (pem_password_cb *)password_callback,
880296465Sdelphij                                       &cb_data);
881296465Sdelphij    }
882109998Smarkm#if !defined(OPENSSL_NO_RC4) && !defined(OPENSSL_NO_RSA)
883296465Sdelphij    else if (format == FORMAT_NETSCAPE || format == FORMAT_IISSGC)
884296465Sdelphij        pkey = load_netscape_key(err, key, file, key_descrip, format);
885109998Smarkm#endif
886296465Sdelphij    else if (format == FORMAT_PKCS12) {
887296465Sdelphij        if (!load_pkcs12(err, key, key_descrip,
888296465Sdelphij                         (pem_password_cb *)password_callback, &cb_data,
889296465Sdelphij                         &pkey, NULL, NULL))
890296465Sdelphij            goto end;
891296465Sdelphij    } else {
892296465Sdelphij        BIO_printf(err, "bad input format specified for key file\n");
893296465Sdelphij        goto end;
894296465Sdelphij    }
89568651Skris end:
896296465Sdelphij    if (key != NULL)
897296465Sdelphij        BIO_free(key);
898296465Sdelphij    if (pkey == NULL) {
899296465Sdelphij        BIO_printf(err, "unable to load %s\n", key_descrip);
900296465Sdelphij        ERR_print_errors(err);
901296465Sdelphij    }
902296465Sdelphij    return (pkey);
903296465Sdelphij}
90468651Skris
905109998SmarkmEVP_PKEY *load_pubkey(BIO *err, const char *file, int format, int maybe_stdin,
906296465Sdelphij                      const char *pass, ENGINE *e, const char *key_descrip)
907296465Sdelphij{
908296465Sdelphij    BIO *key = NULL;
909296465Sdelphij    EVP_PKEY *pkey = NULL;
910296465Sdelphij    PW_CB_DATA cb_data;
91168651Skris
912296465Sdelphij    cb_data.password = pass;
913296465Sdelphij    cb_data.prompt_info = file;
914109998Smarkm
915296465Sdelphij    if (file == NULL && (!maybe_stdin || format == FORMAT_ENGINE)) {
916296465Sdelphij        BIO_printf(err, "no keyfile specified\n");
917296465Sdelphij        goto end;
918296465Sdelphij    }
919111147Snectar#ifndef OPENSSL_NO_ENGINE
920296465Sdelphij    if (format == FORMAT_ENGINE) {
921296465Sdelphij        if (!e)
922296465Sdelphij            BIO_printf(bio_err, "no engine specified\n");
923296465Sdelphij        else
924296465Sdelphij            pkey = ENGINE_load_public_key(e, file, ui_method, &cb_data);
925296465Sdelphij        goto end;
926296465Sdelphij    }
927111147Snectar#endif
928296465Sdelphij    key = BIO_new(BIO_s_file());
929296465Sdelphij    if (key == NULL) {
930296465Sdelphij        ERR_print_errors(err);
931296465Sdelphij        goto end;
932296465Sdelphij    }
933296465Sdelphij    if (file == NULL && maybe_stdin) {
934296465Sdelphij        setvbuf(stdin, NULL, _IONBF, 0);
935296465Sdelphij        BIO_set_fp(key, stdin, BIO_NOCLOSE);
936296465Sdelphij    } else if (BIO_read_filename(key, file) <= 0) {
937296465Sdelphij        BIO_printf(err, "Error opening %s %s\n", key_descrip, file);
938296465Sdelphij        ERR_print_errors(err);
939296465Sdelphij        goto end;
940296465Sdelphij    }
941296465Sdelphij    if (format == FORMAT_ASN1) {
942296465Sdelphij        pkey = d2i_PUBKEY_bio(key, NULL);
943296465Sdelphij    } else if (format == FORMAT_PEM) {
944296465Sdelphij        pkey = PEM_read_bio_PUBKEY(key, NULL,
945296465Sdelphij                                   (pem_password_cb *)password_callback,
946296465Sdelphij                                   &cb_data);
947296465Sdelphij    }
948109998Smarkm#if !defined(OPENSSL_NO_RC4) && !defined(OPENSSL_NO_RSA)
949296465Sdelphij    else if (format == FORMAT_NETSCAPE || format == FORMAT_IISSGC)
950296465Sdelphij        pkey = load_netscape_key(err, key, file, key_descrip, format);
951109998Smarkm#endif
952296465Sdelphij    else {
953296465Sdelphij        BIO_printf(err, "bad input format specified for key file\n");
954296465Sdelphij        goto end;
955296465Sdelphij    }
95668651Skris end:
957296465Sdelphij    if (key != NULL)
958296465Sdelphij        BIO_free(key);
959296465Sdelphij    if (pkey == NULL)
960296465Sdelphij        BIO_printf(err, "unable to load %s\n", key_descrip);
961296465Sdelphij    return (pkey);
962296465Sdelphij}
96368651Skris
964109998Smarkm#if !defined(OPENSSL_NO_RC4) && !defined(OPENSSL_NO_RSA)
965296465Sdelphijstatic EVP_PKEY *load_netscape_key(BIO *err, BIO *key, const char *file,
966296465Sdelphij                                   const char *key_descrip, int format)
967296465Sdelphij{
968296465Sdelphij    EVP_PKEY *pkey;
969296465Sdelphij    BUF_MEM *buf;
970296465Sdelphij    RSA *rsa;
971296465Sdelphij    const unsigned char *p;
972296465Sdelphij    int size, i;
973109998Smarkm
974296465Sdelphij    buf = BUF_MEM_new();
975296465Sdelphij    pkey = EVP_PKEY_new();
976296465Sdelphij    size = 0;
977296465Sdelphij    if (buf == NULL || pkey == NULL)
978296465Sdelphij        goto error;
979296465Sdelphij    for (;;) {
980296465Sdelphij        if (!BUF_MEM_grow_clean(buf, size + 1024 * 10))
981296465Sdelphij            goto error;
982296465Sdelphij        i = BIO_read(key, &(buf->data[size]), 1024 * 10);
983296465Sdelphij        size += i;
984296465Sdelphij        if (i == 0)
985296465Sdelphij            break;
986296465Sdelphij        if (i < 0) {
987296465Sdelphij            BIO_printf(err, "Error reading %s %s", key_descrip, file);
988296465Sdelphij            goto error;
989296465Sdelphij        }
990296465Sdelphij    }
991296465Sdelphij    p = (unsigned char *)buf->data;
992296465Sdelphij    rsa = d2i_RSA_NET(NULL, &p, (long)size, NULL,
993296465Sdelphij                      (format == FORMAT_IISSGC ? 1 : 0));
994296465Sdelphij    if (rsa == NULL)
995296465Sdelphij        goto error;
996296465Sdelphij    BUF_MEM_free(buf);
997296465Sdelphij    EVP_PKEY_set1_RSA(pkey, rsa);
998296465Sdelphij    return pkey;
999296465Sdelphij error:
1000296465Sdelphij    BUF_MEM_free(buf);
1001296465Sdelphij    EVP_PKEY_free(pkey);
1002296465Sdelphij    return NULL;
1003296465Sdelphij}
1004296465Sdelphij#endif                          /* ndef OPENSSL_NO_RC4 */
1005109998Smarkm
1006109998SmarkmSTACK_OF(X509) *load_certs(BIO *err, const char *file, int format,
1007296465Sdelphij                           const char *pass, ENGINE *e,
1008296465Sdelphij                           const char *cert_descrip)
1009296465Sdelphij{
1010296465Sdelphij    BIO *certs;
1011296465Sdelphij    int i;
1012296465Sdelphij    STACK_OF(X509) *othercerts = NULL;
1013296465Sdelphij    STACK_OF(X509_INFO) *allcerts = NULL;
1014296465Sdelphij    X509_INFO *xi;
1015296465Sdelphij    PW_CB_DATA cb_data;
101668651Skris
1017296465Sdelphij    cb_data.password = pass;
1018296465Sdelphij    cb_data.prompt_info = file;
1019109998Smarkm
1020296465Sdelphij    if ((certs = BIO_new(BIO_s_file())) == NULL) {
1021296465Sdelphij        ERR_print_errors(err);
1022296465Sdelphij        goto end;
1023296465Sdelphij    }
102468651Skris
1025296465Sdelphij    if (file == NULL)
1026296465Sdelphij        BIO_set_fp(certs, stdin, BIO_NOCLOSE);
1027296465Sdelphij    else {
1028296465Sdelphij        if (BIO_read_filename(certs, file) <= 0) {
1029296465Sdelphij            BIO_printf(err, "Error opening %s %s\n", cert_descrip, file);
1030296465Sdelphij            ERR_print_errors(err);
1031296465Sdelphij            goto end;
1032296465Sdelphij        }
1033296465Sdelphij    }
103468651Skris
1035296465Sdelphij    if (format == FORMAT_PEM) {
1036296465Sdelphij        othercerts = sk_X509_new_null();
1037296465Sdelphij        if (!othercerts) {
1038296465Sdelphij            sk_X509_free(othercerts);
1039296465Sdelphij            othercerts = NULL;
1040296465Sdelphij            goto end;
1041296465Sdelphij        }
1042296465Sdelphij        allcerts = PEM_X509_INFO_read_bio(certs, NULL, (pem_password_cb *)
1043296465Sdelphij                                          password_callback, &cb_data);
1044296465Sdelphij        for (i = 0; i < sk_X509_INFO_num(allcerts); i++) {
1045296465Sdelphij            xi = sk_X509_INFO_value(allcerts, i);
1046296465Sdelphij            if (xi->x509) {
1047296465Sdelphij                sk_X509_push(othercerts, xi->x509);
1048296465Sdelphij                xi->x509 = NULL;
1049296465Sdelphij            }
1050296465Sdelphij        }
1051296465Sdelphij        goto end;
1052296465Sdelphij    } else {
1053296465Sdelphij        BIO_printf(err, "bad input format specified for %s\n", cert_descrip);
1054296465Sdelphij        goto end;
1055296465Sdelphij    }
1056296465Sdelphij end:
1057296465Sdelphij    if (othercerts == NULL) {
1058296465Sdelphij        BIO_printf(err, "unable to load certificates\n");
1059296465Sdelphij        ERR_print_errors(err);
1060296465Sdelphij    }
1061296465Sdelphij    if (allcerts)
1062296465Sdelphij        sk_X509_INFO_pop_free(allcerts, X509_INFO_free);
1063296465Sdelphij    if (certs != NULL)
1064296465Sdelphij        BIO_free(certs);
1065296465Sdelphij    return (othercerts);
1066296465Sdelphij}
106768651Skris
1068296465Sdelphij#define X509V3_EXT_UNKNOWN_MASK         (0xfL << 16)
1069109998Smarkm/* Return error for unknown extensions */
1070296465Sdelphij#define X509V3_EXT_DEFAULT              0
1071109998Smarkm/* Print error for unknown extensions */
1072296465Sdelphij#define X509V3_EXT_ERROR_UNKNOWN        (1L << 16)
1073109998Smarkm/* ASN1 parse unknown extensions */
1074296465Sdelphij#define X509V3_EXT_PARSE_UNKNOWN        (2L << 16)
1075109998Smarkm/* BIO_dump unknown extensions */
1076296465Sdelphij#define X509V3_EXT_DUMP_UNKNOWN         (3L << 16)
1077109998Smarkm
1078109998Smarkm#define X509_FLAG_CA (X509_FLAG_NO_ISSUER | X509_FLAG_NO_PUBKEY | \
1079296465Sdelphij                         X509_FLAG_NO_HEADER | X509_FLAG_NO_VERSION)
1080109998Smarkm
1081109998Smarkmint set_cert_ex(unsigned long *flags, const char *arg)
1082109998Smarkm{
1083296465Sdelphij    static const NAME_EX_TBL cert_tbl[] = {
1084296465Sdelphij        {"compatible", X509_FLAG_COMPAT, 0xffffffffl},
1085296465Sdelphij        {"ca_default", X509_FLAG_CA, 0xffffffffl},
1086296465Sdelphij        {"no_header", X509_FLAG_NO_HEADER, 0},
1087296465Sdelphij        {"no_version", X509_FLAG_NO_VERSION, 0},
1088296465Sdelphij        {"no_serial", X509_FLAG_NO_SERIAL, 0},
1089296465Sdelphij        {"no_signame", X509_FLAG_NO_SIGNAME, 0},
1090296465Sdelphij        {"no_validity", X509_FLAG_NO_VALIDITY, 0},
1091296465Sdelphij        {"no_subject", X509_FLAG_NO_SUBJECT, 0},
1092296465Sdelphij        {"no_issuer", X509_FLAG_NO_ISSUER, 0},
1093296465Sdelphij        {"no_pubkey", X509_FLAG_NO_PUBKEY, 0},
1094296465Sdelphij        {"no_extensions", X509_FLAG_NO_EXTENSIONS, 0},
1095296465Sdelphij        {"no_sigdump", X509_FLAG_NO_SIGDUMP, 0},
1096296465Sdelphij        {"no_aux", X509_FLAG_NO_AUX, 0},
1097296465Sdelphij        {"no_attributes", X509_FLAG_NO_ATTRIBUTES, 0},
1098296465Sdelphij        {"ext_default", X509V3_EXT_DEFAULT, X509V3_EXT_UNKNOWN_MASK},
1099296465Sdelphij        {"ext_error", X509V3_EXT_ERROR_UNKNOWN, X509V3_EXT_UNKNOWN_MASK},
1100296465Sdelphij        {"ext_parse", X509V3_EXT_PARSE_UNKNOWN, X509V3_EXT_UNKNOWN_MASK},
1101296465Sdelphij        {"ext_dump", X509V3_EXT_DUMP_UNKNOWN, X509V3_EXT_UNKNOWN_MASK},
1102296465Sdelphij        {NULL, 0, 0}
1103296465Sdelphij    };
1104296465Sdelphij    return set_multi_opts(flags, arg, cert_tbl);
1105109998Smarkm}
1106109998Smarkm
110768651Skrisint set_name_ex(unsigned long *flags, const char *arg)
110868651Skris{
1109296465Sdelphij    static const NAME_EX_TBL ex_tbl[] = {
1110296465Sdelphij        {"esc_2253", ASN1_STRFLGS_ESC_2253, 0},
1111296465Sdelphij        {"esc_ctrl", ASN1_STRFLGS_ESC_CTRL, 0},
1112296465Sdelphij        {"esc_msb", ASN1_STRFLGS_ESC_MSB, 0},
1113296465Sdelphij        {"use_quote", ASN1_STRFLGS_ESC_QUOTE, 0},
1114296465Sdelphij        {"utf8", ASN1_STRFLGS_UTF8_CONVERT, 0},
1115296465Sdelphij        {"ignore_type", ASN1_STRFLGS_IGNORE_TYPE, 0},
1116296465Sdelphij        {"show_type", ASN1_STRFLGS_SHOW_TYPE, 0},
1117296465Sdelphij        {"dump_all", ASN1_STRFLGS_DUMP_ALL, 0},
1118296465Sdelphij        {"dump_nostr", ASN1_STRFLGS_DUMP_UNKNOWN, 0},
1119296465Sdelphij        {"dump_der", ASN1_STRFLGS_DUMP_DER, 0},
1120296465Sdelphij        {"compat", XN_FLAG_COMPAT, 0xffffffffL},
1121296465Sdelphij        {"sep_comma_plus", XN_FLAG_SEP_COMMA_PLUS, XN_FLAG_SEP_MASK},
1122296465Sdelphij        {"sep_comma_plus_space", XN_FLAG_SEP_CPLUS_SPC, XN_FLAG_SEP_MASK},
1123296465Sdelphij        {"sep_semi_plus_space", XN_FLAG_SEP_SPLUS_SPC, XN_FLAG_SEP_MASK},
1124296465Sdelphij        {"sep_multiline", XN_FLAG_SEP_MULTILINE, XN_FLAG_SEP_MASK},
1125296465Sdelphij        {"dn_rev", XN_FLAG_DN_REV, 0},
1126296465Sdelphij        {"nofname", XN_FLAG_FN_NONE, XN_FLAG_FN_MASK},
1127296465Sdelphij        {"sname", XN_FLAG_FN_SN, XN_FLAG_FN_MASK},
1128296465Sdelphij        {"lname", XN_FLAG_FN_LN, XN_FLAG_FN_MASK},
1129296465Sdelphij        {"align", XN_FLAG_FN_ALIGN, 0},
1130296465Sdelphij        {"oid", XN_FLAG_FN_OID, XN_FLAG_FN_MASK},
1131296465Sdelphij        {"space_eq", XN_FLAG_SPC_EQ, 0},
1132296465Sdelphij        {"dump_unknown", XN_FLAG_DUMP_UNKNOWN_FIELDS, 0},
1133296465Sdelphij        {"RFC2253", XN_FLAG_RFC2253, 0xffffffffL},
1134296465Sdelphij        {"oneline", XN_FLAG_ONELINE, 0xffffffffL},
1135296465Sdelphij        {"multiline", XN_FLAG_MULTILINE, 0xffffffffL},
1136296465Sdelphij        {"ca_default", XN_FLAG_MULTILINE, 0xffffffffL},
1137296465Sdelphij        {NULL, 0, 0}
1138296465Sdelphij    };
1139296465Sdelphij    return set_multi_opts(flags, arg, ex_tbl);
1140109998Smarkm}
114168651Skris
1142109998Smarkmint set_ext_copy(int *copy_type, const char *arg)
1143109998Smarkm{
1144296465Sdelphij    if (!strcasecmp(arg, "none"))
1145296465Sdelphij        *copy_type = EXT_COPY_NONE;
1146296465Sdelphij    else if (!strcasecmp(arg, "copy"))
1147296465Sdelphij        *copy_type = EXT_COPY_ADD;
1148296465Sdelphij    else if (!strcasecmp(arg, "copyall"))
1149296465Sdelphij        *copy_type = EXT_COPY_ALL;
1150296465Sdelphij    else
1151296465Sdelphij        return 0;
1152296465Sdelphij    return 1;
1153109998Smarkm}
1154109998Smarkm
1155109998Smarkmint copy_extensions(X509 *x, X509_REQ *req, int copy_type)
1156109998Smarkm{
1157296465Sdelphij    STACK_OF(X509_EXTENSION) *exts = NULL;
1158296465Sdelphij    X509_EXTENSION *ext, *tmpext;
1159296465Sdelphij    ASN1_OBJECT *obj;
1160296465Sdelphij    int i, idx, ret = 0;
1161296465Sdelphij    if (!x || !req || (copy_type == EXT_COPY_NONE))
1162296465Sdelphij        return 1;
1163296465Sdelphij    exts = X509_REQ_get_extensions(req);
1164109998Smarkm
1165296465Sdelphij    for (i = 0; i < sk_X509_EXTENSION_num(exts); i++) {
1166296465Sdelphij        ext = sk_X509_EXTENSION_value(exts, i);
1167296465Sdelphij        obj = X509_EXTENSION_get_object(ext);
1168296465Sdelphij        idx = X509_get_ext_by_OBJ(x, obj, -1);
1169296465Sdelphij        /* Does extension exist? */
1170296465Sdelphij        if (idx != -1) {
1171296465Sdelphij            /* If normal copy don't override existing extension */
1172296465Sdelphij            if (copy_type == EXT_COPY_ADD)
1173296465Sdelphij                continue;
1174296465Sdelphij            /* Delete all extensions of same type */
1175296465Sdelphij            do {
1176296465Sdelphij                tmpext = X509_get_ext(x, idx);
1177296465Sdelphij                X509_delete_ext(x, idx);
1178296465Sdelphij                X509_EXTENSION_free(tmpext);
1179296465Sdelphij                idx = X509_get_ext_by_OBJ(x, obj, -1);
1180296465Sdelphij            } while (idx != -1);
1181296465Sdelphij        }
1182296465Sdelphij        if (!X509_add_ext(x, ext, -1))
1183296465Sdelphij            goto end;
1184296465Sdelphij    }
1185109998Smarkm
1186296465Sdelphij    ret = 1;
1187109998Smarkm
1188296465Sdelphij end:
1189109998Smarkm
1190296465Sdelphij    sk_X509_EXTENSION_pop_free(exts, X509_EXTENSION_free);
1191109998Smarkm
1192296465Sdelphij    return ret;
1193109998Smarkm}
1194109998Smarkm
1195296465Sdelphijstatic int set_multi_opts(unsigned long *flags, const char *arg,
1196296465Sdelphij                          const NAME_EX_TBL * in_tbl)
1197109998Smarkm{
1198296465Sdelphij    STACK_OF(CONF_VALUE) *vals;
1199296465Sdelphij    CONF_VALUE *val;
1200296465Sdelphij    int i, ret = 1;
1201296465Sdelphij    if (!arg)
1202296465Sdelphij        return 0;
1203296465Sdelphij    vals = X509V3_parse_list(arg);
1204296465Sdelphij    for (i = 0; i < sk_CONF_VALUE_num(vals); i++) {
1205296465Sdelphij        val = sk_CONF_VALUE_value(vals, i);
1206296465Sdelphij        if (!set_table_opts(flags, val->name, in_tbl))
1207296465Sdelphij            ret = 0;
1208296465Sdelphij    }
1209296465Sdelphij    sk_CONF_VALUE_pop_free(vals, X509V3_conf_free);
1210296465Sdelphij    return ret;
1211109998Smarkm}
1212109998Smarkm
1213296465Sdelphijstatic int set_table_opts(unsigned long *flags, const char *arg,
1214296465Sdelphij                          const NAME_EX_TBL * in_tbl)
1215109998Smarkm{
1216296465Sdelphij    char c;
1217296465Sdelphij    const NAME_EX_TBL *ptbl;
1218296465Sdelphij    c = arg[0];
121968651Skris
1220296465Sdelphij    if (c == '-') {
1221296465Sdelphij        c = 0;
1222296465Sdelphij        arg++;
1223296465Sdelphij    } else if (c == '+') {
1224296465Sdelphij        c = 1;
1225296465Sdelphij        arg++;
1226296465Sdelphij    } else
1227296465Sdelphij        c = 1;
122868651Skris
1229296465Sdelphij    for (ptbl = in_tbl; ptbl->name; ptbl++) {
1230296465Sdelphij        if (!strcasecmp(arg, ptbl->name)) {
1231296465Sdelphij            *flags &= ~ptbl->mask;
1232296465Sdelphij            if (c)
1233296465Sdelphij                *flags |= ptbl->flag;
1234296465Sdelphij            else
1235296465Sdelphij                *flags &= ~ptbl->flag;
1236296465Sdelphij            return 1;
1237296465Sdelphij        }
1238296465Sdelphij    }
1239296465Sdelphij    return 0;
124068651Skris}
124168651Skris
1242296465Sdelphijvoid print_name(BIO *out, const char *title, X509_NAME *nm,
1243296465Sdelphij                unsigned long lflags)
124468651Skris{
1245296465Sdelphij    char *buf;
1246296465Sdelphij    char mline = 0;
1247296465Sdelphij    int indent = 0;
1248109998Smarkm
1249296465Sdelphij    if (title)
1250296465Sdelphij        BIO_puts(out, title);
1251296465Sdelphij    if ((lflags & XN_FLAG_SEP_MASK) == XN_FLAG_SEP_MULTILINE) {
1252296465Sdelphij        mline = 1;
1253296465Sdelphij        indent = 4;
1254296465Sdelphij    }
1255296465Sdelphij    if (lflags == XN_FLAG_COMPAT) {
1256296465Sdelphij        buf = X509_NAME_oneline(nm, 0, 0);
1257296465Sdelphij        BIO_puts(out, buf);
1258296465Sdelphij        BIO_puts(out, "\n");
1259296465Sdelphij        OPENSSL_free(buf);
1260296465Sdelphij    } else {
1261296465Sdelphij        if (mline)
1262296465Sdelphij            BIO_puts(out, "\n");
1263296465Sdelphij        X509_NAME_print_ex(out, nm, indent, lflags);
1264296465Sdelphij        BIO_puts(out, "\n");
1265296465Sdelphij    }
126668651Skris}
126768651Skris
1268109998SmarkmX509_STORE *setup_verify(BIO *bp, char *CAfile, char *CApath)
1269109998Smarkm{
1270296465Sdelphij    X509_STORE *store;
1271296465Sdelphij    X509_LOOKUP *lookup;
1272296465Sdelphij    if (!(store = X509_STORE_new()))
1273296465Sdelphij        goto end;
1274296465Sdelphij    lookup = X509_STORE_add_lookup(store, X509_LOOKUP_file());
1275296465Sdelphij    if (lookup == NULL)
1276296465Sdelphij        goto end;
1277296465Sdelphij    if (CAfile) {
1278296465Sdelphij        if (!X509_LOOKUP_load_file(lookup, CAfile, X509_FILETYPE_PEM)) {
1279296465Sdelphij            BIO_printf(bp, "Error loading file %s\n", CAfile);
1280296465Sdelphij            goto end;
1281296465Sdelphij        }
1282296465Sdelphij    } else
1283296465Sdelphij        X509_LOOKUP_load_file(lookup, NULL, X509_FILETYPE_DEFAULT);
1284109998Smarkm
1285296465Sdelphij    lookup = X509_STORE_add_lookup(store, X509_LOOKUP_hash_dir());
1286296465Sdelphij    if (lookup == NULL)
1287296465Sdelphij        goto end;
1288296465Sdelphij    if (CApath) {
1289296465Sdelphij        if (!X509_LOOKUP_add_dir(lookup, CApath, X509_FILETYPE_PEM)) {
1290296465Sdelphij            BIO_printf(bp, "Error loading directory %s\n", CApath);
1291296465Sdelphij            goto end;
1292296465Sdelphij        }
1293296465Sdelphij    } else
1294296465Sdelphij        X509_LOOKUP_add_dir(lookup, NULL, X509_FILETYPE_DEFAULT);
1295296465Sdelphij
1296296465Sdelphij    ERR_clear_error();
1297296465Sdelphij    return store;
1298296465Sdelphij end:
1299296465Sdelphij    X509_STORE_free(store);
1300296465Sdelphij    return NULL;
1301109998Smarkm}
1302109998Smarkm
1303111147Snectar#ifndef OPENSSL_NO_ENGINE
1304109998Smarkm/* Try to load an engine in a shareable library */
1305109998Smarkmstatic ENGINE *try_load_engine(BIO *err, const char *engine, int debug)
1306296465Sdelphij{
1307296465Sdelphij    ENGINE *e = ENGINE_by_id("dynamic");
1308296465Sdelphij    if (e) {
1309296465Sdelphij        if (!ENGINE_ctrl_cmd_string(e, "SO_PATH", engine, 0)
1310296465Sdelphij            || !ENGINE_ctrl_cmd_string(e, "LOAD", NULL, 0)) {
1311296465Sdelphij            ENGINE_free(e);
1312296465Sdelphij            e = NULL;
1313296465Sdelphij        }
1314296465Sdelphij    }
1315296465Sdelphij    return e;
1316296465Sdelphij}
1317109998Smarkm
1318109998SmarkmENGINE *setup_engine(BIO *err, const char *engine, int debug)
1319296465Sdelphij{
1320296465Sdelphij    ENGINE *e = NULL;
1321109998Smarkm
1322296465Sdelphij    if (engine) {
1323296465Sdelphij        if (strcmp(engine, "auto") == 0) {
1324296465Sdelphij            BIO_printf(err, "enabling auto ENGINE support\n");
1325296465Sdelphij            ENGINE_register_all_complete();
1326296465Sdelphij            return NULL;
1327296465Sdelphij        }
1328296465Sdelphij        if ((e = ENGINE_by_id(engine)) == NULL
1329296465Sdelphij            && (e = try_load_engine(err, engine, debug)) == NULL) {
1330296465Sdelphij            BIO_printf(err, "invalid engine \"%s\"\n", engine);
1331296465Sdelphij            ERR_print_errors(err);
1332296465Sdelphij            return NULL;
1333296465Sdelphij        }
1334296465Sdelphij        if (debug) {
1335296465Sdelphij            ENGINE_ctrl(e, ENGINE_CTRL_SET_LOGSTREAM, 0, err, 0);
1336296465Sdelphij        }
1337296465Sdelphij        ENGINE_ctrl_cmd(e, "SET_USER_INTERFACE", 0, ui_method, 0, 1);
1338296465Sdelphij        if (!ENGINE_set_default(e, ENGINE_METHOD_ALL)) {
1339296465Sdelphij            BIO_printf(err, "can't use that engine\n");
1340296465Sdelphij            ERR_print_errors(err);
1341296465Sdelphij            ENGINE_free(e);
1342296465Sdelphij            return NULL;
1343296465Sdelphij        }
1344109998Smarkm
1345296465Sdelphij        BIO_printf(err, "engine \"%s\" set.\n", ENGINE_get_id(e));
1346109998Smarkm
1347296465Sdelphij        /* Free our "structural" reference. */
1348296465Sdelphij        ENGINE_free(e);
1349296465Sdelphij    }
1350296465Sdelphij    return e;
1351296465Sdelphij}
1352111147Snectar#endif
1353109998Smarkm
1354109998Smarkmint load_config(BIO *err, CONF *cnf)
1355296465Sdelphij{
1356296465Sdelphij    if (!cnf)
1357296465Sdelphij        cnf = config;
1358296465Sdelphij    if (!cnf)
1359296465Sdelphij        return 1;
1360109998Smarkm
1361296465Sdelphij    OPENSSL_load_builtin_modules();
1362109998Smarkm
1363296465Sdelphij    if (CONF_modules_load(cnf, NULL, 0) <= 0) {
1364296465Sdelphij        BIO_printf(err, "Error configuring OpenSSL\n");
1365296465Sdelphij        ERR_print_errors(err);
1366296465Sdelphij        return 0;
1367296465Sdelphij    }
1368296465Sdelphij    return 1;
1369296465Sdelphij}
1370109998Smarkm
1371109998Smarkmchar *make_config_name()
1372296465Sdelphij{
1373296465Sdelphij    const char *t = X509_get_default_cert_area();
1374296465Sdelphij    size_t len;
1375296465Sdelphij    char *p;
1376109998Smarkm
1377296465Sdelphij    len = strlen(t) + strlen(OPENSSL_CONF) + 2;
1378296465Sdelphij    p = OPENSSL_malloc(len);
1379296465Sdelphij    if (p == NULL)
1380296465Sdelphij        return NULL;
1381296465Sdelphij    BUF_strlcpy(p, t, len);
1382109998Smarkm#ifndef OPENSSL_SYS_VMS
1383296465Sdelphij    BUF_strlcat(p, "/", len);
1384109998Smarkm#endif
1385296465Sdelphij    BUF_strlcat(p, OPENSSL_CONF, len);
1386109998Smarkm
1387296465Sdelphij    return p;
1388296465Sdelphij}
1389127128Snectar
1390127128Snectarstatic unsigned long index_serial_hash(const char **a)
1391296465Sdelphij{
1392296465Sdelphij    const char *n;
1393127128Snectar
1394296465Sdelphij    n = a[DB_serial];
1395296465Sdelphij    while (*n == '0')
1396296465Sdelphij        n++;
1397296465Sdelphij    return (lh_strhash(n));
1398296465Sdelphij}
1399127128Snectar
1400127128Snectarstatic int index_serial_cmp(const char **a, const char **b)
1401296465Sdelphij{
1402296465Sdelphij    const char *aa, *bb;
1403127128Snectar
1404296465Sdelphij    for (aa = a[DB_serial]; *aa == '0'; aa++) ;
1405296465Sdelphij    for (bb = b[DB_serial]; *bb == '0'; bb++) ;
1406296465Sdelphij    return (strcmp(aa, bb));
1407296465Sdelphij}
1408127128Snectar
1409127128Snectarstatic int index_name_qual(char **a)
1410296465Sdelphij{
1411296465Sdelphij    return (a[0][0] == 'V');
1412296465Sdelphij}
1413127128Snectar
1414127128Snectarstatic unsigned long index_name_hash(const char **a)
1415296465Sdelphij{
1416296465Sdelphij    return (lh_strhash(a[DB_name]));
1417296465Sdelphij}
1418127128Snectar
1419127128Snectarint index_name_cmp(const char **a, const char **b)
1420296465Sdelphij{
1421296465Sdelphij    return (strcmp(a[DB_name], b[DB_name]));
1422296465Sdelphij}
1423127128Snectar
1424296465Sdelphijstatic IMPLEMENT_LHASH_HASH_FN(index_serial_hash, const char **)
1425296465Sdelphijstatic IMPLEMENT_LHASH_COMP_FN(index_serial_cmp, const char **)
1426296465Sdelphijstatic IMPLEMENT_LHASH_HASH_FN(index_name_hash, const char **)
1427296465Sdelphijstatic IMPLEMENT_LHASH_COMP_FN(index_name_cmp, const char **)
1428127128Snectar#undef BSIZE
1429127128Snectar#define BSIZE 256
1430127128SnectarBIGNUM *load_serial(char *serialfile, int create, ASN1_INTEGER **retai)
1431296465Sdelphij{
1432296465Sdelphij    BIO *in = NULL;
1433296465Sdelphij    BIGNUM *ret = NULL;
1434296465Sdelphij    MS_STATIC char buf[1024];
1435296465Sdelphij    ASN1_INTEGER *ai = NULL;
1436127128Snectar
1437296465Sdelphij    ai = ASN1_INTEGER_new();
1438296465Sdelphij    if (ai == NULL)
1439296465Sdelphij        goto err;
1440127128Snectar
1441296465Sdelphij    if ((in = BIO_new(BIO_s_file())) == NULL) {
1442296465Sdelphij        ERR_print_errors(bio_err);
1443296465Sdelphij        goto err;
1444296465Sdelphij    }
1445127128Snectar
1446296465Sdelphij    if (BIO_read_filename(in, serialfile) <= 0) {
1447296465Sdelphij        if (!create) {
1448296465Sdelphij            perror(serialfile);
1449296465Sdelphij            goto err;
1450296465Sdelphij        } else {
1451296465Sdelphij            ret = BN_new();
1452296465Sdelphij            if (ret == NULL || !rand_serial(ret, ai))
1453296465Sdelphij                BIO_printf(bio_err, "Out of memory\n");
1454296465Sdelphij        }
1455296465Sdelphij    } else {
1456296465Sdelphij        if (!a2i_ASN1_INTEGER(in, ai, buf, 1024)) {
1457296465Sdelphij            BIO_printf(bio_err, "unable to load number from %s\n",
1458296465Sdelphij                       serialfile);
1459296465Sdelphij            goto err;
1460296465Sdelphij        }
1461296465Sdelphij        ret = ASN1_INTEGER_to_BN(ai, NULL);
1462296465Sdelphij        if (ret == NULL) {
1463296465Sdelphij            BIO_printf(bio_err,
1464296465Sdelphij                       "error converting number from bin to BIGNUM\n");
1465296465Sdelphij            goto err;
1466296465Sdelphij        }
1467296465Sdelphij    }
1468127128Snectar
1469296465Sdelphij    if (ret && retai) {
1470296465Sdelphij        *retai = ai;
1471296465Sdelphij        ai = NULL;
1472296465Sdelphij    }
1473127128Snectar err:
1474296465Sdelphij    if (in != NULL)
1475296465Sdelphij        BIO_free(in);
1476296465Sdelphij    if (ai != NULL)
1477296465Sdelphij        ASN1_INTEGER_free(ai);
1478296465Sdelphij    return (ret);
1479296465Sdelphij}
1480127128Snectar
1481296465Sdelphijint save_serial(char *serialfile, char *suffix, BIGNUM *serial,
1482296465Sdelphij                ASN1_INTEGER **retai)
1483296465Sdelphij{
1484296465Sdelphij    char buf[1][BSIZE];
1485296465Sdelphij    BIO *out = NULL;
1486296465Sdelphij    int ret = 0;
1487296465Sdelphij    ASN1_INTEGER *ai = NULL;
1488296465Sdelphij    int j;
1489127128Snectar
1490296465Sdelphij    if (suffix == NULL)
1491296465Sdelphij        j = strlen(serialfile);
1492296465Sdelphij    else
1493296465Sdelphij        j = strlen(serialfile) + strlen(suffix) + 1;
1494296465Sdelphij    if (j >= BSIZE) {
1495296465Sdelphij        BIO_printf(bio_err, "file name too long\n");
1496296465Sdelphij        goto err;
1497296465Sdelphij    }
1498127128Snectar
1499296465Sdelphij    if (suffix == NULL)
1500296465Sdelphij        BUF_strlcpy(buf[0], serialfile, BSIZE);
1501296465Sdelphij    else {
1502127128Snectar#ifndef OPENSSL_SYS_VMS
1503296465Sdelphij        j = BIO_snprintf(buf[0], sizeof buf[0], "%s.%s", serialfile, suffix);
1504127128Snectar#else
1505296465Sdelphij        j = BIO_snprintf(buf[0], sizeof buf[0], "%s-%s", serialfile, suffix);
1506127128Snectar#endif
1507296465Sdelphij    }
1508127128Snectar#ifdef RL_DEBUG
1509296465Sdelphij    BIO_printf(bio_err, "DEBUG: writing \"%s\"\n", buf[0]);
1510127128Snectar#endif
1511296465Sdelphij    out = BIO_new(BIO_s_file());
1512296465Sdelphij    if (out == NULL) {
1513296465Sdelphij        ERR_print_errors(bio_err);
1514296465Sdelphij        goto err;
1515296465Sdelphij    }
1516296465Sdelphij    if (BIO_write_filename(out, buf[0]) <= 0) {
1517296465Sdelphij        perror(serialfile);
1518296465Sdelphij        goto err;
1519296465Sdelphij    }
1520127128Snectar
1521296465Sdelphij    if ((ai = BN_to_ASN1_INTEGER(serial, NULL)) == NULL) {
1522296465Sdelphij        BIO_printf(bio_err, "error converting serial to ASN.1 format\n");
1523296465Sdelphij        goto err;
1524296465Sdelphij    }
1525296465Sdelphij    i2a_ASN1_INTEGER(out, ai);
1526296465Sdelphij    BIO_puts(out, "\n");
1527296465Sdelphij    ret = 1;
1528296465Sdelphij    if (retai) {
1529296465Sdelphij        *retai = ai;
1530296465Sdelphij        ai = NULL;
1531296465Sdelphij    }
1532296465Sdelphij err:
1533296465Sdelphij    if (out != NULL)
1534296465Sdelphij        BIO_free_all(out);
1535296465Sdelphij    if (ai != NULL)
1536296465Sdelphij        ASN1_INTEGER_free(ai);
1537296465Sdelphij    return (ret);
1538296465Sdelphij}
1539127128Snectar
1540127128Snectarint rotate_serial(char *serialfile, char *new_suffix, char *old_suffix)
1541296465Sdelphij{
1542296465Sdelphij    char buf[5][BSIZE];
1543296465Sdelphij    int i, j;
1544296465Sdelphij    struct stat sb;
1545127128Snectar
1546296465Sdelphij    i = strlen(serialfile) + strlen(old_suffix);
1547296465Sdelphij    j = strlen(serialfile) + strlen(new_suffix);
1548296465Sdelphij    if (i > j)
1549296465Sdelphij        j = i;
1550296465Sdelphij    if (j + 1 >= BSIZE) {
1551296465Sdelphij        BIO_printf(bio_err, "file name too long\n");
1552296465Sdelphij        goto err;
1553296465Sdelphij    }
1554127128Snectar#ifndef OPENSSL_SYS_VMS
1555296465Sdelphij    j = BIO_snprintf(buf[0], sizeof buf[0], "%s.%s", serialfile, new_suffix);
1556127128Snectar#else
1557296465Sdelphij    j = BIO_snprintf(buf[0], sizeof buf[0], "%s-%s", serialfile, new_suffix);
1558127128Snectar#endif
1559127128Snectar#ifndef OPENSSL_SYS_VMS
1560296465Sdelphij    j = BIO_snprintf(buf[1], sizeof buf[1], "%s.%s", serialfile, old_suffix);
1561127128Snectar#else
1562296465Sdelphij    j = BIO_snprintf(buf[1], sizeof buf[1], "%s-%s", serialfile, old_suffix);
1563127128Snectar#endif
1564296465Sdelphij    if (stat(serialfile, &sb) < 0) {
1565296465Sdelphij        if (errno != ENOENT
1566127128Snectar#ifdef ENOTDIR
1567296465Sdelphij            && errno != ENOTDIR
1568127128Snectar#endif
1569296465Sdelphij            )
1570296465Sdelphij            goto err;
1571296465Sdelphij    } else {
1572127128Snectar#ifdef RL_DEBUG
1573296465Sdelphij        BIO_printf(bio_err, "DEBUG: renaming \"%s\" to \"%s\"\n",
1574296465Sdelphij                   serialfile, buf[1]);
1575127128Snectar#endif
1576296465Sdelphij        if (rename(serialfile, buf[1]) < 0) {
1577296465Sdelphij            BIO_printf(bio_err,
1578296465Sdelphij                       "unable to rename %s to %s\n", serialfile, buf[1]);
1579296465Sdelphij            perror("reason");
1580296465Sdelphij            goto err;
1581296465Sdelphij        }
1582296465Sdelphij    }
1583127128Snectar#ifdef RL_DEBUG
1584296465Sdelphij    BIO_printf(bio_err, "DEBUG: renaming \"%s\" to \"%s\"\n",
1585296465Sdelphij               buf[0], serialfile);
1586127128Snectar#endif
1587296465Sdelphij    if (rename(buf[0], serialfile) < 0) {
1588296465Sdelphij        BIO_printf(bio_err,
1589296465Sdelphij                   "unable to rename %s to %s\n", buf[0], serialfile);
1590296465Sdelphij        perror("reason");
1591296465Sdelphij        rename(buf[1], serialfile);
1592296465Sdelphij        goto err;
1593296465Sdelphij    }
1594296465Sdelphij    return 1;
1595127128Snectar err:
1596296465Sdelphij    return 0;
1597296465Sdelphij}
1598127128Snectar
1599142425Snectarint rand_serial(BIGNUM *b, ASN1_INTEGER *ai)
1600296465Sdelphij{
1601296465Sdelphij    BIGNUM *btmp;
1602296465Sdelphij    int ret = 0;
1603296465Sdelphij    if (b)
1604296465Sdelphij        btmp = b;
1605296465Sdelphij    else
1606296465Sdelphij        btmp = BN_new();
1607142425Snectar
1608296465Sdelphij    if (!btmp)
1609296465Sdelphij        return 0;
1610142425Snectar
1611296465Sdelphij    if (!BN_pseudo_rand(btmp, SERIAL_RAND_BITS, 0, 0))
1612296465Sdelphij        goto error;
1613296465Sdelphij    if (ai && !BN_to_ASN1_INTEGER(btmp, ai))
1614296465Sdelphij        goto error;
1615142425Snectar
1616296465Sdelphij    ret = 1;
1617142425Snectar
1618296465Sdelphij error:
1619142425Snectar
1620296465Sdelphij    if (!b)
1621296465Sdelphij        BN_free(btmp);
1622296465Sdelphij
1623296465Sdelphij    return ret;
1624296465Sdelphij}
1625296465Sdelphij
1626127128SnectarCA_DB *load_index(char *dbfile, DB_ATTR *db_attr)
1627296465Sdelphij{
1628296465Sdelphij    CA_DB *retdb = NULL;
1629296465Sdelphij    TXT_DB *tmpdb = NULL;
1630296465Sdelphij    BIO *in = BIO_new(BIO_s_file());
1631296465Sdelphij    CONF *dbattr_conf = NULL;
1632296465Sdelphij    char buf[1][BSIZE];
1633296465Sdelphij    long errorline = -1;
1634127128Snectar
1635296465Sdelphij    if (in == NULL) {
1636296465Sdelphij        ERR_print_errors(bio_err);
1637296465Sdelphij        goto err;
1638296465Sdelphij    }
1639296465Sdelphij    if (BIO_read_filename(in, dbfile) <= 0) {
1640296465Sdelphij        perror(dbfile);
1641296465Sdelphij        BIO_printf(bio_err, "unable to open '%s'\n", dbfile);
1642296465Sdelphij        goto err;
1643296465Sdelphij    }
1644296465Sdelphij    if ((tmpdb = TXT_DB_read(in, DB_NUMBER)) == NULL) {
1645296465Sdelphij        if (tmpdb != NULL)
1646296465Sdelphij            TXT_DB_free(tmpdb);
1647296465Sdelphij        goto err;
1648296465Sdelphij    }
1649127128Snectar#ifndef OPENSSL_SYS_VMS
1650296465Sdelphij    BIO_snprintf(buf[0], sizeof buf[0], "%s.attr", dbfile);
1651127128Snectar#else
1652296465Sdelphij    BIO_snprintf(buf[0], sizeof buf[0], "%s-attr", dbfile);
1653127128Snectar#endif
1654296465Sdelphij    dbattr_conf = NCONF_new(NULL);
1655296465Sdelphij    if (NCONF_load(dbattr_conf, buf[0], &errorline) <= 0) {
1656296465Sdelphij        if (errorline > 0) {
1657296465Sdelphij            BIO_printf(bio_err,
1658296465Sdelphij                       "error on line %ld of db attribute file '%s'\n",
1659296465Sdelphij                       errorline, buf[0]);
1660296465Sdelphij            goto err;
1661296465Sdelphij        } else {
1662296465Sdelphij            NCONF_free(dbattr_conf);
1663296465Sdelphij            dbattr_conf = NULL;
1664296465Sdelphij        }
1665296465Sdelphij    }
1666127128Snectar
1667296465Sdelphij    if ((retdb = OPENSSL_malloc(sizeof(CA_DB))) == NULL) {
1668296465Sdelphij        fprintf(stderr, "Out of memory\n");
1669296465Sdelphij        goto err;
1670296465Sdelphij    }
1671127128Snectar
1672296465Sdelphij    retdb->db = tmpdb;
1673296465Sdelphij    tmpdb = NULL;
1674296465Sdelphij    if (db_attr)
1675296465Sdelphij        retdb->attributes = *db_attr;
1676296465Sdelphij    else {
1677296465Sdelphij        retdb->attributes.unique_subject = 1;
1678296465Sdelphij    }
1679127128Snectar
1680296465Sdelphij    if (dbattr_conf) {
1681296465Sdelphij        char *p = NCONF_get_string(dbattr_conf, NULL, "unique_subject");
1682296465Sdelphij        if (p) {
1683160814Ssimon#ifdef RL_DEBUG
1684296465Sdelphij            BIO_printf(bio_err,
1685296465Sdelphij                       "DEBUG[load_index]: unique_subject = \"%s\"\n", p);
1686160814Ssimon#endif
1687296465Sdelphij            retdb->attributes.unique_subject = parse_yesno(p, 1);
1688296465Sdelphij        }
1689296465Sdelphij    }
1690127128Snectar
1691127128Snectar err:
1692296465Sdelphij    if (dbattr_conf)
1693296465Sdelphij        NCONF_free(dbattr_conf);
1694296465Sdelphij    if (tmpdb)
1695296465Sdelphij        TXT_DB_free(tmpdb);
1696296465Sdelphij    if (in)
1697296465Sdelphij        BIO_free_all(in);
1698296465Sdelphij    return retdb;
1699296465Sdelphij}
1700127128Snectar
1701127128Snectarint index_index(CA_DB *db)
1702296465Sdelphij{
1703296465Sdelphij    if (!TXT_DB_create_index(db->db, DB_serial, NULL,
1704296465Sdelphij                             LHASH_HASH_FN(index_serial_hash),
1705296465Sdelphij                             LHASH_COMP_FN(index_serial_cmp))) {
1706296465Sdelphij        BIO_printf(bio_err,
1707296465Sdelphij                   "error creating serial number index:(%ld,%ld,%ld)\n",
1708296465Sdelphij                   db->db->error, db->db->arg1, db->db->arg2);
1709296465Sdelphij        return 0;
1710296465Sdelphij    }
1711127128Snectar
1712296465Sdelphij    if (db->attributes.unique_subject
1713296465Sdelphij        && !TXT_DB_create_index(db->db, DB_name, index_name_qual,
1714296465Sdelphij                                LHASH_HASH_FN(index_name_hash),
1715296465Sdelphij                                LHASH_COMP_FN(index_name_cmp))) {
1716296465Sdelphij        BIO_printf(bio_err, "error creating name index:(%ld,%ld,%ld)\n",
1717296465Sdelphij                   db->db->error, db->db->arg1, db->db->arg2);
1718296465Sdelphij        return 0;
1719296465Sdelphij    }
1720296465Sdelphij    return 1;
1721296465Sdelphij}
1722127128Snectar
1723160814Ssimonint save_index(const char *dbfile, const char *suffix, CA_DB *db)
1724296465Sdelphij{
1725296465Sdelphij    char buf[3][BSIZE];
1726296465Sdelphij    BIO *out = BIO_new(BIO_s_file());
1727296465Sdelphij    int j;
1728127128Snectar
1729296465Sdelphij    if (out == NULL) {
1730296465Sdelphij        ERR_print_errors(bio_err);
1731296465Sdelphij        goto err;
1732296465Sdelphij    }
1733127128Snectar
1734296465Sdelphij    j = strlen(dbfile) + strlen(suffix);
1735296465Sdelphij    if (j + 6 >= BSIZE) {
1736296465Sdelphij        BIO_printf(bio_err, "file name too long\n");
1737296465Sdelphij        goto err;
1738296465Sdelphij    }
1739127128Snectar#ifndef OPENSSL_SYS_VMS
1740296465Sdelphij    j = BIO_snprintf(buf[2], sizeof buf[2], "%s.attr", dbfile);
1741127128Snectar#else
1742296465Sdelphij    j = BIO_snprintf(buf[2], sizeof buf[2], "%s-attr", dbfile);
1743127128Snectar#endif
1744127128Snectar#ifndef OPENSSL_SYS_VMS
1745296465Sdelphij    j = BIO_snprintf(buf[1], sizeof buf[1], "%s.attr.%s", dbfile, suffix);
1746127128Snectar#else
1747296465Sdelphij    j = BIO_snprintf(buf[1], sizeof buf[1], "%s-attr-%s", dbfile, suffix);
1748127128Snectar#endif
1749127128Snectar#ifndef OPENSSL_SYS_VMS
1750296465Sdelphij    j = BIO_snprintf(buf[0], sizeof buf[0], "%s.%s", dbfile, suffix);
1751127128Snectar#else
1752296465Sdelphij    j = BIO_snprintf(buf[0], sizeof buf[0], "%s-%s", dbfile, suffix);
1753127128Snectar#endif
1754127128Snectar#ifdef RL_DEBUG
1755296465Sdelphij    BIO_printf(bio_err, "DEBUG: writing \"%s\"\n", buf[0]);
1756127128Snectar#endif
1757296465Sdelphij    if (BIO_write_filename(out, buf[0]) <= 0) {
1758296465Sdelphij        perror(dbfile);
1759296465Sdelphij        BIO_printf(bio_err, "unable to open '%s'\n", dbfile);
1760296465Sdelphij        goto err;
1761296465Sdelphij    }
1762296465Sdelphij    j = TXT_DB_write(out, db->db);
1763296465Sdelphij    if (j <= 0)
1764296465Sdelphij        goto err;
1765127128Snectar
1766296465Sdelphij    BIO_free(out);
1767296465Sdelphij
1768296465Sdelphij    out = BIO_new(BIO_s_file());
1769127128Snectar#ifdef RL_DEBUG
1770296465Sdelphij    BIO_printf(bio_err, "DEBUG: writing \"%s\"\n", buf[1]);
1771127128Snectar#endif
1772296465Sdelphij    if (BIO_write_filename(out, buf[1]) <= 0) {
1773296465Sdelphij        perror(buf[2]);
1774296465Sdelphij        BIO_printf(bio_err, "unable to open '%s'\n", buf[2]);
1775296465Sdelphij        goto err;
1776296465Sdelphij    }
1777296465Sdelphij    BIO_printf(out, "unique_subject = %s\n",
1778296465Sdelphij               db->attributes.unique_subject ? "yes" : "no");
1779296465Sdelphij    BIO_free(out);
1780127128Snectar
1781296465Sdelphij    return 1;
1782127128Snectar err:
1783296465Sdelphij    return 0;
1784296465Sdelphij}
1785127128Snectar
1786296465Sdelphijint rotate_index(const char *dbfile, const char *new_suffix,
1787296465Sdelphij                 const char *old_suffix)
1788296465Sdelphij{
1789296465Sdelphij    char buf[5][BSIZE];
1790296465Sdelphij    int i, j;
1791296465Sdelphij    struct stat sb;
1792127128Snectar
1793296465Sdelphij    i = strlen(dbfile) + strlen(old_suffix);
1794296465Sdelphij    j = strlen(dbfile) + strlen(new_suffix);
1795296465Sdelphij    if (i > j)
1796296465Sdelphij        j = i;
1797296465Sdelphij    if (j + 6 >= BSIZE) {
1798296465Sdelphij        BIO_printf(bio_err, "file name too long\n");
1799296465Sdelphij        goto err;
1800296465Sdelphij    }
1801127128Snectar#ifndef OPENSSL_SYS_VMS
1802296465Sdelphij    j = BIO_snprintf(buf[4], sizeof buf[4], "%s.attr", dbfile);
1803127128Snectar#else
1804296465Sdelphij    j = BIO_snprintf(buf[4], sizeof buf[4], "%s-attr", dbfile);
1805127128Snectar#endif
1806127128Snectar#ifndef OPENSSL_SYS_VMS
1807296465Sdelphij    j = BIO_snprintf(buf[2], sizeof buf[2], "%s.attr.%s", dbfile, new_suffix);
1808127128Snectar#else
1809296465Sdelphij    j = BIO_snprintf(buf[2], sizeof buf[2], "%s-attr-%s", dbfile, new_suffix);
1810127128Snectar#endif
1811127128Snectar#ifndef OPENSSL_SYS_VMS
1812296465Sdelphij    j = BIO_snprintf(buf[0], sizeof buf[0], "%s.%s", dbfile, new_suffix);
1813127128Snectar#else
1814296465Sdelphij    j = BIO_snprintf(buf[0], sizeof buf[0], "%s-%s", dbfile, new_suffix);
1815127128Snectar#endif
1816127128Snectar#ifndef OPENSSL_SYS_VMS
1817296465Sdelphij    j = BIO_snprintf(buf[1], sizeof buf[1], "%s.%s", dbfile, old_suffix);
1818127128Snectar#else
1819296465Sdelphij    j = BIO_snprintf(buf[1], sizeof buf[1], "%s-%s", dbfile, old_suffix);
1820127128Snectar#endif
1821127128Snectar#ifndef OPENSSL_SYS_VMS
1822296465Sdelphij    j = BIO_snprintf(buf[3], sizeof buf[3], "%s.attr.%s", dbfile, old_suffix);
1823127128Snectar#else
1824296465Sdelphij    j = BIO_snprintf(buf[3], sizeof buf[3], "%s-attr-%s", dbfile, old_suffix);
1825127128Snectar#endif
1826296465Sdelphij    if (stat(dbfile, &sb) < 0) {
1827296465Sdelphij        if (errno != ENOENT
1828127128Snectar#ifdef ENOTDIR
1829296465Sdelphij            && errno != ENOTDIR
1830127128Snectar#endif
1831296465Sdelphij            )
1832296465Sdelphij            goto err;
1833296465Sdelphij    } else {
1834127128Snectar#ifdef RL_DEBUG
1835296465Sdelphij        BIO_printf(bio_err, "DEBUG: renaming \"%s\" to \"%s\"\n",
1836296465Sdelphij                   dbfile, buf[1]);
1837127128Snectar#endif
1838296465Sdelphij        if (rename(dbfile, buf[1]) < 0) {
1839296465Sdelphij            BIO_printf(bio_err,
1840296465Sdelphij                       "unable to rename %s to %s\n", dbfile, buf[1]);
1841296465Sdelphij            perror("reason");
1842296465Sdelphij            goto err;
1843296465Sdelphij        }
1844296465Sdelphij    }
1845127128Snectar#ifdef RL_DEBUG
1846296465Sdelphij    BIO_printf(bio_err, "DEBUG: renaming \"%s\" to \"%s\"\n", buf[0], dbfile);
1847127128Snectar#endif
1848296465Sdelphij    if (rename(buf[0], dbfile) < 0) {
1849296465Sdelphij        BIO_printf(bio_err, "unable to rename %s to %s\n", buf[0], dbfile);
1850296465Sdelphij        perror("reason");
1851296465Sdelphij        rename(buf[1], dbfile);
1852296465Sdelphij        goto err;
1853296465Sdelphij    }
1854296465Sdelphij    if (stat(buf[4], &sb) < 0) {
1855296465Sdelphij        if (errno != ENOENT
1856127128Snectar#ifdef ENOTDIR
1857296465Sdelphij            && errno != ENOTDIR
1858127128Snectar#endif
1859296465Sdelphij            )
1860296465Sdelphij            goto err;
1861296465Sdelphij    } else {
1862127128Snectar#ifdef RL_DEBUG
1863296465Sdelphij        BIO_printf(bio_err, "DEBUG: renaming \"%s\" to \"%s\"\n",
1864296465Sdelphij                   buf[4], buf[3]);
1865127128Snectar#endif
1866296465Sdelphij        if (rename(buf[4], buf[3]) < 0) {
1867296465Sdelphij            BIO_printf(bio_err,
1868296465Sdelphij                       "unable to rename %s to %s\n", buf[4], buf[3]);
1869296465Sdelphij            perror("reason");
1870296465Sdelphij            rename(dbfile, buf[0]);
1871296465Sdelphij            rename(buf[1], dbfile);
1872296465Sdelphij            goto err;
1873296465Sdelphij        }
1874296465Sdelphij    }
1875127128Snectar#ifdef RL_DEBUG
1876296465Sdelphij    BIO_printf(bio_err, "DEBUG: renaming \"%s\" to \"%s\"\n", buf[2], buf[4]);
1877127128Snectar#endif
1878296465Sdelphij    if (rename(buf[2], buf[4]) < 0) {
1879296465Sdelphij        BIO_printf(bio_err, "unable to rename %s to %s\n", buf[2], buf[4]);
1880296465Sdelphij        perror("reason");
1881296465Sdelphij        rename(buf[3], buf[4]);
1882296465Sdelphij        rename(dbfile, buf[0]);
1883296465Sdelphij        rename(buf[1], dbfile);
1884296465Sdelphij        goto err;
1885296465Sdelphij    }
1886296465Sdelphij    return 1;
1887127128Snectar err:
1888296465Sdelphij    return 0;
1889296465Sdelphij}
1890127128Snectar
1891127128Snectarvoid free_index(CA_DB *db)
1892296465Sdelphij{
1893296465Sdelphij    if (db) {
1894296465Sdelphij        if (db->db)
1895296465Sdelphij            TXT_DB_free(db->db);
1896296465Sdelphij        OPENSSL_free(db);
1897296465Sdelphij    }
1898296465Sdelphij}
1899142425Snectar
1900160814Ssimonint parse_yesno(const char *str, int def)
1901296465Sdelphij{
1902296465Sdelphij    int ret = def;
1903296465Sdelphij    if (str) {
1904296465Sdelphij        switch (*str) {
1905296465Sdelphij        case 'f':              /* false */
1906296465Sdelphij        case 'F':              /* FALSE */
1907296465Sdelphij        case 'n':              /* no */
1908296465Sdelphij        case 'N':              /* NO */
1909296465Sdelphij        case '0':              /* 0 */
1910296465Sdelphij            ret = 0;
1911296465Sdelphij            break;
1912296465Sdelphij        case 't':              /* true */
1913296465Sdelphij        case 'T':              /* TRUE */
1914296465Sdelphij        case 'y':              /* yes */
1915296465Sdelphij        case 'Y':              /* YES */
1916296465Sdelphij        case '1':              /* 1 */
1917296465Sdelphij            ret = 1;
1918296465Sdelphij            break;
1919296465Sdelphij        default:
1920296465Sdelphij            ret = def;
1921296465Sdelphij            break;
1922296465Sdelphij        }
1923296465Sdelphij    }
1924296465Sdelphij    return ret;
1925296465Sdelphij}
1926160814Ssimon
1927160814Ssimon/*
1928160814Ssimon * subject is expected to be in the format /type0=value0/type1=value1/type2=...
1929160814Ssimon * where characters may be escaped by \
1930160814Ssimon */
1931160814SsimonX509_NAME *parse_name(char *subject, long chtype, int multirdn)
1932296465Sdelphij{
1933296465Sdelphij    size_t buflen = strlen(subject) + 1; /* to copy the types and values
1934296465Sdelphij                                          * into. due to escaping, the copy
1935296465Sdelphij                                          * can only become shorter */
1936296465Sdelphij    char *buf = OPENSSL_malloc(buflen);
1937296465Sdelphij    size_t max_ne = buflen / 2 + 1; /* maximum number of name elements */
1938296465Sdelphij    char **ne_types = OPENSSL_malloc(max_ne * sizeof(char *));
1939296465Sdelphij    char **ne_values = OPENSSL_malloc(max_ne * sizeof(char *));
1940296465Sdelphij    int *mval = OPENSSL_malloc(max_ne * sizeof(int));
1941160814Ssimon
1942296465Sdelphij    char *sp = subject, *bp = buf;
1943296465Sdelphij    int i, ne_num = 0;
1944160814Ssimon
1945296465Sdelphij    X509_NAME *n = NULL;
1946296465Sdelphij    int nid;
1947160814Ssimon
1948296465Sdelphij    if (!buf || !ne_types || !ne_values || !mval) {
1949296465Sdelphij        BIO_printf(bio_err, "malloc error\n");
1950296465Sdelphij        goto error;
1951296465Sdelphij    }
1952160814Ssimon
1953296465Sdelphij    if (*subject != '/') {
1954296465Sdelphij        BIO_printf(bio_err, "Subject does not start with '/'.\n");
1955296465Sdelphij        goto error;
1956296465Sdelphij    }
1957296465Sdelphij    sp++;                       /* skip leading / */
1958160814Ssimon
1959296465Sdelphij    /* no multivalued RDN by default */
1960296465Sdelphij    mval[ne_num] = 0;
1961160814Ssimon
1962296465Sdelphij    while (*sp) {
1963296465Sdelphij        /* collect type */
1964296465Sdelphij        ne_types[ne_num] = bp;
1965296465Sdelphij        while (*sp) {
1966296465Sdelphij            if (*sp == '\\') {  /* is there anything to escape in the
1967296465Sdelphij                                 * type...? */
1968296465Sdelphij                if (*++sp)
1969296465Sdelphij                    *bp++ = *sp++;
1970296465Sdelphij                else {
1971296465Sdelphij                    BIO_printf(bio_err,
1972296465Sdelphij                               "escape character at end of string\n");
1973296465Sdelphij                    goto error;
1974296465Sdelphij                }
1975296465Sdelphij            } else if (*sp == '=') {
1976296465Sdelphij                sp++;
1977296465Sdelphij                *bp++ = '\0';
1978296465Sdelphij                break;
1979296465Sdelphij            } else
1980296465Sdelphij                *bp++ = *sp++;
1981296465Sdelphij        }
1982296465Sdelphij        if (!*sp) {
1983296465Sdelphij            BIO_printf(bio_err,
1984296465Sdelphij                       "end of string encountered while processing type of subject name element #%d\n",
1985296465Sdelphij                       ne_num);
1986296465Sdelphij            goto error;
1987296465Sdelphij        }
1988296465Sdelphij        ne_values[ne_num] = bp;
1989296465Sdelphij        while (*sp) {
1990296465Sdelphij            if (*sp == '\\') {
1991296465Sdelphij                if (*++sp)
1992296465Sdelphij                    *bp++ = *sp++;
1993296465Sdelphij                else {
1994296465Sdelphij                    BIO_printf(bio_err,
1995296465Sdelphij                               "escape character at end of string\n");
1996296465Sdelphij                    goto error;
1997296465Sdelphij                }
1998296465Sdelphij            } else if (*sp == '/') {
1999296465Sdelphij                sp++;
2000296465Sdelphij                /* no multivalued RDN by default */
2001296465Sdelphij                mval[ne_num + 1] = 0;
2002296465Sdelphij                break;
2003296465Sdelphij            } else if (*sp == '+' && multirdn) {
2004296465Sdelphij                /*
2005296465Sdelphij                 * a not escaped + signals a mutlivalued RDN
2006296465Sdelphij                 */
2007296465Sdelphij                sp++;
2008296465Sdelphij                mval[ne_num + 1] = -1;
2009296465Sdelphij                break;
2010296465Sdelphij            } else
2011296465Sdelphij                *bp++ = *sp++;
2012296465Sdelphij        }
2013296465Sdelphij        *bp++ = '\0';
2014296465Sdelphij        ne_num++;
2015296465Sdelphij    }
2016160814Ssimon
2017296465Sdelphij    if (!(n = X509_NAME_new()))
2018296465Sdelphij        goto error;
2019160814Ssimon
2020296465Sdelphij    for (i = 0; i < ne_num; i++) {
2021296465Sdelphij        if ((nid = OBJ_txt2nid(ne_types[i])) == NID_undef) {
2022296465Sdelphij            BIO_printf(bio_err,
2023296465Sdelphij                       "Subject Attribute %s has no known NID, skipped\n",
2024296465Sdelphij                       ne_types[i]);
2025296465Sdelphij            continue;
2026296465Sdelphij        }
2027160814Ssimon
2028296465Sdelphij        if (!*ne_values[i]) {
2029296465Sdelphij            BIO_printf(bio_err,
2030296465Sdelphij                       "No value provided for Subject Attribute %s, skipped\n",
2031296465Sdelphij                       ne_types[i]);
2032296465Sdelphij            continue;
2033296465Sdelphij        }
2034160814Ssimon
2035296465Sdelphij        if (!X509_NAME_add_entry_by_NID
2036296465Sdelphij            (n, nid, chtype, (unsigned char *)ne_values[i], -1, -1, mval[i]))
2037296465Sdelphij            goto error;
2038296465Sdelphij    }
2039160814Ssimon
2040296465Sdelphij    OPENSSL_free(ne_values);
2041296465Sdelphij    OPENSSL_free(ne_types);
2042296465Sdelphij    OPENSSL_free(buf);
2043296465Sdelphij    OPENSSL_free(mval);
2044296465Sdelphij    return n;
2045160814Ssimon
2046296465Sdelphij error:
2047296465Sdelphij    X509_NAME_free(n);
2048296465Sdelphij    if (ne_values)
2049296465Sdelphij        OPENSSL_free(ne_values);
2050296465Sdelphij    if (ne_types)
2051296465Sdelphij        OPENSSL_free(ne_types);
2052296465Sdelphij    if (mval)
2053296465Sdelphij        OPENSSL_free(mval);
2054296465Sdelphij    if (buf)
2055296465Sdelphij        OPENSSL_free(buf);
2056296465Sdelphij    return NULL;
2057160814Ssimon}
2058160814Ssimon
2059142425Snectar/* This code MUST COME AFTER anything that uses rename() */
2060142425Snectar#ifdef OPENSSL_SYS_WIN32
2061160814Ssimonint WIN32_rename(const char *from, const char *to)
2062296465Sdelphij{
2063296465Sdelphij# ifndef OPENSSL_SYS_WINCE
2064296465Sdelphij    /*
2065296465Sdelphij     * Windows rename gives an error if 'to' exists, so delete it first and
2066296465Sdelphij     * ignore file not found errror
2067296465Sdelphij     */
2068296465Sdelphij    if ((remove(to) != 0) && (errno != ENOENT))
2069296465Sdelphij        return -1;
2070296465Sdelphij#  undef rename
2071296465Sdelphij    return rename(from, to);
2072296465Sdelphij# else
2073296465Sdelphij    /* convert strings to UNICODE */
2074296465Sdelphij    {
2075296465Sdelphij        BOOL result = FALSE;
2076296465Sdelphij        WCHAR *wfrom;
2077296465Sdelphij        WCHAR *wto;
2078296465Sdelphij        int i;
2079296465Sdelphij        wfrom = malloc((strlen(from) + 1) * 2);
2080296465Sdelphij        wto = malloc((strlen(to) + 1) * 2);
2081296465Sdelphij        if (wfrom != NULL && wto != NULL) {
2082296465Sdelphij            for (i = 0; i < (int)strlen(from) + 1; i++)
2083296465Sdelphij                wfrom[i] = (short)from[i];
2084296465Sdelphij            for (i = 0; i < (int)strlen(to) + 1; i++)
2085296465Sdelphij                wto[i] = (short)to[i];
2086296465Sdelphij            result = MoveFile(wfrom, wto);
2087296465Sdelphij        }
2088296465Sdelphij        if (wfrom != NULL)
2089296465Sdelphij            free(wfrom);
2090296465Sdelphij        if (wto != NULL)
2091296465Sdelphij            free(wto);
2092296465Sdelphij        return result;
2093296465Sdelphij    }
2094296465Sdelphij# endif
2095296465Sdelphij}
2096142425Snectar#endif
2097160814Ssimon
2098160814Ssimonint args_verify(char ***pargs, int *pargc,
2099296465Sdelphij                int *badarg, BIO *err, X509_VERIFY_PARAM **pm)
2100296465Sdelphij{
2101296465Sdelphij    ASN1_OBJECT *otmp = NULL;
2102296465Sdelphij    unsigned long flags = 0;
2103296465Sdelphij    int i;
2104296465Sdelphij    int purpose = 0;
2105296465Sdelphij    char **oldargs = *pargs;
2106296465Sdelphij    char *arg = **pargs, *argn = (*pargs)[1];
2107296465Sdelphij    if (!strcmp(arg, "-policy")) {
2108296465Sdelphij        if (!argn)
2109296465Sdelphij            *badarg = 1;
2110296465Sdelphij        else {
2111296465Sdelphij            otmp = OBJ_txt2obj(argn, 0);
2112296465Sdelphij            if (!otmp) {
2113296465Sdelphij                BIO_printf(err, "Invalid Policy \"%s\"\n", argn);
2114296465Sdelphij                *badarg = 1;
2115296465Sdelphij            }
2116296465Sdelphij        }
2117296465Sdelphij        (*pargs)++;
2118296465Sdelphij    } else if (strcmp(arg, "-purpose") == 0) {
2119296465Sdelphij        X509_PURPOSE *xptmp;
2120296465Sdelphij        if (!argn)
2121296465Sdelphij            *badarg = 1;
2122296465Sdelphij        else {
2123296465Sdelphij            i = X509_PURPOSE_get_by_sname(argn);
2124296465Sdelphij            if (i < 0) {
2125296465Sdelphij                BIO_printf(err, "unrecognized purpose\n");
2126296465Sdelphij                *badarg = 1;
2127296465Sdelphij            } else {
2128296465Sdelphij                xptmp = X509_PURPOSE_get0(i);
2129296465Sdelphij                purpose = X509_PURPOSE_get_id(xptmp);
2130296465Sdelphij            }
2131296465Sdelphij        }
2132296465Sdelphij        (*pargs)++;
2133296465Sdelphij    } else if (!strcmp(arg, "-ignore_critical"))
2134296465Sdelphij        flags |= X509_V_FLAG_IGNORE_CRITICAL;
2135296465Sdelphij    else if (!strcmp(arg, "-issuer_checks"))
2136296465Sdelphij        flags |= X509_V_FLAG_CB_ISSUER_CHECK;
2137296465Sdelphij    else if (!strcmp(arg, "-crl_check"))
2138296465Sdelphij        flags |= X509_V_FLAG_CRL_CHECK;
2139296465Sdelphij    else if (!strcmp(arg, "-crl_check_all"))
2140296465Sdelphij        flags |= X509_V_FLAG_CRL_CHECK | X509_V_FLAG_CRL_CHECK_ALL;
2141296465Sdelphij    else if (!strcmp(arg, "-policy_check"))
2142296465Sdelphij        flags |= X509_V_FLAG_POLICY_CHECK;
2143296465Sdelphij    else if (!strcmp(arg, "-explicit_policy"))
2144296465Sdelphij        flags |= X509_V_FLAG_EXPLICIT_POLICY;
2145296465Sdelphij    else if (!strcmp(arg, "-x509_strict"))
2146296465Sdelphij        flags |= X509_V_FLAG_X509_STRICT;
2147296465Sdelphij    else if (!strcmp(arg, "-policy_print"))
2148296465Sdelphij        flags |= X509_V_FLAG_NOTIFY_POLICY;
2149296465Sdelphij    else if (!strcmp(arg, "-check_ss_sig"))
2150296465Sdelphij        flags |= X509_V_FLAG_CHECK_SS_SIGNATURE;
2151296465Sdelphij    else
2152296465Sdelphij        return 0;
2153160814Ssimon
2154296465Sdelphij    if (*badarg) {
2155296465Sdelphij        if (*pm)
2156296465Sdelphij            X509_VERIFY_PARAM_free(*pm);
2157296465Sdelphij        *pm = NULL;
2158296465Sdelphij        goto end;
2159296465Sdelphij    }
2160160814Ssimon
2161296465Sdelphij    if (!*pm && !(*pm = X509_VERIFY_PARAM_new())) {
2162296465Sdelphij        *badarg = 1;
2163296465Sdelphij        goto end;
2164296465Sdelphij    }
2165160814Ssimon
2166296465Sdelphij    if (otmp)
2167296465Sdelphij        X509_VERIFY_PARAM_add0_policy(*pm, otmp);
2168296465Sdelphij    if (flags)
2169296465Sdelphij        X509_VERIFY_PARAM_set_flags(*pm, flags);
2170160814Ssimon
2171296465Sdelphij    if (purpose)
2172296465Sdelphij        X509_VERIFY_PARAM_set_purpose(*pm, purpose);
2173160814Ssimon
2174296465Sdelphij end:
2175160814Ssimon
2176296465Sdelphij    (*pargs)++;
2177160814Ssimon
2178296465Sdelphij    if (pargc)
2179296465Sdelphij        *pargc -= *pargs - oldargs;
2180160814Ssimon
2181296465Sdelphij    return 1;
2182160814Ssimon
2183296465Sdelphij}
2184160814Ssimon
2185160814Ssimonstatic void nodes_print(BIO *out, const char *name,
2186296465Sdelphij                        STACK_OF(X509_POLICY_NODE) *nodes)
2187296465Sdelphij{
2188296465Sdelphij    X509_POLICY_NODE *node;
2189296465Sdelphij    int i;
2190296465Sdelphij    BIO_printf(out, "%s Policies:", name);
2191296465Sdelphij    if (nodes) {
2192296465Sdelphij        BIO_puts(out, "\n");
2193296465Sdelphij        for (i = 0; i < sk_X509_POLICY_NODE_num(nodes); i++) {
2194296465Sdelphij            node = sk_X509_POLICY_NODE_value(nodes, i);
2195296465Sdelphij            X509_POLICY_NODE_print(out, node, 2);
2196296465Sdelphij        }
2197296465Sdelphij    } else
2198296465Sdelphij        BIO_puts(out, " <empty>\n");
2199296465Sdelphij}
2200160814Ssimon
2201160814Ssimonvoid policies_print(BIO *out, X509_STORE_CTX *ctx)
2202296465Sdelphij{
2203296465Sdelphij    X509_POLICY_TREE *tree;
2204296465Sdelphij    int explicit_policy;
2205296465Sdelphij    int free_out = 0;
2206296465Sdelphij    if (out == NULL) {
2207296465Sdelphij        out = BIO_new_fp(stderr, BIO_NOCLOSE);
2208296465Sdelphij        free_out = 1;
2209296465Sdelphij    }
2210296465Sdelphij    tree = X509_STORE_CTX_get0_policy_tree(ctx);
2211296465Sdelphij    explicit_policy = X509_STORE_CTX_get_explicit_policy(ctx);
2212160814Ssimon
2213296465Sdelphij    BIO_printf(out, "Require explicit Policy: %s\n",
2214296465Sdelphij               explicit_policy ? "True" : "False");
2215160814Ssimon
2216296465Sdelphij    nodes_print(out, "Authority", X509_policy_tree_get0_policies(tree));
2217296465Sdelphij    nodes_print(out, "User", X509_policy_tree_get0_user_policies(tree));
2218296465Sdelphij    if (free_out)
2219296465Sdelphij        BIO_free(out);
2220296465Sdelphij}
2221194206Ssimon
2222194206Ssimon#ifndef OPENSSL_NO_JPAKE
2223194206Ssimon
2224194206Ssimonstatic JPAKE_CTX *jpake_init(const char *us, const char *them,
2225296465Sdelphij                             const char *secret)
2226296465Sdelphij{
2227296465Sdelphij    BIGNUM *p = NULL;
2228296465Sdelphij    BIGNUM *g = NULL;
2229296465Sdelphij    BIGNUM *q = NULL;
2230296465Sdelphij    BIGNUM *bnsecret = BN_new();
2231296465Sdelphij    JPAKE_CTX *ctx;
2232194206Ssimon
2233296465Sdelphij    /* Use a safe prime for p (that we found earlier) */
2234296465Sdelphij    BN_hex2bn(&p,
2235296465Sdelphij              "F9E5B365665EA7A05A9C534502780FEE6F1AB5BD4F49947FD036DBD7E905269AF46EF28B0FC07487EE4F5D20FB3C0AF8E700F3A2FA3414970CBED44FEDFF80CE78D800F184BB82435D137AADA2C6C16523247930A63B85661D1FC817A51ACD96168E95898A1F83A79FFB529368AA7833ABD1B0C3AEDDB14D2E1A2F71D99F763F");
2236296465Sdelphij    g = BN_new();
2237296465Sdelphij    BN_set_word(g, 2);
2238296465Sdelphij    q = BN_new();
2239296465Sdelphij    BN_rshift1(q, p);
2240194206Ssimon
2241296465Sdelphij    BN_bin2bn((const unsigned char *)secret, strlen(secret), bnsecret);
2242194206Ssimon
2243296465Sdelphij    ctx = JPAKE_CTX_new(us, them, p, g, q, bnsecret);
2244296465Sdelphij    BN_free(bnsecret);
2245296465Sdelphij    BN_free(q);
2246296465Sdelphij    BN_free(g);
2247296465Sdelphij    BN_free(p);
2248194206Ssimon
2249296465Sdelphij    return ctx;
2250296465Sdelphij}
2251194206Ssimon
2252194206Ssimonstatic void jpake_send_part(BIO *conn, const JPAKE_STEP_PART *p)
2253296465Sdelphij{
2254296465Sdelphij    BN_print(conn, p->gx);
2255296465Sdelphij    BIO_puts(conn, "\n");
2256296465Sdelphij    BN_print(conn, p->zkpx.gr);
2257296465Sdelphij    BIO_puts(conn, "\n");
2258296465Sdelphij    BN_print(conn, p->zkpx.b);
2259296465Sdelphij    BIO_puts(conn, "\n");
2260296465Sdelphij}
2261194206Ssimon
2262194206Ssimonstatic void jpake_send_step1(BIO *bconn, JPAKE_CTX *ctx)
2263296465Sdelphij{
2264296465Sdelphij    JPAKE_STEP1 s1;
2265194206Ssimon
2266296465Sdelphij    JPAKE_STEP1_init(&s1);
2267296465Sdelphij    JPAKE_STEP1_generate(&s1, ctx);
2268296465Sdelphij    jpake_send_part(bconn, &s1.p1);
2269296465Sdelphij    jpake_send_part(bconn, &s1.p2);
2270296465Sdelphij    (void)BIO_flush(bconn);
2271296465Sdelphij    JPAKE_STEP1_release(&s1);
2272296465Sdelphij}
2273194206Ssimon
2274194206Ssimonstatic void jpake_send_step2(BIO *bconn, JPAKE_CTX *ctx)
2275296465Sdelphij{
2276296465Sdelphij    JPAKE_STEP2 s2;
2277194206Ssimon
2278296465Sdelphij    JPAKE_STEP2_init(&s2);
2279296465Sdelphij    JPAKE_STEP2_generate(&s2, ctx);
2280296465Sdelphij    jpake_send_part(bconn, &s2);
2281296465Sdelphij    (void)BIO_flush(bconn);
2282296465Sdelphij    JPAKE_STEP2_release(&s2);
2283296465Sdelphij}
2284194206Ssimon
2285194206Ssimonstatic void jpake_send_step3a(BIO *bconn, JPAKE_CTX *ctx)
2286296465Sdelphij{
2287296465Sdelphij    JPAKE_STEP3A s3a;
2288194206Ssimon
2289296465Sdelphij    JPAKE_STEP3A_init(&s3a);
2290296465Sdelphij    JPAKE_STEP3A_generate(&s3a, ctx);
2291296465Sdelphij    BIO_write(bconn, s3a.hhk, sizeof s3a.hhk);
2292296465Sdelphij    (void)BIO_flush(bconn);
2293296465Sdelphij    JPAKE_STEP3A_release(&s3a);
2294296465Sdelphij}
2295194206Ssimon
2296194206Ssimonstatic void jpake_send_step3b(BIO *bconn, JPAKE_CTX *ctx)
2297296465Sdelphij{
2298296465Sdelphij    JPAKE_STEP3B s3b;
2299194206Ssimon
2300296465Sdelphij    JPAKE_STEP3B_init(&s3b);
2301296465Sdelphij    JPAKE_STEP3B_generate(&s3b, ctx);
2302296465Sdelphij    BIO_write(bconn, s3b.hk, sizeof s3b.hk);
2303296465Sdelphij    (void)BIO_flush(bconn);
2304296465Sdelphij    JPAKE_STEP3B_release(&s3b);
2305296465Sdelphij}
2306194206Ssimon
2307194206Ssimonstatic void readbn(BIGNUM **bn, BIO *bconn)
2308296465Sdelphij{
2309296465Sdelphij    char buf[10240];
2310296465Sdelphij    int l;
2311194206Ssimon
2312296465Sdelphij    l = BIO_gets(bconn, buf, sizeof buf);
2313296465Sdelphij    assert(l > 0);
2314296465Sdelphij    assert(buf[l - 1] == '\n');
2315296465Sdelphij    buf[l - 1] = '\0';
2316296465Sdelphij    BN_hex2bn(bn, buf);
2317296465Sdelphij}
2318194206Ssimon
2319194206Ssimonstatic void jpake_receive_part(JPAKE_STEP_PART *p, BIO *bconn)
2320296465Sdelphij{
2321296465Sdelphij    readbn(&p->gx, bconn);
2322296465Sdelphij    readbn(&p->zkpx.gr, bconn);
2323296465Sdelphij    readbn(&p->zkpx.b, bconn);
2324296465Sdelphij}
2325194206Ssimon
2326194206Ssimonstatic void jpake_receive_step1(JPAKE_CTX *ctx, BIO *bconn)
2327296465Sdelphij{
2328296465Sdelphij    JPAKE_STEP1 s1;
2329194206Ssimon
2330296465Sdelphij    JPAKE_STEP1_init(&s1);
2331296465Sdelphij    jpake_receive_part(&s1.p1, bconn);
2332296465Sdelphij    jpake_receive_part(&s1.p2, bconn);
2333296465Sdelphij    if (!JPAKE_STEP1_process(ctx, &s1)) {
2334296465Sdelphij        ERR_print_errors(bio_err);
2335296465Sdelphij        exit(1);
2336296465Sdelphij    }
2337296465Sdelphij    JPAKE_STEP1_release(&s1);
2338296465Sdelphij}
2339194206Ssimon
2340194206Ssimonstatic void jpake_receive_step2(JPAKE_CTX *ctx, BIO *bconn)
2341296465Sdelphij{
2342296465Sdelphij    JPAKE_STEP2 s2;
2343194206Ssimon
2344296465Sdelphij    JPAKE_STEP2_init(&s2);
2345296465Sdelphij    jpake_receive_part(&s2, bconn);
2346296465Sdelphij    if (!JPAKE_STEP2_process(ctx, &s2)) {
2347296465Sdelphij        ERR_print_errors(bio_err);
2348296465Sdelphij        exit(1);
2349296465Sdelphij    }
2350296465Sdelphij    JPAKE_STEP2_release(&s2);
2351296465Sdelphij}
2352194206Ssimon
2353194206Ssimonstatic void jpake_receive_step3a(JPAKE_CTX *ctx, BIO *bconn)
2354296465Sdelphij{
2355296465Sdelphij    JPAKE_STEP3A s3a;
2356296465Sdelphij    int l;
2357194206Ssimon
2358296465Sdelphij    JPAKE_STEP3A_init(&s3a);
2359296465Sdelphij    l = BIO_read(bconn, s3a.hhk, sizeof s3a.hhk);
2360296465Sdelphij    assert(l == sizeof s3a.hhk);
2361296465Sdelphij    if (!JPAKE_STEP3A_process(ctx, &s3a)) {
2362296465Sdelphij        ERR_print_errors(bio_err);
2363296465Sdelphij        exit(1);
2364296465Sdelphij    }
2365296465Sdelphij    JPAKE_STEP3A_release(&s3a);
2366296465Sdelphij}
2367194206Ssimon
2368194206Ssimonstatic void jpake_receive_step3b(JPAKE_CTX *ctx, BIO *bconn)
2369296465Sdelphij{
2370296465Sdelphij    JPAKE_STEP3B s3b;
2371296465Sdelphij    int l;
2372194206Ssimon
2373296465Sdelphij    JPAKE_STEP3B_init(&s3b);
2374296465Sdelphij    l = BIO_read(bconn, s3b.hk, sizeof s3b.hk);
2375296465Sdelphij    assert(l == sizeof s3b.hk);
2376296465Sdelphij    if (!JPAKE_STEP3B_process(ctx, &s3b)) {
2377296465Sdelphij        ERR_print_errors(bio_err);
2378296465Sdelphij        exit(1);
2379296465Sdelphij    }
2380296465Sdelphij    JPAKE_STEP3B_release(&s3b);
2381296465Sdelphij}
2382194206Ssimon
2383194206Ssimonvoid jpake_client_auth(BIO *out, BIO *conn, const char *secret)
2384296465Sdelphij{
2385296465Sdelphij    JPAKE_CTX *ctx;
2386296465Sdelphij    BIO *bconn;
2387194206Ssimon
2388296465Sdelphij    BIO_puts(out, "Authenticating with JPAKE\n");
2389194206Ssimon
2390296465Sdelphij    ctx = jpake_init("client", "server", secret);
2391194206Ssimon
2392296465Sdelphij    bconn = BIO_new(BIO_f_buffer());
2393296465Sdelphij    BIO_push(bconn, conn);
2394194206Ssimon
2395296465Sdelphij    jpake_send_step1(bconn, ctx);
2396296465Sdelphij    jpake_receive_step1(ctx, bconn);
2397296465Sdelphij    jpake_send_step2(bconn, ctx);
2398296465Sdelphij    jpake_receive_step2(ctx, bconn);
2399296465Sdelphij    jpake_send_step3a(bconn, ctx);
2400296465Sdelphij    jpake_receive_step3b(ctx, bconn);
2401194206Ssimon
2402296465Sdelphij    /*
2403296465Sdelphij     * The problem is that you must use the derived key in the
2404296465Sdelphij     * session key or you are subject to man-in-the-middle
2405296465Sdelphij     * attacks.
2406296465Sdelphij     */
2407296465Sdelphij    BIO_puts(out, "JPAKE authentication succeeded (N.B. This version can"
2408296465Sdelphij             " be MitMed. See the version in HEAD for how to do it"
2409296465Sdelphij             " properly)\n");
2410194206Ssimon
2411296465Sdelphij    BIO_pop(bconn);
2412296465Sdelphij    BIO_free(bconn);
2413296465Sdelphij}
2414194206Ssimon
2415194206Ssimonvoid jpake_server_auth(BIO *out, BIO *conn, const char *secret)
2416296465Sdelphij{
2417296465Sdelphij    JPAKE_CTX *ctx;
2418296465Sdelphij    BIO *bconn;
2419194206Ssimon
2420296465Sdelphij    BIO_puts(out, "Authenticating with JPAKE\n");
2421194206Ssimon
2422296465Sdelphij    ctx = jpake_init("server", "client", secret);
2423194206Ssimon
2424296465Sdelphij    bconn = BIO_new(BIO_f_buffer());
2425296465Sdelphij    BIO_push(bconn, conn);
2426194206Ssimon
2427296465Sdelphij    jpake_receive_step1(ctx, bconn);
2428296465Sdelphij    jpake_send_step1(bconn, ctx);
2429296465Sdelphij    jpake_receive_step2(ctx, bconn);
2430296465Sdelphij    jpake_send_step2(bconn, ctx);
2431296465Sdelphij    jpake_receive_step3a(ctx, bconn);
2432296465Sdelphij    jpake_send_step3b(bconn, ctx);
2433194206Ssimon
2434296465Sdelphij    /*
2435296465Sdelphij     * The problem is that you must use the derived key in the
2436296465Sdelphij     * session key or you are subject to man-in-the-middle
2437296465Sdelphij     * attacks.
2438296465Sdelphij     */
2439296465Sdelphij    BIO_puts(out, "JPAKE authentication succeeded (N.B. This version can"
2440296465Sdelphij             " be MitMed. See the version in HEAD for how to do it"
2441296465Sdelphij             " properly)\n");
2442194206Ssimon
2443296465Sdelphij    BIO_pop(bconn);
2444296465Sdelphij    BIO_free(bconn);
2445296465Sdelphij}
2446194206Ssimon
2447194206Ssimon#endif
2448