mirror of
https://github.com/moparisthebest/curl
synced 2024-12-22 08:08:50 -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"
|
CPPFLAGS="$save_CPPFLAGS"
|
||||||
fi
|
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 -------------------------------------------------------------
|
||||||
dnl parse --with-default-ssl-backend so it can be validated below
|
dnl parse --with-default-ssl-backend so it can be validated below
|
||||||
dnl -------------------------------------------------------------
|
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
|
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
|
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
|
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
|
Dynamically changing num in this way allows the test harness to be used to
|
||||||
test authentication negotiation where several different requests must be sent
|
test authentication negotiation where several different requests must be sent
|
||||||
@ -243,6 +245,7 @@ threaded-resolver
|
|||||||
unittest
|
unittest
|
||||||
unix-sockets
|
unix-sockets
|
||||||
WinSSL
|
WinSSL
|
||||||
|
ld_preload
|
||||||
|
|
||||||
as well as each protocol that curl supports. A protocol only needs to be
|
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
|
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 \
|
test2024 test2025 test2026 test2027 test2028 test2029 test2030 test2031 \
|
||||||
test2032 test2033 test2034 test2035 test2036 test2037 test2038 test2039 \
|
test2032 test2033 test2034 test2035 test2036 test2037 test2038 test2039 \
|
||||||
test2040 test2041 test2042 test2043 test2044 test2045 test2046 test2047 \
|
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_LIBADD =
|
||||||
libhostname_la_DEPENDENCIES =
|
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
|
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
|
@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_cares; # set if built with c-ares
|
||||||
my $has_threadedres;# set if built with threaded resolver
|
my $has_threadedres;# set if built with threaded resolver
|
||||||
my $has_psl; # set if libcurl is built with PSL support
|
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
|
# this version is decided by the particular nghttp2 library that is being used
|
||||||
my $h2cver = "h2c";
|
my $h2cver = "h2c";
|
||||||
@ -2731,6 +2732,9 @@ sub checksystem {
|
|||||||
$curl =~ s/^(.*)(libcurl.*)/$1/g;
|
$curl =~ s/^(.*)(libcurl.*)/$1/g;
|
||||||
|
|
||||||
$libcurl = $2;
|
$libcurl = $2;
|
||||||
|
if($curl =~ /linux|bsd|solaris|darwin/) {
|
||||||
|
$has_ldpreload = 1;
|
||||||
|
}
|
||||||
if($curl =~ /win32|mingw(32|64)/) {
|
if($curl =~ /win32|mingw(32|64)/) {
|
||||||
# This is a Windows MinGW build or native build, we need to use
|
# This is a Windows MinGW build or native build, we need to use
|
||||||
# Win32-style path.
|
# Win32-style path.
|
||||||
@ -3315,6 +3319,11 @@ sub singletest {
|
|||||||
next;
|
next;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
elsif($1 eq "ld_preload") {
|
||||||
|
if($has_ldpreload && !$debug_build) {
|
||||||
|
next;
|
||||||
|
}
|
||||||
|
}
|
||||||
elsif($1 eq "unittest") {
|
elsif($1 eq "unittest") {
|
||||||
if($debug_build) {
|
if($debug_build) {
|
||||||
next;
|
next;
|
||||||
|
@ -763,7 +763,20 @@ static int ProcessRequest(struct httprequest *req)
|
|||||||
logmsg("Authorization header found, as required");
|
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
|
/* 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
|
to 1000. Not only to spice up the complexity of this, but to make
|
||||||
Digest stuff to work in the test suite. */
|
Digest stuff to work in the test suite. */
|
||||||
|
Loading…
Reference in New Issue
Block a user