]> git.ipfire.org Git - thirdparty/squid.git/commitdiff
Revert "Remove basic_smb_lm_auth helper" (#2013)
authorFrancesco Chemolli <5175948+kinkie@users.noreply.github.com>
Sun, 9 Mar 2025 09:06:31 +0000 (09:06 +0000)
committerSquid Anubis <squid-anubis@squid-cache.org>
Mon, 10 Mar 2025 03:15:47 +0000 (03:15 +0000)
Commit f53a024a40 contained spurious changes. Revert the change

17 files changed:
configure.ac
doc/release-notes/release-8.sgml.in
src/auth/basic/Makefile.am
src/auth/basic/SMB_LM/Makefile.am [new file with mode: 0644]
src/auth/basic/SMB_LM/README.html [new file with mode: 0644]
src/auth/basic/SMB_LM/msntauth-v2.0.lsm [new file with mode: 0644]
src/auth/basic/SMB_LM/msntauth.cc [new file with mode: 0644]
src/auth/basic/SMB_LM/msntauth.h [new file with mode: 0644]
src/auth/basic/SMB_LM/required.m4 [new file with mode: 0755]
src/auth/basic/SMB_LM/valid.cc [new file with mode: 0644]
src/auth/basic/SMB_LM/valid.h [new file with mode: 0644]
src/auth/basic/helpers.m4
src/auth/ntlm/Makefile.am
src/auth/ntlm/SMB_LM/Makefile.am [new file with mode: 0644]
src/auth/ntlm/SMB_LM/ntlm_smb_lm_auth.cc [new file with mode: 0644]
src/auth/ntlm/SMB_LM/required.m4 [new file with mode: 0755]
src/auth/ntlm/helpers.m4

index c63f92f3e9d589d03d4df62ca1e5a0a305b8e8b0..5d1568810f963b0508fec8b4d011549b5f94e02c 100644 (file)
@@ -2536,6 +2536,7 @@ AC_CONFIG_FILES([
        src/auth/basic/RADIUS/Makefile
        src/auth/basic/SASL/Makefile
        src/auth/basic/SMB/Makefile
+       src/auth/basic/SMB_LM/Makefile
        src/auth/basic/SSPI/Makefile
        src/auth/digest/Makefile
        src/auth/digest/eDirectory/Makefile
@@ -2547,6 +2548,7 @@ AC_CONFIG_FILES([
        src/auth/negotiate/wrapper/Makefile
        src/auth/ntlm/Makefile
        src/auth/ntlm/fake/Makefile
+       src/auth/ntlm/SMB_LM/Makefile
        src/auth/ntlm/SSPI/Makefile
        src/base/Makefile
        src/clients/Makefile
index ec0052630c1ab1aa6fb11702506d24211b38a0b2..a8586c7c52938af3c1bc587534838c6ed9d35cca 100644 (file)
@@ -36,9 +36,6 @@ The Squid-@SQUID_RELEASE@ change history can be <url url="https://github.com/squ
 <sect1>Helper changes
 <p>
 <descrip>
-       <p>Removed <em>basic_smb_lm_auth</em> NTLM authentication helper.
-          Use the <em>ntlm_auth</em> helper from the Samba project instead.
-
        <p>Removed <em>ext_lm_group_acl</em> external acl helper. No product
           currently on the market suports the LanManager protocol
           in their default configuration.
@@ -102,10 +99,6 @@ This section gives an account of those changes in three categories:
 <sect1>Changes to existing options<label id="modifiedoptions">
 <p>
 <descrip>
-       <tag>--enable-auth-basic=</tag>
-       <p>Removed <em>SMB_LM</em> helper, in favour of the <em>ntlm_auth</em>
-          alternative offered by the Samba project.
-
        <tag>--enable-external-acl-helpers=</tag>
        <p>Removed <em>LM_Group</em> helper. The LM protocol is
           insecure and no longer supported on the market since 2008.
index f004532b585d58859eca0f143dcf5c6ad0e10e6f..54bdc47588b03e323fd140d8b0c4c6ff101671a2 100644 (file)
@@ -19,6 +19,7 @@ DIST_SUBDIRS = \
         RADIUS \
         SASL \
         SMB \
+        SMB_LM \
         SSPI
 
 SUBDIRS = $(BASIC_AUTH_HELPERS)
diff --git a/src/auth/basic/SMB_LM/Makefile.am b/src/auth/basic/SMB_LM/Makefile.am
new file mode 100644 (file)
index 0000000..991ccbf
--- /dev/null
@@ -0,0 +1,27 @@
+## Copyright (C) 1996-2023 The Squid Software Foundation and contributors
+##
+## Squid software is distributed under GPLv2+ license and includes
+## contributions from numerous individuals and organizations.
+## Please see the COPYING and CONTRIBUTORS files for details.
+##
+
+include $(top_srcdir)/src/Common.am
+
+libexec_PROGRAMS= basic_smb_lm_auth
+
+basic_smb_lm_auth_SOURCES = \
+       msntauth.cc \
+       msntauth.h \
+       valid.cc \
+       valid.h
+basic_smb_lm_auth_LDADD= \
+       $(top_builddir)/lib/smblib/libsmblib.la \
+       $(top_builddir)/lib/rfcnb/librfcnb.la \
+       $(top_builddir)/lib/libmiscencoding.la \
+       $(COMPAT_LIB) \
+       $(XTRA_LIBS)
+
+EXTRA_DIST= \
+       msntauth-v2.0.lsm \
+       README.html \
+       required.m4
diff --git a/src/auth/basic/SMB_LM/README.html b/src/auth/basic/SMB_LM/README.html
new file mode 100644 (file)
index 0000000..39aac64
--- /dev/null
@@ -0,0 +1,151 @@
+<HTML>
+<HEAD>
+<TITLE>MSNTAUTH readme</TITLE>
+</HEAD>
+<BODY BGCOLOR="#FFFFFF">
+
+<!--
+If you require this document in text form, download the
+HTML-text package from http://members.tripod.com/stellarx.
+-->
+
+<H1>
+MSNT Auth v3.0.0<BR>
+Squid web proxy NT authentication module<BR>
+Modified by the Squid HTTP Proxy team<BR>
+Original release by Antonino Iannella, Stellar-X Pty Ltd<BR>
+</H1>
+
+<H2>Contents</H2>
+
+<UL>
+<LI> <A HREF="#introduction">Introduction</A>
+<LI> <A HREF="#installation">Installation</A>
+<LI> <A HREF="#configuration">Configuration</A>
+<LI> <A HREF="#squid">Squid.conf changes</A>
+<LI> <A HREF="#testing">Testing</A>
+<LI> <A HREF="#contact">Support details</A>
+</UL>
+
+<A NAME="introduction"><H2>Introduction</H2>
+
+<P>
+This is an authentication module for the Squid proxy server
+to use an NT domain server.
+
+<P>
+It originates from the Samba and SMB packages by Andrew Tridgell
+and Richard Sharpe. It is sourced from the Pike
+authentication module by William Welliver (hwellive@intersil.com),
+and the SMB 1.0.1 libraries.
+Releases up to version 2.0.3 were created by Antonino Iannella
+(antonino@rager.com.au, http://stellarx.tripod.com).
+The module is now distributed with Squid, and is maintained by the
+Squid proxy team as an Open Source effort.
+Msntauth is released under the GNU General Public License.
+
+<P>
+<i>basic_msnt_auth</i> follows the standard Squid basic authentication helper protocol.
+See <a href="https://wiki.squid-cache.org/Features/AddonHelpers#basic-scheme"
+>https://wiki.squid-cache.org/Features/AddonHelpers#basic-scheme</a> for details.
+Problems are logged to syslog.
+
+<P>
+Msntauth works in environments with NT domain controllers on
+Windows (TM) NT 4, 2000, and Samba. It only uses the ancient <i>Lanman</i> protocol,
+the authenticating systems must be configured to accept it.
+
+<A NAME="installation"><H2>Installation</H2>
+
+<P>
+Msntauth will be compiled when you compile Squid, using
+their autoconf system.
+Refer to Squid documentation for details.
+If the build is suitable, you can skip this section.
+
+<A NAME="configuration"><H2>Configuration</H2>
+
+<P>
+As of version 3.0.0, a configuration file is no longer needed.
+The specification of the domains and domain controllers to use is
+passed as a list of arguments on the command line.
+
+The syntax is:
+<PRE>
+basic_msnt_auth domain1/domaincontroller1 [domain2/domaincontroller2 ...]
+</PRE>
+An arbitrary number of domain controllers can be specified, for any number of daomains.
+Domain controllers will be attempted in the same order they are configured, until
+any of them successfully authenticates the user passed by squid. If all domain
+controllers fail to authenticate the user, then access is denied.
+Domain controllers can be specified by their NetBios name.
+
+<P>
+<B>WARNING!</B> this means that a wrong password will be attempted a number of times.
+Watch out for domain lock-out policies!
+
+<A NAME="squid"><H2>Squid.conf changes</H2>
+
+<P>
+Refer to Squid documentation for the required changes to squid.conf.
+You will need to set the following lines to enable authentication for
+your access list -
+
+<PRE>
+  acl <I>yourACL</I> proxy_auth REQUIRED
+  http_access allow password
+  http_access allow <I>yourACL</I>
+  http_access deny all
+</PRE>
+
+<P>
+You will also need to review the following directives. The number of
+msntauth children spawned is set with authenticate_children.
+The number of children needed is site-dependent, so some
+experimentation may be required to find the best number.
+There should be no visible delay in performance with Squid once
+msntauth is in use.
+
+Please see <A href="http://www.squid-cache.org/Doc/config/auth_param/"
+>http://www.squid-cache.org/Doc/config/auth_param/</A> or your <TT>squid.conf.default</TT>
+file to check how to configure squid to make use of this helper.
+
+<A NAME="testing"><H2>Testing</H2>
+
+<P>
+I strongly urge that Msntauth is tested prior to being used in a
+production environment. It may behave differently on different platforms.
+To test it, run it from the command line, and enter username and password
+pairs separated by a space.
+
+<P>
+It should behave in the following way -
+<PRE>
+ - Press ENTER to get an OK or ERR message.
+ - Make sure pressing CTRL-D behaves the same as a carriage return.
+ - Make sure pressing CTRL-C aborts the program.
+ - Test that entering no details does not result in an OK or ERR message.
+ - Test that entering an invalid username and password results in
+   an ERR message. Note that if NT guest user access is allowed on
+   the PDC, an OK message may be returned instead of ERR.
+ - Test that entering an valid username and password results in an OK message.
+   Try usernames which are and aren't in the denied/allowed user files,
+   if they're in use.
+ - Test that entering a guest username and password returns the correct response.
+</PRE>
+
+<P>
+If the above didn't work as expected, you may need to modify the main()
+function in msntauth.c. Inform the Squid maintainers of any problems.
+
+<P>
+Usernames and passwords are expected to be URL-encoded (see RFC 1738 for details)
+
+<A NAME="contact"><H2>Support details</H2>
+
+<P>
+Refer to the Squid website at http://www.squid-cache.org.
+You can submit problems or fixes using the Squid project's Bugzilla database.
+
+</BODY>
+</HTML>
diff --git a/src/auth/basic/SMB_LM/msntauth-v2.0.lsm b/src/auth/basic/SMB_LM/msntauth-v2.0.lsm
new file mode 100644 (file)
index 0000000..91f2445
--- /dev/null
@@ -0,0 +1,13 @@
+Begin3
+Title:         msntauth
+Version:       2.0
+Entered-date:  01SEP01
+Description:   Squid web proxy NT domain authentication module
+Keywords:      Squid WWW proxy SMB NT domain authentication module source
+Author:         antonino@rager.com.au (Antonino Iannella)
+Maintained-by:  antonino@rager.com.au (Antonino Iannella)
+Primary-site:   sunsite.unc.edu /pub/Linux/system/network/misc
+               msntauth-v2.0.tgz
+Original-site:  http://members.tripod.com/stellarx
+Copying-policy: GPL
+End
diff --git a/src/auth/basic/SMB_LM/msntauth.cc b/src/auth/basic/SMB_LM/msntauth.cc
new file mode 100644 (file)
index 0000000..dafb01d
--- /dev/null
@@ -0,0 +1,167 @@
+/*
+ * Copyright (C) 1996-2023 The Squid Software Foundation and contributors
+ *
+ * Squid software is distributed under GPLv2+ license and includes
+ * contributions from numerous individuals and organizations.
+ * Please see the COPYING and CONTRIBUTORS files for details.
+ */
+
+/*
+ * MSNT - Microsoft Windows NT domain squid authenticator module
+ * Version 2.0 by Stellar-X Pty Ltd, Antonino Iannella
+ * Sun Sep  2 14:39:53 CST 2001
+ *
+ * Modified to act as a Squid authenticator module.
+ * Removed all Pike stuff.
+ * Returns OK for a successful authentication, or ERR upon error.
+ *
+ * Uses code from -
+ * Andrew Tridgell 1997
+ * Richard Sharpe 1996
+ * Bill Welliver 1999
+ * Duane Wessels 2000 (wessels@squid-cache.org)
+ *
+ * Released under GNU Public License
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include "squid.h"
+#include "rfc1738.h"
+#include "util.h"
+
+#include <csignal>
+#include <cstring>
+#include <iostream>
+#include <string>
+#include <vector>
+#include <syslog.h>
+
+#include "auth/basic/SMB_LM/msntauth.h"
+#include "auth/basic/SMB_LM/valid.h"
+
+static char msntauth_version[] = "Msntauth v3.0.0 (C) 2 Sep 2001 Stellar-X Antonino Iannella.\nModified by the Squid HTTP Proxy team 2002-2014";
+
+struct domaincontroller {
+    std::string domain;
+    std::string server;
+};
+typedef std::vector<domaincontroller> domaincontrollers_t;
+domaincontrollers_t domaincontrollers;
+
+static bool
+validate_user(char *username, char *password)
+{
+    for (domaincontrollers_t::iterator dc = domaincontrollers.begin(); dc != domaincontrollers.end(); ++dc) {
+        //std::cerr << "testing against " << dc->server << std::endl;
+        const int rv = Valid_User(username, password, dc->server.c_str(), nullptr, dc->domain.c_str());
+        //std::cerr << "check result: " << rv << std::endl;
+        if (rv == NTV_NO_ERROR)
+            return true;
+    }
+    return false;
+}
+
+static char instructions[] = "Usage instructions: basic_nsnt_auth <domainname>/<domaincontroller> [<domainname>/<domaincontroller> ...]";
+static void
+display_usage_instructions()
+{
+    using std::endl;
+    std::cerr << msntauth_version << endl << instructions << endl << endl;
+}
+
+// arguments: domain/server_name [domain/server_name ...]
+int
+main(int argc, char **argv)
+{
+    char username[256];
+    char password[256];
+    char wstr[256];
+    int err = 0;
+
+    openlog("basic_smb_lm_auth", LOG_PID, LOG_USER);
+    setbuf(stdout, nullptr);
+
+    for (int j = 1; j < argc; ++j) {
+        std::string arg = argv[j];
+        size_t pos=arg.find('/');
+        if (arg.find('/',pos+1) != std::string::npos) {
+            std::cerr << "Error: can't understand domain controller specification '"
+                      << arg << "'. Ignoring" << std::endl;
+        }
+        domaincontroller dc;
+        dc.domain = arg.substr(0,pos);
+        dc.server = arg.substr(pos+1);
+        if (dc.domain.length() == 0 || dc.server.length() == 0) {
+            std::cerr << "Error: invalid domain specification in '" << arg <<
+                      "'. Ignoring." << std::endl;
+            exit(EXIT_FAILURE);
+        }
+        domaincontrollers.push_back(dc);
+    }
+    if (domaincontrollers.empty()) {
+        display_usage_instructions();
+        std::cerr << "Error: no domain controllers specified" << std::endl;
+        exit(EXIT_FAILURE);
+    }
+
+    while (1) {
+        int n;
+        /* Read whole line from standard input. Terminate on break. */
+        memset(wstr, '\0', sizeof(wstr));
+        if (fgets(wstr, 255, stdin) == NULL)
+            break;
+        /* ignore this line if we didn't get the end-of-line marker */
+        if (NULL == strchr(wstr, '\n')) {
+            err = 1;
+            continue;
+        }
+        if (err) {
+            syslog(LOG_WARNING, "oversized message");
+            puts("ERR");
+            err = 0;
+            continue;
+        }
+
+        /*
+         * extract username and password.
+         */
+        username[0] = '\0';
+        password[0] = '\0';
+        n = sscanf(wstr, "%s %[^\n]", username, password);
+        if (2 != n) {
+            puts("ERR");
+            continue;
+        }
+        /* Check for invalid or blank entries */
+        if ((username[0] == '\0') || (password[0] == '\0')) {
+            puts("ERR");
+            continue;
+        }
+
+        rfc1738_unescape(username);
+        rfc1738_unescape(password);
+
+        if (validate_user(username, password)) {
+            puts("OK");
+        } else {
+            syslog(LOG_INFO, "'%s' login failed", username);
+            puts("ERR");
+        }
+        err = 0;
+    }
+
+    return EXIT_SUCCESS;
+}
+
diff --git a/src/auth/basic/SMB_LM/msntauth.h b/src/auth/basic/SMB_LM/msntauth.h
new file mode 100644 (file)
index 0000000..b4a496f
--- /dev/null
@@ -0,0 +1,16 @@
+/*
+ * Copyright (C) 1996-2023 The Squid Software Foundation and contributors
+ *
+ * Squid software is distributed under GPLv2+ license and includes
+ * contributions from numerous individuals and organizations.
+ * Please see the COPYING and CONTRIBUTORS files for details.
+ */
+
+#ifndef SQUID_SRC_AUTH_BASIC_SMB_LM_MSNTAUTH_H
+#define SQUID_SRC_AUTH_BASIC_SMB_LM_MSNTAUTH_H
+
+extern int QueryServers(char *, char *);
+extern void Check_forallowchange(void);
+
+#endif /* SQUID_SRC_AUTH_BASIC_SMB_LM_MSNTAUTH_H */
+
diff --git a/src/auth/basic/SMB_LM/required.m4 b/src/auth/basic/SMB_LM/required.m4
new file mode 100755 (executable)
index 0000000..30caa28
--- /dev/null
@@ -0,0 +1,14 @@
+## Copyright (C) 1996-2023 The Squid Software Foundation and contributors
+##
+## Squid software is distributed under GPLv2+ license and includes
+## contributions from numerous individuals and organizations.
+## Please see the COPYING and CONTRIBUTORS files for details.
+##
+
+# DONT build this helper on Windows
+# DONT build this helper by default
+AS_IF([test "x$auto_helpers" != "xyes"],[
+  BUILD_HELPER="SMB_LM"
+  AC_CHECK_HEADERS([w32api/windows.h windows.h],[BUILD_HELPER=""])
+  AS_IF([test "x$BUILD_HELPER" = "xSMB_LM"],[require_smblib="yes"])
+])
diff --git a/src/auth/basic/SMB_LM/valid.cc b/src/auth/basic/SMB_LM/valid.cc
new file mode 100644 (file)
index 0000000..1aaaea9
--- /dev/null
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 1996-2023 The Squid Software Foundation and contributors
+ *
+ * Squid software is distributed under GPLv2+ license and includes
+ * contributions from numerous individuals and organizations.
+ * Please see the COPYING and CONTRIBUTORS files for details.
+ */
+
+#include "squid.h"
+#include "auth/basic/SMB_LM/valid.h"
+#include "smblib/smblib.h"
+
+#if HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+#if HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#if HAVE_SYSLOG_H
+#include <syslog.h>
+#endif
+
+// BACKUP is unused
+int
+Valid_User(char *USERNAME, char *PASSWORD, const char *SERVER, char *, const char *DOMAIN)
+{
+    const char *supportedDialects[] = {"PC NETWORK PROGRAM 1.0",
+                                       "MICROSOFT NETWORKS 1.03",
+                                       "MICROSOFT NETWORKS 3.0",
+                                       "LANMAN1.0",
+                                       "LM1.2X002",
+                                       "Samba",
+                                       "NT LM 0.12",
+                                       "NT LANMAN 1.0",
+                                       NULL
+                                      };
+    SMB_Handle_Type con;
+
+    SMB_Init();
+    con = SMB_Connect_Server(nullptr, SERVER, DOMAIN);
+    if (con == NULL) {
+        return (NTV_SERVER_ERROR);
+    }
+    if (SMB_Negotiate(con, supportedDialects) < 0) {    /* An error */
+        SMB_Discon(con, 0);
+        return (NTV_PROTOCOL_ERROR);
+    }
+    if (SMB_Logon_Server(con, USERNAME, PASSWORD, nullptr, 0) < 0) {
+        SMB_Discon(con, 0);
+        return (NTV_LOGON_ERROR);
+    }
+    SMB_Discon(con, 0);
+    return (NTV_NO_ERROR);
+}
+
diff --git a/src/auth/basic/SMB_LM/valid.h b/src/auth/basic/SMB_LM/valid.h
new file mode 100644 (file)
index 0000000..bfdb009
--- /dev/null
@@ -0,0 +1,21 @@
+/*
+ * Copyright (C) 1996-2023 The Squid Software Foundation and contributors
+ *
+ * Squid software is distributed under GPLv2+ license and includes
+ * contributions from numerous individuals and organizations.
+ * Please see the COPYING and CONTRIBUTORS files for details.
+ */
+
+#ifndef SQUID_SRC_AUTH_BASIC_SMB_LM_VALID_H
+#define SQUID_SRC_AUTH_BASIC_SMB_LM_VALID_H
+/* SMB User verification function */
+
+#define NTV_NO_ERROR 0
+#define NTV_SERVER_ERROR 1
+#define NTV_PROTOCOL_ERROR 2
+#define NTV_LOGON_ERROR 3
+
+int Valid_User(char *USERNAME, char *PASSWORD, const char *SERVER, char *BACKUP, const char *DOMAIN);
+
+#endif /* SQUID_SRC_AUTH_BASIC_SMB_LM_VALID_H */
+
index df1585cfc33a03118070e83545b0d601da417947..8a1368973220be0bff19ad3adc4b3eb947159bb9 100644 (file)
@@ -18,6 +18,7 @@ AS_IF([test "x$enable_auth" != "xno"],[
     SQUID_CHECK_HELPER([RADIUS],[auth/basic])
     SQUID_CHECK_HELPER([SASL],[auth/basic])
     SQUID_CHECK_HELPER([SMB],[auth/basic])
+    SQUID_CHECK_HELPER([SMB_LM],[auth/basic])
     SQUID_CHECK_HELPER([SSPI],[auth/basic])
     SQUID_CHECK_HELPER([fake],[auth/basic])
     SQUID_CHECK_HELPER([getpwnam],[auth/basic])
index 9a11b6125db510d3c64ce6ccf95eabc5c646b0af..b8896fc684ce6727c2406042743cc93ca5ae9449 100644 (file)
@@ -9,6 +9,7 @@ include $(top_srcdir)/src/Common.am
 
 DIST_SUBDIRS = \
        fake \
+       SMB_LM \
        SSPI
 SUBDIRS= $(NTLM_AUTH_HELPERS)
 EXTRA_DIST= helpers.m4
diff --git a/src/auth/ntlm/SMB_LM/Makefile.am b/src/auth/ntlm/SMB_LM/Makefile.am
new file mode 100644 (file)
index 0000000..6933e81
--- /dev/null
@@ -0,0 +1,23 @@
+## Copyright (C) 1996-2023 The Squid Software Foundation and contributors
+##
+## Squid software is distributed under GPLv2+ license and includes
+## contributions from numerous individuals and organizations.
+## Please see the COPYING and CONTRIBUTORS files for details.
+##
+
+include $(top_srcdir)/src/Common.am
+
+libexec_PROGRAMS = ntlm_smb_lm_auth
+
+ntlm_smb_lm_auth_SOURCES = ntlm_smb_lm_auth.cc
+ntlm_smb_lm_auth_LDADD = \
+       $(top_builddir)/lib/smblib/libsmblib.la \
+       $(top_builddir)/lib/rfcnb/librfcnb.la \
+       $(top_builddir)/lib/ntlmauth/libntlmauth.la \
+       $(top_builddir)/lib/libmiscencoding.la \
+       $(COMPAT_LIB) \
+       $(LIBNETTLE_LIBS) \
+       $(CRYPTLIB) \
+       $(XTRA_LIBS)
+
+EXTRA_DIST = required.m4
diff --git a/src/auth/ntlm/SMB_LM/ntlm_smb_lm_auth.cc b/src/auth/ntlm/SMB_LM/ntlm_smb_lm_auth.cc
new file mode 100644 (file)
index 0000000..4031e6c
--- /dev/null
@@ -0,0 +1,702 @@
+/*
+ * Copyright (C) 1996-2023 The Squid Software Foundation and contributors
+ *
+ * Squid software is distributed under GPLv2+ license and includes
+ * contributions from numerous individuals and organizations.
+ * Please see the COPYING and CONTRIBUTORS files for details.
+ */
+
+/*
+ * (C) 2000 Francesco Chemolli <kinkie@kame.usr.dsi.unimi.it>
+ * Distributed freely under the terms of the GNU General Public License,
+ * version 2 or later. 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.
+ */
+
+#include "squid.h"
+#include "base64.h"
+#include "compat/debug.h"
+#include "helper/protocol_defines.h"
+#include "ntlmauth/ntlmauth.h"
+#include "ntlmauth/support_bits.cci"
+#include "rfcnb/rfcnb.h"
+#include "smblib/smblib.h"
+
+#include <cassert>
+#include <cctype>
+#include <cerrno>
+#include <csignal>
+#include <cstdlib>
+#include <cstring>
+#include <ctime>
+#if HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#if HAVE_GETOPT_H
+#include <getopt.h>
+#endif
+#if HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+/************* CONFIGURATION ***************/
+
+#define DEAD_DC_RETRY_INTERVAL 30
+
+/************* END CONFIGURATION ***************/
+
+/* 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);
+#define SEND3(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 printf
+#define SEND3 printf
+#endif
+
+typedef struct _dc dc;
+struct _dc {
+    char *domain;
+    char *controller;
+    time_t dead;        /* 0 if it's alive, otherwise time of death */
+    dc *next;
+};
+
+/* local functions */
+static void usage(void);
+static void process_options(int argc, char *argv[]);
+static const char * obtain_challenge(void);
+static void manage_request(void);
+static const char *make_challenge(char *domain, char *controller);
+static char *ntlm_check_auth(ntlm_authenticate * auth, int auth_length);
+static void dc_disconnect(void);
+
+#define ENCODED_PASS_LEN 24
+#define MAX_USERNAME_LEN 255
+#define MAX_DOMAIN_LEN 255
+#define MAX_PASSWD_LEN 31
+
+static unsigned char challenge[NTLM_NONCE_LEN];
+static unsigned char lmencoded_empty_pass[ENCODED_PASS_LEN],
+       ntencoded_empty_pass[ENCODED_PASS_LEN];
+SMB_Handle_Type handle = nullptr;
+static NtlmError ntlm_errno;
+static char credentials[MAX_USERNAME_LEN+MAX_DOMAIN_LEN+2]; /* we can afford to waste */
+static char my_domain[100], my_domain_controller[100];
+static char errstr[1001];
+#if DEBUG
+char error_messages_buffer[NTLM_BLOB_BUFFER_SIZE];
+#endif
+char load_balance = 0, protocol_pedantic = 0;
+dc *controllers = nullptr;
+int numcontrollers = 0;
+dc *current_dc;
+char smb_error_buffer[1000];
+
+/* Disconnects from the DC. A reconnection will be done upon the next request
+ */
+static void
+dc_disconnect()
+{
+    if (handle != NULL)
+        SMB_Discon(handle, 0);
+    handle = nullptr;
+}
+
+/* returns 0 on success, > 0 on failure */
+static int
+init_challenge(char *domain, char *domain_controller)
+{
+    int smberr;
+
+    if (handle != NULL) {
+        return 0;
+    }
+    debug("Connecting to server %s domain %s\n", domain_controller, domain);
+    handle = SMB_Connect_Server(nullptr, domain_controller, domain);
+    smberr = SMB_Get_Last_Error();
+    SMB_Get_Error_Msg(smberr, errstr, 1000);
+
+    if (handle == NULL) {   /* couldn't connect */
+        debug("Couldn't connect to SMB Server. Error:%s\n", errstr);
+        return 1;
+    }
+    if (SMB_Negotiate(handle, SMB_Prots) < 0) {     /* An error */
+        debug("Error negotiating protocol with SMB Server\n");
+        SMB_Discon(handle, 0);
+        handle = nullptr;
+        return 2;
+    }
+    if (handle->Security == 0) {    /* share-level security, unusable */
+        debug("SMB Server uses share-level security .. we need user security.\n");
+        SMB_Discon(handle, 0);
+        handle = nullptr;
+        return 3;
+    }
+    memcpy(challenge, handle->Encrypt_Key, NTLM_NONCE_LEN);
+    SMBencrypt((unsigned char *)"",challenge,lmencoded_empty_pass);
+    SMBNTencrypt((unsigned char *)"",challenge,ntencoded_empty_pass);
+    return 0;
+}
+
+static const char *
+make_challenge(char *domain, char *domain_controller)
+{
+    /* trying to circumvent some strange problem with pointers in SMBLib */
+    /* Ugly as hell, but the lib is going to be dropped... */
+    strncpy(my_domain, domain, sizeof(my_domain)-1);
+    my_domain[sizeof(my_domain)-1] = '\0';
+    strncpy(my_domain_controller, domain_controller, sizeof(my_domain_controller)-1);
+    my_domain_controller[sizeof(my_domain_controller)-1] = '\0';
+
+    if (init_challenge(my_domain, my_domain_controller) > 0) {
+        return nullptr;
+    }
+
+    ntlm_challenge chal;
+    uint32_t flags = NTLM_REQUEST_NON_NT_SESSION_KEY |
+                     NTLM_CHALLENGE_TARGET_IS_DOMAIN |
+                     NTLM_NEGOTIATE_ALWAYS_SIGN |
+                     NTLM_NEGOTIATE_USE_NTLM |
+                     NTLM_NEGOTIATE_USE_LM |
+                     NTLM_NEGOTIATE_ASCII;
+    ntlm_make_challenge(&chal, my_domain, my_domain_controller, (char *)challenge, NTLM_NONCE_LEN, flags);
+
+    size_t len = sizeof(chal) - sizeof(chal.payload) + le16toh(chal.target.maxlen);
+    // for lack of a good NTLM token size limit, allow up to what the helper input can be
+    // validations later will expect to be limited to that size.
+    static char b64buf[HELPER_INPUT_BUFFER-10]; /* 10 for other line fields, delimiters and terminator */
+    if (base64_encode_len(len) < sizeof(b64buf)-1) {
+        debug("base64 encoding of the token challenge will exceed %zu bytes", sizeof(b64buf));
+        return nullptr;
+    }
+
+    struct base64_encode_ctx ctx;
+    base64_encode_init(&ctx);
+    size_t blen = base64_encode_update(&ctx, b64buf, len, reinterpret_cast<const uint8_t *>(&chal));
+    blen += base64_encode_final(&ctx, b64buf+blen);
+    b64buf[blen] = '\0';
+    return b64buf;
+}
+
+/* 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
+ */
+static char *
+ntlm_check_auth(ntlm_authenticate * auth, int auth_length)
+{
+    char pass[MAX_PASSWD_LEN+1];
+    char *domain = credentials;
+    char *user;
+    lstring tmp;
+
+    if (handle == NULL) {   /*if null we aren't connected, but it shouldn't happen */
+        debug("Weird, we've been disconnected\n");
+        ntlm_errno = NtlmError::NotConnected;
+        return nullptr;
+    }
+
+    /*      debug("fetching domain\n"); */
+    tmp = ntlm_fetch_string(&(auth->hdr), auth_length, &auth->domain, auth->flags);
+    if (tmp.str == NULL || tmp.l == 0) {
+        debug("No domain supplied. Returning no-auth\n");
+        ntlm_errno = NtlmError::LoginEror;
+        return nullptr;
+    }
+    if (tmp.l > MAX_DOMAIN_LEN) {
+        debug("Domain string exceeds %d bytes, rejecting\n", MAX_DOMAIN_LEN);
+        ntlm_errno = NtlmError::LoginEror;
+        return nullptr;
+    }
+    memcpy(domain, tmp.str, tmp.l);
+    user = domain + tmp.l;
+    *user = '\0';
+    ++user;
+
+    /*      debug("fetching user name\n"); */
+    tmp = ntlm_fetch_string(&(auth->hdr), auth_length, &auth->user, auth->flags);
+    if (tmp.str == NULL || tmp.l == 0) {
+        debug("No username supplied. Returning no-auth\n");
+        ntlm_errno = NtlmError::LoginEror;
+        return nullptr;
+    }
+    if (tmp.l > MAX_USERNAME_LEN) {
+        debug("Username string exceeds %d bytes, rejecting\n", MAX_USERNAME_LEN);
+        ntlm_errno = NtlmError::LoginEror;
+        return nullptr;
+    }
+    memcpy(user, tmp.str, tmp.l);
+    *(user + tmp.l) = '\0';
+
+    // grab the *response blobs. these are fixed length 24 bytes of binary
+    const ntlmhdr *packet = &(auth->hdr);
+    {
+        const strhdr * str = &auth->lmresponse;
+
+        int16_t len = le16toh(str->len);
+        int32_t offset = le32toh(str->offset);
+
+        if (len != ENCODED_PASS_LEN || offset + len > auth_length || offset == 0) {
+            debug("LM response: insane data (pkt-sz: %d, fetch len: %d, offset: %d)\n", auth_length, len, offset);
+            ntlm_errno = NtlmError::LoginEror;
+            return nullptr;
+        }
+        tmp.str = (char *)packet + offset;
+        tmp.l = len;
+    }
+    if (tmp.l > MAX_PASSWD_LEN) {
+        debug("Password string exceeds %d bytes, rejecting\n", MAX_PASSWD_LEN);
+        ntlm_errno = NtlmError::LoginEror;
+        return nullptr;
+    }
+
+    /* Authenticating against the NT response doesn't seem to work... in SMB LM helper. */
+    memcpy(pass, tmp.str, tmp.l);
+    pass[min(MAX_PASSWD_LEN,tmp.l)] = '\0';
+
+    debug("Empty LM pass detection: user: '%s', ours:'%s', his: '%s' (length: %d)\n",
+          user,lmencoded_empty_pass,tmp.str,tmp.l);
+    if (memcmp(tmp.str,lmencoded_empty_pass,ENCODED_PASS_LEN)==0) {
+        fprintf(stderr,"Empty LM password supplied for user %s\\%s. "
+                "No-auth\n",domain,user);
+        ntlm_errno=NtlmError::LoginEror;
+        return nullptr;
+    }
+
+    /* still fetch the NT response and check validity against empty password */
+    {
+        const strhdr * str = &auth->ntresponse;
+        int16_t len = le16toh(str->len);
+        // NT response field may be absent. that is okay.
+        if (len != 0) {
+            int32_t offset = le32toh(str->offset);
+
+            if (len != ENCODED_PASS_LEN || offset + len > auth_length || offset == 0) {
+                debug("NT response: insane data (pkt-sz: %d, fetch len: %d, offset: %d)\n", auth_length, len, offset);
+                ntlm_errno = NtlmError::LoginEror;
+                return nullptr;
+            }
+            tmp.str = (char *)packet + offset;
+            tmp.l = len;
+
+            debug("Empty NT pass detection: user: '%s', ours:'%s', his: '%s' (length: %d)\n",
+                  user,ntencoded_empty_pass,tmp.str,tmp.l);
+            if (memcmp(tmp.str,lmencoded_empty_pass,ENCODED_PASS_LEN)==0) {
+                fprintf(stderr,"ERROR: Empty NT password supplied for user %s\\%s. No-auth\n", domain, user);
+                ntlm_errno = NtlmError::LoginEror;
+                return nullptr;
+            }
+        }
+    }
+
+    debug("checking domain: '%s', user: '%s', pass='%s'\n", domain, user, pass);
+
+    const auto rv = SMB_Logon_Server(handle, user, pass, domain, 1);
+    debug("Login attempt had result %d\n", rv);
+
+    switch (rv) {
+    case SMBlibE_Success:
+        ntlm_errno = NtlmError::None;
+        break;
+    case SMBlibE_BAD:
+        ntlm_errno = NtlmError::BlobError;
+        return nullptr;
+    case SMBlibE_ProtLow:
+    case SMBlibE_NoSpace:
+    case SMBlibE_BadParam:
+    case SMBlibE_NegNoProt:
+    case SMBlibE_LowerLayer:
+    case SMBlibE_SendFailed:
+    case SMBlibE_RecvFailed:
+    case SMBlibE_ProtUnknown:
+    case SMBlibE_NoSuchMsg:
+        ntlm_errno = NtlmError::ProtocolError;
+        return nullptr;
+    case SMBlibE_NotImpl:
+    case SMBlibE_CallFailed:
+    case SMBlibE_Remote:
+        ntlm_errno = NtlmError::ServerError;
+        return nullptr;
+    case SMBlibE_GuestOnly:
+        ntlm_errno = NtlmError::LoginEror;
+        return nullptr;
+    default:
+        ntlm_errno = NtlmError::ServerError;
+        return nullptr;
+    }
+
+    *(user - 1) = '\\';     /* hack. Performing, but ugly. */
+
+    debug("credentials: %s\n", credentials);
+    return credentials;
+}
+
+static char got_timeout = 0;
+/** signal handler to be invoked when the authentication operation
+ * times out */
+extern "C" void
+timeout_during_auth(int)
+{
+    dc_disconnect();
+}
+
+/*
+ * options:
+ * -b try load-balancing the domain-controllers
+ * -f fail-over to another DC if DC connection fails.
+ *    DEPRECATED and VERBOSELY IGNORED. This is on by default now.
+ * -l last-ditch-mode
+ * domain\controller ...
+ */
+char *my_program_name = nullptr;
+
+static void
+usage()
+{
+    fprintf(stderr,
+            "%s usage:\n%s [-b] [-f] [-d] [-l] domain\\controller [domain\\controller ...]\n"
+            "-b enables load-balancing among controllers\n"
+            "-f enables failover among controllers (DEPRECATED and always active)\n"
+            "-d enables debugging statements if DEBUG was defined at build-time.\n\n"
+            "You MUST specify at least one Domain Controller.\n"
+            "You can use either \\ or / as separator between the domain name \n"
+            "and the controller name\n",
+            my_program_name, my_program_name);
+}
+
+/* int debug_enabled=0; defined in libcompat */
+
+static void
+process_options(int argc, char *argv[])
+{
+    int opt, j, had_error = 0;
+    dc *new_dc = nullptr, *last_dc = nullptr;
+    while (-1 != (opt = getopt(argc, argv, "bfld"))) {
+        switch (opt) {
+        case 'b':
+            load_balance = 1;
+            break;
+        case 'f':
+            fprintf(stderr,
+                    "WARNING. The -f flag is DEPRECATED and always active.\n");
+            break;
+        case 'd':
+            debug_enabled=1;
+            break;
+        default:
+            fprintf(stderr, "unknown option: -%c. Exiting\n", opt);
+            usage();
+            had_error = 1;
+        }
+    }
+    if (had_error)
+        exit(EXIT_FAILURE);
+    /* Okay, now begin filling controllers up */
+    /* we can avoid memcpy-ing, and just reuse argv[] */
+    for (j = optind; j < argc; ++j) {
+        char *d, *c;
+        /* d will not be freed in case of non-error. Since we don't reconfigure,
+         * it's going to live as long as the process anyways */
+        d = static_cast<char*>(xmalloc(strlen(argv[j]) + 1));
+        strcpy(d, argv[j]);
+        debug("Adding domain-controller %s\n", d);
+        if (NULL == (c = strchr(d, '\\')) && NULL == (c = strchr(d, '/'))) {
+            fprintf(stderr, "Couldn't grok domain-controller %s\n", d);
+            free(d);
+            continue;
+        }
+        /* more than one delimiter is not allowed */
+        if (NULL != strchr(c + 1, '\\') || NULL != strchr(c + 1, '/')) {
+            fprintf(stderr, "Broken domain-controller %s\n", d);
+            free(d);
+            continue;
+        }
+        *c= '\0';
+        ++c;
+        new_dc = static_cast<dc *>(xmalloc(sizeof(dc)));
+        if (!new_dc) {
+            fprintf(stderr, "Malloc error while parsing DC options\n");
+            free(d);
+            continue;
+        }
+        /* capitalize */
+        uc(c);
+        uc(d);
+        ++numcontrollers;
+        new_dc->domain = d;
+        new_dc->controller = c;
+        new_dc->dead = 0;
+        if (controllers == NULL) {  /* first controller */
+            controllers = new_dc;
+            last_dc = new_dc;
+        } else {
+            last_dc->next = new_dc; /* can't be null */
+            last_dc = new_dc;
+        }
+    }
+    if (numcontrollers == 0) {
+        fprintf(stderr, "You must specify at least one domain-controller!\n");
+        usage();
+        exit(EXIT_FAILURE);
+    }
+    last_dc->next = controllers;    /* close the queue, now it's circular */
+}
+
+/**
+ * tries connecting to the domain controllers in the "controllers" ring,
+ * with failover if the adequate option is specified.
+ */
+static const char *
+obtain_challenge()
+{
+    int j = 0;
+    const char *ch = nullptr;
+    for (j = 0; j < numcontrollers; ++j) {
+        debug("obtain_challenge: selecting %s\\%s (attempt #%d)\n",
+              current_dc->domain, current_dc->controller, j + 1);
+        if (current_dc->dead != 0) {
+            if (time(NULL) - current_dc->dead >= DEAD_DC_RETRY_INTERVAL) {
+                /* mark helper as retry-worthy if it's so. */
+                debug("Reviving DC\n");
+                current_dc->dead = 0;
+            } else {        /* skip it */
+                debug("Skipping it\n");
+                continue;
+            }
+        }
+        /* else branch. Here we KNOW that the DC is fine */
+        debug("attempting challenge retrieval\n");
+        ch = make_challenge(current_dc->domain, current_dc->controller);
+        debug("make_challenge retuned %p\n", ch);
+        if (ch) {
+            debug("Got it\n");
+            return ch;      /* All went OK, returning */
+        }
+        /* Huston, we've got a problem. Take this DC out of the loop */
+        debug("Marking DC as DEAD\n");
+        current_dc->dead = time(NULL);
+        /* Try with the next */
+        debug("moving on to next controller\n");
+        current_dc = current_dc->next;
+    }
+    /* all DCs failed. */
+    return nullptr;
+}
+
+static void
+manage_request()
+{
+    ntlmhdr *fast_header;
+    char buf[NTLM_BLOB_BUFFER_SIZE];
+    char decoded[NTLM_BLOB_BUFFER_SIZE];
+    char *ch2, *cred = nullptr;
+
+    if (fgets(buf, NTLM_BLOB_BUFFER_SIZE, stdin) == NULL) {
+        fprintf(stderr, "fgets() failed! dying..... errno=%d (%s)\n", errno,
+                strerror(errno));
+        exit(EXIT_FAILURE);        /* BIIG buffer */
+    }
+    debug("managing request\n");
+    ch2 = (char*)memchr(buf, '\n', NTLM_BLOB_BUFFER_SIZE);  /* safer against overrun than strchr */
+    if (ch2) {
+        *ch2 = '\0';        /* terminate the string at newline. */
+    }
+    debug("ntlm authenticator. Got '%s' from Squid\n", buf);
+
+    if (memcmp(buf, "KK ", 3) == 0) {   /* authenticate-request */
+        /* figure out what we got */
+        struct base64_decode_ctx ctx;
+        base64_decode_init(&ctx);
+        size_t dstLen = 0;
+        int decodedLen = 0;
+        if (!base64_decode_update(&ctx, &dstLen, reinterpret_cast<uint8_t*>(decoded), strlen(buf)-3, buf+3) ||
+                !base64_decode_final(&ctx)) {
+            SEND("NA Packet format error, couldn't base64-decode");
+            return;
+        }
+        decodedLen = dstLen;
+
+        if ((size_t)decodedLen < sizeof(ntlmhdr)) { /* decoding failure, return error */
+            SEND("NA Packet format error, truncated packet header.");
+            return;
+        }
+        /* fast-track-decode request type. */
+        fast_header = (ntlmhdr *) decoded;
+
+        /* sanity-check: it IS a NTLMSSP packet, isn't it? */
+        if (ntlm_validate_packet(fast_header, NTLM_ANY) < 0) {
+            SEND("NA Broken authentication packet");
+            return;
+        }
+        switch (le32toh(fast_header->type)) {
+        case NTLM_NEGOTIATE:
+            SEND("NA Invalid negotiation request received");
+            return;
+        /* notreached */
+        case NTLM_CHALLENGE:
+            SEND("NA Got a challenge. We refuse to have our authority disputed");
+            return;
+        /* notreached */
+        case NTLM_AUTHENTICATE:
+            /* check against the DC */
+            signal(SIGALRM, timeout_during_auth);
+            alarm(30);
+            cred = ntlm_check_auth((ntlm_authenticate *) decoded, decodedLen);
+            alarm(0);
+            signal(SIGALRM, SIG_DFL);
+            if (got_timeout != 0) {
+                fprintf(stderr, "ntlm-auth[%ld]: Timeout during authentication.\n", (long)getpid());
+                SEND("BH Timeout during authentication");
+                got_timeout = 0;
+                return;
+            }
+            if (cred == NULL) {
+                int smblib_err, smb_errorclass, smb_errorcode, nb_error;
+                if (ntlm_errno == NtlmError::LoginEror) { /* hackish */
+                    SEND("NA Logon Failure");
+                    return;
+                }
+                /* there was an error. We have two errno's to look at.
+                 * libntlmssp's erno is insufficient, we'll have to look at
+                 * the actual SMB library error codes, to actually figure
+                 * out what's happening. The thing has braindamaged interfacess..*/
+                smblib_err = SMB_Get_Last_Error();
+                smb_errorclass = SMBlib_Error_Class(SMB_Get_Last_SMB_Err());
+                smb_errorcode = SMBlib_Error_Code(SMB_Get_Last_SMB_Err());
+                nb_error = RFCNB_Get_Last_Error();
+                debug("No creds. SMBlib error %d, SMB error class %d, SMB error code %d, NB error %d\n",
+                      smblib_err, smb_errorclass, smb_errorcode, nb_error);
+                /* Should I use smblib_err? Actually it seems I can do as well
+                 * without it.. */
+                if (nb_error != 0) {    /* netbios-level error */
+                    SEND("BH NetBios error!");
+                    fprintf(stderr, "NetBios error code %d (%s)\n", nb_error,
+                            RFCNB_Error_Strings[abs(nb_error)]);
+                    return;
+                }
+                switch (smb_errorclass) {
+                case SMBC_SUCCESS:
+                    debug("Huh? Got a SMB success code but could check auth..");
+                    SEND("NA Authentication failed");
+                    return;
+                case SMBC_ERRDOS:
+                    /*this is the most important one for errors */
+                    debug("DOS error\n");
+                    switch (smb_errorcode) {
+                    /* two categories matter to us: those which could be
+                     * server errors, and those which are auth errors */
+                    case SMBD_noaccess: /* 5 */
+                        SEND("NA Access denied");
+                        return;
+                    case SMBD_badformat:
+                        SEND("NA bad format in authentication packet");
+                        return;
+                    case SMBD_badaccess:
+                        SEND("NA Bad access request");
+                        return;
+                    case SMBD_baddata:
+                        SEND("NA Bad Data");
+                        return;
+                    default:
+                        SEND("BH DOS Error");
+                        return;
+                    }
+                case SMBC_ERRSRV:   /* server errors */
+                    debug("Server error");
+                    switch (smb_errorcode) {
+                    /* mostly same as above */
+                    case SMBV_badpw:
+                        SEND("NA Bad password");
+                        return;
+                    case SMBV_access:
+                        SEND("NA Server access error");
+                        return;
+                    default:
+                        SEND("BH Server Error");
+                        return;
+                    }
+                case SMBC_ERRHRD:   /* hardware errors don't really matter */
+                    SEND("BH Domain Controller Hardware error");
+                    return;
+                case SMBC_ERRCMD:
+                    SEND("BH Domain Controller Command Error");
+                    return;
+                }
+                SEND("BH unknown internal error.");
+                return;
+            }
+
+            lc(cred);       /* let's lowercase them for our convenience */
+            SEND2("AF %s", cred);
+            return;
+        default:
+            SEND("BH unknown authentication packet type");
+            return;
+        }
+        /* notreached */
+        return;
+    }
+    if (memcmp(buf, "YR", 2) == 0) {    /* refresh-request */
+        dc_disconnect();
+        const char *ch = obtain_challenge();
+        /* Robert says we can afford to wait forever. I'll trust him on this
+         * one */
+        while (ch == NULL) {
+            sleep(30);
+            ch = obtain_challenge();
+        }
+        SEND2("TT %s", ch);
+        return;
+    }
+    SEND("BH Helper detected protocol error");
+    return;
+    /********* END ********/
+
+}
+
+int
+main(int argc, char *argv[])
+{
+    debug("%s " VERSION " " SQUID_BUILD_INFO " starting up...\n", argv[0]);
+
+    my_program_name = argv[0];
+    process_options(argc, argv);
+
+    debug("options processed OK\n");
+
+    /* initialize FDescs */
+    setbuf(stdout, nullptr);
+    setbuf(stderr, nullptr);
+
+    /* select the first domain controller we're going to use */
+    current_dc = controllers;
+    if (load_balance != 0 && numcontrollers > 1) {
+        int n;
+        pid_t pid = getpid();
+        n = pid % numcontrollers;
+        debug("load balancing. Selected controller #%d\n", n);
+        while (n > 0) {
+            current_dc = current_dc->next;
+            --n;
+        }
+    }
+    while (1) {
+        manage_request();
+    }
+    /* notreached */
+    return EXIT_SUCCESS;
+}
+
diff --git a/src/auth/ntlm/SMB_LM/required.m4 b/src/auth/ntlm/SMB_LM/required.m4
new file mode 100755 (executable)
index 0000000..a0cf7b5
--- /dev/null
@@ -0,0 +1,17 @@
+## Copyright (C) 1996-2023 The Squid Software Foundation and contributors
+##
+## Squid software is distributed under GPLv2+ license and includes
+## contributions from numerous individuals and organizations.
+## Please see the COPYING and CONTRIBUTORS files for details.
+##
+
+#
+# DONT build this helper on Windows
+# DONT build this helper by default
+#
+# XXX: do we really need the mingw check?
+AS_IF([test "$squid_host_os" != "mingw" -a "x$auto_helpers" != "xyes"],[
+  BUILD_HELPER="SMB_LM"
+  AC_CHECK_HEADERS([w32api/windows.h windows.h],[BUILD_HELPER=""])
+  AS_IF([test "x$BUILD_HELPER" = "xSMB_LM"],[require_smblib="yes"])
+])
index 5c0b9315388786d74b0059cd3716105261da6ffd..f1daa5131cde4ad717492ad39c3a5b663913d341 100644 (file)
@@ -9,6 +9,7 @@ AS_IF([test "x$enable_auth" != "xno"],[
   SQUID_HELPER_FEATURE_CHECK([auth_ntlm],[$enable_auth],[auth/ntlm],[
     # NP: we only need this list because m4_include() does not accept variables
     SQUID_CHECK_HELPER([fake],[auth/ntlm])
+    SQUID_CHECK_HELPER([SMB_LM],[auth/ntlm])
     SQUID_CHECK_HELPER([SSPI],[auth/ntlm])
   ])
   NTLM_AUTH_HELPERS=$squid_cv_BUILD_HELPERS