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