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