00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029 #include "setup.h"
00030
00031 #include <string.h>
00032 #include <stdlib.h>
00033 #include <ctype.h>
00034 #ifdef HAVE_SYS_SOCKET_H
00035 #include <sys/socket.h>
00036 #endif
00037
00038 #include "urldata.h"
00039 #include "sendf.h"
00040 #include "formdata.h"
00041 #include "url.h"
00042 #include "connect.h"
00043 #include "strequal.h"
00044 #include "select.h"
00045 #include "sslgen.h"
00046
00047 #define _MPRINTF_REPLACE
00048 #include <curl/mprintf.h>
00049
00050 #ifdef USE_NSS
00051
00052 #include "nssg.h"
00053 #include <nspr.h>
00054 #include <nss.h>
00055 #include <ssl.h>
00056 #include <sslerr.h>
00057 #include <secerr.h>
00058 #include <sslproto.h>
00059 #include <prtypes.h>
00060 #include <pk11pub.h>
00061
00062 #include "memory.h"
00063 #include "easyif.h"
00064
00065
00066 #include "memdebug.h"
00067
00068 #ifndef min
00069 #define min(a, b) ((a) < (b) ? (a) : (b))
00070 #endif
00071
00072 PRFileDesc *PR_ImportTCPSocket(PRInt32 osfd);
00073
00074 static int initialized = 0;
00075 static int noverify = 0;
00076
00077 #define HANDSHAKE_TIMEOUT 30
00078
00079 typedef struct {
00080 PRInt32 retryCount;
00081 struct SessionHandle *data;
00082 } pphrase_arg_t;
00083
00084 typedef struct {
00085 const char *name;
00086 int num;
00087 PRInt32 version;
00088 } cipher_s;
00089
00090
00091 #ifdef NSS_ENABLE_ECC
00092 #define ciphernum 48
00093 #else
00094 #define ciphernum 23
00095 #endif
00096
00097 enum sslversion { SSL2 = 1, SSL3 = 2, TLS = 4 };
00098
00099 cipher_s cipherlist[ciphernum] = {
00100
00101 {"rc4", SSL_EN_RC4_128_WITH_MD5, SSL2},
00102 {"rc4export", SSL_EN_RC4_128_EXPORT40_WITH_MD5, SSL2},
00103 {"rc2", SSL_EN_RC2_128_CBC_WITH_MD5, SSL2},
00104 {"rc2export", SSL_EN_RC2_128_CBC_EXPORT40_WITH_MD5, SSL2},
00105 {"des", SSL_EN_DES_64_CBC_WITH_MD5, SSL2},
00106 {"desede3", SSL_EN_DES_192_EDE3_CBC_WITH_MD5, SSL2},
00107
00108 {"rsa_rc4_128_md5", SSL_RSA_WITH_RC4_128_MD5, SSL3 | TLS},
00109 {"rsa_rc4_128_sha", SSL_RSA_WITH_RC4_128_SHA, SSL3 | TLS},
00110 {"rsa_3des_sha", SSL_RSA_WITH_3DES_EDE_CBC_SHA, SSL3 | TLS},
00111 {"rsa_des_sha", SSL_RSA_WITH_DES_CBC_SHA, SSL3 | TLS},
00112 {"rsa_rc4_40_md5", SSL_RSA_EXPORT_WITH_RC4_40_MD5, SSL3 | TLS},
00113 {"rsa_rc2_40_md5", SSL_RSA_EXPORT_WITH_RC2_CBC_40_MD5, SSL3 | TLS},
00114 {"rsa_null_md5", SSL_RSA_WITH_NULL_MD5, SSL3 | TLS},
00115 {"rsa_null_sha", SSL_RSA_WITH_NULL_SHA, SSL3 | TLS},
00116 {"fips_3des_sha", SSL_RSA_FIPS_WITH_3DES_EDE_CBC_SHA, SSL3 | TLS},
00117 {"fips_des_sha", SSL_RSA_FIPS_WITH_DES_CBC_SHA, SSL3 | TLS},
00118 {"fortezza", SSL_FORTEZZA_DMS_WITH_FORTEZZA_CBC_SHA, SSL3 | TLS},
00119 {"fortezza_rc4_128_sha", SSL_FORTEZZA_DMS_WITH_RC4_128_SHA, SSL3 | TLS},
00120 {"fortezza_null", SSL_FORTEZZA_DMS_WITH_NULL_SHA, SSL3 | TLS},
00121
00122 {"rsa_des_56_sha", TLS_RSA_EXPORT1024_WITH_DES_CBC_SHA, SSL3 | TLS},
00123 {"rsa_rc4_56_sha", TLS_RSA_EXPORT1024_WITH_RC4_56_SHA, SSL3 | TLS},
00124
00125 {"rsa_aes_128_sha", TLS_RSA_WITH_AES_128_CBC_SHA, SSL3 | TLS},
00126 {"rsa_aes_256_sha", TLS_RSA_WITH_AES_256_CBC_SHA, SSL3 | TLS},
00127 #ifdef NSS_ENABLE_ECC
00128
00129 {"ecdh_ecdsa_null_sha", TLS_ECDH_ECDSA_WITH_NULL_SHA, TLS},
00130 {"ecdh_ecdsa_rc4_128_sha", TLS_ECDH_ECDSA_WITH_RC4_128_SHA, TLS},
00131 {"ecdh_ecdsa_3des_sha", TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA, TLS},
00132 {"ecdh_ecdsa_aes_128_sha", TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA, TLS},
00133 {"ecdh_ecdsa_aes_256_sha", TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA, TLS},
00134 {"ecdhe_ecdsa_null_sha", TLS_ECDHE_ECDSA_WITH_NULL_SHA, TLS},
00135 {"ecdhe_ecdsa_rc4_128_sha", TLS_ECDHE_ECDSA_WITH_RC4_128_SHA, TLS},
00136 {"ecdhe_ecdsa_3des_sha", TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA, TLS},
00137 {"ecdhe_ecdsa_aes_128_sha", TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, TLS},
00138 {"ecdhe_ecdsa_aes_256_sha", TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA, TLS},
00139 {"ecdh_rsa_null_sha", TLS_ECDH_RSA_WITH_NULL_SHA, TLS},
00140 {"ecdh_rsa_128_sha", TLS_ECDH_RSA_WITH_RC4_128_SHA, TLS},
00141 {"ecdh_rsa_3des_sha", TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA, TLS},
00142 {"ecdh_rsa_aes_128_sha", TLS_ECDH_RSA_WITH_AES_128_CBC_SHA, TLS},
00143 {"ecdh_rsa_aes_256_sha", TLS_ECDH_RSA_WITH_AES_256_CBC_SHA, TLS},
00144 {"echde_rsa_null", TLS_ECDHE_RSA_WITH_NULL_SHA, TLS},
00145 {"ecdhe_rsa_rc4_128_sha", TLS_ECDHE_RSA_WITH_RC4_128_SHA, TLS},
00146 {"ecdhe_rsa_3des_sha", TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA, TLS},
00147 {"ecdhe_rsa_aes_128_sha", TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, TLS},
00148 {"ecdhe_rsa_aes_256_sha", TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA, TLS},
00149 {"ecdh_anon_null_sha", TLS_ECDH_anon_WITH_NULL_SHA, TLS},
00150 {"ecdh_anon_rc4_128sha", TLS_ECDH_anon_WITH_RC4_128_SHA, TLS},
00151 {"ecdh_anon_3des_sha", TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA, TLS},
00152 {"ecdh_anon_aes_128_sha", TLS_ECDH_anon_WITH_AES_128_CBC_SHA, TLS},
00153 {"ecdh_anon_aes_256_sha", TLS_ECDH_anon_WITH_AES_256_CBC_SHA, TLS},
00154 #endif
00155 };
00156
00157 static SECStatus set_ciphers(struct SessionHandle *data, PRFileDesc * model,
00158 char *cipher_list)
00159 {
00160 int i;
00161 PRBool cipher_state[ciphernum];
00162 PRBool found;
00163 char *cipher;
00164 SECStatus rv;
00165
00166
00167
00168
00169
00170 for(i=0; i<SSL_NumImplementedCiphers; i++) {
00171 SSL_CipherPrefSet(model, SSL_ImplementedCiphers[i], SSL_NOT_ALLOWED);
00172 }
00173
00174
00175 for(i=0; i<ciphernum; i++) {
00176 cipher_state[i] = PR_FALSE;
00177 }
00178
00179 cipher = cipher_list;
00180
00181 while(cipher_list && (cipher_list[0])) {
00182 while((*cipher) && (ISSPACE(*cipher)))
00183 ++cipher;
00184
00185 if((cipher_list = strchr(cipher, ','))) {
00186 *cipher_list++ = '\0';
00187 }
00188
00189 found = PR_FALSE;
00190
00191 for(i=0; i<ciphernum; i++) {
00192 if(!strcasecmp(cipher, cipherlist[i].name)) {
00193 cipher_state[i] = PR_TRUE;
00194 found = PR_TRUE;
00195 break;
00196 }
00197 }
00198
00199 if(found == PR_FALSE) {
00200 char buf[1024];
00201 snprintf(buf, 1024, "Unknown cipher in list: %s", cipher);
00202 failf(data, buf);
00203 return SECFailure;
00204 }
00205
00206 if(cipher_list) {
00207 cipher = cipher_list;
00208 }
00209 }
00210
00211
00212 for(i=0; i<ciphernum; i++) {
00213 rv = SSL_CipherPrefSet(model, cipherlist[i].num, cipher_state[i]);
00214 if(rv != SECSuccess) {
00215 failf(data, "Unknown cipher in cipher list");
00216 return SECFailure;
00217 }
00218 }
00219
00220 return SECSuccess;
00221 }
00222
00223 static char * nss_get_password(PK11SlotInfo * slot, PRBool retry, void *arg)
00224 {
00225 pphrase_arg_t *parg = (pphrase_arg_t *) arg;
00226 (void)slot;
00227 (void)retry;
00228 if(parg->data->set.key_passwd)
00229 return (char *)PORT_Strdup((char *)parg->data->set.key_passwd);
00230 else
00231 return NULL;
00232 }
00233
00234 static SECStatus nss_Init_Tokens(struct connectdata * conn)
00235 {
00236 PK11SlotList *slotList;
00237 PK11SlotListElement *listEntry;
00238 SECStatus ret, status = SECSuccess;
00239 pphrase_arg_t *parg;
00240
00241 parg = (pphrase_arg_t *) malloc(sizeof(*parg));
00242 parg->retryCount = 0;
00243 parg->data = conn->data;
00244
00245 PK11_SetPasswordFunc(nss_get_password);
00246
00247 slotList =
00248 PK11_GetAllTokens(CKM_INVALID_MECHANISM, PR_FALSE, PR_TRUE, NULL);
00249
00250 for(listEntry = PK11_GetFirstSafe(slotList);
00251 listEntry; listEntry = listEntry->next) {
00252 PK11SlotInfo *slot = listEntry->slot;
00253
00254 if(PK11_NeedLogin(slot) && PK11_NeedUserInit(slot)) {
00255 if(slot == PK11_GetInternalKeySlot()) {
00256 failf(conn->data, "The NSS database has not been initialized.\n");
00257 }
00258 else {
00259 failf(conn->data, "The token %s has not been initialized.",
00260 PK11_GetTokenName(slot));
00261 }
00262 PK11_FreeSlot(slot);
00263 continue;
00264 }
00265
00266 ret = PK11_Authenticate(slot, PR_TRUE, parg);
00267 if(SECSuccess != ret) {
00268 status = SECFailure;
00269 break;
00270 }
00271 parg->retryCount = 0;
00272 PK11_FreeSlot(slot);
00273 }
00274
00275 free(parg);
00276 return status;
00277 }
00278
00279 static SECStatus BadCertHandler(void *arg, PRFileDesc * socket)
00280 {
00281 SECStatus success = SECSuccess;
00282 (void)arg;
00283 (void)socket;
00284
00285 return success;
00286 }
00287
00291 static SECStatus HandshakeCallback(PRFileDesc * socket, void *arg)
00292 {
00293 (void)socket;
00294 (void)arg;
00295 return SECSuccess;
00296 }
00297
00302 static SECStatus SelectClientCert(void *arg, PRFileDesc * socket,
00303 struct CERTDistNamesStr * caNames,
00304 struct CERTCertificateStr ** pRetCert,
00305 struct SECKEYPrivateKeyStr ** pRetKey)
00306 {
00307 CERTCertificate *cert;
00308 SECKEYPrivateKey *privKey;
00309 char *nickname = (char *)arg;
00310 void *proto_win = NULL;
00311 SECStatus secStatus = SECFailure;
00312 (void)caNames;
00313
00314 proto_win = SSL_RevealPinArg(socket);
00315
00316 cert = PK11_FindCertFromNickname(nickname, proto_win);
00317 if(cert) {
00318 privKey = PK11_FindKeyByAnyCert(cert, proto_win);
00319 if(privKey) {
00320 secStatus = SECSuccess;
00321 }
00322 else {
00323 CERT_DestroyCertificate(cert);
00324 }
00325 }
00326
00327 if(secStatus == SECSuccess) {
00328 *pRetCert = cert;
00329 *pRetKey = privKey;
00330 }
00331
00332 return secStatus;
00333 }
00334
00341 int Curl_nss_init(void)
00342 {
00343 if(!initialized)
00344 PR_Init(PR_USER_THREAD, PR_PRIORITY_NORMAL, 256);
00345
00346
00347
00348 return 1;
00349 }
00350
00351
00352 void Curl_nss_cleanup(void)
00353 {
00354 NSS_Shutdown();
00355 initialized = 0;
00356 }
00357
00358
00359
00360
00361
00362
00363
00364
00365
00366 int
00367 Curl_nss_check_cxn(struct connectdata *conn)
00368 {
00369 int rc;
00370 char buf;
00371
00372 rc =
00373 PR_Recv(conn->ssl[FIRSTSOCKET].handle, (void *)&buf, 1, PR_MSG_PEEK,
00374 PR_SecondsToInterval(1));
00375 if(rc > 0)
00376 return 1;
00377
00378 if(rc == 0)
00379 return 0;
00380
00381 return -1;
00382 }
00383
00384
00385
00386
00387 void Curl_nss_close(struct connectdata *conn)
00388 {
00389 int i;
00390
00391 for(i=0; i<2; i++) {
00392 struct ssl_connect_data *connssl = &conn->ssl[i];
00393
00394 if(connssl->handle) {
00395 PR_Close(connssl->handle);
00396 connssl->handle = NULL;
00397 }
00398 connssl->use = FALSE;
00399 }
00400 }
00401
00402
00403
00404
00405
00406 int Curl_nss_close_all(struct SessionHandle *data)
00407 {
00408 (void)data;
00409 return 0;
00410 }
00411
00412 CURLcode Curl_nss_connect(struct connectdata * conn, int sockindex)
00413 {
00414 PRInt32 err;
00415 PRFileDesc *model = NULL;
00416 PRBool ssl2, ssl3, tlsv1;
00417 struct SessionHandle *data = conn->data;
00418 curl_socket_t sockfd = conn->sock[sockindex];
00419 struct ssl_connect_data *connssl = &conn->ssl[sockindex];
00420 SECStatus rv;
00421 int curlerr = CURLE_SSL_CONNECT_ERROR;
00422
00423
00424 if(!initialized) {
00425 if(!data->set.ssl.CAfile) {
00426 if(data->set.ssl.verifypeer) {
00427 failf(data, "No NSS cacert database specified.");
00428 return CURLE_SSL_CACERT_BADFILE;
00429 }
00430 else {
00431 rv = NSS_NoDB_Init(NULL);
00432 noverify = 1;
00433 }
00434 }
00435 else {
00436 rv = NSS_Initialize(data->set.ssl.CAfile, NULL, NULL, "secmod.db",
00437 NSS_INIT_READONLY);
00438 }
00439 if(rv != SECSuccess) {
00440 curlerr = CURLE_SSL_CACERT_BADFILE;
00441 goto error;
00442 }
00443 }
00444
00445 NSS_SetDomesticPolicy();
00446
00447 model = PR_NewTCPSocket();
00448 if(!model)
00449 goto error;
00450 model = SSL_ImportFD(NULL, model);
00451
00452 if(SSL_OptionSet(model, SSL_SECURITY, PR_TRUE) != SECSuccess)
00453 goto error;
00454 if(SSL_OptionSet(model, SSL_HANDSHAKE_AS_SERVER, PR_FALSE) != SECSuccess)
00455 goto error;
00456 if(SSL_OptionSet(model, SSL_HANDSHAKE_AS_CLIENT, PR_TRUE) != SECSuccess)
00457 goto error;
00458
00459 ssl2 = ssl3 = tlsv1 = PR_FALSE;
00460
00461 switch (data->set.ssl.version) {
00462 default:
00463 case CURL_SSLVERSION_DEFAULT:
00464 ssl2 = ssl3 = tlsv1 = PR_TRUE;
00465 break;
00466 case CURL_SSLVERSION_TLSv1:
00467 tlsv1 = PR_TRUE;
00468 break;
00469 case CURL_SSLVERSION_SSLv2:
00470 ssl2 = PR_TRUE;
00471 break;
00472 case CURL_SSLVERSION_SSLv3:
00473 ssl3 = PR_TRUE;
00474 break;
00475 }
00476
00477 if(SSL_OptionSet(model, SSL_ENABLE_SSL2, ssl2) != SECSuccess)
00478 goto error;
00479 if(SSL_OptionSet(model, SSL_ENABLE_SSL3, ssl3) != SECSuccess)
00480 goto error;
00481 if(SSL_OptionSet(model, SSL_ENABLE_TLS, tlsv1) != SECSuccess)
00482 goto error;
00483
00484 if(data->set.ssl.cipher_list) {
00485 if(set_ciphers(data, model, data->set.ssl.cipher_list) != SECSuccess)
00486 goto error;
00487 }
00488
00489 if(SSL_BadCertHook(model, (SSLBadCertHandler) BadCertHandler, NULL)
00490 != SECSuccess)
00491 goto error;
00492 if(SSL_HandshakeCallback(model, (SSLHandshakeCallback) HandshakeCallback,
00493 NULL) != SECSuccess)
00494 goto error;
00495
00496 if(data->set.cert) {
00497 if(SSL_GetClientAuthDataHook(model,
00498 (SSLGetClientAuthData) SelectClientCert,
00499 (void *)data->set.cert) != SECSuccess) {
00500 curlerr = CURLE_SSL_CERTPROBLEM;
00501 goto error;
00502 }
00503 if(nss_Init_Tokens(conn) != SECSuccess)
00504 goto error;
00505 }
00506
00507
00508 connssl->handle = PR_ImportTCPSocket(sockfd);
00509 connssl->handle = SSL_ImportFD(model, connssl->handle);
00510 if(!connssl->handle)
00511 goto error;
00512
00513
00514 SSL_ResetHandshake(connssl->handle, PR_FALSE);
00515
00516 SSL_SetURL(connssl->handle, conn->host.name);
00517
00518
00519 if (SSL_ForceHandshakeWithTimeout(connssl->handle,
00520 PR_SecondsToInterval(HANDSHAKE_TIMEOUT))
00521 != SECSuccess)
00522 goto error;
00523
00524 return CURLE_OK;
00525
00526 error:
00527 err = PR_GetError();
00528 failf(data, "NSS error %d", err);
00529 if(model)
00530 PR_Close(model);
00531 return curlerr;
00532 }
00533
00534
00535 int Curl_nss_send(struct connectdata *conn,
00536 int sockindex,
00537 void *mem,
00538 size_t len)
00539 {
00540 PRInt32 err;
00541 struct SessionHandle *data = conn->data;
00542 PRInt32 timeout;
00543 int rc;
00544
00545 if(data->set.timeout)
00546 timeout = PR_MillisecondsToInterval(data->set.timeout);
00547 else
00548 timeout = PR_MillisecondsToInterval(DEFAULT_CONNECT_TIMEOUT);
00549
00550 rc = PR_Send(conn->ssl[sockindex].handle, mem, (int)len, 0, timeout);
00551
00552 if(rc < 0) {
00553 err = PR_GetError();
00554
00555 if(err == PR_IO_TIMEOUT_ERROR) {
00556 failf(data, "SSL connection timeout");
00557 return CURLE_OPERATION_TIMEOUTED;
00558 }
00559
00560 failf(conn->data, "SSL write: error %d\n", err);
00561 return -1;
00562 }
00563 return rc;
00564 }
00565
00566
00567
00568
00569
00570
00571 ssize_t Curl_nss_recv(struct connectdata * conn,
00572 int num,
00573 char *buf,
00574 size_t buffersize,
00575 bool * wouldblock)
00576 {
00577 ssize_t nread;
00578 struct SessionHandle *data = conn->data;
00579 PRInt32 timeout;
00580
00581 if(data->set.timeout)
00582 timeout = PR_SecondsToInterval(data->set.timeout);
00583 else
00584 timeout = PR_MillisecondsToInterval(DEFAULT_CONNECT_TIMEOUT);
00585
00586 nread = PR_Recv(conn->ssl[num].handle, buf, (int)buffersize, 0, timeout);
00587 *wouldblock = FALSE;
00588 if(nread < 0) {
00589
00590 PRInt32 err = PR_GetError();
00591
00592 if(err == PR_WOULD_BLOCK_ERROR) {
00593 *wouldblock = TRUE;
00594 return -1;
00595 }
00596 if(err == PR_IO_TIMEOUT_ERROR) {
00597 failf(data, "SSL connection timeout");
00598 return CURLE_OPERATION_TIMEOUTED;
00599 }
00600 failf(conn->data, "SSL read: errno %d", err);
00601 return -1;
00602 }
00603 return nread;
00604 }
00605
00606 size_t Curl_nss_version(char *buffer, size_t size)
00607 {
00608 return snprintf(buffer, size, " NSS/%s", NSS_VERSION);
00609 }
00610 #endif