← Commit list

84112673a0

Daniel Stenberg
Daniel Stenberg
2026-02-22
SUCCESS Duration: 322s

Subject

socks_sspi: split Curl_SOCKS5_gssapi_negotiate into sub functions

Binary

No binary (build failed)

Architecture & Compiler Flags

Architecture: x86_64-linux-gnu Compiler: gcc (Ubuntu 11.4.0-1ubuntu1~22.04.3) 11.4.0

—

Build Log

(log yok)

Commit Diff GitHub →

lib/socks_sspi.c+218 -276
@@ -56,52 +56,70 @@ static int check_sspi_err(struct Curl_easy *data,
}
/* This is the SSPI-using version of this function */
-CURLcode Curl_SOCKS5_gssapi_negotiate(struct Curl_cfilter *cf,
- struct Curl_easy *data)
+static CURLcode socks5_sspi_setup(struct Curl_cfilter *cf,
+ struct Curl_easy *data,
+ CredHandle *cred_handle,
+ char **service_namep)
{
struct connectdata *conn = cf->conn;
- curl_socket_t sock = conn->sock[cf->sockindex];
- CURLcode code;
- size_t actualread;
- size_t written;
- CURLcode result;
- /* Needs GSS-API authentication */
- SECURITY_STATUS status;
- unsigned long sspi_ret_flags = 0;
- unsigned char gss_enc;
- SecBuffer sspi_send_token, sspi_recv_token, sspi_w_token[3];
- SecBufferDesc input_desc, output_desc, wrap_desc;
- SecPkgContext_Sizes sspi_sizes;
- CredHandle cred_handle;
- CtxtHandle sspi_context;
- PCtxtHandle context_handle = NULL;
- SecPkgCredentials_Names names;
- char *service_name = NULL;
- unsigned short us_length;
- unsigned long qop;
- unsigned char socksreq[4]; /* room for GSS-API exchange header only */
const char *service = data->set.str[STRING_PROXY_SERVICE_NAME] ?
- data->set.str[STRING_PROXY_SERVICE_NAME] : "rcmd";
- uint8_t *etbuf;
- size_t etbuf_size;
-
- /* GSS-API request looks like
- * +----+------+-----+----------------+
- * |VER | MTYP | LEN | TOKEN |
- * +----+------+----------------------+
- * | 1 | 1 | 2 | up to 2^16 - 1 |
- * +----+------+-----+----------------+
- */
+ data->set.str[STRING_PROXY_SERVICE_NAME] : "rcmd";
+ SECURITY_STATUS status;
/* prepare service name */
if(strchr(service, '/'))
- service_name = curlx_strdup(service);
+ *service_namep = curlx_strdup(service);
else
- service_name = curl_maprintf("%s/%s",
- service, conn->socks_proxy.host.name);
- if(!service_name)
+ *service_namep = curl_maprintf("%s/%s",
+ service, conn->socks_proxy.host.name);
+ if(!*service_namep)
return CURLE_OUT_OF_MEMORY;
+ status =
+ Curl_pSecFn->AcquireCredentialsHandle(NULL,
+ (TCHAR *)CURL_UNCONST(TEXT("Kerberos")),
+ SECPKG_CRED_OUTBOUND,
+ NULL, NULL, NULL, NULL,
+ cred_handle, NULL);
+
+ if(check_sspi_err(data, status, "AcquireCredentialsHandle")) {
+ failf(data, "Failed to acquire credentials.");
+ return CURLE_COULDNT_CONNECT;
+ }
+
+ return CURLE_OK;
+}
+
+static CURLcode socks5_free_token(SecBuffer *send_token,
+ CURLcode result)
+{
+ if(send_token->pvBuffer) {
+ Curl_pSecFn->FreeContextBuffer(send_token->pvBuffer);
+ send_token->pvBuffer = NULL;
+ }
+ return result;
+}
+
+static CURLcode socks5_sspi_loop(struct Curl_cfilter *cf,
+ struct Curl_easy *data,
+ CredHandle *cred_handle,
+ CtxtHandle *sspi_context,
+ char *service_name,
+ unsigned long *sspi_ret_flagsp)
+{
+ struct connectdata *conn = cf->conn;
+ curl_socket_t sock = conn->sock[cf->sockindex];
+ CURLcode result = CURLE_OK;
+ CURLcode code;
+ SECURITY_STATUS status;
+ SecBuffer sspi_send_token, sspi_recv_token;
+ SecBufferDesc input_desc, output_desc;
+ PCtxtHandle context_handle = NULL;
+ unsigned short us_length;
+ size_t actualread;
+ size_t written;
+ unsigned char socksreq[4];
+
input_desc.cBuffers = 1;
input_desc.pBuffers = &sspi_recv_token;
input_desc.ulVersion = SECBUFFER_VERSION;
@@ -118,50 +136,17 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(struct Curl_cfilter *cf,
sspi_send_token.cbBuffer = 0;
sspi_send_token.pvBuffer = NULL;
- sspi_w_token[0].pvBuffer =
- sspi_w_token[1].pvBuffer =
- sspi_w_token[2].pvBuffer = NULL;
-
- wrap_desc.cBuffers = 3;
- wrap_desc.pBuffers = sspi_w_token;
- wrap_desc.ulVersion = SECBUFFER_VERSION;
-
- memset(&cred_handle, 0, sizeof(cred_handle));
- memset(&sspi_context, 0, sizeof(sspi_context));
-
- names.sUserName = NULL;
-
- etbuf = NULL;
- etbuf_size = 0;
-
- status =
- Curl_pSecFn->AcquireCredentialsHandle(NULL,
- (TCHAR *)CURL_UNCONST(TEXT("Kerberos")),
- SECPKG_CRED_OUTBOUND,
- NULL, NULL, NULL, NULL,
- &cred_handle, NULL);
-
- if(check_sspi_err(data, status, "AcquireCredentialsHandle")) {
- failf(data, "Failed to acquire credentials.");
- result = CURLE_COULDNT_CONNECT;
- goto error;
- }
-
(void)curlx_nonblock(sock, FALSE);
- /* As long as we need to keep sending some context info, and there is no */
- /* errors, keep sending it... */
for(;;) {
- TCHAR *sname;
-
- sname = curlx_convert_UTF8_to_tchar(service_name);
+ TCHAR *sname = curlx_convert_UTF8_to_tchar(service_name);
if(!sname) {
- result = CURLE_OUT_OF_MEMORY;
- goto error;
+ curlx_free(sspi_recv_token.pvBuffer);
+ return socks5_free_token(&sspi_send_token, CURLE_OUT_OF_MEMORY);
}
status =
- Curl_pSecFn->InitializeSecurityContext(&cred_handle, context_handle,
+ Curl_pSecFn->InitializeSecurityContext(cred_handle, context_handle,
sname,
ISC_REQ_MUTUAL_AUTH |
ISC_REQ_ALLOCATE_MEMORY |
@@ -169,19 +154,17 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(struct Curl_cfilter *cf,
ISC_REQ_REPLAY_DETECT,
0, SECURITY_NATIVE_DREP,
&input_desc, 0,
- &sspi_context,
+ sspi_context,
&output_desc,
- &sspi_ret_flags, NULL);
+ sspi_ret_flagsp, NULL);
curlx_free(sname);
-
Curl_safefree(sspi_recv_token.pvBuffer);
sspi_recv_token.cbBuffer = 0;
if(check_sspi_err(data, status, "InitializeSecurityContext")) {
failf(data, "Failed to initialise security context.");
- result = CURLE_COULDNT_CONNECT;
- goto error;
+ return socks5_free_token(&sspi_send_token, CURLE_COULDNT_CONNECT);
}
if(sspi_send_token.cbBuffer) {
@@ -189,8 +172,7 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(struct Curl_cfilter *cf,
socksreq[1] = 1; /* authentication message type */
if(sspi_send_token.cbBuffer > 0xffff) {
/* needs to fit in an unsigned 16-bit field */
- result = CURLE_COULDNT_CONNECT;
- goto error;
+ return socks5_free_token(&sspi_send_token, CURLE_COULDNT_CONNECT);
}
us_length = htons((unsigned short)sspi_send_token.cbBuffer);
memcpy(socksreq + 2, &us_length, sizeof(short));
@@ -198,8 +180,7 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(struct Curl_cfilter *cf,
code = Curl_conn_cf_send(cf->next, data, socksreq, 4, FALSE, &written);
if(code || (written != 4)) {
failf(data, "Failed to send SSPI authentication request.");
- result = CURLE_COULDNT_CONNECT;
- goto error;
+ return socks5_free_token(&sspi_send_token, CURLE_COULDNT_CONNECT);
}
code = Curl_conn_cf_send(cf->next, data,
@@ -207,15 +188,12 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(struct Curl_cfilter *cf,
sspi_send_token.cbBuffer, FALSE, &written);
if(code || (sspi_send_token.cbBuffer != written)) {
failf(data, "Failed to send SSPI authentication token.");
- result = CURLE_COULDNT_CONNECT;
- goto error;
+ return socks5_free_token(&sspi_send_token, CURLE_COULDNT_CONNECT);
}
}
- if(sspi_send_token.pvBuffer) {
- Curl_pSecFn->FreeContextBuffer(sspi_send_token.pvBuffer);
- sspi_send_token.pvBuffer = NULL;
- }
+ if(sspi_send_token.pvBuffer)
+ socks5_free_token(&sspi_send_token, CURLE_OK);
sspi_send_token.cbBuffer = 0;
Curl_safefree(sspi_recv_token.pvBuffer);
@@ -224,37 +202,22 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(struct Curl_cfilter *cf,
if(status != SEC_I_CONTINUE_NEEDED)
break;
- /* analyse response */
-
- /* GSS-API response looks like
- * +----+------+-----+----------------+
- * |VER | MTYP | LEN | TOKEN |
- * +----+------+----------------------+
- * | 1 | 1 | 2 | up to 2^16 - 1 |
- * +----+------+-----+----------------+
- */
-
result = Curl_blockread_all(cf, data, (char *)socksreq, 4, &actualread);
if(result || (actualread != 4)) {
failf(data, "Failed to receive SSPI authentication response.");
- if(!result)
- result = CURLE_COULDNT_CONNECT;
- goto error;
+ return result ? result : CURLE_COULDNT_CONNECT;
}
- /* ignore the first (VER) byte */
- if(socksreq[1] == 255) { /* status / message type */
+ if(socksreq[1] == 255) {
failf(data, "User was rejected by the SOCKS5 server (%u %u).",
(unsigned int)socksreq[0], (unsigned int)socksreq[1]);
- result = CURLE_COULDNT_CONNECT;
- goto error;
+ return CURLE_COULDNT_CONNECT;
}
- if(socksreq[1] != 1) { /* status / message type */
+ if(socksreq[1] != 1) {
failf(data, "Invalid SSPI authentication response type (%u %u).",
(unsigned int)socksreq[0], (unsigned int)socksreq[1]);
- result = CURLE_COULDNT_CONNECT;
- goto error;
+ return CURLE_COULDNT_CONNECT;
}
memcpy(&us_length, socksreq + 2, sizeof(short));
@@ -263,52 +226,56 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(struct Curl_cfilter *cf,
sspi_recv_token.cbBuffer = us_length;
sspi_recv_token.pvBuffer = curlx_malloc(us_length);
- if(!sspi_recv_token.pvBuffer) {
- result = CURLE_OUT_OF_MEMORY;
- goto error;
- }
+ if(!sspi_recv_token.pvBuffer)
+ return CURLE_OUT_OF_MEMORY;
+
result = Curl_blockread_all(cf, data, (char *)sspi_recv_token.pvBuffer,
sspi_recv_token.cbBuffer, &actualread);
if(result || (actualread != us_length)) {
failf(data, "Failed to receive SSPI authentication token.");
- if(!result)
- result = CURLE_COULDNT_CONNECT;
- goto error;
+ curlx_free(sspi_recv_token.pvBuffer);
+ return result ? result : CURLE_COULDNT_CONNECT;
}
- context_handle = &sspi_context;
+ context_handle = sspi_context;
}
- Curl_safefree(service_name);
+ return CURLE_OK;
+}
- /* Everything is good so far, user was authenticated! */
- status = Curl_pSecFn->QueryCredentialsAttributes(&cred_handle,
- SECPKG_CRED_ATTR_NAMES,
- &names);
- if(check_sspi_err(data, status, "QueryCredentialAttributes")) {
- failf(data, "Failed to determine username.");
- result = CURLE_COULDNT_CONNECT;
- goto error;
- }
- else {
- VERBOSE(char *user_utf8 = curlx_convert_tchar_to_UTF8(names.sUserName));
- infof(data, "SOCKS5 server authenticated user %s with GSS-API.",
- (user_utf8 ? user_utf8 : "(unknown)"));
- VERBOSE(curlx_free(user_utf8));
- Curl_pSecFn->FreeContextBuffer(names.sUserName);
- names.sUserName = NULL;
- }
+static CURLcode socks5_free(SecBuffer *sspi_w_token,
+ CURLcode result)
+{
+ Curl_safefree(sspi_w_token[0].pvBuffer);
+ Curl_safefree(sspi_w_token[1].pvBuffer);
+ Curl_safefree(sspi_w_token[2].pvBuffer);
+ return result;
+}
- /* Do encryption */
- socksreq[0] = 1; /* GSS-API subnegotiation version */
- socksreq[1] = 2; /* encryption message type */
+static CURLcode socks5_sspi_encrypt(struct Curl_cfilter *cf,
+ struct Curl_easy *data,
+ CtxtHandle *sspi_context,
+ unsigned long sspi_ret_flags)
+{
+ CURLcode result = CURLE_OK;
+ CURLcode code;
+ SECURITY_STATUS status;
+ unsigned char gss_enc;
+ SecBuffer sspi_w_token[3];
+ SecBufferDesc wrap_desc;
+ SecPkgContext_Sizes sspi_sizes;
+ unsigned short us_length;
+ unsigned long qop;
+ unsigned char socksreq[4];
+ uint8_t *etbuf = NULL;
+ size_t etbuf_size = 0;
+ size_t actualread;
+ size_t written;
- gss_enc = 0; /* no data protection */
- /* do confidentiality protection if supported */
+ gss_enc = 0;
if(sspi_ret_flags & ISC_REQ_CONFIDENTIALITY)
gss_enc = 2;
- /* else do integrity protection */
else if(sspi_ret_flags & ISC_REQ_INTEGRITY)
gss_enc = 1;
@@ -316,96 +283,64 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(struct Curl_cfilter *cf,
(gss_enc == 0) ? "no" :
((gss_enc == 1) ? "integrity" : "confidentiality") );
- /*
- * Sending the encryption type in clear seems wrong. It should be
- * protected with gss_seal()/gss_wrap(). See RFC1961 extract below
- * The NEC reference implementations on which this is based is
- * therefore at fault
- *
- * +------+------+------+.......................+
- * + ver | mtyp | len | token |
- * +------+------+------+.......................+
- * + 0x01 | 0x02 | 0x02 | up to 2^16 - 1 octets |
- * +------+------+------+.......................+
- *
- * Where:
- *
- * - "ver" is the protocol version number, here 1 to represent the
- * first version of the SOCKS/GSS-API protocol
- *
- * - "mtyp" is the message type, here 2 to represent a protection
- * -level negotiation message
- *
- * - "len" is the length of the "token" field in octets
- *
- * - "token" is the GSS-API encapsulated protection level
- *
- * The token is produced by encapsulating an octet containing the
- * required protection level using gss_seal()/gss_wrap() with conf_req
- * set to FALSE. The token is verified using gss_unseal()/
- * gss_unwrap().
- *
- */
+ sspi_w_token[0].pvBuffer =
+ sspi_w_token[1].pvBuffer =
+ sspi_w_token[2].pvBuffer = NULL;
+
+ wrap_desc.cBuffers = 3;
+ wrap_desc.pBuffers = sspi_w_token;
+ wrap_desc.ulVersion = SECBUFFER_VERSION;
+
+ socksreq[0] = 1;
+ socksreq[1] = 2;
if(data->set.socks5_gssapi_nec) {
us_length = htons((unsigned short)1);
memcpy(socksreq + 2, &us_length, sizeof(short));
}
else {
- status = Curl_pSecFn->QueryContextAttributes(&sspi_context,
+ status = Curl_pSecFn->QueryContextAttributes(sspi_context,
SECPKG_ATTR_SIZES,
&sspi_sizes);
if(check_sspi_err(data, status, "QueryContextAttributes")) {
failf(data, "Failed to query security context attributes.");
- result = CURLE_COULDNT_CONNECT;
- goto error;
+ return CURLE_COULDNT_CONNECT;
}
sspi_w_token[0].cbBuffer = sspi_sizes.cbSecurityTrailer;
sspi_w_token[0].BufferType = SECBUFFER_TOKEN;
sspi_w_token[0].pvBuffer = curlx_malloc(sspi_sizes.cbSecurityTrailer);
- if(!sspi_w_token[0].pvBuffer) {
- result = CURLE_OUT_OF_MEMORY;
- goto error;
- }
+ if(!sspi_w_token[0].pvBuffer)
+ return CURLE_OUT_OF_MEMORY;
sspi_w_token[1].cbBuffer = 1;
+ sspi_w_token[1].BufferType = SECBUFFER_DATA;
sspi_w_token[1].pvBuffer = curlx_malloc(1);
- if(!sspi_w_token[1].pvBuffer) {
- result = CURLE_OUT_OF_MEMORY;
- goto error;
- }
+ if(!sspi_w_token[1].pvBuffer)
+ return socks5_free(sspi_w_token, CURLE_OUT_OF_MEMORY);
memcpy(sspi_w_token[1].pvBuffer, &gss_enc, 1);
sspi_w_token[2].BufferType = SECBUFFER_PADDING;
sspi_w_token[2].cbBuffer = sspi_sizes.cbBlockSize;
sspi_w_token[2].pvBuffer = curlx_malloc(sspi_sizes.cbBlockSize);
- if(!sspi_w_token[2].pvBuffer) {
- result = CURLE_OUT_OF_MEMORY;
- goto error;
- }
- status = Curl_pSecFn->EncryptMessage(&sspi_context,
+ if(!sspi_w_token[2].pvBuffer)
+ return socks5_free(sspi_w_token, CURLE_OUT_OF_MEMORY);
+
+ status = Curl_pSecFn->EncryptMessage(sspi_context,
KERB_WRAP_NO_ENCRYPT,
&wrap_desc, 0);
- if(check_sspi_err(data, status, "EncryptMessage")) {
- failf(data, "Failed to query security context attributes.");
- result = CURLE_COULDNT_CONNECT;
- goto error;
- }
+ if(check_sspi_err(data, status, "EncryptMessage"))
+ return socks5_free(sspi_w_token, CURLE_COULDNT_CONNECT);
etbuf_size = sspi_w_token[0].cbBuffer + sspi_w_token[1].cbBuffer +
- sspi_w_token[2].cbBuffer;
- if(etbuf_size > 0xffff) {
- /* needs to fit in an unsigned 16-bit field */
- result = CURLE_COULDNT_CONNECT;
- goto error;
- }
+ sspi_w_token[2].cbBuffer;
+ if(etbuf_size > 0xffff)
+ return socks5_free(sspi_w_token, CURLE_COULDNT_CONNECT);
+
etbuf = curlx_malloc(etbuf_size);
- if(!etbuf) {
- result = CURLE_OUT_OF_MEMORY;
- goto error;
- }
+ if(!etbuf)
+ return socks5_free(sspi_w_token, CURLE_OUT_OF_MEMORY);
memcpy(etbuf, sspi_w_token[0].pvBuffer, sspi_w_token[0].cbBuffer);
memcpy(etbuf + sspi_w_token[0].cbBuffer,
@@ -413,12 +348,7 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(struct Curl_cfilter *cf,
memcpy(etbuf + sspi_w_token[0].cbBuffer + sspi_w_token[1].cbBuffer,
sspi_w_token[2].pvBuffer, sspi_w_token[2].cbBuffer);
- Curl_safefree(sspi_w_token[0].pvBuffer);
- sspi_w_token[0].cbBuffer = 0;
- Curl_safefree(sspi_w_token[1].pvBuffer);
- sspi_w_token[1].cbBuffer = 0;
- Curl_safefree(sspi_w_token[2].pvBuffer);
- sspi_w_token[2].cbBuffer = 0;
+ (void)socks5_free(sspi_w_token, CURLE_OK);
us_length = htons((unsigned short)etbuf_size);
memcpy(socksreq + 2, &us_length, sizeof(short));
@@ -427,8 +357,8 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(struct Curl_cfilter *cf,
code = Curl_conn_cf_send(cf->next, data, socksreq, 4, FALSE, &written);
if(code || (written != 4)) {
failf(data, "Failed to send SSPI encryption request.");
- result = CURLE_COULDNT_CONNECT;
- goto error;
+ curlx_free(etbuf);
+ return CURLE_COULDNT_CONNECT;
}
if(data->set.socks5_gssapi_nec) {
@@ -436,42 +366,35 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(struct Curl_cfilter *cf,
code = Curl_conn_cf_send(cf->next, data, socksreq, 1, FALSE, &written);
if(code || (written != 1)) {
failf(data, "Failed to send SSPI encryption type.");
- result = CURLE_COULDNT_CONNECT;
- goto error;
+ return CURLE_COULDNT_CONNECT;
}
}
else {
- code = Curl_conn_cf_send(cf->next, data, etbuf, etbuf_size,
- FALSE, &written);
+ code = Curl_conn_cf_send(cf->next, data, etbuf, etbuf_size, FALSE,
+ &written);
+ curlx_free(etbuf);
if(code || (etbuf_size != written)) {
failf(data, "Failed to send SSPI encryption type.");
- result = CURLE_COULDNT_CONNECT;
- goto error;
+ return CURLE_COULDNT_CONNECT;
}
- Curl_safefree(etbuf);
}
result = Curl_blockread_all(cf, data, (char *)socksreq, 4, &actualread);
if(result || (actualread != 4)) {
failf(data, "Failed to receive SSPI encryption response.");
- if(!result)
- result = CURLE_COULDNT_CONNECT;
- goto error;
+ return result ? result : CURLE_COULDNT_CONNECT;
}
- /* ignore the first (VER) byte */
- if(socksreq[1] == 255) { /* status / message type */
+ if(socksreq[1] == 255) {
failf(data, "User was rejected by the SOCKS5 server (%u %u).",
(unsigned int)socksreq[0], (unsigned int)socksreq[1]);
- result = CURLE_COULDNT_CONNECT;
- goto error;
+ return CURLE_COULDNT_CONNECT;
}
- if(socksreq[1] != 2) { /* status / message type */
+ if(socksreq[1] != 2) {
failf(data, "Invalid SSPI encryption response type (%u %u).",
(unsigned int)socksreq[0], (unsigned int)socksreq[1]);
- result = CURLE_COULDNT_CONNECT;
- goto error;
+ return CURLE_COULDNT_CONNECT;
}
memcpy(&us_length, socksreq + 2, sizeof(short));
@@ -479,19 +402,16 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(struct Curl_cfilter *cf,
sspi_w_token[0].cbBuffer = us_length;
sspi_w_token[0].pvBuffer = curlx_malloc(us_length);
- if(!sspi_w_token[0].pvBuffer) {
- result = CURLE_OUT_OF_MEMORY;
- goto error;
- }
+ if(!sspi_w_token[0].pvBuffer)
+ return CURLE_OUT_OF_MEMORY;
result = Curl_blockread_all(cf, data, (char *)sspi_w_token[0].pvBuffer,
sspi_w_token[0].cbBuffer, &actualread);
if(result || (actualread != us_length)) {
failf(data, "Failed to receive SSPI encryption type.");
- if(!result)
- result = CURLE_COULDNT_CONNECT;
- goto error;
+ curlx_free(sspi_w_token[0].pvBuffer);
+ return result ? result : CURLE_COULDNT_CONNECT;
}
if(!data->set.socks5_gssapi_nec) {
@@ -501,86 +421,108 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(struct Curl_cfilter *cf,
sspi_w_token[1].cbBuffer = 0;
sspi_w_token[1].pvBuffer = NULL;
- status = Curl_pSecFn->DecryptMessage(&sspi_context, &wrap_desc,
+ status = Curl_pSecFn->DecryptMessage(sspi_context, &wrap_desc,
0, &qop);
- /* since sspi_w_token[1].pvBuffer is allocated by the SSPI in this case, it
- must be freed in this block using FreeContextBuffer() instead of
- potentially in error cleanup using curlx_free(). */
-
if(check_sspi_err(data, status, "DecryptMessage")) {
- failf(data, "Failed to query security context attributes.");
- if(sspi_w_token[1].pvBuffer) {
+ if(sspi_w_token[1].pvBuffer)
Curl_pSecFn->FreeContextBuffer(sspi_w_token[1].pvBuffer);
- sspi_w_token[1].pvBuffer = NULL;
- }
- result = CURLE_COULDNT_CONNECT;
- goto error;
+ curlx_free(sspi_w_token[0].pvBuffer);
+ return CURLE_COULDNT_CONNECT;
}
if(sspi_w_token[1].cbBuffer != 1) {
failf(data, "Invalid SSPI encryption response length (%lu).",
(unsigned long)sspi_w_token[1].cbBuffer);
- if(sspi_w_token[1].pvBuffer) {
+ if(sspi_w_token[1].pvBuffer)
Curl_pSecFn->FreeContextBuffer(sspi_w_token[1].pvBuffer);
- sspi_w_token[1].pvBuffer = NULL;
- }
- result = CURLE_COULDNT_CONNECT;
- goto error;
+ curlx_free(sspi_w_token[0].pvBuffer);
+ return CURLE_COULDNT_CONNECT;
}
memcpy(socksreq, sspi_w_token[1].pvBuffer, sspi_w_token[1].cbBuffer);
- Curl_safefree(sspi_w_token[0].pvBuffer);
- sspi_w_token[0].cbBuffer = 0;
Curl_pSecFn->FreeContextBuffer(sspi_w_token[1].pvBuffer);
- sspi_w_token[1].pvBuffer = NULL;
- sspi_w_token[1].cbBuffer = 0;
}
else {
if(sspi_w_token[0].cbBuffer != 1) {
failf(data, "Invalid SSPI encryption response length (%lu).",
- sspi_w_token[0].cbBuffer);
- result = CURLE_COULDNT_CONNECT;
- goto error;
+ (unsigned long)sspi_w_token[0].cbBuffer);
+ curlx_free(sspi_w_token[0].pvBuffer);
+ return CURLE_COULDNT_CONNECT;
}
memcpy(socksreq, sspi_w_token[0].pvBuffer, sspi_w_token[0].cbBuffer);
- Curl_safefree(sspi_w_token[0].pvBuffer);
- sspi_w_token[0].cbBuffer = 0;
}
- (void)curlx_nonblock(sock, TRUE);
+ curlx_free(sspi_w_token[0].pvBuffer);
infof(data, "SOCKS5 access with%s protection granted BUT NOT USED.",
(socksreq[0] == 0) ? "out GSS-API data" :
((socksreq[0] == 1) ? " GSS-API integrity" :
" GSS-API confidentiality"));
- /* For later use if encryption is required
- conn->socks5_gssapi_enctype = socksreq[0];
- if(socksreq[0] != 0)
- conn->socks5_sspi_context = sspi_context;
- else {
- Curl_pSecFn->DeleteSecurityContext(&sspi_context);
- conn->socks5_sspi_context = sspi_context;
- }
- */
+ return CURLE_OK;
+}
+
+CURLcode Curl_SOCKS5_gssapi_negotiate(struct Curl_cfilter *cf,
+ struct Curl_easy *data)
+{
+ struct connectdata *conn = cf->conn;
+ curl_socket_t sock = conn->sock[cf->sockindex];
+ CURLcode result;
+ SECURITY_STATUS status;
+ CredHandle cred_handle;
+ CtxtHandle sspi_context;
+ SecPkgCredentials_Names names;
+ char *service_name = NULL;
+ unsigned long sspi_ret_flags = 0;
+
+ memset(&cred_handle, 0, sizeof(cred_handle));
+ memset(&sspi_context, 0, sizeof(sspi_context));
+ names.sUserName = NULL;
+
+ result = socks5_sspi_setup(cf, data, &cred_handle, &service_name);
+ if(result)
+ goto error;
+
+ result = socks5_sspi_loop(cf, data, &cred_handle, &sspi_context,
+ service_name, &sspi_ret_flags);
+ if(result)
+ goto error;
+ Curl_safefree(service_name);
+
+ status = Curl_pSecFn->QueryCredentialsAttributes(&cred_handle,
+ SECPKG_CRED_ATTR_NAMES,
+ &names);
+ if(check_sspi_err(data, status, "QueryCredentialAttributes")) {
+ failf(data, "Failed to determine username.");
+ result = CURLE_COULDNT_CONNECT;
+ goto error;
+ }
+ else {
+ VERBOSE(char *user_utf8 = curlx_convert_tchar_to_UTF8(names.sUserName));
+ infof(data, "SOCKS5 server authenticated user %s with GSS-API.",
+ (user_utf8 ? user_utf8 : "(unknown)"));
+ VERBOSE(curlx_free(user_utf8));
+ Curl_pSecFn->FreeContextBuffer(names.sUserName);
+ names.sUserName = NULL;
+ }
+
+ result = socks5_sspi_encrypt(cf, data, &sspi_context, sspi_ret_flags);
+ if(result)
+ goto error;
+
+ (void)curlx_nonblock(sock, TRUE);
Curl_pSecFn->DeleteSecurityContext(&sspi_context);
Curl_pSecFn->FreeCredentialsHandle(&cred_handle);
return CURLE_OK;
+
error:
(void)curlx_nonblock(sock, TRUE);
curlx_free(service_name);
Curl_pSecFn->DeleteSecurityContext(&sspi_context);
Curl_pSecFn->FreeCredentialsHandle(&cred_handle);
- curlx_free(sspi_recv_token.pvBuffer);
- if(sspi_send_token.pvBuffer)
- Curl_pSecFn->FreeContextBuffer(sspi_send_token.pvBuffer);
if(names.sUserName)
Curl_pSecFn->FreeContextBuffer(names.sUserName);
- curlx_free(sspi_w_token[0].pvBuffer);
- curlx_free(sspi_w_token[1].pvBuffer);
- curlx_free(sspi_w_token[2].pvBuffer);
- curlx_free(etbuf);
return result;
}
#endif