diff --git a/Makefile.config.in b/Makefile.config.in index 4ab2bf2a..8854477d 100644 --- a/Makefile.config.in +++ b/Makefile.config.in @@ -158,6 +158,7 @@ CONFIG_SYSMOUSE = @CONFIG_SYSMOUSE@ CONFIG_URI_REWRITE = @CONFIG_URI_REWRITE@ CONFIG_XBEL_BOOKMARKS = @CONFIG_XBEL_BOOKMARKS@ CONFIG_XMLTO = @CONFIG_XMLTO@ +CONFIG_GSSAPI = @CONFIG_GSSAPI@ DEFS = @DEFS@ CFLAGS = @CFLAGS@ diff --git a/configure.in b/configure.in index 024ebc31..ad2831d1 100644 --- a/configure.in +++ b/configure.in @@ -452,6 +452,30 @@ fi EL_ARG_ENABLE(CONFIG_LZMA, lzma, [lzma], [ --enable-lzma enable lzma encoding support]) +dnl =================================================================== +dnl Check for GSSAPI, optional even if installed. +dnl =================================================================== + +enable_gssapi="no"; + +AC_ARG_WITH(gssapi, [ --with-gssapi enable GSSAPI support], + [ if test "x$withval" != xno; then enable_gssapi=yes; fi ]) + +AC_MSG_CHECKING([for GSSAPI]) + +if test "$enable_gssapi" = "yes"; then + AC_MSG_RESULT(yes) + GSSAPI_CFLAGS=`krb5-config --cflags gssapi` + GSSAPI_LIBS=`krb5-config --libs gssapi` + CFLAGS="$GSSAPI_CFLAGS $CFLAGS" + LIBS="$GSSAPI_LIBS $LIBS" + EL_CONFIG(CONFIG_GSSAPI, [GssApi]) +else + AC_MSG_RESULT(no) +fi + +AC_SUBST(CONFIG_GSSAPI) + dnl =================================================================== dnl Bookmark and XBEL support dnl =================================================================== diff --git a/src/protocol/http/Makefile b/src/protocol/http/Makefile index 10ffb867..fb4dfa0f 100644 --- a/src/protocol/http/Makefile +++ b/src/protocol/http/Makefile @@ -1,6 +1,8 @@ top_builddir=../../.. include $(top_builddir)/Makefile.config +OBJS-$(CONFIG_GSSAPI) += http_negotiate.o + OBJS = blacklist.o codes.o http.o include $(top_srcdir)/Makefile.lib diff --git a/src/protocol/http/http.c b/src/protocol/http/http.c index d05a99d9..75df08fe 100644 --- a/src/protocol/http/http.c +++ b/src/protocol/http/http.c @@ -47,6 +47,9 @@ #include "util/memory.h" #include "util/string.h" +#ifdef CONFIG_GSSAPI +#include "http_negotiate.h" +#endif struct http_version { int major; @@ -549,7 +552,7 @@ http_send_header(struct socket *socket) int trace = get_opt_bool("protocol.http.trace"); struct string header; unsigned char *post_data = NULL; - struct auth_entry *entry; + struct auth_entry *entry = NULL; struct uri *uri = conn->proxied_uri; /* Set to the real uri */ unsigned char *optstr; int use_connect, talking_to_proxy; @@ -806,7 +809,11 @@ http_send_header(struct socket *socket) add_crlf_to_string(&header); } - entry = find_auth(uri); +#ifdef CONFIG_GSSAPI + if (http_negotiate_output(uri, &header) != 0) +#endif + entry = find_auth(uri); + if (entry) { if (entry->digest) { unsigned char *response; @@ -1325,12 +1332,13 @@ get_header(struct read_buffer *rb) return 0; } - -static void -check_http_authentication(struct uri *uri, unsigned char *header, - unsigned char *header_field) +/* returns 1 if we need retry the connection (for negotiate-auth only) */ +static int +check_http_authentication(struct connection *conn, struct uri *uri, + unsigned char *header, unsigned char *header_field) { unsigned char *str, *d; + int ret = 0; d = parse_header(header, header_field, &str); while (d) { @@ -1356,10 +1364,24 @@ check_http_authentication(struct uri *uri, unsigned char *header, mem_free(d); break; } - +#ifdef CONFIG_GSSAPI + else if (!strncasecmp(d, HTTPNEG_GSS_STR, HTTPNEG_GSS_STRLEN)) { + if (http_negotiate_input(conn, uri, HTTPNEG_GSS, str)==0) + ret = 1; + mem_free(d); + break; + } + else if (!strncasecmp(d, HTTPNEG_NEG_STR, HTTPNEG_NEG_STRLEN)) { + if (http_negotiate_input(conn, uri, HTTPNEG_NEG, str)==0) + ret = 1; + mem_free(d); + break; + } +#endif mem_free(d); d = parse_header(str, header_field, &str); } + return ret; } @@ -1586,11 +1608,13 @@ again: } if (h == 401) { - unsigned char *head = conn->cached->head; - - check_http_authentication(uri, head, "WWW-Authenticate"); + if (check_http_authentication(conn, uri, + conn->cached->head, "WWW-Authenticate")) { + retry_connection(conn, S_RESTART); + return; + } + } - if (h == 407) { unsigned char *str; diff --git a/src/util/base64.c b/src/util/base64.c index 8a3918ea..2c2e9ad8 100644 --- a/src/util/base64.c +++ b/src/util/base64.c @@ -16,15 +16,22 @@ static unsigned char base64_chars[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmno unsigned char * base64_encode(register unsigned char *in) +{ + assert(in && *in); + if_assert_failed return NULL; + + return base64_encode_bin(in, strlen(in), NULL); +} + +unsigned char * +base64_encode_bin(register unsigned char *in, int inlen, int *outlen) { unsigned char *out; unsigned char *outstr; - int inlen; assert(in && *in); if_assert_failed return NULL; - inlen = strlen(in); out = outstr = mem_alloc((inlen / 3) * 4 + 4 + 1); if (!out) return NULL; @@ -49,16 +56,29 @@ base64_encode(register unsigned char *in) } *out = 0; + if (outlen) + *outlen = out-outstr; + return outstr; } -/* Base64 decoding is used only with the CONFIG_FORMHIST feature, so i'll #ifdef it */ -#ifdef CONFIG_FORMHIST +/* Base64 decoding is used only with the CONFIG_FORMHIST or CONFIG_GSSAPI + feature, so i'll #ifdef it */ +#if defined(CONFIG_FORMHIST) || defined(CONFIG_GSSAPI) + +unsigned char * +base64_decode(register unsigned char *in) +{ + assert(in && *in); + if_assert_failed return NULL; + + return base64_decode_bin(in, strlen(in), NULL); +} /* base64_decode: @in string to decode * returns the string decoded (must be freed by the caller) */ unsigned char * -base64_decode(register unsigned char *in) +base64_decode_bin(register unsigned char *in, int inlen, int *outlen) { static unsigned char is_base64_char[256]; /* static to force initialization at zero */ static unsigned char decode[256]; @@ -71,7 +91,7 @@ base64_decode(register unsigned char *in) assert(in && *in); if_assert_failed return NULL; - outstr = out = mem_alloc(strlen(in) / 4 * 3 + 1); + outstr = out = mem_alloc(inlen / 4 * 3 + 1); if (!outstr) return NULL; if (!once) { @@ -123,6 +143,10 @@ base64_decode(register unsigned char *in) } *out = 0; + + if (outlen) + *outlen = out-outstr; + return outstr; decode_error: diff --git a/src/util/base64.h b/src/util/base64.h index cb5cd732..2bdf0e42 100644 --- a/src/util/base64.h +++ b/src/util/base64.h @@ -4,4 +4,7 @@ unsigned char *base64_encode(unsigned char *); unsigned char *base64_decode(unsigned char *); +unsigned char *base64_encode_bin(unsigned char *, int, int *); +unsigned char *base64_decode_bin(unsigned char *, int, int *); + #endif