Bug Summary

File:s/cmd/tstclnt/tstclnt.c
Warning:line 755, column 32
Access to field 'arg' results in a dereference of a null pointer (loaded from variable 'args')

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-pc-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name tstclnt.c -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -analyzer-config-compatibility-mode=true -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -mframe-pointer=all -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fdebug-compilation-dir=/var/lib/jenkins/workspace/nss-scan-build/nss/cmd/tstclnt -ffunction-sections -fdata-sections -fcoverage-compilation-dir=/var/lib/jenkins/workspace/nss-scan-build/nss/cmd/tstclnt -resource-dir /usr/lib/llvm-18/lib/clang/18 -D HAVE_STRERROR -D LINUX -D linux -D XP_UNIX -D XP_UNIX -D DLL_PREFIX="lib" -D DLL_SUFFIX="so" -D DEBUG -U NDEBUG -D _DEFAULT_SOURCE -D _BSD_SOURCE -D _POSIX_SOURCE -D SDB_MEASURE_USE_TEMP_DIR -D _REENTRANT -D DEBUG -U NDEBUG -D _DEFAULT_SOURCE -D _BSD_SOURCE -D _POSIX_SOURCE -D SDB_MEASURE_USE_TEMP_DIR -D _REENTRANT -D NSS_DISABLE_SSE3 -D NSS_NO_INIT_SUPPORT -D USE_UTIL_DIRECTLY -D NO_NSPR_10_SUPPORT -D SSL_DISABLE_DEPRECATED_CIPHER_SUITE_NAMES -I ../../../dist/Linux4.19_x86_64_gcc_glibc_PTH_64_DBG.OBJ/include -I ../../../dist/public/nss -I ../../../dist/private/nss -I ../../../dist/public/seccmd -I ../../../dist/public/dbm -internal-isystem /usr/lib/llvm-18/lib/clang/18/include -internal-isystem /usr/local/include -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/14/../../../../x86_64-linux-gnu/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -std=c99 -ferror-limit 19 -fgnuc-version=4.2.1 -analyzer-output=html -analyzer-config stable-report-filename=true -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /tmp/scan-build-2024-05-18-082241-28900-1 -x c tstclnt.c
1/* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this
3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
4
5/*
6**
7** Sample client side test program that uses SSL and NSS
8**
9*/
10
11#include "secutil.h"
12#include "basicutil.h"
13
14#if defined(XP_UNIX1)
15#include <unistd.h>
16#else
17#include <ctype.h> /* for isalpha() */
18#endif
19
20#include <stdio.h>
21#include <string.h>
22#include <stdlib.h>
23#include <errno(*__errno_location ()).h>
24#include <fcntl.h>
25#include <stdarg.h>
26
27#include "nspr.h"
28#include "prio.h"
29#include "prnetdb.h"
30#include "nss.h"
31#include "nssb64.h"
32#include "ocsp.h"
33#include "ssl.h"
34#include "sslproto.h"
35#include "sslexp.h"
36#include "pk11func.h"
37#include "secmod.h"
38#include "plgetopt.h"
39#include "plstr.h"
40
41#if defined(WIN32)
42#include <fcntl.h>
43#include <io.h>
44#endif
45
46#define PRINTFif (verbose) printf \
47 if (verbose) \
48 printf
49#define FPRINTFif (verbose) fprintf \
50 if (verbose) \
51 fprintf
52
53#define MAX_WAIT_FOR_SERVER600 600
54#define WAIT_INTERVAL100 100
55#define ZERO_RTT_MAX(2 << 16) (2 << 16)
56
57#define EXIT_CODE_HANDSHAKE_FAILED254 254
58
59#define EXIT_CODE_SIDECHANNELTEST_GOOD0 0
60#define EXIT_CODE_SIDECHANNELTEST_BADCERT1 1
61#define EXIT_CODE_SIDECHANNELTEST_NODATA2 2
62#define EXIT_CODE_SIDECHANNELTEST_REVOKED3 3
63
64PRIntervalTime maxInterval = PR_INTERVAL_NO_TIMEOUT0xffffffffUL;
65
66int ssl3CipherSuites[] = {
67 -1, /* SSL_FORTEZZA_DMS_WITH_FORTEZZA_CBC_SHA* a */
68 -1, /* SSL_FORTEZZA_DMS_WITH_RC4_128_SHA * b */
69 TLS_RSA_WITH_RC4_128_MD50x0004, /* c */
70 TLS_RSA_WITH_3DES_EDE_CBC_SHA0x000a, /* d */
71 TLS_RSA_WITH_DES_CBC_SHA0x0009, /* e */
72 -1, /* TLS_RSA_EXPORT_WITH_RC4_40_MD5 * f */
73 -1, /* TLS_RSA_EXPORT_WITH_RC2_CBC_40_MD5 * g */
74 -1, /* SSL_FORTEZZA_DMS_WITH_NULL_SHA * h */
75 TLS_RSA_WITH_NULL_MD50x0001, /* i */
76 -1, /* SSL_RSA_FIPS_WITH_3DES_EDE_CBC_SHA * j */
77 -1, /* SSL_RSA_FIPS_WITH_DES_CBC_SHA * k */
78 -1, /* TLS_RSA_EXPORT1024_WITH_DES_CBC_SHA * l */
79 -1, /* TLS_RSA_EXPORT1024_WITH_RC4_56_SHA * m */
80 TLS_RSA_WITH_RC4_128_SHA0x0005, /* n */
81 TLS_DHE_DSS_WITH_RC4_128_SHA0x0066, /* o */
82 TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA0x0016, /* p */
83 TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA0x0013, /* q */
84 TLS_DHE_RSA_WITH_DES_CBC_SHA0x0015, /* r */
85 TLS_DHE_DSS_WITH_DES_CBC_SHA0x0012, /* s */
86 TLS_DHE_DSS_WITH_AES_128_CBC_SHA0x0032, /* t */
87 TLS_DHE_RSA_WITH_AES_128_CBC_SHA0x0033, /* u */
88 TLS_RSA_WITH_AES_128_CBC_SHA0x002F, /* v */
89 TLS_DHE_DSS_WITH_AES_256_CBC_SHA0x0038, /* w */
90 TLS_DHE_RSA_WITH_AES_256_CBC_SHA0x0039, /* x */
91 TLS_RSA_WITH_AES_256_CBC_SHA0x0035, /* y */
92 TLS_RSA_WITH_NULL_SHA0x0002, /* z */
93 0
94};
95
96unsigned long __cmp_umuls;
97PRBool verbose;
98int dumpServerChain = 0;
99int renegotiationsToDo = 0;
100int renegotiationsDone = 0;
101PRBool initializedServerSessionCache = PR_FALSE0;
102
103static char *progName;
104static const char *requestFile;
105
106secuPWData pwdata = { PW_NONE, 0 };
107
108SSLNamedGroup *enabledGroups = NULL((void*)0);
109unsigned int enabledGroupsCount = 0;
110const SSLSignatureScheme *enabledSigSchemes = NULL((void*)0);
111unsigned int enabledSigSchemeCount = 0;
112SECItem psk = { siBuffer, NULL((void*)0), 0 };
113SECItem pskLabel = { siBuffer, NULL((void*)0), 0 };
114
115const char *
116signatureSchemeName(SSLSignatureScheme scheme)
117{
118 switch (scheme) {
119#define strcase(x) \
120 case ssl_sig_##x: \
121 return #x
122 strcase(none);
123 strcase(rsa_pkcs1_sha1);
124 strcase(rsa_pkcs1_sha256);
125 strcase(rsa_pkcs1_sha384);
126 strcase(rsa_pkcs1_sha512);
127 strcase(ecdsa_sha1);
128 strcase(ecdsa_secp256r1_sha256);
129 strcase(ecdsa_secp384r1_sha384);
130 strcase(ecdsa_secp521r1_sha512);
131 strcase(rsa_pss_rsae_sha256);
132 strcase(rsa_pss_rsae_sha384);
133 strcase(rsa_pss_rsae_sha512);
134 strcase(ed25519);
135 strcase(ed448);
136 strcase(rsa_pss_pss_sha256);
137 strcase(rsa_pss_pss_sha384);
138 strcase(rsa_pss_pss_sha512);
139 strcase(dsa_sha1);
140 strcase(dsa_sha256);
141 strcase(dsa_sha384);
142 strcase(dsa_sha512);
143#undef strcase
144 case ssl_sig_rsa_pkcs1_sha1md5:
145 return "RSA PKCS#1 SHA1+MD5";
146 default:
147 break;
148 }
149 return "Unknown Scheme";
150}
151
152void
153printSecurityInfo(PRFileDesc *fd)
154{
155 CERTCertificate *cert;
156 const SECItemArray *csa;
157 const SECItem *scts;
158 SSL3Statistics *ssl3stats = SSL_GetStatistics();
159 SECStatus result;
160 SSLChannelInfo channel;
161 SSLCipherSuiteInfo suite;
162
163 result = SSL_GetChannelInfo(fd, &channel, sizeof channel);
164 if (result == SECSuccess &&
165 channel.length == sizeof channel &&
166 channel.cipherSuite) {
167 result = SSL_GetCipherSuiteInfo(channel.cipherSuite,
168 &suite, sizeof suite);
169 if (result == SECSuccess) {
170 FPRINTFif (verbose) fprintf(stderrstderr,
171 "tstclnt: SSL version %d.%d using %d-bit %s with %d-bit %s MAC%s\n",
172 channel.protocolVersion >> 8, channel.protocolVersion & 0xff,
173 suite.effectiveKeyBits, suite.symCipherName,
174 suite.macBits, suite.macAlgorithmName,
175 channel.isFIPS ? " FIPS" : "");
176 FPRINTFif (verbose) fprintf(stderrstderr,
177 "tstclnt: Server Auth: %d-bit %s, Key Exchange: %d-bit %s\n"
178 " Compression: %s, Extended Master Secret: %s\n"
179 " Signature Scheme: %s\n",
180 channel.authKeyBits, suite.authAlgorithmName,
181 channel.keaKeyBits, suite.keaTypeName,
182 channel.compressionMethodName,
183 channel.extendedMasterSecretUsed ? "Yes" : "No",
184 signatureSchemeName(channel.signatureScheme));
185 }
186 }
187 cert = SSL_RevealCert(fd);
188 if (cert) {
189 char *ip = CERT_NameToAscii(&cert->issuer);
190 char *sp = CERT_NameToAscii(&cert->subject);
191 if (sp) {
192 fprintf(stderrstderr, "subject DN: %s\n", sp);
193 PORT_FreePORT_Free_Util(sp);
194 }
195 if (ip) {
196 fprintf(stderrstderr, "issuer DN: %s\n", ip);
197 PORT_FreePORT_Free_Util(ip);
198 }
199 CERT_DestroyCertificate(cert);
200 cert = NULL((void*)0);
201 }
202 fprintf(stderrstderr,
203 "%ld cache hits; %ld cache misses, %ld cache not reusable\n"
204 "%ld stateless resumes\n",
205 ssl3stats->hsh_sid_cache_hits, ssl3stats->hsh_sid_cache_misses,
206 ssl3stats->hsh_sid_cache_not_ok, ssl3stats->hsh_sid_stateless_resumes);
207
208 csa = SSL_PeerStapledOCSPResponses(fd);
209 if (csa) {
210 fprintf(stderrstderr, "Received %d Cert Status items (OCSP stapled data)\n",
211 csa->len);
212 }
213 scts = SSL_PeerSignedCertTimestamps(fd);
214 if (scts && scts->len) {
215 fprintf(stderrstderr, "Received a Signed Certificate Timestamp of length"
216 " %u\n",
217 scts->len);
218 }
219 if (channel.peerDelegCred) {
220 fprintf(stderrstderr, "Received a Delegated Credential\n");
221 }
222}
223
224static void
225PrintUsageHeader()
226{
227 fprintf(stderrstderr,
228 "Usage: %s -h host [-a 1st_hs_name ] [-a 2nd_hs_name ] [-p port]\n"
229 " [-D | -d certdir] [-C] [-b | -R root-module] \n"
230 " [-n nickname] [-Bafosvx] [-c ciphers] [-Y] [-Z] [-E]\n"
231 " [-V [min-version]:[max-version]] [-K] [-T] [-U]\n"
232 " [-r N] [-w passwd] [-W pwfile] [-q [-t seconds]]\n"
233 " [-I groups] [-J signatureschemes]\n"
234 " [-A requestfile] [-L totalconnections] [-P {client,server}]\n"
235 " [-N echConfigs] [-Q] [-z externalPsk]\n"
236 " [-i echGreaseSize]\n"
237 "\n",
238 progName);
239}
240
241static void
242PrintParameterUsage()
243{
244 fprintf(stderrstderr, "%-20s Send different SNI name. 1st_hs_name - at first\n"
245 "%-20s handshake, 2nd_hs_name - at second handshake.\n"
246 "%-20s Default is host from the -h argument.\n",
247 "-a name",
248 "", "");
249 fprintf(stderrstderr, "%-20s Hostname to connect with\n", "-h host");
250 fprintf(stderrstderr, "%-20s Port number for SSL server\n", "-p port");
251 fprintf(stderrstderr,
252 "%-20s Directory with cert database (default is ~/.netscape)\n",
253 "-d certdir");
254 fprintf(stderrstderr, "%-20s Run without a cert database\n", "-D");
255 fprintf(stderrstderr, "%-20s Load the default \"builtins\" root CA module\n", "-b");
256 fprintf(stderrstderr, "%-20s Load the given root CA module\n", "-R");
257 fprintf(stderrstderr, "%-20s Print certificate chain information\n", "-C");
258 fprintf(stderrstderr, "%-20s (use -C twice to print more certificate details)\n", "");
259 fprintf(stderrstderr, "%-20s (use -C three times to include PEM format certificate dumps)\n", "");
260 fprintf(stderrstderr, "%-20s Nickname of key and cert\n",
261 "-n nickname");
262 fprintf(stderrstderr,
263 "%-20s Restricts the set of enabled SSL/TLS protocols versions.\n"
264 "%-20s All versions are enabled by default.\n"
265 "%-20s Possible values for min/max: ssl3 tls1.0 tls1.1 tls1.2 tls1.3\n"
266 "%-20s Example: \"-V ssl3:\" enables SSL 3 and newer.\n",
267 "-V [min]:[max]", "", "", "");
268 fprintf(stderrstderr, "%-20s Send TLS_FALLBACK_SCSV\n", "-K");
269 fprintf(stderrstderr, "%-20s Prints only payload data. Skips HTTP header.\n", "-S");
270 fprintf(stderrstderr, "%-20s Client speaks first. \n", "-f");
271 fprintf(stderrstderr, "%-20s Use synchronous certificate selection & validation\n", "-O");
272 fprintf(stderrstderr, "%-20s Override bad server cert. Make it OK.\n", "-o");
273 fprintf(stderrstderr, "%-20s Disable SSL socket locking.\n", "-s");
274 fprintf(stderrstderr, "%-20s Verbose progress reporting.\n", "-v");
275 fprintf(stderrstderr, "%-20s Ping the server and then exit.\n", "-q");
276 fprintf(stderrstderr, "%-20s Timeout for server ping (default: no timeout).\n", "-t seconds");
277 fprintf(stderrstderr, "%-20s Renegotiate N times (resuming session if N>1).\n", "-r N");
278 fprintf(stderrstderr, "%-20s Enable the session ticket extension.\n", "-u");
279 fprintf(stderrstderr, "%-20s Enable false start.\n", "-g");
280 fprintf(stderrstderr, "%-20s Enable the cert_status extension (OCSP stapling).\n", "-T");
281 fprintf(stderrstderr, "%-20s Enable the signed_certificate_timestamp extension.\n", "-U");
282 fprintf(stderrstderr, "%-20s Enable the delegated credentials extension.\n", "-B");
283 fprintf(stderrstderr, "%-20s Require fresh revocation info from side channel.\n"
284 "%-20s -F once means: require for server cert only\n"
285 "%-20s -F twice means: require for intermediates, too\n"
286 "%-20s (Connect, handshake with server, disable dynamic download\n"
287 "%-20s of OCSP/CRL, verify cert using CERT_PKIXVerifyCert.)\n"
288 "%-20s Exit code:\n"
289 "%-20s 0: have fresh and valid revocation data, status good\n"
290 "%-20s 1: cert failed to verify, prior to revocation checking\n"
291 "%-20s 2: missing, old or invalid revocation data\n"
292 "%-20s 3: have fresh and valid revocation data, status revoked\n",
293 "-F", "", "", "", "", "", "", "", "", "");
294 fprintf(stderrstderr, "%-20s Test -F allows 0=any (default), 1=only OCSP, 2=only CRL\n", "-M");
295 fprintf(stderrstderr, "%-20s Restrict ciphers\n", "-c ciphers");
296 fprintf(stderrstderr, "%-20s Print cipher values allowed for parameter -c and exit\n", "-Y");
297 fprintf(stderrstderr, "%-20s Enforce using an IPv4 destination address\n", "-4");
298 fprintf(stderrstderr, "%-20s Enforce using an IPv6 destination address\n", "-6");
299 fprintf(stderrstderr, "%-20s (Options -4 and -6 cannot be combined.)\n", "");
300 fprintf(stderrstderr, "%-20s Enable the extended master secret extension [RFC7627]\n", "-G");
301 fprintf(stderrstderr, "%-20s Require the use of FFDHE supported groups [RFC7919]\n", "-H");
302 fprintf(stderrstderr, "%-20s Read from a file instead of stdin\n", "-A");
303 fprintf(stderrstderr, "%-20s Allow 0-RTT data (TLS 1.3 only)\n", "-Z");
304 fprintf(stderrstderr, "%-20s Disconnect and reconnect up to N times total\n", "-L");
305 fprintf(stderrstderr, "%-20s Comma separated list of enabled groups for TLS key exchange.\n"
306 "%-20s The following values are valid:\n"
307 "%-20s P256, P384, P521, x25519, FF2048, FF3072, FF4096, FF6144, FF8192\n"
308 "%-20s xyber768d00\n",
309 "-I", "", "", "");
310 fprintf(stderrstderr, "%-20s Comma separated list of signature schemes in preference order.\n"
311 "%-20s The following values are valid:\n"
312 "%-20s rsa_pkcs1_sha1, rsa_pkcs1_sha256, rsa_pkcs1_sha384, rsa_pkcs1_sha512,\n"
313 "%-20s ecdsa_sha1, ecdsa_secp256r1_sha256, ecdsa_secp384r1_sha384,\n"
314 "%-20s ecdsa_secp521r1_sha512,\n"
315 "%-20s rsa_pss_rsae_sha256, rsa_pss_rsae_sha384, rsa_pss_rsae_sha512,\n"
316 "%-20s rsa_pss_pss_sha256, rsa_pss_pss_sha384, rsa_pss_pss_sha512,\n"
317 "%-20s dsa_sha1, dsa_sha256, dsa_sha384, dsa_sha512\n",
318 "-J", "", "", "", "", "", "", "");
319 fprintf(stderrstderr, "%-20s Use DTLS\n", "-P {client, server}");
320 fprintf(stderrstderr, "%-20s Exit after handshake\n", "-Q");
321 fprintf(stderrstderr, "%-20s Use Encrypted Client Hello with the given Base64-encoded ECHConfigs\n", "-N");
322 fprintf(stderrstderr, "%-20s Enable Encrypted Client Hello GREASEing with the given padding size (0-255) \n", "-i");
323 fprintf(stderrstderr, "%-20s Enable post-handshake authentication\n"
324 "%-20s for TLS 1.3; need to specify -n\n",
325 "-E", "");
326 fprintf(stderrstderr, "%-20s Export and print keying material after successful handshake.\n"
327 "%-20s The argument is a comma separated list of exporters in the form:\n"
328 "%-20s LABEL[:OUTPUT-LENGTH[:CONTEXT]]\n"
329 "%-20s where LABEL and CONTEXT can be either a free-form string or\n"
330 "%-20s a hex string if it is preceded by \"0x\"; OUTPUT-LENGTH\n"
331 "%-20s is a decimal integer.\n",
332 "-x", "", "", "", "", "");
333 fprintf(stderrstderr,
334 "%-20s Configure a TLS 1.3 External PSK with the given hex string for a key\n"
335 "%-20s To specify a label, use ':' as a delimiter. For example\n"
336 "%-20s 0xAAAABBBBCCCCDDDD:mylabel. Otherwise, the default label of\n"
337 "%-20s 'Client_identity' will be used.\n",
338 "-z externalPsk", "", "", "");
339 fprintf(stderrstderr, "%-20s Enable middlebox compatibility mode (TLS 1.3 only)\n", "-e");
340}
341
342static void
343Usage()
344{
345 PrintUsageHeader();
346 PrintParameterUsage();
347 exit(1);
348}
349
350static void
351PrintCipherUsage()
352{
353 PrintUsageHeader();
354 fprintf(stderrstderr, "%-20s Letter(s) chosen from the following list\n",
355 "-c ciphers");
356 fprintf(stderrstderr,
357 "c SSL3 RSA WITH RC4 128 MD5\n"
358 "d SSL3 RSA WITH 3DES EDE CBC SHA\n"
359 "e SSL3 RSA WITH DES CBC SHA\n"
360 "i SSL3 RSA WITH NULL MD5\n"
361 "n SSL3 RSA WITH RC4 128 SHA\n"
362 "o SSL3 DHE DSS WITH RC4 128 SHA\n"
363 "p SSL3 DHE RSA WITH 3DES EDE CBC SHA\n"
364 "q SSL3 DHE DSS WITH 3DES EDE CBC SHA\n"
365 "r SSL3 DHE RSA WITH DES CBC SHA\n"
366 "s SSL3 DHE DSS WITH DES CBC SHA\n"
367 "t SSL3 DHE DSS WITH AES 128 CBC SHA\n"
368 "u SSL3 DHE RSA WITH AES 128 CBC SHA\n"
369 "v SSL3 RSA WITH AES 128 CBC SHA\n"
370 "w SSL3 DHE DSS WITH AES 256 CBC SHA\n"
371 "x SSL3 DHE RSA WITH AES 256 CBC SHA\n"
372 "y SSL3 RSA WITH AES 256 CBC SHA\n"
373 "z SSL3 RSA WITH NULL SHA\n"
374 "\n"
375 ":WXYZ Use cipher with hex code { 0xWX , 0xYZ } in TLS\n");
376 exit(1);
377}
378
379void
380milliPause(PRUint32 milli)
381{
382 PRIntervalTime ticks = PR_MillisecondsToInterval(milli);
383 PR_Sleep(ticks);
384}
385
386void
387disableAllSSLCiphers()
388{
389 const PRUint16 *cipherSuites = SSL_GetImplementedCiphers();
390 int i = SSL_GetNumImplementedCiphers();
391 SECStatus rv;
392
393 /* disable all the SSL3 cipher suites */
394 while (--i >= 0) {
395 PRUint16 suite = cipherSuites[i];
396 rv = SSL_CipherPrefSetDefault(suite, PR_FALSE0);
397 if (rv != SECSuccess) {
398 PRErrorCode err = PR_GetError();
399 fprintf(stderrstderr,
400 "SSL_CipherPrefSet didn't like value 0x%04x (i = %d): %s\n",
401 suite, i, SECU_Strerror(err)PR_ErrorToString((err), 0));
402 exit(2);
403 }
404 }
405}
406
407typedef struct
408{
409 PRBool shouldPause; /* PR_TRUE if we should use asynchronous peer cert
410 * authentication */
411 PRBool isPaused; /* PR_TRUE if libssl is waiting for us to validate the
412 * peer's certificate and restart the handshake. */
413 void *dbHandle; /* Certificate database handle to use while
414 * authenticating the peer's certificate. */
415 PRBool testFreshStatusFromSideChannel;
416 PRErrorCode sideChannelRevocationTestResultCode;
417 PRBool requireDataForIntermediates;
418 PRBool allowOCSPSideChannelData;
419 PRBool allowCRLSideChannelData;
420} ServerCertAuth;
421
422/*
423 * Callback is called when incoming certificate is not valid.
424 * Returns SECSuccess to accept the cert anyway, SECFailure to reject.
425 */
426static SECStatus
427ownBadCertHandler(void *arg, PRFileDesc *socket)
428{
429 PRErrorCode err = PR_GetError();
430 /* can log invalid cert here */
431 fprintf(stderrstderr, "Bad server certificate: %d, %s\n", err,
432 SECU_Strerror(err)PR_ErrorToString((err), 0));
433 return SECSuccess; /* override, say it's OK. */
434}
435
436#define EXIT_CODE_SIDECHANNELTEST_GOOD0 0
437#define EXIT_CODE_SIDECHANNELTEST_BADCERT1 1
438#define EXIT_CODE_SIDECHANNELTEST_NODATA2 2
439#define EXIT_CODE_SIDECHANNELTEST_REVOKED3 3
440
441static void
442verifyFromSideChannel(CERTCertificate *cert, ServerCertAuth *sca)
443{
444 PRUint64 revDoNotUse =
445 CERT_REV_M_DO_NOT_TEST_USING_THIS_METHOD0UL;
446
447 PRUint64 revUseLocalOnlyAndSoftFail =
448 CERT_REV_M_TEST_USING_THIS_METHOD1UL |
449 CERT_REV_M_FORBID_NETWORK_FETCHING2UL |
450 CERT_REV_M_REQUIRE_INFO_ON_MISSING_SOURCE8UL |
451 CERT_REV_M_IGNORE_MISSING_FRESH_INFO0UL |
452 CERT_REV_M_STOP_TESTING_ON_FRESH_INFO0UL;
453
454 PRUint64 revUseLocalOnlyAndHardFail =
455 CERT_REV_M_TEST_USING_THIS_METHOD1UL |
456 CERT_REV_M_FORBID_NETWORK_FETCHING2UL |
457 CERT_REV_M_REQUIRE_INFO_ON_MISSING_SOURCE8UL |
458 CERT_REV_M_FAIL_ON_MISSING_FRESH_INFO16UL |
459 CERT_REV_M_STOP_TESTING_ON_FRESH_INFO0UL;
460
461 PRUint64 methodFlagsDoNotUse[2];
462 PRUint64 methodFlagsCheckSoftFail[2];
463 PRUint64 methodFlagsCheckHardFail[2];
464 CERTRevocationTests revTestsDoNotCheck;
465 CERTRevocationTests revTestsOverallSoftFail;
466 CERTRevocationTests revTestsOverallHardFail;
467 CERTRevocationFlags rev;
468 CERTValInParam cvin[2];
469 CERTValOutParam cvout[1];
470 SECStatus rv;
471
472 methodFlagsDoNotUse[cert_revocation_method_crl] = revDoNotUse;
473 methodFlagsDoNotUse[cert_revocation_method_ocsp] = revDoNotUse;
474
475 methodFlagsCheckSoftFail[cert_revocation_method_crl] =
476 sca->allowCRLSideChannelData ? revUseLocalOnlyAndSoftFail : revDoNotUse;
477 methodFlagsCheckSoftFail[cert_revocation_method_ocsp] =
478 sca->allowOCSPSideChannelData ? revUseLocalOnlyAndSoftFail : revDoNotUse;
479
480 methodFlagsCheckHardFail[cert_revocation_method_crl] =
481 sca->allowCRLSideChannelData ? revUseLocalOnlyAndHardFail : revDoNotUse;
482 methodFlagsCheckHardFail[cert_revocation_method_ocsp] =
483 sca->allowOCSPSideChannelData ? revUseLocalOnlyAndHardFail : revDoNotUse;
484
485 revTestsDoNotCheck.cert_rev_flags_per_method = methodFlagsDoNotUse;
486 revTestsDoNotCheck.number_of_defined_methods = 2;
487 revTestsDoNotCheck.number_of_preferred_methods = 0;
488 revTestsDoNotCheck.cert_rev_method_independent_flags =
489 CERT_REV_MI_TEST_ALL_LOCAL_INFORMATION_FIRST1UL |
490 CERT_REV_MI_NO_OVERALL_INFO_REQUIREMENT0UL;
491
492 revTestsOverallSoftFail.cert_rev_flags_per_method = 0; /* must define later */
493 revTestsOverallSoftFail.number_of_defined_methods = 2;
494 revTestsOverallSoftFail.number_of_preferred_methods = 0;
495 revTestsOverallSoftFail.cert_rev_method_independent_flags =
496 CERT_REV_MI_TEST_ALL_LOCAL_INFORMATION_FIRST1UL |
497 CERT_REV_MI_NO_OVERALL_INFO_REQUIREMENT0UL;
498
499 revTestsOverallHardFail.cert_rev_flags_per_method = 0; /* must define later */
500 revTestsOverallHardFail.number_of_defined_methods = 2;
501 revTestsOverallHardFail.number_of_preferred_methods = 0;
502 revTestsOverallHardFail.cert_rev_method_independent_flags =
503 CERT_REV_MI_TEST_ALL_LOCAL_INFORMATION_FIRST1UL |
504 CERT_REV_MI_REQUIRE_SOME_FRESH_INFO_AVAILABLE2UL;
505
506 rev.chainTests = revTestsDoNotCheck;
507 rev.leafTests = revTestsDoNotCheck;
508
509 cvin[0].type = cert_pi_revocationFlags;
510 cvin[0].value.pointer.revocation = &rev;
511 cvin[1].type = cert_pi_end;
512
513 cvout[0].type = cert_po_end;
514
515 /* Strategy:
516 *
517 * Verify with revocation checking disabled.
518 * On failure return 1.
519 *
520 * if result if "good", then continue testing.
521 *
522 * Verify with CERT_REV_M_FAIL_ON_MISSING_FRESH_INFO.
523 * If result is good, return 0.
524 *
525 * On failure continue testing, find out why it failed.
526 *
527 * Verify with CERT_REV_M_IGNORE_MISSING_FRESH_INFO
528 *
529 * If result is "good", then our previous test failed,
530 * because we don't have fresh revocation info, return 2.
531 *
532 * If result is still bad, we do have revocation info,
533 * and it says "revoked" or something equivalent, return 3.
534 */
535
536 /* revocation checking disabled */
537 rv = CERT_PKIXVerifyCert(cert, certificateUsageSSLServer(0x0002),
538 cvin, cvout, NULL((void*)0));
539 if (rv != SECSuccess) {
540 sca->sideChannelRevocationTestResultCode =
541 EXIT_CODE_SIDECHANNELTEST_BADCERT1;
542 return;
543 }
544
545 /* revocation checking, hard fail */
546 if (sca->allowOCSPSideChannelData && sca->allowCRLSideChannelData) {
547 /* any method is allowed. use soft fail on individual checks,
548 * but use hard fail on the overall check
549 */
550 revTestsOverallHardFail.cert_rev_flags_per_method = methodFlagsCheckSoftFail;
551 } else {
552 /* only one method is allowed. use hard fail on the individual checks.
553 * hard/soft fail is irrelevant on overall flags.
554 */
555 revTestsOverallHardFail.cert_rev_flags_per_method = methodFlagsCheckHardFail;
556 }
557 rev.leafTests = revTestsOverallHardFail;
558 rev.chainTests =
559 sca->requireDataForIntermediates ? revTestsOverallHardFail : revTestsDoNotCheck;
560 rv = CERT_PKIXVerifyCert(cert, certificateUsageSSLServer(0x0002),
561 cvin, cvout, NULL((void*)0));
562 if (rv == SECSuccess) {
563 sca->sideChannelRevocationTestResultCode =
564 EXIT_CODE_SIDECHANNELTEST_GOOD0;
565 return;
566 }
567
568 /* revocation checking, soft fail */
569 revTestsOverallSoftFail.cert_rev_flags_per_method = methodFlagsCheckSoftFail;
570 rev.leafTests = revTestsOverallSoftFail;
571 rev.chainTests =
572 sca->requireDataForIntermediates ? revTestsOverallSoftFail : revTestsDoNotCheck;
573 rv = CERT_PKIXVerifyCert(cert, certificateUsageSSLServer(0x0002),
574 cvin, cvout, NULL((void*)0));
575 if (rv == SECSuccess) {
576 sca->sideChannelRevocationTestResultCode =
577 EXIT_CODE_SIDECHANNELTEST_NODATA2;
578 return;
579 }
580
581 sca->sideChannelRevocationTestResultCode =
582 EXIT_CODE_SIDECHANNELTEST_REVOKED3;
583}
584
585static void
586dumpCertificatePEM(CERTCertificate *cert)
587{
588 SECItem data;
589 data.data = cert->derCert.data;
590 data.len = cert->derCert.len;
591 fprintf(stderrstderr, "%s\n%s\n%s\n", NS_CERT_HEADER"-----BEGIN CERTIFICATE-----",
592 BTOA_DataToAsciiBTOA_DataToAscii_Util(data.data, data.len), NS_CERT_TRAILER"-----END CERTIFICATE-----");
593}
594
595static void
596dumpServerCertificateChain(PRFileDesc *fd)
597{
598 CERTCertList *peerCertChain = NULL((void*)0);
599 CERTCertListNode *node = NULL((void*)0);
600 CERTCertificate *peerCert = NULL((void*)0);
601 CERTCertificateList *foundChain = NULL((void*)0);
602 SECU_PPFunc dumpFunction = NULL((void*)0);
603 PRBool dumpCertPEM = PR_FALSE0;
604
605 if (!dumpServerChain) {
606 return;
607 } else if (dumpServerChain == 1) {
608 dumpFunction = (SECU_PPFunc)SECU_PrintCertificateBasicInfo;
609 } else {
610 dumpFunction = (SECU_PPFunc)SECU_PrintCertificate;
611 if (dumpServerChain > 2) {
612 dumpCertPEM = PR_TRUE1;
613 }
614 }
615
616 SECU_EnableWrap(PR_FALSE0);
617
618 fprintf(stderrstderr, "==== certificate(s) sent by server: ====\n");
619 peerCertChain = SSL_PeerCertificateChain(fd);
620 if (peerCertChain) {
621 node = CERT_LIST_HEAD(peerCertChain)((CERTCertListNode *)(&peerCertChain->list)->next);
622 while (!CERT_LIST_END(node, peerCertChain)(((void *)node) == ((void *)&peerCertChain->list))) {
623 CERTCertificate *cert = node->cert;
624 SECU_PrintSignedContent(stderrstderr, &cert->derCert, "Certificate", 0,
625 dumpFunction);
626 if (dumpCertPEM) {
627 dumpCertificatePEM(cert);
628 }
629 node = CERT_LIST_NEXT(node)((CERTCertListNode *)node->links.next);
630 }
631 }
632
633 if (peerCertChain) {
634 peerCert = SSL_RevealCert(fd);
635 if (peerCert) {
636 foundChain = CERT_CertChainFromCert(peerCert, certificateUsageSSLServer(0x0002),
637 PR_TRUE1);
638 }
639 if (foundChain) {
640 unsigned int count = 0;
641 fprintf(stderrstderr, "==== locally found issuer certificate(s): ====\n");
642 for (count = 0; count < (unsigned int)foundChain->len; count++) {
643 CERTCertificate *c;
644 PRBool wasSentByServer = PR_FALSE0;
645 c = CERT_FindCertByDERCert(CERT_GetDefaultCertDB(), &foundChain->certs[count]);
646
647 node = CERT_LIST_HEAD(peerCertChain)((CERTCertListNode *)(&peerCertChain->list)->next);
648 while (!CERT_LIST_END(node, peerCertChain)(((void *)node) == ((void *)&peerCertChain->list))) {
649 CERTCertificate *cert = node->cert;
650 if (CERT_CompareCerts(cert, c)) {
651 wasSentByServer = PR_TRUE1;
652 break;
653 }
654 node = CERT_LIST_NEXT(node)((CERTCertListNode *)node->links.next);
655 }
656
657 if (!wasSentByServer) {
658 SECU_PrintSignedContent(stderrstderr, &c->derCert, "Certificate", 0,
659 dumpFunction);
660 if (dumpCertPEM) {
661 dumpCertificatePEM(c);
662 }
663 }
664 CERT_DestroyCertificate(c);
665 }
666 CERT_DestroyCertificateList(foundChain);
667 }
668 if (peerCert) {
669 CERT_DestroyCertificate(peerCert);
670 }
671
672 CERT_DestroyCertList(peerCertChain);
673 peerCertChain = NULL((void*)0);
674 }
675
676 fprintf(stderrstderr, "==== end of certificate chain information ====\n");
677 fflush(stderrstderr);
678}
679
680static SECStatus
681ownAuthCertificate(void *arg, PRFileDesc *fd, PRBool checkSig,
682 PRBool isServer)
683{
684 ServerCertAuth *serverCertAuth = (ServerCertAuth *)arg;
685
686 if (dumpServerChain) {
687 dumpServerCertificateChain(fd);
688 }
689
690 if (!serverCertAuth->shouldPause) {
691 CERTCertificate *cert;
692 unsigned int i;
693 const SECItemArray *csa;
694
695 if (!serverCertAuth->testFreshStatusFromSideChannel) {
696 return SSL_AuthCertificate(serverCertAuth->dbHandle,
697 fd, checkSig, isServer);
698 }
699
700 /* No verification attempt must have happened before now,
701 * to ensure revocation data has been actively retrieved yet,
702 * or our test will produce incorrect results.
703 */
704
705 cert = SSL_RevealCert(fd);
706 if (!cert) {
707 exit(254);
708 }
709
710 csa = SSL_PeerStapledOCSPResponses(fd);
711 if (csa) {
712 for (i = 0; i < csa->len; ++i) {
713 PORT_SetErrorPORT_SetError_Util(0);
714 if (CERT_CacheOCSPResponseFromSideChannel(
715 serverCertAuth->dbHandle, cert, PR_Now(),
716 &csa->items[i], arg) != SECSuccess) {
717 PORT_Assert(PR_GetError() != 0)((PR_GetError() != 0)?((void)0):PR_Assert("PR_GetError() != 0"
,"tstclnt.c",717))
;
718 }
719 }
720 }
721
722 verifyFromSideChannel(cert, serverCertAuth);
723 CERT_DestroyCertificate(cert);
724 /* return success to ensure our caller will continue and we will
725 * reach the code that handles
726 * serverCertAuth->sideChannelRevocationTestResultCode
727 */
728 return SECSuccess;
729 }
730
731 FPRINTFif (verbose) fprintf(stderrstderr, "%s: using asynchronous certificate validation\n",
732 progName);
733
734 PORT_Assert(!serverCertAuth->isPaused)((!serverCertAuth->isPaused)?((void)0):PR_Assert("!serverCertAuth->isPaused"
,"tstclnt.c",734))
;
735 serverCertAuth->isPaused = PR_TRUE1;
736 return SECWouldBlock;
737}
738
739struct clientCertAsyncParamsStr {
740 void *arg; /* The nickname used for selection, not owned */
741 struct CERTDistNamesStr *caNames; /* CA Names specified by Server, owned. */
742};
743
744/* tstclnt can only have a single handshake in progress at any instant. */
745PRBool clientCertAsyncSelect = PR_TRUE1; /* Async by default */
746PRBool clientCertIsBlocked = PR_FALSE0; /* Whether we waiting to finish ClientAuth */
747struct clientCertAsyncParamsStr *clientCertParams = NULL((void*)0);
748
749SECStatus
750own_CompleteClientAuthData(PRFileDesc *fd, struct clientCertAsyncParamsStr *args)
751{
752 SECStatus rv;
753 CERTCertificate *pRetCert = NULL((void*)0);
754 SECKEYPrivateKey *pRetKey = NULL((void*)0);
755 rv = NSS_GetClientAuthData(args->arg, fd, args->caNames, &pRetCert, &pRetKey);
93
Access to field 'arg' results in a dereference of a null pointer (loaded from variable 'args')
756 if (rv != SECSuccess) {
757 fprintf(stderrstderr, "Failed to load a suitable client certificate \n");
758 }
759 return SSL_ClientCertCallbackComplete(fd, rv, pRetKey, pRetCert);
760}
761
762SECStatus
763restartHandshakeAfterClientCertIfNeeded(PRFileDesc *fd)
764{
765 if (!clientCertIsBlocked) {
80
Assuming 'clientCertIsBlocked' is not equal to 0
81
Taking false branch
89
Assuming 'clientCertIsBlocked' is not equal to 0
90
Taking false branch
766 return SECFailure;
767 }
768 clientCertIsBlocked = PR_FALSE0;
769 own_CompleteClientAuthData(fd, clientCertParams);
91
Passing null pointer value via 2nd parameter 'args'
92
Calling 'own_CompleteClientAuthData'
770 CERT_FreeDistNames(clientCertParams->caNames);
771 PORT_FreePORT_Free_Util(clientCertParams);
772 clientCertParams = NULL((void*)0);
82
Null pointer value stored to 'clientCertParams'
773 return SECSuccess;
774}
775
776SECStatus
777own_GetClientAuthData(void *arg,
778 PRFileDesc *socket,
779 struct CERTDistNamesStr *caNames,
780 struct CERTCertificateStr **pRetCert,
781 struct SECKEYPrivateKeyStr **pRetKey)
782{
783 if (clientCertAsyncSelect) {
784 PR_ASSERT(!clientCertIsBlocked)((!clientCertIsBlocked)?((void)0):PR_Assert("!clientCertIsBlocked"
,"tstclnt.c",784))
;
785 PR_ASSERT(!clientCertParams)((!clientCertParams)?((void)0):PR_Assert("!clientCertParams",
"tstclnt.c",785))
;
786
787 clientCertIsBlocked = PR_TRUE1;
788 clientCertParams = PORT_AllocPORT_Alloc_Util(sizeof(struct clientCertAsyncParamsStr));
789 if (!clientCertParams) {
790 fprintf(stderrstderr, "Unable to allocate buffer for client cert callback\n");
791 exit(1);
792 }
793
794 clientCertParams->arg = arg;
795 clientCertParams->caNames = caNames ? CERT_DupDistNames(caNames) : NULL((void*)0);
796 if (caNames && !clientCertParams->caNames) {
797 fprintf(stderrstderr, "Unable to allocate buffer for client cert callback\n");
798 exit(1);
799 }
800 return SECWouldBlock;
801 }
802
803 if (verbose > 1) {
804 SECStatus rv;
805 fprintf(stderrstderr, "Server requested Client Authentication\n");
806 if (caNames && caNames->nnames > 0) {
807 PLArenaPool *arena = caNames->arena;
808 if (!arena)
809 arena = PORT_NewArenaPORT_NewArena_Util(2048);
810 if (arena) {
811 int i;
812 for (i = 0; i < caNames->nnames; ++i) {
813 char *nameString;
814 CERTName dn;
815 rv = SEC_QuickDERDecodeItemSEC_QuickDERDecodeItem_Util(arena,
816 &dn,
817 SEC_ASN1_GET(CERT_NameTemplate)CERT_NameTemplate,
818 caNames->names + i);
819 if (rv != SECSuccess)
820 continue;
821 nameString = CERT_NameToAscii(&dn);
822 if (!nameString)
823 continue;
824 fprintf(stderrstderr, "CA[%d]: %s\n", i + 1, nameString);
825 PORT_FreePORT_Free_Util(nameString);
826 }
827 if (!caNames->arena) {
828 PORT_FreeArenaPORT_FreeArena_Util(arena, PR_FALSE0);
829 }
830 }
831 }
832 rv = NSS_GetClientAuthData(arg, socket, caNames, pRetCert, pRetKey);
833 if (rv == SECSuccess && *pRetCert) {
834 char *nameString = CERT_NameToAscii(&((*pRetCert)->subject));
835 if (nameString) {
836 fprintf(stderrstderr, "sent cert: %s\n", nameString);
837 PORT_FreePORT_Free_Util(nameString);
838 }
839 } else {
840 fprintf(stderrstderr, "send no cert\n");
841 }
842 return rv;
843 }
844 return NSS_GetClientAuthData(arg, socket, caNames, pRetCert, pRetKey);
845}
846
847#if defined(WIN32) || defined(OS2)
848void
849thread_main(void *arg)
850{
851 PRFileDesc *ps = (PRFileDesc *)arg;
852 PRFileDesc *std_in;
853 int wc, rc;
854 char buf[256];
855
856 if (requestFile) {
857 std_in = PR_Open(requestFile, PR_RDONLY0x01, 0);
858 } else {
859 std_in = PR_GetSpecialFD(PR_StandardInput);
860 }
861
862#ifdef WIN32
863 if (!requestFile) {
864 /* Put stdin into O_BINARY mode
865 ** or else incoming \r\n's will become \n's.
866 */
867 int smrv = _setmode(_fileno(stdinstdin), _O_BINARY);
868 if (smrv == -1) {
869 fprintf(stderrstderr,
870 "%s: Cannot change stdin to binary mode. Use -i option instead.\n",
871 progName);
872 /* plow ahead anyway */
873 }
874 }
875#endif
876
877 do {
878 rc = PR_Read(std_in, buf, sizeof buf);
879 if (rc <= 0)
880 break;
881 wc = PR_Send(ps, buf, rc, 0, maxInterval);
882 } while (wc == rc);
883 PR_Close(ps);
884 if (requestFile) {
885 PR_Close(std_in);
886 }
887}
888
889#endif
890
891static void
892printHostNameAndAddr(const char *host, const PRNetAddr *addr)
893{
894 PRUint16 port = PR_NetAddrInetPort(addr)((addr)->raw.family == 10 ? (addr)->ipv6.port : (addr)->
inet.port)
;
895 char addrBuf[80];
896 PRStatus st = PR_NetAddrToString(addr, addrBuf, sizeof addrBuf);
897
898 if (st == PR_SUCCESS) {
899 port = PR_ntohs(port);
900 FPRINTFif (verbose) fprintf(stderrstderr, "%s: connecting to %s:%hu (address=%s)\n",
901 progName, host, port, addrBuf);
902 }
903}
904
905/*
906 * Prints output according to skipProtoHeader flag. If skipProtoHeader
907 * is not set, prints without any changes, otherwise looking
908 * for \n\r\n(empty line sequence: HTTP header separator) and
909 * prints everything after it.
910 */
911static void
912separateReqHeader(const PRFileDesc *outFd, const char *buf, const int nb,
913 PRBool *wrStarted, int *ptrnMatched)
914{
915
916 /* it is sufficient to look for only "\n\r\n". Hopping that
917 * HTTP response format satisfies the standard */
918 char *ptrnStr = "\n\r\n";
919 char *resPtr;
920
921 if (nb == 0) {
922 return;
923 }
924
925 if (*ptrnMatched > 0) {
926 /* Get here only if previous separateReqHeader call found
927 * only a fragment of "\n\r\n" in previous buffer. */
928 PORT_Assert(*ptrnMatched < 3)((*ptrnMatched < 3)?((void)0):PR_Assert("*ptrnMatched < 3"
,"tstclnt.c",928))
;
929
930 /* the size of fragment of "\n\r\n" what we want to find in this
931 * buffer is equal to *ptrnMatched */
932 if (*ptrnMatched <= nb) {
933 /* move the pointer to the beginning of the fragment */
934 int strSize = *ptrnMatched;
935 char *tmpPtrn = ptrnStr + (3 - strSize);
936 if (PL_strncmp(buf, tmpPtrn, strSize) == 0) {
937 /* print the rest of the buffer(without the fragment) */
938 PR_Write((void *)outFd, buf + strSize, nb - strSize);
939 *wrStarted = PR_TRUE1;
940 return;
941 }
942 } else {
943 /* we are here only when nb == 1 && *ptrnMatched == 2 */
944 if (*buf == '\r') {
945 *ptrnMatched = 1;
946 } else {
947 *ptrnMatched = 0;
948 }
949 return;
950 }
951 }
952 resPtr = PL_strnstr(buf, ptrnStr, nb);
953 if (resPtr != NULL((void*)0)) {
954 /* if "\n\r\n" was found in the buffer, calculate offset
955 * and print the rest of the buffer */
956 int newBn = nb - (resPtr - buf + 3); /* 3 is the length of "\n\r\n" */
957
958 PR_Write((void *)outFd, resPtr + 3, newBn);
959 *wrStarted = PR_TRUE1;
960 return;
961 } else {
962 /* try to find a fragment of "\n\r\n" at the end of the buffer.
963 * if found, set *ptrnMatched to the number of chars left to find
964 * in the next buffer.*/
965 int i;
966 for (i = 1; i < 3; i++) {
967 char *bufPrt;
968 int strSize = 3 - i;
969
970 if (strSize > nb) {
971 continue;
972 }
973 bufPrt = (char *)(buf + nb - strSize);
974
975 if (PL_strncmp(bufPrt, ptrnStr, strSize) == 0) {
976 *ptrnMatched = i;
977 return;
978 }
979 }
980 }
981}
982
983#define SSOCK_FD0 0
984#define STDIN_FD1 1
985
986#define HEXCHAR_TO_INT(c, i)if (((c) >= '0') && ((c) <= '9')) { i = (c) - '0'
; } else if (((c) >= 'a') && ((c) <= 'f')) { i =
(c) - 'a' + 10; } else if (((c) >= 'A') && ((c) <=
'F')) { i = (c) - 'A' + 10; } else { Usage(); }
\
987 if (((c) >= '0') && ((c) <= '9')) { \
988 i = (c) - '0'; \
989 } else if (((c) >= 'a') && ((c) <= 'f')) { \
990 i = (c) - 'a' + 10; \
991 } else if (((c) >= 'A') && ((c) <= 'F')) { \
992 i = (c) - 'A' + 10; \
993 } else { \
994 Usage(); \
995 }
996
997static SECStatus
998restartHandshakeAfterServerCertIfNeeded(PRFileDesc *fd,
999 ServerCertAuth *serverCertAuth,
1000 PRBool override)
1001{
1002 SECStatus rv;
1003 PRErrorCode error = 0;
1004
1005 if (!serverCertAuth->isPaused || clientCertIsBlocked)
1006 return SECSuccess;
1007
1008 FPRINTFif (verbose) fprintf(stderrstderr, "%s: handshake was paused by auth certificate hook\n",
1009 progName);
1010
1011 serverCertAuth->isPaused = PR_FALSE0;
1012 rv = SSL_AuthCertificate(serverCertAuth->dbHandle, fd, PR_TRUE1, PR_FALSE0);
1013 if (rv != SECSuccess) {
1014 error = PR_GetError();
1015 if (error == 0) {
1016 PR_NOT_REACHED("SSL_AuthCertificate return SECFailure without "PR_Assert("SSL_AuthCertificate return SECFailure without " "setting error code."
,"tstclnt.c",1017)
1017 "setting error code.")PR_Assert("SSL_AuthCertificate return SECFailure without " "setting error code."
,"tstclnt.c",1017)
;
1018 error = PR_INVALID_STATE_ERROR(-5931L);
1019 } else if (override) {
1020 rv = ownBadCertHandler(NULL((void*)0), fd);
1021 }
1022 }
1023 if (rv == SECSuccess) {
1024 error = 0;
1025 }
1026
1027 if (SSL_AuthCertificateComplete(fd, error) != SECSuccess) {
1028 rv = SECFailure;
1029 } else {
1030 /* restore the original error code, which could be reset by
1031 * SSL_AuthCertificateComplete */
1032 PORT_SetErrorPORT_SetError_Util(error);
1033 }
1034
1035 return rv;
1036}
1037
1038char *host = NULL((void*)0);
1039char *nickname = NULL((void*)0);
1040char *cipherString = NULL((void*)0);
1041int multiplier = 0;
1042SSLVersionRange enabledVersions;
1043int disableLocking = 0;
1044int enableSessionTickets = 0;
1045int enableFalseStart = 0;
1046int enableCertStatus = 0;
1047int enableSignedCertTimestamps = 0;
1048int forceFallbackSCSV = 0;
1049int enableExtendedMasterSecret = 0;
1050PRBool requireDHNamedGroups = 0;
1051PRBool middleboxCompatMode = 0;
1052PRSocketOptionData opt;
1053PRNetAddr addr;
1054PRBool allowIPv4 = PR_TRUE1;
1055PRBool allowIPv6 = PR_TRUE1;
1056PRBool pingServerFirst = PR_FALSE0;
1057int pingTimeoutSeconds = -1;
1058PRBool clientSpeaksFirst = PR_FALSE0;
1059PRBool skipProtoHeader = PR_FALSE0;
1060ServerCertAuth serverCertAuth;
1061char *hs1SniHostName = NULL((void*)0);
1062char *hs2SniHostName = NULL((void*)0);
1063PRUint16 portno = 443;
1064int override = 0;
1065PRBool enableZeroRtt = PR_FALSE0;
1066PRUint8 *zeroRttData;
1067unsigned int zeroRttLen = 0;
1068PRBool enableAltServerHello = PR_FALSE0;
1069PRBool useDTLS = PR_FALSE0;
1070PRBool actAsServer = PR_FALSE0;
1071PRBool stopAfterHandshake = PR_FALSE0;
1072PRBool requestToExit = PR_FALSE0;
1073char *versionString = NULL((void*)0);
1074PRBool handshakeComplete = PR_FALSE0;
1075char *echConfigs = NULL((void*)0);
1076PRUint16 echGreaseSize = 0;
1077PRBool enablePostHandshakeAuth = PR_FALSE0;
1078PRBool enableDelegatedCredentials = PR_FALSE0;
1079const secuExporter *enabledExporters = NULL((void*)0);
1080unsigned int enabledExporterCount = 0;
1081
1082static int
1083writeBytesToServer(PRFileDesc *s, const PRUint8 *buf, int nb)
1084{
1085 SECStatus rv;
1086 const PRUint8 *bufp = buf;
1087 PRPollDesc pollDesc;
1088
1089 pollDesc.in_flags = PR_POLL_WRITE0x2 | PR_POLL_EXCEPT0x4;
1090 pollDesc.out_flags = 0;
1091 pollDesc.fd = s;
1092
1093 FPRINTFif (verbose) fprintf(stderrstderr, "%s: Writing %d bytes to server\n",
1094 progName, nb);
1095 do {
1096 PRInt32 cc = PR_Send(s, bufp, nb, 0, maxInterval);
1097 if (cc < 0) {
1098 PRErrorCode err = PR_GetError();
1099 if (err != PR_WOULD_BLOCK_ERROR(-5998L)) {
1100 SECU_PrintError(progName, "write to SSL socket failed");
1101 return 254;
1102 }
1103 cc = 0;
1104 }
1105 FPRINTFif (verbose) fprintf(stderrstderr, "%s: %d bytes written\n", progName, cc);
1106 if (enableZeroRtt && !handshakeComplete) {
1107 if (zeroRttLen + cc > ZERO_RTT_MAX(2 << 16)) {
1108 SECU_PrintError(progName, "too much early data to save");
1109 return -1;
1110 }
1111 PORT_Memcpymemcpy(zeroRttData + zeroRttLen, bufp, cc);
1112 zeroRttLen += cc;
1113 }
1114 bufp += cc;
1115 nb -= cc;
1116 if (nb <= 0)
1117 break;
1118
1119 rv = restartHandshakeAfterServerCertIfNeeded(s,
1120 &serverCertAuth, override);
1121 if (rv != SECSuccess) {
1122 SECU_PrintError(progName, "authentication of server cert failed");
1123 return EXIT_CODE_HANDSHAKE_FAILED254;
1124 }
1125
1126 rv = restartHandshakeAfterClientCertIfNeeded(s);
1127 if (rv == SECSuccess) {
1128 continue;
1129 }
1130
1131 pollDesc.in_flags = PR_POLL_WRITE0x2 | PR_POLL_EXCEPT0x4;
1132 pollDesc.out_flags = 0;
1133 FPRINTFif (verbose) fprintf(stderrstderr,
1134 "%s: about to call PR_Poll on writable socket !\n",
1135 progName);
1136 cc = PR_Poll(&pollDesc, 1, PR_INTERVAL_NO_TIMEOUT0xffffffffUL);
1137 if (cc < 0) {
1138 SECU_PrintError(progName, "PR_Poll failed");
1139 return -1;
1140 }
1141 FPRINTFif (verbose) fprintf(stderrstderr,
1142 "%s: PR_Poll returned with writable socket !\n",
1143 progName);
1144 } while (1);
1145
1146 return 0;
1147}
1148
1149void
1150handshakeCallback(PRFileDesc *fd, void *client_data)
1151{
1152 const char *secondHandshakeName = (char *)client_data;
1153 if (secondHandshakeName) {
1154 SSL_SetURL(fd, secondHandshakeName);
1155 }
1156 printSecurityInfo(fd);
1157 if (renegotiationsDone < renegotiationsToDo) {
1158 SSL_ReHandshake(fd, (renegotiationsToDo < 2));
1159 ++renegotiationsDone;
1160 }
1161 if (zeroRttLen) {
1162 /* This data was sent in 0-RTT. */
1163 SSLChannelInfo info;
1164 SECStatus rv;
1165
1166 rv = SSL_GetChannelInfo(fd, &info, sizeof(info));
1167 if (rv != SECSuccess)
1168 return;
1169
1170 if (!info.earlyDataAccepted) {
1171 FPRINTFif (verbose) fprintf(stderrstderr, "Early data rejected. Re-sending %d bytes\n",
1172 zeroRttLen);
1173 writeBytesToServer(fd, zeroRttData, zeroRttLen);
1174 zeroRttLen = 0;
1175 }
1176 }
1177 if (stopAfterHandshake) {
1178 requestToExit = PR_TRUE1;
1179 }
1180 handshakeComplete = PR_TRUE1;
1181
1182 if (enabledExporters) {
1183 SECStatus rv;
1184
1185 rv = exportKeyingMaterials(fd, enabledExporters, enabledExporterCount);
1186 if (rv != SECSuccess) {
1187 PRErrorCode err = PR_GetError();
1188 FPRINTFif (verbose) fprintf(stderrstderr,
1189 "couldn't export keying material: %s\n",
1190 SECU_Strerror(err)PR_ErrorToString((err), 0));
1191 }
1192 }
1193}
1194
1195static SECStatus
1196installServerCertificate(PRFileDesc *s, char *nick)
1197{
1198 CERTCertificate *cert;
1199 SECKEYPrivateKey *privKey = NULL((void*)0);
1200
1201 if (!nick) {
1202 PORT_SetErrorPORT_SetError_Util(SEC_ERROR_INVALID_ARGS);
1203 return SECFailure;
1204 }
1205
1206 cert = PK11_FindCertFromNickname(nick, &pwdata);
1207 if (cert == NULL((void*)0)) {
1208 return SECFailure;
1209 }
1210
1211 privKey = PK11_FindKeyByAnyCert(cert, &pwdata);
1212 if (privKey == NULL((void*)0)) {
1213 return SECFailure;
1214 }
1215 if (SSL_ConfigServerCert(s, cert, privKey, NULL((void*)0), 0) != SECSuccess) {
1216 return SECFailure;
1217 }
1218 SECKEY_DestroyPrivateKey(privKey);
1219 CERT_DestroyCertificate(cert);
1220
1221 return SECSuccess;
1222}
1223
1224static SECStatus
1225bindToClient(PRFileDesc *s)
1226{
1227 PRStatus status;
1228 status = PR_Bind(s, &addr);
1229 if (status != PR_SUCCESS) {
1230 return SECFailure;
1231 }
1232
1233 for (;;) {
1234 /* Bind the remote address on first packet. This must happen
1235 * before we SSL-ize the socket because we need to get the
1236 * peer's address before SSLizing. Recvfrom gives us that
1237 * while not consuming any data. */
1238 unsigned char tmp;
1239 PRNetAddr remote;
1240 int nb;
1241
1242 nb = PR_RecvFrom(s, &tmp, 1, PR_MSG_PEEK0x2,
1243 &remote, PR_INTERVAL_NO_TIMEOUT0xffffffffUL);
1244 if (nb != 1)
1245 continue;
1246
1247 status = PR_Connect(s, &remote, PR_INTERVAL_NO_TIMEOUT0xffffffffUL);
1248 if (status != PR_SUCCESS) {
1249 SECU_PrintError(progName, "server bind to remote end failed");
1250 return SECFailure;
1251 }
1252 return SECSuccess;
1253 }
1254
1255 /* Unreachable. */
1256}
1257
1258static SECStatus
1259connectToServer(PRFileDesc *s, PRPollDesc *pollset)
1260{
1261 PRStatus status;
1262 PRInt32 filesReady;
1263
1264 status = PR_Connect(s, &addr, PR_INTERVAL_NO_TIMEOUT0xffffffffUL);
1265 if (status != PR_SUCCESS) {
1266 if (PR_GetError() == PR_IN_PROGRESS_ERROR(-5934L)) {
1267 if (verbose)
1268 SECU_PrintError(progName, "connect");
1269 milliPause(50 * multiplier);
1270 pollset[SSOCK_FD0].in_flags = PR_POLL_WRITE0x2 | PR_POLL_EXCEPT0x4;
1271 pollset[SSOCK_FD0].out_flags = 0;
1272 pollset[SSOCK_FD0].fd = s;
1273 while (1) {
1274 FPRINTFif (verbose) fprintf(stderrstderr,
1275 "%s: about to call PR_Poll for connect completion!\n",
1276 progName);
1277 filesReady = PR_Poll(pollset, 1, PR_INTERVAL_NO_TIMEOUT0xffffffffUL);
1278 if (filesReady < 0) {
1279 SECU_PrintError(progName, "unable to connect (poll)");
1280 return SECFailure;
1281 }
1282 FPRINTFif (verbose) fprintf(stderrstderr,
1283 "%s: PR_Poll returned 0x%02x for socket out_flags.\n",
1284 progName, pollset[SSOCK_FD0].out_flags);
1285 if (filesReady == 0) { /* shouldn't happen! */
1286 SECU_PrintError(progName, "%s: PR_Poll returned zero!\n");
1287 return SECFailure;
1288 }
1289 status = PR_GetConnectStatus(pollset);
1290 if (status == PR_SUCCESS) {
1291 break;
1292 }
1293 if (PR_GetError() != PR_IN_PROGRESS_ERROR(-5934L)) {
1294 SECU_PrintError(progName, "unable to connect (poll)");
1295 return SECFailure;
1296 }
1297 SECU_PrintError(progName, "poll");
1298 milliPause(50 * multiplier);
1299 }
1300 } else {
1301 SECU_PrintError(progName, "unable to connect");
1302 return SECFailure;
1303 }
1304 }
1305
1306 return SECSuccess;
1307}
1308
1309static SECStatus
1310importPsk(PRFileDesc *s)
1311{
1312 SECU_PrintAsHex(stdoutstdout, &psk, "Using External PSK", 0);
1313 PK11SlotInfo *slot = NULL((void*)0);
1314 PK11SymKey *symKey = NULL((void*)0);
1315 slot = PK11_GetInternalSlot();
1316 if (!slot) {
1317 SECU_PrintError(progName, "PK11_GetInternalSlot failed");
1318 return SECFailure;
1319 }
1320 symKey = PK11_ImportSymKey(slot, CKM_HKDF_KEY_GEN0x0000402cUL, PK11_OriginUnwrap,
1321 CKA_DERIVE0x0000010CUL, &psk, NULL((void*)0));
1322 PK11_FreeSlot(slot);
1323 if (!symKey) {
1324 SECU_PrintError(progName, "PK11_ImportSymKey failed");
1325 return SECFailure;
1326 }
1327
1328 SECStatus rv = SSL_AddExternalPsk(s, symKey, (const PRUint8 *)pskLabel.data,(SSL_GetExperimentalAPI("SSL_AddExternalPsk") ? ((SECStatus(*
) (PRFileDesc * _fd, PK11SymKey * _psk, const PRUint8 *_identity
, unsigned int _identityLen, SSLHashType _hash))SSL_GetExperimentalAPI
("SSL_AddExternalPsk"))(s, symKey, (const PRUint8 *)pskLabel.
data, pskLabel.len, ssl_hash_sha256) : SECFailure)
1329 pskLabel.len, ssl_hash_sha256)(SSL_GetExperimentalAPI("SSL_AddExternalPsk") ? ((SECStatus(*
) (PRFileDesc * _fd, PK11SymKey * _psk, const PRUint8 *_identity
, unsigned int _identityLen, SSLHashType _hash))SSL_GetExperimentalAPI
("SSL_AddExternalPsk"))(s, symKey, (const PRUint8 *)pskLabel.
data, pskLabel.len, ssl_hash_sha256) : SECFailure)
;
1330 PK11_FreeSymKey(symKey);
1331 return rv;
1332}
1333
1334static SECStatus
1335printEchRetryConfigs(PRFileDesc *s)
1336{
1337 if (PORT_GetErrorPORT_GetError_Util() == SSL_ERROR_ECH_RETRY_WITH_ECH) {
1338 SECItem retries = { siBuffer, NULL((void*)0), 0 };
1339 SECStatus rv = SSL_GetEchRetryConfigs(s, &retries)(SSL_GetExperimentalAPI("SSL_GetEchRetryConfigs") ? ((SECStatus
(*) (PRFileDesc * _fd, SECItem * _out))SSL_GetExperimentalAPI
("SSL_GetEchRetryConfigs"))(s, &retries) : SECFailure)
;
1340 if (rv != SECSuccess) {
1341 SECU_PrintError(progName, "SSL_GetEchRetryConfigs failed");
1342 return SECFailure;
1343 }
1344 char *retriesBase64 = NSSBase64_EncodeItemNSSBase64_EncodeItem_Util(NULL((void*)0), NULL((void*)0), 0, &retries);
1345 if (!retriesBase64) {
1346 SECU_PrintError(progName, "NSSBase64_EncodeItem on retry_configs failed");
1347 SECITEM_FreeItemSECITEM_FreeItem_Util(&retries, PR_FALSE0);
1348 return SECFailure;
1349 }
1350
1351 // Remove the newline characters that NSSBase64_EncodeItem unhelpfully inserts.
1352 char *newline = strstr(retriesBase64, "\r\n");
1353 if (newline) {
1354 memmove(newline, newline + 2, strlen(newline + 2) + 1);
1355 }
1356 fprintf(stderrstderr, "Received ECH retry_configs: \n%s\n", retriesBase64);
1357 PORT_FreePORT_Free_Util(retriesBase64);
1358 SECITEM_FreeItemSECITEM_FreeItem_Util(&retries, PR_FALSE0);
1359 }
1360 return SECSuccess;
1361}
1362
1363static int
1364run()
1365{
1366 int headerSeparatorPtrnId = 0;
1367 int error = 0;
1368 SECStatus rv;
1369 PRStatus status;
1370 PRInt32 filesReady;
1371 PRFileDesc *s = NULL((void*)0);
1372 PRFileDesc *std_out;
1373 PRPollDesc pollset[2] = { { 0 }, { 0 } };
1374 PRBool wrStarted = PR_FALSE0;
1375
1376 handshakeComplete = PR_FALSE0;
1377
1378 /* Create socket */
1379 if (useDTLS) {
1
Assuming 'useDTLS' is 0
2
Taking false branch
1380 s = PR_OpenUDPSocket(addr.raw.family);
1381 } else {
1382 s = PR_OpenTCPSocket(addr.raw.family);
1383 }
1384
1385 if (s == NULL((void*)0)) {
3
Assuming 's' is not equal to NULL
4
Taking false branch
1386 SECU_PrintError(progName, "error creating socket");
1387 error = 1;
1388 goto done;
1389 }
1390
1391 if (actAsServer) {
5
Assuming 'actAsServer' is 0
6
Taking false branch
1392 if (bindToClient(s) != SECSuccess) {
1393 return 1;
1394 }
1395 }
1396 opt.option = PR_SockOpt_Nonblocking;
1397 opt.value.non_blocking = PR_TRUE1; /* default */
1398 if (serverCertAuth.testFreshStatusFromSideChannel) {
7
Assuming field 'testFreshStatusFromSideChannel' is 0
8
Taking false branch
1399 opt.value.non_blocking = PR_FALSE0;
1400 }
1401 status = PR_SetSocketOption(s, &opt);
1402 if (status != PR_SUCCESS) {
9
Assuming 'status' is equal to PR_SUCCESS
10
Taking false branch
1403 SECU_PrintError(progName, "error setting socket options");
1404 error = 1;
1405 goto done;
1406 }
1407
1408 if (useDTLS) {
11
Assuming 'useDTLS' is 0
12
Taking false branch
1409 s = DTLS_ImportFD(NULL((void*)0), s);
1410 } else {
1411 s = SSL_ImportFD(NULL((void*)0), s);
1412 }
1413 if (s == NULL((void*)0)) {
13
Assuming 's' is not equal to NULL
14
Taking false branch
1414 SECU_PrintError(progName, "error importing socket");
1415 error = 1;
1416 goto done;
1417 }
1418 SSL_SetPKCS11PinArg(s, &pwdata);
1419
1420 rv = SSL_OptionSet(s, SSL_SECURITY1, 1);
1421 if (rv != SECSuccess) {
15
Assuming 'rv' is equal to SECSuccess
16
Taking false branch
1422 SECU_PrintError(progName, "error enabling socket");
1423 error = 1;
1424 goto done;
1425 }
1426
1427 rv = SSL_OptionSet(s, actAsServer ? SSL_HANDSHAKE_AS_SERVER6 : SSL_HANDSHAKE_AS_CLIENT5, 1);
17
Assuming 'actAsServer' is 0
18
'?' condition is false
1428 if (rv != SECSuccess) {
19
Assuming 'rv' is equal to SECSuccess
20
Taking false branch
1429 SECU_PrintError(progName, "error enabling client handshake");
1430 error = 1;
1431 goto done;
1432 }
1433
1434 /* all SSL3 cipher suites are enabled by default. */
1435 if (cipherString) {
21
Assuming 'cipherString' is null
22
Taking false branch
1436 char *cstringSaved = cipherString;
1437 int ndx;
1438
1439 while (0 != (ndx = *cipherString++)) {
1440 int cipher = 0;
1441
1442 if (ndx == ':') {
1443 int ctmp = 0;
1444
1445 HEXCHAR_TO_INT(*cipherString, ctmp)if (((*cipherString) >= '0') && ((*cipherString) <=
'9')) { ctmp = (*cipherString) - '0'; } else if (((*cipherString
) >= 'a') && ((*cipherString) <= 'f')) { ctmp =
(*cipherString) - 'a' + 10; } else if (((*cipherString) >=
'A') && ((*cipherString) <= 'F')) { ctmp = (*cipherString
) - 'A' + 10; } else { Usage(); }
1446 cipher |= (ctmp << 12);
1447 cipherString++;
1448 HEXCHAR_TO_INT(*cipherString, ctmp)if (((*cipherString) >= '0') && ((*cipherString) <=
'9')) { ctmp = (*cipherString) - '0'; } else if (((*cipherString
) >= 'a') && ((*cipherString) <= 'f')) { ctmp =
(*cipherString) - 'a' + 10; } else if (((*cipherString) >=
'A') && ((*cipherString) <= 'F')) { ctmp = (*cipherString
) - 'A' + 10; } else { Usage(); }
1449 cipher |= (ctmp << 8);
1450 cipherString++;
1451 HEXCHAR_TO_INT(*cipherString, ctmp)if (((*cipherString) >= '0') && ((*cipherString) <=
'9')) { ctmp = (*cipherString) - '0'; } else if (((*cipherString
) >= 'a') && ((*cipherString) <= 'f')) { ctmp =
(*cipherString) - 'a' + 10; } else if (((*cipherString) >=
'A') && ((*cipherString) <= 'F')) { ctmp = (*cipherString
) - 'A' + 10; } else { Usage(); }
1452 cipher |= (ctmp << 4);
1453 cipherString++;
1454 HEXCHAR_TO_INT(*cipherString, ctmp)if (((*cipherString) >= '0') && ((*cipherString) <=
'9')) { ctmp = (*cipherString) - '0'; } else if (((*cipherString
) >= 'a') && ((*cipherString) <= 'f')) { ctmp =
(*cipherString) - 'a' + 10; } else if (((*cipherString) >=
'A') && ((*cipherString) <= 'F')) { ctmp = (*cipherString
) - 'A' + 10; } else { Usage(); }
1455 cipher |= ctmp;
1456 cipherString++;
1457 } else {
1458 if (!isalpha(ndx)((*__ctype_b_loc ())[(int) ((ndx))] & (unsigned short int
) _ISalpha)
)
1459 Usage();
1460 ndx = tolower(ndx) - 'a';
1461 if (ndx < PR_ARRAY_SIZE(ssl3CipherSuites)(sizeof(ssl3CipherSuites)/sizeof((ssl3CipherSuites)[0]))) {
1462 cipher = ssl3CipherSuites[ndx];
1463 }
1464 }
1465 if (cipher > 0) {
1466 rv = SSL_CipherPrefSet(s, cipher, SSL_ALLOWED1);
1467 if (rv != SECSuccess) {
1468 SECU_PrintError(progName, "SSL_CipherPrefSet()");
1469 error = 1;
1470 goto done;
1471 }
1472 } else {
1473 Usage();
1474 }
1475 }
1476 PORT_FreePORT_Free_Util(cstringSaved);
1477 }
1478
1479 rv = SSL_VersionRangeSet(s, &enabledVersions);
1480 if (rv != SECSuccess) {
23
Assuming 'rv' is equal to SECSuccess
24
Taking false branch
1481 SECU_PrintError(progName, "error setting SSL/TLS version range ");
1482 error = 1;
1483 goto done;
1484 }
1485
1486 /* disable SSL socket locking */
1487 rv = SSL_OptionSet(s, SSL_NO_LOCKS17, disableLocking);
1488 if (rv != SECSuccess) {
25
Assuming 'rv' is equal to SECSuccess
26
Taking false branch
1489 SECU_PrintError(progName, "error disabling SSL socket locking");
1490 error = 1;
1491 goto done;
1492 }
1493
1494 /* enable Session Ticket extension. */
1495 rv = SSL_OptionSet(s, SSL_ENABLE_SESSION_TICKETS18, enableSessionTickets);
1496 if (rv != SECSuccess) {
27
Assuming 'rv' is equal to SECSuccess
28
Taking false branch
1497 SECU_PrintError(progName, "error enabling Session Ticket extension");
1498 error = 1;
1499 goto done;
1500 }
1501
1502 /* enable false start. */
1503 rv = SSL_OptionSet(s, SSL_ENABLE_FALSE_START22, enableFalseStart);
1504 if (rv != SECSuccess) {
29
Assuming 'rv' is equal to SECSuccess
30
Taking false branch
1505 SECU_PrintError(progName, "error enabling false start");
1506 error = 1;
1507 goto done;
1508 }
1509
1510 if (forceFallbackSCSV) {
31
Assuming 'forceFallbackSCSV' is 0
32
Taking false branch
1511 rv = SSL_OptionSet(s, SSL_ENABLE_FALLBACK_SCSV28, PR_TRUE1);
1512 if (rv != SECSuccess) {
1513 SECU_PrintError(progName, "error forcing fallback scsv");
1514 error = 1;
1515 goto done;
1516 }
1517 }
1518
1519 /* enable cert status (OCSP stapling). */
1520 rv = SSL_OptionSet(s, SSL_ENABLE_OCSP_STAPLING24, enableCertStatus);
1521 if (rv != SECSuccess) {
33
Assuming 'rv' is equal to SECSuccess
34
Taking false branch
1522 SECU_PrintError(progName, "error enabling cert status (OCSP stapling)");
1523 error = 1;
1524 goto done;
1525 }
1526
1527 /* enable negotiation of delegated credentials (draft-ietf-tls-subcerts) */
1528 rv = SSL_OptionSet(s, SSL_ENABLE_DELEGATED_CREDENTIALS40, enableDelegatedCredentials);
1529 if (rv != SECSuccess) {
35
Assuming 'rv' is equal to SECSuccess
36
Taking false branch
1530 SECU_PrintError(progName, "error enabling delegated credentials");
1531 error = 1;
1532 goto done;
1533 }
1534
1535 /* enable extended master secret mode */
1536 if (enableExtendedMasterSecret) {
37
Assuming 'enableExtendedMasterSecret' is 0
38
Taking false branch
1537 rv = SSL_OptionSet(s, SSL_ENABLE_EXTENDED_MASTER_SECRET30, PR_TRUE1);
1538 if (rv != SECSuccess) {
1539 SECU_PrintError(progName, "error enabling extended master secret");
1540 error = 1;
1541 goto done;
1542 }
1543 }
1544
1545 /* enable 0-RTT (TLS 1.3 only) */
1546 if (enableZeroRtt) {
39
Assuming 'enableZeroRtt' is 0
40
Taking false branch
1547 rv = SSL_OptionSet(s, SSL_ENABLE_0RTT_DATA33, PR_TRUE1);
1548 if (rv != SECSuccess) {
1549 SECU_PrintError(progName, "error enabling 0-RTT");
1550 error = 1;
1551 goto done;
1552 }
1553 }
1554
1555 /* Alternate ServerHello content type (TLS 1.3 only) */
1556 if (enableAltServerHello) {
41
Assuming 'enableAltServerHello' is 0
42
Taking false branch
1557 rv = SSL_UseAltServerHelloType(s, PR_TRUE)(PR_SetError(SSL_ERROR_UNSUPPORTED_EXPERIMENTAL_API, 0), SECFailure
)
;
1558 if (rv != SECSuccess) {
1559 SECU_PrintError(progName, "error enabling alternate ServerHello type");
1560 error = 1;
1561 goto done;
1562 }
1563 }
1564
1565 /* Middlebox compatibility mode (TLS 1.3 only) */
1566 if (middleboxCompatMode) {
43
Assuming 'middleboxCompatMode' is 0
44
Taking false branch
1567 rv = SSL_OptionSet(s, SSL_ENABLE_TLS13_COMPAT_MODE35, PR_TRUE1);
1568 if (rv != SECSuccess) {
1569 SECU_PrintError(progName, "error enabling middlebox compatibility mode");
1570 error = 1;
1571 goto done;
1572 }
1573 }
1574
1575 /* require the use of fixed finite-field DH groups */
1576 if (requireDHNamedGroups) {
45
Assuming 'requireDHNamedGroups' is 0
46
Taking false branch
1577 rv = SSL_OptionSet(s, SSL_REQUIRE_DH_NAMED_GROUPS32, PR_TRUE1);
1578 if (rv != SECSuccess) {
1579 SECU_PrintError(progName, "error in requiring the use of fixed finite-field DH groups");
1580 error = 1;
1581 goto done;
1582 }
1583 }
1584
1585 /* enable Signed Certificate Timestamps. */
1586 rv = SSL_OptionSet(s, SSL_ENABLE_SIGNED_CERT_TIMESTAMPS31,
1587 enableSignedCertTimestamps);
1588 if (rv != SECSuccess) {
47
Assuming 'rv' is equal to SECSuccess
48
Taking false branch
1589 SECU_PrintError(progName, "error enabling signed cert timestamps");
1590 error = 1;
1591 goto done;
1592 }
1593
1594 if (enablePostHandshakeAuth) {
49
Assuming 'enablePostHandshakeAuth' is 0
50
Taking false branch
1595 rv = SSL_OptionSet(s, SSL_ENABLE_POST_HANDSHAKE_AUTH39, PR_TRUE1);
1596 if (rv != SECSuccess) {
1597 SECU_PrintError(progName, "error enabling post-handshake auth");
1598 error = 1;
1599 goto done;
1600 }
1601 }
1602
1603 if (enabledGroups) {
51
Assuming 'enabledGroups' is null
52
Taking false branch
1604 rv = SSL_NamedGroupConfig(s, enabledGroups, enabledGroupsCount);
1605 if (rv < 0) {
1606 SECU_PrintError(progName, "SSL_NamedGroupConfig failed");
1607 error = 1;
1608 goto done;
1609 }
1610 }
1611
1612 if (enabledSigSchemes) {
53
Assuming 'enabledSigSchemes' is null
54
Taking false branch
1613 rv = SSL_SignatureSchemePrefSet(s, enabledSigSchemes, enabledSigSchemeCount);
1614 if (rv < 0) {
1615 SECU_PrintError(progName, "SSL_SignatureSchemePrefSet failed");
1616 error = 1;
1617 goto done;
1618 }
1619 }
1620
1621 if (echConfigs) {
55
Assuming 'echConfigs' is null
56
Taking false branch
1622 SECItem echConfigsBin = { siBuffer, NULL((void*)0), 0 };
1623
1624 if (!NSSBase64_DecodeBufferNSSBase64_DecodeBuffer_Util(NULL((void*)0), &echConfigsBin, echConfigs,
1625 strlen(echConfigs))) {
1626 SECU_PrintError(progName, "ECHConfigs record is invalid base64");
1627 error = 1;
1628 goto done;
1629 }
1630
1631 rv = SSL_SetClientEchConfigs(s, echConfigsBin.data, echConfigsBin.len)(SSL_GetExperimentalAPI("SSL_SetClientEchConfigs") ? ((SECStatus
(*) (PRFileDesc * _fd, const PRUint8 *_echConfigs, unsigned int
_echConfigsLen))SSL_GetExperimentalAPI("SSL_SetClientEchConfigs"
))(s, echConfigsBin.data, echConfigsBin.len) : SECFailure)
;
1632 SECITEM_FreeItemSECITEM_FreeItem_Util(&echConfigsBin, PR_FALSE0);
1633 if (rv < 0) {
1634 SECU_PrintError(progName, "SSL_SetClientEchConfigs failed");
1635 error = 1;
1636 goto done;
1637 }
1638 }
1639
1640 if (echGreaseSize) {
57
Assuming 'echGreaseSize' is 0
58
Taking false branch
1641 rv = SSL_EnableTls13GreaseEch(s, PR_TRUE)(SSL_GetExperimentalAPI("SSL_EnableTls13GreaseEch") ? ((SECStatus
(*) (PRFileDesc * _fd, PRBool _enabled))SSL_GetExperimentalAPI
("SSL_EnableTls13GreaseEch"))(s, 1) : SECFailure)
;
1642 if (rv != SECSuccess) {
1643 SECU_PrintError(progName, "SSL_EnableTls13GreaseEch failed");
1644 error = 1;
1645 goto done;
1646 }
1647 rv = SSL_SetTls13GreaseEchSize(s, echGreaseSize)(SSL_GetExperimentalAPI("SSL_SetTls13GreaseEchSize") ? ((SECStatus
(*) (PRFileDesc * _fd, PRUint8 _size))SSL_GetExperimentalAPI(
"SSL_SetTls13GreaseEchSize"))(s, echGreaseSize) : SECFailure)
;
1648 if (rv != SECSuccess) {
1649 SECU_PrintError(progName, "SSL_SetTls13GreaseEchSize failed");
1650 error = 1;
1651 goto done;
1652 }
1653 }
1654
1655 if (psk.data) {
59
Assuming field 'data' is null
60
Taking false branch
1656 rv = importPsk(s);
1657 if (rv != SECSuccess) {
1658 SECU_PrintError(progName, "importPsk failed");
1659 error = 1;
1660 goto done;
1661 }
1662 }
1663
1664 serverCertAuth.dbHandle = CERT_GetDefaultCertDB();
1665
1666 SSL_AuthCertificateHook(s, ownAuthCertificate, &serverCertAuth);
1667 if (override) {
61
Assuming 'override' is 0
62
Taking false branch
1668 SSL_BadCertHook(s, ownBadCertHandler, NULL((void*)0));
1669 }
1670 if (actAsServer) {
63
Assuming 'actAsServer' is 0
64
Taking false branch
1671 rv = installServerCertificate(s, nickname);
1672 if (rv != SECSuccess) {
1673 SECU_PrintError(progName, "error installing server cert");
1674 return 1;
1675 }
1676 rv = SSL_ConfigServerSessionIDCache(1024, 0, 0, ".");
1677 if (rv != SECSuccess) {
1678 SECU_PrintError(progName, "error configuring session cache");
1679 return 1;
1680 }
1681 initializedServerSessionCache = PR_TRUE1;
1682 } else {
1683 SSL_GetClientAuthDataHook(s, own_GetClientAuthData, (void *)nickname);
1684 }
1685 SSL_HandshakeCallback(s, handshakeCallback, hs2SniHostName);
1686 if (hs1SniHostName) {
65
Assuming 'hs1SniHostName' is null
66
Taking false branch
1687 SSL_SetURL(s, hs1SniHostName);
1688 } else {
1689 SSL_SetURL(s, host);
1690 }
1691
1692 if (actAsServer) {
67
Assuming 'actAsServer' is not equal to 0
68
Taking true branch
1693 rv = SSL_ResetHandshake(s, PR_TRUE1 /* server */);
1694 if (rv != SECSuccess) {
69
Assuming 'rv' is equal to SECSuccess
70
Taking false branch
1695 return 1;
1696 }
1697 } else {
1698 /* Try to connect to the server */
1699 rv = connectToServer(s, pollset);
1700 if (rv != SECSuccess) {
1701 error = 1;
1702 goto done;
1703 }
1704 }
1705
1706 pollset[SSOCK_FD0].fd = s;
1707 pollset[SSOCK_FD0].in_flags = PR_POLL_EXCEPT0x4;
1708 if (!actAsServer)
71
Assuming 'actAsServer' is not equal to 0
72
Taking false branch
1709 pollset[SSOCK_FD0].in_flags |= (clientSpeaksFirst ? 0 : PR_POLL_READ0x1);
1710 else
1711 pollset[SSOCK_FD0].in_flags |= PR_POLL_READ0x1;
1712 if (requestFile) {
73
Assuming 'requestFile' is null
74
Taking false branch
1713 pollset[STDIN_FD1].fd = PR_Open(requestFile, PR_RDONLY0x01, 0);
1714 if (!pollset[STDIN_FD1].fd) {
1715 fprintf(stderrstderr, "%s: unable to open input file: %s\n",
1716 progName, requestFile);
1717 error = 1;
1718 goto done;
1719 }
1720 } else {
1721 pollset[STDIN_FD1].fd = PR_GetSpecialFD(PR_StandardInput);
1722 }
1723 pollset[STDIN_FD1].in_flags = PR_POLL_READ0x1;
1724 std_out = PR_GetSpecialFD(PR_StandardOutput);
1725
1726#if defined(WIN32) || defined(OS2)
1727 /* PR_Poll cannot be used with stdin on Windows or OS/2. (sigh).
1728 ** But use of PR_Poll and non-blocking sockets is a major feature
1729 ** of this program. So, we simulate a pollable stdin with a
1730 ** TCP socket pair and a thread that reads stdin and writes to
1731 ** that socket pair.
1732 */
1733 {
1734 PRFileDesc *fds[2];
1735 PRThread *thread;
1736
1737 int nspr_rv = PR_NewTCPSocketPair(fds);
1738 if (nspr_rv != PR_SUCCESS) {
1739 SECU_PrintError(progName, "PR_NewTCPSocketPair failed");
1740 error = 1;
1741 goto done;
1742 }
1743 pollset[STDIN_FD1].fd = fds[1];
1744
1745 thread = PR_CreateThread(PR_USER_THREAD, thread_main, fds[0],
1746 PR_PRIORITY_NORMAL, PR_GLOBAL_THREAD,
1747 PR_UNJOINABLE_THREAD, 0);
1748 if (!thread) {
1749 SECU_PrintError(progName, "PR_CreateThread failed");
1750 error = 1;
1751 goto done;
1752 }
1753 }
1754#endif
1755
1756 if (serverCertAuth.testFreshStatusFromSideChannel) {
75
Assuming field 'testFreshStatusFromSideChannel' is 0
76
Taking false branch
1757 SSL_ForceHandshake(s);
1758 error = serverCertAuth.sideChannelRevocationTestResultCode;
1759 goto done;
1760 }
1761
1762 /*
1763 ** Select on stdin and on the socket. Write data from stdin to
1764 ** socket, read data from socket and write to stdout.
1765 */
1766 requestToExit = PR_FALSE0;
1767 FPRINTFif (verbose) fprintf(stderrstderr, "%s: ready...\n", progName);
77
Assuming 'verbose' is 0
1768 while (!requestToExit
77.1
'requestToExit' is 0
&&
85
Execution continues on line 1768
86
Assuming 'requestToExit' is 0
1769 (pollset[SSOCK_FD0].in_flags
77.2
Field 'in_flags' is 5
86.1
Field 'in_flags' is 5
|| pollset[STDIN_FD1].in_flags)) {
1770 PRUint8 buf[4000]; /* buffer for stdin */
1771 int nb; /* num bytes read from stdin. */
1772
1773 rv = restartHandshakeAfterServerCertIfNeeded(s, &serverCertAuth,
1774 override);
1775 if (rv
77.3
'rv' is equal to SECSuccess
86.2
'rv' is equal to SECSuccess
!= SECSuccess) {
78
Taking false branch
87
Taking false branch
1776 error = EXIT_CODE_HANDSHAKE_FAILED254;
1777 SECU_PrintError(progName, "authentication of server cert failed");
1778 goto done;
1779 }
1780
1781 rv = restartHandshakeAfterClientCertIfNeeded(s);
79
Calling 'restartHandshakeAfterClientCertIfNeeded'
83
Returning from 'restartHandshakeAfterClientCertIfNeeded'
88
Calling 'restartHandshakeAfterClientCertIfNeeded'
1782 if (rv
83.1
'rv' is equal to SECSuccess
== SECSuccess) {
84
Taking true branch
1783 continue;
1784 }
1785
1786 pollset[SSOCK_FD0].out_flags = 0;
1787 pollset[STDIN_FD1].out_flags = 0;
1788
1789 FPRINTFif (verbose) fprintf(stderrstderr, "%s: about to call PR_Poll !\n", progName);
1790 filesReady = PR_Poll(pollset, PR_ARRAY_SIZE(pollset)(sizeof(pollset)/sizeof((pollset)[0])),
1791 PR_INTERVAL_NO_TIMEOUT0xffffffffUL);
1792 if (filesReady < 0) {
1793 SECU_PrintError(progName, "select failed");
1794 error = 1;
1795 goto done;
1796 }
1797 if (filesReady == 0) { /* shouldn't happen! */
1798 FPRINTFif (verbose) fprintf(stderrstderr, "%s: PR_Poll returned zero!\n", progName);
1799 error = 1;
1800 goto done;
1801 }
1802 FPRINTFif (verbose) fprintf(stderrstderr, "%s: PR_Poll returned!\n", progName);
1803 if (pollset[STDIN_FD1].in_flags) {
1804 FPRINTFif (verbose) fprintf(stderrstderr,
1805 "%s: PR_Poll returned 0x%02x for stdin out_flags.\n",
1806 progName, pollset[STDIN_FD1].out_flags);
1807 }
1808 if (pollset[SSOCK_FD0].in_flags) {
1809 FPRINTFif (verbose) fprintf(stderrstderr,
1810 "%s: PR_Poll returned 0x%02x for socket out_flags.\n",
1811 progName, pollset[SSOCK_FD0].out_flags);
1812 }
1813 if (pollset[STDIN_FD1].out_flags & PR_POLL_READ0x1) {
1814 /* Read from stdin and write to socket */
1815 nb = PR_Read(pollset[STDIN_FD1].fd, buf, sizeof(buf));
1816 FPRINTFif (verbose) fprintf(stderrstderr, "%s: stdin read %d bytes\n", progName, nb);
1817 if (nb < 0) {
1818 if (PR_GetError() != PR_WOULD_BLOCK_ERROR(-5998L)) {
1819 SECU_PrintError(progName, "read from stdin failed");
1820 error = 1;
1821 break;
1822 }
1823 } else if (nb == 0) {
1824 /* EOF on stdin, stop polling stdin for read. */
1825 pollset[STDIN_FD1].in_flags = 0;
1826 if (actAsServer)
1827 requestToExit = PR_TRUE1;
1828 } else {
1829 error = writeBytesToServer(s, buf, nb);
1830 if (error) {
1831 if (echConfigs) {
1832 (void)printEchRetryConfigs(s);
1833 }
1834 goto done;
1835 }
1836 pollset[SSOCK_FD0].in_flags = PR_POLL_READ0x1;
1837 }
1838 }
1839
1840 if (pollset[SSOCK_FD0].in_flags) {
1841 FPRINTFif (verbose) fprintf(stderrstderr,
1842 "%s: PR_Poll returned 0x%02x for socket out_flags.\n",
1843 progName, pollset[SSOCK_FD0].out_flags);
1844 }
1845#ifdef PR_POLL_HUP0x20
1846#define POLL_RECV_FLAGS(0x1 | 0x8 | 0x20) (PR_POLL_READ0x1 | PR_POLL_ERR0x8 | PR_POLL_HUP0x20)
1847#else
1848#define POLL_RECV_FLAGS(0x1 | 0x8 | 0x20) (PR_POLL_READ0x1 | PR_POLL_ERR0x8)
1849#endif
1850 if (pollset[SSOCK_FD0].out_flags & POLL_RECV_FLAGS(0x1 | 0x8 | 0x20)) {
1851 /* Read from socket and write to stdout */
1852 nb = PR_Recv(pollset[SSOCK_FD0].fd, buf, sizeof buf, 0, maxInterval);
1853 FPRINTFif (verbose) fprintf(stderrstderr, "%s: Read from server %d bytes\n", progName, nb);
1854 if (nb < 0) {
1855 if (PR_GetError() != PR_WOULD_BLOCK_ERROR(-5998L)) {
1856 SECU_PrintError(progName, "read from socket failed");
1857 error = 1;
1858 goto done;
1859 }
1860 } else if (nb == 0) {
1861 /* EOF from socket... stop polling socket for read */
1862 pollset[SSOCK_FD0].in_flags = 0;
1863 } else {
1864 if (skipProtoHeader != PR_TRUE1 || wrStarted == PR_TRUE1) {
1865 PR_Write(std_out, buf, nb);
1866 } else {
1867 separateReqHeader(std_out, (char *)buf, nb, &wrStarted,
1868 &headerSeparatorPtrnId);
1869 }
1870 if (verbose)
1871 fputs("\n\n", stderrstderr);
1872 }
1873 }
1874 milliPause(50 * multiplier);
1875 }
1876
1877done:
1878 if (s) {
1879 PR_Close(s);
1880 }
1881 if (requestFile && pollset[STDIN_FD1].fd) {
1882 PR_Close(pollset[STDIN_FD1].fd);
1883 }
1884 return error;
1885}
1886
1887int
1888main(int argc, char **argv)
1889{
1890 PLOptState *optstate;
1891 PLOptStatus optstatus;
1892 PRStatus status;
1893 PRStatus prStatus;
1894 int error = 0;
1895 char *tmp;
1896 SECStatus rv;
1897 char *certDir = NULL((void*)0);
1898 PRBool openDB = PR_TRUE1;
1899 PRBool loadDefaultRootCAs = PR_FALSE0;
1900 char *rootModule = NULL((void*)0);
1901 int numConnections = 1;
1902 PRFileDesc *s = NULL((void*)0);
1903
1904 serverCertAuth.shouldPause = PR_TRUE1;
1905 serverCertAuth.isPaused = PR_FALSE0;
1906 serverCertAuth.dbHandle = NULL((void*)0);
1907 serverCertAuth.testFreshStatusFromSideChannel = PR_FALSE0;
1908 serverCertAuth.sideChannelRevocationTestResultCode = EXIT_CODE_HANDSHAKE_FAILED254;
1909 serverCertAuth.requireDataForIntermediates = PR_FALSE0;
1910 serverCertAuth.allowOCSPSideChannelData = PR_TRUE1;
1911 serverCertAuth.allowCRLSideChannelData = PR_TRUE1;
1912
1913 progName = strrchr(argv[0], '/');
1914 if (!progName)
1915 progName = strrchr(argv[0], '\\');
1916 progName = progName ? progName + 1 : argv[0];
1917
1918 tmp = PR_GetEnvSecure("NSS_DEBUG_TIMEOUT");
1919 if (tmp && tmp[0]) {
1920 int sec = PORT_Atoi(tmp)(int)strtol(tmp, ((void*)0), 10);
1921 if (sec > 0) {
1922 maxInterval = PR_SecondsToInterval(sec);
1923 }
1924 }
1925
1926 optstate = PL_CreateOptState(argc, argv,
1927 "46A:BCDEFGHI:J:KL:M:N:OP:QR:STUV:W:X:YZa:bc:d:efgh:i:m:n:op:qr:st:uvw:x:z:");
1928 while ((optstatus = PL_GetNextOpt(optstate)) == PL_OPT_OK) {
1929 switch (optstate->option) {
1930 case '?':
1931 default:
1932 Usage();
1933 break;
1934
1935 case '4':
1936 allowIPv6 = PR_FALSE0;
1937 if (!allowIPv4)
1938 Usage();
1939 break;
1940 case '6':
1941 allowIPv4 = PR_FALSE0;
1942 if (!allowIPv6)
1943 Usage();
1944 break;
1945
1946 case 'A':
1947 requestFile = PORT_StrdupPORT_Strdup_Util(optstate->value);
1948 break;
1949
1950 case 'B':
1951 enableDelegatedCredentials = PR_TRUE1;
1952 break;
1953
1954 case 'C':
1955 ++dumpServerChain;
1956 break;
1957
1958 case 'D':
1959 openDB = PR_FALSE0;
1960 break;
1961
1962 case 'E':
1963 enablePostHandshakeAuth = PR_TRUE1;
1964 break;
1965
1966 case 'F':
1967 if (serverCertAuth.testFreshStatusFromSideChannel) {
1968 /* parameter given twice or more */
1969 serverCertAuth.requireDataForIntermediates = PR_TRUE1;
1970 }
1971 serverCertAuth.testFreshStatusFromSideChannel = PR_TRUE1;
1972 break;
1973
1974 case 'G':
1975 enableExtendedMasterSecret = PR_TRUE1;
1976 break;
1977
1978 case 'H':
1979 requireDHNamedGroups = PR_TRUE1;
1980 break;
1981
1982 case 'O':
1983 clientCertAsyncSelect = PR_FALSE0;
1984 serverCertAuth.shouldPause = PR_FALSE0;
1985 break;
1986
1987 case 'K':
1988 forceFallbackSCSV = PR_TRUE1;
1989 break;
1990
1991 case 'L':
1992 numConnections = atoi(optstate->value);
1993 break;
1994
1995 case 'M':
1996 switch (atoi(optstate->value)) {
1997 case 1:
1998 serverCertAuth.allowOCSPSideChannelData = PR_TRUE1;
1999 serverCertAuth.allowCRLSideChannelData = PR_FALSE0;
2000 break;
2001 case 2:
2002 serverCertAuth.allowOCSPSideChannelData = PR_FALSE0;
2003 serverCertAuth.allowCRLSideChannelData = PR_TRUE1;
2004 break;
2005 case 0:
2006 default:
2007 serverCertAuth.allowOCSPSideChannelData = PR_TRUE1;
2008 serverCertAuth.allowCRLSideChannelData = PR_TRUE1;
2009 break;
2010 };
2011 break;
2012
2013 case 'N':
2014 echConfigs = PORT_StrdupPORT_Strdup_Util(optstate->value);
2015 break;
2016
2017 case 'i':
2018 echGreaseSize = PORT_Atoi(optstate->value)(int)strtol(optstate->value, ((void*)0), 10);
2019 if (!echGreaseSize || echGreaseSize > 255) {
2020 fprintf(stderrstderr, "ECH Grease size must be within 1..255 (inclusive).\n");
2021 exit(-1);
2022 }
2023 break;
2024
2025 case 'P':
2026 useDTLS = PR_TRUE1;
2027 if (!strcmp(optstate->value, "server")) {
2028 actAsServer = 1;
2029 } else {
2030 if (strcmp(optstate->value, "client")) {
2031 Usage();
2032 }
2033 }
2034 break;
2035
2036 case 'Q':
2037 stopAfterHandshake = PR_TRUE1;
2038 break;
2039
2040 case 'R':
2041 rootModule = PORT_StrdupPORT_Strdup_Util(optstate->value);
2042 break;
2043
2044 case 'S':
2045 skipProtoHeader = PR_TRUE1;
2046 break;
2047
2048 case 'T':
2049 enableCertStatus = 1;
2050 break;
2051
2052 case 'U':
2053 enableSignedCertTimestamps = 1;
2054 break;
2055
2056 case 'V':
2057 versionString = PORT_StrdupPORT_Strdup_Util(optstate->value);
2058 break;
2059
2060 case 'X':
2061 if (!strcmp(optstate->value, "alt-server-hello")) {
2062 enableAltServerHello = PR_TRUE1;
2063 } else {
2064 Usage();
2065 }
2066 break;
2067 case 'Y':
2068 PrintCipherUsage();
2069 exit(0);
2070 break;
2071
2072 case 'Z':
2073 enableZeroRtt = PR_TRUE1;
2074 zeroRttData = PORT_ZAllocPORT_ZAlloc_Util(ZERO_RTT_MAX(2 << 16));
2075 if (!zeroRttData) {
2076 fprintf(stderrstderr, "Unable to allocate buffer for 0-RTT\n");
2077 exit(1);
2078 }
2079 break;
2080
2081 case 'a':
2082 if (!hs1SniHostName) {
2083 hs1SniHostName = PORT_StrdupPORT_Strdup_Util(optstate->value);
2084 } else if (!hs2SniHostName) {
2085 hs2SniHostName = PORT_StrdupPORT_Strdup_Util(optstate->value);
2086 } else {
2087 Usage();
2088 }
2089 break;
2090
2091 case 'b':
2092 loadDefaultRootCAs = PR_TRUE1;
2093 break;
2094
2095 case 'c':
2096 cipherString = PORT_StrdupPORT_Strdup_Util(optstate->value);
2097 break;
2098
2099 case 'g':
2100 enableFalseStart = 1;
2101 break;
2102
2103 case 'd':
2104 certDir = PORT_StrdupPORT_Strdup_Util(optstate->value);
2105 break;
2106
2107 case 'e':
2108 middleboxCompatMode = PR_TRUE1;
2109 break;
2110
2111 case 'f':
2112 clientSpeaksFirst = PR_TRUE1;
2113 break;
2114
2115 case 'h':
2116 host = PORT_StrdupPORT_Strdup_Util(optstate->value);
2117 break;
2118
2119 case 'm':
2120 multiplier = atoi(optstate->value);
2121 if (multiplier < 0)
2122 multiplier = 0;
2123 break;
2124
2125 case 'n':
2126 nickname = PORT_StrdupPORT_Strdup_Util(optstate->value);
2127 break;
2128
2129 case 'o':
2130 override = 1;
2131 break;
2132
2133 case 'p':
2134 portno = (PRUint16)atoi(optstate->value);
2135 break;
2136
2137 case 'q':
2138 pingServerFirst = PR_TRUE1;
2139 break;
2140
2141 case 's':
2142 disableLocking = 1;
2143 break;
2144
2145 case 't':
2146 pingTimeoutSeconds = atoi(optstate->value);
2147 break;
2148
2149 case 'u':
2150 enableSessionTickets = PR_TRUE1;
2151 break;
2152
2153 case 'v':
2154 verbose++;
2155 break;
2156
2157 case 'r':
2158 renegotiationsToDo = atoi(optstate->value);
2159 break;
2160
2161 case 'w':
2162 pwdata.source = PW_PLAINTEXT;
2163 pwdata.data = PORT_StrdupPORT_Strdup_Util(optstate->value);
2164 break;
2165
2166 case 'W':
2167 pwdata.source = PW_FROMFILE;
2168 pwdata.data = PORT_StrdupPORT_Strdup_Util(optstate->value);
2169 break;
2170
2171 case 'I':
2172 rv = parseGroupList(optstate->value, &enabledGroups, &enabledGroupsCount);
2173 if (rv != SECSuccess) {
2174 PL_DestroyOptState(optstate);
2175 fprintf(stderrstderr, "Bad group specified.\n");
2176 Usage();
2177 }
2178 break;
2179
2180 case 'J':
2181 rv = parseSigSchemeList(optstate->value, &enabledSigSchemes, &enabledSigSchemeCount);
2182 if (rv != SECSuccess) {
2183 PL_DestroyOptState(optstate);
2184 fprintf(stderrstderr, "Bad signature scheme specified.\n");
2185 Usage();
2186 }
2187 break;
2188
2189 case 'x':
2190 rv = parseExporters(optstate->value,
2191 &enabledExporters,
2192 &enabledExporterCount);
2193 if (rv != SECSuccess) {
2194 PL_DestroyOptState(optstate);
2195 fprintf(stderrstderr, "Bad exporter specified.\n");
2196 Usage();
2197 }
2198 break;
2199
2200 case 'z':
2201 rv = readPSK(optstate->value, &psk, &pskLabel);
2202 if (rv != SECSuccess) {
2203 PL_DestroyOptState(optstate);
2204 fprintf(stderrstderr, "Bad PSK specified.\n");
2205 Usage();
2206 }
2207 break;
2208 }
2209 }
2210 PL_DestroyOptState(optstate);
2211
2212 SSL_VersionRangeGetSupported(useDTLS ? ssl_variant_datagram : ssl_variant_stream, &enabledVersions);
2213
2214 if (versionString) {
2215 if (SECU_ParseSSLVersionRangeString(versionString,
2216 enabledVersions, &enabledVersions) !=
2217 SECSuccess) {
2218 fprintf(stderrstderr, "Bad version specified.\n");
2219 Usage();
2220 }
2221 PORT_FreePORT_Free_Util(versionString);
2222 }
2223
2224 if (optstatus == PL_OPT_BAD) {
2225 Usage();
2226 }
2227
2228 if (!host || !portno) {
2229 fprintf(stderrstderr, "%s: parameters -h and -p are mandatory\n", progName);
2230 Usage();
2231 }
2232
2233 if (serverCertAuth.testFreshStatusFromSideChannel &&
2234 serverCertAuth.shouldPause) {
2235 fprintf(stderrstderr, "%s: -F requires the use of -O\n", progName);
2236 exit(1);
2237 }
2238
2239 if (certDir && !openDB) {
2240 fprintf(stderrstderr, "%s: Cannot combine parameters -D and -d\n", progName);
2241 exit(1);
2242 }
2243
2244 if (rootModule && loadDefaultRootCAs) {
2245 fprintf(stderrstderr, "%s: Cannot combine parameters -b and -R\n", progName);
2246 exit(1);
2247 }
2248
2249 if (enablePostHandshakeAuth && !nickname) {
2250 fprintf(stderrstderr, "%s: -E requires the use of -n\n", progName);
2251 exit(1);
2252 }
2253
2254 PR_Init(PR_SYSTEM_THREAD, PR_PRIORITY_NORMAL, 1);
2255
2256 PK11_SetPasswordFunc(SECU_GetModulePassword);
2257 memset(&addr, 0, sizeof(addr));
2258 status = PR_StringToNetAddr(host, &addr);
2259 if (status == PR_SUCCESS) {
2260 addr.inet.port = PR_htons(portno);
2261 } else {
2262 PRBool gotLoopbackIP = PR_FALSE0;
2263 if ((!strcmp(host, "localhost") || !strcmp(host, "localhost.localdomain"))
2264 /* only check for preference if both types are allowed */
2265 && allowIPv4 && allowIPv6) {
2266 /* make a decision which IP to prefer */
2267 status = PR_GetPrefLoopbackAddrInfo(&addr, portno);
2268 if (status != PR_FAILURE) {
2269 gotLoopbackIP = PR_TRUE1;
2270 }
2271 }
2272
2273 if (!gotLoopbackIP) {
2274 /* Lookup host */
2275 PRAddrInfo *addrInfo;
2276 void *enumPtr = NULL((void*)0);
2277
2278 addrInfo = PR_GetAddrInfoByName(host, PR_AF_UNSPEC0,
2279 PR_AI_ADDRCONFIG0x20 | PR_AI_NOCANONNAME0x8000);
2280 if (!addrInfo) {
2281 fprintf(stderrstderr, "HOSTNAME=%s\n", host);
2282 SECU_PrintError(progName, "error looking up host");
2283 error = 1;
2284 goto done;
2285 }
2286 for (;;) {
2287 enumPtr = PR_EnumerateAddrInfo(enumPtr, addrInfo, portno, &addr);
2288 if (enumPtr == NULL((void*)0))
2289 break;
2290 if (addr.raw.family == PR_AF_INET2 && allowIPv4)
2291 break;
2292 if (addr.raw.family == PR_AF_INET610 && allowIPv6)
2293 break;
2294 }
2295 PR_FreeAddrInfo(addrInfo);
2296 if (enumPtr == NULL((void*)0)) {
2297 SECU_PrintError(progName, "error looking up host address");
2298 error = 1;
2299 goto done;
2300 }
2301 }
2302 }
2303
2304 printHostNameAndAddr(host, &addr);
2305
2306 if (!certDir) {
2307 certDir = SECU_DefaultSSLDir(); /* Look in $SSL_DIR */
2308 certDir = SECU_ConfigDirectory(certDir);
2309 } else {
2310 char *certDirTmp = certDir;
2311 certDir = SECU_ConfigDirectory(certDirTmp);
2312 PORT_FreePORT_Free_Util(certDirTmp);
2313 }
2314
2315 if (pingServerFirst) {
2316 int iter = 0;
2317 PRErrorCode err;
2318
2319 int max_attempts = MAX_WAIT_FOR_SERVER600;
2320 if (pingTimeoutSeconds >= 0) {
2321 /* If caller requested a timeout, let's try just twice. */
2322 max_attempts = 2;
2323 }
2324 do {
2325 PRIntervalTime timeoutInterval = PR_INTERVAL_NO_TIMEOUT0xffffffffUL;
2326 s = PR_OpenTCPSocket(addr.raw.family);
2327 if (s == NULL((void*)0)) {
2328 SECU_PrintError(progName, "Failed to create a TCP socket");
2329 error = 1;
2330 goto done;
2331 }
2332 opt.option = PR_SockOpt_Nonblocking;
2333 opt.value.non_blocking = PR_FALSE0;
2334 prStatus = PR_SetSocketOption(s, &opt);
2335 if (prStatus != PR_SUCCESS) {
2336 SECU_PrintError(progName,
2337 "Failed to set blocking socket option");
2338 error = 1;
2339 goto done;
2340 }
2341 if (pingTimeoutSeconds >= 0) {
2342 timeoutInterval = PR_SecondsToInterval(pingTimeoutSeconds);
2343 }
2344 prStatus = PR_Connect(s, &addr, timeoutInterval);
2345 if (prStatus == PR_SUCCESS) {
2346 PR_Shutdown(s, PR_SHUTDOWN_BOTH);
2347 goto done;
2348 }
2349 err = PR_GetError();
2350 if ((err != PR_CONNECT_REFUSED_ERROR(-5981L)) &&
2351 (err != PR_CONNECT_RESET_ERROR(-5961L))) {
2352 SECU_PrintError(progName, "TCP Connection failed");
2353 error = 1;
2354 goto done;
2355 }
2356 PR_Close(s);
2357 s = NULL((void*)0);
2358 PR_Sleep(PR_MillisecondsToInterval(WAIT_INTERVAL100));
2359 } while (++iter < max_attempts);
2360 SECU_PrintError(progName,
2361 "Client timed out while waiting for connection to server");
2362 error = 1;
2363 goto done;
2364 }
2365
2366 /* open the cert DB, the key DB, and the secmod DB. */
2367 if (openDB) {
2368 rv = NSS_Init(certDir);
2369 if (rv != SECSuccess) {
2370 SECU_PrintError(progName, "unable to open cert database");
2371 error = 1;
2372 goto done;
2373 }
2374 } else {
2375 rv = NSS_NoDB_Init(NULL((void*)0));
2376 if (rv != SECSuccess) {
2377 SECU_PrintError(progName, "failed to initialize NSS");
2378 error = 1;
2379 goto done;
2380 }
2381 }
2382
2383 if (loadDefaultRootCAs) {
2384 SECMOD_AddNewModule("Builtins",
2385 DLL_PREFIX"lib" "nssckbi." DLL_SUFFIX"so", 0, 0);
2386 } else if (rootModule) {
2387 SECMOD_AddNewModule("Builtins", rootModule, 0, 0);
2388 }
2389
2390 /* all SSL3 cipher suites are enabled by default. */
2391 if (cipherString) {
2392 /* disable all the ciphers, then enable the ones we want. */
2393 disableAllSSLCiphers();
2394 }
2395
2396 while (numConnections--) {
2397 error = run();
2398 if (error) {
2399 goto done;
2400 }
2401 }
2402
2403done:
2404 if (s) {
2405 PR_Close(s);
2406 }
2407
2408 PORT_FreePORT_Free_Util((void *)requestFile);
2409 PORT_FreePORT_Free_Util(hs1SniHostName);
2410 PORT_FreePORT_Free_Util(hs2SniHostName);
2411 PORT_FreePORT_Free_Util(nickname);
2412 PORT_FreePORT_Free_Util(pwdata.data);
2413 PORT_FreePORT_Free_Util(host);
2414 PORT_FreePORT_Free_Util(zeroRttData);
2415 PORT_FreePORT_Free_Util(echConfigs);
2416 SECITEM_ZfreeItemSECITEM_ZfreeItem_Util(&psk, PR_FALSE0);
2417 SECITEM_ZfreeItemSECITEM_ZfreeItem_Util(&pskLabel, PR_FALSE0);
2418
2419 if (enabledGroups) {
2420 PORT_FreePORT_Free_Util(enabledGroups);
2421 }
2422 if (NSS_IsInitialized()) {
2423 SSL_ClearSessionCache();
2424 if (initializedServerSessionCache) {
2425 if (SSL_ShutdownServerSessionIDCache() != SECSuccess) {
2426 error = 1;
2427 }
2428 }
2429
2430 if (NSS_Shutdown() != SECSuccess) {
2431 error = 1;
2432 }
2433 }
2434
2435 FPRINTFif (verbose) fprintf(stderrstderr, "tstclnt: exiting with return code %d\n", error);
2436 PR_Cleanup();
2437 return error;
2438}