~ubuntu-branches/ubuntu/precise/xulrunner-1.9/precise

« back to all changes in this revision

Viewing changes to mozilla/security/nss/cmd/SSLsample/client.c

  • Committer: Bazaar Package Importer
  • Author(s): Alexander Sack
  • Date: 2008-12-16 18:40:18 UTC
  • mfrom: (1.1.15 upstream)
  • Revision ID: james.westby@ubuntu.com-20081216184018-j646ukfhzxnjynix
Tags: 1.9.0.5+nobinonly-0ubuntu1
* new security/stability upstream release v1.9.0.5 (FIREFOX_3_0_5_RELEASE)
  - see USN-690-1
* submit patches upstreamed:
  - bzXXX_plugin_for_mimetype_pref.patch => bz449188_att350098_plugin_for_mimetype_pref.patch
  - update debian/patches/series
* adjust XULFastLoad cache in response to interleaving landing of bmo
  #453545 and #462806
  - update debian/patches/bz368428_attachment_308130.patch

Show diffs side-by-side

added added

removed removed

Lines of Context:
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
 
 
37
 
/****************************************************************************
38
 
 *  SSL client program that sets up a connection to SSL server, transmits   *
39
 
 *  some data and then reads the reply                                      *
40
 
 ****************************************************************************/ 
41
 
 
42
 
#include <stdio.h>
43
 
#include <string.h>
44
 
 
45
 
#if defined(XP_UNIX)
46
 
#include <unistd.h>
47
 
#endif
48
 
 
49
 
#include "prerror.h"
50
 
 
51
 
#include "pk11func.h"
52
 
#include "secitem.h"
53
 
 
54
 
 
55
 
#include <stdlib.h>
56
 
#include <errno.h>
57
 
#include <fcntl.h>
58
 
#include <stdarg.h>
59
 
 
60
 
#include "nspr.h"
61
 
#include "plgetopt.h"
62
 
#include "prio.h"
63
 
#include "prnetdb.h"
64
 
#include "nss.h"
65
 
 
66
 
#include "sslsample.h"
67
 
 
68
 
#define RD_BUF_SIZE (60 * 1024)
69
 
 
70
 
extern int ssl2CipherSuites[];
71
 
extern int ssl3CipherSuites[];
72
 
 
73
 
GlobalThreadMgr threadMGR;
74
 
char *certNickname = NULL;
75
 
char *hostName = NULL;
76
 
char *password = NULL;
77
 
unsigned short port = 0;
78
 
 
79
 
static void
80
 
Usage(const char *progName)
81
 
{
82
 
        fprintf(stderr, 
83
 
          "Usage: %s [-n rsa_nickname] [-p port] [-d dbdir] [-c connections]\n"
84
 
          "          [-w dbpasswd] [-C cipher(s)] hostname\n",
85
 
        progName);
86
 
        exit(1);
87
 
}
88
 
 
89
 
PRFileDesc *
90
 
setupSSLSocket(PRNetAddr *addr)
91
 
{
92
 
        PRFileDesc         *tcpSocket;
93
 
        PRFileDesc         *sslSocket;
94
 
        PRSocketOptionData      socketOption;
95
 
        PRStatus            prStatus;
96
 
        SECStatus           secStatus;
97
 
 
98
 
#if 0
99
 
retry:
100
 
#endif
101
 
 
102
 
        tcpSocket = PR_NewTCPSocket();
103
 
        if (tcpSocket == NULL) {
104
 
                errWarn("PR_NewTCPSocket");
105
 
        }
106
 
 
107
 
        /* Make the socket blocking. */
108
 
        socketOption.option                 = PR_SockOpt_Nonblocking;
109
 
        socketOption.value.non_blocking = PR_FALSE;
110
 
 
111
 
        prStatus = PR_SetSocketOption(tcpSocket, &socketOption);
112
 
        if (prStatus != PR_SUCCESS) {
113
 
                errWarn("PR_SetSocketOption");
114
 
                goto loser;
115
 
        } 
116
 
 
117
 
#if 0
118
 
        /* Verify that a connection can be made to the socket. */
119
 
        prStatus = PR_Connect(tcpSocket, addr, PR_INTERVAL_NO_TIMEOUT);
120
 
        if (prStatus != PR_SUCCESS) {
121
 
                PRErrorCode err = PR_GetError();
122
 
                if (err == PR_CONNECT_REFUSED_ERROR) {
123
 
                        PR_Close(tcpSocket);
124
 
                        PR_Sleep(PR_MillisecondsToInterval(10));
125
 
                        fprintf(stderr, "Connection to port refused, retrying.\n");
126
 
                        goto retry;
127
 
                }
128
 
                errWarn("PR_Connect");
129
 
                goto loser;
130
 
        }
131
 
#endif
132
 
 
133
 
        /* Import the socket into the SSL layer. */
134
 
        sslSocket = SSL_ImportFD(NULL, tcpSocket);
135
 
        if (!sslSocket) {
136
 
                errWarn("SSL_ImportFD");
137
 
                goto loser;
138
 
        }
139
 
 
140
 
        /* Set configuration options. */
141
 
        secStatus = SSL_OptionSet(sslSocket, SSL_SECURITY, PR_TRUE);
142
 
        if (secStatus != SECSuccess) {
143
 
                errWarn("SSL_OptionSet:SSL_SECURITY");
144
 
                goto loser;
145
 
        }
146
 
 
147
 
        secStatus = SSL_OptionSet(sslSocket, SSL_HANDSHAKE_AS_CLIENT, PR_TRUE);
148
 
        if (secStatus != SECSuccess) {
149
 
                errWarn("SSL_OptionSet:SSL_HANDSHAKE_AS_CLIENT");
150
 
                goto loser;
151
 
        }
152
 
 
153
 
        /* Set SSL callback routines. */
154
 
        secStatus = SSL_GetClientAuthDataHook(sslSocket,
155
 
                                  (SSLGetClientAuthData)myGetClientAuthData,
156
 
                                  (void *)certNickname);
157
 
        if (secStatus != SECSuccess) {
158
 
                errWarn("SSL_GetClientAuthDataHook");
159
 
                goto loser;
160
 
        }
161
 
 
162
 
        secStatus = SSL_AuthCertificateHook(sslSocket,
163
 
                                           (SSLAuthCertificate)myAuthCertificate,
164
 
                                       (void *)CERT_GetDefaultCertDB());
165
 
        if (secStatus != SECSuccess) {
166
 
                errWarn("SSL_AuthCertificateHook");
167
 
                goto loser;
168
 
        }
169
 
 
170
 
        secStatus = SSL_BadCertHook(sslSocket, 
171
 
                                   (SSLBadCertHandler)myBadCertHandler, NULL);
172
 
        if (secStatus != SECSuccess) {
173
 
                errWarn("SSL_BadCertHook");
174
 
                goto loser;
175
 
        }
176
 
 
177
 
        secStatus = SSL_HandshakeCallback(sslSocket, 
178
 
                                          myHandshakeCallback,
179
 
                                          NULL);
180
 
        if (secStatus != SECSuccess) {
181
 
                errWarn("SSL_HandshakeCallback");
182
 
                goto loser;
183
 
        }
184
 
 
185
 
        return sslSocket;
186
 
 
187
 
loser:
188
 
 
189
 
        PR_Close(tcpSocket);
190
 
        return NULL;
191
 
}
192
 
 
193
 
 
194
 
const char requestString[] = {"GET /testfile HTTP/1.0\r\n\r\n" };
195
 
 
196
 
SECStatus
197
 
handle_connection(PRFileDesc *sslSocket, int connection)
198
 
{
199
 
        int          countRead = 0;
200
 
        PRInt32  numBytes;
201
 
        char    *readBuffer;
202
 
 
203
 
        readBuffer = PORT_Alloc(RD_BUF_SIZE);
204
 
        if (!readBuffer) {
205
 
                exitErr("PORT_Alloc");
206
 
        }
207
 
 
208
 
        /* compose the http request here. */
209
 
 
210
 
        numBytes = PR_Write(sslSocket, requestString, strlen(requestString));
211
 
        if (numBytes <= 0) {
212
 
                errWarn("PR_Write");
213
 
                PR_Free(readBuffer);
214
 
                readBuffer = NULL;
215
 
                return SECFailure;
216
 
        }
217
 
 
218
 
        /* read until EOF */
219
 
        while (PR_TRUE) {
220
 
                numBytes = PR_Read(sslSocket, readBuffer, RD_BUF_SIZE);
221
 
                if (numBytes == 0) {
222
 
                        break;  /* EOF */
223
 
                }
224
 
                if (numBytes < 0) {
225
 
                        errWarn("PR_Read");
226
 
                        break;
227
 
                }
228
 
                countRead += numBytes;
229
 
                fprintf(stderr, "***** Connection %d read %d bytes (%d total).\n", 
230
 
                        connection, numBytes, countRead );
231
 
                readBuffer[numBytes] = '\0';
232
 
                fprintf(stderr, "************\n%s\n************\n", readBuffer);
233
 
        }
234
 
 
235
 
        printSecurityInfo(sslSocket);
236
 
        
237
 
        PR_Free(readBuffer);
238
 
        readBuffer = NULL;
239
 
 
240
 
        /* Caller closes the socket. */
241
 
 
242
 
        fprintf(stderr, 
243
 
                "***** Connection %d read %d bytes total.\n", 
244
 
                connection, countRead);
245
 
 
246
 
        return SECSuccess;      /* success */
247
 
}
248
 
 
249
 
/* one copy of this function is launched in a separate thread for each
250
 
** connection to be made.
251
 
*/
252
 
SECStatus
253
 
do_connects(void *a, int connection)
254
 
{
255
 
        PRNetAddr  *addr = (PRNetAddr *)a;
256
 
        PRFileDesc *sslSocket;
257
 
        PRHostEnt   hostEntry;
258
 
        char        buffer[PR_NETDB_BUF_SIZE];
259
 
        PRStatus    prStatus;
260
 
        PRIntn      hostenum;
261
 
        SECStatus   secStatus;
262
 
 
263
 
        /* Set up SSL secure socket. */
264
 
        sslSocket = setupSSLSocket(addr);
265
 
        if (sslSocket == NULL) {
266
 
                errWarn("setupSSLSocket");
267
 
                return SECFailure;
268
 
        }
269
 
 
270
 
        secStatus = SSL_SetPKCS11PinArg(sslSocket, password);
271
 
        if (secStatus != SECSuccess) {
272
 
                errWarn("SSL_SetPKCS11PinArg");
273
 
                return secStatus;
274
 
        }
275
 
 
276
 
        secStatus = SSL_SetURL(sslSocket, hostName);
277
 
        if (secStatus != SECSuccess) {
278
 
                errWarn("SSL_SetURL");
279
 
                return secStatus;
280
 
        }
281
 
 
282
 
        /* Prepare and setup network connection. */
283
 
        prStatus = PR_GetHostByName(hostName, buffer, sizeof(buffer), &hostEntry);
284
 
        if (prStatus != PR_SUCCESS) {
285
 
                errWarn("PR_GetHostByName");
286
 
                return SECFailure;
287
 
        }
288
 
 
289
 
        hostenum = PR_EnumerateHostEnt(0, &hostEntry, port, addr);
290
 
        if (hostenum == -1) {
291
 
                errWarn("PR_EnumerateHostEnt");
292
 
                return SECFailure;
293
 
        }
294
 
 
295
 
        prStatus = PR_Connect(sslSocket, addr, PR_INTERVAL_NO_TIMEOUT);
296
 
        if (prStatus != PR_SUCCESS) {
297
 
                errWarn("PR_Connect");
298
 
                return SECFailure;
299
 
        }
300
 
 
301
 
        /* Established SSL connection, ready to send data. */
302
 
#if 0
303
 
        secStatus = SSL_ForceHandshake(sslSocket);
304
 
        if (secStatus != SECSuccess) {
305
 
                errWarn("SSL_ForceHandshake");
306
 
                return secStatus;
307
 
        }
308
 
#endif
309
 
 
310
 
        secStatus = SSL_ResetHandshake(sslSocket, /* asServer */ PR_FALSE);
311
 
        if (secStatus != SECSuccess) {
312
 
                errWarn("SSL_ResetHandshake");
313
 
                prStatus = PR_Close(sslSocket);
314
 
                if (prStatus != PR_SUCCESS) {
315
 
                        errWarn("PR_Close");
316
 
                }
317
 
                return secStatus;
318
 
        }
319
 
 
320
 
        secStatus = handle_connection(sslSocket, connection);
321
 
        if (secStatus != SECSuccess) {
322
 
                errWarn("handle_connection");
323
 
                return secStatus;
324
 
        }
325
 
 
326
 
        PR_Close(sslSocket);
327
 
        return SECSuccess;
328
 
}
329
 
 
330
 
void
331
 
client_main(unsigned short      port, 
332
 
            int                 connections, 
333
 
            const char *        hostName)
334
 
{
335
 
        int                     i;
336
 
        SECStatus       secStatus;
337
 
        PRStatus    prStatus;
338
 
        PRInt32     rv;
339
 
        PRNetAddr       addr;
340
 
        PRHostEnt   hostEntry;
341
 
        char        buffer[256];
342
 
 
343
 
        /* Setup network connection. */
344
 
        prStatus = PR_GetHostByName(hostName, buffer, 256, &hostEntry);
345
 
        if (prStatus != PR_SUCCESS) {
346
 
                exitErr("PR_GetHostByName");
347
 
        }
348
 
 
349
 
        rv = PR_EnumerateHostEnt(0, &hostEntry, port, &addr);
350
 
        if (rv < 0) {
351
 
                exitErr("PR_EnumerateHostEnt");
352
 
        }
353
 
 
354
 
        secStatus = launch_thread(&threadMGR, do_connects, &addr, 1);
355
 
        if (secStatus != SECSuccess) {
356
 
                exitErr("launch_thread");
357
 
        }
358
 
 
359
 
        if (connections > 1) {
360
 
                /* wait for the first connection to terminate, then launch the rest. */
361
 
                reap_threads(&threadMGR);
362
 
                /* Start up the connections */
363
 
                for (i = 2; i <= connections; ++i) {
364
 
                        secStatus = launch_thread(&threadMGR, do_connects, &addr, i);
365
 
                        if (secStatus != SECSuccess) {
366
 
                                errWarn("launch_thread");
367
 
                        }
368
 
                }
369
 
        }
370
 
 
371
 
        reap_threads(&threadMGR);
372
 
        destroy_thread_data(&threadMGR);
373
 
}
374
 
 
375
 
int
376
 
main(int argc, char **argv)
377
 
{
378
 
        char *               certDir      = ".";
379
 
        char *               progName     = NULL;
380
 
        int                                      connections  = 1;
381
 
        char *               cipherString = NULL;
382
 
        SECStatus            secStatus;
383
 
        PLOptState *         optstate;
384
 
        PLOptStatus          status;
385
 
 
386
 
        /* Call the NSPR initialization routines */
387
 
        PR_Init( PR_SYSTEM_THREAD, PR_PRIORITY_NORMAL, 1);
388
 
 
389
 
        progName = PL_strdup(argv[0]);
390
 
 
391
 
        hostName = NULL;
392
 
        optstate = PL_CreateOptState(argc, argv, "C:c:d:n:p:w:");
393
 
        while ((status = PL_GetNextOpt(optstate)) == PL_OPT_OK) {
394
 
                switch(optstate->option) {
395
 
                case 'C' : cipherString = PL_strdup(optstate->value); break;
396
 
                case 'c' : connections = PORT_Atoi(optstate->value);  break;
397
 
                case 'd' : certDir = PL_strdup(optstate->value);      break;
398
 
                case 'n' : certNickname = PL_strdup(optstate->value); break;
399
 
                case 'p' : port = PORT_Atoi(optstate->value);         break;
400
 
                case 'w' : password = PL_strdup(optstate->value);     break;
401
 
                case '\0': hostName = PL_strdup(optstate->value);     break;
402
 
                default  : Usage(progName);
403
 
                }
404
 
        }
405
 
 
406
 
        if (port == 0 || hostName == NULL)
407
 
                Usage(progName);
408
 
 
409
 
        if (certDir == NULL) {
410
 
                certDir = PR_smprintf("%s/.netscape", getenv("HOME"));
411
 
        }
412
 
 
413
 
        /* Set our password function callback. */
414
 
        PK11_SetPasswordFunc(myPasswd);
415
 
 
416
 
        /* Initialize the NSS libraries. */
417
 
        secStatus = NSS_Init(certDir);
418
 
        if (secStatus != SECSuccess) {
419
 
                exitErr("NSS_Init");
420
 
        }
421
 
 
422
 
        /* All cipher suites except RSA_NULL_MD5 are enabled by Domestic Policy. */
423
 
        NSS_SetDomesticPolicy();
424
 
        SSL_CipherPrefSetDefault(SSL_RSA_WITH_NULL_MD5, PR_TRUE);
425
 
 
426
 
        /* all the SSL2 and SSL3 cipher suites are enabled by default. */
427
 
        if (cipherString) {
428
 
            int ndx;
429
 
 
430
 
            /* disable all the ciphers, then enable the ones we want. */
431
 
            disableAllSSLCiphers();
432
 
 
433
 
            while (0 != (ndx = *cipherString++)) {
434
 
                int *cptr;
435
 
                int  cipher;
436
 
 
437
 
                if (! isalpha(ndx))
438
 
                    Usage(progName);
439
 
                cptr = islower(ndx) ? ssl3CipherSuites : ssl2CipherSuites;
440
 
                for (ndx &= 0x1f; (cipher = *cptr++) != 0 && --ndx > 0; )
441
 
                    /* do nothing */;
442
 
                if (cipher) {
443
 
                    SSL_CipherPrefSetDefault(cipher, PR_TRUE);
444
 
                }
445
 
            }
446
 
        }
447
 
 
448
 
        client_main(port, connections, hostName);
449
 
 
450
 
        if (NSS_Shutdown() != SECSuccess) {
451
 
            exit(1);
452
 
        }
453
 
        PR_Cleanup();
454
 
        return 0;
455
 
}
456