1 /* 2 * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved. 3 * 4 * Licensed under the Apache License 2.0 (the "License"). You may not use 5 * this file except in compliance with the License. You can obtain a copy 6 * in the file LICENSE in the source distribution or at 7 * https://www.openssl.org/source/license.html 8 */ 9 10 #include <stdio.h> 11 #include <stdlib.h> 12 #include <string.h> 13 #include "apps.h" 14 #include "progs.h" 15 #include <openssl/bio.h> 16 #include <openssl/err.h> 17 #include <openssl/x509.h> 18 #include <openssl/pem.h> 19 #include <openssl/ssl.h> 20 21 typedef enum OPTION_choice { 22 OPT_COMMON, 23 OPT_INFORM, 24 OPT_OUTFORM, 25 OPT_IN, 26 OPT_OUT, 27 OPT_TEXT, 28 OPT_CERT, 29 OPT_NOOUT, 30 OPT_CONTEXT 31 } OPTION_CHOICE; 32 33 const OPTIONS sess_id_options[] = { 34 OPT_SECTION("General"), 35 { "help", OPT_HELP, '-', "Display this summary" }, 36 { "context", OPT_CONTEXT, 's', "Set the session ID context" }, 37 38 OPT_SECTION("Input"), 39 { "in", OPT_IN, 's', "Input file - default stdin" }, 40 { "inform", OPT_INFORM, 'F', "Input format - default PEM (DER or PEM)" }, 41 42 OPT_SECTION("Output"), 43 { "out", OPT_OUT, '>', "Output file - default stdout" }, 44 { "outform", OPT_OUTFORM, 'f', 45 "Output format - default PEM (PEM, DER or NSS)" }, 46 { "text", OPT_TEXT, '-', "Print ssl session id details" }, 47 { "cert", OPT_CERT, '-', "Output certificate " }, 48 { "noout", OPT_NOOUT, '-', "Don't output the encoded session info" }, 49 { NULL } 50 }; 51 52 static SSL_SESSION *load_sess_id(char *file, int format); 53 54 int sess_id_main(int argc, char **argv) 55 { 56 SSL_SESSION *x = NULL; 57 X509 *peer = NULL; 58 BIO *out = NULL; 59 char *infile = NULL, *outfile = NULL, *context = NULL, *prog; 60 int informat = FORMAT_PEM, outformat = FORMAT_PEM; 61 int cert = 0, noout = 0, text = 0, ret = 1, i, num = 0; 62 OPTION_CHOICE o; 63 64 prog = opt_init(argc, argv, sess_id_options); 65 while ((o = opt_next()) != OPT_EOF) { 66 switch (o) { 67 case OPT_EOF: 68 case OPT_ERR: 69 opthelp: 70 BIO_printf(bio_err, "%s: Use -help for summary.\n", prog); 71 goto end; 72 case OPT_HELP: 73 opt_help(sess_id_options); 74 ret = 0; 75 goto end; 76 case OPT_INFORM: 77 if (!opt_format(opt_arg(), OPT_FMT_PEMDER, &informat)) 78 goto opthelp; 79 break; 80 case OPT_OUTFORM: 81 if (!opt_format(opt_arg(), OPT_FMT_PEMDER | OPT_FMT_NSS, 82 &outformat)) 83 goto opthelp; 84 break; 85 case OPT_IN: 86 infile = opt_arg(); 87 break; 88 case OPT_OUT: 89 outfile = opt_arg(); 90 break; 91 case OPT_TEXT: 92 text = ++num; 93 break; 94 case OPT_CERT: 95 cert = ++num; 96 break; 97 case OPT_NOOUT: 98 noout = ++num; 99 break; 100 case OPT_CONTEXT: 101 context = opt_arg(); 102 break; 103 } 104 } 105 106 /* No extra arguments. */ 107 if (!opt_check_rest_arg(NULL)) 108 goto opthelp; 109 110 x = load_sess_id(infile, informat); 111 if (x == NULL) { 112 goto end; 113 } 114 peer = SSL_SESSION_get0_peer(x); 115 116 if (context != NULL) { 117 size_t ctx_len = strlen(context); 118 if (ctx_len > SSL_MAX_SID_CTX_LENGTH) { 119 BIO_printf(bio_err, "Context too long\n"); 120 goto end; 121 } 122 if (!SSL_SESSION_set1_id_context(x, (unsigned char *)context, 123 ctx_len)) { 124 BIO_printf(bio_err, "Error setting id context\n"); 125 goto end; 126 } 127 } 128 129 if (!noout || text) { 130 out = bio_open_default(outfile, 'w', outformat); 131 if (out == NULL) 132 goto end; 133 } 134 135 if (text) { 136 SSL_SESSION_print(out, x); 137 138 if (cert) { 139 if (peer == NULL) 140 BIO_puts(out, "No certificate present\n"); 141 else 142 X509_print(out, peer); 143 } 144 } 145 146 if (!noout && !cert) { 147 if (outformat == FORMAT_ASN1) { 148 i = i2d_SSL_SESSION_bio(out, x); 149 } else if (outformat == FORMAT_PEM) { 150 i = PEM_write_bio_SSL_SESSION(out, x); 151 } else if (outformat == FORMAT_NSS) { 152 i = SSL_SESSION_print_keylog(out, x); 153 } else { 154 BIO_printf(bio_err, "bad output format specified for outfile\n"); 155 goto end; 156 } 157 if (!i) { 158 BIO_printf(bio_err, "unable to write SSL_SESSION\n"); 159 goto end; 160 } 161 } else if (!noout && (peer != NULL)) { /* just print the certificate */ 162 if (outformat == FORMAT_ASN1) { 163 i = (int)i2d_X509_bio(out, peer); 164 } else if (outformat == FORMAT_PEM) { 165 i = PEM_write_bio_X509(out, peer); 166 } else { 167 BIO_printf(bio_err, "bad output format specified for outfile\n"); 168 goto end; 169 } 170 if (!i) { 171 BIO_printf(bio_err, "unable to write X509\n"); 172 goto end; 173 } 174 } 175 ret = 0; 176 end: 177 BIO_free_all(out); 178 SSL_SESSION_free(x); 179 return ret; 180 } 181 182 static SSL_SESSION *load_sess_id(char *infile, int format) 183 { 184 SSL_SESSION *x = NULL; 185 BIO *in = NULL; 186 187 in = bio_open_default(infile, 'r', format); 188 if (in == NULL) 189 goto end; 190 if (format == FORMAT_ASN1) 191 x = d2i_SSL_SESSION_bio(in, NULL); 192 else 193 x = PEM_read_bio_SSL_SESSION(in, NULL, NULL, NULL); 194 if (x == NULL) { 195 BIO_printf(bio_err, "unable to load SSL_SESSION\n"); 196 ERR_print_errors(bio_err); 197 goto end; 198 } 199 200 end: 201 BIO_free(in); 202 return x; 203 } 204