From de4610a55f9e99bebaf448ca33e2e43baf977c74 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Wed, 28 Jan 2009 21:33:58 +0000 Subject: - Markus Moeller introduced two new options to libcurl: CURLOPT_SOCKS5_GSSAPI_SERVICE and CURLOPT_SOCKS5_GSSAPI_NEC to allow libcurl to do GSS-style authentication with SOCKS5 proxies. The curl tool got the options called --socks5-gssapi-service and --socks5-gssapi-nec to enable these. --- lib/socks.c | 78 +++++++++++++++++++++++++++++++++++++++++++++---------------- 1 file changed, 58 insertions(+), 20 deletions(-) (limited to 'lib/socks.c') diff --git a/lib/socks.c b/lib/socks.c index 693573209..9fc5b7948 100644 --- a/lib/socks.c +++ b/lib/socks.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2008, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2009, 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 @@ -60,14 +60,14 @@ * This is STUPID BLOCKING behaviour which we frown upon, but right now this * is what we have... */ -static int blockread_all(struct connectdata *conn, /* connection data */ - curl_socket_t sockfd, /* read from this socket */ - char *buf, /* store read data here */ - ssize_t buffersize, /* max amount to read */ - ssize_t *n, /* amount bytes read */ - long conn_timeout) /* timeout for data wait - relative to - conn->created */ +int Curl_blockread_all(struct connectdata *conn, /* connection data */ + curl_socket_t sockfd, /* read from this socket */ + char *buf, /* store read data here */ + ssize_t buffersize, /* max amount to read */ + ssize_t *n, /* amount bytes read */ + long conn_timeout) /* timeout for data wait + relative to + conn->created */ { ssize_t nread; ssize_t allread = 0; @@ -264,7 +264,7 @@ CURLcode Curl_SOCKS4(const char *proxy_name, packetsize = 8; /* receive data size */ /* Receive response */ - result = blockread_all(conn, sock, (char *)socksreq, packetsize, + result = Curl_blockread_all(conn, sock, (char *)socksreq, packetsize, &actualread, timeout); if((result != CURLE_OK) || (actualread != packetsize)) { failf(data, "Failed to receive SOCKS4 connect request ack."); @@ -429,9 +429,16 @@ CURLcode Curl_SOCKS5(const char *proxy_name, } socksreq[0] = 5; /* version */ +#if defined(HAVE_GSSAPI) || defined(USE_WINDOWS_SSPI) + socksreq[1] = (char)(proxy_name ? 3 : 2); /* number of methods (below) */ + socksreq[2] = 0; /* no authentication */ + socksreq[3] = 1; /* gssapi */ + socksreq[4] = 2; /* username/password */ +#else socksreq[1] = (char)(proxy_name ? 2 : 1); /* number of methods (below) */ socksreq[2] = 0; /* no authentication */ socksreq[3] = 2; /* username/password */ +#endif Curl_nonblock(sock, FALSE); @@ -462,7 +469,8 @@ CURLcode Curl_SOCKS5(const char *proxy_name, Curl_nonblock(sock, FALSE); - result=blockread_all(conn, sock, (char *)socksreq, 2, &actualread, timeout); + result=Curl_blockread_all(conn, sock, (char *)socksreq, 2, &actualread, + timeout); if((result != CURLE_OK) || (actualread != 2)) { failf(data, "Unable to receive initial SOCKS5 response."); return CURLE_COULDNT_CONNECT; @@ -476,6 +484,15 @@ CURLcode Curl_SOCKS5(const char *proxy_name, /* Nothing to do, no authentication needed */ ; } +#if defined(HAVE_GSSAPI) || defined(USE_WINDOWS_SSPI) + else if(socksreq[1] == 1) { + code = Curl_SOCKS5_gssapi_negotiate(sockindex, conn); + if(code != CURLE_OK) { + failf(data, "Unable to negotiate SOCKS5 gssapi context."); + return CURLE_COULDNT_CONNECT; + } + } +#endif else if(socksreq[1] == 2) { /* Needs user name and password */ size_t userlen, pwlen; @@ -511,7 +528,7 @@ CURLcode Curl_SOCKS5(const char *proxy_name, return CURLE_COULDNT_CONNECT; } - result=blockread_all(conn, sock, (char *)socksreq, 2, &actualread, + result=Curl_blockread_all(conn, sock, (char *)socksreq, 2, &actualread, timeout); if((result != CURLE_OK) || (actualread != 2)) { failf(data, "Unable to receive SOCKS5 sub-negotiation response."); @@ -529,12 +546,16 @@ CURLcode Curl_SOCKS5(const char *proxy_name, } else { /* error */ +#if defined(HAVE_GSSAPI) || defined(USE_WINDOWS_SSPI) + if(socksreq[1] == 255) { +#else if(socksreq[1] == 1) { failf(data, "SOCKS5 GSSAPI per-message authentication is not supported."); return CURLE_COULDNT_CONNECT; } else if(socksreq[1] == 255) { +#endif if(!proxy_name || !*proxy_name) { failf(data, "No authentication method was acceptable. (It is quite likely" @@ -616,6 +637,11 @@ CURLcode Curl_SOCKS5(const char *proxy_name, *((unsigned short*)&socksreq[8]) = htons((unsigned short)remote_port); } +#if defined(HAVE_GSSAPI) || defined(USE_WINDOWS_SSPI) + if(conn->socks5_gssapi_enctype) { + failf(data, "SOCKS5 gssapi protection not yet implemented."); + } else +#endif code = Curl_write_plain(conn, sock, (char *)socksreq, packetsize, &written); if((code != CURLE_OK) || (written != packetsize)) { failf(data, "Failed to send SOCKS5 connect request."); @@ -624,7 +650,12 @@ CURLcode Curl_SOCKS5(const char *proxy_name, packetsize = 10; /* minimum packet size is 10 */ - result = blockread_all(conn, sock, (char *)socksreq, packetsize, +#if defined(HAVE_GSSAPI) || defined(USE_WINDOWS_SSPI) + if(conn->socks5_gssapi_enctype) { + failf(data, "SOCKS5 gssapi protection not yet implemented."); + } else +#endif + result = Curl_blockread_all(conn, sock, (char *)socksreq, packetsize, &actualread, timeout); if((result != CURLE_OK) || (actualread != packetsize)) { failf(data, "Failed to receive SOCKS5 connect request ack."); @@ -674,15 +705,22 @@ CURLcode Curl_SOCKS5(const char *proxy_name, } /* At this point we already read first 10 bytes */ - if(packetsize > 10) { - packetsize -= 10; - result = blockread_all(conn, sock, (char *)&socksreq[10], packetsize, - &actualread, timeout); - if((result != CURLE_OK) || (actualread != packetsize)) { - failf(data, "Failed to receive SOCKS5 connect request ack."); - return CURLE_COULDNT_CONNECT; +#if defined(HAVE_GSSAPI) || defined(USE_WINDOWS_SSPI) + if(!conn->socks5_gssapi_enctype) { + /* decrypt_gssapi_blockread already read the whole packet */ +#endif + if(packetsize > 10) { + packetsize -= 10; + result = Curl_blockread_all(conn, sock, (char *)&socksreq[10], + packetsize, &actualread, timeout); + if((result != CURLE_OK) || (actualread != packetsize)) { + failf(data, "Failed to receive SOCKS5 connect request ack."); + return CURLE_COULDNT_CONNECT; + } } +#if defined(HAVE_GSSAPI) || defined(USE_WINDOWS_SSPI) } +#endif Curl_nonblock(sock, TRUE); return CURLE_OK; /* Proxy was successful! */ -- cgit v1.2.3