1/* apps/sess_id.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#include <stdio.h>
60#include <stdlib.h>
61#include <string.h>
62#include "apps.h"
63#include <openssl/bio.h>
64#include <openssl/err.h>
65#include <openssl/x509.h>
66#include <openssl/pem.h>
67#include <openssl/ssl.h>
68
69#undef PROG
70#define PROG    sess_id_main
71
72static const char *sess_id_usage[] = {
73    "usage: sess_id args\n",
74    "\n",
75    " -inform arg     - input format - default PEM (DER or PEM)\n",
76    " -outform arg    - output format - default PEM\n",
77    " -in arg         - input file - default stdin\n",
78    " -out arg        - output file - default stdout\n",
79    " -text           - print ssl session id details\n",
80    " -cert           - output certificate \n",
81    " -noout          - no CRL output\n",
82    " -context arg    - set the session ID context\n",
83    NULL
84};
85
86static SSL_SESSION *load_sess_id(char *file, int format);
87
88int MAIN(int, char **);
89
90int MAIN(int argc, char **argv)
91{
92    SSL_SESSION *x = NULL;
93    X509 *peer = NULL;
94    int ret = 1, i, num, badops = 0;
95    BIO *out = NULL;
96    int informat, outformat;
97    char *infile = NULL, *outfile = NULL, *context = NULL;
98    int cert = 0, noout = 0, text = 0;
99    const char **pp;
100
101    apps_startup();
102
103    if (bio_err == NULL)
104        if ((bio_err = BIO_new(BIO_s_file())) != NULL)
105            BIO_set_fp(bio_err, stderr, BIO_NOCLOSE | BIO_FP_TEXT);
106
107    informat = FORMAT_PEM;
108    outformat = FORMAT_PEM;
109
110    argc--;
111    argv++;
112    num = 0;
113    while (argc >= 1) {
114        if (strcmp(*argv, "-inform") == 0) {
115            if (--argc < 1)
116                goto bad;
117            informat = str2fmt(*(++argv));
118        } else if (strcmp(*argv, "-outform") == 0) {
119            if (--argc < 1)
120                goto bad;
121            outformat = str2fmt(*(++argv));
122        } else if (strcmp(*argv, "-in") == 0) {
123            if (--argc < 1)
124                goto bad;
125            infile = *(++argv);
126        } else if (strcmp(*argv, "-out") == 0) {
127            if (--argc < 1)
128                goto bad;
129            outfile = *(++argv);
130        } else if (strcmp(*argv, "-text") == 0)
131            text = ++num;
132        else if (strcmp(*argv, "-cert") == 0)
133            cert = ++num;
134        else if (strcmp(*argv, "-noout") == 0)
135            noout = ++num;
136        else if (strcmp(*argv, "-context") == 0) {
137            if (--argc < 1)
138                goto bad;
139            context = *++argv;
140        } else {
141            BIO_printf(bio_err, "unknown option %s\n", *argv);
142            badops = 1;
143            break;
144        }
145        argc--;
146        argv++;
147    }
148
149    if (badops) {
150 bad:
151        for (pp = sess_id_usage; (*pp != NULL); pp++)
152            BIO_printf(bio_err, "%s", *pp);
153        goto end;
154    }
155
156    ERR_load_crypto_strings();
157    x = load_sess_id(infile, informat);
158    if (x == NULL) {
159        goto end;
160    }
161    peer = SSL_SESSION_get0_peer(x);
162
163    if (context) {
164        size_t ctx_len = strlen(context);
165        if (ctx_len > SSL_MAX_SID_CTX_LENGTH) {
166            BIO_printf(bio_err, "Context too long\n");
167            goto end;
168        }
169        SSL_SESSION_set1_id_context(x, (unsigned char *)context, ctx_len);
170    }
171#ifdef undef
172    /* just testing for memory leaks :-) */
173    {
174        SSL_SESSION *s;
175        char buf[1024 * 10], *p;
176        int i;
177
178        s = SSL_SESSION_new();
179
180        p = &buf;
181        i = i2d_SSL_SESSION(x, &p);
182        p = &buf;
183        d2i_SSL_SESSION(&s, &p, (long)i);
184        p = &buf;
185        d2i_SSL_SESSION(&s, &p, (long)i);
186        p = &buf;
187        d2i_SSL_SESSION(&s, &p, (long)i);
188        SSL_SESSION_free(s);
189    }
190#endif
191
192    if (!noout || text) {
193        out = BIO_new(BIO_s_file());
194        if (out == NULL) {
195            ERR_print_errors(bio_err);
196            goto end;
197        }
198
199        if (outfile == NULL) {
200            BIO_set_fp(out, stdout, BIO_NOCLOSE);
201#ifdef OPENSSL_SYS_VMS
202            {
203                BIO *tmpbio = BIO_new(BIO_f_linebuffer());
204                out = BIO_push(tmpbio, out);
205            }
206#endif
207        } else {
208            if (BIO_write_filename(out, outfile) <= 0) {
209                perror(outfile);
210                goto end;
211            }
212        }
213    }
214
215    if (text) {
216        SSL_SESSION_print(out, x);
217
218        if (cert) {
219            if (peer == NULL)
220                BIO_puts(out, "No certificate present\n");
221            else
222                X509_print(out, peer);
223        }
224    }
225
226    if (!noout && !cert) {
227        if (outformat == FORMAT_ASN1)
228            i = i2d_SSL_SESSION_bio(out, x);
229        else if (outformat == FORMAT_PEM)
230            i = PEM_write_bio_SSL_SESSION(out, x);
231        else {
232            BIO_printf(bio_err, "bad output format specified for outfile\n");
233            goto end;
234        }
235        if (!i) {
236            BIO_printf(bio_err, "unable to write SSL_SESSION\n");
237            goto end;
238        }
239    } else if (!noout && (peer != NULL)) { /* just print the certificate */
240        if (outformat == FORMAT_ASN1)
241            i = (int)i2d_X509_bio(out, peer);
242        else if (outformat == FORMAT_PEM)
243            i = PEM_write_bio_X509(out, peer);
244        else {
245            BIO_printf(bio_err, "bad output format specified for outfile\n");
246            goto end;
247        }
248        if (!i) {
249            BIO_printf(bio_err, "unable to write X509\n");
250            goto end;
251        }
252    }
253    ret = 0;
254 end:
255    if (out != NULL)
256        BIO_free_all(out);
257    if (x != NULL)
258        SSL_SESSION_free(x);
259    apps_shutdown();
260    OPENSSL_EXIT(ret);
261}
262
263static SSL_SESSION *load_sess_id(char *infile, int format)
264{
265    SSL_SESSION *x = NULL;
266    BIO *in = NULL;
267
268    in = BIO_new(BIO_s_file());
269    if (in == NULL) {
270        ERR_print_errors(bio_err);
271        goto end;
272    }
273
274    if (infile == NULL)
275        BIO_set_fp(in, stdin, BIO_NOCLOSE);
276    else {
277        if (BIO_read_filename(in, infile) <= 0) {
278            perror(infile);
279            goto end;
280        }
281    }
282    if (format == FORMAT_ASN1)
283        x = d2i_SSL_SESSION_bio(in, NULL);
284    else if (format == FORMAT_PEM)
285        x = PEM_read_bio_SSL_SESSION(in, NULL, NULL, NULL);
286    else {
287        BIO_printf(bio_err, "bad input format specified for input crl\n");
288        goto end;
289    }
290    if (x == NULL) {
291        BIO_printf(bio_err, "unable to load SSL_SESSION\n");
292        ERR_print_errors(bio_err);
293        goto end;
294    }
295
296 end:
297    if (in != NULL)
298        BIO_free(in);
299    return (x);
300}
301