From 09ccfcdcd422fc0b0421562bbdcf53f78a3f3e4b Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Fri, 19 Sep 2003 12:56:22 +0000 Subject: Markus Moeller's SPNEGO patch applied, with my edits, additions and minor cleanups. --- CHANGES | 7 +++ configure.ac | 32 +++++++++++++- docs/libcurl/curl_version_info.3 | 6 ++- include/curl/curl.h | 1 + lib/http.c | 4 +- lib/http_negotiate.c | 92 ++++++++++++++++++++++++++++++++++++++-- lib/http_negotiate.h | 2 +- lib/url.c | 4 +- lib/urldata.h | 11 +++-- lib/version.c | 7 ++- 10 files changed, 150 insertions(+), 16 deletions(-) diff --git a/CHANGES b/CHANGES index c89dc7b6f..f35d2a1f4 100644 --- a/CHANGES +++ b/CHANGES @@ -6,6 +6,13 @@ Changelog + +Daniel (19 September) +- Applied Markus Moeller's patch that introduces SPNEGO support if libcurl + is built with the FBopenssl libraries. curl_version_info() now returns + info on SPNEGO availability. The patch also made the GSSAPI stuff work fine + with the MIT GSS-library (the Heimdal one still works too). + Daniel (16 September) - Doing PUT with --digest failed, as reported in bug report #805853. diff --git a/configure.ac b/configure.ac index 09576a5e7..7f0423011 100644 --- a/configure.ac +++ b/configure.ac @@ -457,6 +457,31 @@ else AC_MSG_RESULT(no) fi +dnl ********************************************************************** +dnl Check for FBopenssl(SPNEGO) libraries +dnl ********************************************************************** + +AC_ARG_WITH(spnego, + AC_HELP_STRING([--with-spnego=DIR], + [Specify location of SPNEGO library fbopenssl]), + [ SPNEGO_ROOT="$withval" + want_spnego="yes" ] +) +AC_MSG_CHECKING([if SPNEGO support is requested]) +if test x"$want_spnego" = xyes; then + + if test -z "$SPNEGO_LIB_DIR"; then + LDFLAGS="$LDFLAGS -L$SPNEGO_ROOT $(wl)-R$SPNEGO_ROOT -lfbopenssl" + else + LDFLAGS="$LDFLAGS $SPNEGO_LIB_DIR" + fi + + AC_DEFINE(HAVE_SPNEGO, 1, [Define this if you have the SPNEGO library fbopenssl]) + AC_MSG_RESULT(yes) +else + AC_MSG_RESULT(no) +fi + dnl ********************************************************************** dnl Check for GSS-API libraries dnl ********************************************************************** @@ -507,7 +532,12 @@ if test x"$want_gss" = xyes; then fi AC_MSG_RESULT(yes) - AC_DEFINE(GSSAPI, 1, [if you have the gssapi libraries]) + AC_DEFINE(HAVE_GSSAPI, 1, [if you have the gssapi libraries]) + if test -f "$GSSAPI_INCS/gssapi.h"; then + AC_DEFINE(HAVE_GSSHEIMDAL, 1, [if you have the Heimdal gssapi libraries]) + else + AC_DEFINE(HAVE_GSSMIT, 1, [if you have the MIT gssapi libraries]) + fi else AC_MSG_RESULT(no) diff --git a/docs/libcurl/curl_version_info.3 b/docs/libcurl/curl_version_info.3 index 15bcb7b42..ed1327b21 100644 --- a/docs/libcurl/curl_version_info.3 +++ b/docs/libcurl/curl_version_info.3 @@ -2,7 +2,7 @@ .\" nroff -man [file] .\" $Id$ .\" -.TH curl_version_info 3 "12 Aug 2003" "libcurl 7.10.7" "libcurl Manual" +.TH curl_version_info 3 "19 Sep 2003" "libcurl 7.10.8" "libcurl Manual" .SH NAME curl_version_info - returns run-time libcurl version info .SH SYNOPSIS @@ -84,6 +84,10 @@ interest for libcurl hackers. (added in 7.10.6) libcurl was built with support for asynchronous name lookups, which allows more exact timeouts (even on Windows) and less blocking when using the multi interface. (added in 7.10.7) +.TP +.B CURL_VERSION_SPNEGO +libcurl was built with support for SPNEGO authentication (Simple and Protected +GSS-API Negotiation Mechanism, defined in RFC 2478.) (added in 7.10.8) .PP \fIssl_version\fP is an ascii string for the OpenSSL version used. If libcurl has no SSL support, this is NULL. diff --git a/include/curl/curl.h b/include/curl/curl.h index 117fb6720..f78d8a84d 100644 --- a/include/curl/curl.h +++ b/include/curl/curl.h @@ -1134,6 +1134,7 @@ typedef struct { #define CURL_VERSION_GSSNEGOTIATE (1<<5) #define CURL_VERSION_DEBUG (1<<6) /* built with debug capabilities */ #define CURL_VERSION_ASYNCHDNS (1<<7) +#define CURL_VERSION_SPNEGO (1<<8) /* * NAME curl_version_info() diff --git a/lib/http.c b/lib/http.c index 8cb97dd1d..5195122a8 100644 --- a/lib/http.c +++ b/lib/http.c @@ -238,7 +238,7 @@ CURLcode http_auth_headers(struct connectdata *conn, } /* Send web authentication header if needed */ if (data->state.authstage == 401) { -#ifdef GSSAPI +#ifdef HAVE_GSSAPI if((data->state.authwant == CURLAUTH_GSSNEGOTIATE) && data->state.negotiate.context && !GSS_ERROR(data->state.negotiate.status)) { @@ -324,7 +324,7 @@ CURLcode Curl_http_auth(struct connectdata *conn, while(*start && isspace((int)*start)) start++; -#ifdef GSSAPI +#ifdef HAVE_GSSAPI if (checkprefix("GSS-Negotiate", start) || checkprefix("Negotiate", start)) { *availp |= CURLAUTH_GSSNEGOTIATE; diff --git a/lib/http_negotiate.c b/lib/http_negotiate.c index 5012b0764..fcbb3eadb 100644 --- a/lib/http_negotiate.c +++ b/lib/http_negotiate.c @@ -22,7 +22,10 @@ ***************************************************************************/ #include "setup.h" -#ifdef GSSAPI +#ifdef HAVE_GSSAPI +#ifdef HAVE_GSSMIT +#define GSS_C_NT_HOSTBASED_SERVICE gss_nt_service_name +#endif #ifndef CURL_DISABLE_HTTP /* -- WIN32 approved -- */ @@ -171,6 +174,46 @@ int Curl_input_negotiate(struct connectdata *conn, char *header) if (rawlen < 0) return -1; input_token.length = rawlen; + +#ifdef SPNEGO /* Handle SPNEGO */ + if (checkprefix("Negotiate", header)) { + ASN1_OBJECT * object = NULL; + int rc = 1; + unsigned char * spnegoToken = NULL; + size_t spnegoTokenLength = 0; + unsigned char * mechToken = NULL; + size_t mechTokenLength = 0; + + spnegoToken = malloc(input_token.length); + if (input_token.value == NULL) + return ENOMEM; + spnegoTokenLength = input_token.length; + + object = OBJ_txt2obj ("1.2.840.113554.1.2.2", 1); + if (!parseSpnegoTargetToken(spnegoToken, + spnegoTokenLength, + NULL, + NULL, + &mechToken, + &mechTokenLength, + NULL, + NULL)) { + free(spnegoToken); + spnegoToken = NULL; + infof(conn->data, "Parse SPNEGO Target Token failed\n"); + } + else { + free(input_token.value); + input_token.value = NULL; + input_token.value = malloc(mechTokenLength); + memcpy(input_token.value, mechToken,mechTokenLength); + input_token.length = mechTokenLength; + free(mechToken); + mechToken = NULL; + infof(conn->data, "Parse SPNEGO Target Token succeded\n"); + } + } +#endif } major_status = gss_init_sec_context(&minor_status, @@ -212,9 +255,50 @@ CURLcode Curl_output_negotiate(struct connectdata *conn) struct negotiatedata *neg_ctx = &conn->data->state.negotiate; OM_uint32 minor_status; char *encoded = NULL; - int len = Curl_base64_encode(neg_ctx->output_token.value, - neg_ctx->output_token.length, - &encoded); + int len; + +#ifdef SPNEGO /* Handle SPNEGO */ + if (checkprefix("Negotiate",neg_ctx->protocol)) { + ASN1_OBJECT * object = NULL; + int rc = 1; + unsigned char * spnegoToken = NULL; + size_t spnegoTokenLength = 0; + unsigned char * responseToken = NULL; + size_t responseTokenLength = 0; + + responseToken = malloc(neg_ctx->output_token.length); + if ( responseToken == NULL) + return CURLE_OUT_OF_MEMORY; + memcpy(responseToken, neg_ctx->output_token.value, + neg_ctx->output_token.length); + responseTokenLength = neg_ctx->output_token.length; + + object=OBJ_txt2obj ("1.2.840.113554.1.2.2", 1); + if (!makeSpnegoInitialToken (object, + responseToken, + responseTokenLength, + &spnegoToken, + &spnegoTokenLength)) { + free(responseToken); + responseToken = NULL; + infof(conn->data, "Make SPNEGO Initial Token failed\n"); + } + else { + free(neg_ctx->output_token.value); + responseToken = NULL; + neg_ctx->output_token.value = malloc(spnegoTokenLength); + memcpy(neg_ctx->output_token.value, spnegoToken,spnegoTokenLength); + neg_ctx->output_token.length = spnegoTokenLength; + free(spnegoToken); + spnegoToken = NULL; + infof(conn->data, "Make SPNEGO Initial Token succeded\n"); + } + } +#endif + len = Curl_base64_encode(neg_ctx->output_token.value, + neg_ctx->output_token.length, + &encoded); + if (len < 0) return CURLE_OUT_OF_MEMORY; diff --git a/lib/http_negotiate.h b/lib/http_negotiate.h index 36a346c56..f58f45560 100644 --- a/lib/http_negotiate.h +++ b/lib/http_negotiate.h @@ -24,7 +24,7 @@ * $Id$ ***************************************************************************/ -#ifdef GSSAPI +#ifdef HAVE_GSSAPI /* this is for Negotiate header input */ int Curl_input_negotiate(struct connectdata *conn, char *header); diff --git a/lib/url.c b/lib/url.c index a1f474d4d..12abbb2c5 100644 --- a/lib/url.c +++ b/lib/url.c @@ -879,7 +879,7 @@ CURLcode Curl_setopt(struct SessionHandle *data, CURLoption option, ...) #ifndef USE_SSLEAY auth &= ~CURLAUTH_NTLM; /* no NTLM without SSL */ #endif -#ifndef GSSAPI +#ifndef HAVE_GSSAPI auth &= ~CURLAUTH_GSSNEGOTIATE; /* no GSS-Negotiate without GSSAPI */ #endif if(!auth) @@ -899,7 +899,7 @@ CURLcode Curl_setopt(struct SessionHandle *data, CURLoption option, ...) #ifndef USE_SSLEAY auth &= ~CURLAUTH_NTLM; /* no NTLM without SSL */ #endif -#ifndef GSSAPI +#ifndef HAVE_GSSAPI auth &= ~CURLAUTH_GSSNEGOTIATE; /* no GSS-Negotiate without GSSAPI */ #endif if(!auth) diff --git a/lib/urldata.h b/lib/urldata.h index 6d89bf736..16c413d61 100644 --- a/lib/urldata.h +++ b/lib/urldata.h @@ -86,9 +86,14 @@ #include /* for content-encoding */ #endif -#ifdef GSSAPI +#ifdef HAVE_GSSAPI +#ifdef HAVE_GSSMIT +#include +#include +#else #include #endif +#endif #ifdef USE_ARES #include @@ -184,7 +189,7 @@ struct ntlmdata { unsigned char nonce[8]; }; -#ifdef GSSAPI +#ifdef HAVE_GSSAPI struct negotiatedata { bool gss; /* Whether we're processing GSS-Negotiate or Negotiate */ const char* protocol; /* "GSS-Negotiate" or "Negotiate" */ @@ -688,7 +693,7 @@ struct UrlState { struct digestdata digest; -#ifdef GSSAPI +#ifdef HAVE_GSSAPI struct negotiatedata negotiate; #endif diff --git a/lib/version.c b/lib/version.c index 651f895e1..3e8c88513 100644 --- a/lib/version.c +++ b/lib/version.c @@ -114,7 +114,7 @@ char *curl_version(void) sprintf(ptr, " zlib/%s", zlibVersion()); ptr += strlen(ptr); #endif -#ifdef GSSAPI +#ifdef HAVE_GSSAPI sprintf(ptr, " GSS"); ptr += strlen(ptr); #endif @@ -177,7 +177,7 @@ static curl_version_info_data version_info = { #ifdef HAVE_LIBZ | CURL_VERSION_LIBZ #endif -#ifdef GSSAPI +#ifdef HAVE_GSSAPI | CURL_VERSION_GSSNEGOTIATE #endif #ifdef CURLDEBUG @@ -185,6 +185,9 @@ static curl_version_info_data version_info = { #endif #ifdef USE_ARES | CURL_VERSION_ASYNCHDNS +#endif +#ifdef HAVE_SPNEGO + | CURL_VERSION_SPNEGO #endif , NULL, /* ssl_version */ -- cgit v1.2.3