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