mirror of
https://github.com/moparisthebest/curl
synced 2024-12-21 15:48:49 -05:00
tests: add initial gssapi test using stub implementation
The stub implementation is pre-loaded using LD_PRELOAD and emulates common gssapi uses (only builds if curl is initially built with gssapi support). The initial tests are currently disabled for debug builds as LD_PRELOAD is not used then. Ref: https://github.com/curl/curl/pull/1687
This commit is contained in:
parent
65872efea7
commit
56d949d31a
@ -1335,6 +1335,13 @@ else
|
||||
CPPFLAGS="$save_CPPFLAGS"
|
||||
fi
|
||||
|
||||
build_libstubgss=no
|
||||
if test x"$want_gss" = "xyes"; then
|
||||
build_libstubgss=yes
|
||||
fi
|
||||
|
||||
AM_CONDITIONAL(BUILD_STUB_GSS, test "x$build_libstubgss" = "xyes")
|
||||
|
||||
dnl -------------------------------------------------------------
|
||||
dnl parse --with-default-ssl-backend so it can be validated below
|
||||
dnl -------------------------------------------------------------
|
||||
|
@ -74,6 +74,8 @@ B) The request was HTTP and included digest details, which adds 1000 to NUM
|
||||
C) If a HTTP request is NTLM type-1, it adds 1001 to num
|
||||
D) If a HTTP request is NTLM type-3, it adds 1002 to num
|
||||
E) If a HTTP request is Basic and num is already >=1000, it adds 1 to num
|
||||
F) If a HTTP request is Negotiate, num gets incremented by one for each
|
||||
request with Negotiate authorization header on the same test case.
|
||||
|
||||
Dynamically changing num in this way allows the test harness to be used to
|
||||
test authentication negotiation where several different requests must be sent
|
||||
@ -243,6 +245,7 @@ threaded-resolver
|
||||
unittest
|
||||
unix-sockets
|
||||
WinSSL
|
||||
ld_preload
|
||||
|
||||
as well as each protocol that curl supports. A protocol only needs to be
|
||||
specified if it is different from the server (useful when the server
|
||||
|
@ -182,4 +182,5 @@ test2016 test2017 test2018 test2019 test2020 test2021 test2022 test2023 \
|
||||
test2024 test2025 test2026 test2027 test2028 test2029 test2030 test2031 \
|
||||
test2032 test2033 test2034 test2035 test2036 test2037 test2038 test2039 \
|
||||
test2040 test2041 test2042 test2043 test2044 test2045 test2046 test2047 \
|
||||
test2048 test2049 test2050 test2051 test2052 test2053 test2054 test2055
|
||||
test2048 test2049 test2050 test2051 test2052 test2053 test2054 test2055 \
|
||||
test2056 test2057
|
||||
|
87
tests/data/test2056
Normal file
87
tests/data/test2056
Normal file
@ -0,0 +1,87 @@
|
||||
<testcase>
|
||||
<info>
|
||||
<keywords>
|
||||
HTTP
|
||||
HTTP GET
|
||||
HTTP Negotiate auth (stub krb5)
|
||||
</keywords>
|
||||
</info>
|
||||
# Server-side
|
||||
<reply>
|
||||
<!-- First request, expect 401 Negotiate -->
|
||||
<data>
|
||||
HTTP/1.1 401 Authorization Required
|
||||
Server: Microsoft-IIS/7.0
|
||||
Content-Type: text/html; charset=iso-8859-1
|
||||
WWW-Authenticate: Negotiate
|
||||
Content-Length: 13
|
||||
|
||||
Not yet sir!
|
||||
</data>
|
||||
<!-- Second request, expect success in one shot -->
|
||||
<data1>
|
||||
HTTP/1.1 200 Things are fine in server land
|
||||
Server: Microsoft-IIS/7.0
|
||||
Content-Type: text/html; charset=iso-8859-1
|
||||
WWW-Authenticate: Negotiate RA==
|
||||
Content-Length: 15
|
||||
|
||||
Nice auth sir!
|
||||
</data1>
|
||||
<datacheck>
|
||||
HTTP/1.1 401 Authorization Required
|
||||
Server: Microsoft-IIS/7.0
|
||||
Content-Type: text/html; charset=iso-8859-1
|
||||
WWW-Authenticate: Negotiate
|
||||
Content-Length: 13
|
||||
|
||||
HTTP/1.1 200 Things are fine in server land
|
||||
Server: Microsoft-IIS/7.0
|
||||
Content-Type: text/html; charset=iso-8859-1
|
||||
WWW-Authenticate: Negotiate RA==
|
||||
Content-Length: 15
|
||||
|
||||
Nice auth sir!
|
||||
</datacheck>
|
||||
</reply>
|
||||
|
||||
# Client-side
|
||||
<client>
|
||||
<server>
|
||||
http
|
||||
</server>
|
||||
<name>
|
||||
HTTP Negotiate authentication (stub krb5)
|
||||
</name>
|
||||
<features>
|
||||
GSS-API
|
||||
ld_preload
|
||||
!debug
|
||||
</features>
|
||||
<setenv>
|
||||
LD_PRELOAD=%PWD/libtest/.libs/libstubgss.so
|
||||
CURL_STUB_GSS_CREDS="KRB5_Alice"
|
||||
</setenv>
|
||||
<command>
|
||||
-u: --negotiate http://%HOSTIP:%HTTPPORT/2056
|
||||
</command>
|
||||
</client>
|
||||
|
||||
# Verify data after the test has been "shot"
|
||||
<verify>
|
||||
<strip>
|
||||
^User-Agent:.*
|
||||
</strip>
|
||||
<protocol>
|
||||
GET /2056 HTTP/1.1
|
||||
Host: %HOSTIP:%HTTPPORT
|
||||
Accept: */*
|
||||
|
||||
GET /2056 HTTP/1.1
|
||||
Host: %HOSTIP:%HTTPPORT
|
||||
Authorization: Negotiate IktSQjVfQWxpY2UiOkhUVFBAMTI3LjAuMC4xOjE6QUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQQ==
|
||||
Accept: */*
|
||||
|
||||
</protocol>
|
||||
</verify>
|
||||
</testcase>
|
108
tests/data/test2057
Normal file
108
tests/data/test2057
Normal file
@ -0,0 +1,108 @@
|
||||
<testcase>
|
||||
<info>
|
||||
<keywords>
|
||||
HTTP
|
||||
HTTP GET
|
||||
HTTP Negotiate auth (stub ntlm)
|
||||
</keywords>
|
||||
</info>
|
||||
# Server-side
|
||||
<reply>
|
||||
<!-- First request, expect 401 Negotiate -->
|
||||
<data>
|
||||
HTTP/1.1 401 Authorization Required
|
||||
Server: Microsoft-IIS/7.0
|
||||
Content-Type: text/html; charset=iso-8859-1
|
||||
WWW-Authenticate: Negotiate
|
||||
Content-Length: 13
|
||||
|
||||
Not yet sir!
|
||||
</data>
|
||||
<!-- Second request, expect 401 (ntlm challenge) -->
|
||||
<data1>
|
||||
HTTP/1.1 401 Authorization Required
|
||||
Server: Microsoft-IIS/7.0
|
||||
Content-Type: text/html; charset=iso-8859-1
|
||||
WWW-Authenticate: Negotiate Qw==
|
||||
Content-Length: 19
|
||||
|
||||
Still not yet sir!
|
||||
</data1>
|
||||
<!-- Third request, expect success -->
|
||||
<data2>
|
||||
HTTP/1.1 200 Things are fine in server land
|
||||
Server: Microsoft-IIS/7.0
|
||||
Content-Type: text/html; charset=iso-8859-1
|
||||
WWW-Authenticate: Negotiate RA==
|
||||
Content-Length: 15
|
||||
|
||||
Nice auth sir!
|
||||
</data2>
|
||||
<datacheck>
|
||||
HTTP/1.1 401 Authorization Required
|
||||
Server: Microsoft-IIS/7.0
|
||||
Content-Type: text/html; charset=iso-8859-1
|
||||
WWW-Authenticate: Negotiate
|
||||
Content-Length: 13
|
||||
|
||||
HTTP/1.1 401 Authorization Required
|
||||
Server: Microsoft-IIS/7.0
|
||||
Content-Type: text/html; charset=iso-8859-1
|
||||
WWW-Authenticate: Negotiate Qw==
|
||||
Content-Length: 19
|
||||
|
||||
HTTP/1.1 200 Things are fine in server land
|
||||
Server: Microsoft-IIS/7.0
|
||||
Content-Type: text/html; charset=iso-8859-1
|
||||
WWW-Authenticate: Negotiate RA==
|
||||
Content-Length: 15
|
||||
|
||||
Nice auth sir!
|
||||
</datacheck>
|
||||
</reply>
|
||||
|
||||
# Client-side
|
||||
<client>
|
||||
<server>
|
||||
http
|
||||
</server>
|
||||
<name>
|
||||
HTTP Negotiate authentication (stub ntlm)
|
||||
</name>
|
||||
<features>
|
||||
GSS-API
|
||||
ld_preload
|
||||
!debug
|
||||
</features>
|
||||
<setenv>
|
||||
LD_PRELOAD=%PWD/libtest/.libs/libstubgss.so
|
||||
CURL_STUB_GSS_CREDS="NTLM_Alice"
|
||||
</setenv>
|
||||
<command>
|
||||
-u: --negotiate http://%HOSTIP:%HTTPPORT/2057
|
||||
</command>
|
||||
</client>
|
||||
|
||||
# Verify data after the test has been "shot"
|
||||
<verify>
|
||||
<strip>
|
||||
^User-Agent:.*
|
||||
</strip>
|
||||
<protocol>
|
||||
GET /2057 HTTP/1.1
|
||||
Host: %HOSTIP:%HTTPPORT
|
||||
Accept: */*
|
||||
|
||||
GET /2057 HTTP/1.1
|
||||
Host: %HOSTIP:%HTTPPORT
|
||||
Authorization: Negotiate Ik5UTE1fQWxpY2UiOkhUVFBAMTI3LjAuMC4xOjI6QUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQQ==
|
||||
Accept: */*
|
||||
|
||||
GET /2057 HTTP/1.1
|
||||
Host: %HOSTIP:%HTTPPORT
|
||||
Authorization: Negotiate Ik5UTE1fQWxpY2UiOkhUVFBAMTI3LjAuMC4xOjM6QUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQQ==
|
||||
Accept: */*
|
||||
|
||||
</protocol>
|
||||
</verify>
|
||||
</testcase>
|
@ -109,6 +109,21 @@ libhostname_la_SOURCES = sethostname.c sethostname.h
|
||||
libhostname_la_LIBADD =
|
||||
libhostname_la_DEPENDENCIES =
|
||||
|
||||
# Build a stub gssapi implementation for testing
|
||||
if BUILD_STUB_GSS
|
||||
noinst_LTLIBRARIES += libstubgss.la
|
||||
|
||||
libstubgss_la_CPPFLAGS = $(AM_CPPFLAGS)
|
||||
libstubgss_la_LDFLAGS = $(AM_LDFLAGS) -avoid-version -rpath /nowhere
|
||||
libstubgss_la_CFLAGS = $(AM_CFLAGS) -g -Wno-unused-parameter
|
||||
|
||||
libstubgss_la_SOURCES = stub_gssapi.c stub_gssapi.h
|
||||
|
||||
libstubgss_la_LIBADD =
|
||||
libstubgss_la_DEPENDENCIES =
|
||||
endif
|
||||
|
||||
|
||||
lib1521.c: $(top_srcdir)/tests/libtest/mk-lib1521.pl $(top_srcdir)/include/curl/curl.h
|
||||
@PERL@ $(top_srcdir)/tests/libtest/mk-lib1521.pl < $(top_srcdir)/include/curl/curl.h > lib1521.c
|
||||
|
||||
|
397
tests/libtest/stub_gssapi.c
Normal file
397
tests/libtest/stub_gssapi.c
Normal file
@ -0,0 +1,397 @@
|
||||
/***************************************************************************
|
||||
* _ _ ____ _
|
||||
* Project ___| | | | _ \| |
|
||||
* / __| | | | |_) | |
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 2017, 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
|
||||
* are also available at https://curl.haxx.se/docs/copyright.html.
|
||||
*
|
||||
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
|
||||
* copies of the Software, and permit persons to whom the Software is
|
||||
* furnished to do so, under the terms of the COPYING file.
|
||||
*
|
||||
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
|
||||
* KIND, either express or implied.
|
||||
*
|
||||
***************************************************************************/
|
||||
|
||||
/* Only provides the bare minimum to link with libcurl */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "stub_gssapi.h"
|
||||
|
||||
#define MAX_CREDS_LENGTH 250
|
||||
#define APPROX_TOKEN_LEN 250
|
||||
|
||||
enum min_err_code {
|
||||
GSS_OK = 0,
|
||||
GSS_NO_MEMORY,
|
||||
GSS_INVALID_ARGS,
|
||||
GSS_INVALID_CREDS,
|
||||
GSS_INVALID_CTX,
|
||||
GSS_SERVER_ERR,
|
||||
GSS_NO_MECH,
|
||||
GSS_LAST
|
||||
};
|
||||
|
||||
const char *min_err_table[] = {
|
||||
"stub-gss: no error",
|
||||
"stub-gss: no memory",
|
||||
"stub-gss: invalid arguments",
|
||||
"stub-gss: invalid credentials",
|
||||
"stub-gss: invalid context",
|
||||
"stub-gss: server returned error",
|
||||
"stub-gss: cannot find a mechanism",
|
||||
NULL
|
||||
};
|
||||
|
||||
struct gss_ctx_id_t_desc_struct {
|
||||
enum { NONE, KRB5, NTLM1, NTLM3 } sent;
|
||||
int have_krb5;
|
||||
int have_ntlm;
|
||||
OM_uint32 flags;
|
||||
char creds[MAX_CREDS_LENGTH];
|
||||
};
|
||||
|
||||
OM_uint32 gss_init_sec_context(OM_uint32 *min,
|
||||
gss_const_cred_id_t initiator_cred_handle,
|
||||
gss_ctx_id_t *context_handle,
|
||||
gss_const_name_t target_name,
|
||||
const gss_OID mech_type,
|
||||
OM_uint32 req_flags,
|
||||
OM_uint32 time_req,
|
||||
const gss_channel_bindings_t input_chan_bindings,
|
||||
const gss_buffer_t input_token,
|
||||
gss_OID *actual_mech_type,
|
||||
gss_buffer_t output_token,
|
||||
OM_uint32 *ret_flags,
|
||||
OM_uint32 *time_rec)
|
||||
{
|
||||
/* The token will be encoded in base64 */
|
||||
int length = APPROX_TOKEN_LEN * 3 / 4;
|
||||
int used = 0;
|
||||
char *token = NULL;
|
||||
const char *creds = NULL;
|
||||
gss_ctx_id_t ctx = NULL;
|
||||
|
||||
if(!min)
|
||||
return GSS_S_FAILURE;
|
||||
|
||||
*min = 0;
|
||||
|
||||
if(!context_handle || !target_name || !output_token) {
|
||||
*min = GSS_INVALID_ARGS;
|
||||
return GSS_S_FAILURE;
|
||||
}
|
||||
|
||||
creds = getenv("CURL_STUB_GSS_CREDS");
|
||||
if(!creds || strlen(creds) >= MAX_CREDS_LENGTH) {
|
||||
*min = GSS_INVALID_CREDS;
|
||||
return GSS_S_FAILURE;
|
||||
}
|
||||
|
||||
ctx = *context_handle;
|
||||
if(ctx && strcmp(ctx->creds, creds)) {
|
||||
*min = GSS_INVALID_CREDS;
|
||||
return GSS_S_FAILURE;
|
||||
}
|
||||
|
||||
output_token->length = 0;
|
||||
output_token->value = NULL;
|
||||
|
||||
if(input_token && input_token->length) {
|
||||
if(!ctx) {
|
||||
*min = GSS_INVALID_CTX;
|
||||
return GSS_S_FAILURE;
|
||||
}
|
||||
|
||||
/* Server response, either D (RA==) or C (Qw==) */
|
||||
if(((char *) input_token->value)[0] == 'D') {
|
||||
/* Done */
|
||||
switch(ctx->sent) {
|
||||
case KRB5:
|
||||
case NTLM3:
|
||||
if(ret_flags)
|
||||
*ret_flags = ctx->flags;
|
||||
if(time_rec)
|
||||
*time_rec = GSS_C_INDEFINITE;
|
||||
return GSS_S_COMPLETE;
|
||||
default:
|
||||
*min = GSS_SERVER_ERR;
|
||||
return GSS_S_FAILURE;
|
||||
}
|
||||
}
|
||||
|
||||
if(((char *) input_token->value)[0] != 'C') {
|
||||
/* We only support Done or Continue */
|
||||
*min = GSS_SERVER_ERR;
|
||||
return GSS_S_FAILURE;
|
||||
}
|
||||
|
||||
/* Continue */
|
||||
switch(ctx->sent) {
|
||||
case KRB5:
|
||||
/* We sent KRB5 and it failed, let's try NTLM */
|
||||
if(ctx->have_ntlm) {
|
||||
ctx->sent = NTLM1;
|
||||
break;
|
||||
}
|
||||
else {
|
||||
*min = GSS_SERVER_ERR;
|
||||
return GSS_S_FAILURE;
|
||||
}
|
||||
case NTLM1:
|
||||
ctx->sent = NTLM3;
|
||||
break;
|
||||
default:
|
||||
*min = GSS_SERVER_ERR;
|
||||
return GSS_S_FAILURE;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if(ctx) {
|
||||
*min = GSS_INVALID_CTX;
|
||||
return GSS_S_FAILURE;
|
||||
}
|
||||
|
||||
ctx = (gss_ctx_id_t) calloc(sizeof(*ctx), 1);
|
||||
if(!ctx) {
|
||||
*min = GSS_NO_MEMORY;
|
||||
return GSS_S_FAILURE;
|
||||
}
|
||||
|
||||
if(strstr(creds, "KRB5"))
|
||||
ctx->have_krb5 = 1;
|
||||
|
||||
if(strstr(creds, "NTLM"))
|
||||
ctx->have_ntlm = 1;
|
||||
|
||||
if(ctx->have_krb5)
|
||||
ctx->sent = KRB5;
|
||||
else if(ctx->have_ntlm)
|
||||
ctx->sent = NTLM1;
|
||||
else {
|
||||
free(ctx);
|
||||
*min = GSS_NO_MECH;
|
||||
return GSS_S_FAILURE;
|
||||
}
|
||||
|
||||
strcpy(ctx->creds, creds);
|
||||
ctx->flags = req_flags;
|
||||
}
|
||||
|
||||
token = malloc(length);
|
||||
if(!token) {
|
||||
free(ctx);
|
||||
*min = GSS_NO_MEMORY;
|
||||
return GSS_S_FAILURE;
|
||||
}
|
||||
|
||||
/* Token format: creds:target:type:padding */
|
||||
used = snprintf(token, length, "%s:%s:%d:", creds,
|
||||
(char *) target_name, ctx->sent);
|
||||
|
||||
if(used >= length) {
|
||||
free(token);
|
||||
free(ctx);
|
||||
*min = GSS_NO_MEMORY;
|
||||
return GSS_S_FAILURE;
|
||||
}
|
||||
|
||||
/* Overwrite null terminator */
|
||||
memset(token + used, 'A', length - used);
|
||||
|
||||
*context_handle = ctx;
|
||||
|
||||
output_token->value = token;
|
||||
output_token->length = length;
|
||||
|
||||
return GSS_S_CONTINUE_NEEDED;
|
||||
}
|
||||
|
||||
OM_uint32 gss_delete_sec_context(OM_uint32 *min,
|
||||
gss_ctx_id_t *context_handle,
|
||||
gss_buffer_t output_token)
|
||||
{
|
||||
if(!min)
|
||||
return GSS_S_FAILURE;
|
||||
|
||||
if(!context_handle) {
|
||||
*min = GSS_INVALID_CTX;
|
||||
return GSS_S_FAILURE;
|
||||
}
|
||||
|
||||
free(*context_handle);
|
||||
*context_handle = NULL;
|
||||
*min = 0;
|
||||
|
||||
return GSS_S_COMPLETE;
|
||||
}
|
||||
|
||||
OM_uint32 gss_release_buffer(OM_uint32 *min,
|
||||
gss_buffer_t buffer)
|
||||
{
|
||||
if(min)
|
||||
*min = 0;
|
||||
|
||||
if(buffer && buffer->length) {
|
||||
free(buffer->value);
|
||||
buffer->length = 0;
|
||||
}
|
||||
|
||||
return GSS_S_COMPLETE;
|
||||
}
|
||||
|
||||
OM_uint32 gss_import_name(OM_uint32 *min,
|
||||
const gss_buffer_t input_name_buffer,
|
||||
const gss_OID input_name_type,
|
||||
gss_name_t *output_name)
|
||||
{
|
||||
char *name = NULL;
|
||||
|
||||
if(!min)
|
||||
return GSS_S_FAILURE;
|
||||
|
||||
if(!input_name_buffer || !output_name) {
|
||||
*min = GSS_INVALID_ARGS;
|
||||
return GSS_S_FAILURE;
|
||||
}
|
||||
|
||||
name = strndup(input_name_buffer->value, input_name_buffer->length);
|
||||
if(!name) {
|
||||
*min = GSS_NO_MEMORY;
|
||||
return GSS_S_FAILURE;
|
||||
}
|
||||
|
||||
*output_name = (gss_name_t) name;
|
||||
*min = 0;
|
||||
|
||||
return GSS_S_COMPLETE;
|
||||
}
|
||||
|
||||
OM_uint32 gss_release_name(OM_uint32 *min,
|
||||
gss_name_t *input_name)
|
||||
{
|
||||
if(min)
|
||||
*min = 0;
|
||||
|
||||
if(input_name)
|
||||
free(*input_name);
|
||||
|
||||
return GSS_S_COMPLETE;
|
||||
}
|
||||
|
||||
OM_uint32 gss_display_status(OM_uint32 *min,
|
||||
OM_uint32 status_value,
|
||||
int status_type,
|
||||
const gss_OID mech_type,
|
||||
OM_uint32 *message_context,
|
||||
gss_buffer_t status_string)
|
||||
{
|
||||
const char maj_str[] = "Stub GSS error";
|
||||
if(min)
|
||||
*min = 0;
|
||||
|
||||
if(message_context)
|
||||
*message_context = 0;
|
||||
|
||||
if(status_string) {
|
||||
status_string->value = NULL;
|
||||
status_string->length = 0;
|
||||
|
||||
if(status_value >= GSS_LAST)
|
||||
return GSS_S_FAILURE;
|
||||
|
||||
switch(status_type) {
|
||||
case GSS_C_GSS_CODE:
|
||||
status_string->value = strdup(maj_str);
|
||||
break;
|
||||
case GSS_C_MECH_CODE:
|
||||
status_string->value = strdup(min_err_table[status_value]);
|
||||
break;
|
||||
default:
|
||||
return GSS_S_FAILURE;
|
||||
}
|
||||
|
||||
if(status_string->value)
|
||||
status_string->length = strlen(status_string->value);
|
||||
else
|
||||
return GSS_S_FAILURE;
|
||||
}
|
||||
|
||||
return GSS_S_COMPLETE;
|
||||
}
|
||||
|
||||
/* Stubs returning error */
|
||||
|
||||
OM_uint32 gss_display_name(OM_uint32 *min,
|
||||
gss_const_name_t input_name,
|
||||
gss_buffer_t output_name_buffer,
|
||||
gss_OID *output_name_type)
|
||||
{
|
||||
return GSS_S_FAILURE;
|
||||
}
|
||||
|
||||
OM_uint32 gss_inquire_context(OM_uint32 *min,
|
||||
gss_const_ctx_id_t context_handle,
|
||||
gss_name_t *src_name,
|
||||
gss_name_t *targ_name,
|
||||
OM_uint32 *lifetime_rec,
|
||||
gss_OID *mech_type,
|
||||
OM_uint32 *ctx_flags,
|
||||
int *locally_initiated,
|
||||
int *open_context)
|
||||
{
|
||||
return GSS_S_FAILURE;
|
||||
}
|
||||
|
||||
OM_uint32 gss_wrap(OM_uint32 *min,
|
||||
gss_const_ctx_id_t context_handle,
|
||||
int conf_req_flag,
|
||||
gss_qop_t qop_req,
|
||||
const gss_buffer_t input_message_buffer,
|
||||
int *conf_state,
|
||||
gss_buffer_t output_message_buffer)
|
||||
{
|
||||
return GSS_S_FAILURE;
|
||||
}
|
||||
|
||||
OM_uint32 gss_unwrap(OM_uint32 *min,
|
||||
gss_const_ctx_id_t context_handle,
|
||||
const gss_buffer_t input_message_buffer,
|
||||
gss_buffer_t output_message_buffer,
|
||||
int *conf_state,
|
||||
gss_qop_t *qop_state)
|
||||
{
|
||||
return GSS_S_FAILURE;
|
||||
}
|
||||
|
||||
OM_uint32 gss_seal(OM_uint32 *min,
|
||||
gss_ctx_id_t context_handle,
|
||||
int conf_req_flag,
|
||||
int qop_req,
|
||||
gss_buffer_t input_message_buffer,
|
||||
int *conf_state,
|
||||
gss_buffer_t output_message_buffer)
|
||||
{
|
||||
return GSS_S_FAILURE;
|
||||
}
|
||||
|
||||
OM_uint32 gss_unseal(OM_uint32 *min,
|
||||
gss_ctx_id_t context_handle,
|
||||
gss_buffer_t input_message_buffer,
|
||||
gss_buffer_t output_message_buffer,
|
||||
int *conf_state,
|
||||
int *qop_state)
|
||||
{
|
||||
return GSS_S_FAILURE;
|
||||
}
|
||||
|
183
tests/libtest/stub_gssapi.h
Normal file
183
tests/libtest/stub_gssapi.h
Normal file
@ -0,0 +1,183 @@
|
||||
#ifndef HEADER_CURL_GSSAPI_STUBS_H
|
||||
#define HEADER_CURL_GSSAPI_STUBS_H
|
||||
/***************************************************************************
|
||||
* _ _ ____ _
|
||||
* Project ___| | | | _ \| |
|
||||
* / __| | | | |_) | |
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 2017, 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
|
||||
* are also available at https://curl.haxx.se/docs/copyright.html.
|
||||
*
|
||||
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
|
||||
* copies of the Software, and permit persons to whom the Software is
|
||||
* furnished to do so, under the terms of the COPYING file.
|
||||
*
|
||||
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
|
||||
* KIND, either express or implied.
|
||||
*
|
||||
***************************************************************************/
|
||||
|
||||
/* Roughly based on Heimdal's gssapi.h */
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
|
||||
#define GSS_ERROR(status) (status & 0x80000000)
|
||||
|
||||
#define GSS_S_COMPLETE 0
|
||||
#define GSS_S_FAILURE (0x80000000)
|
||||
#define GSS_S_CONTINUE_NEEDED (1ul)
|
||||
|
||||
#define GSS_C_QOP_DEFAULT 0
|
||||
#define GSS_C_NO_OID ((gss_OID) 0)
|
||||
#define GSS_C_NO_NAME ((gss_name_t) 0)
|
||||
#define GSS_C_NO_BUFFER ((gss_buffer_t) 0)
|
||||
#define GSS_C_NO_CONTEXT ((gss_ctx_id_t) 0)
|
||||
#define GSS_C_NO_CREDENTIAL ((gss_cred_id_t) 0)
|
||||
#define GSS_C_NO_CHANNEL_BINDINGS ((gss_channel_bindings_t) 0)
|
||||
|
||||
#define GSS_C_NULL_OID GSS_C_NO_OID
|
||||
|
||||
#define GSS_C_EMPTY_BUFFER {0, NULL}
|
||||
|
||||
#define GSS_C_AF_INET 2
|
||||
|
||||
#define GSS_C_GSS_CODE 1
|
||||
#define GSS_C_MECH_CODE 2
|
||||
|
||||
#define GSS_C_DELEG_FLAG 1
|
||||
#define GSS_C_MUTUAL_FLAG 2
|
||||
#define GSS_C_REPLAY_FLAG 4
|
||||
#define GSS_C_CONF_FLAG 16
|
||||
#define GSS_C_INTEG_FLAG 32
|
||||
|
||||
/*
|
||||
* Expiration time of 2^32-1 seconds means infinite lifetime for a
|
||||
* credential or security context
|
||||
*/
|
||||
#define GSS_C_INDEFINITE 0xfffffffful
|
||||
|
||||
#define GSS_C_NT_HOSTBASED_SERVICE NULL
|
||||
|
||||
typedef uint32_t OM_uint32;
|
||||
|
||||
typedef OM_uint32 gss_qop_t;
|
||||
|
||||
typedef struct gss_buffer_desc_struct {
|
||||
size_t length;
|
||||
void *value;
|
||||
} gss_buffer_desc, *gss_buffer_t;
|
||||
|
||||
struct gss_cred_id_t_desc_struct;
|
||||
typedef struct gss_cred_id_t_desc_struct *gss_cred_id_t;
|
||||
typedef const struct gss_cred_id_t_desc_struct *gss_const_cred_id_t;
|
||||
|
||||
struct gss_ctx_id_t_desc_struct;
|
||||
typedef struct gss_ctx_id_t_desc_struct *gss_ctx_id_t;
|
||||
typedef const struct gss_ctx_id_t_desc_struct *gss_const_ctx_id_t;
|
||||
|
||||
struct gss_name_t_desc_struct;
|
||||
typedef struct gss_name_t_desc_struct *gss_name_t;
|
||||
typedef const struct gss_name_t_desc_struct *gss_const_name_t;
|
||||
|
||||
typedef struct gss_OID_desc_struct {
|
||||
OM_uint32 length;
|
||||
void *elements;
|
||||
} gss_OID_desc, *gss_OID;
|
||||
|
||||
typedef struct gss_channel_bindings_struct {
|
||||
OM_uint32 initiator_addrtype;
|
||||
gss_buffer_desc initiator_address;
|
||||
OM_uint32 acceptor_addrtype;
|
||||
gss_buffer_desc acceptor_address;
|
||||
gss_buffer_desc application_data;
|
||||
} *gss_channel_bindings_t;
|
||||
|
||||
OM_uint32 gss_release_buffer(OM_uint32 * /*minor_status*/,
|
||||
gss_buffer_t /*buffer*/);
|
||||
|
||||
OM_uint32 gss_init_sec_context(OM_uint32 * /*minor_status*/,
|
||||
gss_const_cred_id_t /*initiator_cred_handle*/,
|
||||
gss_ctx_id_t * /*context_handle*/,
|
||||
gss_const_name_t /*target_name*/,
|
||||
const gss_OID /*mech_type*/,
|
||||
OM_uint32 /*req_flags*/,
|
||||
OM_uint32 /*time_req*/,
|
||||
const gss_channel_bindings_t /*input_chan_bindings*/,
|
||||
const gss_buffer_t /*input_token*/,
|
||||
gss_OID * /*actual_mech_type*/,
|
||||
gss_buffer_t /*output_token*/,
|
||||
OM_uint32 * /*ret_flags*/,
|
||||
OM_uint32 * /*time_rec*/);
|
||||
|
||||
OM_uint32 gss_delete_sec_context(OM_uint32 * /*minor_status*/,
|
||||
gss_ctx_id_t * /*context_handle*/,
|
||||
gss_buffer_t /*output_token*/);
|
||||
|
||||
OM_uint32 gss_inquire_context(OM_uint32 * /*minor_status*/,
|
||||
gss_const_ctx_id_t /*context_handle*/,
|
||||
gss_name_t * /*src_name*/,
|
||||
gss_name_t * /*targ_name*/,
|
||||
OM_uint32 * /*lifetime_rec*/,
|
||||
gss_OID * /*mech_type*/,
|
||||
OM_uint32 * /*ctx_flags*/,
|
||||
int * /*locally_initiated*/,
|
||||
int * /*open_context*/);
|
||||
|
||||
OM_uint32 gss_wrap(OM_uint32 * /*minor_status*/,
|
||||
gss_const_ctx_id_t /*context_handle*/,
|
||||
int /*conf_req_flag*/,
|
||||
gss_qop_t /*qop_req*/,
|
||||
const gss_buffer_t /*input_message_buffer*/,
|
||||
int * /*conf_state*/,
|
||||
gss_buffer_t /*output_message_buffer*/);
|
||||
|
||||
OM_uint32 gss_unwrap(OM_uint32 * /*minor_status*/,
|
||||
gss_const_ctx_id_t /*context_handle*/,
|
||||
const gss_buffer_t /*input_message_buffer*/,
|
||||
gss_buffer_t /*output_message_buffer*/,
|
||||
int * /*conf_state*/,
|
||||
gss_qop_t * /*qop_state*/);
|
||||
|
||||
OM_uint32 gss_seal(OM_uint32 * /*minor_status*/,
|
||||
gss_ctx_id_t /*context_handle*/,
|
||||
int /*conf_req_flag*/,
|
||||
int /*qop_req*/,
|
||||
gss_buffer_t /*input_message_buffer*/,
|
||||
int * /*conf_state*/,
|
||||
gss_buffer_t /*output_message_buffer*/);
|
||||
|
||||
OM_uint32 gss_unseal(OM_uint32 * /*minor_status*/,
|
||||
gss_ctx_id_t /*context_handle*/,
|
||||
gss_buffer_t /*input_message_buffer*/,
|
||||
gss_buffer_t /*output_message_buffer*/,
|
||||
int * /*conf_state*/,
|
||||
int * /*qop_state*/);
|
||||
|
||||
OM_uint32 gss_import_name(OM_uint32 * /*minor_status*/,
|
||||
const gss_buffer_t /*input_name_buffer*/,
|
||||
const gss_OID /*input_name_type*/,
|
||||
gss_name_t * /*output_name*/);
|
||||
|
||||
OM_uint32 gss_release_name(OM_uint32 * /*minor_status*/,
|
||||
gss_name_t * /*input_name*/);
|
||||
|
||||
OM_uint32 gss_display_name(OM_uint32 * /*minor_status*/,
|
||||
gss_const_name_t /*input_name*/,
|
||||
gss_buffer_t /*output_name_buffer*/,
|
||||
gss_OID * /*output_name_type*/);
|
||||
|
||||
OM_uint32 gss_display_status(OM_uint32 * /*minor_status*/,
|
||||
OM_uint32 /*status_value*/,
|
||||
int /*status_type*/,
|
||||
const gss_OID /*mech_type*/,
|
||||
OM_uint32 * /*message_context*/,
|
||||
gss_buffer_t /*status_string*/);
|
||||
|
||||
#endif /* HEADER_CURL_GSSAPI_STUBS_H */
|
||||
|
@ -232,6 +232,7 @@ my $has_crypto; # set if libcurl is built with cryptographic support
|
||||
my $has_cares; # set if built with c-ares
|
||||
my $has_threadedres;# set if built with threaded resolver
|
||||
my $has_psl; # set if libcurl is built with PSL support
|
||||
my $has_ldpreload; # set if curl is built for systems supporting LD_PRELOAD
|
||||
|
||||
# this version is decided by the particular nghttp2 library that is being used
|
||||
my $h2cver = "h2c";
|
||||
@ -2731,6 +2732,9 @@ sub checksystem {
|
||||
$curl =~ s/^(.*)(libcurl.*)/$1/g;
|
||||
|
||||
$libcurl = $2;
|
||||
if($curl =~ /linux|bsd|solaris|darwin/) {
|
||||
$has_ldpreload = 1;
|
||||
}
|
||||
if($curl =~ /win32|mingw(32|64)/) {
|
||||
# This is a Windows MinGW build or native build, we need to use
|
||||
# Win32-style path.
|
||||
@ -3315,6 +3319,11 @@ sub singletest {
|
||||
next;
|
||||
}
|
||||
}
|
||||
elsif($1 eq "ld_preload") {
|
||||
if($has_ldpreload && !$debug_build) {
|
||||
next;
|
||||
}
|
||||
}
|
||||
elsif($1 eq "unittest") {
|
||||
if($debug_build) {
|
||||
next;
|
||||
|
@ -763,7 +763,20 @@ static int ProcessRequest(struct httprequest *req)
|
||||
logmsg("Authorization header found, as required");
|
||||
}
|
||||
|
||||
if(!req->digest && strstr(req->reqbuf, "Authorization: Digest")) {
|
||||
if(strstr(req->reqbuf, "Authorization: Negotiate")) {
|
||||
/* Negotiate iterations */
|
||||
static long prev_testno = -1;
|
||||
static long prev_partno = -1;
|
||||
logmsg("Negotiate: prev_testno: %d, prev_partno: %d",
|
||||
prev_testno, prev_partno);
|
||||
if(req->testno != prev_testno) {
|
||||
prev_testno = req->testno;
|
||||
prev_partno = req->partno;
|
||||
}
|
||||
prev_partno += 1;
|
||||
req->partno = prev_partno;
|
||||
}
|
||||
else if(!req->digest && strstr(req->reqbuf, "Authorization: Digest")) {
|
||||
/* If the client is passing this Digest-header, we set the part number
|
||||
to 1000. Not only to spice up the complexity of this, but to make
|
||||
Digest stuff to work in the test suite. */
|
||||
|
Loading…
Reference in New Issue
Block a user