source: trunk/third/openssl/apps/openssl.c @ 18442

Revision 18442, 14.2 KB checked in by zacheiss, 21 years ago (diff)
This commit was generated by cvs2svn to compensate for changes in r18441, which included commits to RCS files with non-trunk default branches.
Line 
1/* apps/openssl.c */
2/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
3 * All rights reserved.
4 *
5 * This package is an SSL implementation written
6 * by Eric Young (eay@cryptsoft.com).
7 * The implementation was written so as to conform with Netscapes SSL.
8 *
9 * This library is free for commercial and non-commercial use as long as
10 * the following conditions are aheared to.  The following conditions
11 * apply to all code found in this distribution, be it the RC4, RSA,
12 * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
13 * included with this distribution is covered by the same copyright terms
14 * except that the holder is Tim Hudson (tjh@cryptsoft.com).
15 *
16 * Copyright remains Eric Young's, and as such any Copyright notices in
17 * the code are not to be removed.
18 * If this package is used in a product, Eric Young should be given attribution
19 * as the author of the parts of the library used.
20 * This can be in the form of a textual message at program startup or
21 * in documentation (online or textual) provided with the package.
22 *
23 * Redistribution and use in source and binary forms, with or without
24 * modification, are permitted provided that the following conditions
25 * are met:
26 * 1. Redistributions of source code must retain the copyright
27 *    notice, this list of conditions and the following disclaimer.
28 * 2. Redistributions in binary form must reproduce the above copyright
29 *    notice, this list of conditions and the following disclaimer in the
30 *    documentation and/or other materials provided with the distribution.
31 * 3. All advertising materials mentioning features or use of this software
32 *    must display the following acknowledgement:
33 *    "This product includes cryptographic software written by
34 *     Eric Young (eay@cryptsoft.com)"
35 *    The word 'cryptographic' can be left out if the rouines from the library
36 *    being used are not cryptographic related :-).
37 * 4. If you include any Windows specific code (or a derivative thereof) from
38 *    the apps directory (application code) you must include an acknowledgement:
39 *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
40 *
41 * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
42 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
43 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
44 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
45 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
46 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
47 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
48 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
49 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
50 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
51 * SUCH DAMAGE.
52 *
53 * The licence and distribution terms for any publically available version or
54 * derivative of this code cannot be changed.  i.e. this code cannot simply be
55 * copied and put under another distribution licence
56 * [including the GNU Public Licence.]
57 */
58/* ====================================================================
59 * Copyright (c) 1998-2001 The OpenSSL Project.  All rights reserved.
60 *
61 * Redistribution and use in source and binary forms, with or without
62 * modification, are permitted provided that the following conditions
63 * are met:
64 *
65 * 1. Redistributions of source code must retain the above copyright
66 *    notice, this list of conditions and the following disclaimer.
67 *
68 * 2. Redistributions in binary form must reproduce the above copyright
69 *    notice, this list of conditions and the following disclaimer in
70 *    the documentation and/or other materials provided with the
71 *    distribution.
72 *
73 * 3. All advertising materials mentioning features or use of this
74 *    software must display the following acknowledgment:
75 *    "This product includes software developed by the OpenSSL Project
76 *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
77 *
78 * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
79 *    endorse or promote products derived from this software without
80 *    prior written permission. For written permission, please contact
81 *    openssl-core@openssl.org.
82 *
83 * 5. Products derived from this software may not be called "OpenSSL"
84 *    nor may "OpenSSL" appear in their names without prior written
85 *    permission of the OpenSSL Project.
86 *
87 * 6. Redistributions of any form whatsoever must retain the following
88 *    acknowledgment:
89 *    "This product includes software developed by the OpenSSL Project
90 *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
91 *
92 * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
93 * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
94 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
95 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
96 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
97 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
98 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
99 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
100 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
101 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
102 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
103 * OF THE POSSIBILITY OF SUCH DAMAGE.
104 * ====================================================================
105 *
106 * This product includes cryptographic software written by Eric Young
107 * (eay@cryptsoft.com).  This product includes software written by Tim
108 * Hudson (tjh@cryptsoft.com).
109 *
110 */
111
112
113#include <stdio.h>
114#include <string.h>
115#include <stdlib.h>
116#define OPENSSL_C /* tells apps.h to use complete apps_startup() */
117#include "apps.h"
118#include <openssl/bio.h>
119#include <openssl/crypto.h>
120#include <openssl/lhash.h>
121#include <openssl/conf.h>
122#include <openssl/x509.h>
123#include <openssl/pem.h>
124#include <openssl/ssl.h>
125#include <openssl/engine.h>
126#define USE_SOCKETS /* needed for the _O_BINARY defs in the MS world */
127#include "progs.h"
128#include "s_apps.h"
129#include <openssl/err.h>
130
131/* The LHASH callbacks ("hash" & "cmp") have been replaced by functions with the
132 * base prototypes (we cast each variable inside the function to the required
133 * type of "FUNCTION*"). This removes the necessity for macro-generated wrapper
134 * functions. */
135
136/* static unsigned long MS_CALLBACK hash(FUNCTION *a); */
137static unsigned long MS_CALLBACK hash(const void *a_void);
138/* static int MS_CALLBACK cmp(FUNCTION *a,FUNCTION *b); */
139static int MS_CALLBACK cmp(const void *a_void,const void *b_void);
140static LHASH *prog_init(void );
141static int do_cmd(LHASH *prog,int argc,char *argv[]);
142char *default_config_file=NULL;
143
144/* Make sure there is only one when MONOLITH is defined */
145#ifdef MONOLITH
146CONF *config=NULL;
147BIO *bio_err=NULL;
148#endif
149
150
151static void lock_dbg_cb(int mode, int type, const char *file, int line)
152        {
153        static int modes[CRYPTO_NUM_LOCKS]; /* = {0, 0, ... } */
154        const char *errstr = NULL;
155        int rw;
156       
157        rw = mode & (CRYPTO_READ|CRYPTO_WRITE);
158        if (!((rw == CRYPTO_READ) || (rw == CRYPTO_WRITE)))
159                {
160                errstr = "invalid mode";
161                goto err;
162                }
163
164        if (type < 0 || type > CRYPTO_NUM_LOCKS)
165                {
166                errstr = "type out of bounds";
167                goto err;
168                }
169
170        if (mode & CRYPTO_LOCK)
171                {
172                if (modes[type])
173                        {
174                        errstr = "already locked";
175                        /* must not happen in a single-threaded program
176                         * (would deadlock) */
177                        goto err;
178                        }
179
180                modes[type] = rw;
181                }
182        else if (mode & CRYPTO_UNLOCK)
183                {
184                if (!modes[type])
185                        {
186                        errstr = "not locked";
187                        goto err;
188                        }
189               
190                if (modes[type] != rw)
191                        {
192                        errstr = (rw == CRYPTO_READ) ?
193                                "CRYPTO_r_unlock on write lock" :
194                                "CRYPTO_w_unlock on read lock";
195                        }
196
197                modes[type] = 0;
198                }
199        else
200                {
201                errstr = "invalid mode";
202                goto err;
203                }
204
205 err:
206        if (errstr)
207                {
208                /* we cannot use bio_err here */
209                fprintf(stderr, "openssl (lock_dbg_cb): %s (mode=%d, type=%d) at %s:%d\n",
210                        errstr, mode, type, file, line);
211                }
212        }
213
214
215int main(int Argc, char *Argv[])
216        {
217        ARGS arg;
218#define PROG_NAME_SIZE  39
219        char pname[PROG_NAME_SIZE+1];
220        FUNCTION f,*fp;
221        MS_STATIC char *prompt,buf[1024];
222        char *to_free=NULL;
223        int n,i,ret=0;
224        int argc;
225        char **argv,*p;
226        LHASH *prog=NULL;
227        long errline;
228 
229        arg.data=NULL;
230        arg.count=0;
231
232        if (bio_err == NULL)
233                if ((bio_err=BIO_new(BIO_s_file())) != NULL)
234                        BIO_set_fp(bio_err,stderr,BIO_NOCLOSE|BIO_FP_TEXT);
235
236        if (getenv("OPENSSL_DEBUG_MEMORY") != NULL) /* if not defined, use compiled-in library defaults */
237                {
238                if (!(0 == strcmp(getenv("OPENSSL_DEBUG_MEMORY"), "off")))
239                        {
240                        CRYPTO_malloc_debug_init();
241                        CRYPTO_set_mem_debug_options(V_CRYPTO_MDEBUG_ALL);
242                        }
243                else
244                        {
245                        /* OPENSSL_DEBUG_MEMORY=off */
246                        CRYPTO_set_mem_debug_functions(0, 0, 0, 0, 0);
247                        }
248                }
249        CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_ON);
250
251#if 0
252        if (getenv("OPENSSL_DEBUG_LOCKING") != NULL)
253#endif
254                {
255                CRYPTO_set_locking_callback(lock_dbg_cb);
256                }
257
258        apps_startup();
259
260        /* Lets load up our environment a little */
261        p=getenv("OPENSSL_CONF");
262        if (p == NULL)
263                p=getenv("SSLEAY_CONF");
264        if (p == NULL)
265                p=to_free=make_config_name();
266
267        default_config_file=p;
268
269        config=NCONF_new(NULL);
270        i=NCONF_load(config,p,&errline);
271        if (i == 0)
272                {
273                NCONF_free(config);
274                config = NULL;
275                ERR_clear_error();
276                }
277
278        prog=prog_init();
279
280        /* first check the program name */
281        program_name(Argv[0],pname,sizeof pname);
282
283        f.name=pname;
284        fp=(FUNCTION *)lh_retrieve(prog,&f);
285        if (fp != NULL)
286                {
287                Argv[0]=pname;
288                ret=fp->func(Argc,Argv);
289                goto end;
290                }
291
292        /* ok, now check that there are not arguments, if there are,
293         * run with them, shifting the ssleay off the front */
294        if (Argc != 1)
295                {
296                Argc--;
297                Argv++;
298                ret=do_cmd(prog,Argc,Argv);
299                if (ret < 0) ret=0;
300                goto end;
301                }
302
303        /* ok, lets enter the old 'OpenSSL>' mode */
304       
305        for (;;)
306                {
307                ret=0;
308                p=buf;
309                n=sizeof buf;
310                i=0;
311                for (;;)
312                        {
313                        p[0]='\0';
314                        if (i++)
315                                prompt=">";
316                        else    prompt="OpenSSL> ";
317                        fputs(prompt,stdout);
318                        fflush(stdout);
319                        fgets(p,n,stdin);
320                        if (p[0] == '\0') goto end;
321                        i=strlen(p);
322                        if (i <= 1) break;
323                        if (p[i-2] != '\\') break;
324                        i-=2;
325                        p+=i;
326                        n-=i;
327                        }
328                if (!chopup_args(&arg,buf,&argc,&argv)) break;
329
330                ret=do_cmd(prog,argc,argv);
331                if (ret < 0)
332                        {
333                        ret=0;
334                        goto end;
335                        }
336                if (ret != 0)
337                        BIO_printf(bio_err,"error in %s\n",argv[0]);
338                (void)BIO_flush(bio_err);
339                }
340        BIO_printf(bio_err,"bad exit\n");
341        ret=1;
342end:
343        if (to_free)
344                OPENSSL_free(to_free);
345        if (config != NULL)
346                {
347                NCONF_free(config);
348                config=NULL;
349                }
350        if (prog != NULL) lh_free(prog);
351        if (arg.data != NULL) OPENSSL_free(arg.data);
352
353        apps_shutdown();
354
355        CRYPTO_mem_leaks(bio_err);
356        if (bio_err != NULL)
357                {
358                BIO_free(bio_err);
359                bio_err=NULL;
360                }
361        OPENSSL_EXIT(ret);
362        }
363
364#define LIST_STANDARD_COMMANDS "list-standard-commands"
365#define LIST_MESSAGE_DIGEST_COMMANDS "list-message-digest-commands"
366#define LIST_CIPHER_COMMANDS "list-cipher-commands"
367
368static int do_cmd(LHASH *prog, int argc, char *argv[])
369        {
370        FUNCTION f,*fp;
371        int i,ret=1,tp,nl;
372
373        if ((argc <= 0) || (argv[0] == NULL))
374                { ret=0; goto end; }
375        f.name=argv[0];
376        fp=(FUNCTION *)lh_retrieve(prog,&f);
377        if (fp != NULL)
378                {
379                ret=fp->func(argc,argv);
380                }
381        else if ((strncmp(argv[0],"no-",3)) == 0)
382                {
383                BIO *bio_stdout = BIO_new_fp(stdout,BIO_NOCLOSE);
384#ifdef OPENSSL_SYS_VMS
385                {
386                BIO *tmpbio = BIO_new(BIO_f_linebuffer());
387                bio_stdout = BIO_push(tmpbio, bio_stdout);
388                }
389#endif
390                f.name=argv[0]+3;
391                ret = (lh_retrieve(prog,&f) != NULL);
392                if (!ret)
393                        BIO_printf(bio_stdout, "%s\n", argv[0]);
394                else
395                        BIO_printf(bio_stdout, "%s\n", argv[0]+3);
396                BIO_free_all(bio_stdout);
397                goto end;
398                }
399        else if ((strcmp(argv[0],"quit") == 0) ||
400                (strcmp(argv[0],"q") == 0) ||
401                (strcmp(argv[0],"exit") == 0) ||
402                (strcmp(argv[0],"bye") == 0))
403                {
404                ret= -1;
405                goto end;
406                }
407        else if ((strcmp(argv[0],LIST_STANDARD_COMMANDS) == 0) ||
408                (strcmp(argv[0],LIST_MESSAGE_DIGEST_COMMANDS) == 0) ||
409                (strcmp(argv[0],LIST_CIPHER_COMMANDS) == 0))
410                {
411                int list_type;
412                BIO *bio_stdout;
413
414                if (strcmp(argv[0],LIST_STANDARD_COMMANDS) == 0)
415                        list_type = FUNC_TYPE_GENERAL;
416                else if (strcmp(argv[0],LIST_MESSAGE_DIGEST_COMMANDS) == 0)
417                        list_type = FUNC_TYPE_MD;
418                else /* strcmp(argv[0],LIST_CIPHER_COMMANDS) == 0 */
419                        list_type = FUNC_TYPE_CIPHER;
420                bio_stdout = BIO_new_fp(stdout,BIO_NOCLOSE);
421#ifdef OPENSSL_SYS_VMS
422                {
423                BIO *tmpbio = BIO_new(BIO_f_linebuffer());
424                bio_stdout = BIO_push(tmpbio, bio_stdout);
425                }
426#endif
427               
428                for (fp=functions; fp->name != NULL; fp++)
429                        if (fp->type == list_type)
430                                BIO_printf(bio_stdout, "%s\n", fp->name);
431                BIO_free_all(bio_stdout);
432                ret=0;
433                goto end;
434                }
435        else
436                {
437                BIO_printf(bio_err,"openssl:Error: '%s' is an invalid command.\n",
438                        argv[0]);
439                BIO_printf(bio_err, "\nStandard commands");
440                i=0;
441                tp=0;
442                for (fp=functions; fp->name != NULL; fp++)
443                        {
444                        nl=0;
445                        if (((i++) % 5) == 0)
446                                {
447                                BIO_printf(bio_err,"\n");
448                                nl=1;
449                                }
450                        if (fp->type != tp)
451                                {
452                                tp=fp->type;
453                                if (!nl) BIO_printf(bio_err,"\n");
454                                if (tp == FUNC_TYPE_MD)
455                                        {
456                                        i=1;
457                                        BIO_printf(bio_err,
458                                                "\nMessage Digest commands (see the `dgst' command for more details)\n");
459                                        }
460                                else if (tp == FUNC_TYPE_CIPHER)
461                                        {
462                                        i=1;
463                                        BIO_printf(bio_err,"\nCipher commands (see the `enc' command for more details)\n");
464                                        }
465                                }
466                        BIO_printf(bio_err,"%-15s",fp->name);
467                        }
468                BIO_printf(bio_err,"\n\n");
469                ret=0;
470                }
471end:
472        return(ret);
473        }
474
475static int SortFnByName(const void *_f1,const void *_f2)
476    {
477    const FUNCTION *f1=_f1;
478    const FUNCTION *f2=_f2;
479
480    if(f1->type != f2->type)
481        return f1->type-f2->type;
482    return strcmp(f1->name,f2->name);
483    }
484
485static LHASH *prog_init(void)
486        {
487        LHASH *ret;
488        FUNCTION *f;
489        int i;
490
491        /* Purely so it looks nice when the user hits ? */
492        for(i=0,f=functions ; f->name != NULL ; ++f,++i)
493            ;
494        qsort(functions,i,sizeof *functions,SortFnByName);
495
496        if ((ret=lh_new(hash, cmp)) == NULL)
497                return(NULL);
498
499        for (f=functions; f->name != NULL; f++)
500                lh_insert(ret,f);
501        return(ret);
502        }
503
504/* static int MS_CALLBACK cmp(FUNCTION *a, FUNCTION *b) */
505static int MS_CALLBACK cmp(const void *a_void, const void *b_void)
506        {
507        return(strncmp(((FUNCTION *)a_void)->name,
508                        ((FUNCTION *)b_void)->name,8));
509        }
510
511/* static unsigned long MS_CALLBACK hash(FUNCTION *a) */
512static unsigned long MS_CALLBACK hash(const void *a_void)
513        {
514        return(lh_strhash(((FUNCTION *)a_void)->name));
515        }
Note: See TracBrowser for help on using the repository browser.