Get s_client to report on whether early data was accepted or not
[openssl.git] / apps / s_cb.c
index 2c7fce5272f56f12ea583514e95cfaf1a41f9cbc..50bd965dd1587da2553facdda8274cc380f77e6e 100644 (file)
@@ -32,6 +32,13 @@ VERIFY_CB_ARGS verify_args = { 0, 0, X509_V_OK, 0 };
 static unsigned char cookie_secret[COOKIE_SECRET_LENGTH];
 static int cookie_initialized = 0;
 #endif
+static BIO *bio_keylog = NULL;
+static unsigned long nmflag = XN_FLAG_ONELINE;
+
+int set_nameopt(const char *arg)
+{
+  return set_name_ex(&nmflag, arg);
+}
 
 static const char *lookup(int val, const STRINT_PAIR* list, const char* def)
 {
@@ -55,7 +62,7 @@ int verify_callback(int ok, X509_STORE_CTX *ctx)
         if (err_cert) {
             X509_NAME_print_ex(bio_err,
                                X509_get_subject_name(err_cert),
-                               0, XN_FLAG_ONELINE);
+                               0, nmflag);
             BIO_puts(bio_err, "\n");
         } else
             BIO_puts(bio_err, "<no cert>\n");
@@ -76,7 +83,7 @@ int verify_callback(int ok, X509_STORE_CTX *ctx)
     case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT:
         BIO_puts(bio_err, "issuer= ");
         X509_NAME_print_ex(bio_err, X509_get_issuer_name(err_cert),
-                           0, XN_FLAG_ONELINE);
+                           0, nmflag);
         BIO_puts(bio_err, "\n");
         break;
     case X509_V_ERR_CERT_NOT_YET_VALID:
@@ -238,7 +245,7 @@ static int do_print_sigalgs(BIO *out, SSL *s, int shared)
     int i, nsig, client;
     client = SSL_is_server(s) ? 0 : 1;
     if (shared)
-        nsig = SSL_get_shared_sigalgs(s, -1, NULL, NULL, NULL, NULL, NULL);
+        nsig = SSL_get_shared_sigalgs(s, 0, NULL, NULL, NULL, NULL, NULL);
     else
         nsig = SSL_get_sigalgs(s, -1, NULL, NULL, NULL, NULL, NULL);
     if (nsig == 0)
@@ -261,7 +268,7 @@ static int do_print_sigalgs(BIO *out, SSL *s, int shared)
             SSL_get_sigalgs(s, i, &sign_nid, &hash_nid, NULL, &rsign, &rhash);
         if (i)
             BIO_puts(out, ":");
-        sstr= get_sigtype(sign_nid);
+        sstr = get_sigtype(sign_nid);
         if (sstr)
             BIO_printf(out, "%s+", sstr);
         else
@@ -285,7 +292,7 @@ int ssl_print_sigalgs(BIO *out, SSL *s)
     if (SSL_get_peer_signature_nid(s, &nid))
         BIO_printf(out, "Peer signing digest: %s\n", OBJ_nid2sn(nid));
     if (SSL_get_peer_signature_type_nid(s, &nid))
-        BIO_printf(bio_err, "Peer signature type: %s\n", get_sigtype(nid));
+        BIO_printf(out, "Peer signature type: %s\n", get_sigtype(nid));
     return 1;
 }
 
@@ -812,7 +819,7 @@ static int set_cert_cb(SSL *ssl, void *arg)
         rv = SSL_check_chain(ssl, exc->cert, exc->key, exc->chain);
         BIO_printf(bio_err, "Checking cert chain %d:\nSubject: ", i);
         X509_NAME_print_ex(bio_err, X509_get_subject_name(exc->cert), 0,
-                           XN_FLAG_ONELINE);
+                           nmflag);
         BIO_puts(bio_err, "\n");
         print_chain_flags(ssl, rv);
         if (rv & CERT_PKEY_VALID) {
@@ -943,6 +950,7 @@ int args_excert(int opt, SSL_EXCERT **pexc)
             BIO_printf(bio_err, "%s: Error adding xcert\n", opt_getprog());
             goto err;
         }
+        *pexc = exc;
         exc->certfile = opt_arg();
         break;
     case OPT_X_KEY:
@@ -1088,7 +1096,6 @@ void print_ssl_summary(SSL *s)
 {
     const SSL_CIPHER *c;
     X509 *peer;
-    /* const char *pnam = SSL_is_server(s) ? "client" : "server"; */
 
     BIO_printf(bio_err, "Protocol version: %s\n", SSL_get_version(s));
     print_raw_cipherlist(s);
@@ -1101,7 +1108,7 @@ void print_ssl_summary(SSL *s)
 
         BIO_puts(bio_err, "Peer certificate: ");
         X509_NAME_print_ex(bio_err, X509_get_subject_name(peer),
-                           0, XN_FLAG_ONELINE);
+                           0, nmflag);
         BIO_puts(bio_err, "\n");
         if (SSL_get_peer_signature_nid(s, &nid))
             BIO_printf(bio_err, "Hash used: %s\n", OBJ_nid2sn(nid));
@@ -1355,3 +1362,50 @@ void ssl_ctx_security_debug(SSL_CTX *ctx, int verbose)
     SSL_CTX_set_security_callback(ctx, security_callback_debug);
     SSL_CTX_set0_security_ex_data(ctx, &sdb);
 }
+
+static void keylog_callback(const SSL *ssl, const char *line)
+{
+    if (bio_keylog == NULL) {
+        BIO_printf(bio_err, "Keylog callback is invoked without valid file!\n");
+        return;
+    }
+
+    /*
+     * There might be concurrent writers to the keylog file, so we must ensure
+     * that the given line is written at once.
+     */
+    BIO_printf(bio_keylog, "%s\n", line);
+    (void)BIO_flush(bio_keylog);
+}
+
+int set_keylog_file(SSL_CTX *ctx, const char *keylog_file)
+{
+    /* Close any open files */
+    BIO_free_all(bio_keylog);
+    bio_keylog = NULL;
+
+    if (ctx == NULL || keylog_file == NULL) {
+        /* Keylogging is disabled, OK. */
+        return 0;
+    }
+
+    /*
+     * Append rather than write in order to allow concurrent modification.
+     * Furthermore, this preserves existing keylog files which is useful when
+     * the tool is run multiple times.
+     */
+    bio_keylog = BIO_new_file(keylog_file, "a");
+    if (bio_keylog == NULL) {
+        BIO_printf(bio_err, "Error writing keylog file %s\n", keylog_file);
+        return 1;
+    }
+
+    /* Write a header for seekable, empty files (this excludes pipes). */
+    if (BIO_tell(bio_keylog) == 0) {
+        BIO_puts(bio_keylog,
+                 "# SSL/TLS secrets log file, generated by OpenSSL\n");
+        (void)BIO_flush(bio_keylog);
+    }
+    SSL_CTX_set_keylog_callback(ctx, keylog_callback);
+    return 0;
+}