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