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