From: Markus Moeller Date: Fri, 15 Apr 2011 11:51:15 +0000 (-0600) Subject: negotiate_wrapper_auth: version 1.0.1 X-Git-Tag: take06~6^2~6 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=eb3dea38c796fbf091b023e98e832b053c750453;p=thirdparty%2Fsquid.git negotiate_wrapper_auth: version 1.0.1 A helper to perform Negotaite authentication in both its Negotiate/NTLM and Negotiate/Kerberos forms. Makes use of additional Squid helpers after unwrapping the header token. --- diff --git a/configure.ac b/configure.ac index a612b7a83e..b454a79248 100644 --- a/configure.ac +++ b/configure.ac @@ -3424,6 +3424,7 @@ AC_CONFIG_FILES([\ helpers/negotiate_auth/Makefile \ helpers/negotiate_auth/kerberos/Makefile \ helpers/negotiate_auth/SSPI/Makefile \ + helpers/negotiate_auth/wrapper/Makefile \ helpers/external_acl/Makefile \ helpers/external_acl/AD_group/Makefile \ helpers/external_acl/eDirectory_userip/Makefile \ diff --git a/helpers/negotiate_auth/Makefile.am b/helpers/negotiate_auth/Makefile.am index 8350ac5758..4bb6e49773 100644 --- a/helpers/negotiate_auth/Makefile.am +++ b/helpers/negotiate_auth/Makefile.am @@ -1,3 +1,3 @@ -DIST_SUBDIRS = kerberos SSPI +DIST_SUBDIRS = kerberos SSPI wrapper SUBDIRS = $(NEGOTIATE_AUTH_HELPERS) diff --git a/helpers/negotiate_auth/wrapper/Makefile.am b/helpers/negotiate_auth/wrapper/Makefile.am new file mode 100644 index 0000000000..4aafe3f16d --- /dev/null +++ b/helpers/negotiate_auth/wrapper/Makefile.am @@ -0,0 +1,8 @@ +include $(top_srcdir)/src/Common.am + +EXTRA_DIST = config.test + +libexec_PROGRAMS = negotiate_wrapper_auth + +negotiate_wrapper_auth_SOURCES = negotiate_wrapper.cc nw_base64.cc nw_base64.h +negotiate_wrapper_auth_LDADD = $(COMPAT_LIB) $(XTRA_LIBS) diff --git a/helpers/negotiate_auth/wrapper/config.test b/helpers/negotiate_auth/wrapper/config.test new file mode 100755 index 0000000000..039e4d0069 --- /dev/null +++ b/helpers/negotiate_auth/wrapper/config.test @@ -0,0 +1,2 @@ +#!/bin/sh +exit 0 diff --git a/helpers/negotiate_auth/wrapper/negotiate_wrapper.cc b/helpers/negotiate_auth/wrapper/negotiate_wrapper.cc new file mode 100644 index 0000000000..81073eaf45 --- /dev/null +++ b/helpers/negotiate_auth/wrapper/negotiate_wrapper.cc @@ -0,0 +1,409 @@ +/* + * ----------------------------------------------------------------------------- + * + * Author: Markus Moeller (markus_moeller at compuserve.com) + * + * Copyright (C) 2011 Markus Moeller. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. + * + * ----------------------------------------------------------------------------- + */ +/* + * Hosted at http://sourceforge.net/projects/squidkerbauth + */ + +#include "config.h" +#include "nw_base64.h" + +#if HAVE_STRING_H +#include +#endif +#if HAVE_STDIO_H +#include +#endif +#if HAVE_STDLIB_H +#include +#endif +#if HAVE_NETDB_H +#include +#endif +#if HAVE_UNISTD_H +#include +#endif +#if HAVE_TIME_H +#include +#endif +#if HAVE_SYS_TIME_H +#include +#endif +#if HAVE_ERRNO_H +#include +#endif + +#if !defined(HAVE_DECL_XMALLOC) || !HAVE_DECL_XMALLOC +#define xmalloc malloc +#endif +#if !defined(HAVE_DECL_XSTRDUP) || !HAVE_DECL_XSTRDUP +#define xstrdup strdup +#endif +#if !defined(HAVE_DECL_XFREE) || !HAVE_DECL_XFREE +#define xfree free +#endif + +#undef PROGRAM +#define PROGRAM "negotiate_wrapper" +#undef VERSION +#define VERSION "1.0.1" + +#ifndef MAX_AUTHTOKEN_LEN +#define MAX_AUTHTOKEN_LEN 65535 +#endif + +static const unsigned char ntlmProtocol[] = {'N', 'T', 'L', 'M', 'S', 'S', 'P', 0}; + +static const char * +LogTime() +{ + struct tm *tm; + struct timeval now; + static time_t last_t = 0; + static char buf[128]; + + gettimeofday(&now, NULL); + if (now.tv_sec != last_t) { + tm = localtime((time_t *) & now.tv_sec); + strftime(buf, 127, "%Y/%m/%d %H:%M:%S", tm); + last_t = now.tv_sec; + } + return buf; +} + +void usage(void) +{ + fprintf(stderr, "Usage: \n"); + fprintf(stderr, "negotiate_wrapper [-h] [-d] --ntlm ntlm helper + arguments --kerberos kerberos helper + arguments\n"); + fprintf(stderr, "-h help\n"); + fprintf(stderr, "-d full debug\n"); + fprintf(stderr, "--ntlm full ntlm helper path with arguments\n"); + fprintf(stderr, "--kerberos full kerberos helper path with arguments\n"); +} + +int +main(int argc, char *const argv[]) +{ + char buf[MAX_AUTHTOKEN_LEN]; + char tbuff[MAX_AUTHTOKEN_LEN]; + char buff[MAX_AUTHTOKEN_LEN+2]; + char *c, *p; + static int err = 0; + int opt, debug = 0; + int length; + int nstart = 0, kstart = 0; + int nend = 0, kend = 0; + char *token; + char **nargs, **kargs; + int i,j; + int fpid; + FILE *FDKIN,*FDKOUT; + FILE *FDNIN,*FDNOUT; + int pkin[2]; + int pkout[2]; + int pnin[2]; + int pnout[2]; + + setbuf(stdout, NULL); + setbuf(stdin, NULL); + + if (argc ==1 || !strncasecmp(argv[1],"-h",2)) { + usage(); + return 0; + } + + j = 1; + if (!strncasecmp(argv[1],"-d",2)) { + debug = 1; + j = 2; + } + + for (i=j; i kstart) { + kend = nstart-1; + nend = argc-1; + } else { + kend = argc-1; + nend = kstart-1; + } + if (nstart == 0 || kstart == 0 || kend-kstart <= 0 || nend-nstart <= 0 ) { + usage(); + return 0; + } + + if (debug) + fprintf(stderr, "%s| %s: Starting version %s\n", LogTime(), PROGRAM, + VERSION); + + if ((nargs = (char **)xmalloc((nend-nstart+1)*sizeof(char *))) == NULL) { + fprintf(stderr, "%s| %s: Error allocating memory for ntlm helper\n", LogTime(), PROGRAM); + return 1; + } + memcpy(nargs,argv+nstart+1,(nend-nstart)*sizeof(char *)); + nargs[nend-nstart]=NULL; + if (debug) { + fprintf(stderr, "%s| %s: NTLM command: ", LogTime(), PROGRAM); + for (i=0; i(memchr(buf, '\n', sizeof(buf) - 1)); + if (c) { + *c = '\0'; + length = c - buf; + } else { + err = 1; + } + if (err) { + if (debug) + fprintf(stderr, "%s| %s: Oversized message\n", LogTime(), + PROGRAM); + fprintf(stdout, "BH Oversized message\n"); + err = 0; + continue; + } + if (debug) + fprintf(stderr, "%s| %s: Got '%s' from squid (length: %d).\n", + LogTime(), PROGRAM, buf, length); + + if (buf[0] == '\0') { + if (debug) + fprintf(stderr, "%s| %s: Invalid request\n", LogTime(), + PROGRAM); + fprintf(stdout, "BH Invalid request\n"); + continue; + } + if (strlen(buf) < 2) { + if (debug) + fprintf(stderr, "%s| %s: Invalid request [%s]\n", LogTime(), + PROGRAM, buf); + fprintf(stdout, "BH Invalid request\n"); + continue; + } + if (!strncmp(buf, "QQ", 2)) { + fprintf(stdout, "BH quit command\n"); + return 0; + } + if (strncmp(buf, "YR", 2) && strncmp(buf, "KK", 2)) { + if (debug) + fprintf(stderr, "%s| %s: Invalid request [%s]\n", LogTime(), + PROGRAM, buf); + fprintf(stdout, "BH Invalid request\n"); + continue; + } + if (strlen(buf) <= 3) { + if (debug) + fprintf(stderr, "%s| %s: Invalid negotiate request [%s]\n", + LogTime(), PROGRAM, buf); + fprintf(stdout, "BH Invalid negotiate request\n"); + continue; + } + length = nw_base64_decode_len(buf + 3); + if (debug) + fprintf(stderr, "%s| %s: Decode '%s' (decoded length: %d).\n", + LogTime(), PROGRAM, buf + 3, (int) length); + + if ((token = (char *)xmalloc(length)) == NULL) { + fprintf(stderr, "%s| %s: Error allocating memory for token\n", LogTime(), PROGRAM); + return 1; + } + + nw_base64_decode(token, buf + 3, length); + + if ((length >= sizeof ntlmProtocol + 1) && + (!memcmp(token, ntlmProtocol, sizeof ntlmProtocol))) { + free(token); + if (debug) + fprintf(stderr, "%s| %s: received type %d NTLM token\n", + LogTime(), PROGRAM, (int) *((unsigned char *) token + + sizeof ntlmProtocol)); + fprintf(FDNIN, "%s\n",buf); + if (fgets(tbuff, sizeof(tbuff) - 1, FDNOUT) == NULL) { + if (ferror(FDNOUT)) { + fprintf(stderr, + "fgets() failed! dying..... errno=%d (%s)\n", + ferror(FDNOUT), strerror(ferror(FDNOUT))); + return 1; + } + fprintf(stderr, "%s| %s: Error reading NTLM helper response\n", + LogTime(), PROGRAM); + return 0; + } + /* + Need to translate NTLM reply to Negotiate reply + AF user => AF blob user + NA reason => NA blob reason + Set blob to '=' + */ + if (strlen(tbuff) >= 3 && (!strncmp(tbuff,"AF ",3) || !strncmp(tbuff,"NA ",3))) { + int i; + strncpy(buff,tbuff,3); + buff[3]='='; + for (i=2; i<=strlen(tbuff); i++) + buff[i+2] = tbuff[i]; + } else { + strcpy(buff,tbuff); + } + } else { + free(token); + if (debug) + fprintf(stderr, "%s| %s: received Kerberos token\n", + LogTime(), PROGRAM); + + fprintf(FDKIN, "%s\n",buf); + if (fgets(buff, sizeof(buff) - 1, FDKOUT) == NULL) { + if (ferror(FDKOUT)) { + fprintf(stderr, + "fgets() failed! dying..... errno=%d (%s)\n", + ferror(FDKOUT), strerror(ferror(FDKOUT))); + return 1; + } + fprintf(stderr, "%s| %s: Error reading Kerberos helper response\n", + LogTime(), PROGRAM); + return 0; + } + } + fprintf(stdout,"%s",buff); + if (debug) + fprintf(stderr, "%s| %s: Return '%s'\n", + LogTime(), PROGRAM, buff); + } + + return 1; +} diff --git a/helpers/negotiate_auth/wrapper/nw_base64.cc b/helpers/negotiate_auth/wrapper/nw_base64.cc new file mode 100644 index 0000000000..1e7fb8b791 --- /dev/null +++ b/helpers/negotiate_auth/wrapper/nw_base64.cc @@ -0,0 +1,83 @@ +/* + * Markus Moeller has modified the following code from Squid + */ +#include "config.h" +#include "nw_base64.h" +#include +#include +#include + + +static void nw_base64_init(void); + +static int base64_initialized = 0; +#define BASE64_VALUE_SZ 256 +int base64_value[BASE64_VALUE_SZ]; +const char base64_code[] = + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; + + +static void +nw_base64_init(void) +{ + int i; + + for (i = 0; i < BASE64_VALUE_SZ; i++) + base64_value[i] = -1; + + for (i = 0; i < 64; i++) + base64_value[(int) base64_code[i]] = i; + base64_value['='] = 0; + + base64_initialized = 1; +} + +void +nw_base64_decode(char *result, const char *data, int result_size) +{ + int j; + int c; + long val; + if (!data) + return; + if (!base64_initialized) + nw_base64_init(); + val = c = 0; + + for (j = 0; *data; data++) { + unsigned int k = ((unsigned char) *data) % BASE64_VALUE_SZ; + if (base64_value[k] < 0) + continue; + val <<= 6; + val += base64_value[k]; + if (++c < 4) + continue; + /* One quantum of four encoding characters/24 bit */ + if (j >= result_size) + break; + result[j++] = val >> 16; /* High 8 bits */ + if (j >= result_size) + break; + result[j++] = (val >> 8) & 0xff; /* Mid 8 bits */ + if (j >= result_size) + break; + result[j++] = val & 0xff; /* Low 8 bits */ + val = c = 0; + } + return; +} + +int +nw_base64_decode_len(const char *data) +{ + int i, j; + + j = 0; + for (i = strlen(data) - 1; i >= 0; i--) { + if (data[i] == '=') + j++; + if (data[i] != '=') + break; + } + return strlen(data) / 4 * 3 - j; +} diff --git a/helpers/negotiate_auth/wrapper/nw_base64.h b/helpers/negotiate_auth/wrapper/nw_base64.h new file mode 100644 index 0000000000..2bebd32544 --- /dev/null +++ b/helpers/negotiate_auth/wrapper/nw_base64.h @@ -0,0 +1,11 @@ +#ifndef _NW_BASE64_H +#define _NW_BASE64_H + +/* + * Markus Moeller has modified the following code from Squid + */ + +void nw_base64_decode(char *result, const char *data, int result_size); +int nw_base64_decode_len(const char *data); + +#endif