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:
Isaac Boukris 2017-07-18 21:46:21 +03:00 committed by Marcel Raad
parent 65872efea7
commit 56d949d31a
No known key found for this signature in database
GPG Key ID: 33C416EFAE4D6F02
10 changed files with 825 additions and 2 deletions

View File

@ -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 -------------------------------------------------------------

View File

@ -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

View File

@ -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
View 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
View 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>

View File

@ -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
View 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
View 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 */

View File

@ -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;

View File

@ -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. */