From 59cf93ccdbaa5e866f9de6b2d9b1ae5cee84863f Mon Sep 17 00:00:00 2001 From: Quinn Slack Date: Wed, 19 Jan 2011 20:35:02 +0100 Subject: TLS-SRP: support added when using GnuTLS --- lib/gtls.c | 71 +++++++++++++++++++++++++++++++++++++++++++++++++++++----- lib/strerror.c | 5 ++++- lib/url.c | 27 ++++++++++++++++++++++ lib/urldata.h | 14 ++++++++++++ lib/version.c | 3 +++ 5 files changed, 114 insertions(+), 6 deletions(-) (limited to 'lib') diff --git a/lib/gtls.c b/lib/gtls.c index 9a87c39a8..b5ef8fb99 100644 --- a/lib/gtls.c +++ b/lib/gtls.c @@ -346,6 +346,29 @@ gtls_connect_step1(struct connectdata *conn, return CURLE_SSL_CONNECT_ERROR; } +#ifdef USE_TLS_SRP + if(data->set.ssl.authtype == CURL_TLSAUTH_SRP) { + infof(data, "Using TLS-SRP username: %s\n", data->set.ssl.username); + + rc = gnutls_srp_allocate_client_credentials( + &conn->ssl[sockindex].srp_client_cred); + if(rc != GNUTLS_E_SUCCESS) { + failf(data, "gnutls_srp_allocate_client_cred() failed: %s", + gnutls_strerror(rc)); + return CURLE_TLSAUTH_FAILED; + } + + rc = gnutls_srp_set_client_credentials(conn->ssl[sockindex].srp_client_cred, + data->set.ssl.username, + data->set.ssl.password); + if(rc != GNUTLS_E_SUCCESS) { + failf(data, "gnutls_srp_set_client_cred() failed: %s", + gnutls_strerror(rc)); + return CURLE_TLSAUTH_FAILED; + } + } +#endif + if(data->set.ssl.CAfile) { /* set the trusted CA cert bundle file */ gnutls_certificate_set_verify_flags(conn->ssl[sockindex].cred, @@ -431,9 +454,18 @@ gtls_connect_step1(struct connectdata *conn, } } +#ifdef USE_TLS_SRP /* put the credentials to the current session */ - rc = gnutls_credentials_set(session, GNUTLS_CRD_CERTIFICATE, - conn->ssl[sockindex].cred); + if(data->set.ssl.authtype == CURL_TLSAUTH_SRP) { + rc = gnutls_credentials_set(session, GNUTLS_CRD_SRP, + conn->ssl[sockindex].srp_client_cred); + if (rc != GNUTLS_E_SUCCESS) { + failf(data, "gnutls_credentials_set() failed: %s", gnutls_strerror(rc)); + } + } else +#endif + rc = gnutls_credentials_set(session, GNUTLS_CRD_CERTIFICATE, + conn->ssl[sockindex].cred); /* set the connection handle (file descriptor for the socket) */ gnutls_transport_set_ptr(session, @@ -496,8 +528,21 @@ gtls_connect_step3(struct connectdata *conn, if(data->set.ssl.verifypeer || data->set.ssl.verifyhost || data->set.ssl.issuercert) { - failf(data, "failed to get server cert"); - return CURLE_PEER_FAILED_VERIFICATION; +#ifdef USE_TLS_SRP + if(data->set.ssl.authtype == CURL_TLSAUTH_SRP + && data->set.ssl.username != NULL + && !data->set.ssl.verifypeer + && gnutls_cipher_get(session)) { + /* no peer cert, but auth is ok if we have SRP user and cipher and no + peer verify */ + } + else { +#endif + failf(data, "failed to get server cert"); + return CURLE_PEER_FAILED_VERIFICATION; +#ifdef USE_TLS_SRP + } +#endif } infof(data, "\t common name: WARNING couldn't obtain\n"); } @@ -530,8 +575,10 @@ gtls_connect_step3(struct connectdata *conn, else infof(data, "\t server certificate verification OK\n"); } - else + else { infof(data, "\t server certificate verification SKIPPED\n"); + goto after_server_cert_verification; + } /* initialize an X.509 certificate structure. */ gnutls_x509_crt_init(&x509_cert); @@ -661,6 +708,8 @@ gtls_connect_step3(struct connectdata *conn, gnutls_x509_crt_deinit(x509_cert); +after_server_cert_verification: + /* compression algorithm (if any) */ ptr = gnutls_compression_get_name(gnutls_compression_get(session)); /* the *_get_name() says "NULL" if GNUTLS_COMP_NULL is returned */ @@ -820,6 +869,12 @@ static void close_one(struct connectdata *conn, gnutls_certificate_free_credentials(conn->ssl[idx].cred); conn->ssl[idx].cred = NULL; } +#ifdef USE_TLS_SRP + if (conn->ssl[idx].srp_client_cred) { + gnutls_srp_free_client_credentials(conn->ssl[idx].srp_client_cred); + conn->ssl[idx].srp_client_cred = NULL; + } +#endif } void Curl_gtls_close(struct connectdata *conn, int sockindex) @@ -889,6 +944,12 @@ int Curl_gtls_shutdown(struct connectdata *conn, int sockindex) } gnutls_certificate_free_credentials(conn->ssl[sockindex].cred); +#ifdef USE_TLS_SRP + if(data->set.ssl.authtype == CURL_TLSAUTH_SRP + && data->set.ssl.username != NULL) + gnutls_srp_free_client_credentials(conn->ssl[sockindex].srp_client_cred); +#endif + conn->ssl[sockindex].cred = NULL; conn->ssl[sockindex].session = NULL; diff --git a/lib/strerror.c b/lib/strerror.c index e8ecea59f..6b67a8777 100644 --- a/lib/strerror.c +++ b/lib/strerror.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 2004 - 2010, Daniel Stenberg, , et al. + * Copyright (C) 2004 - 2011, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -281,6 +281,9 @@ curl_easy_strerror(CURLcode error) case CURLE_CHUNK_FAILED: return "Chunk callback failed"; + case CURLE_TLSAUTH_FAILED: + return "TLS Authentication failed"; + /* error codes not used by current libcurl */ case CURLE_OBSOLETE4: case CURLE_OBSOLETE10: diff --git a/lib/url.c b/lib/url.c index f8bd07aad..cd89e1f89 100644 --- a/lib/url.c +++ b/lib/url.c @@ -751,6 +751,9 @@ CURLcode Curl_init_userdefined(struct UserDefined *set) */ set->ssl.verifypeer = TRUE; set->ssl.verifyhost = 2; +#ifdef USE_TLS_SRP + set->ssl.authtype = CURL_TLSAUTH_NONE; +#endif set->ssh_auth_types = CURLSSH_AUTH_DEFAULT; /* defaults to any auth type */ set->ssl.sessionid = TRUE; /* session ID caching enabled by default */ @@ -2526,6 +2529,26 @@ CURLcode Curl_setopt(struct SessionHandle *data, CURLoption option, case CURLOPT_FNMATCH_DATA: data->set.fnmatch_data = va_arg(param, void *); break; +#ifdef USE_TLS_SRP + case CURLOPT_TLSAUTH_USERNAME: + result = setstropt(&data->set.str[STRING_TLSAUTH_USERNAME], + va_arg(param, char *)); + if (data->set.str[STRING_TLSAUTH_USERNAME] && !data->set.ssl.authtype) + data->set.ssl.authtype = CURL_TLSAUTH_SRP; /* default to SRP */ + break; + case CURLOPT_TLSAUTH_PASSWORD: + result = setstropt(&data->set.str[STRING_TLSAUTH_PASSWORD], + va_arg(param, char *)); + if (data->set.str[STRING_TLSAUTH_USERNAME] && !data->set.ssl.authtype) + data->set.ssl.authtype = CURL_TLSAUTH_SRP; /* default to SRP */ + break; + case CURLOPT_TLSAUTH_TYPE: + if (strncmp((char *)va_arg(param, char *), "SRP", strlen("SRP")) == 0) + data->set.ssl.authtype = CURL_TLSAUTH_SRP; + else + data->set.ssl.authtype = CURL_TLSAUTH_NONE; + break; +#endif default: /* unknown tag and its companion, just ignore: */ result = CURLE_FAILED_INIT; /* correct this */ @@ -4929,6 +4952,10 @@ static CURLcode create_conn(struct SessionHandle *data, data->set.ssl.random_file = data->set.str[STRING_SSL_RANDOM_FILE]; data->set.ssl.egdsocket = data->set.str[STRING_SSL_EGDSOCKET]; data->set.ssl.cipher_list = data->set.str[STRING_SSL_CIPHER_LIST]; +#ifdef USE_TLS_SRP + data->set.ssl.username = data->set.str[STRING_TLSAUTH_USERNAME]; + data->set.ssl.password = data->set.str[STRING_TLSAUTH_PASSWORD]; +#endif if(!Curl_clone_ssl_config(&data->set.ssl, &conn->ssl_config)) return CURLE_OUT_OF_MEMORY; diff --git a/lib/urldata.h b/lib/urldata.h index 55167fbc3..a86f7f156 100644 --- a/lib/urldata.h +++ b/lib/urldata.h @@ -251,6 +251,9 @@ struct ssl_connect_data { #ifdef USE_GNUTLS gnutls_session session; gnutls_certificate_credentials cred; +#ifdef USE_TLS_SRP + gnutls_srp_client_credentials srp_client_cred; +#endif ssl_connect_state connecting_state; #endif /* USE_GNUTLS */ #ifdef USE_POLARSSL @@ -300,6 +303,12 @@ struct ssl_config_data { void *fsslctxp; /* parameter for call back */ bool sessionid; /* cache session IDs or not */ bool certinfo; /* gather lots of certificate info */ + +#ifdef USE_TLS_SRP + char *username; /* TLS username (for, e.g., SRP) */ + char *password; /* TLS password (for, e.g., SRP) */ + enum CURL_TLSAUTH authtype; /* TLS authentication type (default SRP) */ +#endif }; /* information stored about one single SSL session */ @@ -1315,6 +1324,11 @@ enum dupstring { #endif STRING_MAIL_FROM, +#ifdef USE_TLS_SRP + STRING_TLSAUTH_USERNAME, /* TLS auth */ + STRING_TLSAUTH_PASSWORD, /* TLS auth */ +#endif + /* -- end of strings -- */ STRING_LAST /* not used, just an end-of-list marker */ }; diff --git a/lib/version.c b/lib/version.c index 5931e7180..52989cdc6 100644 --- a/lib/version.c +++ b/lib/version.c @@ -264,6 +264,9 @@ static curl_version_info_data version_info = { #endif #if defined(CURL_DOES_CONVERSIONS) | CURL_VERSION_CONV +#endif +#if defined(USE_TLS_SRP) + | CURL_VERSION_TLSAUTH_SRP #endif , NULL, /* ssl_version */ -- cgit v1.2.1