[BACK]Return to apps.c CVS log [TXT][DIR] Up to [local] / src / usr.bin / openssl

Annotation of src/usr.bin/openssl/apps.c, Revision 1.1

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