client.c
上传用户:lyxiangda
上传日期:2007-01-12
资源大小:3042k
文件大小:11k
源码类别:

CA认证

开发平台:

WINDOWS

  1. /*
  2.  * The contents of this file are subject to the Mozilla Public
  3.  * License Version 1.1 (the "License"); you may not use this file
  4.  * except in compliance with the License. You may obtain a copy of
  5.  * the License at http://www.mozilla.org/MPL/
  6.  * 
  7.  * Software distributed under the License is distributed on an "AS
  8.  * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
  9.  * implied. See the License for the specific language governing
  10.  * rights and limitations under the License.
  11.  * 
  12.  * The Original Code is the Netscape security libraries.
  13.  * 
  14.  * The Initial Developer of the Original Code is Netscape
  15.  * Communications Corporation.  Portions created by Netscape are 
  16.  * Copyright (C) 1994-2000 Netscape Communications Corporation.  All
  17.  * Rights Reserved.
  18.  * 
  19.  * Contributor(s):
  20.  * 
  21.  * Alternatively, the contents of this file may be used under the
  22.  * terms of the GNU General Public License Version 2 or later (the
  23.  * "GPL"), in which case the provisions of the GPL are applicable 
  24.  * instead of those above.  If you wish to allow use of your 
  25.  * version of this file only under the terms of the GPL and not to
  26.  * allow others to use your version of this file under the MPL,
  27.  * indicate your decision by deleting the provisions above and
  28.  * replace them with the notice and other provisions required by
  29.  * the GPL.  If you do not delete the provisions above, a recipient
  30.  * may use your version of this file under either the MPL or the
  31.  * GPL.
  32.  */
  33. /****************************************************************************
  34.  *  SSL client program that sets up a connection to SSL server, transmits   *
  35.  *  some data and then reads the reply                                      *
  36.  ****************************************************************************/ 
  37. #include <stdio.h>
  38. #include <string.h>
  39. #if defined(XP_UNIX)
  40. #include <unistd.h>
  41. #endif
  42. #include "prerror.h"
  43. #include "pk11func.h"
  44. #include "secitem.h"
  45. #include <stdlib.h>
  46. #include <errno.h>
  47. #include <fcntl.h>
  48. #include <stdarg.h>
  49. #include "nspr.h"
  50. #include "plgetopt.h"
  51. #include "prio.h"
  52. #include "prnetdb.h"
  53. #include "nss.h"
  54. #include "sslsample.h"
  55. #define RD_BUF_SIZE (60 * 1024)
  56. extern int cipherSuites[];
  57. extern int ssl2CipherSuites[];
  58. extern int ssl3CipherSuites[];
  59. GlobalThreadMgr threadMGR;
  60. char *certNickname = NULL;
  61. char *hostName = NULL;
  62. char *password = NULL;
  63. unsigned short port = 0;
  64. static void
  65. Usage(const char *progName)
  66. {
  67. fprintf(stderr, 
  68.   "Usage: %s [-n rsa_nickname] [-p port] [-d dbdir] [-c connections]n"
  69.   "          [-w dbpasswd] [-C cipher(s)] hostnamen",
  70. progName);
  71. exit(1);
  72. }
  73. PRFileDesc *
  74. setupSSLSocket(PRNetAddr *addr)
  75. {
  76. PRFileDesc         *tcpSocket;
  77. PRFileDesc         *sslSocket;
  78. PRSocketOptionData socketOption;
  79. PRStatus            prStatus;
  80. SECStatus           secStatus;
  81. retry:
  82. tcpSocket = PR_NewTCPSocket();
  83. if (tcpSocket == NULL) {
  84. errWarn("PR_NewTCPSocket");
  85. }
  86. /* Make the socket blocking. */
  87. socketOption.option             = PR_SockOpt_Nonblocking;
  88. socketOption.value.non_blocking = PR_FALSE;
  89. prStatus = PR_SetSocketOption(tcpSocket, &socketOption);
  90. if (prStatus != PR_SUCCESS) {
  91. errWarn("PR_SetSocketOption");
  92. goto loser;
  93. #if 0
  94. /* Verify that a connection can be made to the socket. */
  95. prStatus = PR_Connect(tcpSocket, addr, PR_INTERVAL_NO_TIMEOUT);
  96. if (prStatus != PR_SUCCESS) {
  97. PRErrorCode err = PR_GetError();
  98. if (err == PR_CONNECT_REFUSED_ERROR) {
  99. PR_Close(tcpSocket);
  100. PR_Sleep(PR_MillisecondsToInterval(10));
  101. fprintf(stderr, "Connection to port refused, retrying.n");
  102. goto retry;
  103. }
  104. errWarn("PR_Connect");
  105. goto loser;
  106. }
  107. #endif
  108. /* Import the socket into the SSL layer. */
  109. sslSocket = SSL_ImportFD(NULL, tcpSocket);
  110. if (!sslSocket) {
  111. errWarn("SSL_ImportFD");
  112. goto loser;
  113. }
  114. /* Set configuration options. */
  115. secStatus = SSL_Enable(sslSocket, SSL_SECURITY, PR_TRUE);
  116. if (secStatus != SECSuccess) {
  117. errWarn("SSL_Enable:SSL_SECURITY");
  118. goto loser;
  119. }
  120. secStatus = SSL_Enable(sslSocket, SSL_HANDSHAKE_AS_CLIENT, PR_TRUE);
  121. if (secStatus != SECSuccess) {
  122. errWarn("SSL_Enable:SSL_HANDSHAKE_AS_CLIENT");
  123. goto loser;
  124. }
  125. /* Set SSL callback routines. */
  126. secStatus = SSL_GetClientAuthDataHook(sslSocket,
  127.                           (SSLGetClientAuthData)myGetClientAuthData,
  128.                           (void *)certNickname);
  129. if (secStatus != SECSuccess) {
  130. errWarn("SSL_GetClientAuthDataHook");
  131. goto loser;
  132. }
  133. secStatus = SSL_AuthCertificateHook(sslSocket,
  134.                                    (SSLAuthCertificate)myAuthCertificate,
  135.                                        (void *)CERT_GetDefaultCertDB());
  136. if (secStatus != SECSuccess) {
  137. errWarn("SSL_AuthCertificateHook");
  138. goto loser;
  139. }
  140. secStatus = SSL_BadCertHook(sslSocket, 
  141.                            (SSLBadCertHandler)myBadCertHandler, NULL);
  142. if (secStatus != SECSuccess) {
  143. errWarn("SSL_BadCertHook");
  144. goto loser;
  145. }
  146. secStatus = SSL_HandshakeCallback(sslSocket, 
  147.                                  (SSLHandshakeCallback)myHandshakeCallback,
  148.                                  NULL);
  149. if (secStatus != SECSuccess) {
  150. errWarn("SSL_HandshakeCallback");
  151. goto loser;
  152. }
  153. return sslSocket;
  154. loser:
  155. PR_Close(tcpSocket);
  156. return NULL;
  157. }
  158. const char requestString[] = {"GET /testfile HTTP/1.0rnrn" };
  159. SECStatus
  160. handle_connection(PRFileDesc *sslSocket, int connection)
  161. {
  162. int      countRead = 0;
  163. PRInt32  numBytes;
  164. char    *readBuffer;
  165. readBuffer = PORT_Alloc(RD_BUF_SIZE);
  166. if (!readBuffer) {
  167. exitErr("PORT_Alloc");
  168. }
  169. /* compose the http request here. */
  170. numBytes = PR_Write(sslSocket, requestString, strlen(requestString));
  171. if (numBytes <= 0) {
  172. errWarn("PR_Write");
  173. PR_Free(readBuffer);
  174. readBuffer = NULL;
  175. return SECFailure;
  176. }
  177. /* read until EOF */
  178. while (PR_TRUE) {
  179. numBytes = PR_Read(sslSocket, readBuffer, RD_BUF_SIZE);
  180. if (numBytes == 0) {
  181. break; /* EOF */
  182. }
  183. if (numBytes < 0) {
  184. errWarn("PR_Read");
  185. break;
  186. }
  187. countRead += numBytes;
  188. fprintf(stderr, "***** Connection %d read %d bytes (%d total).n", 
  189. connection, numBytes, countRead );
  190. readBuffer[numBytes] = '';
  191. fprintf(stderr, "************n%sn************n", readBuffer);
  192. }
  193. printSecurityInfo(sslSocket);
  194. PR_Free(readBuffer);
  195. readBuffer = NULL;
  196. /* Caller closes the socket. */
  197. fprintf(stderr, 
  198.         "***** Connection %d read %d bytes total.n", 
  199.         connection, countRead);
  200. return SECSuccess; /* success */
  201. }
  202. /* one copy of this function is launched in a separate thread for each
  203. ** connection to be made.
  204. */
  205. SECStatus
  206. do_connects(void *a, int connection)
  207. {
  208. PRNetAddr  *addr = (PRNetAddr *)a;
  209. PRFileDesc *sslSocket;
  210. PRHostEnt   hostEntry;
  211. char        buffer[PR_NETDB_BUF_SIZE];
  212. PRStatus    prStatus;
  213. PRIntn      hostenum;
  214. SECStatus   secStatus;
  215. /* Set up SSL secure socket. */
  216. sslSocket = setupSSLSocket(addr);
  217. if (sslSocket == NULL) {
  218. errWarn("setupSSLSocket");
  219. return SECFailure;
  220. }
  221. secStatus = SSL_SetPKCS11PinArg(sslSocket, password);
  222. if (secStatus != SECSuccess) {
  223. errWarn("SSL_SetPKCS11PinArg");
  224. return secStatus;
  225. }
  226. secStatus = SSL_SetURL(sslSocket, hostName);
  227. if (secStatus != SECSuccess) {
  228. errWarn("SSL_SetURL");
  229. return secStatus;
  230. }
  231. /* Prepare and setup network connection. */
  232. prStatus = PR_GetHostByName(hostName, buffer, sizeof(buffer), &hostEntry);
  233. if (prStatus != PR_SUCCESS) {
  234. errWarn("PR_GetHostByName");
  235. return SECFailure;
  236. }
  237. hostenum = PR_EnumerateHostEnt(0, &hostEntry, port, addr);
  238. if (hostenum == -1) {
  239. errWarn("PR_EnumerateHostEnt");
  240. return SECFailure;
  241. }
  242. prStatus = PR_Connect(sslSocket, addr, PR_INTERVAL_NO_TIMEOUT);
  243. if (prStatus != PR_SUCCESS) {
  244. errWarn("PR_Connect");
  245. return SECFailure;
  246. }
  247. /* Established SSL connection, ready to send data. */
  248. #if 0
  249. secStatus = SSL_ForceHandshake(sslSocket);
  250. if (secStatus != SECSuccess) {
  251. errWarn("SSL_ForceHandshake");
  252. return secStatus;
  253. }
  254. #endif
  255. secStatus = SSL_ResetHandshake(sslSocket, /* asServer */ PR_FALSE);
  256. if (secStatus != SECSuccess) {
  257. errWarn("SSL_ResetHandshake");
  258. prStatus = PR_Close(sslSocket);
  259. if (prStatus != PR_SUCCESS) {
  260. errWarn("PR_Close");
  261. }
  262. return secStatus;
  263. }
  264. secStatus = handle_connection(sslSocket, connection);
  265. if (secStatus != SECSuccess) {
  266. errWarn("handle_connection");
  267. return secStatus;
  268. }
  269. PR_Close(sslSocket);
  270. return SECSuccess;
  271. }
  272. void
  273. client_main(unsigned short      port, 
  274.             int                 connections, 
  275.             const char *        hostName)
  276. {
  277. int i;
  278. SECStatus secStatus;
  279. PRStatus    prStatus;
  280. PRInt32     rv;
  281. PRNetAddr addr;
  282. PRHostEnt   hostEntry;
  283. char        buffer[256];
  284. /* Setup network connection. */
  285. prStatus = PR_GetHostByName(hostName, buffer, 256, &hostEntry);
  286. if (prStatus != PR_SUCCESS) {
  287. exitErr("PR_GetHostByName");
  288. }
  289. rv = PR_EnumerateHostEnt(0, &hostEntry, port, &addr);
  290. if (rv < 0) {
  291. exitErr("PR_EnumerateHostEnt");
  292. }
  293. secStatus = launch_thread(&threadMGR, do_connects, &addr, 1);
  294. if (secStatus != SECSuccess) {
  295. exitErr("launch_thread");
  296. }
  297. if (connections > 1) {
  298. /* wait for the first connection to terminate, then launch the rest. */
  299. reap_threads(&threadMGR);
  300. /* Start up the connections */
  301. for (i = 2; i <= connections; ++i) {
  302. secStatus = launch_thread(&threadMGR, do_connects, &addr, i);
  303. if (secStatus != SECSuccess) {
  304. errWarn("launch_thread");
  305. }
  306. }
  307. }
  308. reap_threads(&threadMGR);
  309. destroy_thread_data(&threadMGR);
  310. }
  311. int
  312. main(int argc, char **argv)
  313. {
  314. char *               certDir      = ".";
  315. char *               progName     = NULL;
  316. int  connections  = 1;
  317. char *               cipherString = NULL;
  318. SECStatus            secStatus;
  319. PLOptState *         optstate;
  320. PLOptStatus          status;
  321. /* Call the NSPR initialization routines */
  322. PR_Init( PR_SYSTEM_THREAD, PR_PRIORITY_NORMAL, 1);
  323. progName = PL_strdup(argv[0]);
  324. hostName = NULL;
  325. optstate = PL_CreateOptState(argc, argv, "C:c:d:n:p:w:");
  326. while ((status = PL_GetNextOpt(optstate)) == PL_OPT_OK) {
  327. switch(optstate->option) {
  328. case 'C' : cipherString = PL_strdup(optstate->value); break;
  329. case 'c' : connections = PORT_Atoi(optstate->value);  break;
  330. case 'd' : certDir = PL_strdup(optstate->value);      break;
  331. case 'n' : certNickname = PL_strdup(optstate->value); break;
  332. case 'p' : port = PORT_Atoi(optstate->value);         break;
  333. case 'w' : password = PL_strdup(optstate->value);     break;
  334. case '': hostName = PL_strdup(optstate->value);     break;
  335. default  : Usage(progName);
  336. }
  337. }
  338. if (port == 0 || hostName == NULL)
  339. Usage(progName);
  340. if (certDir == NULL) {
  341. certDir = PR_smprintf("%s/.netscape", getenv("HOME"));
  342. }
  343. /* Set our password function callback. */
  344. PK11_SetPasswordFunc(myPasswd);
  345. /* Initialize the NSS libraries. */
  346. secStatus = NSS_Init(certDir);
  347. if (secStatus != SECSuccess) {
  348. exitErr("NSS_Init");
  349. }
  350. /* All cipher suites except RSA_NULL_MD5 are enabled by Domestic Policy. */
  351. NSS_SetDomesticPolicy();
  352. SSL_EnableCipher(SSL_RSA_WITH_NULL_MD5, SSL_ALLOWED);
  353. /* all the SSL2 and SSL3 cipher suites are enabled by default. */
  354. if (cipherString) {
  355. int ndx;
  356. /* disable all the ciphers, then enable the ones we want. */
  357. disableSSL2Ciphers();
  358. disableSSL3Ciphers();
  359. while (0 != (ndx = *cipherString++)) {
  360. int *cptr;
  361. int  cipher;
  362. if (! isalpha(ndx))
  363. Usage(progName);
  364. cptr = islower(ndx) ? ssl3CipherSuites : ssl2CipherSuites;
  365. for (ndx &= 0x1f; (cipher = *cptr++) != 0 && --ndx > 0; )
  366. /* do nothing */;
  367. if (cipher) {
  368. SSL_EnableCipher(cipher, SSL_ALLOWED);
  369. }
  370. }
  371. }
  372. client_main(port, connections, hostName);
  373. NSS_Shutdown();
  374. PR_Cleanup();
  375. return 0;
  376. }