155714Skris/* apps/openssl.c */
255714Skris/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
355714Skris * All rights reserved.
455714Skris *
555714Skris * This package is an SSL implementation written
655714Skris * by Eric Young (eay@cryptsoft.com).
755714Skris * The implementation was written so as to conform with Netscapes SSL.
8296341Sdelphij *
955714Skris * This library is free for commercial and non-commercial use as long as
1055714Skris * the following conditions are aheared to.  The following conditions
1155714Skris * apply to all code found in this distribution, be it the RC4, RSA,
1255714Skris * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
1355714Skris * included with this distribution is covered by the same copyright terms
1455714Skris * except that the holder is Tim Hudson (tjh@cryptsoft.com).
15296341Sdelphij *
1655714Skris * Copyright remains Eric Young's, and as such any Copyright notices in
1755714Skris * the code are not to be removed.
1855714Skris * If this package is used in a product, Eric Young should be given attribution
1955714Skris * as the author of the parts of the library used.
2055714Skris * This can be in the form of a textual message at program startup or
2155714Skris * in documentation (online or textual) provided with the package.
22296341Sdelphij *
2355714Skris * Redistribution and use in source and binary forms, with or without
2455714Skris * modification, are permitted provided that the following conditions
2555714Skris * are met:
2655714Skris * 1. Redistributions of source code must retain the copyright
2755714Skris *    notice, this list of conditions and the following disclaimer.
2855714Skris * 2. Redistributions in binary form must reproduce the above copyright
2955714Skris *    notice, this list of conditions and the following disclaimer in the
3055714Skris *    documentation and/or other materials provided with the distribution.
3155714Skris * 3. All advertising materials mentioning features or use of this software
3255714Skris *    must display the following acknowledgement:
3355714Skris *    "This product includes cryptographic software written by
3455714Skris *     Eric Young (eay@cryptsoft.com)"
3555714Skris *    The word 'cryptographic' can be left out if the rouines from the library
3655714Skris *    being used are not cryptographic related :-).
37296341Sdelphij * 4. If you include any Windows specific code (or a derivative thereof) from
3855714Skris *    the apps directory (application code) you must include an acknowledgement:
3955714Skris *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
40296341Sdelphij *
4155714Skris * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
4255714Skris * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
4355714Skris * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
4455714Skris * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
4555714Skris * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
4655714Skris * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
4755714Skris * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
4855714Skris * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
4955714Skris * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
5055714Skris * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
5155714Skris * SUCH DAMAGE.
52296341Sdelphij *
5355714Skris * The licence and distribution terms for any publically available version or
5455714Skris * derivative of this code cannot be changed.  i.e. this code cannot simply be
5555714Skris * copied and put under another distribution licence
5655714Skris * [including the GNU Public Licence.]
5755714Skris */
58109998Smarkm/* ====================================================================
59162911Ssimon * Copyright (c) 1998-2006 The OpenSSL Project.  All rights reserved.
60109998Smarkm *
61109998Smarkm * Redistribution and use in source and binary forms, with or without
62109998Smarkm * modification, are permitted provided that the following conditions
63109998Smarkm * are met:
64109998Smarkm *
65109998Smarkm * 1. Redistributions of source code must retain the above copyright
66296341Sdelphij *    notice, this list of conditions and the following disclaimer.
67109998Smarkm *
68109998Smarkm * 2. Redistributions in binary form must reproduce the above copyright
69109998Smarkm *    notice, this list of conditions and the following disclaimer in
70109998Smarkm *    the documentation and/or other materials provided with the
71109998Smarkm *    distribution.
72109998Smarkm *
73109998Smarkm * 3. All advertising materials mentioning features or use of this
74109998Smarkm *    software must display the following acknowledgment:
75109998Smarkm *    "This product includes software developed by the OpenSSL Project
76109998Smarkm *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
77109998Smarkm *
78109998Smarkm * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
79109998Smarkm *    endorse or promote products derived from this software without
80109998Smarkm *    prior written permission. For written permission, please contact
81109998Smarkm *    openssl-core@openssl.org.
82109998Smarkm *
83109998Smarkm * 5. Products derived from this software may not be called "OpenSSL"
84109998Smarkm *    nor may "OpenSSL" appear in their names without prior written
85109998Smarkm *    permission of the OpenSSL Project.
86109998Smarkm *
87109998Smarkm * 6. Redistributions of any form whatsoever must retain the following
88109998Smarkm *    acknowledgment:
89109998Smarkm *    "This product includes software developed by the OpenSSL Project
90109998Smarkm *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
91109998Smarkm *
92109998Smarkm * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
93109998Smarkm * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
94109998Smarkm * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
95109998Smarkm * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
96109998Smarkm * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
97109998Smarkm * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
98109998Smarkm * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
99109998Smarkm * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
100109998Smarkm * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
101109998Smarkm * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
102109998Smarkm * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
103109998Smarkm * OF THE POSSIBILITY OF SUCH DAMAGE.
104109998Smarkm * ====================================================================
105109998Smarkm *
106109998Smarkm * This product includes cryptographic software written by Eric Young
107109998Smarkm * (eay@cryptsoft.com).  This product includes software written by Tim
108109998Smarkm * Hudson (tjh@cryptsoft.com).
109109998Smarkm *
110109998Smarkm */
11155714Skris
11255714Skris#include <stdio.h>
11355714Skris#include <string.h>
11455714Skris#include <stdlib.h>
115296341Sdelphij#define OPENSSL_C               /* tells apps.h to use complete
116296341Sdelphij                                 * apps_startup() */
117109998Smarkm#include "apps.h"
11855714Skris#include <openssl/bio.h>
11955714Skris#include <openssl/crypto.h>
120264331Sjkim#include <openssl/rand.h>
12155714Skris#include <openssl/lhash.h>
12255714Skris#include <openssl/conf.h>
12355714Skris#include <openssl/x509.h>
12455714Skris#include <openssl/pem.h>
12555714Skris#include <openssl/ssl.h>
126111147Snectar#ifndef OPENSSL_NO_ENGINE
127296341Sdelphij# include <openssl/engine.h>
128111147Snectar#endif
129296341Sdelphij#define USE_SOCKETS             /* needed for the _O_BINARY defs in the MS
130296341Sdelphij                                 * world */
13159191Skris#include "progs.h"
13255714Skris#include "s_apps.h"
13355714Skris#include <openssl/err.h>
134238405Sjkim#ifdef OPENSSL_FIPS
135296341Sdelphij# include <openssl/fips.h>
136238405Sjkim#endif
13755714Skris
138296341Sdelphij/*
139296341Sdelphij * The LHASH callbacks ("hash" & "cmp") have been replaced by functions with
140296341Sdelphij * the base prototypes (we cast each variable inside the function to the
141296341Sdelphij * required type of "FUNCTION*"). This removes the necessity for
142296341Sdelphij * macro-generated wrapper functions.
143296341Sdelphij */
144109998Smarkm
145296341Sdelphijstatic LHASH_OF(FUNCTION) *prog_init(void);
146296341Sdelphijstatic int do_cmd(LHASH_OF(FUNCTION) *prog, int argc, char *argv[]);
147238405Sjkimstatic void list_pkey(BIO *out);
148238405Sjkimstatic void list_cipher(BIO *out);
149238405Sjkimstatic void list_md(BIO *out);
150296341Sdelphijchar *default_config_file = NULL;
15155714Skris
15255714Skris/* Make sure there is only one when MONOLITH is defined */
15355714Skris#ifdef MONOLITH
154296341SdelphijCONF *config = NULL;
155296341SdelphijBIO *bio_err = NULL;
15655714Skris#endif
15755714Skris
158109998Smarkmstatic void lock_dbg_cb(int mode, int type, const char *file, int line)
159296341Sdelphij{
160296341Sdelphij    static int modes[CRYPTO_NUM_LOCKS]; /* = {0, 0, ... } */
161296341Sdelphij    const char *errstr = NULL;
162296341Sdelphij    int rw;
163109998Smarkm
164296341Sdelphij    rw = mode & (CRYPTO_READ | CRYPTO_WRITE);
165296341Sdelphij    if (!((rw == CRYPTO_READ) || (rw == CRYPTO_WRITE))) {
166296341Sdelphij        errstr = "invalid mode";
167296341Sdelphij        goto err;
168296341Sdelphij    }
169109998Smarkm
170296341Sdelphij    if (type < 0 || type >= CRYPTO_NUM_LOCKS) {
171296341Sdelphij        errstr = "type out of bounds";
172296341Sdelphij        goto err;
173296341Sdelphij    }
174109998Smarkm
175296341Sdelphij    if (mode & CRYPTO_LOCK) {
176296341Sdelphij        if (modes[type]) {
177296341Sdelphij            errstr = "already locked";
178296341Sdelphij            /*
179296341Sdelphij             * must not happen in a single-threaded program (would deadlock)
180296341Sdelphij             */
181296341Sdelphij            goto err;
182296341Sdelphij        }
183109998Smarkm
184296341Sdelphij        modes[type] = rw;
185296341Sdelphij    } else if (mode & CRYPTO_UNLOCK) {
186296341Sdelphij        if (!modes[type]) {
187296341Sdelphij            errstr = "not locked";
188296341Sdelphij            goto err;
189296341Sdelphij        }
190109998Smarkm
191296341Sdelphij        if (modes[type] != rw) {
192296341Sdelphij            errstr = (rw == CRYPTO_READ) ?
193296341Sdelphij                "CRYPTO_r_unlock on write lock" :
194296341Sdelphij                "CRYPTO_w_unlock on read lock";
195296341Sdelphij        }
196296341Sdelphij
197296341Sdelphij        modes[type] = 0;
198296341Sdelphij    } else {
199296341Sdelphij        errstr = "invalid mode";
200296341Sdelphij        goto err;
201296341Sdelphij    }
202296341Sdelphij
203109998Smarkm err:
204296341Sdelphij    if (errstr) {
205296341Sdelphij        /* we cannot use bio_err here */
206296341Sdelphij        fprintf(stderr,
207296341Sdelphij                "openssl (lock_dbg_cb): %s (mode=%d, type=%d) at %s:%d\n",
208296341Sdelphij                errstr, mode, type, file, line);
209296341Sdelphij    }
210296341Sdelphij}
211109998Smarkm
212238405Sjkim#if defined( OPENSSL_SYS_VMS) && (__INITIAL_POINTER_SIZE == 64)
213238405Sjkim# define ARGV _Argv
214238405Sjkim#else
215238405Sjkim# define ARGV Argv
216238405Sjkim#endif
217109998Smarkm
218238405Sjkimint main(int Argc, char *ARGV[])
219296341Sdelphij{
220296341Sdelphij    ARGS arg;
221296341Sdelphij#define PROG_NAME_SIZE  39
222296341Sdelphij    char pname[PROG_NAME_SIZE + 1];
223296341Sdelphij    FUNCTION f, *fp;
224296341Sdelphij    MS_STATIC const char *prompt;
225296341Sdelphij    MS_STATIC char buf[1024];
226296341Sdelphij    char *to_free = NULL;
227296341Sdelphij    int n, i, ret = 0;
228296341Sdelphij    int argc;
229296341Sdelphij    char **argv, *p;
230296341Sdelphij    LHASH_OF(FUNCTION) *prog = NULL;
231296341Sdelphij    long errline;
23255714Skris
233238405Sjkim#if defined( OPENSSL_SYS_VMS) && (__INITIAL_POINTER_SIZE == 64)
234296341Sdelphij    /*-
235296341Sdelphij     * 2011-03-22 SMS.
236296341Sdelphij     * If we have 32-bit pointers everywhere, then we're safe, and
237296341Sdelphij     * we bypass this mess, as on non-VMS systems.  (See ARGV,
238296341Sdelphij     * above.)
239296341Sdelphij     * Problem 1: Compaq/HP C before V7.3 always used 32-bit
240296341Sdelphij     * pointers for argv[].
241296341Sdelphij     * Fix 1: For a 32-bit argv[], when we're using 64-bit pointers
242296341Sdelphij     * everywhere else, we always allocate and use a 64-bit
243296341Sdelphij     * duplicate of argv[].
244296341Sdelphij     * Problem 2: Compaq/HP C V7.3 (Alpha, IA64) before ECO1 failed
245296341Sdelphij     * to NULL-terminate a 64-bit argv[].  (As this was written, the
246296341Sdelphij     * compiler ECO was available only on IA64.)
247296341Sdelphij     * Fix 2: Unless advised not to (VMS_TRUST_ARGV), we test a
248296341Sdelphij     * 64-bit argv[argc] for NULL, and, if necessary, use a
249296341Sdelphij     * (properly) NULL-terminated (64-bit) duplicate of argv[].
250296341Sdelphij     * The same code is used in either case to duplicate argv[].
251296341Sdelphij     * Some of these decisions could be handled in preprocessing,
252296341Sdelphij     * but the code tends to get even uglier, and the penalty for
253296341Sdelphij     * deciding at compile- or run-time is tiny.
254296341Sdelphij     */
255296341Sdelphij    char **Argv = NULL;
256296341Sdelphij    int free_Argv = 0;
257194206Ssimon
258296341Sdelphij    if ((sizeof(_Argv) < 8)     /* 32-bit argv[]. */
259238405Sjkim# if !defined( VMS_TRUST_ARGV)
260296341Sdelphij        || (_Argv[Argc] != NULL) /* Untrusted argv[argc] not NULL. */
261238405Sjkim# endif
262296341Sdelphij        ) {
263296341Sdelphij        int i;
264296341Sdelphij        Argv = OPENSSL_malloc((Argc + 1) * sizeof(char *));
265296341Sdelphij        if (Argv == NULL) {
266296341Sdelphij            ret = -1;
267296341Sdelphij            goto end;
268296341Sdelphij        }
269296341Sdelphij        for (i = 0; i < Argc; i++)
270296341Sdelphij            Argv[i] = _Argv[i];
271296341Sdelphij        Argv[Argc] = NULL;      /* Certain NULL termination. */
272296341Sdelphij        free_Argv = 1;
273296341Sdelphij    } else {
274296341Sdelphij        /*
275296341Sdelphij         * Use the known-good 32-bit argv[] (which needs the type cast to
276296341Sdelphij         * satisfy the compiler), or the trusted or tested-good 64-bit argv[]
277296341Sdelphij         * as-is.
278296341Sdelphij         */
279296341Sdelphij        Argv = (char **)_Argv;
280296341Sdelphij    }
281296341Sdelphij#endif                          /* defined( OPENSSL_SYS_VMS) &&
282296341Sdelphij                                 * (__INITIAL_POINTER_SIZE == 64) */
283194206Ssimon
284296341Sdelphij    arg.data = NULL;
285296341Sdelphij    arg.count = 0;
286238405Sjkim
287296341Sdelphij    if (bio_err == NULL)
288296341Sdelphij        if ((bio_err = BIO_new(BIO_s_file())) != NULL)
289296341Sdelphij            BIO_set_fp(bio_err, stderr, BIO_NOCLOSE | BIO_FP_TEXT);
29055714Skris
291296341Sdelphij    if (getenv("OPENSSL_DEBUG_MEMORY") != NULL) { /* if not defined, use
292296341Sdelphij                                                   * compiled-in library
293296341Sdelphij                                                   * defaults */
294296341Sdelphij        if (!(0 == strcmp(getenv("OPENSSL_DEBUG_MEMORY"), "off"))) {
295296341Sdelphij            CRYPTO_malloc_debug_init();
296296341Sdelphij            CRYPTO_set_mem_debug_options(V_CRYPTO_MDEBUG_ALL);
297296341Sdelphij        } else {
298296341Sdelphij            /* OPENSSL_DEBUG_MEMORY=off */
299296341Sdelphij            CRYPTO_set_mem_debug_functions(0, 0, 0, 0, 0);
300296341Sdelphij        }
301296341Sdelphij    }
302296341Sdelphij    CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_ON);
30355714Skris
304109998Smarkm#if 0
305296341Sdelphij    if (getenv("OPENSSL_DEBUG_LOCKING") != NULL)
306109998Smarkm#endif
307296341Sdelphij    {
308296341Sdelphij        CRYPTO_set_locking_callback(lock_dbg_cb);
309296341Sdelphij    }
310109998Smarkm
311296341Sdelphij    if (getenv("OPENSSL_FIPS")) {
312238405Sjkim#ifdef OPENSSL_FIPS
313296341Sdelphij        if (!FIPS_mode_set(1)) {
314296341Sdelphij            ERR_load_crypto_strings();
315296341Sdelphij            ERR_print_errors(BIO_new_fp(stderr, BIO_NOCLOSE));
316296341Sdelphij            EXIT(1);
317296341Sdelphij        }
318238405Sjkim#else
319296341Sdelphij        fprintf(stderr, "FIPS mode not supported.\n");
320296341Sdelphij        EXIT(1);
321238405Sjkim#endif
322296341Sdelphij    }
323238405Sjkim
324296341Sdelphij    apps_startup();
325109998Smarkm
326296341Sdelphij    /* Lets load up our environment a little */
327296341Sdelphij    p = getenv("OPENSSL_CONF");
328296341Sdelphij    if (p == NULL)
329296341Sdelphij        p = getenv("SSLEAY_CONF");
330296341Sdelphij    if (p == NULL)
331296341Sdelphij        p = to_free = make_config_name();
33255714Skris
333296341Sdelphij    default_config_file = p;
33455714Skris
335296341Sdelphij    config = NCONF_new(NULL);
336296341Sdelphij    i = NCONF_load(config, p, &errline);
337296341Sdelphij    if (i == 0) {
338296341Sdelphij        if (ERR_GET_REASON(ERR_peek_last_error())
339296341Sdelphij            == CONF_R_NO_SUCH_FILE) {
340296341Sdelphij            BIO_printf(bio_err, "WARNING: can't open config file: %s\n", p);
341296341Sdelphij            ERR_clear_error();
342296341Sdelphij            NCONF_free(config);
343296341Sdelphij            config = NULL;
344296341Sdelphij        } else {
345296341Sdelphij            ERR_print_errors(bio_err);
346296341Sdelphij            NCONF_free(config);
347296341Sdelphij            exit(1);
348296341Sdelphij        }
349296341Sdelphij    }
35055714Skris
351296341Sdelphij    prog = prog_init();
35255714Skris
353296341Sdelphij    /* first check the program name */
354296341Sdelphij    program_name(Argv[0], pname, sizeof pname);
35555714Skris
356296341Sdelphij    f.name = pname;
357296341Sdelphij    fp = lh_FUNCTION_retrieve(prog, &f);
358296341Sdelphij    if (fp != NULL) {
359296341Sdelphij        Argv[0] = pname;
360296341Sdelphij        ret = fp->func(Argc, Argv);
361296341Sdelphij        goto end;
362296341Sdelphij    }
36355714Skris
364296341Sdelphij    /*
365296341Sdelphij     * ok, now check that there are not arguments, if there are, run with
366296341Sdelphij     * them, shifting the ssleay off the front
367296341Sdelphij     */
368296341Sdelphij    if (Argc != 1) {
369296341Sdelphij        Argc--;
370296341Sdelphij        Argv++;
371296341Sdelphij        ret = do_cmd(prog, Argc, Argv);
372296341Sdelphij        if (ret < 0)
373296341Sdelphij            ret = 0;
374296341Sdelphij        goto end;
375296341Sdelphij    }
37655714Skris
377296341Sdelphij    /* ok, lets enter the old 'OpenSSL>' mode */
37855714Skris
379296341Sdelphij    for (;;) {
380296341Sdelphij        ret = 0;
381296341Sdelphij        p = buf;
382296341Sdelphij        n = sizeof buf;
383296341Sdelphij        i = 0;
384296341Sdelphij        for (;;) {
385296341Sdelphij            p[0] = '\0';
386296341Sdelphij            if (i++)
387296341Sdelphij                prompt = ">";
388296341Sdelphij            else
389296341Sdelphij                prompt = "OpenSSL> ";
390296341Sdelphij            fputs(prompt, stdout);
391296341Sdelphij            fflush(stdout);
392296341Sdelphij            if (!fgets(p, n, stdin))
393296341Sdelphij                goto end;
394296341Sdelphij            if (p[0] == '\0')
395296341Sdelphij                goto end;
396296341Sdelphij            i = strlen(p);
397296341Sdelphij            if (i <= 1)
398296341Sdelphij                break;
399296341Sdelphij            if (p[i - 2] != '\\')
400296341Sdelphij                break;
401296341Sdelphij            i -= 2;
402296341Sdelphij            p += i;
403296341Sdelphij            n -= i;
404296341Sdelphij        }
405296341Sdelphij        if (!chopup_args(&arg, buf, &argc, &argv))
406296341Sdelphij            break;
40755714Skris
408296341Sdelphij        ret = do_cmd(prog, argc, argv);
409296341Sdelphij        if (ret < 0) {
410296341Sdelphij            ret = 0;
411296341Sdelphij            goto end;
412296341Sdelphij        }
413296341Sdelphij        if (ret != 0)
414296341Sdelphij            BIO_printf(bio_err, "error in %s\n", argv[0]);
415296341Sdelphij        (void)BIO_flush(bio_err);
416296341Sdelphij    }
417296341Sdelphij    BIO_printf(bio_err, "bad exit\n");
418296341Sdelphij    ret = 1;
419296341Sdelphij end:
420296341Sdelphij    if (to_free)
421296341Sdelphij        OPENSSL_free(to_free);
422296341Sdelphij    if (config != NULL) {
423296341Sdelphij        NCONF_free(config);
424296341Sdelphij        config = NULL;
425296341Sdelphij    }
426296341Sdelphij    if (prog != NULL)
427296341Sdelphij        lh_FUNCTION_free(prog);
428296341Sdelphij    if (arg.data != NULL)
429296341Sdelphij        OPENSSL_free(arg.data);
430109998Smarkm
431238405Sjkim#if defined( OPENSSL_SYS_VMS) && (__INITIAL_POINTER_SIZE == 64)
432296341Sdelphij    /* Free any duplicate Argv[] storage. */
433296341Sdelphij    if (free_Argv) {
434296341Sdelphij        OPENSSL_free(Argv);
435296341Sdelphij    }
436238405Sjkim#endif
437296341Sdelphij    apps_shutdown();
438296341Sdelphij    CRYPTO_mem_leaks(bio_err);
439296341Sdelphij    if (bio_err != NULL) {
440296341Sdelphij        BIO_free(bio_err);
441296341Sdelphij        bio_err = NULL;
442296341Sdelphij    }
443279264Sdelphij
444296341Sdelphij    OPENSSL_EXIT(ret);
445296341Sdelphij}
44655714Skris
44755714Skris#define LIST_STANDARD_COMMANDS "list-standard-commands"
44855714Skris#define LIST_MESSAGE_DIGEST_COMMANDS "list-message-digest-commands"
449238405Sjkim#define LIST_MESSAGE_DIGEST_ALGORITHMS "list-message-digest-algorithms"
45055714Skris#define LIST_CIPHER_COMMANDS "list-cipher-commands"
451238405Sjkim#define LIST_CIPHER_ALGORITHMS "list-cipher-algorithms"
452238405Sjkim#define LIST_PUBLIC_KEY_ALGORITHMS "list-public-key-algorithms"
45355714Skris
454238405Sjkimstatic int do_cmd(LHASH_OF(FUNCTION) *prog, int argc, char *argv[])
455296341Sdelphij{
456296341Sdelphij    FUNCTION f, *fp;
457296341Sdelphij    int i, ret = 1, tp, nl;
45855714Skris
459296341Sdelphij    if ((argc <= 0) || (argv[0] == NULL)) {
460296341Sdelphij        ret = 0;
461296341Sdelphij        goto end;
462296341Sdelphij    }
463296341Sdelphij    f.name = argv[0];
464296341Sdelphij    fp = lh_FUNCTION_retrieve(prog, &f);
465296341Sdelphij    if (fp == NULL) {
466296341Sdelphij        if (EVP_get_digestbyname(argv[0])) {
467296341Sdelphij            f.type = FUNC_TYPE_MD;
468296341Sdelphij            f.func = dgst_main;
469296341Sdelphij            fp = &f;
470296341Sdelphij        } else if (EVP_get_cipherbyname(argv[0])) {
471296341Sdelphij            f.type = FUNC_TYPE_CIPHER;
472296341Sdelphij            f.func = enc_main;
473296341Sdelphij            fp = &f;
474296341Sdelphij        }
475296341Sdelphij    }
476296341Sdelphij    if (fp != NULL) {
477296341Sdelphij        ret = fp->func(argc, argv);
478296341Sdelphij    } else if ((strncmp(argv[0], "no-", 3)) == 0) {
479296341Sdelphij        BIO *bio_stdout = BIO_new_fp(stdout, BIO_NOCLOSE);
480109998Smarkm#ifdef OPENSSL_SYS_VMS
481296341Sdelphij        {
482296341Sdelphij            BIO *tmpbio = BIO_new(BIO_f_linebuffer());
483296341Sdelphij            bio_stdout = BIO_push(tmpbio, bio_stdout);
484296341Sdelphij        }
48568651Skris#endif
486296341Sdelphij        f.name = argv[0] + 3;
487296341Sdelphij        ret = (lh_FUNCTION_retrieve(prog, &f) != NULL);
488296341Sdelphij        if (!ret)
489296341Sdelphij            BIO_printf(bio_stdout, "%s\n", argv[0]);
490296341Sdelphij        else
491296341Sdelphij            BIO_printf(bio_stdout, "%s\n", argv[0] + 3);
492296341Sdelphij        BIO_free_all(bio_stdout);
493296341Sdelphij        goto end;
494296341Sdelphij    } else if ((strcmp(argv[0], "quit") == 0) ||
495296341Sdelphij               (strcmp(argv[0], "q") == 0) ||
496296341Sdelphij               (strcmp(argv[0], "exit") == 0) ||
497296341Sdelphij               (strcmp(argv[0], "bye") == 0)) {
498296341Sdelphij        ret = -1;
499296341Sdelphij        goto end;
500296341Sdelphij    } else if ((strcmp(argv[0], LIST_STANDARD_COMMANDS) == 0) ||
501296341Sdelphij               (strcmp(argv[0], LIST_MESSAGE_DIGEST_COMMANDS) == 0) ||
502296341Sdelphij               (strcmp(argv[0], LIST_MESSAGE_DIGEST_ALGORITHMS) == 0) ||
503296341Sdelphij               (strcmp(argv[0], LIST_CIPHER_COMMANDS) == 0) ||
504296341Sdelphij               (strcmp(argv[0], LIST_CIPHER_ALGORITHMS) == 0) ||
505296341Sdelphij               (strcmp(argv[0], LIST_PUBLIC_KEY_ALGORITHMS) == 0)) {
506296341Sdelphij        int list_type;
507296341Sdelphij        BIO *bio_stdout;
50855714Skris
509296341Sdelphij        if (strcmp(argv[0], LIST_STANDARD_COMMANDS) == 0)
510296341Sdelphij            list_type = FUNC_TYPE_GENERAL;
511296341Sdelphij        else if (strcmp(argv[0], LIST_MESSAGE_DIGEST_COMMANDS) == 0)
512296341Sdelphij            list_type = FUNC_TYPE_MD;
513296341Sdelphij        else if (strcmp(argv[0], LIST_MESSAGE_DIGEST_ALGORITHMS) == 0)
514296341Sdelphij            list_type = FUNC_TYPE_MD_ALG;
515296341Sdelphij        else if (strcmp(argv[0], LIST_PUBLIC_KEY_ALGORITHMS) == 0)
516296341Sdelphij            list_type = FUNC_TYPE_PKEY;
517296341Sdelphij        else if (strcmp(argv[0], LIST_CIPHER_ALGORITHMS) == 0)
518296341Sdelphij            list_type = FUNC_TYPE_CIPHER_ALG;
519296341Sdelphij        else                    /* strcmp(argv[0],LIST_CIPHER_COMMANDS) == 0 */
520296341Sdelphij            list_type = FUNC_TYPE_CIPHER;
521296341Sdelphij        bio_stdout = BIO_new_fp(stdout, BIO_NOCLOSE);
522109998Smarkm#ifdef OPENSSL_SYS_VMS
523296341Sdelphij        {
524296341Sdelphij            BIO *tmpbio = BIO_new(BIO_f_linebuffer());
525296341Sdelphij            bio_stdout = BIO_push(tmpbio, bio_stdout);
526296341Sdelphij        }
52768651Skris#endif
528238405Sjkim
529296341Sdelphij        if (!load_config(bio_err, NULL))
530296341Sdelphij            goto end;
531238405Sjkim
532296341Sdelphij        if (list_type == FUNC_TYPE_PKEY)
533296341Sdelphij            list_pkey(bio_stdout);
534296341Sdelphij        if (list_type == FUNC_TYPE_MD_ALG)
535296341Sdelphij            list_md(bio_stdout);
536296341Sdelphij        if (list_type == FUNC_TYPE_CIPHER_ALG)
537296341Sdelphij            list_cipher(bio_stdout);
538296341Sdelphij        else {
539296341Sdelphij            for (fp = functions; fp->name != NULL; fp++)
540296341Sdelphij                if (fp->type == list_type)
541296341Sdelphij                    BIO_printf(bio_stdout, "%s\n", fp->name);
542296341Sdelphij        }
543296341Sdelphij        BIO_free_all(bio_stdout);
544296341Sdelphij        ret = 0;
545296341Sdelphij        goto end;
546296341Sdelphij    } else {
547296341Sdelphij        BIO_printf(bio_err, "openssl:Error: '%s' is an invalid command.\n",
548296341Sdelphij                   argv[0]);
549296341Sdelphij        BIO_printf(bio_err, "\nStandard commands");
550296341Sdelphij        i = 0;
551296341Sdelphij        tp = 0;
552296341Sdelphij        for (fp = functions; fp->name != NULL; fp++) {
553296341Sdelphij            nl = 0;
554162911Ssimon#ifdef OPENSSL_NO_CAMELLIA
555296341Sdelphij            if (((i++) % 5) == 0)
556162911Ssimon#else
557296341Sdelphij            if (((i++) % 4) == 0)
558162911Ssimon#endif
559296341Sdelphij            {
560296341Sdelphij                BIO_printf(bio_err, "\n");
561296341Sdelphij                nl = 1;
562296341Sdelphij            }
563296341Sdelphij            if (fp->type != tp) {
564296341Sdelphij                tp = fp->type;
565296341Sdelphij                if (!nl)
566296341Sdelphij                    BIO_printf(bio_err, "\n");
567296341Sdelphij                if (tp == FUNC_TYPE_MD) {
568296341Sdelphij                    i = 1;
569296341Sdelphij                    BIO_printf(bio_err,
570296341Sdelphij                               "\nMessage Digest commands (see the `dgst' command for more details)\n");
571296341Sdelphij                } else if (tp == FUNC_TYPE_CIPHER) {
572296341Sdelphij                    i = 1;
573296341Sdelphij                    BIO_printf(bio_err,
574296341Sdelphij                               "\nCipher commands (see the `enc' command for more details)\n");
575296341Sdelphij                }
576296341Sdelphij            }
577162911Ssimon#ifdef OPENSSL_NO_CAMELLIA
578296341Sdelphij            BIO_printf(bio_err, "%-15s", fp->name);
579162911Ssimon#else
580296341Sdelphij            BIO_printf(bio_err, "%-18s", fp->name);
581162911Ssimon#endif
582296341Sdelphij        }
583296341Sdelphij        BIO_printf(bio_err, "\n\n");
584296341Sdelphij        ret = 0;
585296341Sdelphij    }
586296341Sdelphij end:
587296341Sdelphij    return (ret);
588296341Sdelphij}
58955714Skris
590296341Sdelphijstatic int SortFnByName(const void *_f1, const void *_f2)
591296341Sdelphij{
592296341Sdelphij    const FUNCTION *f1 = _f1;
593296341Sdelphij    const FUNCTION *f2 = _f2;
59455714Skris
595296341Sdelphij    if (f1->type != f2->type)
596296341Sdelphij        return f1->type - f2->type;
597296341Sdelphij    return strcmp(f1->name, f2->name);
598296341Sdelphij}
59955714Skris
600238405Sjkimstatic void list_pkey(BIO *out)
601296341Sdelphij{
602296341Sdelphij    int i;
603296341Sdelphij    for (i = 0; i < EVP_PKEY_asn1_get_count(); i++) {
604296341Sdelphij        const EVP_PKEY_ASN1_METHOD *ameth;
605296341Sdelphij        int pkey_id, pkey_base_id, pkey_flags;
606296341Sdelphij        const char *pinfo, *pem_str;
607296341Sdelphij        ameth = EVP_PKEY_asn1_get0(i);
608296341Sdelphij        EVP_PKEY_asn1_get0_info(&pkey_id, &pkey_base_id, &pkey_flags,
609296341Sdelphij                                &pinfo, &pem_str, ameth);
610296341Sdelphij        if (pkey_flags & ASN1_PKEY_ALIAS) {
611296341Sdelphij            BIO_printf(out, "Name: %s\n", OBJ_nid2ln(pkey_id));
612296341Sdelphij            BIO_printf(out, "\tType: Alias to %s\n",
613296341Sdelphij                       OBJ_nid2ln(pkey_base_id));
614296341Sdelphij        } else {
615296341Sdelphij            BIO_printf(out, "Name: %s\n", pinfo);
616296341Sdelphij            BIO_printf(out, "\tType: %s Algorithm\n",
617296341Sdelphij                       pkey_flags & ASN1_PKEY_DYNAMIC ?
618296341Sdelphij                       "External" : "Builtin");
619296341Sdelphij            BIO_printf(out, "\tOID: %s\n", OBJ_nid2ln(pkey_id));
620296341Sdelphij            if (pem_str == NULL)
621296341Sdelphij                pem_str = "(none)";
622296341Sdelphij            BIO_printf(out, "\tPEM string: %s\n", pem_str);
623296341Sdelphij        }
624238405Sjkim
625296341Sdelphij    }
626296341Sdelphij}
627296341Sdelphij
628238405Sjkimstatic void list_cipher_fn(const EVP_CIPHER *c,
629296341Sdelphij                           const char *from, const char *to, void *arg)
630296341Sdelphij{
631296341Sdelphij    if (c)
632296341Sdelphij        BIO_printf(arg, "%s\n", EVP_CIPHER_name(c));
633296341Sdelphij    else {
634296341Sdelphij        if (!from)
635296341Sdelphij            from = "<undefined>";
636296341Sdelphij        if (!to)
637296341Sdelphij            to = "<undefined>";
638296341Sdelphij        BIO_printf(arg, "%s => %s\n", from, to);
639296341Sdelphij    }
640296341Sdelphij}
641238405Sjkim
642238405Sjkimstatic void list_cipher(BIO *out)
643296341Sdelphij{
644296341Sdelphij    EVP_CIPHER_do_all_sorted(list_cipher_fn, out);
645296341Sdelphij}
646238405Sjkim
647238405Sjkimstatic void list_md_fn(const EVP_MD *m,
648296341Sdelphij                       const char *from, const char *to, void *arg)
649296341Sdelphij{
650296341Sdelphij    if (m)
651296341Sdelphij        BIO_printf(arg, "%s\n", EVP_MD_name(m));
652296341Sdelphij    else {
653296341Sdelphij        if (!from)
654296341Sdelphij            from = "<undefined>";
655296341Sdelphij        if (!to)
656296341Sdelphij            to = "<undefined>";
657296341Sdelphij        BIO_printf(arg, "%s => %s\n", from, to);
658296341Sdelphij    }
659296341Sdelphij}
660238405Sjkim
661238405Sjkimstatic void list_md(BIO *out)
662296341Sdelphij{
663296341Sdelphij    EVP_MD_do_all_sorted(list_md_fn, out);
664296341Sdelphij}
665238405Sjkim
666296341Sdelphijstatic int MS_CALLBACK function_cmp(const FUNCTION * a, const FUNCTION * b)
667296341Sdelphij{
668296341Sdelphij    return strncmp(a->name, b->name, 8);
669296341Sdelphij}
670296341Sdelphij
671238405Sjkimstatic IMPLEMENT_LHASH_COMP_FN(function, FUNCTION)
672238405Sjkim
673296341Sdelphijstatic unsigned long MS_CALLBACK function_hash(const FUNCTION * a)
674296341Sdelphij{
675296341Sdelphij    return lh_strhash(a->name);
676296341Sdelphij}
677296341Sdelphij
678238405Sjkimstatic IMPLEMENT_LHASH_HASH_FN(function, FUNCTION)
679238405Sjkim
680238405Sjkimstatic LHASH_OF(FUNCTION) *prog_init(void)
681296341Sdelphij{
682296341Sdelphij    LHASH_OF(FUNCTION) *ret;
683296341Sdelphij    FUNCTION *f;
684296341Sdelphij    size_t i;
68555714Skris
686296341Sdelphij    /* Purely so it looks nice when the user hits ? */
687296341Sdelphij    for (i = 0, f = functions; f->name != NULL; ++f, ++i) ;
688296341Sdelphij    qsort(functions, i, sizeof *functions, SortFnByName);
68955714Skris
690296341Sdelphij    if ((ret = lh_FUNCTION_new()) == NULL)
691296341Sdelphij        return (NULL);
69255714Skris
693296341Sdelphij    for (f = functions; f->name != NULL; f++)
694296341Sdelphij        (void)lh_FUNCTION_insert(ret, f);
695296341Sdelphij    return (ret);
696296341Sdelphij}
697