diff options
Diffstat (limited to 'lib/socks_gssapi.c')
-rw-r--r-- | lib/socks_gssapi.c | 196 |
1 files changed, 85 insertions, 111 deletions
diff --git a/lib/socks_gssapi.c b/lib/socks_gssapi.c index 1ff6f60..8e575c2 100644 --- a/lib/socks_gssapi.c +++ b/lib/socks_gssapi.c @@ -5,7 +5,8 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 2009, Markus Moeller, <markus_moeller@compuserve.com> + * Copyright (C) 2009, 2011, Markus Moeller, <markus_moeller@compuserve.com> + * Copyright (C) 2012 - 2015, 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 @@ -20,40 +21,26 @@ * ***************************************************************************/ -#include "setup.h" +#include "curl_setup.h" -#ifndef CURL_DISABLE_PROXY - -#ifdef HAVE_GSSAPI -#ifdef HAVE_OLD_GSSMIT -#define GSS_C_NT_HOSTBASED_SERVICE gss_nt_service_name -#endif -#ifndef gss_nt_service_name -#define gss_nt_service_name GSS_C_NT_HOSTBASED_SERVICE -#endif -#include <string.h> - -#ifdef HAVE_STDLIB_H -#include <stdlib.h> -#endif +#if defined(HAVE_GSSAPI) && !defined(CURL_DISABLE_PROXY) +#include "curl_gssapi.h" #include "urldata.h" #include "sendf.h" #include "connect.h" #include "timeval.h" #include "socks.h" - -static gss_ctx_id_t gss_context = GSS_C_NO_CONTEXT; - -#define _MPRINTF_REPLACE /* use our functions only */ -#include <curl/mprintf.h> - +#include "warnless.h" +#include "curl_printf.h" #include "curl_memory.h" /* The last #include file should be: */ #include "memdebug.h" +static gss_ctx_id_t gss_context = GSS_C_NO_CONTEXT; + /* - * Helper gssapi error functions. + * Helper GSS-API error functions. */ static int check_gss_err(struct SessionHandle *data, OM_uint32 major_status, @@ -61,7 +48,7 @@ static int check_gss_err(struct SessionHandle *data, const char* function) { if(GSS_ERROR(major_status)) { - OM_uint32 maj_stat,min_stat; + OM_uint32 maj_stat, min_stat; OM_uint32 msg_ctx = 0; gss_buffer_desc status_string; char buf[1024]; @@ -97,20 +84,18 @@ static int check_gss_err(struct SessionHandle *data, GSS_C_NULL_OID, &msg_ctx, &status_string); if(maj_stat == GSS_S_COMPLETE) { - if(sizeof(buf) > len + status_string.length) { + if(sizeof(buf) > len + status_string.length) strcpy(buf+len, (char*) status_string.value); - len += status_string.length; - } gss_release_buffer(&min_stat, &status_string); break; } gss_release_buffer(&min_stat, &status_string); } - failf(data, "GSSAPI error: %s failed:\n%s\n", function, buf); - return(1); + failf(data, "GSS-API error: %s failed:\n%s", function, buf); + return 1; } - return(0); + return 0; } CURLcode Curl_SOCKS5_gssapi_negotiate(int sockindex, @@ -122,7 +107,6 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(int sockindex, ssize_t actualread; ssize_t written; int result; - long timeout; OM_uint32 gss_major_status, gss_minor_status, gss_status; OM_uint32 gss_ret_flags; int gss_conf_state, gss_enc; @@ -133,15 +117,12 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(int sockindex, gss_buffer_desc* gss_token = GSS_C_NO_BUFFER; gss_name_t server = GSS_C_NO_NAME; gss_name_t gss_client_name = GSS_C_NO_NAME; - u_short us_length; + unsigned short us_length; char *user=NULL; - unsigned char socksreq[4]; /* room for gssapi exchange header only */ + unsigned char socksreq[4]; /* room for GSS-API exchange header only */ char *serviceptr = data->set.str[STRING_SOCKS5_GSSAPI_SERVICE]; - /* get timeout */ - timeout = Curl_timeleft(conn, NULL, TRUE); - - /* GSSAPI request looks like + /* GSS-API request looks like * +----+------+-----+----------------+ * |VER | MTYP | LEN | TOKEN | * +----+------+----------------------+ @@ -150,7 +131,7 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(int sockindex, */ /* prepare service name */ - if (strchr(serviceptr,'/')) { + if(strchr(serviceptr, '/')) { service.value = malloc(strlen(serviceptr)); if(!service.value) return CURLE_OUT_OF_MEMORY; @@ -169,13 +150,13 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(int sockindex, serviceptr, conn->proxy.name); gss_major_status = gss_import_name(&gss_minor_status, &service, - gss_nt_service_name, &server); + GSS_C_NT_HOSTBASED_SERVICE, &server); } gss_release_buffer(&gss_status, &service); /* clear allocated memory */ - if(check_gss_err(data,gss_major_status, - gss_minor_status,"gss_import_name()")) { + if(check_gss_err(data, gss_major_status, + gss_minor_status, "gss_import_name()")) { failf(data, "Failed to create service name."); gss_release_name(&gss_status, &server); return CURLE_COULDNT_CONNECT; @@ -184,41 +165,38 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(int sockindex, /* As long as we need to keep sending some context info, and there's no */ /* errors, keep sending it... */ for(;;) { - gss_major_status = gss_init_sec_context(&gss_minor_status, - GSS_C_NO_CREDENTIAL, - &gss_context, server, - GSS_C_NULL_OID, - GSS_C_MUTUAL_FLAG | - GSS_C_REPLAY_FLAG, - 0, - NULL, - gss_token, - NULL, - &gss_send_token, - &gss_ret_flags, - NULL); + gss_major_status = Curl_gss_init_sec_context(data, + &gss_minor_status, + &gss_context, + server, + &Curl_krb5_mech_oid, + NULL, + gss_token, + &gss_send_token, + TRUE, + &gss_ret_flags); if(gss_token != GSS_C_NO_BUFFER) gss_release_buffer(&gss_status, &gss_recv_token); - if(check_gss_err(data,gss_major_status, - gss_minor_status,"gss_init_sec_context")) { + if(check_gss_err(data, gss_major_status, + gss_minor_status, "gss_init_sec_context")) { gss_release_name(&gss_status, &server); gss_release_buffer(&gss_status, &gss_recv_token); gss_release_buffer(&gss_status, &gss_send_token); gss_delete_sec_context(&gss_status, &gss_context, NULL); - failf(data, "Failed to initial GSSAPI token."); + failf(data, "Failed to initial GSS-API token."); return CURLE_COULDNT_CONNECT; } if(gss_send_token.length != 0) { - socksreq[0] = 1; /* gssapi subnegotiation version */ + socksreq[0] = 1; /* GSS-API subnegotiation version */ socksreq[1] = 1; /* authentication message type */ us_length = htons((short)gss_send_token.length); - memcpy(socksreq+2,&us_length,sizeof(short)); + memcpy(socksreq+2, &us_length, sizeof(short)); code = Curl_write_plain(conn, sock, (char *)socksreq, 4, &written); - if((code != CURLE_OK) || (4 != written)) { - failf(data, "Failed to send GSSAPI authentication request."); + if(code || (4 != written)) { + failf(data, "Failed to send GSS-API authentication request."); gss_release_name(&gss_status, &server); gss_release_buffer(&gss_status, &gss_recv_token); gss_release_buffer(&gss_status, &gss_send_token); @@ -229,8 +207,8 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(int sockindex, code = Curl_write_plain(conn, sock, (char *)gss_send_token.value, gss_send_token.length, &written); - if((code != CURLE_OK) || ((ssize_t)gss_send_token.length != written)) { - failf(data, "Failed to send GSSAPI authentication token."); + if(code || ((ssize_t)gss_send_token.length != written)) { + failf(data, "Failed to send GSS-API authentication token."); gss_release_name(&gss_status, &server); gss_release_buffer(&gss_status, &gss_recv_token); gss_release_buffer(&gss_status, &gss_send_token); @@ -246,7 +224,7 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(int sockindex, /* analyse response */ - /* GSSAPI response looks like + /* GSS-API response looks like * +----+------+-----+----------------+ * |VER | MTYP | LEN | TOKEN | * +----+------+----------------------+ @@ -254,10 +232,9 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(int sockindex, * +----+------+-----+----------------+ */ - result=Curl_blockread_all(conn, sock, (char *)socksreq, 4, - &actualread, timeout); - if(result != CURLE_OK || actualread != 4) { - failf(data, "Failed to receive GSSAPI authentication response."); + result=Curl_blockread_all(conn, sock, (char *)socksreq, 4, &actualread); + if(result || (actualread != 4)) { + failf(data, "Failed to receive GSS-API authentication response."); gss_release_name(&gss_status, &server); gss_delete_sec_context(&gss_status, &gss_context, NULL); return CURLE_COULDNT_CONNECT; @@ -273,7 +250,7 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(int sockindex, } if(socksreq[1] != 1) { /* status / messgae type */ - failf(data, "Invalid GSSAPI authentication response type (%d %d).", + failf(data, "Invalid GSS-API authentication response type (%d %d).", socksreq[0], socksreq[1]); gss_release_name(&gss_status, &server); gss_delete_sec_context(&gss_status, &gss_context, NULL); @@ -287,7 +264,7 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(int sockindex, gss_recv_token.value=malloc(us_length); if(!gss_recv_token.value) { failf(data, - "Could not allocate memory for GSSAPI authentication " + "Could not allocate memory for GSS-API authentication " "response token."); gss_release_name(&gss_status, &server); gss_delete_sec_context(&gss_status, &gss_context, NULL); @@ -295,11 +272,10 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(int sockindex, } result=Curl_blockread_all(conn, sock, (char *)gss_recv_token.value, - gss_recv_token.length, - &actualread, timeout); + gss_recv_token.length, &actualread); - if(result != CURLE_OK || actualread != us_length) { - failf(data, "Failed to receive GSSAPI authentication token."); + if(result || (actualread != us_length)) { + failf(data, "Failed to receive GSS-API authentication token."); gss_release_name(&gss_status, &server); gss_release_buffer(&gss_status, &gss_recv_token); gss_delete_sec_context(&gss_status, &gss_context, NULL); @@ -315,8 +291,8 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(int sockindex, gss_major_status = gss_inquire_context (&gss_minor_status, gss_context, &gss_client_name, NULL, NULL, NULL, NULL, NULL, NULL); - if(check_gss_err(data,gss_major_status, - gss_minor_status,"gss_inquire_context")) { + if(check_gss_err(data, gss_major_status, + gss_minor_status, "gss_inquire_context")) { gss_delete_sec_context(&gss_status, &gss_context, NULL); gss_release_name(&gss_status, &gss_client_name); failf(data, "Failed to determine user name."); @@ -324,8 +300,8 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(int sockindex, } gss_major_status = gss_display_name(&gss_minor_status, gss_client_name, &gss_send_token, NULL); - if(check_gss_err(data,gss_major_status, - gss_minor_status,"gss_display_name")) { + if(check_gss_err(data, gss_major_status, + gss_minor_status, "gss_display_name")) { gss_delete_sec_context(&gss_status, &gss_context, NULL); gss_release_name(&gss_status, &gss_client_name); gss_release_buffer(&gss_status, &gss_send_token); @@ -344,12 +320,12 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(int sockindex, user[gss_send_token.length] = '\0'; gss_release_name(&gss_status, &gss_client_name); gss_release_buffer(&gss_status, &gss_send_token); - infof(data, "SOCKS5 server authencticated user %s with gssapi.\n",user); + infof(data, "SOCKS5 server authencticated user %s with GSS-API.\n",user); free(user); user=NULL; /* Do encryption */ - socksreq[0] = 1; /* gssapi subnegotiation version */ + socksreq[0] = 1; /* GSS-API subnegotiation version */ socksreq[1] = 2; /* encryption message type */ gss_enc = 0; /* no data protection */ @@ -360,7 +336,7 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(int sockindex, else if(gss_ret_flags & GSS_C_INTEG_FLAG) gss_enc = 1; - infof(data, "SOCKS5 server supports gssapi %s data protection.\n", + infof(data, "SOCKS5 server supports GSS-API %s data protection.\n", (gss_enc==0)?"no":((gss_enc==1)?"integrity":"confidentiality")); /* force for the moment to no data protection */ gss_enc = 0; @@ -396,7 +372,7 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(int sockindex, */ if(data->set.socks5_gssapi_nec) { us_length = htons((short)1); - memcpy(socksreq+2,&us_length,sizeof(short)); + memcpy(socksreq+2, &us_length, sizeof(short)); } else { gss_send_token.length = 1; @@ -411,22 +387,22 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(int sockindex, GSS_C_QOP_DEFAULT, &gss_send_token, &gss_conf_state, &gss_w_token); - if(check_gss_err(data,gss_major_status,gss_minor_status,"gss_wrap")) { + if(check_gss_err(data, gss_major_status, gss_minor_status, "gss_wrap")) { gss_release_buffer(&gss_status, &gss_send_token); gss_release_buffer(&gss_status, &gss_w_token); gss_delete_sec_context(&gss_status, &gss_context, NULL); - failf(data, "Failed to wrap GSSAPI encryption value into token."); + failf(data, "Failed to wrap GSS-API encryption value into token."); return CURLE_COULDNT_CONNECT; } gss_release_buffer(&gss_status, &gss_send_token); us_length = htons((short)gss_w_token.length); - memcpy(socksreq+2,&us_length,sizeof(short)); + memcpy(socksreq+2, &us_length, sizeof(short)); } code = Curl_write_plain(conn, sock, (char *)socksreq, 4, &written); - if((code != CURLE_OK) || (4 != written)) { - failf(data, "Failed to send GSSAPI encryption request."); + if(code || (4 != written)) { + failf(data, "Failed to send GSS-API encryption request."); gss_release_buffer(&gss_status, &gss_w_token); gss_delete_sec_context(&gss_status, &gss_context, NULL); return CURLE_COULDNT_CONNECT; @@ -435,16 +411,17 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(int sockindex, if(data->set.socks5_gssapi_nec) { memcpy(socksreq, &gss_enc, 1); code = Curl_write_plain(conn, sock, socksreq, 1, &written); - if((code != CURLE_OK) || ( 1 != written)) { - failf(data, "Failed to send GSSAPI encryption type."); + if(code || ( 1 != written)) { + failf(data, "Failed to send GSS-API encryption type."); gss_delete_sec_context(&gss_status, &gss_context, NULL); return CURLE_COULDNT_CONNECT; } - } else { + } + else { code = Curl_write_plain(conn, sock, (char *)gss_w_token.value, gss_w_token.length, &written); - if((code != CURLE_OK) || ((ssize_t)gss_w_token.length != written)) { - failf(data, "Failed to send GSSAPI encryption type."); + if(code || ((ssize_t)gss_w_token.length != written)) { + failf(data, "Failed to send GSS-API encryption type."); gss_release_buffer(&gss_status, &gss_w_token); gss_delete_sec_context(&gss_status, &gss_context, NULL); return CURLE_COULDNT_CONNECT; @@ -452,10 +429,9 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(int sockindex, gss_release_buffer(&gss_status, &gss_w_token); } - result=Curl_blockread_all(conn, sock, (char *)socksreq, 4, - &actualread, timeout); - if(result != CURLE_OK || actualread != 4) { - failf(data, "Failed to receive GSSAPI encryption response."); + result=Curl_blockread_all(conn, sock, (char *)socksreq, 4, &actualread); + if(result || (actualread != 4)) { + failf(data, "Failed to receive GSS-API encryption response."); gss_delete_sec_context(&gss_status, &gss_context, NULL); return CURLE_COULDNT_CONNECT; } @@ -469,7 +445,7 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(int sockindex, } if(socksreq[1] != 2) { /* status / messgae type */ - failf(data, "Invalid GSSAPI encryption response type (%d %d).", + failf(data, "Invalid GSS-API encryption response type (%d %d).", socksreq[0], socksreq[1]); gss_delete_sec_context(&gss_status, &gss_context, NULL); return CURLE_COULDNT_CONNECT; @@ -485,11 +461,10 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(int sockindex, return CURLE_OUT_OF_MEMORY; } result=Curl_blockread_all(conn, sock, (char *)gss_recv_token.value, - gss_recv_token.length, - &actualread, timeout); + gss_recv_token.length, &actualread); - if(result != CURLE_OK || actualread != us_length) { - failf(data, "Failed to receive GSSAPI encryptrion type."); + if(result || (actualread != us_length)) { + failf(data, "Failed to receive GSS-API encryptrion type."); gss_release_buffer(&gss_status, &gss_recv_token); gss_delete_sec_context(&gss_status, &gss_context, NULL); return CURLE_COULDNT_CONNECT; @@ -500,42 +475,42 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(int sockindex, &gss_recv_token, &gss_w_token, 0, GSS_C_QOP_DEFAULT); - if(check_gss_err(data,gss_major_status,gss_minor_status,"gss_unwrap")) { + if(check_gss_err(data, gss_major_status, gss_minor_status, "gss_unwrap")) { gss_release_buffer(&gss_status, &gss_recv_token); gss_release_buffer(&gss_status, &gss_w_token); gss_delete_sec_context(&gss_status, &gss_context, NULL); - failf(data, "Failed to unwrap GSSAPI encryption value into token."); + failf(data, "Failed to unwrap GSS-API encryption value into token."); return CURLE_COULDNT_CONNECT; } gss_release_buffer(&gss_status, &gss_recv_token); if(gss_w_token.length != 1) { - failf(data, "Invalid GSSAPI encryption response length (%d).", + failf(data, "Invalid GSS-API encryption response length (%d).", gss_w_token.length); gss_release_buffer(&gss_status, &gss_w_token); gss_delete_sec_context(&gss_status, &gss_context, NULL); return CURLE_COULDNT_CONNECT; } - memcpy(socksreq,gss_w_token.value,gss_w_token.length); + memcpy(socksreq, gss_w_token.value, gss_w_token.length); gss_release_buffer(&gss_status, &gss_w_token); } else { if(gss_recv_token.length != 1) { - failf(data, "Invalid GSSAPI encryption response length (%d).", + failf(data, "Invalid GSS-API encryption response length (%d).", gss_recv_token.length); gss_release_buffer(&gss_status, &gss_recv_token); gss_delete_sec_context(&gss_status, &gss_context, NULL); return CURLE_COULDNT_CONNECT; } - memcpy(socksreq,gss_recv_token.value,gss_recv_token.length); + memcpy(socksreq, gss_recv_token.value, gss_recv_token.length); gss_release_buffer(&gss_status, &gss_recv_token); } infof(data, "SOCKS5 access with%s protection granted.\n", - (socksreq[0]==0)?"out gssapi data": - ((socksreq[0]==1)?" gssapi integrity":" gssapi confidentiality")); + (socksreq[0]==0)?"out GSS-API data": + ((socksreq[0]==1)?" GSS-API integrity":" GSS-API confidentiality")); conn->socks5_gssapi_enctype = socksreq[0]; if(socksreq[0] == 0) @@ -543,6 +518,5 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(int sockindex, return CURLE_OK; } -#endif -#endif /* CURL_DISABLE_PROXY */ +#endif /* HAVE_GSSAPI && !CURL_DISABLE_PROXY */ |