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