doom3-gpl
Doom 3 GPL source release
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
ssluse.c
Go to the documentation of this file.
1 /***************************************************************************
2  * _ _ ____ _
3  * Project ___| | | | _ \| |
4  * / __| | | | |_) | |
5  * | (__| |_| | _ <| |___
6  * \___|\___/|_| \_\_____|
7  *
8  * Copyright (C) 1998 - 2004, 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  * $Id: ssluse.c,v 1.93 2004/03/11 12:57:04 bagder Exp $
22  ***************************************************************************/
23 
24 /*
25  * The original SSL code for curl was written by
26  * Linas Vepstas <linas@linas.org> and Sampo Kellomaki <sampo@iki.fi>
27  */
28 
29 #include "setup.h"
30 
31 #include <string.h>
32 #include <stdlib.h>
33 #include <ctype.h>
34 #ifdef HAVE_SYS_TYPES_H
35 #include <sys/types.h>
36 #endif
37 #ifdef HAVE_SYS_SOCKET_H
38 #include <sys/socket.h>
39 #endif
40 
41 #include "urldata.h"
42 #include "sendf.h"
43 #include "formdata.h" /* for the boundary function */
44 #include "url.h" /* for the ssl config check function */
45 #include "inet_pton.h"
46 #include "ssluse.h"
47 #include "connect.h" /* Curl_ourerrno() proto */
48 
49 #ifdef USE_SSLEAY
50 #include <openssl/rand.h>
51 #include <openssl/x509v3.h>
52 
53 /* The last #include file should be: */
54 #ifdef CURLDEBUG
55 #include "memdebug.h"
56 #endif
57 
58 #if OPENSSL_VERSION_NUMBER >= 0x0090581fL
59 #define HAVE_SSL_GET1_SESSION 1
60 #else
61 #undef HAVE_SSL_GET1_SESSION
62 #endif
63 
64 #if OPENSSL_VERSION_NUMBER >= 0x00904100L
65 #define HAVE_USERDATA_IN_PWD_CALLBACK 1
66 #else
67 #undef HAVE_USERDATA_IN_PWD_CALLBACK
68 #endif
69 
70 #if OPENSSL_VERSION_NUMBER >= 0x00907001L
71 /* ENGINE_load_private_key() takes four arguments */
72 #define HAVE_ENGINE_LOAD_FOUR_ARGS
73 #else
74 /* ENGINE_load_private_key() takes three arguments */
75 #undef HAVE_ENGINE_LOAD_FOUR_ARGS
76 #endif
77 
78 
79 #ifndef HAVE_USERDATA_IN_PWD_CALLBACK
80 static char global_passwd[64];
81 #endif
82 
83 static int passwd_callback(char *buf, int num, int verify
84 #if HAVE_USERDATA_IN_PWD_CALLBACK
85  /* This was introduced in 0.9.4, we can set this
86  using SSL_CTX_set_default_passwd_cb_userdata()
87  */
88  , void *global_passwd
89 #endif
90  )
91 {
92  if(verify)
93  fprintf(stderr, "%s\n", buf);
94  else {
95  if(num > (int)strlen((char *)global_passwd)) {
96  strcpy(buf, global_passwd);
97  return strlen(buf);
98  }
99  }
100  return 0;
101 }
102 
103 static
104 bool seed_enough(int nread)
105 {
106 #ifdef HAVE_RAND_STATUS
107  nread = 0; /* to prevent compiler warnings */
108 
109  /* only available in OpenSSL 0.9.5a and later */
110  if(RAND_status())
111  return TRUE;
112 #else
113  if(nread > 500)
114  /* this is a very silly decision to make */
115  return TRUE;
116 #endif
117  return FALSE; /* not enough */
118 }
119 
120 static
121 int random_the_seed(struct SessionHandle *data)
122 {
123  char *buf = data->state.buffer; /* point to the big buffer */
124  int nread=0;
125 
126  /* Q: should we add support for a random file name as a libcurl option?
127  A: Yes, it is here */
128 
129 #ifndef RANDOM_FILE
130  /* if RANDOM_FILE isn't defined, we only perform this if an option tells
131  us to! */
132  if(data->set.ssl.random_file)
133 #define RANDOM_FILE "" /* doesn't matter won't be used */
134 #endif
135  {
136  /* let the option override the define */
137  nread += RAND_load_file((data->set.ssl.random_file?
138  data->set.ssl.random_file:RANDOM_FILE),
139  16384);
140  if(seed_enough(nread))
141  return nread;
142  }
143 
144 #if defined(HAVE_RAND_EGD)
145  /* only available in OpenSSL 0.9.5 and later */
146  /* EGD_SOCKET is set at configure time or not at all */
147 #ifndef EGD_SOCKET
148  /* If we don't have the define set, we only do this if the egd-option
149  is set */
150  if(data->set.ssl.egdsocket)
151 #define EGD_SOCKET "" /* doesn't matter won't be used */
152 #endif
153  {
154  /* If there's an option and a define, the option overrides the
155  define */
156  int ret = RAND_egd(data->set.ssl.egdsocket?
157  data->set.ssl.egdsocket:EGD_SOCKET);
158  if(-1 != ret) {
159  nread += ret;
160  if(seed_enough(nread))
161  return nread;
162  }
163  }
164 #endif
165 
166  /* If we get here, it means we need to seed the PRNG using a "silly"
167  approach! */
168 #ifdef HAVE_RAND_SCREEN
169  /* This one gets a random value by reading the currently shown screen */
170  RAND_screen();
171  nread = 100; /* just a value */
172 #else
173  {
174  int len;
175  char *area;
176 
177  /* Changed call to RAND_seed to use the underlying RAND_add implementation
178  * directly. Do this in a loop, with the amount of additional entropy
179  * being dependent upon the algorithm used by Curl_FormBoundary(): N bytes
180  * of a 7-bit ascii set. -- Richard Gorton, March 11 2003.
181  */
182 
183  do {
184  area = Curl_FormBoundary();
185  if(!area)
186  return 3; /* out of memory */
187 
188  len = strlen(area);
189  RAND_add(area, len, (len >> 1));
190 
191  free(area); /* now remove the random junk */
192  } while (!RAND_status());
193  }
194 #endif
195 
196  /* generates a default path for the random seed file */
197  buf[0]=0; /* blank it first */
198  RAND_file_name(buf, BUFSIZE);
199  if(buf[0]) {
200  /* we got a file name to try */
201  nread += RAND_load_file(buf, 16384);
202  if(seed_enough(nread))
203  return nread;
204  }
205 
206  infof(data, "libcurl is now using a weak random seed!\n");
207  return nread;
208 }
209 
210 #ifndef SSL_FILETYPE_ENGINE
211 #define SSL_FILETYPE_ENGINE 42
212 #endif
213 static int do_file_type(const char *type)
214 {
215  if(!type || !type[0])
216  return SSL_FILETYPE_PEM;
217  if(curl_strequal(type, "PEM"))
218  return SSL_FILETYPE_PEM;
219  if(curl_strequal(type, "DER"))
220  return SSL_FILETYPE_ASN1;
221  if(curl_strequal(type, "ENG"))
222  return SSL_FILETYPE_ENGINE;
223  return -1;
224 }
225 
226 static
227 int cert_stuff(struct connectdata *conn,
228  SSL_CTX* ctx,
229  char *cert_file,
230  const char *cert_type,
231  char *key_file,
232  const char *key_type)
233 {
234  struct SessionHandle *data = conn->data;
235  int file_type;
236 
237  if(cert_file != NULL) {
238  SSL *ssl;
239  X509 *x509;
240 
241  if(data->set.key_passwd) {
242 #ifndef HAVE_USERDATA_IN_PWD_CALLBACK
243  /*
244  * If password has been given, we store that in the global
245  * area (*shudder*) for a while:
246  */
247  strcpy(global_passwd, data->set.key_passwd);
248 #else
249  /*
250  * We set the password in the callback userdata
251  */
252  SSL_CTX_set_default_passwd_cb_userdata(ctx,
253  data->set.key_passwd);
254 #endif
255  /* Set passwd callback: */
256  SSL_CTX_set_default_passwd_cb(ctx, passwd_callback);
257  }
258 
259  file_type = do_file_type(cert_type);
260 
261  switch(file_type) {
262  case SSL_FILETYPE_PEM:
263  /* SSL_CTX_use_certificate_chain_file() only works on PEM files */
264  if(SSL_CTX_use_certificate_chain_file(ctx,
265  cert_file) != 1) {
266  failf(data, "unable to set certificate file (wrong password?)");
267  return 0;
268  }
269  break;
270 
271  case SSL_FILETYPE_ASN1:
272  /* SSL_CTX_use_certificate_file() works with either PEM or ASN1, but
273  we use the case above for PEM so this can only be performed with
274  ASN1 files. */
275  if(SSL_CTX_use_certificate_file(ctx,
276  cert_file,
277  file_type) != 1) {
278  failf(data, "unable to set certificate file (wrong password?)");
279  return 0;
280  }
281  break;
282  case SSL_FILETYPE_ENGINE:
283  failf(data, "file type ENG for certificate not implemented");
284  return 0;
285 
286  default:
287  failf(data, "not supported file type '%s' for certificate", cert_type);
288  return 0;
289  }
290 
291  file_type = do_file_type(key_type);
292 
293  switch(file_type) {
294  case SSL_FILETYPE_PEM:
295  if(key_file == NULL)
296  /* cert & key can only be in PEM case in the same file */
297  key_file=cert_file;
298  case SSL_FILETYPE_ASN1:
299  if(SSL_CTX_use_PrivateKey_file(ctx, key_file, file_type) != 1) {
300  failf(data, "unable to set private key file: '%s' type %s\n",
301  key_file, key_type?key_type:"PEM");
302  return 0;
303  }
304  break;
305  case SSL_FILETYPE_ENGINE:
306 #ifdef HAVE_OPENSSL_ENGINE_H
307  { /* XXXX still needs some work */
308  EVP_PKEY *priv_key = NULL;
309  if(conn && conn->data && conn->data->engine) {
310 #ifdef HAVE_ENGINE_LOAD_FOUR_ARGS
311  UI_METHOD *ui_method = UI_OpenSSL();
312 #endif
313  if(!key_file || !key_file[0]) {
314  failf(data, "no key set to load from crypto engine\n");
315  return 0;
316  }
317  priv_key = ENGINE_load_private_key(conn->data->engine,key_file,
318 #ifdef HAVE_ENGINE_LOAD_FOUR_ARGS
319  ui_method,
320 #endif
321  data->set.key_passwd);
322  if(!priv_key) {
323  failf(data, "failed to load private key from crypto engine\n");
324  return 0;
325  }
326  if(SSL_CTX_use_PrivateKey(ctx, priv_key) != 1) {
327  failf(data, "unable to set private key\n");
328  EVP_PKEY_free(priv_key);
329  return 0;
330  }
331  EVP_PKEY_free(priv_key); /* we don't need the handle any more... */
332  }
333  else {
334  failf(data, "crypto engine not set, can't load private key\n");
335  return 0;
336  }
337  }
338 #else
339  failf(data, "file type ENG for private key not supported\n");
340  return 0;
341 #endif
342  break;
343  default:
344  failf(data, "not supported file type for private key\n");
345  return 0;
346  }
347 
348  ssl=SSL_new(ctx);
349  x509=SSL_get_certificate(ssl);
350 
351  /* This version was provided by Evan Jordan and is supposed to not
352  leak memory as the previous version: */
353  if(x509 != NULL) {
354  EVP_PKEY *pktmp = X509_get_pubkey(x509);
355  EVP_PKEY_copy_parameters(pktmp,SSL_get_privatekey(ssl));
356  EVP_PKEY_free(pktmp);
357  }
358 
359  SSL_free(ssl);
360 
361  /* If we are using DSA, we can copy the parameters from
362  * the private key */
363 
364 
365  /* Now we know that a key and cert have been set against
366  * the SSL context */
367  if(!SSL_CTX_check_private_key(ctx)) {
368  failf(data, "Private key does not match the certificate public key");
369  return(0);
370  }
371 #ifndef HAVE_USERDATA_IN_PWD_CALLBACK
372  /* erase it now */
373  memset(global_passwd, 0, sizeof(global_passwd));
374 #endif
375  }
376  return(1);
377 }
378 
379 static
380 int cert_verify_callback(int ok, X509_STORE_CTX *ctx)
381 {
382  X509 *err_cert;
383  char buf[256];
384 
385  err_cert=X509_STORE_CTX_get_current_cert(ctx);
386  X509_NAME_oneline(X509_get_subject_name(err_cert),buf,256);
387 
388  return ok;
389 }
390 
391 #endif
392 
393 #ifdef USE_SSLEAY
394 /* "global" init done? */
395 static int init_ssl=0;
396 
397 /* we have the "SSL is seeded" boolean global for the application to
398  prevent multiple time-consuming seedings in vain */
399 static bool ssl_seeded = FALSE;
400 #endif
401 
402 /* Global init */
403 void Curl_SSL_init(void)
404 {
405 #ifdef USE_SSLEAY
406  /* make sure this is only done once */
407  if(0 != init_ssl)
408  return;
409 
410  init_ssl++; /* never again */
411 
412 #ifdef HAVE_ENGINE_LOAD_BUILTIN_ENGINES
413  ENGINE_load_builtin_engines();
414 #endif
415 
416  /* Lets get nice error messages */
417  SSL_load_error_strings();
418 
419  /* Setup all the global SSL stuff */
420  SSLeay_add_ssl_algorithms();
421 #else
422  /* SSL disabled, do nothing */
423 #endif
424 }
425 
426 /* Global cleanup */
428 {
429 #ifdef USE_SSLEAY
430  if(init_ssl) {
431  /* only cleanup if we did a previous init */
432 
433  /* Free the SSL error strings */
434  ERR_free_strings();
435 
436  /* EVP_cleanup() removes all ciphers and digests from the
437  table. */
438  EVP_cleanup();
439 
440 #ifdef HAVE_ENGINE_cleanup
441  ENGINE_cleanup();
442 #endif
443 
444 #ifdef HAVE_CRYPTO_CLEANUP_ALL_EX_DATA
445  /* this function was not present in 0.9.6b, but was added sometimes
446  later */
447  CRYPTO_cleanup_all_ex_data();
448 #endif
449 
450  init_ssl=0; /* not inited any more */
451  }
452 #else
453  /* SSL disabled, do nothing */
454 #endif
455 }
456 
457 #ifndef USE_SSLEAY
458 void Curl_SSL_Close(struct connectdata *conn)
459 {
460  (void)conn;
461 }
462 #endif
463 
464 #ifdef USE_SSLEAY
465 
466 /*
467  * This function is called when an SSL connection is closed.
468  */
469 void Curl_SSL_Close(struct connectdata *conn)
470 {
471  if(conn->ssl[FIRSTSOCKET].use) {
472  int i;
473  /*
474  ERR_remove_state() frees the error queue associated with
475  thread pid. If pid == 0, the current thread will have its
476  error queue removed.
477 
478  Since error queue data structures are allocated
479  automatically for new threads, they must be freed when
480  threads are terminated in oder to avoid memory leaks.
481  */
482  ERR_remove_state(0);
483 
484  for(i=0; i<2; i++) {
485  struct ssl_connect_data *connssl = &conn->ssl[i];
486 
487  if(connssl->handle) {
488  (void)SSL_shutdown(connssl->handle);
489  SSL_set_connect_state(connssl->handle);
490 
491  SSL_free (connssl->handle);
492  connssl->handle = NULL;
493  }
494  if(connssl->ctx) {
495  SSL_CTX_free (connssl->ctx);
496  connssl->ctx = NULL;
497  }
498  connssl->use = FALSE; /* get back to ordinary socket usage */
499  }
500  }
501 }
502 
503 
504 /*
505  * This sets up a session cache to the specified size.
506  */
507 CURLcode Curl_SSL_InitSessions(struct SessionHandle *data, long amount)
508 {
509  struct curl_ssl_session *session;
510 
511  if(data->state.session)
512  /* this is just a precaution to prevent multiple inits */
513  return CURLE_OK;
514 
515  session = (struct curl_ssl_session *)
516  malloc(amount * sizeof(struct curl_ssl_session));
517  if(!session)
518  return CURLE_OUT_OF_MEMORY;
519 
520  /* "blank out" the newly allocated memory */
521  memset(session, 0, amount * sizeof(struct curl_ssl_session));
522 
523  /* store the info in the SSL section */
524  data->set.ssl.numsessions = amount;
525  data->state.session = session;
526  data->state.sessionage = 1; /* this is brand new */
527 
528  return CURLE_OK;
529 }
530 
531 /*
532  * Check if there's a session ID for the given connection in the cache,
533  * and if there's one suitable, it is returned.
534  */
535 static int Get_SSL_Session(struct connectdata *conn,
536  SSL_SESSION **ssl_sessionid)
537 {
538  struct curl_ssl_session *check;
539  struct SessionHandle *data = conn->data;
540  long i;
541 
542  for(i=0; i< data->set.ssl.numsessions; i++) {
543  check = &data->state.session[i];
544  if(!check->sessionid)
545  /* not session ID means blank entry */
546  continue;
547  if(curl_strequal(conn->name, check->name) &&
548  (conn->remote_port == check->remote_port) &&
549  Curl_ssl_config_matches(&conn->ssl_config, &check->ssl_config)) {
550  /* yes, we have a session ID! */
551  data->state.sessionage++; /* increase general age */
552  check->age = data->state.sessionage; /* set this as used in this age */
553  *ssl_sessionid = check->sessionid;
554  return FALSE;
555  }
556  }
557  *ssl_sessionid = (SSL_SESSION *)NULL;
558  return TRUE;
559 }
560 
561 /*
562  * Kill a single session ID entry in the cache.
563  */
564 static int Kill_Single_Session(struct curl_ssl_session *session)
565 {
566  if(session->sessionid) {
567  /* defensive check */
568 
569  /* free the ID */
570  SSL_SESSION_free(session->sessionid);
571  session->sessionid=NULL;
572  session->age = 0; /* fresh */
573 
574  Curl_free_ssl_config(&session->ssl_config);
575 
576  free(session->name);
577  session->name = NULL; /* no name */
578 
579  return 0; /* ok */
580  }
581  else
582  return 1;
583 }
584 
585 /*
586  * This function is called when the 'data' struct is going away. Close
587  * down everything and free all resources!
588  */
589 int Curl_SSL_Close_All(struct SessionHandle *data)
590 {
591  int i;
592 
593  if(data->state.session) {
594  for(i=0; i< data->set.ssl.numsessions; i++)
595  /* the single-killer function handles empty table slots */
596  Kill_Single_Session(&data->state.session[i]);
597 
598  /* free the cache data */
599  free(data->state.session);
600  }
601 #ifdef HAVE_OPENSSL_ENGINE_H
602  if(data->engine)
603  {
604  ENGINE_free(data->engine);
605  data->engine = NULL;
606  }
607 #endif
608  return 0;
609 }
610 
611 /*
612  * Extract the session id and store it in the session cache.
613  */
614 static int Store_SSL_Session(struct connectdata *conn,
615  struct ssl_connect_data *ssl)
616 {
617  SSL_SESSION *ssl_sessionid;
618  int i;
619  struct SessionHandle *data=conn->data; /* the mother of all structs */
620  struct curl_ssl_session *store = &data->state.session[0];
621  int oldest_age=data->state.session[0].age; /* zero if unused */
622 
623  /* ask OpenSSL, say please */
624 
625 #ifdef HAVE_SSL_GET1_SESSION
626  ssl_sessionid = SSL_get1_session(ssl->handle);
627 
628  /* SSL_get1_session() will increment the reference
629  count and the session will stay in memory until explicitly freed with
630  SSL_SESSION_free(3), regardless of its state.
631  This function was introduced in openssl 0.9.5a. */
632 #else
633  ssl_sessionid = SSL_get_session(ssl->handle);
634 
635  /* if SSL_get1_session() is unavailable, use SSL_get_session().
636  This is an inferior option because the session can be flushed
637  at any time by openssl. It is included only so curl compiles
638  under versions of openssl < 0.9.5a.
639 
640  WARNING: How curl behaves if it's session is flushed is
641  untested.
642  */
643 #endif
644 
645  /* Now we should add the session ID and the host name to the cache, (remove
646  the oldest if necessary) */
647 
648  /* find an empty slot for us, or find the oldest */
649  for(i=1; (i<data->set.ssl.numsessions) &&
650  data->state.session[i].sessionid; i++) {
651  if(data->state.session[i].age < oldest_age) {
652  oldest_age = data->state.session[i].age;
653  store = &data->state.session[i];
654  }
655  }
656  if(i == data->set.ssl.numsessions)
657  /* cache is full, we must "kill" the oldest entry! */
658  Kill_Single_Session(store);
659  else
660  store = &data->state.session[i]; /* use this slot */
661 
662  /* now init the session struct wisely */
663  store->sessionid = ssl_sessionid;
664  store->age = data->state.sessionage; /* set current age */
665  store->name = strdup(conn->name); /* clone host name */
666  store->remote_port = conn->remote_port; /* port number */
667 
669 
670  return 0;
671 }
672 
673 static int Curl_ASN1_UTCTIME_output(struct connectdata *conn,
674  const char *prefix,
675  ASN1_UTCTIME *tm)
676 {
677  char *asn1_string;
678  int gmt=FALSE;
679  int i;
680  int year=0,month=0,day=0,hour=0,minute=0,second=0;
681  struct SessionHandle *data = conn->data;
682 
683  if(!data->set.verbose)
684  return 0;
685 
686  i=tm->length;
687  asn1_string=(char *)tm->data;
688 
689  if(i < 10)
690  return 1;
691  if(asn1_string[i-1] == 'Z')
692  gmt=TRUE;
693  for (i=0; i<10; i++)
694  if((asn1_string[i] > '9') || (asn1_string[i] < '0'))
695  return 2;
696 
697  year= (asn1_string[0]-'0')*10+(asn1_string[1]-'0');
698  if(year < 50)
699  year+=100;
700 
701  month= (asn1_string[2]-'0')*10+(asn1_string[3]-'0');
702  if((month > 12) || (month < 1))
703  return 3;
704 
705  day= (asn1_string[4]-'0')*10+(asn1_string[5]-'0');
706  hour= (asn1_string[6]-'0')*10+(asn1_string[7]-'0');
707  minute= (asn1_string[8]-'0')*10+(asn1_string[9]-'0');
708 
709  if((asn1_string[10] >= '0') && (asn1_string[10] <= '9') &&
710  (asn1_string[11] >= '0') && (asn1_string[11] <= '9'))
711  second= (asn1_string[10]-'0')*10+(asn1_string[11]-'0');
712 
713  infof(data,
714  "%s%04d-%02d-%02d %02d:%02d:%02d %s\n",
715  prefix, year+1900, month, day, hour, minute, second, (gmt?"GMT":""));
716 
717  return 0;
718 }
719 
720 #endif
721 
722 /* ====================================================== */
723 #ifdef USE_SSLEAY
724 static int
725 cert_hostcheck(const char *certname, const char *hostname)
726 {
727  char *tmp;
728  const char *certdomain;
729 
730  if(!certname ||
731  strlen(certname)<3 ||
732  !hostname ||
733  !strlen(hostname)) /* sanity check */
734  return 0;
735 
736  if(curl_strequal(certname, hostname)) /* trivial case */
737  return 1;
738 
739  certdomain = certname + 1;
740 
741  if((certname[0] != '*') || (certdomain[0] != '.'))
742  return 0; /* not a wildcard certificate, check failed */
743 
744  if(!strchr(certdomain+1, '.'))
745  return 0; /* the certificate must have at least another dot in its name */
746 
747  /* find 'certdomain' within 'hostname' */
748  tmp = strstr(hostname, certdomain);
749  if(tmp) {
750  /* ok the certname's domain matches the hostname, let's check that it's a
751  tail-match */
752  if(curl_strequal(tmp, certdomain))
753  /* looks like a match. Just check we havent swallowed a '.' */
754  return tmp == strchr(hostname, '.');
755  else
756  return 0;
757  }
758  return 0;
759 }
760 
761 /* Quote from RFC2818 section 3.1 "Server Identity"
762 
763  If a subjectAltName extension of type dNSName is present, that MUST
764  be used as the identity. Otherwise, the (most specific) Common Name
765  field in the Subject field of the certificate MUST be used. Although
766  the use of the Common Name is existing practice, it is deprecated and
767  Certification Authorities are encouraged to use the dNSName instead.
768 
769  Matching is performed using the matching rules specified by
770  [RFC2459]. If more than one identity of a given type is present in
771  the certificate (e.g., more than one dNSName name, a match in any one
772  of the set is considered acceptable.) Names may contain the wildcard
773  character * which is considered to match any single domain name
774  component or component fragment. E.g., *.a.com matches foo.a.com but
775  not bar.foo.a.com. f*.com matches foo.com but not bar.com.
776 
777  In some cases, the URI is specified as an IP address rather than a
778  hostname. In this case, the iPAddress subjectAltName must be present
779  in the certificate and must exactly match the IP in the URI.
780 
781 */
782 static CURLcode verifyhost(struct connectdata *conn,
783  X509 *server_cert)
784 {
785  char peer_CN[257];
786  bool matched = FALSE; /* no alternative match yet */
787  int target = GEN_DNS; /* target type, GEN_DNS or GEN_IPADD */
788  int addrlen = 0;
789  struct SessionHandle *data = conn->data;
790  STACK_OF(GENERAL_NAME) *altnames;
791 #ifdef ENABLE_IPV6
792  struct in6_addr addr;
793 #else
794  struct in_addr addr;
795 #endif
796 
797 #ifdef ENABLE_IPV6
798  if(conn->bits.ipv6_ip &&
799  Curl_inet_pton(AF_INET6, conn->hostname, &addr)) {
800  target = GEN_IPADD;
801  addrlen = sizeof(struct in6_addr);
802  }
803  else
804 #endif
805  if(Curl_inet_pton(AF_INET, conn->hostname, &addr)) {
806  target = GEN_IPADD;
807  addrlen = sizeof(struct in_addr);
808  }
809 
810  /* get a "list" of alternative names */
811  altnames = X509_get_ext_d2i(server_cert, NID_subject_alt_name, NULL, NULL);
812 
813  if(altnames) {
814  int hostlen = 0;
815  int domainlen = 0;
816  char *domain = NULL;
817  int numalts;
818  int i;
819 
820  if(GEN_DNS == target) {
821  hostlen = strlen(conn->hostname);
822  domain = strchr(conn->hostname, '.');
823  if(domain)
824  domainlen = strlen(domain);
825  }
826 
827  /* get amount of alternatives, RFC2459 claims there MUST be at least
828  one, but we don't depend on it... */
829  numalts = sk_GENERAL_NAME_num(altnames);
830 
831  /* loop through all alternatives while none has matched */
832  for (i=0; (i<numalts) && !matched; i++) {
833  /* get a handle to alternative name number i */
834  const GENERAL_NAME *check = sk_GENERAL_NAME_value(altnames, i);
835 
836  /* only check alternatives of the same type the target is */
837  if(check->type == target) {
838  /* get data and length */
839  const char *altptr = (char *)ASN1_STRING_data(check->d.ia5);
840  const int altlen = ASN1_STRING_length(check->d.ia5);
841 
842  switch(target) {
843  case GEN_DNS: /* name comparison */
844  /* Is this an exact match? */
845  if((hostlen == altlen) &&
846  curl_strnequal(conn->hostname, altptr, hostlen))
847  matched = TRUE;
848 
849  /* Is this a wildcard match? */
850  else if((altptr[0] == '*') &&
851  (domainlen == altlen-1) &&
852  curl_strnequal(domain, altptr+1, domainlen))
853  matched = TRUE;
854  break;
855 
856  case GEN_IPADD: /* IP address comparison */
857  /* compare alternative IP address if the data chunk is the same size
858  our server IP address is */
859  if((altlen == addrlen) && !memcmp(altptr, &addr, altlen))
860  matched = TRUE;
861  break;
862  }
863  }
864  }
865  GENERAL_NAMES_free(altnames);
866  }
867 
868  if(matched)
869  /* an alternative name matched the server hostname */
870  infof(data, "\t subjectAltName: %s matched\n", conn->hostname);
871  else {
872  bool obtain=FALSE;
873  if(X509_NAME_get_text_by_NID(X509_get_subject_name(server_cert),
874  NID_commonName,
875  peer_CN,
876  sizeof(peer_CN)) < 0) {
877  if(data->set.ssl.verifyhost > 1) {
878  failf(data,
879  "SSL: unable to obtain common name from peer certificate");
881  }
882  else {
883  /* Consider verifyhost == 1 as an "OK" for a missing CN field, but we
884  output a note about the situation */
885  infof(data, "\t common name: WARNING couldn't obtain\n");
886  }
887  }
888  else
889  obtain = TRUE;
890 
891  if(obtain) {
892  if(!cert_hostcheck(peer_CN, conn->hostname)) {
893  if(data->set.ssl.verifyhost > 1) {
894  failf(data, "SSL: certificate subject name '%s' does not match "
895  "target host name '%s'", peer_CN, conn->hostname);
897  }
898  else
899  infof(data, "\t common name: %s (does not match '%s')\n",
900  peer_CN, conn->hostname);
901  }
902  else
903  infof(data, "\t common name: %s (matched)\n", peer_CN);
904  }
905  }
906 
907  return CURLE_OK;
908 }
909 #endif
910 
911 /* ====================================================== */
912 CURLcode
914  int sockindex)
915 {
916  CURLcode retcode = CURLE_OK;
917 
918 #ifdef USE_SSLEAY
919  struct SessionHandle *data = conn->data;
920  int err;
921  int what;
922  char * str;
923  SSL_METHOD *req_method;
924  SSL_SESSION *ssl_sessionid=NULL;
925  ASN1_TIME *certdate;
926  curl_socket_t sockfd = conn->sock[sockindex];
927  struct ssl_connect_data *connssl = &conn->ssl[sockindex];
928 
929  /* mark this is being ssl enabled from here on out. */
930  connssl->use = TRUE;
931 
932  if(!ssl_seeded || data->set.ssl.random_file || data->set.ssl.egdsocket) {
933  /* Make funny stuff to get random input */
934  random_the_seed(data);
935 
936  ssl_seeded = TRUE;
937  }
938 
939  /* check to see if we've been told to use an explicit SSL/TLS version */
940  switch(data->set.ssl.version) {
941  default:
943  /* we try to figure out version */
944  req_method = SSLv23_client_method();
945  break;
947  req_method = TLSv1_client_method();
948  break;
950  req_method = SSLv2_client_method();
951  break;
953  req_method = SSLv3_client_method();
954  break;
955  }
956 
957  connssl->ctx = SSL_CTX_new(req_method);
958 
959  if(!connssl->ctx) {
960  failf(data, "SSL: couldn't create a context!");
961  return CURLE_OUT_OF_MEMORY;
962  }
963 
964  /* OpenSSL contains code to work-around lots of bugs and flaws in various
965  SSL-implementations. SSL_CTX_set_options() is used to enabled those
966  work-arounds. The man page for this option states that SSL_OP_ALL enables
967  ll the work-arounds and that "It is usually safe to use SSL_OP_ALL to
968  enable the bug workaround options if compatibility with somewhat broken
969  implementations is desired."
970 
971  */
972  SSL_CTX_set_options(connssl->ctx, SSL_OP_ALL);
973 
974  if(data->set.cert) {
975  if(!cert_stuff(conn,
976  connssl->ctx,
977  data->set.cert,
978  data->set.cert_type,
979  data->set.key,
980  data->set.key_type)) {
981  /* failf() is already done in cert_stuff() */
982  return CURLE_SSL_CERTPROBLEM;
983  }
984  }
985 
986  if(data->set.ssl.cipher_list) {
987  if(!SSL_CTX_set_cipher_list(connssl->ctx,
988  data->set.ssl.cipher_list)) {
989  failf(data, "failed setting cipher list");
990  return CURLE_SSL_CIPHER;
991  }
992  }
993 
994  if (data->set.ssl.CAfile || data->set.ssl.CApath) {
995  /* tell SSL where to find CA certificates that are used to verify
996  the servers certificate. */
997  if (!SSL_CTX_load_verify_locations(connssl->ctx, data->set.ssl.CAfile,
998  data->set.ssl.CApath)) {
999  if (data->set.ssl.verifypeer) {
1000  /* Fail if we insist on successfully verifying the server. */
1001  failf(data,"error setting certificate verify locations:\n"
1002  " CAfile: %s\n CApath: %s\n",
1003  data->set.ssl.CAfile ? data->set.ssl.CAfile : "none",
1004  data->set.ssl.CApath ? data->set.ssl.CApath : "none");
1005  return CURLE_SSL_CACERT;
1006  }
1007  else {
1008  /* Just continue with a warning if no strict certificate verification
1009  is required. */
1010  infof(data, "error setting certificate verify locations,"
1011  " continuing anyway:\n");
1012  }
1013  }
1014  else {
1015  /* Everything is fine. */
1016  infof(data, "successfully set certificate verify locations:\n");
1017  }
1018  infof(data,
1019  " CAfile: %s\n"
1020  " CApath: %s\n",
1021  data->set.ssl.CAfile ? data->set.ssl.CAfile : "none",
1022  data->set.ssl.CApath ? data->set.ssl.CApath : "none");
1023  }
1024  /* SSL always tries to verify the peer, this only says whether it should
1025  * fail to connect if the verification fails, or if it should continue
1026  * anyway. In the latter case the result of the verification is checked with
1027  * SSL_get_verify_result() below. */
1028  SSL_CTX_set_verify(connssl->ctx,
1029  data->set.ssl.verifypeer?SSL_VERIFY_PEER:SSL_VERIFY_NONE,
1030  cert_verify_callback);
1031 
1032  /* give application a chance to interfere with SSL set up. */
1033  if(data->set.ssl.fsslctx) {
1034  retcode = (*data->set.ssl.fsslctx)(data, connssl->ctx,
1035  data->set.ssl.fsslctxp);
1036  if(retcode) {
1037  failf(data,"error signaled by ssl ctx callback");
1038  return retcode;
1039  }
1040  }
1041 
1042  /* Lets make an SSL structure */
1043  connssl->handle = SSL_new(connssl->ctx);
1044  SSL_set_connect_state(connssl->handle);
1045 
1046  connssl->server_cert = 0x0;
1047 
1048  if(!conn->bits.reuse) {
1049  /* We're not re-using a connection, check if there's a cached ID we
1050  can/should use here! */
1051  if(!Get_SSL_Session(conn, &ssl_sessionid)) {
1052  /* we got a session id, use it! */
1053  SSL_set_session(connssl->handle, ssl_sessionid);
1054  /* Informational message */
1055  infof (data, "SSL re-using session ID\n");
1056  }
1057  }
1058 
1059  /* pass the raw socket into the SSL layers */
1060  SSL_set_fd(connssl->handle, sockfd);
1061 
1062  while(1) {
1063  fd_set writefd;
1064  fd_set readfd;
1065  struct timeval interval;
1066  long timeout_ms;
1067 
1068  /* Find out if any timeout is set. If not, use 300 seconds.
1069  Otherwise, figure out the most strict timeout of the two possible one
1070  and then how much time that has elapsed to know how much time we
1071  allow for the connect call */
1072  if(data->set.timeout || data->set.connecttimeout) {
1073  double has_passed;
1074 
1075  /* Evaluate in milliseconds how much time that has passed */
1076  has_passed = Curl_tvdiff(Curl_tvnow(), data->progress.start);
1077 
1078 #ifndef min
1079 #define min(a, b) ((a) < (b) ? (a) : (b))
1080 #endif
1081 
1082  /* get the most strict timeout of the ones converted to milliseconds */
1083  if(data->set.timeout &&
1084  (data->set.timeout>data->set.connecttimeout))
1085  timeout_ms = data->set.timeout*1000;
1086  else
1087  timeout_ms = data->set.connecttimeout*1000;
1088 
1089  /* subtract the passed time */
1090  timeout_ms -= (long)has_passed;
1091 
1092  if(timeout_ms < 0) {
1093  /* a precaution, no need to continue if time already is up */
1094  failf(data, "SSL connection timeout");
1096  }
1097  }
1098  else
1099  /* no particular time-out has been set */
1100  timeout_ms=300000; /* milliseconds, default to five minutes */
1101 
1102 
1103  FD_ZERO(&writefd);
1104  FD_ZERO(&readfd);
1105 
1106  err = SSL_connect(connssl->handle);
1107 
1108  /* 1 is fine
1109  0 is "not successful but was shut down controlled"
1110  <0 is "handshake was not successful, because a fatal error occurred" */
1111  if(1 != err) {
1112  int detail = SSL_get_error(connssl->handle, err);
1113 
1114  if(SSL_ERROR_WANT_READ == detail)
1115  FD_SET(sockfd, &readfd);
1116  else if(SSL_ERROR_WANT_WRITE == detail)
1117  FD_SET(sockfd, &writefd);
1118  else {
1119  /* untreated error */
1120  char error_buffer[120]; /* OpenSSL documents that this must be at least
1121  120 bytes long. */
1122 
1123  detail = ERR_get_error(); /* Gets the earliest error code from the
1124  thread's error queue and removes the
1125  entry. */
1126 
1127  switch(detail) {
1128  case 0x1407E086:
1129  /* 1407E086:
1130  SSL routines:
1131  SSL2_SET_CERTIFICATE:
1132  certificate verify failed */
1133  case 0x14090086:
1134  /* 14090086:
1135  SSL routines:
1136  SSL3_GET_SERVER_CERTIFICATE:
1137  certificate verify failed */
1138  failf(data,
1139  "SSL certificate problem, verify that the CA cert is OK");
1140  return CURLE_SSL_CACERT;
1141  default:
1142  /* detail is already set to the SSL error above */
1143  failf(data, "SSL: %s", ERR_error_string(detail, error_buffer));
1144  /* OpenSSL 0.9.6 and later has a function named
1145  ERRO_error_string_n() that takes the size of the buffer as a third
1146  argument, and we should possibly switch to using that one in the
1147  future. */
1148  return CURLE_SSL_CONNECT_ERROR;
1149  }
1150  }
1151  }
1152  else
1153  /* we have been connected fine, get out of the connect loop */
1154  break;
1155 
1156  interval.tv_sec = timeout_ms/1000;
1157  timeout_ms -= interval.tv_sec*1000;
1158 
1159  interval.tv_usec = timeout_ms*1000;
1160 
1161  while(1) {
1162  what = select(sockfd+1, &readfd, &writefd, NULL, &interval);
1163  if(what > 0)
1164  /* reabable or writable, go loop in the outer loop */
1165  break;
1166  else if(0 == what) {
1167  /* timeout */
1168  failf(data, "SSL connection timeout");
1169  return CURLE_OPERATION_TIMEDOUT;
1170  }
1171  else {
1172 #if !defined(WIN32) && defined(EINTR)
1173  /* For platforms without EINTR all errnos are bad */
1174  if (errno == EINTR)
1175  continue; /* retry the select() */
1176 #endif
1177  /* anything other than the unimportant EINTR is fatally bad */
1178  failf(data, "select on SSL socket, errno: %d", Curl_ourerrno());
1179  return CURLE_SSL_CONNECT_ERROR;
1180  }
1181  } /* while()-loop for the select() */
1182  } /* while()-loop for the SSL_connect() */
1183 
1184  /* Informational message */
1185  infof (data, "SSL connection using %s\n",
1186  SSL_get_cipher(connssl->handle));
1187 
1188  if(!ssl_sessionid) {
1189  /* Since this is not a cached session ID, then we want to stach this one
1190  in the cache! */
1191  Store_SSL_Session(conn, connssl);
1192  }
1193 
1194 
1195  /* Get server's certificate (note: beware of dynamic allocation) - opt */
1196  /* major serious hack alert -- we should check certificates
1197  * to authenticate the server; otherwise we risk man-in-the-middle
1198  * attack
1199  */
1200 
1201  connssl->server_cert = SSL_get_peer_certificate(connssl->handle);
1202  if(!connssl->server_cert) {
1203  failf(data, "SSL: couldn't get peer certificate!");
1205  }
1206  infof (data, "Server certificate:\n");
1207 
1208  str = X509_NAME_oneline(X509_get_subject_name(connssl->server_cert),
1209  NULL, 0);
1210  if(!str) {
1211  failf(data, "SSL: couldn't get X509-subject!");
1212  X509_free(connssl->server_cert);
1213  return CURLE_SSL_CONNECT_ERROR;
1214  }
1215  infof(data, "\t subject: %s\n", str);
1216  CRYPTO_free(str);
1217 
1218  certdate = X509_get_notBefore(connssl->server_cert);
1219  Curl_ASN1_UTCTIME_output(conn, "\t start date: ", certdate);
1220 
1221  certdate = X509_get_notAfter(connssl->server_cert);
1222  Curl_ASN1_UTCTIME_output(conn, "\t expire date: ", certdate);
1223 
1224  if(data->set.ssl.verifyhost) {
1225  retcode = verifyhost(conn, connssl->server_cert);
1226  if(retcode) {
1227  X509_free(connssl->server_cert);
1228  return retcode;
1229  }
1230  }
1231 
1232  str = X509_NAME_oneline(X509_get_issuer_name(connssl->server_cert),
1233  NULL, 0);
1234  if(!str) {
1235  failf(data, "SSL: couldn't get X509-issuer name!");
1236  retcode = CURLE_SSL_CONNECT_ERROR;
1237  }
1238  else {
1239  infof(data, "\t issuer: %s\n", str);
1240  CRYPTO_free(str);
1241 
1242  /* We could do all sorts of certificate verification stuff here before
1243  deallocating the certificate. */
1244 
1245  data->set.ssl.certverifyresult=SSL_get_verify_result(connssl->handle);
1246  if(data->set.ssl.certverifyresult != X509_V_OK) {
1247  if(data->set.ssl.verifypeer) {
1248  /* We probably never reach this, because SSL_connect() will fail
1249  and we return earlyer if verifypeer is set? */
1250  failf(data, "SSL certificate verify result: %d",
1251  data->set.ssl.certverifyresult);
1252  retcode = CURLE_SSL_PEER_CERTIFICATE;
1253  }
1254  else
1255  infof(data, "SSL certificate verify result: %d, continuing anyway.\n",
1256  data->set.ssl.certverifyresult);
1257  }
1258  else
1259  infof(data, "SSL certificate verify ok.\n");
1260  }
1261 
1262  X509_free(connssl->server_cert);
1263 #else /* USE_SSLEAY */
1264  (void)conn;
1265  (void)sockindex;
1266 #endif
1267  return retcode;
1268 }
struct ssl_connect_data ssl[2]
Definition: urldata.h:459
struct ConnectBits bits
Definition: urldata.h:462
char buffer[BUFSIZE+1]
Definition: urldata.h:679
long numsessions
Definition: urldata.h:156
struct timeval start
Definition: urldata.h:629
int curl_socket_t
Definition: setup.h:254
#define FIRSTSOCKET
Definition: urldata.h:394
struct ssl_config_data ssl
Definition: urldata.h:829
long tv_sec
Definition: timeval.h:37
long connecttimeout
Definition: urldata.h:795
void * fsslctxp
Definition: urldata.h:158
#define failf
Definition: sendf.h:32
struct curl_ssl_session * session
Definition: urldata.h:691
bool Curl_clone_ssl_config(struct ssl_config_data *source, struct ssl_config_data *dest)
Definition: url.c:3426
CURLcode
Definition: curl.h:209
GLuint GLuint GLsizei GLenum type
Definition: glext.h:2845
unsigned short remote_port
Definition: urldata.h:434
GLenum GLsizei len
Definition: glext.h:3472
struct UrlState state
Definition: urldata.h:903
int Curl_ourerrno(void)
Definition: connect.c:98
int i
Definition: process.py:33
GLuint GLuint num
Definition: glext.h:5390
char * CApath
Definition: urldata.h:151
char * egdsocket
Definition: urldata.h:154
struct Progress progress
Definition: urldata.h:902
struct ssl_config_data ssl_config
Definition: urldata.h:460
void Curl_SSL_cleanup(void)
Definition: ssluse.c:427
char * random_file
Definition: urldata.h:153
bool reuse
Definition: urldata.h:279
long timeout
Definition: urldata.h:794
char * cipher_list
Definition: urldata.h:155
void * sessionid
Definition: urldata.h:164
long tv_usec
Definition: timeval.h:38
bool ipv6_ip
Definition: urldata.h:284
struct ssl_config_data ssl_config
Definition: urldata.h:167
CURLcode Curl_SSL_InitSessions(struct SessionHandle *, long)
char * hostname
Definition: urldata.h:432
#define NULL
Definition: Lib.h:88
long verifypeer
Definition: urldata.h:147
char * Curl_FormBoundary(void)
Definition: formdata.c:1031
#define select(args...)
Definition: amigaos.h:39
GLsizei GLsizei GLenum GLenum const GLvoid * data
Definition: glext.h:2853
char * key
Definition: urldata.h:806
void Curl_SSL_init(void)
Definition: ssluse.c:403
int() curl_strnequal(const char *s1, const char *s2, size_t n)
Definition: strequal.c:57
curl_ssl_ctx_callback fsslctx
Definition: urldata.h:157
long Curl_tvdiff(struct timeval newer, struct timeval older)
Definition: timeval.c:92
GLenum const GLvoid * addr
Definition: glext.h:5393
Definition: curl.h:210
struct SessionHandle * data
Definition: urldata.h:403
char * cert_type
Definition: urldata.h:805
int Curl_inet_pton(int af, const char *src, void *dst)
Definition: inet_pton.c:73
long verifyhost
Definition: urldata.h:148
char * strdup(char *s1)
Definition: main.c:183
char * name
Definition: urldata.h:430
char * key_passwd
Definition: urldata.h:808
static WindowRef ValidModeCallbackProc inCallback OSStatus err
char * cert
Definition: urldata.h:804
curl_socket_t sock[2]
Definition: urldata.h:454
bool verbose
Definition: urldata.h:871
bool Curl_ssl_config_matches(struct ssl_config_data *data, struct ssl_config_data *needle)
Definition: url.c:3409
#define infof
Definition: sendf.h:31
typedef void(APIENTRYP PFNGLBLENDCOLORPROC)(GLclampf red
#define FALSE
Definition: mprintf.c:70
struct timeval Curl_tvnow(void)
Definition: timeval.c:81
long sessionage
Definition: urldata.h:692
struct UserDefined set
Definition: urldata.h:898
void Curl_free_ssl_config(struct ssl_config_data *sslc)
Definition: url.c:3466
char * key_type
Definition: urldata.h:807
#define TRUE
Definition: mprintf.c:69
unsigned short remote_port
Definition: urldata.h:166
int Curl_SSL_Close_All(struct SessionHandle *data)
CURLcode Curl_SSLConnect(struct connectdata *conn, int sockindex)
Definition: ssluse.c:913
void Curl_SSL_Close(struct connectdata *conn)
Definition: ssluse.c:458
idSession * session
Definition: Session.cpp:48
int() curl_strequal(const char *s1, const char *s2)
Definition: strequal.c:37
long certverifyresult
Definition: urldata.h:146
#define CURLE_OPERATION_TIMEDOUT
Definition: curl.h:286
char * CAfile
Definition: urldata.h:152
#define BUFSIZE
Definition: urldata.h:104