]> git.ipfire.org Git - thirdparty/squid.git/commitdiff
Upgrade mswin_sspi_auth to ntlm_sspi_auth
authorAmos Jeffries <squid3@treenet.co.nz>
Mon, 28 Jun 2010 10:51:55 +0000 (22:51 +1200)
committerAmos Jeffries <squid3@treenet.co.nz>
Mon, 28 Jun 2010 10:51:55 +0000 (22:51 +1200)
* Make use of new libntlmauth API for several actions.

TODO: C++ upgrade will need to be done in conjunction with someone who
      can assist testing the build.

configure.in
helpers/ntlm_auth/SSPI/Makefile.am [new file with mode: 0644]
helpers/ntlm_auth/SSPI/config.test [moved from helpers/ntlm_auth/mswin_sspi/config.test with 100% similarity]
helpers/ntlm_auth/SSPI/ntlm_sspi_auth.8 [new file with mode: 0644]
helpers/ntlm_auth/SSPI/ntlm_sspi_auth.cc [moved from helpers/ntlm_auth/mswin_sspi/ntlm_auth.c with 53% similarity]
helpers/ntlm_auth/mswin_sspi/Makefile.am [deleted file]
helpers/ntlm_auth/mswin_sspi/libntlmssp.c [deleted file]
helpers/ntlm_auth/mswin_sspi/ntlm.h [deleted file]
helpers/ntlm_auth/mswin_sspi/readme.txt [deleted file]

index 56d9d7fa4cdc2ec43121d1a5756c9f7801dae9fe..14daa51aad24c61c36083ce777016c4afc9d68d6 100644 (file)
@@ -1577,6 +1577,7 @@ if test "$enable_auth_ntlm" != "no" ; then
     done
 fi
 AC_MSG_NOTICE([NTLM auth helpers built: $NTLM_AUTH_HELPERS])
+AM_CONDITIONAL(ENABLE_AUTH_NTLM, test "$enable_auth_ntlm" != "no")
 AC_SUBST(NTLM_AUTH_HELPERS)
 
 AC_ARG_ENABLE(auth-negotiate,
@@ -3819,7 +3820,7 @@ AC_CONFIG_FILES([\
        helpers/ntlm_auth/fake/Makefile \
        helpers/ntlm_auth/smb_lm/Makefile \
        helpers/ntlm_auth/smb_lm/smbval/Makefile \
-       helpers/ntlm_auth/mswin_sspi/Makefile \
+       helpers/ntlm_auth/SSPI/Makefile \
        helpers/negotiate_auth/Makefile \
        helpers/negotiate_auth/kerberos/Makefile \
        helpers/negotiate_auth/mswin_sspi/Makefile \
diff --git a/helpers/ntlm_auth/SSPI/Makefile.am b/helpers/ntlm_auth/SSPI/Makefile.am
new file mode 100644 (file)
index 0000000..7c6fd08
--- /dev/null
@@ -0,0 +1,17 @@
+include $(top_srcdir)/src/Common.am
+
+man_MANS = ntlm_sspi_auth.8
+
+libexec_PROGRAMS = ntlm_sspi_auth
+
+ntlm_sspi_auth_SOURCES = ntlm_sspi_auth.cc
+
+LDADD = \
+       -L$(top_builddir)/libntlmauth -lntlmauth \
+       -L$(top_builddir)/lib -lsspwin32 \
+       $(COMPAT_LIB) \
+       -lnetapi32 \
+       -ladvapi32 \
+       $(XTRA_LIBS)
+
+EXTRA_DIST = ntlm_sspi_auth.8 config.test
diff --git a/helpers/ntlm_auth/SSPI/ntlm_sspi_auth.8 b/helpers/ntlm_auth/SSPI/ntlm_sspi_auth.8
new file mode 100644 (file)
index 0000000..b66efef
--- /dev/null
@@ -0,0 +1,123 @@
+.if !'po4a'hide' .TH ntlm_sspi_auth.exe 8
+.
+.SH NAME
+.if !'po4a'hide' .B ntlm_sspi_auth.exe
+.if !'po4a'hide' \-
+Native Windows NTLM/NTLMv2 authenticator for Squid with
+automatic support for NTLM NEGOTIATE packets.
+.PP
+Version 1.22
+.
+.SH SYNOPSIS
+.if !'po4a'hide' .B ntlm_sspi_auth.exe
+.if !'po4a'hide' .B "[\-dhv] [\-A "
+Group Name
+.if !'po4a'hide' .B "] [\-D "
+Group Name
+.if !'po4a'hide' .B "]"
+.
+.SH DESCRIPTION
+.B ntlm_sspi_auth.exe
+is an installed binary built on Windows systems. It provides native access to the
+Security Service Provider Interface of Windows for authenticating with NTLM / NTLMv2.
+It has automatic support for NTLM NEGOTIATE packets.
+.
+.SH OPTIONS
+.if !'po4a'hide' .TP 12
+.if !'po4a'hide' .B \-d
+Write debug info to stderr.
+.if !'po4a'hide' .B \-h
+Display the binary help and command line syntax info using stderr.
+.if !'po4a'hide' .B \-v
+Enables verbose NTLM packet debugging.
+.if !'po4a'hide' .B \-A
+Specify a Windows Local Group name allowed to authenticate.
+.if !'po4a'hide' .B \-D
+Specify a Windows Local Group name which is to be denied authentication.
+.
+.SH CONFIGURATION
+.PP Allowing Users
+.PP
+Users that are allowed to access the web proxy must have the Windows NT
+User Rights "logon from the network".
+.PP
+Optionally the authenticator can verify the NT LOCAL group membership of
+the user against the User Group specified in the Authenticator's command
+line.
+.PP
+This can be accomplished creating a local user group on the NT machine,
+grant the privilege, and adding users to it, it works only with MACHINE
+Local Groups, not Domain Local Groups.
+.PP
+Better group checking is available with External Acl, see mswin_check_group
+documentation.
+.PP
+.B squid.conf
+typical minimal required changes:
+.if !'po4a'hide' .RS
+.if !'po4a'hide' auth_param ntlm program c:/squid/libexec/mswin_ntlm_auth.exe
+.if !'po4a'hide' auth_param ntlm children 5
+.if !'po4a'hide' 
+.if !'po4a'hide' acl password proxy_auth REQUIRED
+.if !'po4a'hide' 
+.if !'po4a'hide' http_access allow password
+.if !'po4a'hide' http_access deny all
+.
+.PP Refer to Squid documentation for more details.
+.
+.PP
+Internet Explorer has some problems with 
+.B ftp:// 
+URLs when handling internal Squid FTP icons.
+The following 
+.B squid.conf 
+ACL works around this when placed before the authentication ACL:
+.if !'po4a'hide' .RS
+.if !'po4a'hide' acl internal_icons urlpath_regex -i /squid-internal-static/icons/
+.if !'po4a'hide' 
+.if !'po4a'hide' http_access allow our_networks internal_icons
+.
+.SH AUTHOR
+This program was written by
+.if !'po4a'hide' .I Guido Serassio <guido.serassio@acmeconsulting.it>
+.PP
+Based on prior work in by
+.if !'po4a'hide' .I Francesco Chemolli <kinkie@squid-cache.org>
+.if !'po4a'hide' .I Robert Collins <lifeless@squid-cache.org>
+.PP
+This manual was written by
+.if !'po4a'hide' .I Guido Serassio <guido.serassio@acmeconsulting.it>
+.if !'po4a'hide' .I Amos Jeffries <amosjeffries@squid-cache.org>
+.
+.SH COPYRIGHT
+This program and documentation is copyright to the authors named above.
+.PP
+Distributed under the GNU General Public License (GNU GPL) version 2 or later (GPLv2+).
+.
+.SH QUESTIONS
+Questions on the usage of this program can be sent to the
+.I Squid Users mailing list
+.if !'po4a'hide' <squid-users@squid-cache.org>
+.
+.SH REPORTING BUGS
+Bug reports need to be made in English.
+See http://wiki.squid-cache.org/SquidFaq/BugReporting for details of what you need to include with your bug report.
+.PP
+Report bugs or bug fixes using http://bugs.squid-cache.org/
+.PP
+Report serious security bugs to
+.I Squid Bugs <squid-bugs@squid-cache.org>
+.PP
+Report ideas for new improvements to the
+.I Squid Developers mailing list
+.if !'po4a'hide' <squid-dev@squid-cache.org>
+.
+.SH SEE ALSO
+.if !'po4a'hide' .BR squid "(8), "
+.if !'po4a'hide' .BR GPL "(7), "
+.br
+The Squid FAQ wiki
+.if !'po4a'hide' http://wiki.squid-cache.org/SquidFaq
+.br
+The Squid Configuration Manual
+.if !'po4a'hide' http://www.squid-cache.org/Doc/config/
similarity index 53%
rename from helpers/ntlm_auth/mswin_sspi/ntlm_auth.c
rename to helpers/ntlm_auth/SSPI/ntlm_sspi_auth.cc
index 31e76eaa0dd81db3756dd51edc54d6faeee44fd9..d047e617bc46b3028ce47a34cb3683ce372bdf8a 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * mswin_ntlm_auth: helper for NTLM Authentication for Squid Cache
+ * ntlm_sspi_auth: helper for NTLM Authentication for Squid Cache
  *
  * (C)2002,2005 Guido Serassio - Acme Consulting S.r.l.
  *
  *
  */
 
+/************* CONFIGURATION ***************/
+
+#define FAIL_DEBUG 0
+
+/************* END CONFIGURATION ***************/
+
+typedef unsigned char uchar;
+
+#include "config.h"
+#include "helpers/defines.h"
+#include "libntlmauth/ntlmauth.h"
+#include "libntlmauth/support_bits.h"
+#include "sspwin32.h"
 #include "util.h"
-#if HAVE_GETOPT_H
-#include <getopt.h>
-#endif
-#include "ntlm.h"
+
+#include <windows.h>
+#include <sspi.h>
+#include <security.h>
 #if HAVE_CTYPE_H
 #include <ctype.h>
 #endif
+#if HAVE_GETOPT_H
+#include <getopt.h>
+#endif
+#include <lm.h>
+#include <ntsecapi.h>
 
 #define BUFFER_SIZE 10240
 
-int debug_enabled = 0;
 int NTLM_packet_debug_enabled = 0;
-
 static int have_challenge;
-
 char * NTAllowedGroup;
 char * NTDisAllowedGroup;
 int UseDisallowedGroup = 0;
 int UseAllowedGroup = 0;
+
 #if FAIL_DEBUG
 int fail_debug_enabled = 0;
 #endif
 
-/* makes a null-terminated string upper-case. Changes CONTENTS! */
-void
-uc(char *string)
+/* returns 1 on success, 0 on failure */
+int
+Valid_Group(char *UserName, char *Group)
 {
-    char *p = string, c;
-    while ((c = *p)) {
-        *p = xtoupper(c);
-        p++;
-    }
+    int result = FALSE;
+    WCHAR wszUserName[UNLEN+1];        // Unicode user name
+    WCHAR wszGroup[GNLEN+1];   // Unicode Group
+
+    LPLOCALGROUP_USERS_INFO_0 pBuf = NULL;
+    LPLOCALGROUP_USERS_INFO_0 pTmpBuf;
+    DWORD dwLevel = 0;
+    DWORD dwFlags = LG_INCLUDE_INDIRECT;
+    DWORD dwPrefMaxLen = -1;
+    DWORD dwEntriesRead = 0;
+    DWORD dwTotalEntries = 0;
+    NET_API_STATUS nStatus;
+    DWORD i;
+    DWORD dwTotalCount = 0;
+
+    /* Convert ANSI User Name and Group to Unicode */
+
+    MultiByteToWideChar(CP_ACP, 0, UserName,
+                        strlen(UserName) + 1, wszUserName,
+                        sizeof(wszUserName) / sizeof(wszUserName[0]));
+    MultiByteToWideChar(CP_ACP, 0, Group,
+                        strlen(Group) + 1, wszGroup, sizeof(wszGroup) / sizeof(wszGroup[0]));
+
+    /*
+     * Call the NetUserGetLocalGroups function
+     * specifying information level 0.
+     *
+     * The LG_INCLUDE_INDIRECT flag specifies that the
+     * function should also return the names of the local
+     * groups in which the user is indirectly a member.
+     */
+    nStatus = NetUserGetLocalGroups(NULL,
+                                    wszUserName,
+                                    dwLevel,
+                                    dwFlags,
+                                    (LPBYTE *) & pBuf, dwPrefMaxLen, &dwEntriesRead, &dwTotalEntries);
+    /*
+     * If the call succeeds,
+     */
+    if (nStatus == NERR_Success) {
+        if ((pTmpBuf = pBuf) != NULL) {
+            for (i = 0; i < dwEntriesRead; i++) {
+                if (pTmpBuf == NULL) {
+                    result = FALSE;
+                    break;
+                }
+                if (wcscmp(pTmpBuf->lgrui0_name, wszGroup) == 0) {
+                    result = TRUE;
+                    break;
+                }
+                pTmpBuf++;
+                dwTotalCount++;
+            }
+        }
+    } else
+        result = FALSE;
+    /*
+     * Free the allocated memory.
+     */
+    if (pBuf != NULL)
+        NetApiBufferFree(pBuf);
+    return result;
+}
+
+
+char * AllocStrFromLSAStr(LSA_UNICODE_STRING LsaStr)
+{
+    size_t len;
+    static char * target;
+
+    len = LsaStr.Length/sizeof(WCHAR) + 1;
+
+    /* allocate buffer for str + null termination */
+    safe_free(target);
+    target = (char *)xmalloc(len);
+    if (target == NULL)
+        return NULL;
+
+    /* copy unicode buffer */
+    WideCharToMultiByte(CP_ACP, 0, LsaStr.Buffer, LsaStr.Length, target, len, NULL, NULL );
+
+    /* add null termination */
+    target[len-1] = '\0';
+    return target;
 }
 
-/* makes a null-terminated string lower-case. Changes CONTENTS! */
-static void
-lc(char *string)
+
+char * GetDomainName(void)
+
 {
-    char *p = string, c;
-    while ((c = *p)) {
-        *p = xtolower(c);
-        p++;
+    LSA_HANDLE PolicyHandle;
+    LSA_OBJECT_ATTRIBUTES ObjectAttributes;
+    NTSTATUS status;
+    PPOLICY_PRIMARY_DOMAIN_INFO ppdiDomainInfo;
+    PWKSTA_INFO_100 pwkiWorkstationInfo;
+    DWORD netret;
+    char * DomainName = NULL;
+
+    /*
+     * Always initialize the object attributes to all zeroes.
+     */
+    memset(&ObjectAttributes, '\0', sizeof(ObjectAttributes));
+
+    /*
+     * You need the local workstation name. Use NetWkstaGetInfo at level
+     * 100 to retrieve a WKSTA_INFO_100 structure.
+     *
+     * The wki100_computername field contains a pointer to a UNICODE
+     * string containing the local computer name.
+     */
+    netret = NetWkstaGetInfo(NULL, 100, (LPBYTE *)&pwkiWorkstationInfo);
+    if (netret == NERR_Success) {
+        /*
+         * We have the workstation name in:
+         * pwkiWorkstationInfo->wki100_computername
+         *
+         * Next, open the policy object for the local system using
+         * the LsaOpenPolicy function.
+         */
+        status = LsaOpenPolicy(
+                     NULL,
+                     &ObjectAttributes,
+                     GENERIC_READ | POLICY_VIEW_LOCAL_INFORMATION,
+                     &PolicyHandle
+                 );
+
+        /*
+         * Error checking.
+         */
+        if (status) {
+            debug("OpenPolicy Error: %ld\n", status);
+        } else {
+
+            /*
+             * You have a handle to the policy object. Now, get the
+             * domain information using LsaQueryInformationPolicy.
+             */
+            status = LsaQueryInformationPolicy(PolicyHandle,
+                                               PolicyPrimaryDomainInformation,
+                                               (void **)&ppdiDomainInfo);
+            if (status) {
+                debug("LsaQueryInformationPolicy Error: %ld\n", status);
+            } else  {
+
+                /* Get name in useable format */
+                DomainName = AllocStrFromLSAStr(ppdiDomainInfo->Name);
+
+                /*
+                 * Check the Sid pointer, if it is null, the
+                 * workstation is either a stand-alone computer
+                 * or a member of a workgroup.
+                 */
+                if (ppdiDomainInfo->Sid) {
+
+                    /*
+                     * Member of a domain. Display it in debug mode.
+                     */
+                    debug("Member of Domain %s\n",DomainName);
+                } else {
+                    DomainName = NULL;
+                }
+            }
+        }
+
+        /*
+         * Clean up all the memory buffers created by the LSA and
+         * Net* APIs.
+         */
+        NetApiBufferFree(pwkiWorkstationInfo);
+        LsaFreeMemory((LPVOID)ppdiDomainInfo);
+    } else
+        debug("NetWkstaGetInfo Error: %ld\n", netret);
+    return DomainName;
+}
+
+/* returns NULL on failure, or a pointer to
+ * the user's credentials (domain\\username)
+ * upon success. WARNING. It's pointing to static storage.
+ * In case of problem sets as side-effect ntlm_errno to one of the
+ * codes defined in libntlmauth/ntlmauth.h
+ */
+int
+ntlm_check_auth(ntlm_authenticate * auth, char *user, char *domain, int auth_length)
+{
+    int x;
+    int rv;
+    char credentials[DNLEN+UNLEN+2];   /* we can afford to waste */
+    lstring tmp;
+
+    if (!NTLM_LocalCall) {
+
+        user[0] = '\0';
+        domain[0] = '\0';
+        x = ntlm_unpack_auth(auth, user, domain, auth_length);
+
+        if (x != NTLM_ERR_NONE)
+            return x;
+
+        if (domain[0] == '\0') {
+            debug("No domain supplied. Returning no-auth\n");
+            return NTLM_BAD_REQUEST;
+        }
+        if (user[0] == '\0') {
+            debug("No username supplied. Returning no-auth\n");
+            return NTLM_BAD_REQUEST;
+        }
+        debug("checking domain: '%s', user: '%s'\n", domain, user);
+
+    } else
+        debug("checking local user\n");
+
+    snprintf(credentials, DNLEN+UNLEN+2, "%s\\%s", domain, user);
+
+    rv = SSP_ValidateNTLMCredentials(auth, auth_length, credentials);
+
+    debug("Login attempt had result %d\n", rv);
+
+    if (!rv) {                 /* failed */
+        return NTLM_SSPI_ERROR;
+    }
+
+    if (UseAllowedGroup) {
+        if (!Valid_Group(credentials, NTAllowedGroup)) {
+            debug("User %s not in allowed Group %s\n", credentials, NTAllowedGroup);
+            return NTLM_BAD_NTGROUP;
+        }
     }
+    if (UseDisallowedGroup) {
+        if (Valid_Group(credentials, NTDisAllowedGroup)) {
+            debug("User %s is in denied Group %s\n", credentials, NTDisAllowedGroup);
+            return NTLM_BAD_NTGROUP;
+        }
+    }
+
+    debug("credentials: %s\n", credentials);
+    return NTLM_ERR_NONE;
 }
 
 void
@@ -174,22 +410,6 @@ process_options(int argc, char *argv[])
         exit(1);
 }
 
-
-const char *
-obtain_challenge(ntlm_negotiate * nego, int nego_length)
-{
-    const char *ch = NULL;
-
-    debug("attempting SSPI challenge retrieval\n");
-    ch = SSP_MakeChallenge(nego, nego_length);
-    if (ch) {
-        debug("Got it\n");
-        return ch;             /* All went OK, returning */
-    }
-    return NULL;
-}
-
-
 int
 manage_request()
 {
@@ -200,6 +420,21 @@ manage_request()
     int plen;
     int oversized = 0;
     char * ErrorMessage;
+    static ntlm_negotiate local_nego;
+    char domain[DNLEN+1];
+    char user[UNLEN+1];
+
+    /* NP: for some reason this helper sometimes needs to accept
+     * from clients that send no negotiate packet. */
+    if (memcpy(local_nego.signature, "NTLMSSP", 8) != 0) {
+        memset(&local_nego, 0, sizeof(ntlm_negotiate));        /* reset */
+        memcpy(local_nego.signature, "NTLMSSP", 8);     /* set the signature */
+        local_nego.type = le32toh(NTLM_NEGOTIATE);      /* this is a challenge */
+        local_nego.flags = le32toh(NTLM_NEGOTIATE_ALWAYS_SIGN |
+                                   NTLM_NEGOTIATE_USE_NTLM |
+                                   NTLM_NEGOTIATE_USE_LM |
+                                   NTLM_NEGOTIATE_ASCII );
+    }
 
 try_again:
     if (fgets(buf, BUFFER_SIZE, stdin) == NULL)
@@ -229,8 +464,10 @@ try_again:
         /* figure out what we got */
         if (strlen(buf) > 3)
             decoded = base64_decode(buf + 3);
-        else
-            decoded = base64_decode(ntlm_make_negotiate());
+        else {
+            debug("Negotiate packet not supplied - self generated\n");
+            decoded = (char *) &local_nego;
+        }
         /* Note: we don't need to manage memory at this point, since
          *  base64_decode returns a pointer to static storage.
          */
@@ -242,7 +479,7 @@ try_again:
         fast_header = (struct _ntlmhdr *) decoded;
 
         /* sanity-check: it IS a NTLMSSP packet, isn't it? */
-        if (memcmp(fast_header->signature, "NTLMSSP", 8) != 0) {
+        if (ntlm_validate_packet(fast_header, NTLM_ANY) != NTLM_ERR_NONE) {
             SEND("NA Broken authentication packet");
             return 1;
         }
@@ -252,8 +489,9 @@ try_again:
             if (strlen(buf) > 3)
                 plen = (strlen(buf) - 3) * 3 / 4;              /* we only need it here. Optimization */
             else
-                plen = NEGOTIATE_LENGTH;
-            if ((c = (char *) obtain_challenge((ntlm_negotiate *) decoded, plen)) != NULL ) {
+                plen = sizeof(ntlmhdr) + sizeof u_int32_t); /* local_nego only has header and flags set. */
+            debug("attempting SSPI challenge retrieval\n");
+            if ((c = (char *) SSP_MakeChallenge((ntlm_negotiate *) decoded, plen)) != NULL ) {
                 if (NTLM_packet_debug_enabled) {
                     printf("TT %s\n",c);
                     decoded = base64_decode(c);
@@ -270,8 +508,7 @@ try_again:
             return 1;
             /* notreached */
         case NTLM_CHALLENGE:
-            SEND
-            ("NA Got a challenge. We refuse to have our authority disputed");
+            SEND("NA Got a challenge. We refuse to have our authority disputed");
             return 1;
             /* notreached */
         case NTLM_AUTHENTICATE:
@@ -303,7 +540,7 @@ try_again:
         fast_header = (struct _ntlmhdr *) decoded;
 
         /* sanity-check: it IS a NTLMSSP packet, isn't it? */
-        if (memcmp(fast_header->signature, "NTLMSSP", 8) != 0) {
+        if (ntlm_validate_packet(fast_header, NTLM_ANY) != NTLM_ERR_NONE) {
             SEND("NA Broken authentication packet");
             return 1;
         }
@@ -320,13 +557,15 @@ try_again:
         case NTLM_AUTHENTICATE:
             /* check against SSPI */
             plen = (strlen(buf) - 3) * 3 / 4;          /* we only need it here. Optimization */
-            cred = ntlm_check_auth((ntlm_authenticate *) decoded, plen);
+            err = ntlm_check_auth((ntlm_authenticate *) decoded, user, domain, plen);
             have_challenge = 0;
-            if (cred == NULL) {
+            if (err != NTLM_ERR_NONE) {
 #if FAIL_DEBUG
                 fail_debug_enabled =1;
 #endif
                 switch (ntlm_errno) {
+                case NTLM_ERR_NONE:
+                    break;
                 case NTLM_BAD_NTGROUP:
                     SEND("NA Incorrect Group Membership");
                     return 1;
@@ -356,8 +595,8 @@ try_again:
                     return 1;
                 }
             }
-            lc(cred);          /* let's lowercase them for our convenience */
-            SEND2("AF %s", cred);
+            /* let's lowercase them for our convenience */
+            SEND3("AF %s\\%s", lc(domain), lc(user));
             return 1;
         default:
             helperfail("unknown authentication packet type");
diff --git a/helpers/ntlm_auth/mswin_sspi/Makefile.am b/helpers/ntlm_auth/mswin_sspi/Makefile.am
deleted file mode 100644 (file)
index 86c0adf..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-include $(top_srcdir)/src/Common.am
-
-libexec_PROGRAMS = mswin_ntlm_auth
-
-mswin_ntlm_auth_SOURCES = libntlmssp.c ntlm_auth.c ntlm.h
-
-## we need our local files too (but avoid -I. at all costs)
-INCLUDES += -I$(srcdir)
-
-LDADD = \
-       $(top_builddir)/compat/libcompat.la \
-       -L$(top_builddir)/lib -lmiscutil -lntlmauth \
-       -lsspwin32 \
-       -lnetapi32 \
-       -ladvapi32 \
-       $(XTRA_LIBS)
-
-EXTRA_DIST = readme.txt config.test
diff --git a/helpers/ntlm_auth/mswin_sspi/libntlmssp.c b/helpers/ntlm_auth/mswin_sspi/libntlmssp.c
deleted file mode 100644 (file)
index 1d3fded..0000000
+++ /dev/null
@@ -1,382 +0,0 @@
-/*
- * (C) 2002,2005 Guido Serassio <guido.serassio@acmeconsulting.it>
- * Based on previous work of Francesco Chemolli and Robert Collins
- * Distributed freely under the terms of the GNU General Public License,
- * version 2. See the file COPYING for licensing details
- *
- * 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, USA.
- */
-
-typedef unsigned char uchar;
-
-#include "util.h"
-#include "ntlm.h"
-#if HAVE_CTYPE_H
-#include <ctype.h>
-#endif
-#include <lm.h>
-#include <ntsecapi.h>
-
-/* returns 1 on success, 0 on failure */
-int
-Valid_Group(char *UserName, char *Group)
-{
-    int result = FALSE;
-    WCHAR wszUserName[UNLEN+1];        // Unicode user name
-    WCHAR wszGroup[GNLEN+1];   // Unicode Group
-
-    LPLOCALGROUP_USERS_INFO_0 pBuf = NULL;
-    LPLOCALGROUP_USERS_INFO_0 pTmpBuf;
-    DWORD dwLevel = 0;
-    DWORD dwFlags = LG_INCLUDE_INDIRECT;
-    DWORD dwPrefMaxLen = -1;
-    DWORD dwEntriesRead = 0;
-    DWORD dwTotalEntries = 0;
-    NET_API_STATUS nStatus;
-    DWORD i;
-    DWORD dwTotalCount = 0;
-
-    /* Convert ANSI User Name and Group to Unicode */
-
-    MultiByteToWideChar(CP_ACP, 0, UserName,
-                        strlen(UserName) + 1, wszUserName,
-                        sizeof(wszUserName) / sizeof(wszUserName[0]));
-    MultiByteToWideChar(CP_ACP, 0, Group,
-                        strlen(Group) + 1, wszGroup, sizeof(wszGroup) / sizeof(wszGroup[0]));
-
-    /*
-     * Call the NetUserGetLocalGroups function
-     * specifying information level 0.
-     *
-     * The LG_INCLUDE_INDIRECT flag specifies that the
-     * function should also return the names of the local
-     * groups in which the user is indirectly a member.
-     */
-    nStatus = NetUserGetLocalGroups(NULL,
-                                    wszUserName,
-                                    dwLevel,
-                                    dwFlags,
-                                    (LPBYTE *) & pBuf, dwPrefMaxLen, &dwEntriesRead, &dwTotalEntries);
-    /*
-     * If the call succeeds,
-     */
-    if (nStatus == NERR_Success) {
-        if ((pTmpBuf = pBuf) != NULL) {
-            for (i = 0; i < dwEntriesRead; i++) {
-                if (pTmpBuf == NULL) {
-                    result = FALSE;
-                    break;
-                }
-                if (wcscmp(pTmpBuf->lgrui0_name, wszGroup) == 0) {
-                    result = TRUE;
-                    break;
-                }
-                pTmpBuf++;
-                dwTotalCount++;
-            }
-        }
-    } else
-        result = FALSE;
-    /*
-     * Free the allocated memory.
-     */
-    if (pBuf != NULL)
-        NetApiBufferFree(pBuf);
-    return result;
-}
-
-
-char * AllocStrFromLSAStr(LSA_UNICODE_STRING LsaStr)
-{
-    size_t len;
-    static char * target;
-
-    len = LsaStr.Length/sizeof(WCHAR) + 1;
-
-    /* allocate buffer for str + null termination */
-    safe_free(target);
-    target = (char *)xmalloc(len);
-    if (target == NULL)
-        return NULL;
-
-    /* copy unicode buffer */
-    WideCharToMultiByte(CP_ACP, 0, LsaStr.Buffer, LsaStr.Length, target, len, NULL, NULL );
-
-    /* add null termination */
-    target[len-1] = '\0';
-    return target;
-}
-
-
-char * GetDomainName(void)
-
-{
-    LSA_HANDLE PolicyHandle;
-    LSA_OBJECT_ATTRIBUTES ObjectAttributes;
-    NTSTATUS status;
-    PPOLICY_PRIMARY_DOMAIN_INFO ppdiDomainInfo;
-    PWKSTA_INFO_100 pwkiWorkstationInfo;
-    DWORD netret;
-    char * DomainName = NULL;
-
-    /*
-     * Always initialize the object attributes to all zeroes.
-     */
-    memset(&ObjectAttributes, '\0', sizeof(ObjectAttributes));
-
-    /*
-     * You need the local workstation name. Use NetWkstaGetInfo at level
-     * 100 to retrieve a WKSTA_INFO_100 structure.
-     *
-     * The wki100_computername field contains a pointer to a UNICODE
-     * string containing the local computer name.
-     */
-    netret = NetWkstaGetInfo(NULL, 100, (LPBYTE *)&pwkiWorkstationInfo);
-    if (netret == NERR_Success) {
-        /*
-         * We have the workstation name in:
-         * pwkiWorkstationInfo->wki100_computername
-         *
-         * Next, open the policy object for the local system using
-         * the LsaOpenPolicy function.
-         */
-        status = LsaOpenPolicy(
-                     NULL,
-                     &ObjectAttributes,
-                     GENERIC_READ | POLICY_VIEW_LOCAL_INFORMATION,
-                     &PolicyHandle
-                 );
-
-        /*
-         * Error checking.
-         */
-        if (status) {
-            debug("OpenPolicy Error: %ld\n", status);
-        } else {
-
-            /*
-             * You have a handle to the policy object. Now, get the
-             * domain information using LsaQueryInformationPolicy.
-             */
-            status = LsaQueryInformationPolicy(PolicyHandle,
-                                               PolicyPrimaryDomainInformation,
-                                               (void **)&ppdiDomainInfo);
-            if (status) {
-                debug("LsaQueryInformationPolicy Error: %ld\n", status);
-            } else  {
-
-                /* Get name in useable format */
-                DomainName = AllocStrFromLSAStr(ppdiDomainInfo->Name);
-
-                /*
-                 * Check the Sid pointer, if it is null, the
-                 * workstation is either a stand-alone computer
-                 * or a member of a workgroup.
-                 */
-                if (ppdiDomainInfo->Sid) {
-
-                    /*
-                     * Member of a domain. Display it in debug mode.
-                     */
-                    debug("Member of Domain %s\n",DomainName);
-                } else {
-                    DomainName = NULL;
-                }
-            }
-        }
-
-        /*
-         * Clean up all the memory buffers created by the LSA and
-         * Net* APIs.
-         */
-        NetApiBufferFree(pwkiWorkstationInfo);
-        LsaFreeMemory((LPVOID)ppdiDomainInfo);
-    } else
-        debug("NetWkstaGetInfo Error: %ld\n", netret);
-    return DomainName;
-}
-
-
-int ntlm_errno;
-
-
-/* returns NULL on failure, or a pointer to
- * the user's credentials (domain\\username)
- * upon success. WARNING. It's pointing to static storage.
- * In case of problem sets as side-effect ntlm_errno to one of the
- * codes defined in ntlm.h
- */
-char *
-ntlm_check_auth(ntlm_authenticate * auth, int auth_length)
-{
-    int rv;
-    char domain[DNLEN+1];
-    char user[UNLEN+1];
-    static char credentials[DNLEN+UNLEN+2];    /* we can afford to waste */
-
-    lstring tmp;
-
-    if (!NTLM_LocalCall) {
-
-        tmp = ntlm_fetch_string((char *) auth, auth_length, &auth->domain);
-
-        if (tmp.str == NULL || tmp.l == 0) {
-            debug("No domain supplied. Returning no-auth\n");
-            ntlm_errno = NTLM_BAD_REQUEST;
-            return NULL;
-        }
-        if (Use_Unicode) {
-            /* copy unicode buffer */
-            WideCharToMultiByte(CP_ACP, 0, (LPCWSTR) tmp.str, tmp.l, domain, DNLEN, NULL, NULL );
-            /* add null termination */
-            domain[tmp.l / sizeof(WCHAR)] = '\0';
-        } else {
-            if (tmp.l > DNLEN) {
-                debug("Domain string exceeds %d bytes, rejecting\n", DNLEN);
-                ntlm_errno = NTLM_BAD_REQUEST;
-                return NULL;
-            }
-            memcpy(domain, tmp.str, tmp.l);
-            domain[tmp.l] = '\0';
-        }
-        tmp = ntlm_fetch_string((char *) auth, auth_length, &auth->user);
-        if (tmp.str == NULL || tmp.l == 0) {
-            debug("No username supplied. Returning no-auth\n");
-            ntlm_errno = NTLM_BAD_REQUEST;
-            return NULL;
-        }
-        if (Use_Unicode) {
-            /* copy unicode buffer */
-            WideCharToMultiByte(CP_ACP, 0, (LPCWSTR) tmp.str, tmp.l, user, UNLEN, NULL, NULL );
-            /* add null termination */
-            user[tmp.l / sizeof(WCHAR)] = '\0';
-        } else {
-            if (tmp.l > UNLEN) {
-                debug("Username string exceeds %d bytes, rejecting\n", UNLEN);
-                ntlm_errno = NTLM_BAD_REQUEST;
-                return NULL;
-            }
-            memcpy(user, tmp.str, tmp.l);
-            user[tmp.l] = '\0';
-        }
-        debug("checking domain: '%s', user: '%s'\n", domain, user);
-
-    } else
-        debug("checking local user\n");
-
-    rv = SSP_ValidateNTLMCredentials(auth, auth_length, credentials);
-
-    debug("Login attempt had result %d\n", rv);
-
-    if (!rv) {                 /* failed */
-        ntlm_errno = NTLM_SSPI_ERROR;
-        return NULL;
-    }
-
-    if (UseAllowedGroup) {
-        if (!Valid_Group(credentials, NTAllowedGroup)) {
-            ntlm_errno = NTLM_BAD_NTGROUP;
-            debug("User %s not in allowed Group %s\n", credentials, NTAllowedGroup);
-            return NULL;
-        }
-    }
-    if (UseDisallowedGroup) {
-        if (Valid_Group(credentials, NTDisAllowedGroup)) {
-            ntlm_errno = NTLM_BAD_NTGROUP;
-            debug("User %s is in denied Group %s\n", credentials, NTDisAllowedGroup);
-            return NULL;
-        }
-    }
-
-    debug("credentials: %s\n", credentials);
-    return credentials;
-}
-
-
-const char *
-ntlm_make_negotiate(void)
-{
-    ntlm_negotiate ne;
-    const char *encoded;
-    memset(&ne, 0, sizeof(ntlm_negotiate));    /* reset */
-    memcpy(ne.signature, "NTLMSSP", 8);                /* set the signature */
-    ne.type = le32toh(NTLM_NEGOTIATE); /* this is a challenge */
-    ne.flags = le32toh(
-                   NEGOTIATE_ALWAYS_SIGN |
-                   NEGOTIATE_USE_NTLM |
-                   NEGOTIATE_USE_LM |
-                   NEGOTIATE_ASCII |
-                   0
-               );
-    encoded = base64_encode_bin((char *) &ne, NEGOTIATE_LENGTH);
-    debug("Negotiate packet not supplied - self generated\n");
-    return encoded;
-}
-
-
-void hex_dump(void *data, int size)
-{
-    /* dumps size bytes of *data to stdout. Looks like:
-     * [0000] 75 6E 6B 6E 6F 77 6E 20
-     *                  30 FF 00 00 00 00 39 00 unknown 0.....9.
-     * (in a single line of course)
-     */
-
-    if (!data)
-        return;
-
-    if (debug_enabled) {
-        unsigned char *p = data;
-        unsigned char c;
-        int n;
-        char bytestr[4] = {0};
-        char addrstr[10] = {0};
-        char hexstr[ 16*3 + 5] = {0};
-        char charstr[16*1 + 5] = {0};
-        for (n=1; n<=size; n++) {
-            if (n%16 == 1) {
-                /* store address for this line */
-                snprintf(addrstr, sizeof(addrstr), "%.4x",
-                         ((unsigned int)p-(unsigned int)data) );
-            }
-
-            c = *p;
-            if (xisalnum(c) == 0) {
-                c = '.';
-            }
-
-            /* store hex str (for left side) */
-            snprintf(bytestr, sizeof(bytestr), "%02X ", *p);
-            strncat(hexstr, bytestr, sizeof(hexstr)-strlen(hexstr)-1);
-
-            /* store char str (for right side) */
-            snprintf(bytestr, sizeof(bytestr), "%c", c);
-            strncat(charstr, bytestr, sizeof(charstr)-strlen(charstr)-1);
-
-            if (n%16 == 0) {
-                /* line completed */
-                fprintf(stderr, "[%4.4s]   %-50.50s  %s\n", addrstr, hexstr, charstr);
-                hexstr[0] = 0;
-                charstr[0] = 0;
-            } else if (n%8 == 0) {
-                /* half line: add whitespaces */
-                strncat(hexstr, "  ", sizeof(hexstr)-strlen(hexstr)-1);
-                strncat(charstr, " ", sizeof(charstr)-strlen(charstr)-1);
-            }
-            p++; /* next byte */
-        }
-
-        if (strlen(hexstr) > 0) {
-            /* print rest of buffer if not empty */
-            fprintf(stderr, "[%4.4s]   %-50.50s  %s\n", addrstr, hexstr, charstr);
-        }
-    }
-}
-
diff --git a/helpers/ntlm_auth/mswin_sspi/ntlm.h b/helpers/ntlm_auth/mswin_sspi/ntlm.h
deleted file mode 100644 (file)
index 6433ab4..0000000
+++ /dev/null
@@ -1,119 +0,0 @@
-/*
- * (C) 2002,2005 Guido Serassio <guido.serassio@acmeconsulting.it>
- * Based on previous work of Francesco Chemolli, Robert Collins and Andrew Doran
- *
- * Distributed freely under the terms of the GNU General Public License,
- * version 2. See the file COPYING for licensing details
- *
- * 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, USA.
- */
-
-#ifndef _NTLM_H_
-#define _NTLM_H_
-
-#include "sspwin32.h"
-#include <windows.h>
-#include <sspi.h>
-#include <security.h>
-#include "ntlmauth.h"
-#undef debug
-
-/************* CONFIGURATION ***************/
-/*
- * define this if you want debugging
- */
-#ifndef DEBUG
-#define DEBUG
-#endif
-
-#define FAIL_DEBUG 0
-
-/************* END CONFIGURATION ***************/
-
-#include <sys/types.h>
-
-extern int debug_enabled;
-#if FAIL_DEBUG
-extern int fail_debug_enabled;
-#endif
-
-/* Debugging stuff */
-
-#ifdef __GNUC__                        /* this is really a gcc-ism */
-#ifdef DEBUG
-#include <stdio.h>
-#include <unistd.h>
-static char *__foo;
-#define debug(X...) if (debug_enabled) { \
-                    fprintf(stderr,"ntlm-auth[%d](%s:%d): ", getpid(), \
-                    ((__foo=strrchr(__FILE__,'/'))==NULL?__FILE__:__foo+1),\
-                    __LINE__);\
-                    fprintf(stderr,X); }
-#else /* DEBUG */
-#define debug(X...)            /* */
-#endif /* DEBUG */
-#else /* __GNUC__ */
-static void
-debug(char *format,...)
-{
-#ifdef DEBUG
-#ifdef _SQUID_MSWIN_
-#if FAIL_DEBUG
-    if (debug_enabled || fail_debug_enabled) {
-#else
-if (debug_enabled) {
-#endif
-        va_list args;
-
-        va_start(args,format);
-        fprintf(stderr, "ntlm-auth[%d]: ",getpid());
-        vfprintf(stderr, format, args);
-        va_end(args);
-#if FAIL_DEBUG
-        fail_debug_enabled = 0;
-#endif
-    }
-#endif /* _SQUID_MSWIN_ */
-#endif /* DEBUG */
-}
-#endif /* __GNUC__ */
-
-
-/* A couple of harmless helper macros */
-#define SEND(X) debug("sending '%s' to squid\n",X); printf(X "\n");
-#ifdef __GNUC__
-#define SEND2(X,Y...) debug("sending '" X "' to squid\n",Y); printf(X "\n",Y);
-#else
-/* no gcc, no debugging. varargs macros are a gcc extension */
-#define SEND2(X,Y) debug("sending '" X "' to squid\n",Y); printf(X "\n",Y);
-#endif
-
-extern char * NTAllowedGroup;
-extern char * NTDisAllowedGroup;
-extern int UseDisallowedGroup;
-extern int UseAllowedGroup;
-extern int ntlm_errno;
-
-#define NTLM_NO_ERROR 0
-#define NTLM_SSPI_ERROR 1
-#define NTLM_BAD_NTGROUP 2
-#define NTLM_BAD_REQUEST 3
-
-#define NEGOTIATE_LENGTH 16
-
-extern void uc(char *);
-
-extern const char * ntlm_make_negotiate(void);
-extern char *ntlm_check_auth(ntlm_authenticate * auth, int auth_length);
-extern void hex_dump(void *, int);
-
-#define safe_free(x)   if (x) { free(x); x = NULL; }
-
-#endif /* _NTLM_H_ */
diff --git a/helpers/ntlm_auth/mswin_sspi/readme.txt b/helpers/ntlm_auth/mswin_sspi/readme.txt
deleted file mode 100644 (file)
index 3267333..0000000
+++ /dev/null
@@ -1,52 +0,0 @@
-mswin_ntlm_auth.exe
-
-Native Windows NTLM/NTLMv2 authenticator for Squid with
-automatic support for NTLM NEGOTIATE packets.
-
-=====
-Usage
-=====
-
-mswin_ntlm_auth [-d] [-v] [-A|D LocalUserGroup] [-h]
-
--d enables debugging.
--v enables verbose NTLM packet debugging.
--A specify a Windows Local Group name allowed to authenticate.
--D specify a Windows Local Group name not allowed to authenticate.
--h print program usage
-
-This is released under the GNU General Public License
-
-==============
-Allowing Users
-==============
-
-Users that are allowed to access the web proxy must have the Windows NT
-User Rights "logon from the network".
-Optionally the authenticator can verify the NT LOCAL group membership of 
-the user against the User Group specified in the Authenticator's command
-line. 
-This can be accomplished creating a local user group on the NT machine,
-grant the privilege, and adding users to it, it works only with MACHINE
-Local Groups, not Domain Local Groups.
-Better group checking is available with External Acl, see mswin_check_group
-documentation.
-
-Squid.conf typical minimal required changes:
-
-auth_param ntlm program c:/squid/libexec/mswin_ntlm_auth.exe
-auth_param ntlm children 5
-
-acl password proxy_auth REQUIRED
-
-http_access allow password
-http_access deny all
-
-Refer to Squid documentation for more details.
-
-Currently Internet Explorer has some problems with ftp:// URLs when handling
-internal Squid FTP icons. The following squid.conf ACL works around this:
-
-acl internal_icons urlpath_regex -i /squid-internal-static/icons/
-
-http_access allow our_networks internal_icons <== BEFORE authentication ACL !!!