5
5
* | (__| |_| | _ <| |___
6
6
* \___|\___/|_| \_\_____|
8
* Copyright (C) 1998 - 2008, Daniel Stenberg, <daniel@haxx.se>, et al.
8
* Copyright (C) 1998 - 2009, Daniel Stenberg, <daniel@haxx.se>, et al.
10
10
* This software is licensed as described in the file COPYING, which
11
11
* you should have received as part of this distribution. The terms
18
18
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
19
19
* KIND, either express or implied.
21
* $Id: sslgen.c,v 1.37 2008-05-09 11:27:55 mmarek Exp $
21
* $Id: sslgen.c,v 1.45 2009-02-25 12:51:39 bagder Exp $
22
22
***************************************************************************/
24
/* This file is for "generic" SSL functions that all libcurl internals should
25
use. It is responsible for calling the proper 'ossl' function in ssluse.c
26
(OpenSSL based) or the 'gtls' function in gtls.c (GnuTLS based).
24
/* This file is for implementing all "generic" SSL functions that all libcurl
25
internals should use. It is then responsible for calling the proper
28
28
SSL-functions in libcurl should call functions in this source file, and not
29
29
to any specific SSL-layer.
33
33
Curl_gtls_ - prefix for GnuTLS ones
34
34
Curl_nss_ - prefix for NSS ones
36
Note that this source code uses curlssl_* functions, and they are all
37
defines/macros #defined by the lib-specific header files.
36
39
"SSL/TLS Strong Encryption: An Introduction"
37
40
http://httpd.apache.org/docs-2.0/ssl/ssl_intro.html
54
57
#include "nssg.h" /* NSS versions */
55
58
#include "qssl.h" /* QSOSSL versions */
59
62
#include "memory.h"
60
64
/* The last #include file should be: */
61
65
#include "memdebug.h"
63
/* "global" init done? */
64
static bool init_ssl=FALSE;
66
static bool safe_strequal(char* str1, char* str2);
68
67
static bool safe_strequal(char* str1, char* str2)
71
70
/* both pointers point to something then compare them */
72
return (bool)(0 != strequal(str1, str2));
71
return (bool)(0 != Curl_raw_equal(str1, str2));
74
73
/* if both pointers are NULL then treat them as equal */
75
74
return (bool)(!str1 && !str2);
205
178
Curl_ssl_connect(struct connectdata *conn, int sockindex)
208
/* mark this is being ssl enabled from here on. */
181
/* mark this is being ssl-enabled from here on. */
209
182
conn->ssl[sockindex].use = TRUE;
210
183
conn->ssl[sockindex].state = ssl_connection_negotiating;
213
return Curl_ossl_connect(conn, sockindex);
216
return Curl_gtls_connect(conn, sockindex);
219
return Curl_nss_connect(conn, sockindex);
222
return Curl_qsossl_connect(conn, sockindex);
223
#endif /* USE_QSOSSL */
225
#endif /* USE_GNUTLS */
226
#endif /* USE_SSLEAY */
185
res = curlssl_connect(conn, sockindex);
188
Curl_pgrsTime(conn->data, TIMER_APPCONNECT); /* SSL is connected */
237
194
Curl_ssl_connect_nonblocking(struct connectdata *conn, int sockindex,
240
#if defined(USE_SSL) && defined(USE_SSLEAY)
241
/* mark this is being ssl enabled from here on. */
242
conn->ssl[sockindex].use = TRUE;
243
return Curl_ossl_connect_nonblocking(conn, sockindex, done);
247
*done = TRUE; /* fallback to BLOCKING */
248
conn->ssl[sockindex].use = TRUE;
249
return Curl_nss_connect(conn, sockindex);
252
*done = TRUE; /* fallback to BLOCKING */
253
conn->ssl[sockindex].use = TRUE;
254
return Curl_qsossl_connect(conn, sockindex);
257
fallback to BLOCKING call. */
259
conn->ssl[sockindex].use = TRUE;
260
return Curl_ssl_connect(conn, sockindex);
261
#endif /* USE_QSOSSL */
263
#endif /* USE_SSLEAY */
197
#ifdef curlssl_connect_nonblocking
198
/* mark this is being ssl requested from here on. */
199
conn->ssl[sockindex].use = TRUE;
200
return curlssl_connect_nonblocking(conn, sockindex, done);
202
*done = TRUE; /* fallback to BLOCKING */
203
conn->ssl[sockindex].use = TRUE;
204
return curlssl_connect(conn, sockindex);
205
#endif /* non-blocking connect support */
269
209
* Check if there's a session ID for the given connection in the cache, and if
270
210
* there's one suitable, it is provided. Returns TRUE when no entry matched.
286
226
if(!check->sessionid)
287
227
/* not session ID means blank entry */
289
if(curl_strequal(conn->host.name, check->name) &&
229
if(Curl_raw_equal(conn->host.name, check->name) &&
290
230
(conn->remote_port == check->remote_port) &&
291
231
Curl_ssl_config_matches(&conn->ssl_config, &check->ssl_config)) {
292
232
/* yes, we have a session ID! */
311
251
/* defensive check */
313
253
/* free the ID the SSL-layer specific way */
315
Curl_ossl_session_free(session->sessionid);
318
Curl_gtls_session_free(session->sessionid);
321
/* No session handling for QsoSSL. */
324
/* NSS has its own session ID cache */
326
#endif /* USE_QSOSSL */
327
#endif /* USE_GNUTLS */
328
#endif /* USE_SSLEAY */
254
curlssl_session_free(session->sessionid);
329
256
session->sessionid=NULL;
330
257
session->age = 0; /* fresh */
414
338
free(data->state.session);
415
339
data->state.session = NULL;
418
Curl_ossl_close_all(data);
421
Curl_gtls_close_all(data);
424
Curl_nss_close_all(data);
427
Curl_qsossl_close_all(data);
428
#endif /* USE_QSOSSL */
430
#endif /* USE_GNUTLS */
431
#endif /* USE_SSLEAY */
342
curlssl_close_all(data);
437
345
void Curl_ssl_close(struct connectdata *conn, int sockindex)
439
347
DEBUGASSERT((sockindex <= 1) && (sockindex >= -1));
442
Curl_ossl_close(conn, sockindex);
443
#endif /* USE_SSLEAY */
445
Curl_gtls_close(conn, sockindex);
446
#endif /* USE_GNUTLS */
448
Curl_nss_close(conn, sockindex);
451
Curl_qsossl_close(conn, sockindex);
452
#endif /* USE_QSOSSL */
456
#endif /* !USE_SSL */
348
curlssl_close(conn, sockindex);
459
351
CURLcode Curl_ssl_shutdown(struct connectdata *conn, int sockindex)
462
if(Curl_ossl_shutdown(conn, sockindex))
463
return CURLE_SSL_SHUTDOWN_FAILED;
466
if(Curl_gtls_shutdown(conn, sockindex))
467
return CURLE_SSL_SHUTDOWN_FAILED;
470
if(Curl_qsossl_shutdown(conn, sockindex))
471
return CURLE_SSL_SHUTDOWN_FAILED;
472
#endif /* USE_QSOSSL */
473
#endif /* USE_GNUTLS */
474
#endif /* USE_SSLEAY */
353
if(curlssl_shutdown(conn, sockindex))
354
return CURLE_SSL_SHUTDOWN_FAILED;
476
356
conn->ssl[sockindex].use = FALSE; /* get back to ordinary socket usage */
477
357
conn->ssl[sockindex].state = ssl_connection_none;
482
/* Selects an (Open)SSL crypto engine
362
/* Selects an SSL crypto engine
484
364
CURLcode Curl_ssl_set_engine(struct SessionHandle *data, const char *engine)
487
return Curl_ossl_set_engine(data, engine);
490
/* FIX: add code here */
493
return CURLE_FAILED_INIT;
496
/* NSS doesn't set an engine this way */
499
return CURLE_FAILED_INIT;
502
/* QSOSSL doesn't set an engine this way */
505
return CURLE_FAILED_INIT;
510
return CURLE_FAILED_INIT;
511
#endif /* USE_QSOSSL */
513
#endif /* USE_GNUTLS */
514
#endif /* USE_SSLEAY */
366
return curlssl_set_engine(data, engine);
517
/* Selects an (Open?)SSL crypto engine
369
/* Selects the default SSL crypto engine
519
371
CURLcode Curl_ssl_set_engine_default(struct SessionHandle *data)
522
return Curl_ossl_set_engine_default(data);
525
/* FIX: add code here */
527
return CURLE_FAILED_INIT;
530
/* A no-op for NSS */
532
return CURLE_FAILED_INIT;
535
/* A no-op for QSOSSL */
537
return CURLE_FAILED_INIT;
541
return CURLE_FAILED_INIT;
542
#endif /* USE_QSOSSL */
544
#endif /* USE_GNUTLS */
545
#endif /* USE_SSLEAY */
373
return curlssl_set_engine_default(data);
548
376
/* Return list of OpenSSL crypto engine names. */
549
377
struct curl_slist *Curl_ssl_engines_list(struct SessionHandle *data)
552
return Curl_ossl_engines_list(data);
555
/* FIX: add code here? */
560
/* In theory we could return the PKCS#11 modules loaded but that
561
* would just confuse things */
566
/* No engine support in QSOSSL. */
572
#endif /* USE_QSOSSL */
574
#endif /* USE_GNUTLS */
575
#endif /* USE_SSLEAY */
379
return curlssl_engines_list(data);
578
382
/* return number of sent (non-SSL) bytes */
585
return Curl_ossl_send(conn, sockindex, mem, len);
588
return Curl_gtls_send(conn, sockindex, mem, len);
591
return Curl_nss_send(conn, sockindex, mem, len);
594
return Curl_qsossl_send(conn, sockindex, mem, len);
601
#endif /* USE_QSOSSL */
603
#endif /* USE_GNUTLS */
604
#endif /* USE_SSLEAY */
388
return curlssl_send(conn, sockindex, mem, len);
607
391
/* return number of received (decrypted) bytes */
615
399
char *mem, /* store read data here */
616
400
size_t len) /* max amount to read */
620
403
bool block = FALSE;
623
nread = Curl_ossl_recv(conn, sockindex, mem, len, &block);
626
nread = Curl_gtls_recv(conn, sockindex, mem, len, &block);
629
nread = Curl_nss_recv(conn, sockindex, mem, len, &block);
632
nread = Curl_qsossl_recv(conn, sockindex, mem, len, &block);
633
#endif /* USE_QSOSSL */
635
#endif /* USE_GNUTLS */
636
#endif /* USE_SSLEAY */
405
nread = curlssl_recv(conn, sockindex, mem, len, &block);
637
406
if(nread == -1) {
639
408
return 0; /* this is a true error, not EWOULDBLOCK */
660
421
CURLcode Curl_ssl_initsessions(struct SessionHandle *data, long amount)
663
423
struct curl_ssl_session *session;
665
425
if(data->state.session)
666
426
/* this is just a precaution to prevent multiple inits */
669
session = (struct curl_ssl_session *)
670
calloc(sizeof(struct curl_ssl_session), amount);
429
session = calloc(sizeof(struct curl_ssl_session), amount);
672
431
return CURLE_OUT_OF_MEMORY;
675
434
data->set.ssl.numsessions = amount;
676
435
data->state.session = session;
677
436
data->state.sessionage = 1; /* this is brand new */
679
/* without SSL, do nothing */
687
440
size_t Curl_ssl_version(char *buffer, size_t size)
690
return Curl_ossl_version(buffer, size);
693
return Curl_gtls_version(buffer, size);
696
return Curl_nss_version(buffer, size);
699
return Curl_qsossl_version(buffer, size);
703
return 0; /* no SSL support */
704
#endif /* USE_QSOSSL */
706
#endif /* USE_GNUTLS */
707
#endif /* USE_SSLEAY */
442
return curlssl_version(buffer, size);
712
446
* This function tries to determine connection status.
719
453
int Curl_ssl_check_cxn(struct connectdata *conn)
722
return Curl_ossl_check_cxn(conn);
725
return Curl_nss_check_cxn(conn);
728
return Curl_qsossl_check_cxn(conn);
731
/* TODO: we lack implementation of this for GnuTLS */
732
return -1; /* connection status unknown */
733
#endif /* USE_QSOSSL */
735
#endif /* USE_SSLEAY */
455
return curlssl_check_cxn(conn);
738
458
bool Curl_ssl_data_pending(const struct connectdata *conn,
742
/* OpenSSL-specific */
743
if(conn->ssl[connindex].handle)
745
return (bool)(0 != SSL_pending(conn->ssl[connindex].handle));
750
return FALSE; /* nothing pending */
461
return curlssl_data_pending(conn, connindex);
464
void Curl_ssl_free_certinfo(struct SessionHandle *data)
467
struct curl_certinfo *ci = &data->info.certs;
468
if(ci->num_of_certs) {
469
/* free all individual lists used */
470
for(i=0; i<ci->num_of_certs; i++)
471
curl_slist_free_all(ci->certinfo[i]);
472
free(ci->certinfo); /* free the actual array too */
473
ci->num_of_certs = 0;