Main Page | Class List | Directories | File List | Class Members | File Members

openssl.c

Go to the documentation of this file.
00001 /* apps/openssl.c */
00002 /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
00003  * All rights reserved.
00004  *
00005  * This package is an SSL implementation written
00006  * by Eric Young (eay@cryptsoft.com).
00007  * The implementation was written so as to conform with Netscapes SSL.
00008  * 
00009  * This library is free for commercial and non-commercial use as long as
00010  * the following conditions are aheared to.  The following conditions
00011  * apply to all code found in this distribution, be it the RC4, RSA,
00012  * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
00013  * included with this distribution is covered by the same copyright terms
00014  * except that the holder is Tim Hudson (tjh@cryptsoft.com).
00015  * 
00016  * Copyright remains Eric Young's, and as such any Copyright notices in
00017  * the code are not to be removed.
00018  * If this package is used in a product, Eric Young should be given attribution
00019  * as the author of the parts of the library used.
00020  * This can be in the form of a textual message at program startup or
00021  * in documentation (online or textual) provided with the package.
00022  * 
00023  * Redistribution and use in source and binary forms, with or without
00024  * modification, are permitted provided that the following conditions
00025  * are met:
00026  * 1. Redistributions of source code must retain the copyright
00027  *    notice, this list of conditions and the following disclaimer.
00028  * 2. Redistributions in binary form must reproduce the above copyright
00029  *    notice, this list of conditions and the following disclaimer in the
00030  *    documentation and/or other materials provided with the distribution.
00031  * 3. All advertising materials mentioning features or use of this software
00032  *    must display the following acknowledgement:
00033  *    "This product includes cryptographic software written by
00034  *     Eric Young (eay@cryptsoft.com)"
00035  *    The word 'cryptographic' can be left out if the rouines from the library
00036  *    being used are not cryptographic related :-).
00037  * 4. If you include any Windows specific code (or a derivative thereof) from 
00038  *    the apps directory (application code) you must include an acknowledgement:
00039  *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
00040  * 
00041  * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
00042  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00043  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00044  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
00045  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
00046  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
00047  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
00048  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
00049  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
00050  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
00051  * SUCH DAMAGE.
00052  * 
00053  * The licence and distribution terms for any publically available version or
00054  * derivative of this code cannot be changed.  i.e. this code cannot simply be
00055  * copied and put under another distribution licence
00056  * [including the GNU Public Licence.]
00057  */
00058 /* ====================================================================
00059  * Copyright (c) 1998-2001 The OpenSSL Project.  All rights reserved.
00060  *
00061  * Redistribution and use in source and binary forms, with or without
00062  * modification, are permitted provided that the following conditions
00063  * are met:
00064  *
00065  * 1. Redistributions of source code must retain the above copyright
00066  *    notice, this list of conditions and the following disclaimer. 
00067  *
00068  * 2. Redistributions in binary form must reproduce the above copyright
00069  *    notice, this list of conditions and the following disclaimer in
00070  *    the documentation and/or other materials provided with the
00071  *    distribution.
00072  *
00073  * 3. All advertising materials mentioning features or use of this
00074  *    software must display the following acknowledgment:
00075  *    "This product includes software developed by the OpenSSL Project
00076  *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
00077  *
00078  * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
00079  *    endorse or promote products derived from this software without
00080  *    prior written permission. For written permission, please contact
00081  *    openssl-core@openssl.org.
00082  *
00083  * 5. Products derived from this software may not be called "OpenSSL"
00084  *    nor may "OpenSSL" appear in their names without prior written
00085  *    permission of the OpenSSL Project.
00086  *
00087  * 6. Redistributions of any form whatsoever must retain the following
00088  *    acknowledgment:
00089  *    "This product includes software developed by the OpenSSL Project
00090  *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
00091  *
00092  * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
00093  * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00094  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
00095  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
00096  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
00097  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
00098  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
00099  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
00100  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
00101  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
00102  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
00103  * OF THE POSSIBILITY OF SUCH DAMAGE.
00104  * ====================================================================
00105  *
00106  * This product includes cryptographic software written by Eric Young
00107  * (eay@cryptsoft.com).  This product includes software written by Tim
00108  * Hudson (tjh@cryptsoft.com).
00109  *
00110  */
00111 
00112 
00113 #include <stdio.h>
00114 #include <string.h>
00115 #include <stdlib.h>
00116 #define OPENSSL_C /* tells apps.h to use complete apps_startup() */
00117 #include "apps.h"
00118 #include <openssl/bio.h>
00119 #include <openssl/crypto.h>
00120 #include <openssl/lhash.h>
00121 #include <openssl/conf.h>
00122 #include <openssl/x509.h>
00123 #include <openssl/pem.h>
00124 #include <openssl/ssl.h>
00125 #ifndef OPENSSL_NO_ENGINE
00126 #include <openssl/engine.h>
00127 #endif
00128 #define USE_SOCKETS /* needed for the _O_BINARY defs in the MS world */
00129 #include "progs.h"
00130 #include "s_apps.h"
00131 #include <openssl/err.h>
00132 
00133 /* The LHASH callbacks ("hash" & "cmp") have been replaced by functions with the
00134  * base prototypes (we cast each variable inside the function to the required
00135  * type of "FUNCTION*"). This removes the necessity for macro-generated wrapper
00136  * functions. */
00137 
00138 /* static unsigned long MS_CALLBACK hash(FUNCTION *a); */
00139 static unsigned long MS_CALLBACK hash(const void *a_void);
00140 /* static int MS_CALLBACK cmp(FUNCTION *a,FUNCTION *b); */
00141 static int MS_CALLBACK cmp(const void *a_void,const void *b_void);
00142 static LHASH *prog_init(void );
00143 static int do_cmd(LHASH *prog,int argc,char *argv[]);
00144 char *default_config_file=NULL;
00145 
00146 /* Make sure there is only one when MONOLITH is defined */
00147 #ifdef MONOLITH
00148 CONF *config=NULL;
00149 BIO *bio_err=NULL;
00150 #endif
00151 
00152 
00153 static void lock_dbg_cb(int mode, int type, const char *file, int line)
00154         {
00155         static int modes[CRYPTO_NUM_LOCKS]; /* = {0, 0, ... } */
00156         const char *errstr = NULL;
00157         int rw;
00158         
00159         rw = mode & (CRYPTO_READ|CRYPTO_WRITE);
00160         if (!((rw == CRYPTO_READ) || (rw == CRYPTO_WRITE)))
00161                 {
00162                 errstr = "invalid mode";
00163                 goto err;
00164                 }
00165 
00166         if (type < 0 || type >= CRYPTO_NUM_LOCKS)
00167                 {
00168                 errstr = "type out of bounds";
00169                 goto err;
00170                 }
00171 
00172         if (mode & CRYPTO_LOCK)
00173                 {
00174                 if (modes[type])
00175                         {
00176                         errstr = "already locked";
00177                         /* must not happen in a single-threaded program
00178                          * (would deadlock) */
00179                         goto err;
00180                         }
00181 
00182                 modes[type] = rw;
00183                 }
00184         else if (mode & CRYPTO_UNLOCK)
00185                 {
00186                 if (!modes[type])
00187                         {
00188                         errstr = "not locked";
00189                         goto err;
00190                         }
00191                 
00192                 if (modes[type] != rw)
00193                         {
00194                         errstr = (rw == CRYPTO_READ) ?
00195                                 "CRYPTO_r_unlock on write lock" :
00196                                 "CRYPTO_w_unlock on read lock";
00197                         }
00198 
00199                 modes[type] = 0;
00200                 }
00201         else
00202                 {
00203                 errstr = "invalid mode";
00204                 goto err;
00205                 }
00206 
00207  err:
00208         if (errstr)
00209                 {
00210                 /* we cannot use bio_err here */
00211                 fprintf(stderr, "openssl (lock_dbg_cb): %s (mode=%d, type=%d) at %s:%d\n",
00212                         errstr, mode, type, file, line);
00213                 }
00214         }
00215 
00216 
00217 int main(int Argc, char *Argv[])
00218         {
00219         ARGS arg;
00220 #define PROG_NAME_SIZE  39
00221         char pname[PROG_NAME_SIZE+1];
00222         FUNCTION f,*fp;
00223         MS_STATIC const char *prompt;
00224         MS_STATIC char buf[1024];
00225         char *to_free=NULL;
00226         int n,i,ret=0;
00227         int argc;
00228         char **argv,*p;
00229         LHASH *prog=NULL;
00230         long errline;
00231  
00232         arg.data=NULL;
00233         arg.count=0;
00234 
00235         if (bio_err == NULL)
00236                 if ((bio_err=BIO_new(BIO_s_file())) != NULL)
00237                         BIO_set_fp(bio_err,stderr,BIO_NOCLOSE|BIO_FP_TEXT);
00238 
00239         if (getenv("OPENSSL_DEBUG_MEMORY") != NULL) /* if not defined, use compiled-in library defaults */
00240                 {
00241                 if (!(0 == strcmp(getenv("OPENSSL_DEBUG_MEMORY"), "off")))
00242                         {
00243                         CRYPTO_malloc_debug_init();
00244                         CRYPTO_set_mem_debug_options(V_CRYPTO_MDEBUG_ALL);
00245                         }
00246                 else
00247                         {
00248                         /* OPENSSL_DEBUG_MEMORY=off */
00249                         CRYPTO_set_mem_debug_functions(0, 0, 0, 0, 0);
00250                         }
00251                 }
00252         CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_ON);
00253 
00254 #if 0
00255         if (getenv("OPENSSL_DEBUG_LOCKING") != NULL)
00256 #endif
00257                 {
00258                 CRYPTO_set_locking_callback(lock_dbg_cb);
00259                 }
00260 
00261         apps_startup();
00262 
00263         /* Lets load up our environment a little */
00264         p=getenv("OPENSSL_CONF");
00265         if (p == NULL)
00266                 p=getenv("SSLEAY_CONF");
00267         if (p == NULL)
00268                 p=to_free=make_config_name();
00269 
00270         default_config_file=p;
00271 
00272         config=NCONF_new(NULL);
00273         i=NCONF_load(config,p,&errline);
00274         if (i == 0)
00275                 {
00276                 NCONF_free(config);
00277                 config = NULL;
00278                 ERR_clear_error();
00279                 }
00280 
00281         prog=prog_init();
00282 
00283         /* first check the program name */
00284         program_name(Argv[0],pname,sizeof pname);
00285 
00286         f.name=pname;
00287         fp=(FUNCTION *)lh_retrieve(prog,&f);
00288         if (fp != NULL)
00289                 {
00290                 Argv[0]=pname;
00291                 ret=fp->func(Argc,Argv);
00292                 goto end;
00293                 }
00294 
00295         /* ok, now check that there are not arguments, if there are,
00296          * run with them, shifting the ssleay off the front */
00297         if (Argc != 1)
00298                 {
00299                 Argc--;
00300                 Argv++;
00301                 ret=do_cmd(prog,Argc,Argv);
00302                 if (ret < 0) ret=0;
00303                 goto end;
00304                 }
00305 
00306         /* ok, lets enter the old 'OpenSSL>' mode */
00307         
00308         for (;;)
00309                 {
00310                 ret=0;
00311                 p=buf;
00312                 n=sizeof buf;
00313                 i=0;
00314                 for (;;)
00315                         {
00316                         p[0]='\0';
00317                         if (i++)
00318                                 prompt=">";
00319                         else    prompt="OpenSSL> ";
00320                         fputs(prompt,stdout);
00321                         fflush(stdout);
00322                         fgets(p,n,stdin);
00323                         if (p[0] == '\0') goto end;
00324                         i=strlen(p);
00325                         if (i <= 1) break;
00326                         if (p[i-2] != '\\') break;
00327                         i-=2;
00328                         p+=i;
00329                         n-=i;
00330                         }
00331                 if (!chopup_args(&arg,buf,&argc,&argv)) break;
00332 
00333                 ret=do_cmd(prog,argc,argv);
00334                 if (ret < 0)
00335                         {
00336                         ret=0;
00337                         goto end;
00338                         }
00339                 if (ret != 0)
00340                         BIO_printf(bio_err,"error in %s\n",argv[0]);
00341                 (void)BIO_flush(bio_err);
00342                 }
00343         BIO_printf(bio_err,"bad exit\n");
00344         ret=1;
00345 end:
00346         if (to_free)
00347                 OPENSSL_free(to_free);
00348         if (config != NULL)
00349                 {
00350                 NCONF_free(config);
00351                 config=NULL;
00352                 }
00353         if (prog != NULL) lh_free(prog);
00354         if (arg.data != NULL) OPENSSL_free(arg.data);
00355 
00356         apps_shutdown();
00357 
00358         CRYPTO_mem_leaks(bio_err);
00359         if (bio_err != NULL)
00360                 {
00361                 BIO_free(bio_err);
00362                 bio_err=NULL;
00363                 }
00364         OPENSSL_EXIT(ret);
00365         }
00366 
00367 #define LIST_STANDARD_COMMANDS "list-standard-commands"
00368 #define LIST_MESSAGE_DIGEST_COMMANDS "list-message-digest-commands"
00369 #define LIST_CIPHER_COMMANDS "list-cipher-commands"
00370 
00371 static int do_cmd(LHASH *prog, int argc, char *argv[])
00372         {
00373         FUNCTION f,*fp;
00374         int i,ret=1,tp,nl;
00375 
00376         if ((argc <= 0) || (argv[0] == NULL))
00377                 { ret=0; goto end; }
00378         f.name=argv[0];
00379         fp=(FUNCTION *)lh_retrieve(prog,&f);
00380         if (fp != NULL)
00381                 {
00382                 ret=fp->func(argc,argv);
00383                 }
00384         else if ((strncmp(argv[0],"no-",3)) == 0)
00385                 {
00386                 BIO *bio_stdout = BIO_new_fp(stdout,BIO_NOCLOSE);
00387 #ifdef OPENSSL_SYS_VMS
00388                 {
00389                 BIO *tmpbio = BIO_new(BIO_f_linebuffer());
00390                 bio_stdout = BIO_push(tmpbio, bio_stdout);
00391                 }
00392 #endif
00393                 f.name=argv[0]+3;
00394                 ret = (lh_retrieve(prog,&f) != NULL);
00395                 if (!ret)
00396                         BIO_printf(bio_stdout, "%s\n", argv[0]);
00397                 else
00398                         BIO_printf(bio_stdout, "%s\n", argv[0]+3);
00399                 BIO_free_all(bio_stdout);
00400                 goto end;
00401                 }
00402         else if ((strcmp(argv[0],"quit") == 0) ||
00403                 (strcmp(argv[0],"q") == 0) ||
00404                 (strcmp(argv[0],"exit") == 0) ||
00405                 (strcmp(argv[0],"bye") == 0))
00406                 {
00407                 ret= -1;
00408                 goto end;
00409                 }
00410         else if ((strcmp(argv[0],LIST_STANDARD_COMMANDS) == 0) ||
00411                 (strcmp(argv[0],LIST_MESSAGE_DIGEST_COMMANDS) == 0) ||
00412                 (strcmp(argv[0],LIST_CIPHER_COMMANDS) == 0))
00413                 {
00414                 int list_type;
00415                 BIO *bio_stdout;
00416 
00417                 if (strcmp(argv[0],LIST_STANDARD_COMMANDS) == 0)
00418                         list_type = FUNC_TYPE_GENERAL;
00419                 else if (strcmp(argv[0],LIST_MESSAGE_DIGEST_COMMANDS) == 0)
00420                         list_type = FUNC_TYPE_MD;
00421                 else /* strcmp(argv[0],LIST_CIPHER_COMMANDS) == 0 */
00422                         list_type = FUNC_TYPE_CIPHER;
00423                 bio_stdout = BIO_new_fp(stdout,BIO_NOCLOSE);
00424 #ifdef OPENSSL_SYS_VMS
00425                 {
00426                 BIO *tmpbio = BIO_new(BIO_f_linebuffer());
00427                 bio_stdout = BIO_push(tmpbio, bio_stdout);
00428                 }
00429 #endif
00430                 
00431                 for (fp=functions; fp->name != NULL; fp++)
00432                         if (fp->type == list_type)
00433                                 BIO_printf(bio_stdout, "%s\n", fp->name);
00434                 BIO_free_all(bio_stdout);
00435                 ret=0;
00436                 goto end;
00437                 }
00438         else
00439                 {
00440                 BIO_printf(bio_err,"openssl:Error: '%s' is an invalid command.\n",
00441                         argv[0]);
00442                 BIO_printf(bio_err, "\nStandard commands");
00443                 i=0;
00444                 tp=0;
00445                 for (fp=functions; fp->name != NULL; fp++)
00446                         {
00447                         nl=0;
00448                         if (((i++) % 5) == 0)
00449                                 {
00450                                 BIO_printf(bio_err,"\n");
00451                                 nl=1;
00452                                 }
00453                         if (fp->type != tp)
00454                                 {
00455                                 tp=fp->type;
00456                                 if (!nl) BIO_printf(bio_err,"\n");
00457                                 if (tp == FUNC_TYPE_MD)
00458                                         {
00459                                         i=1;
00460                                         BIO_printf(bio_err,
00461                                                 "\nMessage Digest commands (see the `dgst' command for more details)\n");
00462                                         }
00463                                 else if (tp == FUNC_TYPE_CIPHER)
00464                                         {
00465                                         i=1;
00466                                         BIO_printf(bio_err,"\nCipher commands (see the `enc' command for more details)\n");
00467                                         }
00468                                 }
00469                         BIO_printf(bio_err,"%-15s",fp->name);
00470                         }
00471                 BIO_printf(bio_err,"\n\n");
00472                 ret=0;
00473                 }
00474 end:
00475         return(ret);
00476         }
00477 
00478 static int SortFnByName(const void *_f1,const void *_f2)
00479     {
00480     const FUNCTION *f1=_f1;
00481     const FUNCTION *f2=_f2;
00482 
00483     if(f1->type != f2->type)
00484         return f1->type-f2->type;
00485     return strcmp(f1->name,f2->name);
00486     }
00487 
00488 static LHASH *prog_init(void)
00489         {
00490         LHASH *ret;
00491         FUNCTION *f;
00492         size_t i;
00493 
00494         /* Purely so it looks nice when the user hits ? */
00495         for(i=0,f=functions ; f->name != NULL ; ++f,++i)
00496             ;
00497         qsort(functions,i,sizeof *functions,SortFnByName);
00498 
00499         if ((ret=lh_new(hash, cmp)) == NULL)
00500                 return(NULL);
00501 
00502         for (f=functions; f->name != NULL; f++)
00503                 lh_insert(ret,f);
00504         return(ret);
00505         }
00506 
00507 /* static int MS_CALLBACK cmp(FUNCTION *a, FUNCTION *b) */
00508 static int MS_CALLBACK cmp(const void *a_void, const void *b_void)
00509         {
00510         return(strncmp(((const FUNCTION *)a_void)->name,
00511                         ((const FUNCTION *)b_void)->name,8));
00512         }
00513 
00514 /* static unsigned long MS_CALLBACK hash(FUNCTION *a) */
00515 static unsigned long MS_CALLBACK hash(const void *a_void)
00516         {
00517         return(lh_strhash(((const FUNCTION *)a_void)->name));
00518         }

© sourcejam.com 2005-2008