diff -Nur squid-3/tools/1 squid-3-krb5/tools/1 --- squid-3/tools/1 1970-01-01 01:00:00.000000000 +0100 +++ squid-3-krb5/tools/1 2010-08-15 11:56:58.000000000 +0100 @@ -0,0 +1,94 @@ +# +# Makefile for the Squid Object Cache server +# +# Uncomment and customize the following to suit your needs: +# + +include $(top_srcdir)/src/Common.am + +AUTOMAKE_OPTIONS = subdir-objects + +## we need our local files too (but avoid -I. at all costs) +INCLUDES += -I$(srcdir) + +SUBDIRS = +EXTRA_DIST = +man_MANS = +DISTCLEANFILES = + +LDADD = \ + $(top_builddir)/src/time.o \ + $(top_builddir)/src/ip/libip.la \ + $(COMPAT_LIB) \ + $(XTRA_LIBS) \ + $(KRB5LIBS) +# On Windows may need: +# secur32.lib ws2_32.lib advapi32.lib +# + +include $(top_srcdir)/doc/manuals/Substitute.am + +test_tools.cc: $(top_srcdir)/test-suite/test_tools.cc + cp $(top_srcdir)/test-suite/test_tools.cc . + +# stock tools for unit tests - library independent versions of dlink_list +# etc. +# globals.cc is needed by test_tools.cc. +# Neither of these should be disted from here. +TESTSOURCES= test_tools.cc +CLEANFILES += test_tools.cc + +## ##### helper-mux ##### + +libexec_SCRIPTS = helper-mux.pl +EXTRA_DIST += helper-mux.pl helper-mux.README + +## Test Scripts +EXTRA_DIST += helper-ok-dying.pl helper-ok.pl + +## ##### squidclient ##### + +bin_PROGRAMS = squidclient + +squidclient_SOURCES = squidclient.cc \ + test_tools.cc + +EXTRA_DIST += squidclient.1 +man_MANS += squidclient.1 + + + +## ##### cachemgr.cgi ##### + +DEFAULT_CACHEMGR_CONFIG = $(sysconfdir)/cachemgr.conf + +libexec_PROGRAMS = cachemgr$(CGIEXT) + +cachemgr__CGIEXT__SOURCES = cachemgr.cc \ + test_tools.cc + +cachemgr__CGIEXT__CXXFLAGS = -DDEFAULT_CACHEMGR_CONFIG=\"$(DEFAULT_CACHEMGR_CONFIG)\" $(AM_CXXFLAGS) + +EXTRA_DIST += cachemgr.conf cachemgr.cgi.8 cachemgr.cgi.8.in +CLEANFILES += cachemgr.cgi.8 +man_MANS += cachemgr.cgi.8 + +cachemgr.cgi.8: $(srcdir)/cachemgr.cgi.8.in Makefile + $(SUBSTITUTE) < $(srcdir)/cachemgr.cgi.8.in > $@ + + + +## Shared + +install-data-local: + $(INSTALL_DATA) $(srcdir)/cachemgr.conf $(DESTDIR)$(DEFAULT_CACHEMGR_CONFIG).default + @if test -f $(DESTDIR)$(DEFAULT_CACHEMGR_CONFIG) ; then \ + echo "$@ will not overwrite existing $(DESTDIR)$(DEFAULT_CACHEMGR_CONFIG)" ; \ + else \ + echo "$(INSTALL_DATA) $(srcdir)/cachemgr.conf $(DESTDIR)$(DEFAULT_CACHEMGR_CONFIG)"; \ + $(INSTALL_DATA) $(srcdir)/cachemgr.conf $(DESTDIR)$(DEFAULT_CACHEMGR_CONFIG); \ + fi + +uninstall-local: + @$(SHELL) $(top_srcdir)/scripts/remove-cfg.sh "$(RM)" $(DESTDIR)$(DEFAULT_CACHEMGR_CONFIG) + $(RM) -f $(DESTDIR)$(DEFAULT_CACHEMGR_CONFIG).default diff -Nur squid-3/tools/Makefile.am squid-3-krb5/tools/Makefile.am --- squid-3/tools/Makefile.am 2010-08-13 01:12:56.000000000 +0100 +++ squid-3-krb5/tools/Makefile.am 2010-08-15 11:57:01.000000000 +0100 @@ -20,7 +20,11 @@ $(top_builddir)/src/time.o \ $(top_builddir)/src/ip/libip.la \ $(COMPAT_LIB) \ - $(XTRA_LIBS) + $(XTRA_LIBS) \ + $(KRB5LIBS) +# On Windows may need: +# secur32.lib ws2_32.lib advapi32.lib +# include $(top_srcdir)/doc/manuals/Substitute.am diff -Nur squid-3/tools/Makefile.in squid-3-krb5/tools/Makefile.in --- squid-3/tools/Makefile.in 2010-08-13 01:14:18.000000000 +0100 +++ squid-3-krb5/tools/Makefile.in 2010-08-15 11:54:26.000000000 +0100 @@ -74,7 +74,7 @@ am__DEPENDENCIES_2 = cachemgr__CGIEXT__DEPENDENCIES = $(top_builddir)/src/time.o \ $(top_builddir)/src/ip/libip.la $(am__DEPENDENCIES_1) \ - $(am__DEPENDENCIES_2) + $(am__DEPENDENCIES_2) $(am__DEPENDENCIES_2) cachemgr__CGIEXT__LINK = $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CXXLD) \ $(cachemgr__CGIEXT__CXXFLAGS) $(CXXFLAGS) $(AM_LDFLAGS) \ @@ -84,7 +84,7 @@ squidclient_LDADD = $(LDADD) squidclient_DEPENDENCIES = $(top_builddir)/src/time.o \ $(top_builddir)/src/ip/libip.la $(am__DEPENDENCIES_1) \ - $(am__DEPENDENCIES_2) + $(am__DEPENDENCIES_2) $(am__DEPENDENCIES_2) libexecSCRIPT_INSTALL = $(INSTALL_SCRIPT) SCRIPTS = $(libexec_SCRIPTS) DEFAULT_INCLUDES = @@ -341,7 +341,8 @@ $(top_builddir)/src/time.o \ $(top_builddir)/src/ip/libip.la \ $(COMPAT_LIB) \ - $(XTRA_LIBS) + $(XTRA_LIBS) \ + $(KRB5LIBS) SUBSTITUTE = sed "\ s%@DEFAULT_ERROR_DIR@%$(DEFAULT_ERROR_DIR)%g;\ diff -Nur squid-3/tools/squidclient.cc squid-3-krb5/tools/squidclient.cc --- squid-3/tools/squidclient.cc 2010-08-13 01:12:56.000000000 +0100 +++ squid-3-krb5/tools/squidclient.cc 2010-08-15 12:25:02.000000000 +0100 @@ -79,6 +79,51 @@ #include #endif +#if HAVE_GSSAPI +#ifdef HAVE_HEIMDAL_KERBEROS +#ifdef HAVE_GSSAPI_GSSAPI_H +#include +#elif defined(HAVE_GSSAPI_H) +#include +#else +#error "GSSAPI header required" +#endif +#define gss_nt_service_name GSS_C_NT_HOSTBASED_SERVICE +#else +#ifdef HAVE_SEAM_KERBEROS +#ifdef HAVE_GSSAPI_GSSAPI_H +#include +#elif defined(HAVE_GSSAPI_H) +#include +#else +#error "GSSAPI header required" +#endif +#ifdef HAVE_GSSAPI_GSSAPI_EXT_H +#include +#endif +#define gss_nt_service_name GSS_C_NT_HOSTBASED_SERVICE +#else /*MIT */ +#ifdef HAVE_GSSAPI_GSSAPI_H +#include +#elif defined(HAVE_GSSAPI_H) +#include +#else +#error "GSSAPI header required" +#endif +#ifdef HAVE_GSSAPI_GSSAPI_KRB5_H +#include +#endif +#ifdef HAVE_GSSAPI_GSSAPI_GENERIC_H +#include +#endif +#endif +#endif + +#ifndef gss_mech_spnego +static gss_OID_desc _gss_mech_spnego = {6, (void *) "\x2b\x06\x01\x05\x05\x02"}; +gss_OID gss_mech_spnego = &_gss_mech_spnego; +#endif +#endif #ifndef BUFSIZ #define BUFSIZ 8192 @@ -104,6 +149,13 @@ static void set_our_signal(void); static ssize_t myread(int fd, void *buf, size_t len); static ssize_t mywrite(int fd, void *buf, size_t len); + + +#if HAVE_GSSAPI +static int check_gss_err(OM_uint32 major_status, OM_uint32 minor_status, const char *function); +static char *GSSAPI_token(const char *server); +#endif + static int put_fd; static char *put_file = NULL; @@ -149,10 +201,14 @@ " -u user Proxy authentication username\n" " -U user WWW authentication username\n" " -v Verbose. Print outgoing message to stderr.\n" - " -V version HTTP Version. Use '-' for HTTP/0.9 omitted case\n", + " -V version HTTP Version. Use '-' for HTTP/0.9 omitted case\n" " -w password Proxy authentication password\n" " -W password WWW authentication password\n" - VERSION, progname, CACHE_HTTP_PORT); +#if HAVE_GSSAPI + " -n Proxy Negotiate(Kerberos) authentication\n" + " -N WWW Negotiate(Kerberos) authentication\n" +#endif + ,VERSION, progname, CACHE_HTTP_PORT); exit(1); } @@ -166,6 +222,7 @@ int keep_alive = 0; int opt_noaccept = 0; int opt_verbose = 0; + int www_neg, proxy_neg; const char *hostname, *localhost; Ip::Address iaddr; char url[BUFSIZ], msg[MESSAGELEN], buf[BUFSIZ]; @@ -196,6 +253,8 @@ ping = 0; pcount = 0; ping_int = 1 * 1000; + www_neg = 0; + proxy_neg = 0; if (argc < 2) { usage(argv[0]); /* need URL */ @@ -205,8 +264,11 @@ if (url[0] == '-') usage(argv[0]); - +#if HAVE_GSSAPI + while ((c = getopt(argc, argv, "ah:j:V:l:P:i:km:p:rsvt:g:p:I:H:T:u:U:w:W:nN?")) != -1) +#else while ((c = getopt(argc, argv, "ah:j:V:l:P:i:km:p:rsvt:g:p:I:H:T:u:U:w:W:?")) != -1) +#endif switch (c) { case 'a': @@ -307,6 +369,15 @@ www_password = optarg; break; +#if HAVE_GSSAPI + case 'n': + proxy_neg = 1; + break; + + case 'N': + www_neg = 1; + break; +#endif case 'v': /* undocumented: may increase verb-level by giving more -v's */ opt_verbose++; @@ -348,7 +419,6 @@ fstat(put_fd, &sb); } - if (!host) { char *newhost = strstr(url, "://"); if (newhost) { @@ -364,7 +434,6 @@ host = newhost; } } - if (version[0] == '-' || !version[0] || version[0] == '0') { /* HTTP/0.9, no headers, no version */ snprintf(msg, BUFSIZ, "%s %s\r\n", method, url); @@ -373,9 +442,8 @@ if (host) { snprintf(buf, BUFSIZ, "Host: %s\r\n", host); - strcat(msg,buf); + strcat(msg, buf); } - if (reload) { snprintf(buf, BUFSIZ, "Pragma: no-cache\r\n"); strcat(msg, buf); @@ -426,6 +494,24 @@ snprintf(buf, BUFSIZ, "Authorization: Basic %s\r\n", base64_encode(buf)); strcat(msg, buf); } +#if HAVE_GSSAPI + if (www_neg || proxy_neg) { + if (www_neg) { + if (host) { + snprintf(buf, BUFSIZ, "Authorization: Negotiate %s\r\n", GSSAPI_token(host)); + strcat(msg, buf); + } else + fprintf(stderr, "ERROR: server host missing\n"); + } + if (proxy_neg) { + if (hostname) { + snprintf(buf, BUFSIZ, "Proxy-Authorization: Negotiate %s\r\n", GSSAPI_token(hostname)); + strcat(msg, buf); + } else + fprintf(stderr, "ERROR: porxy server host missing\n"); + } + } +#endif /* HTTP/1.0 may need keep-alive */ if (strcmp(version, "1.0") == 0) { @@ -477,14 +563,14 @@ /* Connect to the server */ if (localhost) { - if ( !iaddr.GetHostByName(localhost) ) { + if (!iaddr.GetHostByName(localhost)) { fprintf(stderr, "client: ERROR: Cannot resolve %s: Host unknown.\n", localhost); exit(1); } } else { /* Process the remote host name to locate the Protocol required - in case we are being asked to link to another version of squid */ - if ( !iaddr.GetHostByName(hostname) ) { + * in case we are being asked to link to another version of squid */ + if (!iaddr.GetHostByName(hostname)) { fprintf(stderr, "client: ERROR: Cannot resolve %s: Host unknown.\n", hostname); exit(1); } @@ -502,13 +588,11 @@ perror("client: bind"); exit(1); } - iaddr.SetEmpty(); - if ( !iaddr.GetHostByName(hostname) ) { + if (!iaddr.GetHostByName(hostname)) { fprintf(stderr, "client: ERROR: Cannot resolve %s: Host unknown.\n", hostname); exit(1); } - iaddr.SetPort(port); if (client_comm_connect(conn, iaddr, ping ? &tv1 : NULL) < 0) { @@ -523,7 +607,6 @@ } exit(1); } - /* Send the HTTP request */ bytesWritten = mywrite(conn, msg, strlen(msg)); @@ -534,7 +617,6 @@ fprintf(stderr, "client: ERROR: Cannot send request?: %s\n", msg); exit(1); } - if (put_file) { int x; lseek(put_fd, 0, SEEK_SET); @@ -630,7 +712,7 @@ } static int -client_comm_bind(int sock, const Ip::Address &addr) +client_comm_bind(int sock, const Ip::Address & addr) { int res; @@ -649,7 +731,7 @@ } static int -client_comm_connect(int sock, const Ip::Address &addr, struct timeval *tvp) +client_comm_connect(int sock, const Ip::Address & addr, struct timeval *tvp) { int res; static struct addrinfo *AI = NULL; @@ -736,3 +818,120 @@ return send(fd, buf, len, 0); #endif } + +#if HAVE_GSSAPI +static int +check_gss_err(OM_uint32 major_status, OM_uint32 minor_status, const char *function) +{ + if (GSS_ERROR(major_status)) { + OM_uint32 maj_stat, min_stat; + OM_uint32 msg_ctx = 0; + gss_buffer_desc status_string; + char buf[1024]; + size_t len; + + len = 0; + msg_ctx = 0; + while (!msg_ctx) { + /* convert major status code (GSS-API error) to text */ + maj_stat = gss_display_status(&min_stat, major_status, + GSS_C_GSS_CODE, + GSS_C_NULL_OID, + &msg_ctx, &status_string); + if (maj_stat == GSS_S_COMPLETE) { + if (sizeof(buf) > len + status_string.length + 1) { + sprintf(buf + len, "%s", (char *) status_string.value); + len += status_string.length; + } + gss_release_buffer(&min_stat, &status_string); + break; + } + gss_release_buffer(&min_stat, &status_string); + } + if (sizeof(buf) > len + 2) { + sprintf(buf + len, "%s", ". "); + len += 2; + } + msg_ctx = 0; + while (!msg_ctx) { + /* convert minor status code (underlying routine error) to text */ + maj_stat = gss_display_status(&min_stat, minor_status, + GSS_C_MECH_CODE, + GSS_C_NULL_OID, + &msg_ctx, &status_string); + if (maj_stat == GSS_S_COMPLETE) { + if (sizeof(buf) > len + status_string.length) { + sprintf(buf + len, "%s", (char *) status_string.value); + len += status_string.length; + } + gss_release_buffer(&min_stat, &status_string); + break; + } + gss_release_buffer(&min_stat, &status_string); + } + fprintf(stderr, "%s failed: %s\n", function, buf); + return (1); + } + return (0); +} + +static char * +GSSAPI_token(const char *server) +{ + OM_uint32 major_status, minor_status; + gss_ctx_id_t gss_context = GSS_C_NO_CONTEXT; + gss_name_t server_name = GSS_C_NO_NAME; + gss_buffer_desc service = GSS_C_EMPTY_BUFFER; + gss_buffer_desc input_token = GSS_C_EMPTY_BUFFER; + gss_buffer_desc output_token = GSS_C_EMPTY_BUFFER; + char *token = NULL; + + setbuf(stdout, NULL); + setbuf(stdin, NULL); + + if (!server) { + fprintf(stderr, "Error: No server name\n"); + return NULL; + } + service.value = xmalloc(strlen("HTTP") + strlen(server) + 2); + snprintf((char *) service.value, strlen("HTTP") + strlen(server) + 2, "%s@%s", "HTTP", server); + service.length = strlen((char *) service.value); + + major_status = gss_import_name(&minor_status, &service, + gss_nt_service_name, &server_name); + + if (check_gss_err(major_status, minor_status, "gss_import_name()")) + goto cleanup; + + major_status = gss_init_sec_context(&minor_status, + GSS_C_NO_CREDENTIAL, + &gss_context, + server_name, + gss_mech_spnego, + 0, + 0, + GSS_C_NO_CHANNEL_BINDINGS, + &input_token, + NULL, + &output_token, + NULL, + NULL); + + if (check_gss_err(major_status, minor_status, "gss_init_sec_context()")) + goto cleanup; + + if (output_token.length) + token = (char *) base64_encode_bin((const char *) output_token.value, output_token.length); + +cleanup: + if (!output_token.length) + token = (char *) "ERROR"; + gss_delete_sec_context(&minor_status, &gss_context, NULL); + gss_release_buffer(&minor_status, &service); + gss_release_buffer(&minor_status, &input_token); + gss_release_buffer(&minor_status, &output_token); + gss_release_name(&minor_status, &server_name); + + return token; +} +#endif