1/***************************************************************************
2 *                                  _   _ ____  _
3 *  Project                     ___| | | |  _ \| |
4 *                             / __| | | | |_) | |
5 *                            | (__| |_| |  _ <| |___
6 *                             \___|\___/|_| \_\_____|
7 *
8 * Copyright (C) 2010, DirecTV
9 * contact: Eric Hu <ehu@directv.com>
10 *
11 * This software is licensed as described in the file COPYING, which
12 * you should have received as part of this distribution. The terms
13 * are also available at http://curl.haxx.se/docs/copyright.html.
14 *
15 * You may opt to use, copy, modify, merge, publish, distribute and/or sell
16 * copies of the Software, and permit persons to whom the Software is
17 * furnished to do so, under the terms of the COPYING file.
18 *
19 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
20 * KIND, either express or implied.
21 *
22 ***************************************************************************/
23
24/*
25 * Source file for all axTLS-specific code for the TLS/SSL layer. No code
26 * but sslgen.c should ever call or use these functions.
27 */
28
29#include "setup.h"
30#ifdef USE_AXTLS
31#include <axTLS/ssl.h>
32#include "axtls.h"
33
34#include <string.h>
35#include <stdlib.h>
36#include <ctype.h>
37#ifdef HAVE_SYS_SOCKET_H
38#include <sys/socket.h>
39#endif
40
41#include "sendf.h"
42#include "inet_pton.h"
43#include "sslgen.h"
44#include "parsedate.h"
45#include "connect.h" /* for the connect timeout */
46#include "select.h"
47#define _MPRINTF_REPLACE /* use our functions only */
48#include <curl/mprintf.h>
49#include "curl_memory.h"
50/* The last #include file should be: */
51#include "memdebug.h"
52
53/* SSL_read is opied from axTLS compat layer */
54static int SSL_read(SSL *ssl, void *buf, int num)
55{
56  uint8_t *read_buf;
57  int ret;
58
59  while((ret = ssl_read(ssl, &read_buf)) == SSL_OK);
60
61  if(ret > SSL_OK){
62    memcpy(buf, read_buf, ret > num ? num : ret);
63  }
64
65  return ret;
66}
67
68/* Global axTLS init, called from Curl_ssl_init() */
69int Curl_axtls_init(void)
70{
71/* axTLS has no global init.  Everything is done through SSL and SSL_CTX
72 * structs stored in connectdata structure.  Perhaps can move to axtls.h.
73 */
74  return 1;
75}
76
77int Curl_axtls_cleanup(void)
78{
79  /* axTLS has no global cleanup.  Perhaps can move this to axtls.h. */
80  return 1;
81}
82
83static CURLcode map_error_to_curl(int axtls_err)
84{
85  switch (axtls_err) {
86  case SSL_ERROR_NOT_SUPPORTED:
87  case SSL_ERROR_INVALID_VERSION:
88  case -70:                       /* protocol version alert from server */
89    return CURLE_UNSUPPORTED_PROTOCOL;
90    break;
91  case SSL_ERROR_NO_CIPHER:
92    return CURLE_SSL_CIPHER;
93    break;
94  case SSL_ERROR_BAD_CERTIFICATE: /* this may be bad server cert too */
95  case SSL_ERROR_NO_CERT_DEFINED:
96  case -42:                       /* bad certificate alert from server */
97  case -43:                       /* unsupported cert alert from server */
98  case -44:                       /* cert revoked alert from server */
99  case -45:                       /* cert expired alert from server */
100  case -46:                       /* cert unknown alert from server */
101    return CURLE_SSL_CERTPROBLEM;
102    break;
103  case SSL_X509_ERROR(X509_NOT_OK):
104  case SSL_X509_ERROR(X509_VFY_ERROR_NO_TRUSTED_CERT):
105  case SSL_X509_ERROR(X509_VFY_ERROR_BAD_SIGNATURE):
106  case SSL_X509_ERROR(X509_VFY_ERROR_NOT_YET_VALID):
107  case SSL_X509_ERROR(X509_VFY_ERROR_EXPIRED):
108  case SSL_X509_ERROR(X509_VFY_ERROR_SELF_SIGNED):
109  case SSL_X509_ERROR(X509_VFY_ERROR_INVALID_CHAIN):
110  case SSL_X509_ERROR(X509_VFY_ERROR_UNSUPPORTED_DIGEST):
111  case SSL_X509_ERROR(X509_INVALID_PRIV_KEY):
112    return CURLE_PEER_FAILED_VERIFICATION;
113    break;
114  case -48:                       /* unknown ca alert from server */
115    return CURLE_SSL_CACERT;
116    break;
117  case -49:                       /* access denied alert from server */
118    return CURLE_REMOTE_ACCESS_DENIED;
119    break;
120  case SSL_ERROR_CONN_LOST:
121  case SSL_ERROR_SOCK_SETUP_FAILURE:
122  case SSL_ERROR_INVALID_HANDSHAKE:
123  case SSL_ERROR_INVALID_PROT_MSG:
124  case SSL_ERROR_INVALID_HMAC:
125  case SSL_ERROR_INVALID_SESSION:
126  case SSL_ERROR_INVALID_KEY:     /* it's too bad this doesn't map better */
127  case SSL_ERROR_FINISHED_INVALID:
128  case SSL_ERROR_NO_CLIENT_RENOG:
129  default:
130    return CURLE_SSL_CONNECT_ERROR;
131    break;
132  }
133}
134
135static Curl_recv axtls_recv;
136static Curl_send axtls_send;
137
138/*
139 * This function is called after the TCP connect has completed. Setup the TLS
140 * layer and do all necessary magic.
141 */
142CURLcode
143Curl_axtls_connect(struct connectdata *conn,
144                  int sockindex)
145
146{
147  struct SessionHandle *data = conn->data;
148  SSL_CTX *ssl_ctx;
149  SSL *ssl;
150  int cert_types[] = {SSL_OBJ_X509_CERT, SSL_OBJ_PKCS12, 0};
151  int key_types[] = {SSL_OBJ_RSA_KEY, SSL_OBJ_PKCS8, SSL_OBJ_PKCS12, 0};
152  int i, ssl_fcn_return;
153  const uint8_t *ssl_sessionid;
154  size_t ssl_idsize;
155  const char *x509;
156
157  /* Assuming users will not compile in custom key/cert to axTLS */
158  uint32_t client_option = SSL_NO_DEFAULT_KEY|SSL_SERVER_VERIFY_LATER;
159
160  if(conn->ssl[sockindex].state == ssl_connection_complete)
161    /* to make us tolerant against being called more than once for the
162       same connection */
163    return CURLE_OK;
164
165  /* axTLS only supports TLSv1 */
166  /* check to see if we've been told to use an explicit SSL/TLS version */
167  switch(data->set.ssl.version) {
168  case CURL_SSLVERSION_DEFAULT:
169  case CURL_SSLVERSION_TLSv1:
170    break;
171  default:
172    failf(data, "axTLS only supports TLSv1");
173    return CURLE_SSL_CONNECT_ERROR;
174  }
175
176#ifdef  AXTLSDEBUG
177  client_option |= SSL_DISPLAY_STATES | SSL_DISPLAY_RSA | SSL_DISPLAY_CERTS;
178#endif /* AXTLSDEBUG */
179
180  /* Allocate an SSL_CTX struct */
181  ssl_ctx = ssl_ctx_new(client_option, SSL_DEFAULT_CLNT_SESS);
182  if(ssl_ctx == NULL) {
183    failf(data, "unable to create client SSL context");
184    return CURLE_SSL_CONNECT_ERROR;
185  }
186
187  /* Load the trusted CA cert bundle file */
188  if(data->set.ssl.CAfile) {
189    if(ssl_obj_load(ssl_ctx, SSL_OBJ_X509_CACERT, data->set.ssl.CAfile, NULL)
190       != SSL_OK){
191      infof(data, "error reading ca cert file %s \n",
192            data->set.ssl.CAfile);
193      if(data->set.ssl.verifypeer){
194        Curl_axtls_close(conn, sockindex);
195        return CURLE_SSL_CACERT_BADFILE;
196      }
197    }
198    else
199      infof(data, "found certificates in %s\n", data->set.ssl.CAfile);
200  }
201
202  /* gtls.c tasks we're skipping for now:
203   * 1) certificate revocation list checking
204   * 2) dns name assignment to host
205   * 3) set protocol priority.  axTLS is TLSv1 only, so can probably ignore
206   * 4) set certificate priority.  axTLS ignores type and sends certs in
207   *  order added.  can probably ignore this.
208   */
209
210  /* Load client certificate */
211  if(data->set.str[STRING_CERT]){
212    i=0;
213    /* Instead of trying to analyze cert type here, let axTLS try them all. */
214    while(cert_types[i] != 0){
215      ssl_fcn_return = ssl_obj_load(ssl_ctx, cert_types[i],
216                                    data->set.str[STRING_CERT], NULL);
217      if(ssl_fcn_return == SSL_OK){
218        infof(data, "successfully read cert file %s \n",
219              data->set.str[STRING_CERT]);
220        break;
221      }
222      i++;
223    }
224    /* Tried all cert types, none worked. */
225    if(cert_types[i] == 0){
226      failf(data, "%s is not x509 or pkcs12 format",
227            data->set.str[STRING_CERT]);
228      Curl_axtls_close(conn, sockindex);
229      return CURLE_SSL_CERTPROBLEM;
230    }
231  }
232
233  /* Load client key.
234     If a pkcs12 file successfully loaded a cert, then there's nothing to do
235     because the key has already been loaded. */
236  if(data->set.str[STRING_KEY] && cert_types[i] != SSL_OBJ_PKCS12){
237    i=0;
238    /* Instead of trying to analyze key type here, let axTLS try them all. */
239    while(key_types[i] != 0){
240      ssl_fcn_return = ssl_obj_load(ssl_ctx, key_types[i],
241                                    data->set.str[STRING_KEY], NULL);
242      if(ssl_fcn_return == SSL_OK){
243        infof(data, "successfully read key file %s \n",
244              data->set.str[STRING_KEY]);
245        break;
246      }
247      i++;
248    }
249    /* Tried all key types, none worked. */
250    if(key_types[i] == 0){
251      failf(data, "Failure: %s is not a supported key file",
252            data->set.str[STRING_KEY]);
253      Curl_axtls_close(conn, sockindex);
254      return CURLE_SSL_CONNECT_ERROR;
255    }
256  }
257
258  /* gtls.c does more here that is being left out for now
259   * 1) set session credentials.  can probably ignore since axtls puts this
260   *    info in the ssl_ctx struct
261   * 2) setting up callbacks.  these seem gnutls specific
262   */
263
264  /* In axTLS, handshaking happens inside ssl_client_new. */
265  if(!Curl_ssl_getsessionid(conn, (void **) &ssl_sessionid, &ssl_idsize)) {
266    /* we got a session id, use it! */
267    infof (data, "SSL re-using session ID\n");
268    ssl = ssl_client_new(ssl_ctx, conn->sock[sockindex],
269                         ssl_sessionid, (uint8_t)ssl_idsize);
270  }
271  else
272    ssl = ssl_client_new(ssl_ctx, conn->sock[sockindex], NULL, 0);
273
274  /* Check to make sure handshake was ok. */
275  ssl_fcn_return = ssl_handshake_status(ssl);
276  if(ssl_fcn_return != SSL_OK){
277    Curl_axtls_close(conn, sockindex);
278    ssl_display_error(ssl_fcn_return); /* goes to stdout. */
279    return map_error_to_curl(ssl_fcn_return);
280  }
281  infof (data, "handshake completed successfully\n");
282
283  /* Here, gtls.c gets the peer certificates and fails out depending on
284   * settings in "data."  axTLS api doesn't have get cert chain fcn, so omit?
285   */
286
287  /* Verify server's certificate */
288  if(data->set.ssl.verifypeer){
289    if(ssl_verify_cert(ssl) != SSL_OK){
290      Curl_axtls_close(conn, sockindex);
291      failf(data, "server cert verify failed");
292      return CURLE_SSL_CONNECT_ERROR;
293    }
294  }
295  else
296    infof(data, "\t server certificate verification SKIPPED\n");
297
298  /* Here, gtls.c does issuer verification. axTLS has no straightforward
299   * equivalent, so omitting for now.*/
300
301  /* See if common name was set in server certificate */
302  x509 = ssl_get_cert_dn(ssl, SSL_X509_CERT_COMMON_NAME);
303  if(x509 == NULL)
304    infof(data, "error fetching CN from cert\n");
305
306  /* Here, gtls.c does the following
307   * 1) x509 hostname checking per RFC2818.  axTLS doesn't support this, but
308   *    it seems useful.  Omitting for now.
309   * 2) checks cert validity based on time.  axTLS does this in ssl_verify_cert
310   * 3) displays a bunch of cert information.  axTLS doesn't support most of
311   *    this, but a couple fields are available.
312   */
313
314  /* General housekeeping */
315  conn->ssl[sockindex].state = ssl_connection_complete;
316  conn->ssl[sockindex].ssl = ssl;
317  conn->ssl[sockindex].ssl_ctx = ssl_ctx;
318  conn->recv[sockindex] = axtls_recv;
319  conn->send[sockindex] = axtls_send;
320
321  /* Put our freshly minted SSL session in cache */
322  ssl_idsize = ssl_get_session_id_size(ssl);
323  ssl_sessionid = ssl_get_session_id(ssl);
324  if(Curl_ssl_addsessionid(conn, (void *) ssl_sessionid, ssl_idsize)
325     != CURLE_OK)
326    infof (data, "failed to add session to cache\n");
327
328  return CURLE_OK;
329}
330
331
332/* return number of sent (non-SSL) bytes */
333static ssize_t axtls_send(struct connectdata *conn,
334                          int sockindex,
335                          const void *mem,
336                          size_t len,
337                          CURLcode *err)
338{
339  /* ssl_write() returns 'int' while write() and send() returns 'size_t' */
340  int rc = ssl_write(conn->ssl[sockindex].ssl, mem, (int)len);
341
342  infof(conn->data, "  axtls_send\n");
343
344  if(rc < 0 ) {
345    *err = map_error_to_curl(rc);
346    rc = -1; /* generic error code for send failure */
347  }
348
349  *err = CURLE_OK;
350  return rc;
351}
352
353void Curl_axtls_close_all(struct SessionHandle *data)
354{
355  (void)data;
356  infof(data, "  Curl_axtls_close_all\n");
357}
358
359void Curl_axtls_close(struct connectdata *conn, int sockindex)
360{
361  struct ssl_connect_data *connssl = &conn->ssl[sockindex];
362
363  infof(conn->data, "  Curl_axtls_close\n");
364  if(connssl->ssl) {
365    /* line from ssluse.c: (void)SSL_shutdown(connssl->ssl);
366       axTLS compat layer does nothing for SSL_shutdown */
367
368    /* The following line is from ssluse.c.  There seems to be no axTLS
369       equivalent.  ssl_free and ssl_ctx_free close things.
370       SSL_set_connect_state(connssl->handle); */
371
372    ssl_free (connssl->ssl);
373    connssl->ssl = NULL;
374  }
375  if(connssl->ssl_ctx) {
376    ssl_ctx_free (connssl->ssl_ctx);
377    connssl->ssl_ctx = NULL;
378  }
379}
380
381/*
382 * This function is called to shut down the SSL layer but keep the
383 * socket open (CCC - Clear Command Channel)
384 */
385int Curl_axtls_shutdown(struct connectdata *conn, int sockindex)
386{
387  /* Outline taken from ssluse.c since functions are in axTLS compat layer.
388     axTLS's error set is much smaller, so a lot of error-handling was removed.
389   */
390  int retval = 0;
391  struct ssl_connect_data *connssl = &conn->ssl[sockindex];
392  struct SessionHandle *data = conn->data;
393  char buf[120]; /* We will use this for the OpenSSL error buffer, so it has
394                    to be at least 120 bytes long. */
395  ssize_t nread;
396
397  infof(conn->data, "  Curl_axtls_shutdown\n");
398
399  /* This has only been tested on the proftpd server, and the mod_tls code
400     sends a close notify alert without waiting for a close notify alert in
401     response. Thus we wait for a close notify alert from the server, but
402     we do not send one. Let's hope other servers do the same... */
403
404  /* axTLS compat layer does nothing for SSL_shutdown, so we do nothing too
405  if(data->set.ftp_ccc == CURLFTPSSL_CCC_ACTIVE)
406      (void)SSL_shutdown(connssl->ssl);
407  */
408
409  if(connssl->ssl) {
410    int what = Curl_socket_ready(conn->sock[sockindex],
411                                 CURL_SOCKET_BAD, SSL_SHUTDOWN_TIMEOUT);
412    if(what > 0) {
413      /* Something to read, let's do it and hope that it is the close
414         notify alert from the server */
415      nread = (ssize_t)SSL_read(conn->ssl[sockindex].ssl, buf,
416                                sizeof(buf));
417
418      if(nread < SSL_OK){
419        failf(data, "close notify alert not received during shutdown");
420        retval = -1;
421      }
422    }
423    else if(0 == what) {
424      /* timeout */
425      failf(data, "SSL shutdown timeout");
426    }
427    else {
428      /* anything that gets here is fatally bad */
429      failf(data, "select/poll on SSL socket, errno: %d", SOCKERRNO);
430      retval = -1;
431    }
432
433    ssl_free (connssl->ssl);
434    connssl->ssl = NULL;
435  }
436  return retval;
437}
438
439static ssize_t axtls_recv(struct connectdata *conn, /* connection data */
440                          int num,                  /* socketindex */
441                          char *buf,                /* store read data here */
442                          size_t buffersize,        /* max amount to read */
443                          CURLcode *err)
444{
445  struct ssl_connect_data *connssl = &conn->ssl[num];
446  ssize_t ret = 0;
447
448  infof(conn->data, "  axtls_recv\n");
449
450  if(connssl){
451    ret = (ssize_t)SSL_read(conn->ssl[num].ssl, buf, (int)buffersize);
452
453    /* axTLS isn't terribly generous about error reporting */
454    /* With patched axTLS, SSL_CLOSE_NOTIFY=-3.  Hard-coding until axTLS
455       team approves proposed fix. */
456    if(ret == -3 ){
457      Curl_axtls_close(conn, num);
458    }
459    else if(ret < 0) {
460      failf(conn->data, "axTLS recv error (%d)", (int)ret);
461      *err = map_error_to_curl(ret);
462      return -1;
463    }
464  }
465
466  *err = CURLE_OK;
467  return ret;
468}
469
470/*
471 * Return codes:
472 *     1 means the connection is still in place
473 *     0 means the connection has been closed
474 *    -1 means the connection status is unknown
475 */
476int Curl_axtls_check_cxn(struct connectdata *conn)
477{
478  /* ssluse.c line: rc = SSL_peek(conn->ssl[FIRSTSOCKET].ssl, (void*)&buf, 1);
479     axTLS compat layer always returns the last argument, so connection is
480     always alive? */
481
482  infof(conn->data, "  Curl_axtls_check_cxn\n");
483   return 1; /* connection still in place */
484}
485
486void Curl_axtls_session_free(void *ptr)
487{
488  (void)ptr;
489  /* free the ID */
490  /* both ssluse.c and gtls.c do something here, but axTLS's OpenSSL
491     compatibility layer does nothing, so we do nothing too. */
492}
493
494size_t Curl_axtls_version(char *buffer, size_t size)
495{
496  return snprintf(buffer, size, "axTLS/%s", ssl_version());
497}
498
499#endif /* USE_AXTLS */
500