/security/nss/cmd/strsclnt/strsclnt.c

http://github.com/zpao/v8monkey · C · 1578 lines · 1223 code · 235 blank · 120 comment · 265 complexity · 5b8c8a3464c5ed0187e77c6ec3570211 MD5 · raw file

  1. /* ***** BEGIN LICENSE BLOCK *****
  2. * Version: MPL 1.1/GPL 2.0/LGPL 2.1
  3. *
  4. * The contents of this file are subject to the Mozilla Public License Version
  5. * 1.1 (the "License"); you may not use this file except in compliance with
  6. * the License. You may obtain a copy of the License at
  7. * http://www.mozilla.org/MPL/
  8. *
  9. * Software distributed under the License is distributed on an "AS IS" basis,
  10. * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
  11. * for the specific language governing rights and limitations under the
  12. * License.
  13. *
  14. * The Original Code is the Netscape security libraries.
  15. *
  16. * The Initial Developer of the Original Code is
  17. * Netscape Communications Corporation.
  18. * Portions created by the Initial Developer are Copyright (C) 1994-2000
  19. * the Initial Developer. All Rights Reserved.
  20. *
  21. * Contributor(s):
  22. *
  23. * Alternatively, the contents of this file may be used under the terms of
  24. * either the GNU General Public License Version 2 or later (the "GPL"), or
  25. * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
  26. * in which case the provisions of the GPL or the LGPL are applicable instead
  27. * of those above. If you wish to allow use of your version of this file only
  28. * under the terms of either the GPL or the LGPL, and not to allow others to
  29. * use your version of this file under the terms of the MPL, indicate your
  30. * decision by deleting the provisions above and replace them with the notice
  31. * and other provisions required by the GPL or the LGPL. If you do not delete
  32. * the provisions above, a recipient may use your version of this file under
  33. * the terms of any one of the MPL, the GPL or the LGPL.
  34. *
  35. * ***** END LICENSE BLOCK ***** */
  36. #include <stdio.h>
  37. #include <string.h>
  38. #include "secutil.h"
  39. #if defined(XP_UNIX)
  40. #include <unistd.h>
  41. #endif
  42. #include <stdlib.h>
  43. #if !defined(_WIN32_WCE)
  44. #include <errno.h>
  45. #include <fcntl.h>
  46. #endif
  47. #include <stdarg.h>
  48. #include "plgetopt.h"
  49. #include "nspr.h"
  50. #include "prio.h"
  51. #include "prnetdb.h"
  52. #include "prerror.h"
  53. #include "pk11func.h"
  54. #include "secitem.h"
  55. #include "sslproto.h"
  56. #include "nss.h"
  57. #include "ssl.h"
  58. #ifndef PORT_Sprintf
  59. #define PORT_Sprintf sprintf
  60. #endif
  61. #ifndef PORT_Strstr
  62. #define PORT_Strstr strstr
  63. #endif
  64. #ifndef PORT_Malloc
  65. #define PORT_Malloc PR_Malloc
  66. #endif
  67. #define RD_BUF_SIZE (60 * 1024)
  68. /* Include these cipher suite arrays to re-use tstclnt's
  69. * cipher selection code.
  70. */
  71. int ssl2CipherSuites[] = {
  72. SSL_EN_RC4_128_WITH_MD5, /* A */
  73. SSL_EN_RC4_128_EXPORT40_WITH_MD5, /* B */
  74. SSL_EN_RC2_128_CBC_WITH_MD5, /* C */
  75. SSL_EN_RC2_128_CBC_EXPORT40_WITH_MD5, /* D */
  76. SSL_EN_DES_64_CBC_WITH_MD5, /* E */
  77. SSL_EN_DES_192_EDE3_CBC_WITH_MD5, /* F */
  78. 0
  79. };
  80. int ssl3CipherSuites[] = {
  81. -1, /* SSL_FORTEZZA_DMS_WITH_FORTEZZA_CBC_SHA* a */
  82. -1, /* SSL_FORTEZZA_DMS_WITH_RC4_128_SHA * b */
  83. SSL_RSA_WITH_RC4_128_MD5, /* c */
  84. SSL_RSA_WITH_3DES_EDE_CBC_SHA, /* d */
  85. SSL_RSA_WITH_DES_CBC_SHA, /* e */
  86. SSL_RSA_EXPORT_WITH_RC4_40_MD5, /* f */
  87. SSL_RSA_EXPORT_WITH_RC2_CBC_40_MD5, /* g */
  88. -1, /* SSL_FORTEZZA_DMS_WITH_NULL_SHA * h */
  89. SSL_RSA_WITH_NULL_MD5, /* i */
  90. SSL_RSA_FIPS_WITH_3DES_EDE_CBC_SHA, /* j */
  91. SSL_RSA_FIPS_WITH_DES_CBC_SHA, /* k */
  92. TLS_RSA_EXPORT1024_WITH_DES_CBC_SHA, /* l */
  93. TLS_RSA_EXPORT1024_WITH_RC4_56_SHA, /* m */
  94. SSL_RSA_WITH_RC4_128_SHA, /* n */
  95. TLS_DHE_DSS_WITH_RC4_128_SHA, /* o */
  96. SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA, /* p */
  97. SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA, /* q */
  98. SSL_DHE_RSA_WITH_DES_CBC_SHA, /* r */
  99. SSL_DHE_DSS_WITH_DES_CBC_SHA, /* s */
  100. TLS_DHE_DSS_WITH_AES_128_CBC_SHA, /* t */
  101. TLS_DHE_RSA_WITH_AES_128_CBC_SHA, /* u */
  102. TLS_RSA_WITH_AES_128_CBC_SHA, /* v */
  103. TLS_DHE_DSS_WITH_AES_256_CBC_SHA, /* w */
  104. TLS_DHE_RSA_WITH_AES_256_CBC_SHA, /* x */
  105. TLS_RSA_WITH_AES_256_CBC_SHA, /* y */
  106. SSL_RSA_WITH_NULL_SHA, /* z */
  107. 0
  108. };
  109. #define NO_FULLHS_PERCENTAGE -1
  110. /* This global string is so that client main can see
  111. * which ciphers to use.
  112. */
  113. static const char *cipherString;
  114. static PRInt32 certsTested;
  115. static int MakeCertOK;
  116. static int NoReuse;
  117. static int fullhs = NO_FULLHS_PERCENTAGE; /* percentage of full handshakes to
  118. ** perform */
  119. static PRInt32 globalconid = 0; /* atomically set */
  120. static int total_connections; /* total number of connections to perform */
  121. static int total_connections_rounded_down_to_hundreds;
  122. static int total_connections_modulo_100;
  123. static PRBool NoDelay;
  124. static PRBool QuitOnTimeout = PR_FALSE;
  125. static PRBool ThrottleUp = PR_FALSE;
  126. static PRLock * threadLock; /* protects the global variables below */
  127. static PRTime lastConnectFailure;
  128. static PRTime lastConnectSuccess;
  129. static PRTime lastThrottleUp;
  130. static PRInt32 remaining_connections; /* number of connections left */
  131. static int active_threads = 8; /* number of threads currently trying to
  132. ** connect */
  133. static PRInt32 numUsed;
  134. /* end of variables protected by threadLock */
  135. static SSL3Statistics * ssl3stats;
  136. static int failed_already = 0;
  137. static PRBool disableSSL2 = PR_FALSE;
  138. static PRBool disableSSL3 = PR_FALSE;
  139. static PRBool disableTLS = PR_FALSE;
  140. static PRBool bypassPKCS11 = PR_FALSE;
  141. static PRBool disableLocking = PR_FALSE;
  142. static PRBool ignoreErrors = PR_FALSE;
  143. static PRBool enableSessionTickets = PR_FALSE;
  144. static PRBool enableCompression = PR_FALSE;
  145. static PRBool enableFalseStart = PR_FALSE;
  146. PRIntervalTime maxInterval = PR_INTERVAL_NO_TIMEOUT;
  147. char * progName;
  148. int stopping;
  149. int verbose;
  150. SECItem bigBuf;
  151. #define PRINTF if (verbose) printf
  152. #define FPRINTF if (verbose) fprintf
  153. static void
  154. Usage(const char *progName)
  155. {
  156. fprintf(stderr,
  157. "Usage: %s [-n nickname] [-p port] [-d dbdir] [-c connections]\n"
  158. " [-23BDNTovqs] [-f filename] [-N | -P percentage]\n"
  159. " [-w dbpasswd] [-C cipher(s)] [-t threads] [-W pwfile]\n"
  160. " [-a sniHostName] hostname\n"
  161. " where -v means verbose\n"
  162. " -o flag is interpreted as follows:\n"
  163. " 1 -o means override the result of server certificate validation.\n"
  164. " 2 -o's mean skip server certificate validation altogether.\n"
  165. " -D means no TCP delays\n"
  166. " -q means quit when server gone (timeout rather than retry forever)\n"
  167. " -s means disable SSL socket locking\n"
  168. " -N means no session reuse\n"
  169. " -P means do a specified percentage of full handshakes (0-100)\n"
  170. " -2 means disable SSL2\n"
  171. " -3 means disable SSL3\n"
  172. " -T means disable TLS\n"
  173. " -U means enable throttling up threads\n"
  174. " -B bypasses the PKCS11 layer for SSL encryption and MACing\n"
  175. " -u enable TLS Session Ticket extension\n"
  176. " -z enable compression\n"
  177. " -g enable false start\n",
  178. progName);
  179. exit(1);
  180. }
  181. static void
  182. errWarn(char * funcString)
  183. {
  184. PRErrorCode perr = PR_GetError();
  185. const char * errString = SECU_Strerror(perr);
  186. fprintf(stderr, "strsclnt: %s returned error %d:\n%s\n",
  187. funcString, perr, errString);
  188. }
  189. static void
  190. errExit(char * funcString)
  191. {
  192. errWarn(funcString);
  193. exit(1);
  194. }
  195. /**************************************************************************
  196. **
  197. ** Routines for disabling SSL ciphers.
  198. **
  199. **************************************************************************/
  200. void
  201. disableAllSSLCiphers(void)
  202. {
  203. const PRUint16 *cipherSuites = SSL_GetImplementedCiphers();
  204. int i = SSL_GetNumImplementedCiphers();
  205. SECStatus rv;
  206. /* disable all the SSL3 cipher suites */
  207. while (--i >= 0) {
  208. PRUint16 suite = cipherSuites[i];
  209. rv = SSL_CipherPrefSetDefault(suite, PR_FALSE);
  210. if (rv != SECSuccess) {
  211. printf("SSL_CipherPrefSetDefault didn't like value 0x%04x (i = %d)\n",
  212. suite, i);
  213. errWarn("SSL_CipherPrefSetDefault");
  214. exit(2);
  215. }
  216. }
  217. }
  218. /* This invokes the "default" AuthCert handler in libssl.
  219. ** The only reason to use this one is that it prints out info as it goes.
  220. */
  221. static SECStatus
  222. mySSLAuthCertificate(void *arg, PRFileDesc *fd, PRBool checkSig,
  223. PRBool isServer)
  224. {
  225. SECStatus rv;
  226. CERTCertificate * peerCert;
  227. if (MakeCertOK>=2) {
  228. return SECSuccess;
  229. }
  230. peerCert = SSL_PeerCertificate(fd);
  231. PRINTF("strsclnt: Subject: %s\nstrsclnt: Issuer : %s\n",
  232. peerCert->subjectName, peerCert->issuerName);
  233. /* invoke the "default" AuthCert handler. */
  234. rv = SSL_AuthCertificate(arg, fd, checkSig, isServer);
  235. PR_ATOMIC_INCREMENT(&certsTested);
  236. if (rv == SECSuccess) {
  237. fputs("strsclnt: -- SSL: Server Certificate Validated.\n", stderr);
  238. }
  239. CERT_DestroyCertificate(peerCert);
  240. /* error, if any, will be displayed by the Bad Cert Handler. */
  241. return rv;
  242. }
  243. static SECStatus
  244. myBadCertHandler( void *arg, PRFileDesc *fd)
  245. {
  246. PRErrorCode err = PR_GetError();
  247. if (!MakeCertOK)
  248. fprintf(stderr,
  249. "strsclnt: -- SSL: Server Certificate Invalid, err %d.\n%s\n",
  250. err, SECU_Strerror(err));
  251. return (MakeCertOK ? SECSuccess : SECFailure);
  252. }
  253. void
  254. printSecurityInfo(PRFileDesc *fd)
  255. {
  256. CERTCertificate * cert = NULL;
  257. SSL3Statistics * ssl3stats = SSL_GetStatistics();
  258. SECStatus result;
  259. SSLChannelInfo channel;
  260. SSLCipherSuiteInfo suite;
  261. static int only_once;
  262. if (only_once && verbose < 2)
  263. return;
  264. only_once = 1;
  265. result = SSL_GetChannelInfo(fd, &channel, sizeof channel);
  266. if (result == SECSuccess &&
  267. channel.length == sizeof channel &&
  268. channel.cipherSuite) {
  269. result = SSL_GetCipherSuiteInfo(channel.cipherSuite,
  270. &suite, sizeof suite);
  271. if (result == SECSuccess) {
  272. FPRINTF(stderr,
  273. "strsclnt: SSL version %d.%d using %d-bit %s with %d-bit %s MAC\n",
  274. channel.protocolVersion >> 8, channel.protocolVersion & 0xff,
  275. suite.effectiveKeyBits, suite.symCipherName,
  276. suite.macBits, suite.macAlgorithmName);
  277. FPRINTF(stderr,
  278. "strsclnt: Server Auth: %d-bit %s, Key Exchange: %d-bit %s\n"
  279. " Compression: %s\n",
  280. channel.authKeyBits, suite.authAlgorithmName,
  281. channel.keaKeyBits, suite.keaTypeName,
  282. channel.compressionMethodName);
  283. }
  284. }
  285. cert = SSL_LocalCertificate(fd);
  286. if (!cert)
  287. cert = SSL_PeerCertificate(fd);
  288. if (verbose && cert) {
  289. char * ip = CERT_NameToAscii(&cert->issuer);
  290. char * sp = CERT_NameToAscii(&cert->subject);
  291. if (sp) {
  292. fprintf(stderr, "strsclnt: subject DN: %s\n", sp);
  293. PORT_Free(sp);
  294. }
  295. if (ip) {
  296. fprintf(stderr, "strsclnt: issuer DN: %s\n", ip);
  297. PORT_Free(ip);
  298. }
  299. }
  300. if (cert) {
  301. CERT_DestroyCertificate(cert);
  302. cert = NULL;
  303. }
  304. fprintf(stderr,
  305. "strsclnt: %ld cache hits; %ld cache misses, %ld cache not reusable\n"
  306. " %ld stateless resumes\n",
  307. ssl3stats->hsh_sid_cache_hits,
  308. ssl3stats->hsh_sid_cache_misses,
  309. ssl3stats->hsh_sid_cache_not_ok,
  310. ssl3stats->hsh_sid_stateless_resumes);
  311. }
  312. /**************************************************************************
  313. ** Begin thread management routines and data.
  314. **************************************************************************/
  315. #define MAX_THREADS 128
  316. typedef int startFn(void *a, void *b, int c);
  317. static PRInt32 numConnected;
  318. static int max_threads; /* peak threads allowed */
  319. typedef struct perThreadStr {
  320. void * a;
  321. void * b;
  322. int tid;
  323. int rv;
  324. startFn * startFunc;
  325. PRThread * prThread;
  326. PRBool inUse;
  327. } perThread;
  328. perThread threads[MAX_THREADS];
  329. void
  330. thread_wrapper(void * arg)
  331. {
  332. perThread * slot = (perThread *)arg;
  333. PRBool done = PR_FALSE;
  334. do {
  335. PRBool doop = PR_FALSE;
  336. PRBool dosleep = PR_FALSE;
  337. PRTime now = PR_Now();
  338. PR_Lock(threadLock);
  339. if (! (slot->tid < active_threads)) {
  340. /* this thread isn't supposed to be running */
  341. if (!ThrottleUp) {
  342. /* we'll never need this thread again, so abort it */
  343. done = PR_TRUE;
  344. } else if (remaining_connections > 0) {
  345. /* we may still need this thread, so just sleep for 1s */
  346. dosleep = PR_TRUE;
  347. /* the conditions to trigger a throttle up are :
  348. ** 1. last PR_Connect failure must have happened more than
  349. ** 10s ago
  350. ** 2. last throttling up must have happened more than 0.5s ago
  351. ** 3. there must be a more recent PR_Connect success than
  352. ** failure
  353. */
  354. if ( (now - lastConnectFailure > 10 * PR_USEC_PER_SEC) &&
  355. ( (!lastThrottleUp) || ( (now - lastThrottleUp) >=
  356. (PR_USEC_PER_SEC/2)) ) &&
  357. (lastConnectSuccess > lastConnectFailure) ) {
  358. /* try throttling up by one thread */
  359. active_threads = PR_MIN(max_threads, active_threads+1);
  360. fprintf(stderr,"active_threads set up to %d\n",
  361. active_threads);
  362. lastThrottleUp = PR_MAX(now, lastThrottleUp);
  363. }
  364. } else {
  365. /* no more connections left, we are done */
  366. done = PR_TRUE;
  367. }
  368. } else {
  369. /* this thread should run */
  370. if (--remaining_connections >= 0) { /* protected by threadLock */
  371. doop = PR_TRUE;
  372. } else {
  373. done = PR_TRUE;
  374. }
  375. }
  376. PR_Unlock(threadLock);
  377. if (doop) {
  378. slot->rv = (* slot->startFunc)(slot->a, slot->b, slot->tid);
  379. PRINTF("strsclnt: Thread in slot %d returned %d\n",
  380. slot->tid, slot->rv);
  381. }
  382. if (dosleep) {
  383. PR_Sleep(PR_SecondsToInterval(1));
  384. }
  385. } while (!done && (!failed_already || ignoreErrors));
  386. }
  387. SECStatus
  388. launch_thread(
  389. startFn * startFunc,
  390. void * a,
  391. void * b,
  392. int tid)
  393. {
  394. PRUint32 i;
  395. perThread * slot;
  396. PR_Lock(threadLock);
  397. PORT_Assert(numUsed < MAX_THREADS);
  398. if (! (numUsed < MAX_THREADS)) {
  399. PR_Unlock(threadLock);
  400. return SECFailure;
  401. }
  402. i = numUsed++;
  403. slot = &threads[i];
  404. slot->a = a;
  405. slot->b = b;
  406. slot->tid = tid;
  407. slot->startFunc = startFunc;
  408. slot->prThread = PR_CreateThread(PR_USER_THREAD,
  409. thread_wrapper, slot,
  410. PR_PRIORITY_NORMAL, PR_GLOBAL_THREAD,
  411. PR_JOINABLE_THREAD, 0);
  412. if (slot->prThread == NULL) {
  413. PR_Unlock(threadLock);
  414. printf("strsclnt: Failed to launch thread!\n");
  415. return SECFailure;
  416. }
  417. slot->inUse = 1;
  418. PR_Unlock(threadLock);
  419. PRINTF("strsclnt: Launched thread in slot %d \n", i);
  420. return SECSuccess;
  421. }
  422. /* join all the threads */
  423. int
  424. reap_threads(void)
  425. {
  426. int i;
  427. for (i = 0; i < MAX_THREADS; ++i) {
  428. if (threads[i].prThread) {
  429. PR_JoinThread(threads[i].prThread);
  430. threads[i].prThread = NULL;
  431. }
  432. }
  433. return 0;
  434. }
  435. void
  436. destroy_thread_data(void)
  437. {
  438. PORT_Memset(threads, 0, sizeof threads);
  439. if (threadLock) {
  440. PR_DestroyLock(threadLock);
  441. threadLock = NULL;
  442. }
  443. }
  444. void
  445. init_thread_data(void)
  446. {
  447. threadLock = PR_NewLock();
  448. }
  449. /**************************************************************************
  450. ** End thread management routines.
  451. **************************************************************************/
  452. PRBool useModelSocket = PR_TRUE;
  453. static const char stopCmd[] = { "GET /stop " };
  454. static const char outHeader[] = {
  455. "HTTP/1.0 200 OK\r\n"
  456. "Server: Netscape-Enterprise/2.0a\r\n"
  457. "Date: Tue, 26 Aug 1997 22:10:05 GMT\r\n"
  458. "Content-type: text/plain\r\n"
  459. "\r\n"
  460. };
  461. struct lockedVarsStr {
  462. PRLock * lock;
  463. int count;
  464. int waiters;
  465. PRCondVar * condVar;
  466. };
  467. typedef struct lockedVarsStr lockedVars;
  468. void
  469. lockedVars_Init( lockedVars * lv)
  470. {
  471. lv->count = 0;
  472. lv->waiters = 0;
  473. lv->lock = PR_NewLock();
  474. lv->condVar = PR_NewCondVar(lv->lock);
  475. }
  476. void
  477. lockedVars_Destroy( lockedVars * lv)
  478. {
  479. PR_DestroyCondVar(lv->condVar);
  480. lv->condVar = NULL;
  481. PR_DestroyLock(lv->lock);
  482. lv->lock = NULL;
  483. }
  484. void
  485. lockedVars_WaitForDone(lockedVars * lv)
  486. {
  487. PR_Lock(lv->lock);
  488. while (lv->count > 0) {
  489. PR_WaitCondVar(lv->condVar, PR_INTERVAL_NO_TIMEOUT);
  490. }
  491. PR_Unlock(lv->lock);
  492. }
  493. int /* returns count */
  494. lockedVars_AddToCount(lockedVars * lv, int addend)
  495. {
  496. int rv;
  497. PR_Lock(lv->lock);
  498. rv = lv->count += addend;
  499. if (rv <= 0) {
  500. PR_NotifyCondVar(lv->condVar);
  501. }
  502. PR_Unlock(lv->lock);
  503. return rv;
  504. }
  505. int
  506. do_writes(
  507. void * a,
  508. void * b,
  509. int c)
  510. {
  511. PRFileDesc * ssl_sock = (PRFileDesc *)a;
  512. lockedVars * lv = (lockedVars *)b;
  513. int sent = 0;
  514. int count = 0;
  515. while (sent < bigBuf.len) {
  516. count = PR_Send(ssl_sock, bigBuf.data + sent, bigBuf.len - sent,
  517. 0, maxInterval);
  518. if (count < 0) {
  519. errWarn("PR_Send bigBuf");
  520. break;
  521. }
  522. FPRINTF(stderr, "strsclnt: PR_Send wrote %d bytes from bigBuf\n",
  523. count );
  524. sent += count;
  525. }
  526. if (count >= 0) { /* last write didn't fail. */
  527. PR_Shutdown(ssl_sock, PR_SHUTDOWN_SEND);
  528. }
  529. /* notify the reader that we're done. */
  530. lockedVars_AddToCount(lv, -1);
  531. return (sent < bigBuf.len) ? SECFailure : SECSuccess;
  532. }
  533. int
  534. handle_fdx_connection( PRFileDesc * ssl_sock, int connection)
  535. {
  536. SECStatus result;
  537. int firstTime = 1;
  538. int countRead = 0;
  539. lockedVars lv;
  540. char *buf;
  541. lockedVars_Init(&lv);
  542. lockedVars_AddToCount(&lv, 1);
  543. /* Attempt to launch the writer thread. */
  544. result = launch_thread(do_writes, ssl_sock, &lv, connection);
  545. if (result != SECSuccess)
  546. goto cleanup;
  547. buf = PR_Malloc(RD_BUF_SIZE);
  548. if (buf) {
  549. do {
  550. /* do reads here. */
  551. PRInt32 count;
  552. count = PR_Recv(ssl_sock, buf, RD_BUF_SIZE, 0, maxInterval);
  553. if (count < 0) {
  554. errWarn("PR_Recv");
  555. break;
  556. }
  557. countRead += count;
  558. FPRINTF(stderr,
  559. "strsclnt: connection %d read %d bytes (%d total).\n",
  560. connection, count, countRead );
  561. if (firstTime) {
  562. firstTime = 0;
  563. printSecurityInfo(ssl_sock);
  564. }
  565. } while (lockedVars_AddToCount(&lv, 0) > 0);
  566. PR_Free(buf);
  567. buf = 0;
  568. }
  569. /* Wait for writer to finish */
  570. lockedVars_WaitForDone(&lv);
  571. lockedVars_Destroy(&lv);
  572. FPRINTF(stderr,
  573. "strsclnt: connection %d read %d bytes total. -----------------------\n",
  574. connection, countRead);
  575. cleanup:
  576. /* Caller closes the socket. */
  577. return SECSuccess;
  578. }
  579. const char request[] = {"GET /abc HTTP/1.0\r\n\r\n" };
  580. SECStatus
  581. handle_connection( PRFileDesc *ssl_sock, int tid)
  582. {
  583. int countRead = 0;
  584. PRInt32 rv;
  585. char *buf;
  586. buf = PR_Malloc(RD_BUF_SIZE);
  587. if (!buf)
  588. return SECFailure;
  589. /* compose the http request here. */
  590. rv = PR_Send(ssl_sock, request, strlen(request), 0, maxInterval);
  591. if (rv <= 0) {
  592. errWarn("PR_Send");
  593. PR_Free(buf);
  594. buf = 0;
  595. failed_already = 1;
  596. return SECFailure;
  597. }
  598. printSecurityInfo(ssl_sock);
  599. /* read until EOF */
  600. while (1) {
  601. rv = PR_Recv(ssl_sock, buf, RD_BUF_SIZE, 0, maxInterval);
  602. if (rv == 0) {
  603. break; /* EOF */
  604. }
  605. if (rv < 0) {
  606. errWarn("PR_Recv");
  607. failed_already = 1;
  608. break;
  609. }
  610. countRead += rv;
  611. FPRINTF(stderr,
  612. "strsclnt: connection on thread %d read %d bytes (%d total).\n",
  613. tid, rv, countRead );
  614. }
  615. PR_Free(buf);
  616. buf = 0;
  617. /* Caller closes the socket. */
  618. FPRINTF(stderr,
  619. "strsclnt: connection on thread %d read %d bytes total. ---------\n",
  620. tid, countRead);
  621. return SECSuccess; /* success */
  622. }
  623. #define USE_SOCK_PEER_ID 1
  624. #ifdef USE_SOCK_PEER_ID
  625. PRInt32 lastFullHandshakePeerID;
  626. void
  627. myHandshakeCallback(PRFileDesc *socket, void *arg)
  628. {
  629. PR_ATOMIC_SET(&lastFullHandshakePeerID, (PRInt32) arg);
  630. }
  631. #endif
  632. /* one copy of this function is launched in a separate thread for each
  633. ** connection to be made.
  634. */
  635. int
  636. do_connects(
  637. void * a,
  638. void * b,
  639. int tid)
  640. {
  641. PRNetAddr * addr = (PRNetAddr *) a;
  642. PRFileDesc * model_sock = (PRFileDesc *) b;
  643. PRFileDesc * ssl_sock = 0;
  644. PRFileDesc * tcp_sock = 0;
  645. PRStatus prStatus;
  646. PRUint32 sleepInterval = 50; /* milliseconds */
  647. SECStatus result;
  648. int rv = SECSuccess;
  649. PRSocketOptionData opt;
  650. retry:
  651. tcp_sock = PR_OpenTCPSocket(addr->raw.family);
  652. if (tcp_sock == NULL) {
  653. errExit("PR_OpenTCPSocket");
  654. }
  655. opt.option = PR_SockOpt_Nonblocking;
  656. opt.value.non_blocking = PR_FALSE;
  657. prStatus = PR_SetSocketOption(tcp_sock, &opt);
  658. if (prStatus != PR_SUCCESS) {
  659. errWarn("PR_SetSocketOption(PR_SockOpt_Nonblocking, PR_FALSE)");
  660. PR_Close(tcp_sock);
  661. return SECSuccess;
  662. }
  663. if (NoDelay) {
  664. opt.option = PR_SockOpt_NoDelay;
  665. opt.value.no_delay = PR_TRUE;
  666. prStatus = PR_SetSocketOption(tcp_sock, &opt);
  667. if (prStatus != PR_SUCCESS) {
  668. errWarn("PR_SetSocketOption(PR_SockOpt_NoDelay, PR_TRUE)");
  669. PR_Close(tcp_sock);
  670. return SECSuccess;
  671. }
  672. }
  673. prStatus = PR_Connect(tcp_sock, addr, PR_INTERVAL_NO_TIMEOUT);
  674. if (prStatus != PR_SUCCESS) {
  675. PRErrorCode err = PR_GetError(); /* save error code */
  676. if (ThrottleUp) {
  677. PRTime now = PR_Now();
  678. PR_Lock(threadLock);
  679. lastConnectFailure = PR_MAX(now, lastConnectFailure);
  680. PR_Unlock(threadLock);
  681. }
  682. if ((err == PR_CONNECT_REFUSED_ERROR) ||
  683. (err == PR_CONNECT_RESET_ERROR) ) {
  684. int connections = numConnected;
  685. PR_Close(tcp_sock);
  686. PR_Lock(threadLock);
  687. if (connections > 2 && active_threads >= connections) {
  688. active_threads = connections - 1;
  689. fprintf(stderr,"active_threads set down to %d\n",
  690. active_threads);
  691. }
  692. PR_Unlock(threadLock);
  693. if (QuitOnTimeout && sleepInterval > 40000) {
  694. fprintf(stderr,
  695. "strsclnt: Client timed out waiting for connection to server.\n");
  696. exit(1);
  697. }
  698. PR_Sleep(PR_MillisecondsToInterval(sleepInterval));
  699. sleepInterval <<= 1;
  700. goto retry;
  701. }
  702. errWarn("PR_Connect");
  703. rv = SECFailure;
  704. goto done;
  705. } else {
  706. if (ThrottleUp) {
  707. PRTime now = PR_Now();
  708. PR_Lock(threadLock);
  709. lastConnectSuccess = PR_MAX(now, lastConnectSuccess);
  710. PR_Unlock(threadLock);
  711. }
  712. }
  713. ssl_sock = SSL_ImportFD(model_sock, tcp_sock);
  714. /* XXX if this import fails, close tcp_sock and return. */
  715. if (!ssl_sock) {
  716. PR_Close(tcp_sock);
  717. return SECSuccess;
  718. }
  719. if (fullhs != NO_FULLHS_PERCENTAGE) {
  720. #ifdef USE_SOCK_PEER_ID
  721. char sockPeerIDString[512];
  722. static PRInt32 sockPeerID = 0; /* atomically incremented */
  723. PRInt32 thisPeerID;
  724. #endif
  725. PRInt32 savid = PR_ATOMIC_INCREMENT(&globalconid);
  726. PRInt32 conid = 1 + (savid - 1) % 100;
  727. /* don't change peer ID on the very first handshake, which is always
  728. a full, so the session gets stored into the client cache */
  729. if ( (savid != 1) &&
  730. ( ( (savid <= total_connections_rounded_down_to_hundreds) &&
  731. (conid <= fullhs) ) ||
  732. (conid*100 <= total_connections_modulo_100*fullhs ) ) )
  733. #ifdef USE_SOCK_PEER_ID
  734. {
  735. /* force a full handshake by changing the socket peer ID */
  736. thisPeerID = PR_ATOMIC_INCREMENT(&sockPeerID);
  737. } else {
  738. /* reuse previous sockPeerID for restart handhsake */
  739. thisPeerID = lastFullHandshakePeerID;
  740. }
  741. PR_snprintf(sockPeerIDString, sizeof(sockPeerIDString), "ID%d",
  742. thisPeerID);
  743. SSL_SetSockPeerID(ssl_sock, sockPeerIDString);
  744. SSL_HandshakeCallback(ssl_sock, myHandshakeCallback, (void*)thisPeerID);
  745. #else
  746. /* force a full handshake by setting the no cache option */
  747. SSL_OptionSet(ssl_sock, SSL_NO_CACHE, 1);
  748. #endif
  749. }
  750. rv = SSL_ResetHandshake(ssl_sock, /* asServer */ 0);
  751. if (rv != SECSuccess) {
  752. errWarn("SSL_ResetHandshake");
  753. goto done;
  754. }
  755. PR_ATOMIC_INCREMENT(&numConnected);
  756. if (bigBuf.data != NULL) {
  757. result = handle_fdx_connection( ssl_sock, tid);
  758. } else {
  759. result = handle_connection( ssl_sock, tid);
  760. }
  761. PR_ATOMIC_DECREMENT(&numConnected);
  762. done:
  763. if (ssl_sock) {
  764. PR_Close(ssl_sock);
  765. } else if (tcp_sock) {
  766. PR_Close(tcp_sock);
  767. }
  768. return SECSuccess;
  769. }
  770. typedef struct {
  771. PRLock* lock;
  772. char* nickname;
  773. CERTCertificate* cert;
  774. SECKEYPrivateKey* key;
  775. void* wincx;
  776. } cert_and_key;
  777. PRBool FindCertAndKey(cert_and_key* Cert_And_Key)
  778. {
  779. if ( (NULL == Cert_And_Key->nickname) || (0 == strcmp(Cert_And_Key->nickname,"none"))) {
  780. return PR_TRUE;
  781. }
  782. Cert_And_Key->cert = CERT_FindUserCertByUsage(CERT_GetDefaultCertDB(),
  783. Cert_And_Key->nickname, certUsageSSLClient,
  784. PR_FALSE, Cert_And_Key->wincx);
  785. if (Cert_And_Key->cert) {
  786. Cert_And_Key->key = PK11_FindKeyByAnyCert(Cert_And_Key->cert, Cert_And_Key->wincx);
  787. }
  788. if (Cert_And_Key->cert && Cert_And_Key->key) {
  789. return PR_TRUE;
  790. } else {
  791. return PR_FALSE;
  792. }
  793. }
  794. PRBool LoggedIn(CERTCertificate* cert, SECKEYPrivateKey* key)
  795. {
  796. if ( (cert->slot) && (key->pkcs11Slot) &&
  797. (PR_TRUE == PK11_IsLoggedIn(cert->slot, NULL)) &&
  798. (PR_TRUE == PK11_IsLoggedIn(key->pkcs11Slot, NULL)) ) {
  799. return PR_TRUE;
  800. }
  801. return PR_FALSE;
  802. }
  803. SECStatus
  804. StressClient_GetClientAuthData(void * arg,
  805. PRFileDesc * socket,
  806. struct CERTDistNamesStr * caNames,
  807. struct CERTCertificateStr ** pRetCert,
  808. struct SECKEYPrivateKeyStr **pRetKey)
  809. {
  810. cert_and_key* Cert_And_Key = (cert_and_key*) arg;
  811. if (!pRetCert || !pRetKey) {
  812. /* bad pointers, can't return a cert or key */
  813. return SECFailure;
  814. }
  815. *pRetCert = NULL;
  816. *pRetKey = NULL;
  817. if (Cert_And_Key && Cert_And_Key->nickname) {
  818. while (PR_TRUE) {
  819. if (Cert_And_Key && Cert_And_Key->lock) {
  820. int timeout = 0;
  821. PR_Lock(Cert_And_Key->lock);
  822. if (Cert_And_Key->cert) {
  823. *pRetCert = CERT_DupCertificate(Cert_And_Key->cert);
  824. }
  825. if (Cert_And_Key->key) {
  826. *pRetKey = SECKEY_CopyPrivateKey(Cert_And_Key->key);
  827. }
  828. PR_Unlock(Cert_And_Key->lock);
  829. if (!*pRetCert || !*pRetKey) {
  830. /* one or both of them failed to copy. Either the source was NULL, or there was
  831. ** an out of memory condition. Free any allocated copy and fail */
  832. if (*pRetCert) {
  833. CERT_DestroyCertificate(*pRetCert);
  834. *pRetCert = NULL;
  835. }
  836. if (*pRetKey) {
  837. SECKEY_DestroyPrivateKey(*pRetKey);
  838. *pRetKey = NULL;
  839. }
  840. break;
  841. }
  842. /* now check if those objects are valid */
  843. if ( PR_FALSE == LoggedIn(*pRetCert, *pRetKey) ) {
  844. /* token is no longer logged in, it was removed */
  845. /* first, delete and clear our invalid local objects */
  846. CERT_DestroyCertificate(*pRetCert);
  847. SECKEY_DestroyPrivateKey(*pRetKey);
  848. *pRetCert = NULL;
  849. *pRetKey = NULL;
  850. PR_Lock(Cert_And_Key->lock);
  851. /* check if another thread already logged back in */
  852. if (PR_TRUE == LoggedIn(Cert_And_Key->cert, Cert_And_Key->key)) {
  853. /* yes : try again */
  854. PR_Unlock(Cert_And_Key->lock);
  855. continue;
  856. }
  857. /* this is the thread to retry */
  858. CERT_DestroyCertificate(Cert_And_Key->cert);
  859. SECKEY_DestroyPrivateKey(Cert_And_Key->key);
  860. Cert_And_Key->cert = NULL;
  861. Cert_And_Key->key = NULL;
  862. /* now look up the cert and key again */
  863. while (PR_FALSE == FindCertAndKey(Cert_And_Key) ) {
  864. PR_Sleep(PR_SecondsToInterval(1));
  865. timeout++;
  866. if (timeout>=60) {
  867. printf("\nToken pulled and not reinserted early enough : aborting.\n");
  868. exit(1);
  869. }
  870. }
  871. PR_Unlock(Cert_And_Key->lock);
  872. continue;
  873. /* try again to reduce code size */
  874. }
  875. return SECSuccess;
  876. }
  877. }
  878. *pRetCert = NULL;
  879. *pRetKey = NULL;
  880. return SECFailure;
  881. } else {
  882. /* no cert configured, automatically find the right cert. */
  883. CERTCertificate * cert = NULL;
  884. SECKEYPrivateKey * privkey = NULL;
  885. CERTCertNicknames * names;
  886. int i;
  887. void * proto_win = NULL;
  888. SECStatus rv = SECFailure;
  889. if (Cert_And_Key) {
  890. proto_win = Cert_And_Key->wincx;
  891. }
  892. names = CERT_GetCertNicknames(CERT_GetDefaultCertDB(),
  893. SEC_CERT_NICKNAMES_USER, proto_win);
  894. if (names != NULL) {
  895. for (i = 0; i < names->numnicknames; i++) {
  896. cert = CERT_FindUserCertByUsage(CERT_GetDefaultCertDB(),
  897. names->nicknames[i], certUsageSSLClient,
  898. PR_FALSE, proto_win);
  899. if ( !cert )
  900. continue;
  901. /* Only check unexpired certs */
  902. if (CERT_CheckCertValidTimes(cert, PR_Now(), PR_TRUE) !=
  903. secCertTimeValid ) {
  904. CERT_DestroyCertificate(cert);
  905. continue;
  906. }
  907. rv = NSS_CmpCertChainWCANames(cert, caNames);
  908. if ( rv == SECSuccess ) {
  909. privkey = PK11_FindKeyByAnyCert(cert, proto_win);
  910. if ( privkey )
  911. break;
  912. }
  913. rv = SECFailure;
  914. CERT_DestroyCertificate(cert);
  915. }
  916. CERT_FreeNicknames(names);
  917. }
  918. if (rv == SECSuccess) {
  919. *pRetCert = cert;
  920. *pRetKey = privkey;
  921. }
  922. return rv;
  923. }
  924. }
  925. int
  926. hexchar_to_int(int c)
  927. {
  928. if (((c) >= '0') && ((c) <= '9'))
  929. return (c) - '0';
  930. if (((c) >= 'a') && ((c) <= 'f'))
  931. return (c) - 'a' + 10;
  932. if (((c) >= 'A') && ((c) <= 'F'))
  933. return (c) - 'A' + 10;
  934. failed_already = 1;
  935. return -1;
  936. }
  937. void
  938. client_main(
  939. unsigned short port,
  940. int connections,
  941. cert_and_key* Cert_And_Key,
  942. const char * hostName,
  943. const char * sniHostName)
  944. {
  945. PRFileDesc *model_sock = NULL;
  946. int i;
  947. int rv;
  948. PRStatus status;
  949. PRNetAddr addr;
  950. status = PR_StringToNetAddr(hostName, &addr);
  951. if (status == PR_SUCCESS) {
  952. addr.inet.port = PR_htons(port);
  953. } else {
  954. /* Lookup host */
  955. PRAddrInfo *addrInfo;
  956. void *enumPtr = NULL;
  957. addrInfo = PR_GetAddrInfoByName(hostName, PR_AF_UNSPEC,
  958. PR_AI_ADDRCONFIG | PR_AI_NOCANONNAME);
  959. if (!addrInfo) {
  960. SECU_PrintError(progName, "error looking up host");
  961. return;
  962. }
  963. do {
  964. enumPtr = PR_EnumerateAddrInfo(enumPtr, addrInfo, port, &addr);
  965. } while (enumPtr != NULL &&
  966. addr.raw.family != PR_AF_INET &&
  967. addr.raw.family != PR_AF_INET6);
  968. PR_FreeAddrInfo(addrInfo);
  969. if (enumPtr == NULL) {
  970. SECU_PrintError(progName, "error looking up host address");
  971. return;
  972. }
  973. }
  974. /* all suites except RSA_NULL_MD5 are enabled by Domestic Policy */
  975. NSS_SetDomesticPolicy();
  976. /* all the SSL2 and SSL3 cipher suites are enabled by default. */
  977. if (cipherString) {
  978. int ndx;
  979. /* disable all the ciphers, then enable the ones we want. */
  980. disableAllSSLCiphers();
  981. while (0 != (ndx = *cipherString)) {
  982. const char * startCipher = cipherString++;
  983. int cipher = 0;
  984. SECStatus rv;
  985. if (ndx == ':') {
  986. cipher = hexchar_to_int(*cipherString++);
  987. cipher <<= 4;
  988. cipher |= hexchar_to_int(*cipherString++);
  989. cipher <<= 4;
  990. cipher |= hexchar_to_int(*cipherString++);
  991. cipher <<= 4;
  992. cipher |= hexchar_to_int(*cipherString++);
  993. if (cipher <= 0) {
  994. fprintf(stderr, "strsclnt: Invalid cipher value: %-5.5s\n",
  995. startCipher);
  996. failed_already = 1;
  997. return;
  998. }
  999. } else {
  1000. if (isalpha(ndx)) {
  1001. const int *cptr;
  1002. cptr = islower(ndx) ? ssl3CipherSuites : ssl2CipherSuites;
  1003. for (ndx &= 0x1f; (cipher = *cptr++) != 0 && --ndx > 0; )
  1004. /* do nothing */;
  1005. }
  1006. if (cipher <= 0) {
  1007. fprintf(stderr, "strsclnt: Invalid cipher letter: %c\n",
  1008. *startCipher);
  1009. failed_already = 1;
  1010. return;
  1011. }
  1012. }
  1013. rv = SSL_CipherPrefSetDefault(cipher, PR_TRUE);
  1014. if (rv != SECSuccess) {
  1015. fprintf(stderr,
  1016. "strsclnt: SSL_CipherPrefSetDefault(0x%04x) failed\n",
  1017. cipher);
  1018. failed_already = 1;
  1019. return;
  1020. }
  1021. }
  1022. }
  1023. /* configure model SSL socket. */
  1024. model_sock = PR_OpenTCPSocket(addr.raw.family);
  1025. if (model_sock == NULL) {
  1026. errExit("PR_OpenTCPSocket for model socket");
  1027. }
  1028. model_sock = SSL_ImportFD(NULL, model_sock);
  1029. if (model_sock == NULL) {
  1030. errExit("SSL_ImportFD");
  1031. }
  1032. /* do SSL configuration. */
  1033. rv = SSL_OptionSet(model_sock, SSL_SECURITY,
  1034. !(disableSSL2 && disableSSL3 && disableTLS));
  1035. if (rv < 0) {
  1036. errExit("SSL_OptionSet SSL_SECURITY");
  1037. }
  1038. rv = SSL_OptionSet(model_sock, SSL_ENABLE_SSL2, !disableSSL2);
  1039. if (rv != SECSuccess) {
  1040. errExit("error enabling SSLv2 ");
  1041. }
  1042. rv = SSL_OptionSet(model_sock, SSL_V2_COMPATIBLE_HELLO, !disableSSL2);
  1043. if (rv != SECSuccess) {
  1044. errExit("error enabling SSLv2 compatible hellos ");
  1045. }
  1046. rv = SSL_OptionSet(model_sock, SSL_ENABLE_SSL3, !disableSSL3);
  1047. if (rv != SECSuccess) {
  1048. errExit("error enabling SSLv3 ");
  1049. }
  1050. rv = SSL_OptionSet(model_sock, SSL_ENABLE_TLS, !disableTLS);
  1051. if (rv != SECSuccess) {
  1052. errExit("error enabling TLS ");
  1053. }
  1054. if (bigBuf.data) { /* doing FDX */
  1055. rv = SSL_OptionSet(model_sock, SSL_ENABLE_FDX, 1);
  1056. if (rv < 0) {
  1057. errExit("SSL_OptionSet SSL_ENABLE_FDX");
  1058. }
  1059. }
  1060. if (NoReuse) {
  1061. rv = SSL_OptionSet(model_sock, SSL_NO_CACHE, 1);
  1062. if (rv < 0) {
  1063. errExit("SSL_OptionSet SSL_NO_CACHE");
  1064. }
  1065. }
  1066. if (bypassPKCS11) {
  1067. rv = SSL_OptionSet(model_sock, SSL_BYPASS_PKCS11, 1);
  1068. if (rv < 0) {
  1069. errExit("SSL_OptionSet SSL_BYPASS_PKCS11");
  1070. }
  1071. }
  1072. if (disableLocking) {
  1073. rv = SSL_OptionSet(model_sock, SSL_NO_LOCKS, 1);
  1074. if (rv < 0) {
  1075. errExit("SSL_OptionSet SSL_NO_LOCKS");
  1076. }
  1077. }
  1078. if (enableSessionTickets) {
  1079. rv = SSL_OptionSet(model_sock, SSL_ENABLE_SESSION_TICKETS, PR_TRUE);
  1080. if (rv != SECSuccess)
  1081. errExit("SSL_OptionSet SSL_ENABLE_SESSION_TICKETS");
  1082. }
  1083. if (enableCompression) {
  1084. rv = SSL_OptionSet(model_sock, SSL_ENABLE_DEFLATE, PR_TRUE);
  1085. if (rv != SECSuccess)
  1086. errExit("SSL_OptionSet SSL_ENABLE_DEFLATE");
  1087. }
  1088. if (enableFalseStart) {
  1089. rv = SSL_OptionSet(model_sock, SSL_ENABLE_FALSE_START, PR_TRUE);
  1090. if (rv != SECSuccess)
  1091. errExit("SSL_OptionSet SSL_ENABLE_FALSE_START");
  1092. }
  1093. SSL_SetURL(model_sock, hostName);
  1094. SSL_AuthCertificateHook(model_sock, mySSLAuthCertificate,
  1095. (void *)CERT_GetDefaultCertDB());
  1096. SSL_BadCertHook(model_sock, myBadCertHandler, NULL);
  1097. SSL_GetClientAuthDataHook(model_sock, StressClient_GetClientAuthData, (void*)Cert_And_Key);
  1098. if (sniHostName) {
  1099. SSL_SetURL(model_sock, sniHostName);
  1100. }
  1101. /* I'm not going to set the HandshakeCallback function. */
  1102. /* end of ssl configuration. */
  1103. init_thread_data();
  1104. remaining_connections = total_connections = connections;
  1105. total_connections_modulo_100 = total_connections % 100;
  1106. total_connections_rounded_down_to_hundreds =
  1107. total_connections - total_connections_modulo_100;
  1108. if (!NoReuse) {
  1109. remaining_connections = 1;
  1110. rv = launch_thread(do_connects, &addr, model_sock, 0);
  1111. /* wait for the first connection to terminate, then launch the rest. */
  1112. reap_threads();
  1113. remaining_connections = total_connections - 1 ;
  1114. }
  1115. if (remaining_connections > 0) {
  1116. active_threads = PR_MIN(active_threads, remaining_connections);
  1117. /* Start up the threads */
  1118. for (i=0;i<active_threads;i++) {
  1119. rv = launch_thread(do_connects, &addr, model_sock, i);
  1120. }
  1121. reap_threads();
  1122. }
  1123. destroy_thread_data();
  1124. PR_Close(model_sock);
  1125. }
  1126. SECStatus
  1127. readBigFile(const char * fileName)
  1128. {
  1129. PRFileInfo info;
  1130. PRStatus status;
  1131. SECStatus rv = SECFailure;
  1132. int count;
  1133. int hdrLen;
  1134. PRFileDesc *local_file_fd = NULL;
  1135. status = PR_GetFileInfo(fileName, &info);
  1136. if (status == PR_SUCCESS &&
  1137. info.type == PR_FILE_FILE &&
  1138. info.size > 0 &&
  1139. NULL != (local_file_fd = PR_Open(fileName, PR_RDONLY, 0))) {
  1140. hdrLen = PORT_Strlen(outHeader);
  1141. bigBuf.len = hdrLen + info.size;
  1142. bigBuf.data = PORT_Malloc(bigBuf.len + 4095);
  1143. if (!bigBuf.data) {
  1144. errWarn("PORT_Malloc");
  1145. goto done;
  1146. }
  1147. PORT_Memcpy(bigBuf.data, outHeader, hdrLen);
  1148. count = PR_Read(local_file_fd, bigBuf.data + hdrLen, info.size);
  1149. if (count != info.size) {
  1150. errWarn("PR_Read local file");
  1151. goto done;
  1152. }
  1153. rv = SECSuccess;
  1154. done:
  1155. PR_Close(local_file_fd);
  1156. }
  1157. return rv;
  1158. }
  1159. int
  1160. main(int argc, char **argv)
  1161. {
  1162. const char * dir = ".";
  1163. const char * fileName = NULL;
  1164. char * hostName = NULL;
  1165. char * nickName = NULL;
  1166. char * tmp = NULL;
  1167. int connections = 1;
  1168. int exitVal;
  1169. int tmpInt;
  1170. unsigned short port = 443;
  1171. SECStatus rv;
  1172. PLOptState * optstate;
  1173. PLOptStatus status;
  1174. cert_and_key Cert_And_Key;
  1175. secuPWData pwdata = { PW_NONE, 0 };
  1176. char * sniHostName = NULL;
  1177. /* Call the NSPR initialization routines */
  1178. PR_Init( PR_SYSTEM_THREAD, PR_PRIORITY_NORMAL, 1);
  1179. tmp = strrchr(argv[0], '/');
  1180. tmp = tmp ? tmp + 1 : argv[0];
  1181. progName = strrchr(tmp, '\\');
  1182. progName = progName ? progName + 1 : tmp;
  1183. optstate = PL_CreateOptState(argc, argv,
  1184. "23BC:DNP:TUW:a:c:d:f:gin:op:qst:uvw:z");
  1185. while ((status = PL_GetNextOpt(optstate)) == PL_OPT_OK) {
  1186. switch(optstate->option) {
  1187. case '2': disableSSL2 = PR_TRUE; break;
  1188. case '3': disableSSL3 = PR_TRUE; break;
  1189. case 'B': bypassPKCS11 = PR_TRUE; break;
  1190. case 'C': cipherString = optstate->value; break;
  1191. case 'D': NoDelay = PR_TRUE; break;
  1192. case 'N': NoReuse = 1; break;
  1193. case 'P': fullhs = PORT_Atoi(optstate->value); break;
  1194. case 'T': disableTLS = PR_TRUE; break;
  1195. case 'U': ThrottleUp = PR_TRUE; break;
  1196. case 'a': sniHostName = PL_strdup(optstate->value); break;
  1197. case 'c': connections = PORT_Atoi(optstate->value); break;
  1198. case 'd': dir = optstate->value; break;
  1199. case 'f': fileName = optstate->value; break;
  1200. case 'g': enableFalseStart = PR_TRUE; break;
  1201. case 'i': ignoreErrors = PR_TRUE; break;
  1202. case 'n': nickName = PL_strdup(optstate->value); break;
  1203. case 'o': MakeCertOK++; break;
  1204. case 'p': port = PORT_Atoi(optstate->value); break;
  1205. case 'q': QuitOnTimeout = PR_TRUE; break;
  1206. case 's': disableLocking = PR_TRUE; break;
  1207. case 't':
  1208. tmpInt = PORT_Atoi(optstate->value);
  1209. if (tmpInt > 0 && tmpInt < MAX_THREADS)
  1210. max_threads = active_threads = tmpInt;
  1211. break;
  1212. case 'u': enableSessionTickets = PR_TRUE; break;
  1213. case 'v': verbose++; break;
  1214. case 'w':
  1215. pwdata.source = PW_PLAINTEXT;
  1216. pwdata.data = PL_strdup(optstate->value);
  1217. break;
  1218. case 'W':
  1219. pwdata.source = PW_FROMFILE;
  1220. pwdata.data = PL_strdup(optstate->value);
  1221. break;
  1222. case 'z': enableCompression = PR_TRUE; break;
  1223. case 0: /* positional parameter */
  1224. if (hostName) {
  1225. Usage(progName);
  1226. }
  1227. hostName = PL_strdup(optstate->value);
  1228. break;
  1229. default:
  1230. case '?':
  1231. Usage(progName);
  1232. break;
  1233. }
  1234. }
  1235. PL_DestroyOptState(optstate);
  1236. if (!hostName || status == PL_OPT_BAD)
  1237. Usage(progName);
  1238. if (fullhs!= NO_FULLHS_PERCENTAGE && (fullhs < 0 || fullhs>100 || NoReuse) )
  1239. Usage(progName);
  1240. if (port == 0)
  1241. Usage(progName);
  1242. if (fileName)
  1243. readBigFile(fileName);
  1244. PK11_SetPasswordFunc(SECU_GetModulePassword);
  1245. tmp = PR_GetEnv("NSS_DEBUG_TIMEOUT");
  1246. if (tmp && tmp[0]) {
  1247. int sec = PORT_Atoi(tmp);
  1248. if (sec > 0) {
  1249. maxInterval = PR_SecondsToInterval(sec);
  1250. }
  1251. }
  1252. /* Call the NSS initialization routines */
  1253. rv = NSS_Initialize(dir, "", "", SECMOD_DB, NSS_INIT_READONLY);
  1254. if (rv != SECSuccess) {
  1255. fputs("NSS_Init failed.\n", stderr);
  1256. exit(1);
  1257. }
  1258. ssl3stats = SSL_GetStatistics();
  1259. Cert_And_Key.lock = PR_NewLock();
  1260. Cert_And_Key.nickname = nickName;
  1261. Cert_And_Key.wincx = &pwdata;
  1262. Cert_And_Key.cert = NULL;
  1263. Cert_And_Key.key = NULL;
  1264. if (PR_FALSE == FindCertAndKey(&Cert_And_Key)) {
  1265. if (Cert_And_Key.cert == NULL) {
  1266. fprintf(stderr, "strsclnt: Can't find certificate %s\n", Cert_And_Key.nickname);
  1267. exit(1);
  1268. }
  1269. if (Cert_And_Key.key == NULL) {
  1270. fprintf(stderr, "strsclnt: Can't find Private Key for cert %s\n",
  1271. Cert_And_Key.nickname);
  1272. exit(1);
  1273. }
  1274. }
  1275. client_main(port, connections, &Cert_And_Key, hostName,
  1276. sniHostName);
  1277. /* clean up */
  1278. if (Cert_And_Key.cert) {
  1279. CERT_DestroyCertificate(Cert_And_Key.cert);
  1280. }
  1281. if (Cert_And_Key.key) {
  1282. SECKEY_DestroyPrivateKey(Cert_And_Key.key);
  1283. }
  1284. PR_DestroyLock(Cert_And_Key.lock);
  1285. if (pwdata.data) {
  1286. PL_strfree(pwdata.data);
  1287. }
  1288. if (Cert_And_Key.nickname) {
  1289. PL_strfree(Cert_And_Key.nickname);
  1290. }
  1291. if (sniHostName) {
  1292. PL_strfree(sniHostName);
  1293. }
  1294. PL_strfree(hostName);
  1295. /* some final stats. */
  1296. if (ssl3stats->hsh_sid_cache_hits +
  1297. ssl3stats->hsh_sid_cache_misses +
  1298. ssl3stats->hsh_sid_cache_not_ok +
  1299. ssl3stats->hsh_sid_stateless_resumes == 0) {
  1300. /* presumably we were testing SSL2. */
  1301. printf("strsclnt: SSL2 - %d server certificates tested.\n",
  1302. certsTested);
  1303. } else {
  1304. printf(
  1305. "strsclnt: %ld cache hits; %ld cache misses, %ld cache not reusable\n"
  1306. " %ld stateless resumes\n",
  1307. ssl3stats->hsh_sid_cache_hits,
  1308. ssl3stats->hsh_sid_cache_misses,
  1309. ssl3stats->hsh_sid_cache_not_ok,
  1310. ssl3stats->hsh_sid_stateless_resumes);
  1311. }
  1312. if (!NoReuse) {
  1313. if (enableSessionTickets)
  1314. exitVal = (ssl3stats->hsh_sid_stateless_resumes == 0);
  1315. else
  1316. exitVal = (ssl3stats->hsh_sid_cache_misses > 1) ||
  1317. (ssl3stats->hsh_sid_stateless_resumes != 0);
  1318. if (!exitVal)
  1319. exitVal = (ssl3stats->hsh_sid_cache_not_ok != 0) ||
  1320. (certsTested > 1);
  1321. } else {
  1322. printf("strsclnt: NoReuse - %d server certificates tested.\n",
  1323. certsTested);
  1324. if (ssl3stats->hsh_sid_cache_hits +
  1325. ssl3stats->hsh_sid_cache_misses +
  1326. ssl3stats->hsh_sid_cache_not_ok +
  1327. ssl3stats->hsh_sid_stateless_resumes > 0) {
  1328. exitVal = (ssl3stats->hsh_sid_cache_misses != connections) ||
  1329. (ssl3stats->hsh_sid_stateless_resumes != 0) ||
  1330. (certsTested != connections);
  1331. } else { /* ssl2 connections */
  1332. exitVal = (certsTested != connections);
  1333. }
  1334. }
  1335. exitVal = ( exitVal || failed_already );
  1336. SSL_ClearSessionCache();
  1337. if (NSS_Shutdown() != SECSuccess) {
  1338. printf("strsclnt: NSS_Shutdown() failed.\n");
  1339. exit(1);
  1340. }
  1341. PR_Cleanup();
  1342. return exitVal;
  1343. }