1 /* ***** BEGIN LICENSE BLOCK *****
2 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
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/
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
14 * The Original Code is the Netscape security libraries.
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.
22 * Douglas Stebila <douglas@stebila.ca>, Sun Microsystems Laboratories
24 * Alternatively, the contents of this file may be used under the terms of
25 * either the GNU General Public License Version 2 or later (the "GPL"), or
26 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
27 * in which case the provisions of the GPL or the LGPL are applicable instead
28 * of those above. If you wish to allow use of your version of this file only
29 * under the terms of either the GPL or the LGPL, and not to allow others to
30 * use your version of this file under the terms of the MPL, indicate your
31 * decision by deleting the provisions above and replace them with the notice
32 * and other provisions required by the GPL or the LGPL. If you do not delete
33 * the provisions above, a recipient may use your version of this file under
34 * the terms of any one of the MPL, the GPL or the LGPL.
36 * ***** END LICENSE BLOCK ***** */
38 /****************************************************************************
39 * SSL client program that tests a server for proper operation of SSL2, *
40 * SSL3, and TLS. Test propder certificate installation. *
42 * This code was modified from the SSLSample code also kept in the NSS *
44 ****************************************************************************/
75 #define RD_BUF_SIZE (60 * 1024)
77 extern int ssl2CipherSuites[];
78 extern int ssl3CipherSuites[];
80 GlobalThreadMgr threadMGR;
81 char *certNickname = NULL;
82 char *hostName = NULL;
83 secuPWData pwdata = { PW_NONE, 0 };
84 unsigned short port = 0;
88 Usage(const char *progName)
90 PRFileDesc *pr_stderr;
92 pr_stderr = PR_STDERR;
94 PR_fprintf(pr_stderr, "Usage:\n"
95 " %s [-c ] [-o] [-p port] [-d dbdir] [-w password] [-f pwfile]\n"
96 " \t\t[-C cipher(s)] [-l <url> -t <nickname> ] hostname",
98 PR_fprintf (pr_stderr, "\nWhere:\n");
99 PR_fprintf (pr_stderr,
100 " %-13s dump server cert chain into files\n",
102 PR_fprintf (pr_stderr,
103 " %-13s perform server cert OCSP check\n",
105 PR_fprintf (pr_stderr,
106 " %-13s server port to be used\n",
108 PR_fprintf (pr_stderr,
109 " %-13s use security databases in \"dbdir\"\n",
111 PR_fprintf (pr_stderr,
112 " %-13s key database password\n",
114 PR_fprintf (pr_stderr,
115 " %-13s token password file\n",
117 PR_fprintf (pr_stderr,
118 " %-13s communication cipher list\n",
120 PR_fprintf (pr_stderr,
121 " %-13s OCSP responder location. This location is used to\n"
122 " %-13s check status of a server certificate. If not \n"
123 " %-13s specified, location will be taken from the AIA\n"
124 " %-13s server certificate extension.\n",
125 "-l url", "", "", "");
126 PR_fprintf (pr_stderr,
127 " %-13s OCSP Trusted Responder Cert nickname\n\n",
134 setupSSLSocket(PRNetAddr *addr)
136 PRFileDesc *tcpSocket;
137 PRFileDesc *sslSocket;
138 PRSocketOptionData socketOption;
143 tcpSocket = PR_NewTCPSocket();
144 if (tcpSocket == NULL) {
145 errWarn("PR_NewTCPSocket");
148 /* Make the socket blocking. */
149 socketOption.option = PR_SockOpt_Nonblocking;
150 socketOption.value.non_blocking = PR_FALSE;
152 prStatus = PR_SetSocketOption(tcpSocket, &socketOption);
153 if (prStatus != PR_SUCCESS) {
154 errWarn("PR_SetSocketOption");
159 /* Import the socket into the SSL layer. */
160 sslSocket = SSL_ImportFD(NULL, tcpSocket);
162 errWarn("SSL_ImportFD");
166 /* Set configuration options. */
167 secStatus = SSL_OptionSet(sslSocket, SSL_SECURITY, PR_TRUE);
168 if (secStatus != SECSuccess) {
169 errWarn("SSL_OptionSet:SSL_SECURITY");
173 secStatus = SSL_OptionSet(sslSocket, SSL_HANDSHAKE_AS_CLIENT, PR_TRUE);
174 if (secStatus != SECSuccess) {
175 errWarn("SSL_OptionSet:SSL_HANDSHAKE_AS_CLIENT");
179 /* Set SSL callback routines. */
180 secStatus = SSL_GetClientAuthDataHook(sslSocket,
181 (SSLGetClientAuthData)myGetClientAuthData,
182 (void *)certNickname);
183 if (secStatus != SECSuccess) {
184 errWarn("SSL_GetClientAuthDataHook");
188 secStatus = SSL_AuthCertificateHook(sslSocket,
189 (SSLAuthCertificate)myAuthCertificate,
190 (void *)CERT_GetDefaultCertDB());
191 if (secStatus != SECSuccess) {
192 errWarn("SSL_AuthCertificateHook");
196 secStatus = SSL_BadCertHook(sslSocket,
197 (SSLBadCertHandler)myBadCertHandler, NULL);
198 if (secStatus != SECSuccess) {
199 errWarn("SSL_BadCertHook");
203 secStatus = SSL_HandshakeCallback(sslSocket,
206 if (secStatus != SECSuccess) {
207 errWarn("SSL_HandshakeCallback");
220 const char requestString[] = {"GET /testfile HTTP/1.0\r\n\r\n" };
223 handle_connection(PRFileDesc *sslSocket, int connection)
229 readBuffer = PORT_Alloc(RD_BUF_SIZE);
231 exitErr("PORT_Alloc");
234 /* compose the http request here. */
236 numBytes = PR_Write(sslSocket, requestString, strlen(requestString));
246 numBytes = PR_Read(sslSocket, readBuffer, RD_BUF_SIZE);
254 countRead += numBytes;
257 printSecurityInfo(stderr, sslSocket);
262 /* Caller closes the socket. */
265 "***** Connection %d read %d bytes total.\n",
266 connection, countRead);
268 return SECSuccess; /* success */
271 #define BYTE(n,i) (((i)>>((n)*8))&0xff)
273 /* one copy of this function is launched in a separate thread for each
274 ** connection to be made.
277 do_connects(void *a, int connection)
279 PRNetAddr *addr = (PRNetAddr *)a;
280 PRFileDesc *sslSocket;
282 char buffer[PR_NETDB_BUF_SIZE];
288 /* Set up SSL secure socket. */
289 sslSocket = setupSSLSocket(addr);
290 if (sslSocket == NULL) {
291 errWarn("setupSSLSocket");
295 secStatus = SSL_SetPKCS11PinArg(sslSocket, &pwdata);
296 if (secStatus != SECSuccess) {
297 errWarn("SSL_SetPKCS11PinArg");
301 secStatus = SSL_SetURL(sslSocket, hostName);
302 if (secStatus != SECSuccess) {
303 errWarn("SSL_SetURL");
307 /* Prepare and setup network connection. */
308 prStatus = PR_GetHostByName(hostName, buffer, sizeof(buffer), &hostEntry);
309 if (prStatus != PR_SUCCESS) {
310 errWarn("PR_GetHostByName");
314 hostenum = PR_EnumerateHostEnt(0, &hostEntry, port, addr);
315 if (hostenum == -1) {
316 errWarn("PR_EnumerateHostEnt");
320 ip = PR_ntohl(addr->inet.ip);
322 "Connecting to host %s (addr %d.%d.%d.%d) on port %d\n",
323 hostName, BYTE(3,ip), BYTE(2,ip), BYTE(1,ip),
324 BYTE(0,ip), PR_ntohs(addr->inet.port));
326 prStatus = PR_Connect(sslSocket, addr, PR_INTERVAL_NO_TIMEOUT);
327 if (prStatus != PR_SUCCESS) {
328 errWarn("PR_Connect");
332 /* Established SSL connection, ready to send data. */
334 secStatus = SSL_ForceHandshake(sslSocket);
335 if (secStatus != SECSuccess) {
336 errWarn("SSL_ForceHandshake");
341 secStatus = SSL_ResetHandshake(sslSocket, /* asServer */ PR_FALSE);
342 if (secStatus != SECSuccess) {
343 errWarn("SSL_ResetHandshake");
344 prStatus = PR_Close(sslSocket);
345 if (prStatus != PR_SUCCESS) {
351 secStatus = handle_connection(sslSocket, connection);
352 if (secStatus != SECSuccess) {
353 /* error already printed out in handle_connection */
354 /* errWarn("handle_connection"); */
355 prStatus = PR_Close(sslSocket);
356 if (prStatus != PR_SUCCESS) {
367 client_main(unsigned short port,
369 const char * hostName)
377 char buffer[PR_NETDB_BUF_SIZE];
379 /* Setup network connection. */
380 prStatus = PR_GetHostByName(hostName, buffer, sizeof(buffer), &hostEntry);
381 if (prStatus != PR_SUCCESS) {
382 exitErr("PR_GetHostByName");
385 rv = PR_EnumerateHostEnt(0, &hostEntry, port, &addr);
387 exitErr("PR_EnumerateHostEnt");
390 secStatus = launch_thread(&threadMGR, do_connects, &addr, 1);
391 if (secStatus != SECSuccess) {
392 exitErr("launch_thread");
395 if (connections > 1) {
396 /* wait for the first connection to terminate, then launch the rest. */
397 reap_threads(&threadMGR);
398 /* Start up the connections */
399 for (i = 2; i <= connections; ++i) {
400 secStatus = launch_thread(&threadMGR, do_connects, &addr, i);
401 if (secStatus != SECSuccess) {
402 errWarn("launch_thread");
407 reap_threads(&threadMGR);
408 destroy_thread_data(&threadMGR);
411 #define HEXCHAR_TO_INT(c, i) \
412 if (((c) >= '0') && ((c) <= '9')) { \
414 } else if (((c) >= 'a') && ((c) <= 'f')) { \
415 i = (c) - 'a' + 10; \
416 } else if (((c) >= 'A') && ((c) <= 'F')) { \
417 i = (c) - 'A' + 10; \
423 main(int argc, char **argv)
425 char * certDir = NULL;
426 char * progName = NULL;
428 char * cipherString = NULL;
429 char * respUrl = NULL;
430 char * respCertName = NULL;
432 PLOptState * optstate;
434 PRBool doOcspCheck = PR_FALSE;
436 /* Call the NSPR initialization routines */
437 PR_Init( PR_SYSTEM_THREAD, PR_PRIORITY_NORMAL, 1);
439 progName = PORT_Strdup(argv[0]);
442 optstate = PL_CreateOptState(argc, argv, "C:cd:f:l:n:p:ot:w:");
443 while ((status = PL_GetNextOpt(optstate)) == PL_OPT_OK) {
444 switch(optstate->option) {
445 case 'C' : cipherString = PL_strdup(optstate->value); break;
446 case 'c' : dumpChain = PR_TRUE; break;
447 case 'd' : certDir = PL_strdup(optstate->value); break;
448 case 'l' : respUrl = PL_strdup(optstate->value); break;
449 case 'p' : port = PORT_Atoi(optstate->value); break;
450 case 'o' : doOcspCheck = PR_TRUE; break;
451 case 't' : respCertName = PL_strdup(optstate->value); break;
453 pwdata.source = PW_PLAINTEXT;
454 pwdata.data = PORT_Strdup(optstate->value);
458 pwdata.source = PW_FROMFILE;
459 pwdata.data = PORT_Strdup(optstate->value);
461 case '\0': hostName = PL_strdup(optstate->value); break;
462 default : Usage(progName);
470 if (port == 0 || hostName == NULL)
474 ((respCertName != NULL && respUrl == NULL) ||
475 (respUrl != NULL && respCertName == NULL))) {
476 SECU_PrintError (progName, "options -l <url> and -t "
477 "<responder> must be used together");
481 PK11_SetPasswordFunc(SECU_GetModulePassword);
483 /* Initialize the NSS libraries. */
485 secStatus = NSS_Init(certDir);
487 secStatus = NSS_NoDB_Init(NULL);
489 /* load the builtins */
490 SECMOD_AddNewModule("Builtins",
491 DLL_PREFIX"nssckbi."DLL_SUFFIX, 0, 0);
493 if (secStatus != SECSuccess) {
496 SECU_RegisterDynamicOids();
498 if (doOcspCheck == PR_TRUE) {
500 CERTCertDBHandle *handle = CERT_GetDefaultCertDB();
501 if (handle == NULL) {
502 SECU_PrintError (progName, "problem getting certdb handle");
506 rv = CERT_EnableOCSPChecking (handle);
507 if (rv != SECSuccess) {
508 SECU_PrintError (progName, "error enabling OCSP checking");
512 if (respUrl != NULL) {
513 rv = CERT_SetOCSPDefaultResponder (handle, respUrl,
515 if (rv != SECSuccess) {
516 SECU_PrintError (progName,
517 "error setting default responder");
521 rv = CERT_EnableOCSPDefaultResponder (handle);
522 if (rv != SECSuccess) {
523 SECU_PrintError (progName,
524 "error enabling default responder");
530 /* All cipher suites except RSA_NULL_MD5 are enabled by
531 * Domestic Policy. */
532 NSS_SetDomesticPolicy();
533 SSL_CipherPrefSetDefault(SSL_RSA_WITH_NULL_MD5, PR_TRUE);
535 /* all the SSL2 and SSL3 cipher suites are enabled by default. */
539 /* disable all the ciphers, then enable the ones we want. */
540 disableAllSSLCiphers();
542 while (0 != (ndx = *cipherString++)) {
549 HEXCHAR_TO_INT(*cipherString, ctmp)
550 cipher |= (ctmp << 12);
552 HEXCHAR_TO_INT(*cipherString, ctmp)
553 cipher |= (ctmp << 8);
555 HEXCHAR_TO_INT(*cipherString, ctmp)
556 cipher |= (ctmp << 4);
558 HEXCHAR_TO_INT(*cipherString, ctmp)
565 cptr = islower(ndx) ? ssl3CipherSuites : ssl2CipherSuites;
566 for (ndx &= 0x1f; (cipher = *cptr++) != 0 && --ndx > 0; )
570 SSL_CipherPrefSetDefault(cipher, PR_TRUE);
577 client_main(port, connections, hostName);
581 CERTCertDBHandle *handle = CERT_GetDefaultCertDB();
582 CERT_DisableOCSPDefaultResponder(handle);
583 CERT_DisableOCSPChecking (handle);
586 if (NSS_Shutdown() != SECSuccess) {