diff options
Diffstat (limited to 'security/nss/cmd/tstclnt/tstclnt.c')
-rw-r--r-- | security/nss/cmd/tstclnt/tstclnt.c | 301 |
1 files changed, 65 insertions, 236 deletions
diff --git a/security/nss/cmd/tstclnt/tstclnt.c b/security/nss/cmd/tstclnt/tstclnt.c index 1ad99502b..959afec59 100644 --- a/security/nss/cmd/tstclnt/tstclnt.c +++ b/security/nss/cmd/tstclnt/tstclnt.c @@ -31,7 +31,6 @@ #include "ocsp.h" #include "ssl.h" #include "sslproto.h" -#include "sslexp.h" #include "pk11func.h" #include "secmod.h" #include "plgetopt.h" @@ -96,7 +95,6 @@ PRBool verbose; int dumpServerChain = 0; int renegotiationsToDo = 0; int renegotiationsDone = 0; -PRBool initializedServerSessionCache = PR_FALSE; static char *progName; @@ -180,7 +178,7 @@ PrintUsageHeader(const char *progName) "[-n nickname] [-Bafosvx] [-c ciphers] [-Y] [-Z]\n" "[-V [min-version]:[max-version]] [-K] [-T] [-U]\n" "[-r N] [-w passwd] [-W pwfile] [-q [-t seconds]] [-I groups]\n" - "[-A requestfile] [-L totalconnections] [-P {client,server}] [-Q]\n" + "[-A requestfile] [-L totalconnections]\n" "\n", progName); } @@ -204,7 +202,7 @@ PrintParameterUsage(void) fprintf(stderr, "%-20s Print certificate chain information\n", "-C"); fprintf(stderr, "%-20s (use -C twice to print more certificate details)\n", ""); fprintf(stderr, "%-20s (use -C three times to include PEM format certificate dumps)\n", ""); - fprintf(stderr, "%-20s Nickname of key and cert\n", + fprintf(stderr, "%-20s Nickname of key and cert for client auth\n", "-n nickname"); fprintf(stderr, "%-20s Restricts the set of enabled SSL/TLS protocols versions.\n" @@ -253,9 +251,6 @@ PrintParameterUsage(void) "%-20s The following values are valid:\n" "%-20s P256, P384, P521, x25519, FF2048, FF3072, FF4096, FF6144, FF8192\n", "-I", "", ""); - fprintf(stderr, "%-20s Enable alternative TLS 1.3 handshake\n", "-X alt-server-hello"); - fprintf(stderr, "%-20s Use DTLS\n", "-P {client, server}"); - fprintf(stderr, "%-20s Exit after handshake\n", "-Q"); } static void @@ -919,12 +914,6 @@ char *requestString = NULL; PRInt32 requestStringLen = 0; PRBool requestSent = PR_FALSE; PRBool enableZeroRtt = PR_FALSE; -PRBool enableAltServerHello = PR_FALSE; -PRBool useDTLS = PR_FALSE; -PRBool actAsServer = PR_FALSE; -PRBool stopAfterHandshake = PR_FALSE; -PRBool requestToExit = PR_FALSE; -char *versionString = NULL; static int writeBytesToServer(PRFileDesc *s, const char *buf, int nb) @@ -1007,129 +996,12 @@ handshakeCallback(PRFileDesc *fd, void *client_data) writeBytesToServer(fd, requestString, requestStringLen); } } - if (stopAfterHandshake) { - requestToExit = PR_TRUE; - } } #define REQUEST_WAITING (requestString && !requestSent) -static SECStatus -installServerCertificate(PRFileDesc *s, char *nickname) -{ - CERTCertificate *cert; - SECKEYPrivateKey *privKey = NULL; - - if (!nickname) { - PORT_SetError(SEC_ERROR_INVALID_ARGS); - return SECFailure; - } - - cert = PK11_FindCertFromNickname(nickname, &pwdata); - if (cert == NULL) { - return SECFailure; - } - - privKey = PK11_FindKeyByAnyCert(cert, &pwdata); - if (privKey == NULL) { - return SECFailure; - } - if (SSL_ConfigServerCert(s, cert, privKey, NULL, 0) != SECSuccess) { - return SECFailure; - } - SECKEY_DestroyPrivateKey(privKey); - CERT_DestroyCertificate(cert); - - return SECSuccess; -} - -static SECStatus -bindToClient(PRFileDesc *s) -{ - PRStatus status; - status = PR_Bind(s, &addr); - if (status != PR_SUCCESS) { - return SECFailure; - } - - for (;;) { - /* Bind the remote address on first packet. This must happen - * before we SSL-ize the socket because we need to get the - * peer's address before SSLizing. Recvfrom gives us that - * while not consuming any data. */ - unsigned char tmp; - PRNetAddr remote; - int nb; - - nb = PR_RecvFrom(s, &tmp, 1, PR_MSG_PEEK, - &remote, PR_INTERVAL_NO_TIMEOUT); - if (nb != 1) - continue; - - status = PR_Connect(s, &remote, PR_INTERVAL_NO_TIMEOUT); - if (status != PR_SUCCESS) { - SECU_PrintError(progName, "server bind to remote end failed"); - return SECFailure; - } - return SECSuccess; - } - - /* Unreachable. */ -} - -static SECStatus -connectToServer(PRFileDesc *s, PRPollDesc *pollset) -{ - PRStatus status; - PRInt32 filesReady; - - status = PR_Connect(s, &addr, PR_INTERVAL_NO_TIMEOUT); - if (status != PR_SUCCESS) { - if (PR_GetError() == PR_IN_PROGRESS_ERROR) { - if (verbose) - SECU_PrintError(progName, "connect"); - milliPause(50 * multiplier); - pollset[SSOCK_FD].in_flags = PR_POLL_WRITE | PR_POLL_EXCEPT; - pollset[SSOCK_FD].out_flags = 0; - pollset[SSOCK_FD].fd = s; - while (1) { - FPRINTF(stderr, - "%s: about to call PR_Poll for connect completion!\n", - progName); - filesReady = PR_Poll(pollset, 1, PR_INTERVAL_NO_TIMEOUT); - if (filesReady < 0) { - SECU_PrintError(progName, "unable to connect (poll)"); - return SECFailure; - } - FPRINTF(stderr, - "%s: PR_Poll returned 0x%02x for socket out_flags.\n", - progName, pollset[SSOCK_FD].out_flags); - if (filesReady == 0) { /* shouldn't happen! */ - SECU_PrintError(progName, "%s: PR_Poll returned zero!\n"); - return SECFailure; - } - status = PR_GetConnectStatus(pollset); - if (status == PR_SUCCESS) { - break; - } - if (PR_GetError() != PR_IN_PROGRESS_ERROR) { - SECU_PrintError(progName, "unable to connect (poll)"); - return SECFailure; - } - SECU_PrintError(progName, "poll"); - milliPause(50 * multiplier); - } - } else { - SECU_PrintError(progName, "unable to connect"); - return SECFailure; - } - } - - return SECSuccess; -} - static int -run(void) +run_client(void) { int headerSeparatorPtrnId = 0; int error = 0; @@ -1145,23 +1017,13 @@ run(void) requestSent = PR_FALSE; /* Create socket */ - if (useDTLS) { - s = PR_OpenUDPSocket(addr.raw.family); - } else { - s = PR_OpenTCPSocket(addr.raw.family); - } - + s = PR_OpenTCPSocket(addr.raw.family); if (s == NULL) { SECU_PrintError(progName, "error creating socket"); error = 1; goto done; } - if (actAsServer) { - if (bindToClient(s) != SECSuccess) { - return 1; - } - } opt.option = PR_SockOpt_Nonblocking; opt.value.non_blocking = PR_TRUE; /* default */ if (serverCertAuth.testFreshStatusFromSideChannel) { @@ -1174,16 +1036,13 @@ run(void) goto done; } - if (useDTLS) { - s = DTLS_ImportFD(NULL, s); - } else { - s = SSL_ImportFD(NULL, s); - } + s = SSL_ImportFD(NULL, s); if (s == NULL) { SECU_PrintError(progName, "error importing socket"); error = 1; goto done; } + SSL_SetPKCS11PinArg(s, &pwdata); rv = SSL_OptionSet(s, SSL_SECURITY, 1); @@ -1193,7 +1052,7 @@ run(void) goto done; } - rv = SSL_OptionSet(s, actAsServer ? SSL_HANDSHAKE_AS_SERVER : SSL_HANDSHAKE_AS_CLIENT, 1); + rv = SSL_OptionSet(s, SSL_HANDSHAKE_AS_CLIENT, 1); if (rv != SECSuccess) { SECU_PrintError(progName, "error enabling client handshake"); error = 1; @@ -1319,16 +1178,6 @@ run(void) } } - /* Alternate ServerHello content type (TLS 1.3 only) */ - if (enableAltServerHello) { - rv = SSL_UseAltServerHelloType(s, PR_TRUE); - if (rv != SECSuccess) { - SECU_PrintError(progName, "error enabling alternate ServerHello type"); - error = 1; - goto done; - } - } - /* require the use of fixed finite-field DH groups */ if (requireDHNamedGroups) { rv = SSL_OptionSet(s, SSL_REQUIRE_DH_NAMED_GROUPS, PR_TRUE); @@ -1363,21 +1212,7 @@ run(void) if (override) { SSL_BadCertHook(s, ownBadCertHandler, NULL); } - if (actAsServer) { - rv = installServerCertificate(s, nickname); - if (rv != SECSuccess) { - SECU_PrintError(progName, "error installing server cert"); - return 1; - } - rv = SSL_ConfigServerSessionIDCache(1024, 0, 0, "."); - if (rv != SECSuccess) { - SECU_PrintError(progName, "error configuring session cache"); - return 1; - } - initializedServerSessionCache = PR_TRUE; - } else { - SSL_GetClientAuthDataHook(s, own_GetClientAuthData, (void *)nickname); - } + SSL_GetClientAuthDataHook(s, own_GetClientAuthData, (void *)nickname); SSL_HandshakeCallback(s, handshakeCallback, hs2SniHostName); if (hs1SniHostName) { SSL_SetURL(s, hs1SniHostName); @@ -1385,27 +1220,56 @@ run(void) SSL_SetURL(s, host); } - if (actAsServer) { - rv = SSL_ResetHandshake(s, PR_TRUE /* server */); - if (rv != SECSuccess) { - return 1; - } - } else { - /* Try to connect to the server */ - rv = connectToServer(s, pollset); - if (rv != SECSuccess) { - ; + /* Try to connect to the server */ + status = PR_Connect(s, &addr, PR_INTERVAL_NO_TIMEOUT); + if (status != PR_SUCCESS) { + if (PR_GetError() == PR_IN_PROGRESS_ERROR) { + if (verbose) + SECU_PrintError(progName, "connect"); + milliPause(50 * multiplier); + pollset[SSOCK_FD].in_flags = PR_POLL_WRITE | PR_POLL_EXCEPT; + pollset[SSOCK_FD].out_flags = 0; + pollset[SSOCK_FD].fd = s; + while (1) { + FPRINTF(stderr, + "%s: about to call PR_Poll for connect completion!\n", + progName); + filesReady = PR_Poll(pollset, 1, PR_INTERVAL_NO_TIMEOUT); + if (filesReady < 0) { + SECU_PrintError(progName, "unable to connect (poll)"); + error = 1; + goto done; + } + FPRINTF(stderr, + "%s: PR_Poll returned 0x%02x for socket out_flags.\n", + progName, pollset[SSOCK_FD].out_flags); + if (filesReady == 0) { /* shouldn't happen! */ + FPRINTF(stderr, "%s: PR_Poll returned zero!\n", progName); + error = 1; + goto done; + } + status = PR_GetConnectStatus(pollset); + if (status == PR_SUCCESS) { + break; + } + if (PR_GetError() != PR_IN_PROGRESS_ERROR) { + SECU_PrintError(progName, "unable to connect (poll)"); + error = 1; + goto done; + } + SECU_PrintError(progName, "poll"); + milliPause(50 * multiplier); + } + } else { + SECU_PrintError(progName, "unable to connect"); error = 1; goto done; } } pollset[SSOCK_FD].fd = s; - pollset[SSOCK_FD].in_flags = PR_POLL_EXCEPT; - if (!actAsServer) - pollset[SSOCK_FD].in_flags |= (clientSpeaksFirst ? 0 : PR_POLL_READ); - else - pollset[SSOCK_FD].in_flags |= PR_POLL_READ; + pollset[SSOCK_FD].in_flags = PR_POLL_EXCEPT | + (clientSpeaksFirst ? 0 : PR_POLL_READ); pollset[STDIN_FD].fd = PR_GetSpecialFD(PR_StandardInput); if (!REQUEST_WAITING) { pollset[STDIN_FD].in_flags = PR_POLL_READ; @@ -1455,11 +1319,9 @@ run(void) ** Select on stdin and on the socket. Write data from stdin to ** socket, read data from socket and write to stdout. */ - requestToExit = PR_FALSE; FPRINTF(stderr, "%s: ready...\n", progName); - while (!requestToExit && - ((pollset[SSOCK_FD].in_flags | pollset[STDIN_FD].in_flags) || - REQUEST_WAITING)) { + while ((pollset[SSOCK_FD].in_flags | pollset[STDIN_FD].in_flags) || + REQUEST_WAITING) { char buf[4000]; /* buffer for stdin */ int nb; /* num bytes read from stdin. */ @@ -1645,10 +1507,12 @@ main(int argc, char **argv) } } + SSL_VersionRangeGetSupported(ssl_variant_stream, &enabledVersions); + /* XXX: 'B' was used in the past but removed in 3.28, * please leave some time before resuing it. */ optstate = PL_CreateOptState(argc, argv, - "46A:CDFGHI:KL:M:OP:QR:STUV:W:X:YZa:bc:d:fgh:m:n:op:qr:st:uvw:z"); + "46A:CDFGHI:KL:M:OR:STUV:W:YZa:bc:d:fgh:m:n:op:qr:st:uvw:z"); while ((optstatus = PL_GetNextOpt(optstate)) == PL_OPT_OK) { switch (optstate->option) { case '?': @@ -1729,21 +1593,6 @@ main(int argc, char **argv) }; break; - case 'P': - useDTLS = PR_TRUE; - if (!strcmp(optstate->value, "server")) { - actAsServer = 1; - } else { - if (strcmp(optstate->value, "client")) { - Usage(progName); - } - } - break; - - case 'Q': - stopAfterHandshake = PR_TRUE; - break; - case 'R': rootModule = PORT_Strdup(optstate->value); break; @@ -1761,16 +1610,14 @@ main(int argc, char **argv) break; case 'V': - versionString = PORT_Strdup(optstate->value); - break; - - case 'X': - if (!strcmp(optstate->value, "alt-server-hello")) { - enableAltServerHello = PR_TRUE; - } else { + if (SECU_ParseSSLVersionRangeString(optstate->value, + enabledVersions, &enabledVersions) != + SECSuccess) { + fprintf(stderr, "Bad version specified.\n"); Usage(progName); } break; + case 'Y': PrintCipherUsage(progName); exit(0); @@ -1880,19 +1727,8 @@ main(int argc, char **argv) break; } } - PL_DestroyOptState(optstate); - SSL_VersionRangeGetSupported(useDTLS ? ssl_variant_datagram : ssl_variant_stream, &enabledVersions); - - if (versionString) { - if (SECU_ParseSSLVersionRangeString(versionString, - enabledVersions, &enabledVersions) != - SECSuccess) { - fprintf(stderr, "Bad version specified.\n"); - Usage(progName); - } - PORT_Free(versionString); - } + PL_DestroyOptState(optstate); if (optstatus == PL_OPT_BAD) { Usage(progName); @@ -1922,7 +1758,7 @@ main(int argc, char **argv) PR_Init(PR_SYSTEM_THREAD, PR_PRIORITY_NORMAL, 1); PK11_SetPasswordFunc(SECU_GetModulePassword); - memset(&addr, 0, sizeof(addr)); + status = PR_StringToNetAddr(host, &addr); if (status == PR_SUCCESS) { addr.inet.port = PR_htons(portno); @@ -1934,7 +1770,6 @@ main(int argc, char **argv) addrInfo = PR_GetAddrInfoByName(host, PR_AF_UNSPEC, PR_AI_ADDRCONFIG | PR_AI_NOCANONNAME); if (!addrInfo) { - fprintf(stderr, "HOSTNAME=%s\n", host); SECU_PrintError(progName, "error looking up host"); error = 1; goto done; @@ -2049,7 +1884,7 @@ main(int argc, char **argv) } while (numConnections--) { - error = run(); + error = run_client(); if (error) { goto done; } @@ -2080,12 +1915,6 @@ done: } if (NSS_IsInitialized()) { SSL_ClearSessionCache(); - if (initializedServerSessionCache) { - if (SSL_ShutdownServerSessionIDCache() != SECSuccess) { - error = 1; - } - } - if (NSS_Shutdown() != SECSuccess) { error = 1; } |