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 if (!opt_check_rest_arg(NULL)) 102 goto opthelp; 103 104 x = load_sess_id(infile, informat); 105 if (x == NULL) { 106 goto end; 107 } 108 peer = SSL_SESSION_get0_peer(x); 109 110 if (context != NULL) { 111 size_t ctx_len = strlen(context); 112 if (ctx_len > SSL_MAX_SID_CTX_LENGTH) { 113 BIO_printf(bio_err, "Context too long\n"); 114 goto end; 115 } 116 if (!SSL_SESSION_set1_id_context(x, (unsigned char *)context, 117 ctx_len)) { 118 BIO_printf(bio_err, "Error setting id context\n"); 119 goto end; 120 } 121 } 122 123 if (!noout || text) { 124 out = bio_open_default(outfile, 'w', outformat); 125 if (out == NULL) 126 goto end; 127 } 128 129 if (text) { 130 SSL_SESSION_print(out, x); 131 132 if (cert) { 133 if (peer == NULL) 134 BIO_puts(out, "No certificate present\n"); 135 else 136 X509_print(out, peer); 137 } 138 } 139 140 if (!noout && !cert) { 141 if (outformat == FORMAT_ASN1) { 142 i = i2d_SSL_SESSION_bio(out, x); 143 } else if (outformat == FORMAT_PEM) { 144 i = PEM_write_bio_SSL_SESSION(out, x); 145 } else if (outformat == FORMAT_NSS) { 146 i = SSL_SESSION_print_keylog(out, x); 147 } else { 148 BIO_printf(bio_err, "bad output format specified for outfile\n"); 149 goto end; 150 } 151 if (!i) { 152 BIO_printf(bio_err, "unable to write SSL_SESSION\n"); 153 goto end; 154 } 155 } else if (!noout && (peer != NULL)) { /* just print the certificate */ 156 if (outformat == FORMAT_ASN1) { 157 i = (int)i2d_X509_bio(out, peer); 158 } else if (outformat == FORMAT_PEM) { 159 i = PEM_write_bio_X509(out, peer); 160 } else { 161 BIO_printf(bio_err, "bad output format specified for outfile\n"); 162 goto end; 163 } 164 if (!i) { 165 BIO_printf(bio_err, "unable to write X509\n"); 166 goto end; 167 } 168 } 169 ret = 0; 170 end: 171 BIO_free_all(out); 172 SSL_SESSION_free(x); 173 return ret; 174 } 175 176 static SSL_SESSION *load_sess_id(char *infile, int format) 177 { 178 SSL_SESSION *x = NULL; 179 BIO *in = NULL; 180 181 in = bio_open_default(infile, 'r', format); 182 if (in == NULL) 183 goto end; 184 if (format == FORMAT_ASN1) 185 x = d2i_SSL_SESSION_bio(in, NULL); 186 else 187 x = PEM_read_bio_SSL_SESSION(in, NULL, NULL, NULL); 188 if (x == NULL) { 189 BIO_printf(bio_err, "unable to load SSL_SESSION\n"); 190 ERR_print_errors(bio_err); 191 goto end; 192 } 193 194 end: 195 BIO_free(in); 196 return x; 197 } 198