26 #if defined(USE_WINDOWS_SSPI) && !defined(CURL_DISABLE_PROXY) 47 SECURITY_STATUS status,
50 if(status != SEC_E_OK &&
51 status != SEC_I_COMPLETE_AND_CONTINUE &&
52 status != SEC_I_COMPLETE_NEEDED &&
53 status != SEC_I_CONTINUE_NEEDED) {
54 failf(conn->
data,
"SSPI error: %s failed: %s",
function,
55 Curl_sspi_strerror(conn, status));
62 CURLcode Curl_SOCKS5_gssapi_negotiate(
int sockindex,
72 SECURITY_STATUS status;
73 unsigned long sspi_ret_flags = 0;
74 unsigned char gss_enc;
75 SecBuffer sspi_send_token, sspi_recv_token, sspi_w_token[3];
76 SecBufferDesc input_desc, output_desc, wrap_desc;
77 SecPkgContext_Sizes sspi_sizes;
78 CredHandle cred_handle;
79 CtxtHandle sspi_context;
80 PCtxtHandle context_handle = NULL;
81 SecPkgCredentials_Names names;
83 char *service_name = NULL;
84 unsigned short us_length;
86 unsigned char socksreq[4];
87 const char *service = data->
set.
str[STRING_PROXY_SERVICE_NAME] ?
88 data->
set.
str[STRING_PROXY_SERVICE_NAME] :
"rcmd";
89 const size_t service_length = strlen(service);
100 if(strchr(service,
'/')) {
101 service_name =
strdup(service);
106 service_name =
malloc(service_length +
110 snprintf(service_name, service_length +
115 input_desc.cBuffers = 1;
116 input_desc.pBuffers = &sspi_recv_token;
117 input_desc.ulVersion = SECBUFFER_VERSION;
119 sspi_recv_token.BufferType = SECBUFFER_TOKEN;
120 sspi_recv_token.cbBuffer = 0;
121 sspi_recv_token.pvBuffer = NULL;
123 output_desc.cBuffers = 1;
124 output_desc.pBuffers = &sspi_send_token;
125 output_desc.ulVersion = SECBUFFER_VERSION;
127 sspi_send_token.BufferType = SECBUFFER_TOKEN;
128 sspi_send_token.cbBuffer = 0;
129 sspi_send_token.pvBuffer = NULL;
131 wrap_desc.cBuffers = 3;
132 wrap_desc.pBuffers = sspi_w_token;
133 wrap_desc.ulVersion = SECBUFFER_VERSION;
135 cred_handle.dwLower = 0;
136 cred_handle.dwUpper = 0;
138 status = s_pSecFn->AcquireCredentialsHandle(NULL,
139 (TCHAR *) TEXT(
"Kerberos"),
140 SECPKG_CRED_OUTBOUND,
148 if(check_sspi_err(conn, status,
"AcquireCredentialsHandle")) {
149 failf(data,
"Failed to acquire credentials.");
151 s_pSecFn->FreeCredentialsHandle(&cred_handle);
160 sname = Curl_convert_UTF8_to_tchar(service_name);
164 status = s_pSecFn->InitializeSecurityContext(&cred_handle,
167 ISC_REQ_MUTUAL_AUTH |
168 ISC_REQ_ALLOCATE_MEMORY |
169 ISC_REQ_CONFIDENTIALITY |
170 ISC_REQ_REPLAY_DETECT,
172 SECURITY_NATIVE_DREP,
180 Curl_unicodefree(sname);
182 if(sspi_recv_token.pvBuffer) {
183 s_pSecFn->FreeContextBuffer(sspi_recv_token.pvBuffer);
184 sspi_recv_token.pvBuffer = NULL;
185 sspi_recv_token.cbBuffer = 0;
188 if(check_sspi_err(conn, status,
"InitializeSecurityContext")) {
190 s_pSecFn->FreeCredentialsHandle(&cred_handle);
191 s_pSecFn->DeleteSecurityContext(&sspi_context);
192 if(sspi_recv_token.pvBuffer)
193 s_pSecFn->FreeContextBuffer(sspi_recv_token.pvBuffer);
194 failf(data,
"Failed to initialise security context.");
198 if(sspi_send_token.cbBuffer != 0) {
201 us_length = htons((
short)sspi_send_token.cbBuffer);
202 memcpy(socksreq + 2, &us_length,
sizeof(
short));
205 if(code || (4 != written)) {
206 failf(data,
"Failed to send SSPI authentication request.");
208 if(sspi_send_token.pvBuffer)
209 s_pSecFn->FreeContextBuffer(sspi_send_token.pvBuffer);
210 if(sspi_recv_token.pvBuffer)
211 s_pSecFn->FreeContextBuffer(sspi_recv_token.pvBuffer);
212 s_pSecFn->FreeCredentialsHandle(&cred_handle);
213 s_pSecFn->DeleteSecurityContext(&sspi_context);
218 sspi_send_token.cbBuffer, &written);
219 if(code || (sspi_send_token.cbBuffer != (
size_t)written)) {
220 failf(data,
"Failed to send SSPI authentication token.");
222 if(sspi_send_token.pvBuffer)
223 s_pSecFn->FreeContextBuffer(sspi_send_token.pvBuffer);
224 if(sspi_recv_token.pvBuffer)
225 s_pSecFn->FreeContextBuffer(sspi_recv_token.pvBuffer);
226 s_pSecFn->FreeCredentialsHandle(&cred_handle);
227 s_pSecFn->DeleteSecurityContext(&sspi_context);
233 if(sspi_send_token.pvBuffer) {
234 s_pSecFn->FreeContextBuffer(sspi_send_token.pvBuffer);
235 sspi_send_token.pvBuffer = NULL;
237 sspi_send_token.cbBuffer = 0;
239 if(sspi_recv_token.pvBuffer) {
240 s_pSecFn->FreeContextBuffer(sspi_recv_token.pvBuffer);
241 sspi_recv_token.pvBuffer = NULL;
243 sspi_recv_token.cbBuffer = 0;
245 if(status != SEC_I_CONTINUE_NEEDED)
259 if(result || (actualread != 4)) {
260 failf(data,
"Failed to receive SSPI authentication response.");
262 s_pSecFn->FreeCredentialsHandle(&cred_handle);
263 s_pSecFn->DeleteSecurityContext(&sspi_context);
268 if(socksreq[1] == 255) {
269 failf(data,
"User was rejected by the SOCKS5 server (%u %u).",
270 (
unsigned int)socksreq[0], (
unsigned int)socksreq[1]);
272 s_pSecFn->FreeCredentialsHandle(&cred_handle);
273 s_pSecFn->DeleteSecurityContext(&sspi_context);
277 if(socksreq[1] != 1) {
278 failf(data,
"Invalid SSPI authentication response type (%u %u).",
279 (
unsigned int)socksreq[0], (
unsigned int)socksreq[1]);
281 s_pSecFn->FreeCredentialsHandle(&cred_handle);
282 s_pSecFn->DeleteSecurityContext(&sspi_context);
286 memcpy(&us_length, socksreq + 2,
sizeof(
short));
287 us_length = ntohs(us_length);
289 sspi_recv_token.cbBuffer = us_length;
290 sspi_recv_token.pvBuffer =
malloc(us_length);
292 if(!sspi_recv_token.pvBuffer) {
294 s_pSecFn->FreeCredentialsHandle(&cred_handle);
295 s_pSecFn->DeleteSecurityContext(&sspi_context);
299 sspi_recv_token.cbBuffer, &actualread);
301 if(result || (actualread != us_length)) {
302 failf(data,
"Failed to receive SSPI authentication token.");
304 if(sspi_recv_token.pvBuffer)
305 s_pSecFn->FreeContextBuffer(sspi_recv_token.pvBuffer);
306 s_pSecFn->FreeCredentialsHandle(&cred_handle);
307 s_pSecFn->DeleteSecurityContext(&sspi_context);
311 context_handle = &sspi_context;
317 status = s_pSecFn->QueryCredentialsAttributes(&cred_handle,
318 SECPKG_CRED_ATTR_NAMES,
320 s_pSecFn->FreeCredentialsHandle(&cred_handle);
321 if(check_sspi_err(conn, status,
"QueryCredentialAttributes")) {
322 s_pSecFn->DeleteSecurityContext(&sspi_context);
323 s_pSecFn->FreeContextBuffer(names.sUserName);
324 failf(data,
"Failed to determine user name.");
327 infof(data,
"SOCKS5 server authencticated user %s with GSS-API.\n",
329 s_pSecFn->FreeContextBuffer(names.sUserName);
337 if(sspi_ret_flags & ISC_REQ_CONFIDENTIALITY)
340 else if(sspi_ret_flags & ISC_REQ_INTEGRITY)
343 infof(data,
"SOCKS5 server supports GSS-API %s data protection.\n",
344 (gss_enc == 0)?
"no":((gss_enc == 1)?
"integrity":
"confidentiality") );
378 if(data->
set.socks5_gssapi_nec) {
379 us_length = htons((
short)1);
380 memcpy(socksreq + 2, &us_length,
sizeof(
short));
383 status = s_pSecFn->QueryContextAttributes(&sspi_context,
386 if(check_sspi_err(conn, status,
"QueryContextAttributes")) {
387 s_pSecFn->DeleteSecurityContext(&sspi_context);
388 failf(data,
"Failed to query security context attributes.");
392 sspi_w_token[0].cbBuffer = sspi_sizes.cbSecurityTrailer;
393 sspi_w_token[0].BufferType = SECBUFFER_TOKEN;
394 sspi_w_token[0].pvBuffer =
malloc(sspi_sizes.cbSecurityTrailer);
396 if(!sspi_w_token[0].pvBuffer) {
397 s_pSecFn->DeleteSecurityContext(&sspi_context);
401 sspi_w_token[1].cbBuffer = 1;
402 sspi_w_token[1].pvBuffer =
malloc(1);
403 if(!sspi_w_token[1].pvBuffer) {
404 s_pSecFn->FreeContextBuffer(sspi_w_token[0].pvBuffer);
405 s_pSecFn->DeleteSecurityContext(&sspi_context);
409 memcpy(sspi_w_token[1].pvBuffer, &gss_enc, 1);
410 sspi_w_token[2].BufferType = SECBUFFER_PADDING;
411 sspi_w_token[2].cbBuffer = sspi_sizes.cbBlockSize;
412 sspi_w_token[2].pvBuffer =
malloc(sspi_sizes.cbBlockSize);
413 if(!sspi_w_token[2].pvBuffer) {
414 s_pSecFn->FreeContextBuffer(sspi_w_token[0].pvBuffer);
415 s_pSecFn->FreeContextBuffer(sspi_w_token[1].pvBuffer);
416 s_pSecFn->DeleteSecurityContext(&sspi_context);
419 status = s_pSecFn->EncryptMessage(&sspi_context,
420 KERB_WRAP_NO_ENCRYPT,
423 if(check_sspi_err(conn, status,
"EncryptMessage")) {
424 s_pSecFn->FreeContextBuffer(sspi_w_token[0].pvBuffer);
425 s_pSecFn->FreeContextBuffer(sspi_w_token[1].pvBuffer);
426 s_pSecFn->FreeContextBuffer(sspi_w_token[2].pvBuffer);
427 s_pSecFn->DeleteSecurityContext(&sspi_context);
428 failf(data,
"Failed to query security context attributes.");
431 sspi_send_token.cbBuffer = sspi_w_token[0].cbBuffer
432 + sspi_w_token[1].cbBuffer
433 + sspi_w_token[2].cbBuffer;
434 sspi_send_token.pvBuffer =
malloc(sspi_send_token.cbBuffer);
435 if(!sspi_send_token.pvBuffer) {
436 s_pSecFn->FreeContextBuffer(sspi_w_token[0].pvBuffer);
437 s_pSecFn->FreeContextBuffer(sspi_w_token[1].pvBuffer);
438 s_pSecFn->FreeContextBuffer(sspi_w_token[2].pvBuffer);
439 s_pSecFn->DeleteSecurityContext(&sspi_context);
443 memcpy(sspi_send_token.pvBuffer, sspi_w_token[0].pvBuffer,
444 sspi_w_token[0].cbBuffer);
445 memcpy((PUCHAR) sspi_send_token.pvBuffer +(
int)sspi_w_token[0].cbBuffer,
446 sspi_w_token[1].pvBuffer, sspi_w_token[1].cbBuffer);
447 memcpy((PUCHAR) sspi_send_token.pvBuffer
448 + sspi_w_token[0].cbBuffer
449 + sspi_w_token[1].cbBuffer,
450 sspi_w_token[2].pvBuffer, sspi_w_token[2].cbBuffer);
452 s_pSecFn->FreeContextBuffer(sspi_w_token[0].pvBuffer);
453 sspi_w_token[0].pvBuffer = NULL;
454 sspi_w_token[0].cbBuffer = 0;
455 s_pSecFn->FreeContextBuffer(sspi_w_token[1].pvBuffer);
456 sspi_w_token[1].pvBuffer = NULL;
457 sspi_w_token[1].cbBuffer = 0;
458 s_pSecFn->FreeContextBuffer(sspi_w_token[2].pvBuffer);
459 sspi_w_token[2].pvBuffer = NULL;
460 sspi_w_token[2].cbBuffer = 0;
462 us_length = htons((
short)sspi_send_token.cbBuffer);
463 memcpy(socksreq + 2, &us_length,
sizeof(
short));
467 if(code || (4 != written)) {
468 failf(data,
"Failed to send SSPI encryption request.");
469 if(sspi_send_token.pvBuffer)
470 s_pSecFn->FreeContextBuffer(sspi_send_token.pvBuffer);
471 s_pSecFn->DeleteSecurityContext(&sspi_context);
475 if(data->
set.socks5_gssapi_nec) {
476 memcpy(socksreq, &gss_enc, 1);
478 if(code || (1 != written)) {
479 failf(data,
"Failed to send SSPI encryption type.");
480 s_pSecFn->DeleteSecurityContext(&sspi_context);
486 sspi_send_token.cbBuffer, &written);
487 if(code || (sspi_send_token.cbBuffer != (
size_t)written)) {
488 failf(data,
"Failed to send SSPI encryption type.");
489 if(sspi_send_token.pvBuffer)
490 s_pSecFn->FreeContextBuffer(sspi_send_token.pvBuffer);
491 s_pSecFn->DeleteSecurityContext(&sspi_context);
494 if(sspi_send_token.pvBuffer)
495 s_pSecFn->FreeContextBuffer(sspi_send_token.pvBuffer);
499 if(result || (actualread != 4)) {
500 failf(data,
"Failed to receive SSPI encryption response.");
501 s_pSecFn->DeleteSecurityContext(&sspi_context);
506 if(socksreq[1] == 255) {
507 failf(data,
"User was rejected by the SOCKS5 server (%u %u).",
508 (
unsigned int)socksreq[0], (
unsigned int)socksreq[1]);
509 s_pSecFn->DeleteSecurityContext(&sspi_context);
513 if(socksreq[1] != 2) {
514 failf(data,
"Invalid SSPI encryption response type (%u %u).",
515 (
unsigned int)socksreq[0], (
unsigned int)socksreq[1]);
516 s_pSecFn->DeleteSecurityContext(&sspi_context);
520 memcpy(&us_length, socksreq + 2,
sizeof(
short));
521 us_length = ntohs(us_length);
523 sspi_w_token[0].cbBuffer = us_length;
524 sspi_w_token[0].pvBuffer =
malloc(us_length);
525 if(!sspi_w_token[0].pvBuffer) {
526 s_pSecFn->DeleteSecurityContext(&sspi_context);
531 sspi_w_token[0].cbBuffer, &actualread);
533 if(result || (actualread != us_length)) {
534 failf(data,
"Failed to receive SSPI encryption type.");
535 s_pSecFn->FreeContextBuffer(sspi_w_token[0].pvBuffer);
536 s_pSecFn->DeleteSecurityContext(&sspi_context);
541 if(!data->
set.socks5_gssapi_nec) {
542 wrap_desc.cBuffers = 2;
543 sspi_w_token[0].BufferType = SECBUFFER_STREAM;
544 sspi_w_token[1].BufferType = SECBUFFER_DATA;
545 sspi_w_token[1].cbBuffer = 0;
546 sspi_w_token[1].pvBuffer = NULL;
548 status = s_pSecFn->DecryptMessage(&sspi_context,
553 if(check_sspi_err(conn, status,
"DecryptMessage")) {
554 if(sspi_w_token[0].pvBuffer)
555 s_pSecFn->FreeContextBuffer(sspi_w_token[0].pvBuffer);
556 if(sspi_w_token[1].pvBuffer)
557 s_pSecFn->FreeContextBuffer(sspi_w_token[1].pvBuffer);
558 s_pSecFn->DeleteSecurityContext(&sspi_context);
559 failf(data,
"Failed to query security context attributes.");
563 if(sspi_w_token[1].cbBuffer != 1) {
564 failf(data,
"Invalid SSPI encryption response length (%lu).",
565 (
unsigned long)sspi_w_token[1].cbBuffer);
566 if(sspi_w_token[0].pvBuffer)
567 s_pSecFn->FreeContextBuffer(sspi_w_token[0].pvBuffer);
568 if(sspi_w_token[1].pvBuffer)
569 s_pSecFn->FreeContextBuffer(sspi_w_token[1].pvBuffer);
570 s_pSecFn->DeleteSecurityContext(&sspi_context);
574 memcpy(socksreq, sspi_w_token[1].pvBuffer, sspi_w_token[1].cbBuffer);
575 s_pSecFn->FreeContextBuffer(sspi_w_token[0].pvBuffer);
576 s_pSecFn->FreeContextBuffer(sspi_w_token[1].pvBuffer);
579 if(sspi_w_token[0].cbBuffer != 1) {
580 failf(data,
"Invalid SSPI encryption response length (%lu).",
581 (
unsigned long)sspi_w_token[0].cbBuffer);
582 s_pSecFn->FreeContextBuffer(sspi_w_token[0].pvBuffer);
583 s_pSecFn->DeleteSecurityContext(&sspi_context);
586 memcpy(socksreq, sspi_w_token[0].pvBuffer, sspi_w_token[0].cbBuffer);
587 s_pSecFn->FreeContextBuffer(sspi_w_token[0].pvBuffer);
590 infof(data,
"SOCKS5 access with%s protection granted.\n",
591 (socksreq[0] == 0)?
"out GSS-API data":
592 ((socksreq[0] == 1)?
" GSS-API integrity":
" GSS-API confidentiality"));
CURLcode Curl_write_plain(struct connectdata *conn, curl_socket_t sockfd, const void *mem, size_t len, ssize_t *written)
UNITTEST_START int result
memcpy(filename, filename1, strlen(filename1))
struct proxy_info socks_proxy
int Curl_blockread_all(struct connectdata *conn, curl_socket_t sockfd, char *buf, ssize_t buffersize, ssize_t *n)