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