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

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

1.1     ! jsing       1: /* $OpenBSD: engine.c,v 1.27 2014/07/14 00:35:10 deraadt Exp $ */
        !             2: /* Written by Richard Levitte <richard@levitte.org> for the OpenSSL
        !             3:  * project 2000.
        !             4:  */
        !             5: /* ====================================================================
        !             6:  * Copyright (c) 2000 The OpenSSL Project.  All rights reserved.
        !             7:  *
        !             8:  * Redistribution and use in source and binary forms, with or without
        !             9:  * modification, are permitted provided that the following conditions
        !            10:  * are met:
        !            11:  *
        !            12:  * 1. Redistributions of source code must retain the above copyright
        !            13:  *    notice, this list of conditions and the following disclaimer.
        !            14:  *
        !            15:  * 2. Redistributions in binary form must reproduce the above copyright
        !            16:  *    notice, this list of conditions and the following disclaimer in
        !            17:  *    the documentation and/or other materials provided with the
        !            18:  *    distribution.
        !            19:  *
        !            20:  * 3. All advertising materials mentioning features or use of this
        !            21:  *    software must display the following acknowledgment:
        !            22:  *    "This product includes software developed by the OpenSSL Project
        !            23:  *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
        !            24:  *
        !            25:  * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
        !            26:  *    endorse or promote products derived from this software without
        !            27:  *    prior written permission. For written permission, please contact
        !            28:  *    licensing@OpenSSL.org.
        !            29:  *
        !            30:  * 5. Products derived from this software may not be called "OpenSSL"
        !            31:  *    nor may "OpenSSL" appear in their names without prior written
        !            32:  *    permission of the OpenSSL Project.
        !            33:  *
        !            34:  * 6. Redistributions of any form whatsoever must retain the following
        !            35:  *    acknowledgment:
        !            36:  *    "This product includes software developed by the OpenSSL Project
        !            37:  *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
        !            38:  *
        !            39:  * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
        !            40:  * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
        !            41:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
        !            42:  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
        !            43:  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
        !            44:  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
        !            45:  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
        !            46:  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
        !            47:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
        !            48:  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
        !            49:  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
        !            50:  * OF THE POSSIBILITY OF SUCH DAMAGE.
        !            51:  * ====================================================================
        !            52:  *
        !            53:  * This product includes cryptographic software written by Eric Young
        !            54:  * (eay@cryptsoft.com).  This product includes software written by Tim
        !            55:  * Hudson (tjh@cryptsoft.com).
        !            56:  *
        !            57:  */
        !            58:
        !            59: #include <stdio.h>
        !            60: #include <stdlib.h>
        !            61: #include <string.h>
        !            62:
        !            63: #include "apps.h"
        !            64:
        !            65: #ifndef OPENSSL_NO_ENGINE
        !            66: #include <openssl/engine.h>
        !            67: #include <openssl/err.h>
        !            68: #include <openssl/ssl.h>
        !            69:
        !            70: static const char *engine_usage[] = {
        !            71:        "usage: engine opts [engine ...]\n",
        !            72:        " -v[v[v[v]]] - verbose mode, for each engine, list its 'control commands'\n",
        !            73:        "               -vv will additionally display each command's description\n",
        !            74:        "               -vvv will also add the input flags for each command\n",
        !            75:        "               -vvvv will also show internal input flags\n",
        !            76:        " -c          - for each engine, also list the capabilities\n",
        !            77:        " -t[t]       - for each engine, check that they are really available\n",
        !            78:        "               -tt will display error trace for unavailable engines\n",
        !            79:        " -pre <cmd>  - runs command 'cmd' against the ENGINE before any attempts\n",
        !            80:        "               to load it (if -t is used)\n",
        !            81:        " -post <cmd> - runs command 'cmd' against the ENGINE after loading it\n",
        !            82:        "               (only used if -t is also provided)\n",
        !            83:        " NB: -pre and -post will be applied to all ENGINEs supplied on the command\n",
        !            84:        " line, or all supported ENGINEs if none are specified.\n",
        !            85:        " Eg. '-pre \"SO_PATH:/lib/libdriver.so\"' calls command \"SO_PATH\" with\n",
        !            86:        " argument \"/lib/libdriver.so\".\n",
        !            87:        NULL
        !            88: };
        !            89:
        !            90: static void
        !            91: identity(char *ptr)
        !            92: {
        !            93:        return;
        !            94: }
        !            95:
        !            96: static int
        !            97: append_buf(char **buf, const char *s, int *size, int step)
        !            98: {
        !            99:        int l = strlen(s);
        !           100:
        !           101:        if (*buf == NULL) {
        !           102:                *size = step;
        !           103:                *buf = malloc(*size);
        !           104:                if (*buf == NULL)
        !           105:                        return 0;
        !           106:                **buf = '\0';
        !           107:        }
        !           108:        if (**buf != '\0')
        !           109:                l += 2;         /* ", " */
        !           110:
        !           111:        if (strlen(*buf) + strlen(s) >= (unsigned int) *size) {
        !           112:                *size += step;
        !           113:                *buf = realloc(*buf, *size);
        !           114:        }
        !           115:        if (*buf == NULL)
        !           116:                return 0;
        !           117:
        !           118:        if (**buf != '\0')
        !           119:                strlcat(*buf, ", ", *size);
        !           120:        strlcat(*buf, s, *size);
        !           121:
        !           122:        return 1;
        !           123: }
        !           124:
        !           125: static int
        !           126: util_flags(BIO * bio_out, unsigned int flags, const char *indent)
        !           127: {
        !           128:        int started = 0, err = 0;
        !           129:        /* Indent before displaying input flags */
        !           130:        BIO_printf(bio_out, "%s%s(input flags): ", indent, indent);
        !           131:        if (flags == 0) {
        !           132:                BIO_printf(bio_out, "<no flags>\n");
        !           133:                return 1;
        !           134:        }
        !           135:        /*
        !           136:         * If the object is internal, mark it in a way that shows instead of
        !           137:         * having it part of all the other flags, even if it really is.
        !           138:         */
        !           139:        if (flags & ENGINE_CMD_FLAG_INTERNAL) {
        !           140:                BIO_printf(bio_out, "[Internal] ");
        !           141:        }
        !           142:        if (flags & ENGINE_CMD_FLAG_NUMERIC) {
        !           143:                BIO_printf(bio_out, "NUMERIC");
        !           144:                started = 1;
        !           145:        }
        !           146:        /*
        !           147:         * Now we check that no combinations of the mutually exclusive
        !           148:         * NUMERIC, STRING, and NO_INPUT flags have been used. Future flags
        !           149:         * that can be OR'd together with these would need to added after
        !           150:         * these to preserve the testing logic.
        !           151:         */
        !           152:        if (flags & ENGINE_CMD_FLAG_STRING) {
        !           153:                if (started) {
        !           154:                        BIO_printf(bio_out, "|");
        !           155:                        err = 1;
        !           156:                }
        !           157:                BIO_printf(bio_out, "STRING");
        !           158:                started = 1;
        !           159:        }
        !           160:        if (flags & ENGINE_CMD_FLAG_NO_INPUT) {
        !           161:                if (started) {
        !           162:                        BIO_printf(bio_out, "|");
        !           163:                        err = 1;
        !           164:                }
        !           165:                BIO_printf(bio_out, "NO_INPUT");
        !           166:                started = 1;
        !           167:        }
        !           168:        /* Check for unknown flags */
        !           169:        flags = flags & ~ENGINE_CMD_FLAG_NUMERIC &
        !           170:            ~ENGINE_CMD_FLAG_STRING &
        !           171:            ~ENGINE_CMD_FLAG_NO_INPUT &
        !           172:            ~ENGINE_CMD_FLAG_INTERNAL;
        !           173:        if (flags) {
        !           174:                if (started)
        !           175:                        BIO_printf(bio_out, "|");
        !           176:                BIO_printf(bio_out, "<0x%04X>", flags);
        !           177:        }
        !           178:        if (err)
        !           179:                BIO_printf(bio_out, "  <illegal flags!>");
        !           180:        BIO_printf(bio_out, "\n");
        !           181:        return 1;
        !           182: }
        !           183:
        !           184: static int
        !           185: util_verbose(ENGINE * e, int verbose, BIO * bio_out, const char *indent)
        !           186: {
        !           187:        static const int line_wrap = 78;
        !           188:        int num;
        !           189:        int ret = 0;
        !           190:        char *name = NULL;
        !           191:        char *desc = NULL;
        !           192:        int flags;
        !           193:        int xpos = 0;
        !           194:        STACK_OF(OPENSSL_STRING) * cmds = NULL;
        !           195:        if (!ENGINE_ctrl(e, ENGINE_CTRL_HAS_CTRL_FUNCTION, 0, NULL, NULL) ||
        !           196:            ((num = ENGINE_ctrl(e, ENGINE_CTRL_GET_FIRST_CMD_TYPE,
        !           197:                        0, NULL, NULL)) <= 0)) {
        !           198: #if 0
        !           199:                BIO_printf(bio_out, "%s<no control commands>\n", indent);
        !           200: #endif
        !           201:                return 1;
        !           202:        }
        !           203:        cmds = sk_OPENSSL_STRING_new_null();
        !           204:
        !           205:        if (!cmds)
        !           206:                goto err;
        !           207:        do {
        !           208:                int len;
        !           209:                /* Get the command input flags */
        !           210:                if ((flags = ENGINE_ctrl(e, ENGINE_CTRL_GET_CMD_FLAGS, num,
        !           211:                            NULL, NULL)) < 0)
        !           212:                        goto err;
        !           213:                if (!(flags & ENGINE_CMD_FLAG_INTERNAL) || verbose >= 4) {
        !           214:                        /* Get the command name */
        !           215:                        if ((len = ENGINE_ctrl(e, ENGINE_CTRL_GET_NAME_LEN_FROM_CMD, num,
        !           216:                                    NULL, NULL)) <= 0)
        !           217:                                goto err;
        !           218:                        if ((name = malloc(len + 1)) == NULL)
        !           219:                                goto err;
        !           220:                        if (ENGINE_ctrl(e, ENGINE_CTRL_GET_NAME_FROM_CMD, num, name,
        !           221:                                NULL) <= 0)
        !           222:                                goto err;
        !           223:                        /* Get the command description */
        !           224:                        if ((len = ENGINE_ctrl(e, ENGINE_CTRL_GET_DESC_LEN_FROM_CMD, num,
        !           225:                                    NULL, NULL)) < 0)
        !           226:                                goto err;
        !           227:                        if (len > 0) {
        !           228:                                if ((desc = malloc(len + 1)) == NULL)
        !           229:                                        goto err;
        !           230:                                if (ENGINE_ctrl(e, ENGINE_CTRL_GET_DESC_FROM_CMD, num, desc,
        !           231:                                        NULL) <= 0)
        !           232:                                        goto err;
        !           233:                        }
        !           234:                        /* Now decide on the output */
        !           235:                        if (xpos == 0)
        !           236:                                /* Do an indent */
        !           237:                                xpos = BIO_puts(bio_out, indent);
        !           238:                        else
        !           239:                                /* Otherwise prepend a ", " */
        !           240:                                xpos += BIO_printf(bio_out, ", ");
        !           241:                        if (verbose == 1) {
        !           242:                                /* We're just listing names, comma-delimited */
        !           243:                                if ((xpos > (int) strlen(indent)) &&
        !           244:                                    (xpos + (int) strlen(name) > line_wrap)) {
        !           245:                                        BIO_printf(bio_out, "\n");
        !           246:                                        xpos = BIO_puts(bio_out, indent);
        !           247:                                }
        !           248:                                xpos += BIO_printf(bio_out, "%s", name);
        !           249:                        } else {
        !           250:                                /* We're listing names plus descriptions */
        !           251:                                BIO_printf(bio_out, "%s: %s\n", name,
        !           252:                                    (desc == NULL) ? "<no description>" : desc);
        !           253:                                /* ... and sometimes input flags */
        !           254:                                if ((verbose >= 3) && !util_flags(bio_out, flags,
        !           255:                                        indent))
        !           256:                                        goto err;
        !           257:                                xpos = 0;
        !           258:                        }
        !           259:                }
        !           260:                free(name);
        !           261:                name = NULL;
        !           262:                free(desc);
        !           263:                desc = NULL;
        !           264:
        !           265:                /* Move to the next command */
        !           266:                num = ENGINE_ctrl(e, ENGINE_CTRL_GET_NEXT_CMD_TYPE,
        !           267:                    num, NULL, NULL);
        !           268:        } while (num > 0);
        !           269:        if (xpos > 0)
        !           270:                BIO_printf(bio_out, "\n");
        !           271:        ret = 1;
        !           272: err:
        !           273:        if (cmds)
        !           274:                sk_OPENSSL_STRING_pop_free(cmds, identity);
        !           275:        free(name);
        !           276:        free(desc);
        !           277:        return ret;
        !           278: }
        !           279:
        !           280: static void
        !           281: util_do_cmds(ENGINE * e, STACK_OF(OPENSSL_STRING) * cmds,
        !           282:     BIO * bio_out, const char *indent)
        !           283: {
        !           284:        int loop, res, num = sk_OPENSSL_STRING_num(cmds);
        !           285:
        !           286:        if (num < 0) {
        !           287:                BIO_printf(bio_out, "[Error]: internal stack error\n");
        !           288:                return;
        !           289:        }
        !           290:        for (loop = 0; loop < num; loop++) {
        !           291:                char buf[256];
        !           292:                const char *cmd, *arg;
        !           293:                cmd = sk_OPENSSL_STRING_value(cmds, loop);
        !           294:                res = 1;        /* assume success */
        !           295:                /* Check if this command has no ":arg" */
        !           296:                if ((arg = strstr(cmd, ":")) == NULL) {
        !           297:                        if (!ENGINE_ctrl_cmd_string(e, cmd, NULL, 0))
        !           298:                                res = 0;
        !           299:                } else {
        !           300:                        if ((int) (arg - cmd) > 254) {
        !           301:                                BIO_printf(bio_out, "[Error]: command name too long\n");
        !           302:                                return;
        !           303:                        }
        !           304:                        memcpy(buf, cmd, (int) (arg - cmd));
        !           305:                        buf[arg - cmd] = '\0';
        !           306:                        arg++;  /* Move past the ":" */
        !           307:                        /* Call the command with the argument */
        !           308:                        if (!ENGINE_ctrl_cmd_string(e, buf, arg, 0))
        !           309:                                res = 0;
        !           310:                }
        !           311:                if (res)
        !           312:                        BIO_printf(bio_out, "[Success]: %s\n", cmd);
        !           313:                else {
        !           314:                        BIO_printf(bio_out, "[Failure]: %s\n", cmd);
        !           315:                        ERR_print_errors(bio_out);
        !           316:                }
        !           317:        }
        !           318: }
        !           319:
        !           320: int engine_main(int, char **);
        !           321:
        !           322: int
        !           323: engine_main(int argc, char **argv)
        !           324: {
        !           325:        int ret = 1, i;
        !           326:        const char **pp;
        !           327:        int verbose = 0, list_cap = 0, test_avail = 0, test_avail_noise = 0;
        !           328:        ENGINE *e;
        !           329:        STACK_OF(OPENSSL_STRING) * engines = sk_OPENSSL_STRING_new_null();
        !           330:        STACK_OF(OPENSSL_STRING) * pre_cmds = sk_OPENSSL_STRING_new_null();
        !           331:        STACK_OF(OPENSSL_STRING) * post_cmds = sk_OPENSSL_STRING_new_null();
        !           332:        int badops = 1;
        !           333:        BIO *bio_out = NULL;
        !           334:        const char *indent = "     ";
        !           335:
        !           336:        bio_out = BIO_new_fp(stdout, BIO_NOCLOSE);
        !           337:
        !           338:        argc--;
        !           339:        argv++;
        !           340:        while (argc >= 1) {
        !           341:                if (strncmp(*argv, "-v", 2) == 0) {
        !           342:                        if (strspn(*argv + 1, "v") < strlen(*argv + 1))
        !           343:                                goto skip_arg_loop;
        !           344:                        if ((verbose = strlen(*argv + 1)) > 4)
        !           345:                                goto skip_arg_loop;
        !           346:                } else if (strcmp(*argv, "-c") == 0)
        !           347:                        list_cap = 1;
        !           348:                else if (strncmp(*argv, "-t", 2) == 0) {
        !           349:                        test_avail = 1;
        !           350:                        if (strspn(*argv + 1, "t") < strlen(*argv + 1))
        !           351:                                goto skip_arg_loop;
        !           352:                        if ((test_avail_noise = strlen(*argv + 1) - 1) > 1)
        !           353:                                goto skip_arg_loop;
        !           354:                } else if (strcmp(*argv, "-pre") == 0) {
        !           355:                        argc--;
        !           356:                        argv++;
        !           357:                        if (argc == 0)
        !           358:                                goto skip_arg_loop;
        !           359:                        sk_OPENSSL_STRING_push(pre_cmds, *argv);
        !           360:                } else if (strcmp(*argv, "-post") == 0) {
        !           361:                        argc--;
        !           362:                        argv++;
        !           363:                        if (argc == 0)
        !           364:                                goto skip_arg_loop;
        !           365:                        sk_OPENSSL_STRING_push(post_cmds, *argv);
        !           366:                } else if ((strncmp(*argv, "-h", 2) == 0) ||
        !           367:                    (strcmp(*argv, "-?") == 0))
        !           368:                        goto skip_arg_loop;
        !           369:                else
        !           370:                        sk_OPENSSL_STRING_push(engines, *argv);
        !           371:                argc--;
        !           372:                argv++;
        !           373:        }
        !           374:        /* Looks like everything went OK */
        !           375:        badops = 0;
        !           376: skip_arg_loop:
        !           377:
        !           378:        if (badops) {
        !           379:                for (pp = engine_usage; (*pp != NULL); pp++)
        !           380:                        BIO_printf(bio_err, "%s", *pp);
        !           381:                goto end;
        !           382:        }
        !           383:        if (sk_OPENSSL_STRING_num(engines) == 0) {
        !           384:                for (e = ENGINE_get_first(); e != NULL; e = ENGINE_get_next(e)) {
        !           385:                        sk_OPENSSL_STRING_push(engines, (char *) ENGINE_get_id(e));
        !           386:                }
        !           387:        }
        !           388:        for (i = 0; i < sk_OPENSSL_STRING_num(engines); i++) {
        !           389:                const char *id = sk_OPENSSL_STRING_value(engines, i);
        !           390:                if ((e = ENGINE_by_id(id)) != NULL) {
        !           391:                        const char *name = ENGINE_get_name(e);
        !           392:                        /* Do "id" first, then "name". Easier to auto-parse. */
        !           393:                        BIO_printf(bio_out, "(%s) %s\n", id, name);
        !           394:                        util_do_cmds(e, pre_cmds, bio_out, indent);
        !           395:                        if (strcmp(ENGINE_get_id(e), id) != 0) {
        !           396:                                BIO_printf(bio_out, "Loaded: (%s) %s\n",
        !           397:                                    ENGINE_get_id(e), ENGINE_get_name(e));
        !           398:                        }
        !           399:                        if (list_cap) {
        !           400:                                int cap_size = 256;
        !           401:                                char *cap_buf = NULL;
        !           402:                                int k, n;
        !           403:                                const int *nids;
        !           404:                                ENGINE_CIPHERS_PTR fn_c;
        !           405:                                ENGINE_DIGESTS_PTR fn_d;
        !           406:                                ENGINE_PKEY_METHS_PTR fn_pk;
        !           407:
        !           408:                                if (ENGINE_get_RSA(e) != NULL
        !           409:                                    && !append_buf(&cap_buf, "RSA",
        !           410:                                        &cap_size, 256))
        !           411:                                        goto end;
        !           412:                                if (ENGINE_get_DSA(e) != NULL
        !           413:                                    && !append_buf(&cap_buf, "DSA",
        !           414:                                        &cap_size, 256))
        !           415:                                        goto end;
        !           416:                                if (ENGINE_get_DH(e) != NULL
        !           417:                                    && !append_buf(&cap_buf, "DH",
        !           418:                                        &cap_size, 256))
        !           419:                                        goto end;
        !           420:                                if (ENGINE_get_RAND(e) != NULL
        !           421:                                    && !append_buf(&cap_buf, "RAND",
        !           422:                                        &cap_size, 256))
        !           423:                                        goto end;
        !           424:
        !           425:                                fn_c = ENGINE_get_ciphers(e);
        !           426:                                if (!fn_c)
        !           427:                                        goto skip_ciphers;
        !           428:                                n = fn_c(e, NULL, &nids, 0);
        !           429:                                for (k = 0; k < n; ++k)
        !           430:                                        if (!append_buf(&cap_buf,
        !           431:                                                OBJ_nid2sn(nids[k]),
        !           432:                                                &cap_size, 256))
        !           433:                                                goto end;
        !           434:
        !           435:                skip_ciphers:
        !           436:                                fn_d = ENGINE_get_digests(e);
        !           437:                                if (!fn_d)
        !           438:                                        goto skip_digests;
        !           439:                                n = fn_d(e, NULL, &nids, 0);
        !           440:                                for (k = 0; k < n; ++k)
        !           441:                                        if (!append_buf(&cap_buf,
        !           442:                                                OBJ_nid2sn(nids[k]),
        !           443:                                                &cap_size, 256))
        !           444:                                                goto end;
        !           445:
        !           446:                skip_digests:
        !           447:                                fn_pk = ENGINE_get_pkey_meths(e);
        !           448:                                if (!fn_pk)
        !           449:                                        goto skip_pmeths;
        !           450:                                n = fn_pk(e, NULL, &nids, 0);
        !           451:                                for (k = 0; k < n; ++k)
        !           452:                                        if (!append_buf(&cap_buf,
        !           453:                                                OBJ_nid2sn(nids[k]),
        !           454:                                                &cap_size, 256))
        !           455:                                                goto end;
        !           456:                skip_pmeths:
        !           457:                                if (cap_buf && (*cap_buf != '\0'))
        !           458:                                        BIO_printf(bio_out, " [%s]\n", cap_buf);
        !           459:
        !           460:                                free(cap_buf);
        !           461:                        }
        !           462:                        if (test_avail) {
        !           463:                                BIO_printf(bio_out, "%s", indent);
        !           464:                                if (ENGINE_init(e)) {
        !           465:                                        BIO_printf(bio_out, "[ available ]\n");
        !           466:                                        util_do_cmds(e, post_cmds, bio_out, indent);
        !           467:                                        ENGINE_finish(e);
        !           468:                                } else {
        !           469:                                        BIO_printf(bio_out, "[ unavailable ]\n");
        !           470:                                        if (test_avail_noise)
        !           471:                                                ERR_print_errors_fp(stdout);
        !           472:                                        ERR_clear_error();
        !           473:                                }
        !           474:                        }
        !           475:                        if ((verbose > 0) && !util_verbose(e, verbose, bio_out, indent))
        !           476:                                goto end;
        !           477:                        ENGINE_free(e);
        !           478:                } else
        !           479:                        ERR_print_errors(bio_err);
        !           480:        }
        !           481:
        !           482:        ret = 0;
        !           483: end:
        !           484:
        !           485:        ERR_print_errors(bio_err);
        !           486:        sk_OPENSSL_STRING_pop_free(engines, identity);
        !           487:        sk_OPENSSL_STRING_pop_free(pre_cmds, identity);
        !           488:        sk_OPENSSL_STRING_pop_free(post_cmds, identity);
        !           489:        if (bio_out != NULL)
        !           490:                BIO_free_all(bio_out);
        !           491:
        !           492:        return (ret);
        !           493: }
        !           494: #endif