诸暨麻将添加redis
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

1572 lines
45 KiB

  1. /***************************************************************************
  2. * _ _ ____ _
  3. * Project ___| | | | _ \| |
  4. * / __| | | | |_) | |
  5. * | (__| |_| | _ <| |___
  6. * \___|\___/|_| \_\_____|
  7. *
  8. * Copyright (C) 1998 - 2012, Daniel Stenberg, <daniel@haxx.se>, et al.
  9. *
  10. * This software is licensed as described in the file COPYING, which
  11. * you should have received as part of this distribution. The terms
  12. * are also available at http://curl.haxx.se/docs/copyright.html.
  13. *
  14. * You may opt to use, copy, modify, merge, publish, distribute and/or sell
  15. * copies of the Software, and permit persons to whom the Software is
  16. * furnished to do so, under the terms of the COPYING file.
  17. *
  18. * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
  19. * KIND, either express or implied.
  20. *
  21. ***************************************************************************/
  22. /*
  23. * Source file for all NSS-specific code for the TLS/SSL layer. No code
  24. * but sslgen.c should ever call or use these functions.
  25. */
  26. #include "curl_setup.h"
  27. #ifdef USE_NSS
  28. #include "urldata.h"
  29. #include "sendf.h"
  30. #include "formdata.h" /* for the boundary function */
  31. #include "url.h" /* for the ssl config check function */
  32. #include "connect.h"
  33. #include "strequal.h"
  34. #include "select.h"
  35. #include "sslgen.h"
  36. #include "llist.h"
  37. #define _MPRINTF_REPLACE /* use the internal *printf() functions */
  38. #include <curl/mprintf.h>
  39. #include "nssg.h"
  40. #include <nspr.h>
  41. #include <nss.h>
  42. #include <ssl.h>
  43. #include <sslerr.h>
  44. #include <secerr.h>
  45. #include <secmod.h>
  46. #include <sslproto.h>
  47. #include <prtypes.h>
  48. #include <pk11pub.h>
  49. #include <prio.h>
  50. #include <secitem.h>
  51. #include <secport.h>
  52. #include <certdb.h>
  53. #include <base64.h>
  54. #include <cert.h>
  55. #include <prerror.h>
  56. #include "curl_memory.h"
  57. #include "rawstr.h"
  58. #include "warnless.h"
  59. /* The last #include file should be: */
  60. #include "memdebug.h"
  61. #define SSL_DIR "/etc/pki/nssdb"
  62. /* enough to fit the string "PEM Token #[0|1]" */
  63. #define SLOTSIZE 13
  64. PRFileDesc *PR_ImportTCPSocket(PRInt32 osfd);
  65. PRLock * nss_initlock = NULL;
  66. PRLock * nss_crllock = NULL;
  67. #ifdef HAVE_NSS_INITCONTEXT
  68. NSSInitContext * nss_context = NULL;
  69. #endif
  70. volatile int initialized = 0;
  71. typedef struct {
  72. const char *name;
  73. int num;
  74. } cipher_s;
  75. #define PK11_SETATTRS(_attr, _idx, _type, _val, _len) do { \
  76. CK_ATTRIBUTE *ptr = (_attr) + ((_idx)++); \
  77. ptr->type = (_type); \
  78. ptr->pValue = (_val); \
  79. ptr->ulValueLen = (_len); \
  80. } WHILE_FALSE
  81. #define CERT_NewTempCertificate __CERT_NewTempCertificate
  82. #define NUM_OF_CIPHERS sizeof(cipherlist)/sizeof(cipherlist[0])
  83. static const cipher_s cipherlist[] = {
  84. /* SSL2 cipher suites */
  85. {"rc4", SSL_EN_RC4_128_WITH_MD5},
  86. {"rc4-md5", SSL_EN_RC4_128_WITH_MD5},
  87. {"rc4export", SSL_EN_RC4_128_EXPORT40_WITH_MD5},
  88. {"rc2", SSL_EN_RC2_128_CBC_WITH_MD5},
  89. {"rc2export", SSL_EN_RC2_128_CBC_EXPORT40_WITH_MD5},
  90. {"des", SSL_EN_DES_64_CBC_WITH_MD5},
  91. {"desede3", SSL_EN_DES_192_EDE3_CBC_WITH_MD5},
  92. /* SSL3/TLS cipher suites */
  93. {"rsa_rc4_128_md5", SSL_RSA_WITH_RC4_128_MD5},
  94. {"rsa_rc4_128_sha", SSL_RSA_WITH_RC4_128_SHA},
  95. {"rsa_3des_sha", SSL_RSA_WITH_3DES_EDE_CBC_SHA},
  96. {"rsa_des_sha", SSL_RSA_WITH_DES_CBC_SHA},
  97. {"rsa_rc4_40_md5", SSL_RSA_EXPORT_WITH_RC4_40_MD5},
  98. {"rsa_rc2_40_md5", SSL_RSA_EXPORT_WITH_RC2_CBC_40_MD5},
  99. {"rsa_null_md5", SSL_RSA_WITH_NULL_MD5},
  100. {"rsa_null_sha", SSL_RSA_WITH_NULL_SHA},
  101. {"fips_3des_sha", SSL_RSA_FIPS_WITH_3DES_EDE_CBC_SHA},
  102. {"fips_des_sha", SSL_RSA_FIPS_WITH_DES_CBC_SHA},
  103. {"fortezza", SSL_FORTEZZA_DMS_WITH_FORTEZZA_CBC_SHA},
  104. {"fortezza_rc4_128_sha", SSL_FORTEZZA_DMS_WITH_RC4_128_SHA},
  105. {"fortezza_null", SSL_FORTEZZA_DMS_WITH_NULL_SHA},
  106. /* TLS 1.0: Exportable 56-bit Cipher Suites. */
  107. {"rsa_des_56_sha", TLS_RSA_EXPORT1024_WITH_DES_CBC_SHA},
  108. {"rsa_rc4_56_sha", TLS_RSA_EXPORT1024_WITH_RC4_56_SHA},
  109. /* AES ciphers. */
  110. {"rsa_aes_128_sha", TLS_RSA_WITH_AES_128_CBC_SHA},
  111. {"rsa_aes_256_sha", TLS_RSA_WITH_AES_256_CBC_SHA},
  112. #ifdef NSS_ENABLE_ECC
  113. /* ECC ciphers. */
  114. {"ecdh_ecdsa_null_sha", TLS_ECDH_ECDSA_WITH_NULL_SHA},
  115. {"ecdh_ecdsa_rc4_128_sha", TLS_ECDH_ECDSA_WITH_RC4_128_SHA},
  116. {"ecdh_ecdsa_3des_sha", TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA},
  117. {"ecdh_ecdsa_aes_128_sha", TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA},
  118. {"ecdh_ecdsa_aes_256_sha", TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA},
  119. {"ecdhe_ecdsa_null_sha", TLS_ECDHE_ECDSA_WITH_NULL_SHA},
  120. {"ecdhe_ecdsa_rc4_128_sha", TLS_ECDHE_ECDSA_WITH_RC4_128_SHA},
  121. {"ecdhe_ecdsa_3des_sha", TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA},
  122. {"ecdhe_ecdsa_aes_128_sha", TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA},
  123. {"ecdhe_ecdsa_aes_256_sha", TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA},
  124. {"ecdh_rsa_null_sha", TLS_ECDH_RSA_WITH_NULL_SHA},
  125. {"ecdh_rsa_128_sha", TLS_ECDH_RSA_WITH_RC4_128_SHA},
  126. {"ecdh_rsa_3des_sha", TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA},
  127. {"ecdh_rsa_aes_128_sha", TLS_ECDH_RSA_WITH_AES_128_CBC_SHA},
  128. {"ecdh_rsa_aes_256_sha", TLS_ECDH_RSA_WITH_AES_256_CBC_SHA},
  129. {"echde_rsa_null", TLS_ECDHE_RSA_WITH_NULL_SHA},
  130. {"ecdhe_rsa_rc4_128_sha", TLS_ECDHE_RSA_WITH_RC4_128_SHA},
  131. {"ecdhe_rsa_3des_sha", TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA},
  132. {"ecdhe_rsa_aes_128_sha", TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA},
  133. {"ecdhe_rsa_aes_256_sha", TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA},
  134. {"ecdh_anon_null_sha", TLS_ECDH_anon_WITH_NULL_SHA},
  135. {"ecdh_anon_rc4_128sha", TLS_ECDH_anon_WITH_RC4_128_SHA},
  136. {"ecdh_anon_3des_sha", TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA},
  137. {"ecdh_anon_aes_128_sha", TLS_ECDH_anon_WITH_AES_128_CBC_SHA},
  138. {"ecdh_anon_aes_256_sha", TLS_ECDH_anon_WITH_AES_256_CBC_SHA},
  139. #endif
  140. };
  141. /* following ciphers are new in NSS 3.4 and not enabled by default, therefore
  142. they are enabled explicitly */
  143. static const int enable_ciphers_by_default[] = {
  144. TLS_DHE_DSS_WITH_AES_128_CBC_SHA,
  145. TLS_DHE_DSS_WITH_AES_256_CBC_SHA,
  146. TLS_DHE_RSA_WITH_AES_128_CBC_SHA,
  147. TLS_DHE_RSA_WITH_AES_256_CBC_SHA,
  148. TLS_RSA_WITH_AES_128_CBC_SHA,
  149. TLS_RSA_WITH_AES_256_CBC_SHA,
  150. SSL_NULL_WITH_NULL_NULL
  151. };
  152. static const char* pem_library = "libnsspem.so";
  153. SECMODModule* mod = NULL;
  154. static const char* nss_error_to_name(PRErrorCode code)
  155. {
  156. const char *name = PR_ErrorToName(code);
  157. if(name)
  158. return name;
  159. return "unknown error";
  160. }
  161. static void nss_print_error_message(struct SessionHandle *data, PRUint32 err)
  162. {
  163. failf(data, "%s", PR_ErrorToString(err, PR_LANGUAGE_I_DEFAULT));
  164. }
  165. static SECStatus set_ciphers(struct SessionHandle *data, PRFileDesc * model,
  166. char *cipher_list)
  167. {
  168. unsigned int i;
  169. PRBool cipher_state[NUM_OF_CIPHERS];
  170. PRBool found;
  171. char *cipher;
  172. SECStatus rv;
  173. /* First disable all ciphers. This uses a different max value in case
  174. * NSS adds more ciphers later we don't want them available by
  175. * accident
  176. */
  177. for(i=0; i<SSL_NumImplementedCiphers; i++) {
  178. SSL_CipherPrefSet(model, SSL_ImplementedCiphers[i], SSL_NOT_ALLOWED);
  179. }
  180. /* Set every entry in our list to false */
  181. for(i=0; i<NUM_OF_CIPHERS; i++) {
  182. cipher_state[i] = PR_FALSE;
  183. }
  184. cipher = cipher_list;
  185. while(cipher_list && (cipher_list[0])) {
  186. while((*cipher) && (ISSPACE(*cipher)))
  187. ++cipher;
  188. if((cipher_list = strchr(cipher, ','))) {
  189. *cipher_list++ = '\0';
  190. }
  191. found = PR_FALSE;
  192. for(i=0; i<NUM_OF_CIPHERS; i++) {
  193. if(Curl_raw_equal(cipher, cipherlist[i].name)) {
  194. cipher_state[i] = PR_TRUE;
  195. found = PR_TRUE;
  196. break;
  197. }
  198. }
  199. if(found == PR_FALSE) {
  200. failf(data, "Unknown cipher in list: %s", cipher);
  201. return SECFailure;
  202. }
  203. if(cipher_list) {
  204. cipher = cipher_list;
  205. }
  206. }
  207. /* Finally actually enable the selected ciphers */
  208. for(i=0; i<NUM_OF_CIPHERS; i++) {
  209. rv = SSL_CipherPrefSet(model, cipherlist[i].num, cipher_state[i]);
  210. if(rv != SECSuccess) {
  211. failf(data, "cipher-suite not supported by NSS: %s", cipherlist[i].name);
  212. return SECFailure;
  213. }
  214. }
  215. return SECSuccess;
  216. }
  217. /*
  218. * Get the number of ciphers that are enabled. We use this to determine
  219. * if we need to call NSS_SetDomesticPolicy() to enable the default ciphers.
  220. */
  221. static int num_enabled_ciphers(void)
  222. {
  223. PRInt32 policy = 0;
  224. int count = 0;
  225. unsigned int i;
  226. for(i=0; i<NUM_OF_CIPHERS; i++) {
  227. SSL_CipherPolicyGet(cipherlist[i].num, &policy);
  228. if(policy)
  229. count++;
  230. }
  231. return count;
  232. }
  233. /*
  234. * Determine whether the nickname passed in is a filename that needs to
  235. * be loaded as a PEM or a regular NSS nickname.
  236. *
  237. * returns 1 for a file
  238. * returns 0 for not a file (NSS nickname)
  239. */
  240. static int is_file(const char *filename)
  241. {
  242. struct_stat st;
  243. if(filename == NULL)
  244. return 0;
  245. if(stat(filename, &st) == 0)
  246. if(S_ISREG(st.st_mode))
  247. return 1;
  248. return 0;
  249. }
  250. /* Check if the given string is filename or nickname of a certificate. If the
  251. * given string is recognized as filename, return NULL. If the given string is
  252. * recognized as nickname, return a duplicated string. The returned string
  253. * should be later deallocated using free(). If the OOM failure occurs, we
  254. * return NULL, too.
  255. */
  256. static char* dup_nickname(struct SessionHandle *data, enum dupstring cert_kind)
  257. {
  258. const char *str = data->set.str[cert_kind];
  259. const char *n;
  260. if(!is_file(str))
  261. /* no such file exists, use the string as nickname */
  262. return strdup(str);
  263. /* search the last slash; we require at least one slash in a file name */
  264. n = strrchr(str, '/');
  265. if(!n) {
  266. infof(data, "warning: certificate file name \"%s\" handled as nickname; "
  267. "please use \"./%s\" to force file name\n", str, str);
  268. return strdup(str);
  269. }
  270. /* we'll use the PEM reader to read the certificate from file */
  271. return NULL;
  272. }
  273. /* Call PK11_CreateGenericObject() with the given obj_class and filename. If
  274. * the call succeeds, append the object handle to the list of objects so that
  275. * the object can be destroyed in Curl_nss_close(). */
  276. static CURLcode nss_create_object(struct ssl_connect_data *ssl,
  277. CK_OBJECT_CLASS obj_class,
  278. const char *filename, bool cacert)
  279. {
  280. PK11SlotInfo *slot;
  281. PK11GenericObject *obj;
  282. CK_BBOOL cktrue = CK_TRUE;
  283. CK_BBOOL ckfalse = CK_FALSE;
  284. CK_ATTRIBUTE attrs[/* max count of attributes */ 4];
  285. int attr_cnt = 0;
  286. CURLcode err = (cacert)
  287. ? CURLE_SSL_CACERT_BADFILE
  288. : CURLE_SSL_CERTPROBLEM;
  289. const int slot_id = (cacert) ? 0 : 1;
  290. char *slot_name = aprintf("PEM Token #%d", slot_id);
  291. if(!slot_name)
  292. return CURLE_OUT_OF_MEMORY;
  293. slot = PK11_FindSlotByName(slot_name);
  294. free(slot_name);
  295. if(!slot)
  296. return err;
  297. PK11_SETATTRS(attrs, attr_cnt, CKA_CLASS, &obj_class, sizeof(obj_class));
  298. PK11_SETATTRS(attrs, attr_cnt, CKA_TOKEN, &cktrue, sizeof(CK_BBOOL));
  299. PK11_SETATTRS(attrs, attr_cnt, CKA_LABEL, (unsigned char *)filename,
  300. strlen(filename) + 1);
  301. if(CKO_CERTIFICATE == obj_class) {
  302. CK_BBOOL *pval = (cacert) ? (&cktrue) : (&ckfalse);
  303. PK11_SETATTRS(attrs, attr_cnt, CKA_TRUST, pval, sizeof(*pval));
  304. }
  305. obj = PK11_CreateGenericObject(slot, attrs, attr_cnt, PR_FALSE);
  306. PK11_FreeSlot(slot);
  307. if(!obj)
  308. return err;
  309. if(!Curl_llist_insert_next(ssl->obj_list, ssl->obj_list->tail, obj)) {
  310. PK11_DestroyGenericObject(obj);
  311. return CURLE_OUT_OF_MEMORY;
  312. }
  313. if(!cacert && CKO_CERTIFICATE == obj_class)
  314. /* store reference to a client certificate */
  315. ssl->obj_clicert = obj;
  316. return CURLE_OK;
  317. }
  318. /* Destroy the NSS object whose handle is given by ptr. This function is
  319. * a callback of Curl_llist_alloc() used by Curl_llist_destroy() to destroy
  320. * NSS objects in Curl_nss_close() */
  321. static void nss_destroy_object(void *user, void *ptr)
  322. {
  323. PK11GenericObject *obj = (PK11GenericObject *)ptr;
  324. (void) user;
  325. PK11_DestroyGenericObject(obj);
  326. }
  327. static CURLcode nss_load_cert(struct ssl_connect_data *ssl,
  328. const char *filename, PRBool cacert)
  329. {
  330. CURLcode err = (cacert)
  331. ? CURLE_SSL_CACERT_BADFILE
  332. : CURLE_SSL_CERTPROBLEM;
  333. /* libnsspem.so leaks memory if the requested file does not exist. For more
  334. * details, go to <https://bugzilla.redhat.com/734760>. */
  335. if(is_file(filename))
  336. err = nss_create_object(ssl, CKO_CERTIFICATE, filename, cacert);
  337. if(CURLE_OK == err && !cacert) {
  338. /* we have successfully loaded a client certificate */
  339. CERTCertificate *cert;
  340. char *nickname = NULL;
  341. char *n = strrchr(filename, '/');
  342. if(n)
  343. n++;
  344. /* The following undocumented magic helps to avoid a SIGSEGV on call
  345. * of PK11_ReadRawAttribute() from SelectClientCert() when using an
  346. * immature version of libnsspem.so. For more details, go to
  347. * <https://bugzilla.redhat.com/733685>. */
  348. nickname = aprintf("PEM Token #1:%s", n);
  349. if(nickname) {
  350. cert = PK11_FindCertFromNickname(nickname, NULL);
  351. if(cert)
  352. CERT_DestroyCertificate(cert);
  353. free(nickname);
  354. }
  355. }
  356. return err;
  357. }
  358. /* add given CRL to cache if it is not already there */
  359. static SECStatus nss_cache_crl(SECItem *crlDER)
  360. {
  361. CERTCertDBHandle *db = CERT_GetDefaultCertDB();
  362. CERTSignedCrl *crl = SEC_FindCrlByDERCert(db, crlDER, 0);
  363. if(crl) {
  364. /* CRL already cached */
  365. SEC_DestroyCrl(crl);
  366. SECITEM_FreeItem(crlDER, PR_FALSE);
  367. return SECSuccess;
  368. }
  369. /* acquire lock before call of CERT_CacheCRL() */
  370. PR_Lock(nss_crllock);
  371. if(SECSuccess != CERT_CacheCRL(db, crlDER)) {
  372. /* unable to cache CRL */
  373. PR_Unlock(nss_crllock);
  374. SECITEM_FreeItem(crlDER, PR_FALSE);
  375. return SECFailure;
  376. }
  377. /* we need to clear session cache, so that the CRL could take effect */
  378. SSL_ClearSessionCache();
  379. PR_Unlock(nss_crllock);
  380. return SECSuccess;
  381. }
  382. static SECStatus nss_load_crl(const char* crlfilename)
  383. {
  384. PRFileDesc *infile;
  385. PRFileInfo info;
  386. SECItem filedata = { 0, NULL, 0 };
  387. SECItem crlDER = { 0, NULL, 0 };
  388. char *body;
  389. infile = PR_Open(crlfilename, PR_RDONLY, 0);
  390. if(!infile)
  391. return SECFailure;
  392. if(PR_SUCCESS != PR_GetOpenFileInfo(infile, &info))
  393. goto fail;
  394. if(!SECITEM_AllocItem(NULL, &filedata, info.size + /* zero ended */ 1))
  395. goto fail;
  396. if(info.size != PR_Read(infile, filedata.data, info.size))
  397. goto fail;
  398. /* place a trailing zero right after the visible data */
  399. body = (char*)filedata.data;
  400. body[--filedata.len] = '\0';
  401. body = strstr(body, "-----BEGIN");
  402. if(body) {
  403. /* assume ASCII */
  404. char *trailer;
  405. char *begin = PORT_Strchr(body, '\n');
  406. if(!begin)
  407. begin = PORT_Strchr(body, '\r');
  408. if(!begin)
  409. goto fail;
  410. trailer = strstr(++begin, "-----END");
  411. if(!trailer)
  412. goto fail;
  413. /* retrieve DER from ASCII */
  414. *trailer = '\0';
  415. if(ATOB_ConvertAsciiToItem(&crlDER, begin))
  416. goto fail;
  417. SECITEM_FreeItem(&filedata, PR_FALSE);
  418. }
  419. else
  420. /* assume DER */
  421. crlDER = filedata;
  422. PR_Close(infile);
  423. return nss_cache_crl(&crlDER);
  424. fail:
  425. PR_Close(infile);
  426. SECITEM_FreeItem(&filedata, PR_FALSE);
  427. return SECFailure;
  428. }
  429. static CURLcode nss_load_key(struct connectdata *conn, int sockindex,
  430. char *key_file)
  431. {
  432. PK11SlotInfo *slot;
  433. SECStatus status;
  434. CURLcode rv;
  435. struct ssl_connect_data *ssl = conn->ssl;
  436. (void)sockindex; /* unused */
  437. rv = nss_create_object(ssl, CKO_PRIVATE_KEY, key_file, FALSE);
  438. if(CURLE_OK != rv) {
  439. PR_SetError(SEC_ERROR_BAD_KEY, 0);
  440. return rv;
  441. }
  442. slot = PK11_FindSlotByName("PEM Token #1");
  443. if(!slot)
  444. return CURLE_SSL_CERTPROBLEM;
  445. /* This will force the token to be seen as re-inserted */
  446. SECMOD_WaitForAnyTokenEvent(mod, 0, 0);
  447. PK11_IsPresent(slot);
  448. status = PK11_Authenticate(slot, PR_TRUE,
  449. conn->data->set.str[STRING_KEY_PASSWD]);
  450. PK11_FreeSlot(slot);
  451. return (SECSuccess == status)
  452. ? CURLE_OK
  453. : CURLE_SSL_CERTPROBLEM;
  454. }
  455. static int display_error(struct connectdata *conn, PRInt32 err,
  456. const char *filename)
  457. {
  458. switch(err) {
  459. case SEC_ERROR_BAD_PASSWORD:
  460. failf(conn->data, "Unable to load client key: Incorrect password");
  461. return 1;
  462. case SEC_ERROR_UNKNOWN_CERT:
  463. failf(conn->data, "Unable to load certificate %s", filename);
  464. return 1;
  465. default:
  466. break;
  467. }
  468. return 0; /* The caller will print a generic error */
  469. }
  470. static CURLcode cert_stuff(struct connectdata *conn, int sockindex,
  471. char *cert_file, char *key_file)
  472. {
  473. struct SessionHandle *data = conn->data;
  474. CURLcode rv;
  475. if(cert_file) {
  476. rv = nss_load_cert(&conn->ssl[sockindex], cert_file, PR_FALSE);
  477. if(CURLE_OK != rv) {
  478. const PRErrorCode err = PR_GetError();
  479. if(!display_error(conn, err, cert_file)) {
  480. const char *err_name = nss_error_to_name(err);
  481. failf(data, "unable to load client cert: %d (%s)", err, err_name);
  482. }
  483. return rv;
  484. }
  485. }
  486. if(key_file || (is_file(cert_file))) {
  487. if(key_file)
  488. rv = nss_load_key(conn, sockindex, key_file);
  489. else
  490. /* In case the cert file also has the key */
  491. rv = nss_load_key(conn, sockindex, cert_file);
  492. if(CURLE_OK != rv) {
  493. const PRErrorCode err = PR_GetError();
  494. if(!display_error(conn, err, key_file)) {
  495. const char *err_name = nss_error_to_name(err);
  496. failf(data, "unable to load client key: %d (%s)", err, err_name);
  497. }
  498. return rv;
  499. }
  500. }
  501. return CURLE_OK;
  502. }
  503. static char * nss_get_password(PK11SlotInfo * slot, PRBool retry, void *arg)
  504. {
  505. (void)slot; /* unused */
  506. if(retry || NULL == arg)
  507. return NULL;
  508. else
  509. return (char *)PORT_Strdup((char *)arg);
  510. }
  511. /* bypass the default SSL_AuthCertificate() hook in case we do not want to
  512. * verify peer */
  513. static SECStatus nss_auth_cert_hook(void *arg, PRFileDesc *fd, PRBool checksig,
  514. PRBool isServer)
  515. {
  516. struct connectdata *conn = (struct connectdata *)arg;
  517. if(!conn->data->set.ssl.verifypeer) {
  518. infof(conn->data, "skipping SSL peer certificate verification\n");
  519. return SECSuccess;
  520. }
  521. return SSL_AuthCertificate(CERT_GetDefaultCertDB(), fd, checksig, isServer);
  522. }
  523. /**
  524. * Inform the application that the handshake is complete.
  525. */
  526. static void HandshakeCallback(PRFileDesc *sock, void *arg)
  527. {
  528. (void)sock;
  529. (void)arg;
  530. }
  531. static void display_cert_info(struct SessionHandle *data,
  532. CERTCertificate *cert)
  533. {
  534. char *subject, *issuer, *common_name;
  535. PRExplodedTime printableTime;
  536. char timeString[256];
  537. PRTime notBefore, notAfter;
  538. subject = CERT_NameToAscii(&cert->subject);
  539. issuer = CERT_NameToAscii(&cert->issuer);
  540. common_name = CERT_GetCommonName(&cert->subject);
  541. infof(data, "\tsubject: %s\n", subject);
  542. CERT_GetCertTimes(cert, &notBefore, &notAfter);
  543. PR_ExplodeTime(notBefore, PR_GMTParameters, &printableTime);
  544. PR_FormatTime(timeString, 256, "%b %d %H:%M:%S %Y GMT", &printableTime);
  545. infof(data, "\tstart date: %s\n", timeString);
  546. PR_ExplodeTime(notAfter, PR_GMTParameters, &printableTime);
  547. PR_FormatTime(timeString, 256, "%b %d %H:%M:%S %Y GMT", &printableTime);
  548. infof(data, "\texpire date: %s\n", timeString);
  549. infof(data, "\tcommon name: %s\n", common_name);
  550. infof(data, "\tissuer: %s\n", issuer);
  551. PR_Free(subject);
  552. PR_Free(issuer);
  553. PR_Free(common_name);
  554. }
  555. static void display_conn_info(struct connectdata *conn, PRFileDesc *sock)
  556. {
  557. SSLChannelInfo channel;
  558. SSLCipherSuiteInfo suite;
  559. CERTCertificate *cert;
  560. if(SSL_GetChannelInfo(sock, &channel, sizeof channel) ==
  561. SECSuccess && channel.length == sizeof channel &&
  562. channel.cipherSuite) {
  563. if(SSL_GetCipherSuiteInfo(channel.cipherSuite,
  564. &suite, sizeof suite) == SECSuccess) {
  565. infof(conn->data, "SSL connection using %s\n", suite.cipherSuiteName);
  566. }
  567. }
  568. infof(conn->data, "Server certificate:\n");
  569. cert = SSL_PeerCertificate(sock);
  570. display_cert_info(conn->data, cert);
  571. CERT_DestroyCertificate(cert);
  572. return;
  573. }
  574. static SECStatus BadCertHandler(void *arg, PRFileDesc *sock)
  575. {
  576. struct connectdata *conn = (struct connectdata *)arg;
  577. struct SessionHandle *data = conn->data;
  578. PRErrorCode err = PR_GetError();
  579. CERTCertificate *cert;
  580. /* remember the cert verification result */
  581. data->set.ssl.certverifyresult = err;
  582. if(err == SSL_ERROR_BAD_CERT_DOMAIN && !data->set.ssl.verifyhost)
  583. /* we are asked not to verify the host name */
  584. return SECSuccess;
  585. /* print only info about the cert, the error is printed off the callback */
  586. cert = SSL_PeerCertificate(sock);
  587. if(cert) {
  588. infof(data, "Server certificate:\n");
  589. display_cert_info(data, cert);
  590. CERT_DestroyCertificate(cert);
  591. }
  592. return SECFailure;
  593. }
  594. /**
  595. *
  596. * Check that the Peer certificate's issuer certificate matches the one found
  597. * by issuer_nickname. This is not exactly the way OpenSSL and GNU TLS do the
  598. * issuer check, so we provide comments that mimic the OpenSSL
  599. * X509_check_issued function (in x509v3/v3_purp.c)
  600. */
  601. static SECStatus check_issuer_cert(PRFileDesc *sock,
  602. char *issuer_nickname)
  603. {
  604. CERTCertificate *cert,*cert_issuer,*issuer;
  605. SECStatus res=SECSuccess;
  606. void *proto_win = NULL;
  607. /*
  608. PRArenaPool *tmpArena = NULL;
  609. CERTAuthKeyID *authorityKeyID = NULL;
  610. SECITEM *caname = NULL;
  611. */
  612. cert = SSL_PeerCertificate(sock);
  613. cert_issuer = CERT_FindCertIssuer(cert,PR_Now(),certUsageObjectSigner);
  614. proto_win = SSL_RevealPinArg(sock);
  615. issuer = PK11_FindCertFromNickname(issuer_nickname, proto_win);
  616. if((!cert_issuer) || (!issuer))
  617. res = SECFailure;
  618. else if(SECITEM_CompareItem(&cert_issuer->derCert,
  619. &issuer->derCert)!=SECEqual)
  620. res = SECFailure;
  621. CERT_DestroyCertificate(cert);
  622. CERT_DestroyCertificate(issuer);
  623. CERT_DestroyCertificate(cert_issuer);
  624. return res;
  625. }
  626. /**
  627. *
  628. * Callback to pick the SSL client certificate.
  629. */
  630. static SECStatus SelectClientCert(void *arg, PRFileDesc *sock,
  631. struct CERTDistNamesStr *caNames,
  632. struct CERTCertificateStr **pRetCert,
  633. struct SECKEYPrivateKeyStr **pRetKey)
  634. {
  635. struct ssl_connect_data *connssl = (struct ssl_connect_data *)arg;
  636. struct SessionHandle *data = connssl->data;
  637. const char *nickname = connssl->client_nickname;
  638. if(connssl->obj_clicert) {
  639. /* use the cert/key provided by PEM reader */
  640. static const char pem_slotname[] = "PEM Token #1";
  641. SECItem cert_der = { 0, NULL, 0 };
  642. void *proto_win = SSL_RevealPinArg(sock);
  643. struct CERTCertificateStr *cert;
  644. struct SECKEYPrivateKeyStr *key;
  645. PK11SlotInfo *slot = PK11_FindSlotByName(pem_slotname);
  646. if(NULL == slot) {
  647. failf(data, "NSS: PK11 slot not found: %s", pem_slotname);
  648. return SECFailure;
  649. }
  650. if(PK11_ReadRawAttribute(PK11_TypeGeneric, connssl->obj_clicert, CKA_VALUE,
  651. &cert_der) != SECSuccess) {
  652. failf(data, "NSS: CKA_VALUE not found in PK11 generic object");
  653. PK11_FreeSlot(slot);
  654. return SECFailure;
  655. }
  656. cert = PK11_FindCertFromDERCertItem(slot, &cert_der, proto_win);
  657. SECITEM_FreeItem(&cert_der, PR_FALSE);
  658. if(NULL == cert) {
  659. failf(data, "NSS: client certificate from file not found");
  660. PK11_FreeSlot(slot);
  661. return SECFailure;
  662. }
  663. key = PK11_FindPrivateKeyFromCert(slot, cert, NULL);
  664. PK11_FreeSlot(slot);
  665. if(NULL == key) {
  666. failf(data, "NSS: private key from file not found");
  667. CERT_DestroyCertificate(cert);
  668. return SECFailure;
  669. }
  670. infof(data, "NSS: client certificate from file\n");
  671. display_cert_info(data, cert);
  672. *pRetCert = cert;
  673. *pRetKey = key;
  674. return SECSuccess;
  675. }
  676. /* use the default NSS hook */
  677. if(SECSuccess != NSS_GetClientAuthData((void *)nickname, sock, caNames,
  678. pRetCert, pRetKey)
  679. || NULL == *pRetCert) {
  680. if(NULL == nickname)
  681. failf(data, "NSS: client certificate not found (nickname not "
  682. "specified)");
  683. else
  684. failf(data, "NSS: client certificate not found: %s", nickname);
  685. return SECFailure;
  686. }
  687. /* get certificate nickname if any */
  688. nickname = (*pRetCert)->nickname;
  689. if(NULL == nickname)
  690. nickname = "[unknown]";
  691. if(NULL == *pRetKey) {
  692. failf(data, "NSS: private key not found for certificate: %s", nickname);
  693. return SECFailure;
  694. }
  695. infof(data, "NSS: using client certificate: %s\n", nickname);
  696. display_cert_info(data, *pRetCert);
  697. return SECSuccess;
  698. }
  699. /* This function is supposed to decide, which error codes should be used
  700. * to conclude server is TLS intolerant.
  701. *
  702. * taken from xulrunner - nsNSSIOLayer.cpp
  703. */
  704. static PRBool
  705. isTLSIntoleranceError(PRInt32 err)
  706. {
  707. switch (err) {
  708. case SSL_ERROR_BAD_MAC_ALERT:
  709. case SSL_ERROR_BAD_MAC_READ:
  710. case SSL_ERROR_HANDSHAKE_FAILURE_ALERT:
  711. case SSL_ERROR_HANDSHAKE_UNEXPECTED_ALERT:
  712. case SSL_ERROR_CLIENT_KEY_EXCHANGE_FAILURE:
  713. case SSL_ERROR_ILLEGAL_PARAMETER_ALERT:
  714. case SSL_ERROR_NO_CYPHER_OVERLAP:
  715. case SSL_ERROR_BAD_SERVER:
  716. case SSL_ERROR_BAD_BLOCK_PADDING:
  717. case SSL_ERROR_UNSUPPORTED_VERSION:
  718. case SSL_ERROR_PROTOCOL_VERSION_ALERT:
  719. case SSL_ERROR_RX_MALFORMED_FINISHED:
  720. case SSL_ERROR_BAD_HANDSHAKE_HASH_VALUE:
  721. case SSL_ERROR_DECODE_ERROR_ALERT:
  722. case SSL_ERROR_RX_UNKNOWN_ALERT:
  723. return PR_TRUE;
  724. default:
  725. return PR_FALSE;
  726. }
  727. }
  728. static CURLcode nss_init_core(struct SessionHandle *data, const char *cert_dir)
  729. {
  730. #ifdef HAVE_NSS_INITCONTEXT
  731. NSSInitParameters initparams;
  732. if(nss_context != NULL)
  733. return CURLE_OK;
  734. memset((void *) &initparams, '\0', sizeof(initparams));
  735. initparams.length = sizeof(initparams);
  736. #else /* HAVE_NSS_INITCONTEXT */
  737. SECStatus rv;
  738. if(NSS_IsInitialized())
  739. return CURLE_OK;
  740. #endif
  741. if(cert_dir) {
  742. const bool use_sql = NSS_VersionCheck("3.12.0");
  743. char *certpath = aprintf("%s%s", use_sql ? "sql:" : "", cert_dir);
  744. if(!certpath)
  745. return CURLE_OUT_OF_MEMORY;
  746. infof(data, "Initializing NSS with certpath: %s\n", certpath);
  747. #ifdef HAVE_NSS_INITCONTEXT
  748. nss_context = NSS_InitContext(certpath, "", "", "", &initparams,
  749. NSS_INIT_READONLY | NSS_INIT_PK11RELOAD);
  750. free(certpath);
  751. if(nss_context != NULL)
  752. return CURLE_OK;
  753. #else /* HAVE_NSS_INITCONTEXT */
  754. rv = NSS_Initialize(certpath, "", "", "", NSS_INIT_READONLY);
  755. free(certpath);
  756. if(rv == SECSuccess)
  757. return CURLE_OK;
  758. #endif
  759. infof(data, "Unable to initialize NSS database\n");
  760. }
  761. infof(data, "Initializing NSS with certpath: none\n");
  762. #ifdef HAVE_NSS_INITCONTEXT
  763. nss_context = NSS_InitContext("", "", "", "", &initparams, NSS_INIT_READONLY
  764. | NSS_INIT_NOCERTDB | NSS_INIT_NOMODDB | NSS_INIT_FORCEOPEN
  765. | NSS_INIT_NOROOTINIT | NSS_INIT_OPTIMIZESPACE | NSS_INIT_PK11RELOAD);
  766. if(nss_context != NULL)
  767. return CURLE_OK;
  768. #else /* HAVE_NSS_INITCONTEXT */
  769. if(NSS_NoDB_Init(NULL) == SECSuccess)
  770. return CURLE_OK;
  771. #endif
  772. infof(data, "Unable to initialize NSS\n");
  773. return CURLE_SSL_CACERT_BADFILE;
  774. }
  775. static CURLcode nss_init(struct SessionHandle *data)
  776. {
  777. char *cert_dir;
  778. struct_stat st;
  779. CURLcode rv;
  780. if(initialized)
  781. return CURLE_OK;
  782. /* First we check if $SSL_DIR points to a valid dir */
  783. cert_dir = getenv("SSL_DIR");
  784. if(cert_dir) {
  785. if((stat(cert_dir, &st) != 0) ||
  786. (!S_ISDIR(st.st_mode))) {
  787. cert_dir = NULL;
  788. }
  789. }
  790. /* Now we check if the default location is a valid dir */
  791. if(!cert_dir) {
  792. if((stat(SSL_DIR, &st) == 0) &&
  793. (S_ISDIR(st.st_mode))) {
  794. cert_dir = (char *)SSL_DIR;
  795. }
  796. }
  797. rv = nss_init_core(data, cert_dir);
  798. if(rv)
  799. return rv;
  800. if(num_enabled_ciphers() == 0)
  801. NSS_SetDomesticPolicy();
  802. initialized = 1;
  803. return CURLE_OK;
  804. }
  805. /**
  806. * Global SSL init
  807. *
  808. * @retval 0 error initializing SSL
  809. * @retval 1 SSL initialized successfully
  810. */
  811. int Curl_nss_init(void)
  812. {
  813. /* curl_global_init() is not thread-safe so this test is ok */
  814. if(nss_initlock == NULL) {
  815. PR_Init(PR_USER_THREAD, PR_PRIORITY_NORMAL, 256);
  816. nss_initlock = PR_NewLock();
  817. nss_crllock = PR_NewLock();
  818. }
  819. /* We will actually initialize NSS later */
  820. return 1;
  821. }
  822. CURLcode Curl_nss_force_init(struct SessionHandle *data)
  823. {
  824. CURLcode rv;
  825. if(!nss_initlock) {
  826. failf(data,
  827. "unable to initialize NSS, curl_global_init() should have been "
  828. "called with CURL_GLOBAL_SSL or CURL_GLOBAL_ALL");
  829. return CURLE_FAILED_INIT;
  830. }
  831. PR_Lock(nss_initlock);
  832. rv = nss_init(data);
  833. PR_Unlock(nss_initlock);
  834. return rv;
  835. }
  836. /* Global cleanup */
  837. void Curl_nss_cleanup(void)
  838. {
  839. /* This function isn't required to be threadsafe and this is only done
  840. * as a safety feature.
  841. */
  842. PR_Lock(nss_initlock);
  843. if(initialized) {
  844. /* Free references to client certificates held in the SSL session cache.
  845. * Omitting this hampers destruction of the security module owning
  846. * the certificates. */
  847. SSL_ClearSessionCache();
  848. if(mod && SECSuccess == SECMOD_UnloadUserModule(mod)) {
  849. SECMOD_DestroyModule(mod);
  850. mod = NULL;
  851. }
  852. #ifdef HAVE_NSS_INITCONTEXT
  853. NSS_ShutdownContext(nss_context);
  854. nss_context = NULL;
  855. #else /* HAVE_NSS_INITCONTEXT */
  856. NSS_Shutdown();
  857. #endif
  858. }
  859. PR_Unlock(nss_initlock);
  860. PR_DestroyLock(nss_initlock);
  861. PR_DestroyLock(nss_crllock);
  862. nss_initlock = NULL;
  863. initialized = 0;
  864. }
  865. /*
  866. * This function uses SSL_peek to determine connection status.
  867. *
  868. * Return codes:
  869. * 1 means the connection is still in place
  870. * 0 means the connection has been closed
  871. * -1 means the connection status is unknown
  872. */
  873. int
  874. Curl_nss_check_cxn(struct connectdata *conn)
  875. {
  876. int rc;
  877. char buf;
  878. rc =
  879. PR_Recv(conn->ssl[FIRSTSOCKET].handle, (void *)&buf, 1, PR_MSG_PEEK,
  880. PR_SecondsToInterval(1));
  881. if(rc > 0)
  882. return 1; /* connection still in place */
  883. if(rc == 0)
  884. return 0; /* connection has been closed */
  885. return -1; /* connection status unknown */
  886. }
  887. /*
  888. * This function is called when an SSL connection is closed.
  889. */
  890. void Curl_nss_close(struct connectdata *conn, int sockindex)
  891. {
  892. struct ssl_connect_data *connssl = &conn->ssl[sockindex];
  893. if(connssl->handle) {
  894. /* NSS closes the socket we previously handed to it, so we must mark it
  895. as closed to avoid double close */
  896. fake_sclose(conn->sock[sockindex]);
  897. conn->sock[sockindex] = CURL_SOCKET_BAD;
  898. if((connssl->client_nickname != NULL) || (connssl->obj_clicert != NULL))
  899. /* A server might require different authentication based on the
  900. * particular path being requested by the client. To support this
  901. * scenario, we must ensure that a connection will never reuse the
  902. * authentication data from a previous connection. */
  903. SSL_InvalidateSession(connssl->handle);
  904. if(connssl->client_nickname != NULL) {
  905. free(connssl->client_nickname);
  906. connssl->client_nickname = NULL;
  907. }
  908. /* destroy all NSS objects in order to avoid failure of NSS shutdown */
  909. Curl_llist_destroy(connssl->obj_list, NULL);
  910. connssl->obj_list = NULL;
  911. connssl->obj_clicert = NULL;
  912. PR_Close(connssl->handle);
  913. connssl->handle = NULL;
  914. }
  915. }
  916. /*
  917. * This function is called when the 'data' struct is going away. Close
  918. * down everything and free all resources!
  919. */
  920. int Curl_nss_close_all(struct SessionHandle *data)
  921. {
  922. (void)data;
  923. return 0;
  924. }
  925. /* return true if NSS can provide error code (and possibly msg) for the
  926. error */
  927. static bool is_nss_error(CURLcode err)
  928. {
  929. switch(err) {
  930. case CURLE_PEER_FAILED_VERIFICATION:
  931. case CURLE_SSL_CACERT:
  932. case CURLE_SSL_CERTPROBLEM:
  933. case CURLE_SSL_CONNECT_ERROR:
  934. case CURLE_SSL_ISSUER_ERROR:
  935. return true;
  936. default:
  937. return false;
  938. }
  939. }
  940. /* return true if the given error code is related to a client certificate */
  941. static bool is_cc_error(PRInt32 err)
  942. {
  943. switch(err) {
  944. case SSL_ERROR_BAD_CERT_ALERT:
  945. case SSL_ERROR_EXPIRED_CERT_ALERT:
  946. case SSL_ERROR_REVOKED_CERT_ALERT:
  947. return true;
  948. default:
  949. return false;
  950. }
  951. }
  952. static Curl_recv nss_recv;
  953. static Curl_send nss_send;
  954. static CURLcode nss_load_ca_certificates(struct connectdata *conn,
  955. int sockindex)
  956. {
  957. struct SessionHandle *data = conn->data;
  958. const char *cafile = data->set.ssl.CAfile;
  959. const char *capath = data->set.ssl.CApath;
  960. if(cafile) {
  961. CURLcode rv = nss_load_cert(&conn->ssl[sockindex], cafile, PR_TRUE);
  962. if(CURLE_OK != rv)
  963. return rv;
  964. }
  965. if(capath) {
  966. struct_stat st;
  967. if(stat(capath, &st) == -1)
  968. return CURLE_SSL_CACERT_BADFILE;
  969. if(S_ISDIR(st.st_mode)) {
  970. PRDirEntry *entry;
  971. PRDir *dir = PR_OpenDir(capath);
  972. if(!dir)
  973. return CURLE_SSL_CACERT_BADFILE;
  974. while((entry = PR_ReadDir(dir, PR_SKIP_BOTH | PR_SKIP_HIDDEN))) {
  975. char *fullpath = aprintf("%s/%s", capath, entry->name);
  976. if(!fullpath) {
  977. PR_CloseDir(dir);
  978. return CURLE_OUT_OF_MEMORY;
  979. }
  980. if(CURLE_OK != nss_load_cert(&conn->ssl[sockindex], fullpath, PR_TRUE))
  981. /* This is purposefully tolerant of errors so non-PEM files can
  982. * be in the same directory */
  983. infof(data, "failed to load '%s' from CURLOPT_CAPATH\n", fullpath);
  984. free(fullpath);
  985. }
  986. PR_CloseDir(dir);
  987. }
  988. else
  989. infof(data, "warning: CURLOPT_CAPATH not a directory (%s)\n", capath);
  990. }
  991. infof(data, " CAfile: %s\n CApath: %s\n",
  992. cafile ? cafile : "none",
  993. capath ? capath : "none");
  994. return CURLE_OK;
  995. }
  996. CURLcode Curl_nss_connect(struct connectdata *conn, int sockindex)
  997. {
  998. PRErrorCode err = 0;
  999. PRFileDesc *model = NULL;
  1000. PRBool ssl2 = PR_FALSE;
  1001. PRBool ssl3 = PR_FALSE;
  1002. PRBool tlsv1 = PR_FALSE;
  1003. PRBool ssl_no_cache;
  1004. PRBool ssl_cbc_random_iv;
  1005. struct SessionHandle *data = conn->data;
  1006. curl_socket_t sockfd = conn->sock[sockindex];
  1007. struct ssl_connect_data *connssl = &conn->ssl[sockindex];
  1008. CURLcode curlerr;
  1009. const int *cipher_to_enable;
  1010. PRSocketOptionData sock_opt;
  1011. long time_left;
  1012. PRUint32 timeout;
  1013. if(connssl->state == ssl_connection_complete)
  1014. return CURLE_OK;
  1015. connssl->data = data;
  1016. /* list of all NSS objects we need to destroy in Curl_nss_close() */
  1017. connssl->obj_list = Curl_llist_alloc(nss_destroy_object);
  1018. if(!connssl->obj_list)
  1019. return CURLE_OUT_OF_MEMORY;
  1020. /* FIXME. NSS doesn't support multiple databases open at the same time. */
  1021. PR_Lock(nss_initlock);
  1022. curlerr = nss_init(conn->data);
  1023. if(CURLE_OK != curlerr) {
  1024. PR_Unlock(nss_initlock);
  1025. goto error;
  1026. }
  1027. curlerr = CURLE_SSL_CONNECT_ERROR;
  1028. if(!mod) {
  1029. char *configstring = aprintf("library=%s name=PEM", pem_library);
  1030. if(!configstring) {
  1031. PR_Unlock(nss_initlock);
  1032. goto error;
  1033. }
  1034. mod = SECMOD_LoadUserModule(configstring, NULL, PR_FALSE);
  1035. free(configstring);
  1036. if(!mod || !mod->loaded) {
  1037. if(mod) {
  1038. SECMOD_DestroyModule(mod);
  1039. mod = NULL;
  1040. }
  1041. infof(data, "WARNING: failed to load NSS PEM library %s. Using "
  1042. "OpenSSL PEM certificates will not work.\n", pem_library);
  1043. }
  1044. }
  1045. PK11_SetPasswordFunc(nss_get_password);
  1046. PR_Unlock(nss_initlock);
  1047. model = PR_NewTCPSocket();
  1048. if(!model)
  1049. goto error;
  1050. model = SSL_ImportFD(NULL, model);
  1051. if(SSL_OptionSet(model, SSL_SECURITY, PR_TRUE) != SECSuccess)
  1052. goto error;
  1053. if(SSL_OptionSet(model, SSL_HANDSHAKE_AS_SERVER, PR_FALSE) != SECSuccess)
  1054. goto error;
  1055. if(SSL_OptionSet(model, SSL_HANDSHAKE_AS_CLIENT, PR_TRUE) != SECSuccess)
  1056. goto error;
  1057. /* do not use SSL cache if we are not going to verify peer */
  1058. ssl_no_cache = (data->set.ssl.verifypeer) ? PR_FALSE : PR_TRUE;
  1059. if(SSL_OptionSet(model, SSL_NO_CACHE, ssl_no_cache) != SECSuccess)
  1060. goto error;
  1061. switch (data->set.ssl.version) {
  1062. default:
  1063. case CURL_SSLVERSION_DEFAULT:
  1064. ssl3 = PR_TRUE;
  1065. if(data->state.ssl_connect_retry)
  1066. infof(data, "TLS disabled due to previous handshake failure\n");
  1067. else
  1068. tlsv1 = PR_TRUE;
  1069. break;
  1070. case CURL_SSLVERSION_TLSv1:
  1071. tlsv1 = PR_TRUE;
  1072. break;
  1073. case CURL_SSLVERSION_SSLv2:
  1074. ssl2 = PR_TRUE;
  1075. break;
  1076. case CURL_SSLVERSION_SSLv3:
  1077. ssl3 = PR_TRUE;
  1078. break;
  1079. }
  1080. if(SSL_OptionSet(model, SSL_ENABLE_SSL2, ssl2) != SECSuccess)
  1081. goto error;
  1082. if(SSL_OptionSet(model, SSL_ENABLE_SSL3, ssl3) != SECSuccess)
  1083. goto error;
  1084. if(SSL_OptionSet(model, SSL_ENABLE_TLS, tlsv1) != SECSuccess)
  1085. goto error;
  1086. if(SSL_OptionSet(model, SSL_V2_COMPATIBLE_HELLO, ssl2) != SECSuccess)
  1087. goto error;
  1088. ssl_cbc_random_iv = !data->set.ssl_enable_beast;
  1089. #ifdef SSL_CBC_RANDOM_IV
  1090. /* unless the user explicitly asks to allow the protocol vulnerability, we
  1091. use the work-around */
  1092. if(SSL_OptionSet(model, SSL_CBC_RANDOM_IV, ssl_cbc_random_iv) != SECSuccess)
  1093. infof(data, "warning: failed to set SSL_CBC_RANDOM_IV = %d\n",
  1094. ssl_cbc_random_iv);
  1095. #else
  1096. if(ssl_cbc_random_iv)
  1097. infof(data, "warning: support for SSL_CBC_RANDOM_IV not compiled in\n");
  1098. #endif
  1099. /* reset the flag to avoid an infinite loop */
  1100. data->state.ssl_connect_retry = FALSE;
  1101. /* enable all ciphers from enable_ciphers_by_default */
  1102. cipher_to_enable = enable_ciphers_by_default;
  1103. while(SSL_NULL_WITH_NULL_NULL != *cipher_to_enable) {
  1104. if(SSL_CipherPrefSet(model, *cipher_to_enable, PR_TRUE) != SECSuccess) {
  1105. curlerr = CURLE_SSL_CIPHER;
  1106. goto error;
  1107. }
  1108. cipher_to_enable++;
  1109. }
  1110. if(data->set.ssl.cipher_list) {
  1111. if(set_ciphers(data, model, data->set.ssl.cipher_list) != SECSuccess) {
  1112. curlerr = CURLE_SSL_CIPHER;
  1113. goto error;
  1114. }
  1115. }
  1116. if(!data->set.ssl.verifypeer && data->set.ssl.verifyhost)
  1117. infof(data, "warning: ignoring value of ssl.verifyhost\n");
  1118. /* bypass the default SSL_AuthCertificate() hook in case we do not want to
  1119. * verify peer */
  1120. if(SSL_AuthCertificateHook(model, nss_auth_cert_hook, conn) != SECSuccess)
  1121. goto error;
  1122. data->set.ssl.certverifyresult=0; /* not checked yet */
  1123. if(SSL_BadCertHook(model, BadCertHandler, conn) != SECSuccess)
  1124. goto error;
  1125. if(SSL_HandshakeCallback(model, HandshakeCallback, NULL) != SECSuccess)
  1126. goto error;
  1127. if(data->set.ssl.verifypeer) {
  1128. const CURLcode rv = nss_load_ca_certificates(conn, sockindex);
  1129. if(CURLE_OK != rv) {
  1130. curlerr = rv;
  1131. goto error;
  1132. }
  1133. }
  1134. if(data->set.ssl.CRLfile) {
  1135. if(SECSuccess != nss_load_crl(data->set.ssl.CRLfile)) {
  1136. curlerr = CURLE_SSL_CRL_BADFILE;
  1137. goto error;
  1138. }
  1139. infof(data,
  1140. " CRLfile: %s\n",
  1141. data->set.ssl.CRLfile ? data->set.ssl.CRLfile : "none");
  1142. }
  1143. if(data->set.str[STRING_CERT]) {
  1144. char *nickname = dup_nickname(data, STRING_CERT);
  1145. if(nickname) {
  1146. /* we are not going to use libnsspem.so to read the client cert */
  1147. connssl->obj_clicert = NULL;
  1148. }
  1149. else {
  1150. CURLcode rv = cert_stuff(conn, sockindex, data->set.str[STRING_CERT],
  1151. data->set.str[STRING_KEY]);
  1152. if(CURLE_OK != rv) {
  1153. /* failf() is already done in cert_stuff() */
  1154. curlerr = rv;
  1155. goto error;
  1156. }
  1157. }
  1158. /* store the nickname for SelectClientCert() called during handshake */
  1159. connssl->client_nickname = nickname;
  1160. }
  1161. else
  1162. connssl->client_nickname = NULL;
  1163. if(SSL_GetClientAuthDataHook(model, SelectClientCert,
  1164. (void *)connssl) != SECSuccess) {
  1165. curlerr = CURLE_SSL_CERTPROBLEM;
  1166. goto error;
  1167. }
  1168. /* Import our model socket onto the existing file descriptor */
  1169. connssl->handle = PR_ImportTCPSocket(sockfd);
  1170. connssl->handle = SSL_ImportFD(model, connssl->handle);
  1171. if(!connssl->handle)
  1172. goto error;
  1173. PR_Close(model); /* We don't need this any more */
  1174. model = NULL;
  1175. /* This is the password associated with the cert that we're using */
  1176. if(data->set.str[STRING_KEY_PASSWD]) {
  1177. SSL_SetPKCS11PinArg(connssl->handle, data->set.str[STRING_KEY_PASSWD]);
  1178. }
  1179. /* Force handshake on next I/O */
  1180. SSL_ResetHandshake(connssl->handle, /* asServer */ PR_FALSE);
  1181. SSL_SetURL(connssl->handle, conn->host.name);
  1182. /* check timeout situation */
  1183. time_left = Curl_timeleft(data, NULL, TRUE);
  1184. if(time_left < 0L) {
  1185. failf(data, "timed out before SSL handshake");
  1186. curlerr = CURLE_OPERATION_TIMEDOUT;
  1187. goto error;
  1188. }
  1189. timeout = PR_MillisecondsToInterval((PRUint32) time_left);
  1190. /* Force the handshake now */
  1191. if(SSL_ForceHandshakeWithTimeout(connssl->handle, timeout) != SECSuccess) {
  1192. if(conn->data->set.ssl.certverifyresult == SSL_ERROR_BAD_CERT_DOMAIN)
  1193. curlerr = CURLE_PEER_FAILED_VERIFICATION;
  1194. else if(conn->data->set.ssl.certverifyresult!=0)
  1195. curlerr = CURLE_SSL_CACERT;
  1196. goto error;
  1197. }
  1198. /* switch the SSL socket into non-blocking mode */
  1199. sock_opt.option = PR_SockOpt_Nonblocking;
  1200. sock_opt.value.non_blocking = PR_TRUE;
  1201. if(PR_SetSocketOption(connssl->handle, &sock_opt) != PR_SUCCESS)
  1202. goto error;
  1203. connssl->state = ssl_connection_complete;
  1204. conn->recv[sockindex] = nss_recv;
  1205. conn->send[sockindex] = nss_send;
  1206. display_conn_info(conn, connssl->handle);
  1207. if(data->set.str[STRING_SSL_ISSUERCERT]) {
  1208. SECStatus ret = SECFailure;
  1209. char *nickname = dup_nickname(data, STRING_SSL_ISSUERCERT);
  1210. if(nickname) {
  1211. /* we support only nicknames in case of STRING_SSL_ISSUERCERT for now */
  1212. ret = check_issuer_cert(connssl->handle, nickname);
  1213. free(nickname);
  1214. }
  1215. if(SECFailure == ret) {
  1216. infof(data,"SSL certificate issuer check failed\n");
  1217. curlerr = CURLE_SSL_ISSUER_ERROR;
  1218. goto error;
  1219. }
  1220. else {
  1221. infof(data, "SSL certificate issuer check ok\n");
  1222. }
  1223. }
  1224. return CURLE_OK;
  1225. error:
  1226. /* reset the flag to avoid an infinite loop */
  1227. data->state.ssl_connect_retry = FALSE;
  1228. if(is_nss_error(curlerr)) {
  1229. /* read NSPR error code */
  1230. err = PR_GetError();
  1231. if(is_cc_error(err))
  1232. curlerr = CURLE_SSL_CERTPROBLEM;
  1233. /* print the error number and error string */
  1234. infof(data, "NSS error %d (%s)\n", err, nss_error_to_name(err));
  1235. /* print a human-readable message describing the error if available */
  1236. nss_print_error_message(data, err);
  1237. }
  1238. if(model)
  1239. PR_Close(model);
  1240. /* cleanup on connection failure */
  1241. Curl_llist_destroy(connssl->obj_list, NULL);
  1242. connssl->obj_list = NULL;
  1243. if(ssl3 && tlsv1 && isTLSIntoleranceError(err)) {
  1244. /* schedule reconnect through Curl_retry_request() */
  1245. data->state.ssl_connect_retry = TRUE;
  1246. infof(data, "Error in TLS handshake, trying SSLv3...\n");
  1247. return CURLE_OK;
  1248. }
  1249. return curlerr;
  1250. }
  1251. static ssize_t nss_send(struct connectdata *conn, /* connection data */
  1252. int sockindex, /* socketindex */
  1253. const void *mem, /* send this data */
  1254. size_t len, /* amount to write */
  1255. CURLcode *curlcode)
  1256. {
  1257. ssize_t rc = PR_Send(conn->ssl[sockindex].handle, mem, (int)len, 0,
  1258. PR_INTERVAL_NO_WAIT);
  1259. if(rc < 0) {
  1260. PRInt32 err = PR_GetError();
  1261. if(err == PR_WOULD_BLOCK_ERROR)
  1262. *curlcode = CURLE_AGAIN;
  1263. else {
  1264. /* print the error number and error string */
  1265. const char *err_name = nss_error_to_name(err);
  1266. infof(conn->data, "SSL write: error %d (%s)\n", err, err_name);
  1267. /* print a human-readable message describing the error if available */
  1268. nss_print_error_message(conn->data, err);
  1269. *curlcode = (is_cc_error(err))
  1270. ? CURLE_SSL_CERTPROBLEM
  1271. : CURLE_SEND_ERROR;
  1272. }
  1273. return -1;
  1274. }
  1275. return rc; /* number of bytes */
  1276. }
  1277. static ssize_t nss_recv(struct connectdata * conn, /* connection data */
  1278. int num, /* socketindex */
  1279. char *buf, /* store read data here */
  1280. size_t buffersize, /* max amount to read */
  1281. CURLcode *curlcode)
  1282. {
  1283. ssize_t nread = PR_Recv(conn->ssl[num].handle, buf, (int)buffersize, 0,
  1284. PR_INTERVAL_NO_WAIT);
  1285. if(nread < 0) {
  1286. /* failed SSL read */
  1287. PRInt32 err = PR_GetError();
  1288. if(err == PR_WOULD_BLOCK_ERROR)
  1289. *curlcode = CURLE_AGAIN;
  1290. else {
  1291. /* print the error number and error string */
  1292. const char *err_name = nss_error_to_name(err);
  1293. infof(conn->data, "SSL read: errno %d (%s)\n", err, err_name);
  1294. /* print a human-readable message describing the error if available */
  1295. nss_print_error_message(conn->data, err);
  1296. *curlcode = (is_cc_error(err))
  1297. ? CURLE_SSL_CERTPROBLEM
  1298. : CURLE_RECV_ERROR;
  1299. }
  1300. return -1;
  1301. }
  1302. return nread;
  1303. }
  1304. size_t Curl_nss_version(char *buffer, size_t size)
  1305. {
  1306. return snprintf(buffer, size, "NSS/%s", NSS_VERSION);
  1307. }
  1308. int Curl_nss_seed(struct SessionHandle *data)
  1309. {
  1310. /* TODO: implement? */
  1311. (void) data;
  1312. return 0;
  1313. }
  1314. void Curl_nss_random(struct SessionHandle *data,
  1315. unsigned char *entropy,
  1316. size_t length)
  1317. {
  1318. Curl_nss_seed(data); /* Initiate the seed if not already done */
  1319. PK11_GenerateRandom(entropy, curlx_uztosi(length));
  1320. }
  1321. void Curl_nss_md5sum(unsigned char *tmp, /* input */
  1322. size_t tmplen,
  1323. unsigned char *md5sum, /* output */
  1324. size_t md5len)
  1325. {
  1326. PK11Context *MD5pw = PK11_CreateDigestContext(SEC_OID_MD5);
  1327. unsigned int MD5out;
  1328. PK11_DigestOp(MD5pw, tmp, curlx_uztoui(tmplen));
  1329. PK11_DigestFinal(MD5pw, md5sum, &MD5out, curlx_uztoui(md5len));
  1330. PK11_DestroyContext(MD5pw, PR_TRUE);
  1331. }
  1332. #endif /* USE_NSS */