xref: /openbsd-src/usr.bin/openssl/sess_id.c (revision b0100c001bd51e907fb99299d4d3a1255d0e4452)
1*b0100c00Stb /* $OpenBSD: sess_id.c,v 1.13 2025/01/02 12:31:44 tb Exp $ */
2dab3f910Sjsing /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
3dab3f910Sjsing  * All rights reserved.
4dab3f910Sjsing  *
5dab3f910Sjsing  * This package is an SSL implementation written
6dab3f910Sjsing  * by Eric Young (eay@cryptsoft.com).
7dab3f910Sjsing  * The implementation was written so as to conform with Netscapes SSL.
8dab3f910Sjsing  *
9dab3f910Sjsing  * This library is free for commercial and non-commercial use as long as
10dab3f910Sjsing  * the following conditions are aheared to.  The following conditions
11dab3f910Sjsing  * apply to all code found in this distribution, be it the RC4, RSA,
12dab3f910Sjsing  * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
13dab3f910Sjsing  * included with this distribution is covered by the same copyright terms
14dab3f910Sjsing  * except that the holder is Tim Hudson (tjh@cryptsoft.com).
15dab3f910Sjsing  *
16dab3f910Sjsing  * Copyright remains Eric Young's, and as such any Copyright notices in
17dab3f910Sjsing  * the code are not to be removed.
18dab3f910Sjsing  * If this package is used in a product, Eric Young should be given attribution
19dab3f910Sjsing  * as the author of the parts of the library used.
20dab3f910Sjsing  * This can be in the form of a textual message at program startup or
21dab3f910Sjsing  * in documentation (online or textual) provided with the package.
22dab3f910Sjsing  *
23dab3f910Sjsing  * Redistribution and use in source and binary forms, with or without
24dab3f910Sjsing  * modification, are permitted provided that the following conditions
25dab3f910Sjsing  * are met:
26dab3f910Sjsing  * 1. Redistributions of source code must retain the copyright
27dab3f910Sjsing  *    notice, this list of conditions and the following disclaimer.
28dab3f910Sjsing  * 2. Redistributions in binary form must reproduce the above copyright
29dab3f910Sjsing  *    notice, this list of conditions and the following disclaimer in the
30dab3f910Sjsing  *    documentation and/or other materials provided with the distribution.
31dab3f910Sjsing  * 3. All advertising materials mentioning features or use of this software
32dab3f910Sjsing  *    must display the following acknowledgement:
33dab3f910Sjsing  *    "This product includes cryptographic software written by
34dab3f910Sjsing  *     Eric Young (eay@cryptsoft.com)"
35dab3f910Sjsing  *    The word 'cryptographic' can be left out if the rouines from the library
36dab3f910Sjsing  *    being used are not cryptographic related :-).
37dab3f910Sjsing  * 4. If you include any Windows specific code (or a derivative thereof) from
38dab3f910Sjsing  *    the apps directory (application code) you must include an acknowledgement:
39dab3f910Sjsing  *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
40dab3f910Sjsing  *
41dab3f910Sjsing  * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
42dab3f910Sjsing  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
43dab3f910Sjsing  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
44dab3f910Sjsing  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
45dab3f910Sjsing  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
46dab3f910Sjsing  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
47dab3f910Sjsing  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
48dab3f910Sjsing  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
49dab3f910Sjsing  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
50dab3f910Sjsing  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
51dab3f910Sjsing  * SUCH DAMAGE.
52dab3f910Sjsing  *
53dab3f910Sjsing  * The licence and distribution terms for any publically available version or
54dab3f910Sjsing  * derivative of this code cannot be changed.  i.e. this code cannot simply be
55dab3f910Sjsing  * copied and put under another distribution licence
56dab3f910Sjsing  * [including the GNU Public Licence.]
57dab3f910Sjsing  */
58dab3f910Sjsing 
59dab3f910Sjsing #include <stdio.h>
60dab3f910Sjsing #include <stdlib.h>
61dab3f910Sjsing #include <string.h>
62dab3f910Sjsing 
63dab3f910Sjsing #include "apps.h"
64dab3f910Sjsing 
65dab3f910Sjsing #include <openssl/bio.h>
66dab3f910Sjsing #include <openssl/err.h>
67dab3f910Sjsing #include <openssl/pem.h>
68dab3f910Sjsing #include <openssl/ssl.h>
69dab3f910Sjsing #include <openssl/x509.h>
70dab3f910Sjsing 
71bc6c34e1Sdoug static struct {
72bc6c34e1Sdoug 	int cert;
73bc6c34e1Sdoug 	char *context;
74bc6c34e1Sdoug 	char *infile;
75bc6c34e1Sdoug 	int informat;
76bc6c34e1Sdoug 	int noout;
77bc6c34e1Sdoug 	char *outfile;
78bc6c34e1Sdoug 	int outformat;
79bc6c34e1Sdoug 	int text;
80e7718adaStb } cfg;
81bc6c34e1Sdoug 
82ea149709Sguenther static const struct option sess_id_options[] = {
83bc6c34e1Sdoug 	{
84bc6c34e1Sdoug 		.name = "cert",
85bc6c34e1Sdoug 		.desc = "Output certificate if present in session",
86bc6c34e1Sdoug 		.type = OPTION_FLAG,
87e7718adaStb 		.opt.flag = &cfg.cert,
88bc6c34e1Sdoug 	},
89bc6c34e1Sdoug 	{
90bc6c34e1Sdoug 		.name = "context",
91bc6c34e1Sdoug 		.argname = "id",
92bc6c34e1Sdoug 		.desc = "Set the session ID context for output",
93bc6c34e1Sdoug 		.type = OPTION_ARG,
94e7718adaStb 		.opt.arg = &cfg.context,
95bc6c34e1Sdoug 	},
96bc6c34e1Sdoug 	{
97bc6c34e1Sdoug 		.name = "in",
98bc6c34e1Sdoug 		.argname = "file",
99bc6c34e1Sdoug 		.desc = "Input file (default stdin)",
100bc6c34e1Sdoug 		.type = OPTION_ARG,
101e7718adaStb 		.opt.arg = &cfg.infile,
102bc6c34e1Sdoug 	},
103bc6c34e1Sdoug 	{
104bc6c34e1Sdoug 		.name = "inform",
105bc6c34e1Sdoug 		.argname = "format",
106bc6c34e1Sdoug 		.desc = "Input format (DER or PEM (default))",
107bc6c34e1Sdoug 		.type = OPTION_ARG_FORMAT,
108e7718adaStb 		.opt.value = &cfg.informat,
109bc6c34e1Sdoug 	},
110bc6c34e1Sdoug 	{
111bc6c34e1Sdoug 		.name = "noout",
112bc6c34e1Sdoug 		.desc = "Do not output the encoded session info",
113bc6c34e1Sdoug 		.type = OPTION_FLAG,
114e7718adaStb 		.opt.flag = &cfg.noout,
115bc6c34e1Sdoug 	},
116bc6c34e1Sdoug 	{
117bc6c34e1Sdoug 		.name = "out",
118bc6c34e1Sdoug 		.argname = "file",
119bc6c34e1Sdoug 		.desc = "Output file (default stdout)",
120bc6c34e1Sdoug 		.type = OPTION_ARG,
121e7718adaStb 		.opt.arg = &cfg.outfile,
122bc6c34e1Sdoug 	},
123bc6c34e1Sdoug 	{
124bc6c34e1Sdoug 		.name = "outform",
125bc6c34e1Sdoug 		.argname = "format",
126bc6c34e1Sdoug 		.desc = "Output format (DER or PEM (default))",
127bc6c34e1Sdoug 		.type = OPTION_ARG_FORMAT,
128e7718adaStb 		.opt.value = &cfg.outformat,
129bc6c34e1Sdoug 	},
130bc6c34e1Sdoug 	{
131bc6c34e1Sdoug 		.name = "text",
132bc6c34e1Sdoug 		.desc = "Print various public or private key components in"
133bc6c34e1Sdoug 		    " plain text",
134bc6c34e1Sdoug 		.type = OPTION_FLAG,
135e7718adaStb 		.opt.flag = &cfg.text,
136bc6c34e1Sdoug 	},
137bc6c34e1Sdoug 	{ NULL }
138dab3f910Sjsing };
139dab3f910Sjsing 
140bc6c34e1Sdoug static void
141bc6c34e1Sdoug sess_id_usage(void)
142bc6c34e1Sdoug {
143bc6c34e1Sdoug 	fprintf(stderr,
144bc6c34e1Sdoug 	    "usage: sess_id [-cert] [-context id] [-in file] [-inform fmt] "
145bc6c34e1Sdoug 	    "[-noout]\n"
146bc6c34e1Sdoug 	    "    [-out file] [-outform fmt] [-text]\n\n");
147bc6c34e1Sdoug 	options_usage(sess_id_options);
148bc6c34e1Sdoug }
149dab3f910Sjsing 
150bc6c34e1Sdoug static SSL_SESSION *load_sess_id(char *file, int format);
151dab3f910Sjsing 
152dab3f910Sjsing int
153dab3f910Sjsing sess_id_main(int argc, char **argv)
154dab3f910Sjsing {
155dab3f910Sjsing 	SSL_SESSION *x = NULL;
156dab3f910Sjsing 	X509 *peer = NULL;
157bc6c34e1Sdoug 	int ret = 1, i;
158dab3f910Sjsing 	BIO *out = NULL;
159dab3f910Sjsing 
16051811eadSderaadt 	if (pledge("stdio cpath wpath rpath", NULL) == -1) {
1619bc487adSdoug 		perror("pledge");
162e370f0eeSdoug 		exit(1);
163e370f0eeSdoug 	}
1649bc487adSdoug 
165e7718adaStb 	memset(&cfg, 0, sizeof(cfg));
166dab3f910Sjsing 
167e7718adaStb 	cfg.informat = FORMAT_PEM;
168e7718adaStb 	cfg.outformat = FORMAT_PEM;
169bc6c34e1Sdoug 
170bc6c34e1Sdoug 	if (options_parse(argc, argv, sess_id_options, NULL, NULL) != 0) {
171bc6c34e1Sdoug 		sess_id_usage();
172bc6c34e1Sdoug 		return (1);
173dab3f910Sjsing 	}
174dab3f910Sjsing 
175e7718adaStb 	x = load_sess_id(cfg.infile, cfg.informat);
176dab3f910Sjsing 	if (x == NULL) {
177dab3f910Sjsing 		goto end;
178dab3f910Sjsing 	}
179dab3f910Sjsing 	peer = SSL_SESSION_get0_peer(x);
180dab3f910Sjsing 
181e7718adaStb 	if (cfg.context) {
182e7718adaStb 		size_t ctx_len = strlen(cfg.context);
183dab3f910Sjsing 		if (ctx_len > SSL_MAX_SID_CTX_LENGTH) {
184dab3f910Sjsing 			BIO_printf(bio_err, "Context too long\n");
185dab3f910Sjsing 			goto end;
186dab3f910Sjsing 		}
187bc6c34e1Sdoug 		SSL_SESSION_set1_id_context(x,
188e7718adaStb 		    (unsigned char *)cfg.context, ctx_len);
189dab3f910Sjsing 	}
190dab3f910Sjsing 
191e7718adaStb 	if (!cfg.noout || cfg.text) {
192dab3f910Sjsing 		out = BIO_new(BIO_s_file());
193dab3f910Sjsing 		if (out == NULL) {
194dab3f910Sjsing 			ERR_print_errors(bio_err);
195dab3f910Sjsing 			goto end;
196dab3f910Sjsing 		}
197e7718adaStb 		if (cfg.outfile == NULL) {
198dab3f910Sjsing 			BIO_set_fp(out, stdout, BIO_NOCLOSE);
199dab3f910Sjsing 		} else {
200e7718adaStb 			if (BIO_write_filename(out, cfg.outfile)
201bc6c34e1Sdoug 			    <= 0) {
202e7718adaStb 				perror(cfg.outfile);
203dab3f910Sjsing 				goto end;
204dab3f910Sjsing 			}
205dab3f910Sjsing 		}
206dab3f910Sjsing 	}
207e7718adaStb 	if (cfg.text) {
208dab3f910Sjsing 		SSL_SESSION_print(out, x);
209dab3f910Sjsing 
210e7718adaStb 		if (cfg.cert) {
211dab3f910Sjsing 			if (peer == NULL)
212dab3f910Sjsing 				BIO_puts(out, "No certificate present\n");
213dab3f910Sjsing 			else
214dab3f910Sjsing 				X509_print(out, peer);
215dab3f910Sjsing 		}
216dab3f910Sjsing 	}
217e7718adaStb 	if (!cfg.noout && !cfg.cert) {
218e7718adaStb 		if (cfg.outformat == FORMAT_ASN1)
219dab3f910Sjsing 			i = i2d_SSL_SESSION_bio(out, x);
220e7718adaStb 		else if (cfg.outformat == FORMAT_PEM)
221dab3f910Sjsing 			i = PEM_write_bio_SSL_SESSION(out, x);
222dab3f910Sjsing 		else {
223bc6c34e1Sdoug 			BIO_printf(bio_err,
224bc6c34e1Sdoug 			    "bad output format specified for outfile\n");
225dab3f910Sjsing 			goto end;
226dab3f910Sjsing 		}
227dab3f910Sjsing 		if (!i) {
228dab3f910Sjsing 			BIO_printf(bio_err, "unable to write SSL_SESSION\n");
229dab3f910Sjsing 			goto end;
230dab3f910Sjsing 		}
231e7718adaStb 	} else if (!cfg.noout && (peer != NULL)) {
232bc6c34e1Sdoug 		/* just print the certificate */
233e7718adaStb 		if (cfg.outformat == FORMAT_ASN1)
234dab3f910Sjsing 			i = (int) i2d_X509_bio(out, peer);
235e7718adaStb 		else if (cfg.outformat == FORMAT_PEM)
236dab3f910Sjsing 			i = PEM_write_bio_X509(out, peer);
237dab3f910Sjsing 		else {
238bc6c34e1Sdoug 			BIO_printf(bio_err,
239bc6c34e1Sdoug 			    "bad output format specified for outfile\n");
240dab3f910Sjsing 			goto end;
241dab3f910Sjsing 		}
242dab3f910Sjsing 		if (!i) {
243dab3f910Sjsing 			BIO_printf(bio_err, "unable to write X509\n");
244dab3f910Sjsing 			goto end;
245dab3f910Sjsing 		}
246dab3f910Sjsing 	}
247dab3f910Sjsing 	ret = 0;
248bc6c34e1Sdoug 
249dab3f910Sjsing  end:
250dab3f910Sjsing 	BIO_free_all(out);
251dab3f910Sjsing 	SSL_SESSION_free(x);
252dab3f910Sjsing 
253dab3f910Sjsing 	return (ret);
254dab3f910Sjsing }
255dab3f910Sjsing 
256dab3f910Sjsing static SSL_SESSION *
257dab3f910Sjsing load_sess_id(char *infile, int format)
258dab3f910Sjsing {
259dab3f910Sjsing 	SSL_SESSION *x = NULL;
260dab3f910Sjsing 	BIO *in = NULL;
261dab3f910Sjsing 
262dab3f910Sjsing 	in = BIO_new(BIO_s_file());
263dab3f910Sjsing 	if (in == NULL) {
264dab3f910Sjsing 		ERR_print_errors(bio_err);
265dab3f910Sjsing 		goto end;
266dab3f910Sjsing 	}
267dab3f910Sjsing 	if (infile == NULL)
268dab3f910Sjsing 		BIO_set_fp(in, stdin, BIO_NOCLOSE);
269dab3f910Sjsing 	else {
270dab3f910Sjsing 		if (BIO_read_filename(in, infile) <= 0) {
271dab3f910Sjsing 			perror(infile);
272dab3f910Sjsing 			goto end;
273dab3f910Sjsing 		}
274dab3f910Sjsing 	}
275dab3f910Sjsing 	if (format == FORMAT_ASN1)
276dab3f910Sjsing 		x = d2i_SSL_SESSION_bio(in, NULL);
277dab3f910Sjsing 	else if (format == FORMAT_PEM)
278dab3f910Sjsing 		x = PEM_read_bio_SSL_SESSION(in, NULL, NULL, NULL);
279dab3f910Sjsing 	else {
280bc6c34e1Sdoug 		BIO_printf(bio_err,
281bc6c34e1Sdoug 		    "bad input format specified for input crl\n");
282dab3f910Sjsing 		goto end;
283dab3f910Sjsing 	}
284dab3f910Sjsing 	if (x == NULL) {
285dab3f910Sjsing 		BIO_printf(bio_err, "unable to load SSL_SESSION\n");
286dab3f910Sjsing 		ERR_print_errors(bio_err);
287dab3f910Sjsing 		goto end;
288dab3f910Sjsing 	}
289dab3f910Sjsing  end:
290dab3f910Sjsing 	BIO_free(in);
291dab3f910Sjsing 	return (x);
292dab3f910Sjsing }
293