summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorQuinn Slack <sqs@cs.stanford.edu>2011-01-19 20:35:02 +0100
committerDaniel Stenberg <daniel@haxx.se>2011-01-19 20:35:02 +0100
commit59cf93ccdbaa5e866f9de6b2d9b1ae5cee84863f (patch)
treeb0a40c875954b842a9bf50f409d571de04507044 /lib
parent4f13340ab8be7baa0fe6210bb3a19b8994875fd8 (diff)
downloadcurl-59cf93ccdbaa5e866f9de6b2d9b1ae5cee84863f.tar.gz
TLS-SRP: support added when using GnuTLS
Diffstat (limited to 'lib')
-rw-r--r--lib/gtls.c71
-rw-r--r--lib/strerror.c5
-rw-r--r--lib/url.c27
-rw-r--r--lib/urldata.h14
-rw-r--r--lib/version.c3
5 files changed, 114 insertions, 6 deletions
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, <daniel@haxx.se>, et al.
+ * Copyright (C) 2004 - 2011, Daniel Stenberg, <daniel@haxx.se>, 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 <username> */
+ STRING_TLSAUTH_PASSWORD, /* TLS auth <password> */
+#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
@@ -265,6 +265,9 @@ static curl_version_info_data version_info = {
#if defined(CURL_DOES_CONVERSIONS)
| CURL_VERSION_CONV
#endif
+#if defined(USE_TLS_SRP)
+ | CURL_VERSION_TLSAUTH_SRP
+#endif
,
NULL, /* ssl_version */
0, /* ssl_version_num, this is kept at zero */