+++ /dev/null
-.if !'po4a'hide' .TH ext_lm_group_acl 8
-.
-.SH NAME
-ext_lm_group_acl \- Squid external ACL helper to check Windows users group membership.
-.PP
-Version 1.22
-.
-.SH SYNOPSIS
-.if !'po4a'hide' .B ext_lm_group_acl
-.if !'po4a'hide' .B "[\-D "
-domain
-.if !'po4a'hide' .B "] [\-cdhGP]"
-.
-.SH DESCRIPTION
-.B ext_lm_group_acl
-is an installed binary in Squid for Windows builds.
-.PP
-This helper must be used in with an authentication scheme (typically
-Basic or NTLM) based on Windows NT/2000 domain users (LM mode).
-.PP
-It reads from the standard input the domain username and a list of groups
-and tries to match each against the groups membership of the specified
-username.
-.
-.SH OPTIONS
-.if !'po4a'hide' .TP 12
-.if !'po4a'hide' .B \-c
-Use case insensitive compare.
-.
-.if !'po4a'hide' .TP
-.if !'po4a'hide' .B \-d
-Write debug info to stderr.
-.
-.if !'po4a'hide' .TP
-.if !'po4a'hide' .B \-D domain
-Specify the default user's domain.
-.
-.if !'po4a'hide' .TP
-.if !'po4a'hide' .B \-G
-Start helper in Domain Global Group mode.
-.
-.if !'po4a'hide' .TP
-.if !'po4a'hide' .B \-h
-Display the binary help and command line syntax info using stderr.
-.
-.if !'po4a'hide' .TP
-.if !'po4a'hide' .B \-P
-Use ONLY PDCs for group validation.
-.
-.SH CONFIGURATION
-.if !'po4a'hide' .RS
-.if !'po4a'hide' .B external_acl_type NT_global_group %LOGIN c:/squid/libexec/ext_lm_group_acl.exe -G
-.if !'po4a'hide' .br
-.if !'po4a'hide' .B external_acl_type NT_local_group %LOGIN c:/squid/libexec/ext_lm_group_acl.exe
-.if !'po4a'hide' .br
-.if !'po4a'hide' .br
-.if !'po4a'hide' .B acl GProxyUsers external NT_global_group GProxyUsers
-.if !'po4a'hide' .br
-.if !'po4a'hide' .B acl LProxyUsers external NT_local_group LProxyUsers
-.if !'po4a'hide' .br
-.if !'po4a'hide' .B acl password proxy_auth REQUIRED
-.if !'po4a'hide' .br
-.if !'po4a'hide' .br
-.if !'po4a'hide' .B http_access allow password GProxyUsers
-.if !'po4a'hide' .br
-.if !'po4a'hide' .B http_access allow password LProxyUsers
-.if !'po4a'hide' .br
-.if !'po4a'hide' .B http_access deny all
-.if !'po4a'hide' .RE
-.
-.PP
-In the previous example all validated NT users member of GProxyUsers Global
-domain group or member of LProxyUsers machine local group are allowed to
-use the cache.
-.
-.PP
-Groups with spaces in name, for example
-.B "Domain Users"
-, must be quoted and the acl data (
-.B "Domain Users"
-) must be placed into a separate file included by specifying
-.B "/path/to/file"
-.
-The previous example will be:
-.if !'po4a'hide' .RS
-.if !'po4a'hide' acl ProxyUsers external NT_global_group "c:/squid/etc/DomainUsers.txt"
-.if !'po4a'hide' .RE
-.
-The
-.B DomainUsers.txt
-file will contain only the following line:
-.if !'po4a'hide' .RS
-.B "Domain Users"
-.if !'po4a'hide' .RE
-.
-.PP
-.B NOTE:
-The standard group name comparison is case sensitive, so group name
-must be specified with same case as in the NT/2000 Domain.
-It's possible to enable case insensitive group name comparison (
-.B \-c
-), but on some not-english locales, the results can be unexpected.
-.
-.PP
-.B NOTE:
-Native WIN32 NTLM and Basic Helpers must be used without the
-.B \-A
-and
-.B \-D
-switches.
-.PP
-Refer to Squid documentation for the more details on squid.conf.
-.
-.SH TESTING
-.PP
-I strongly recommend that
-.B ext_lm_group_acl
-is tested prior to being used in a production environment. It may behave differently on different platforms.
-.
-.PP
-To test it, run it from the command line. Enter username and group
-pairs separated by a space (username must entered with URL-encoded
-.I domain%5Cusername
-syntax). Press
-.B ENTER
-to get an
-.B OK
-or
-.B ERR
-message.
-.PP
-Make sure pressing
-.B CTRL+D
-behaves the same as a carriage return.
-.PP
-Make sure pressing
-.B CTRL+C
-aborts the program.
-.
-.PP
-Test that entering no details does not result in an
-.B OK
-or
-.B ERR
-message.
-.PP
-Test that entering an invalid username and group results in an
-.B ERR
-message.
-.PP
-Test that entering an valid username and group results in an
-.B OK
-message.
-.
-.SH AUTHOR
-This program was written by
-.if !'po4a'hide' .I Guido Serassio <guido.serassio@acmeconsulting.it>
-with contributions by
-.if !'po4a'hide' .I Henrik Nordstrom <hno@squid-cache.org>
-.PP
-Based in part on prior work in
-.B check_group
-by
-.if !'po4a'hide' .I Rodrigo Albani de Campos
-.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
-.PP
- * 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.
-.PP
-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@lists.squid-cache.org>
-.
-.SH REPORTING BUGS
-Bug reports need to be made in English.
-See https://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 https://bugs.squid-cache.org/
-.PP
-Report serious security bugs to
-.I Squid Bugs <squid-bugs@lists.squid-cache.org>
-.PP
-Report ideas for new improvements to the
-.I Squid Developers mailing list
-.if !'po4a'hide' <squid-dev@lists.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' https://wiki.squid-cache.org/SquidFaq
-.br
-The Squid Configuration Manual
-.if !'po4a'hide' http://www.squid-cache.org/Doc/config/
+++ /dev/null
-/*
- * 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.
- */
-
-/*
- * mswin_check_lm_group: lookup group membership in a Windows NT/2000 domain
- *
- * (C)2002,2005 Guido Serassio - Acme Consulting S.r.l.
- *
- * Authors:
- * Guido Serassio <guido.serassio@acmeconsulting.it>
- * Acme Consulting S.r.l., Italy <http://www.acmeconsulting.it>
- *
- * With contributions from others mentioned in the change history section
- * below.
- *
- * In part based on check_group by Rodrigo Albani de Campos.
- *
- * Dependencies: Windows NT4 SP4 and later.
- *
- * 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, USA.
- *
- * History:
- *
- * Version 1.22
- * 08-07-2005 Guido Serassio
- * Added -P option for force usage of PDCs for group validation.
- * Added support for '/' char as domain separator.
- * Fixed Bugzilla #1336.
- * Version 1.21
- * 23-04-2005 Guido Serassio
- * Added -D option for specify default user's domain.
- * Version 1.20.1
- * 15-08-2004 Guido Serassio
- * Helper protocol changed to use URL escaped strings in Squid-3.0
- * (Original work of Henrik Nordstrom)
- * Version 1.20
- * 13-06-2004 Guido Serassio
- * Added support for running on a Domain Controller.
- * Version 1.10
- * 01-05-2003 Guido Serassio
- * Added option for case insensitive group name comparison.
- * More debug info.
- * Updated documentation.
- * Segfault bug fix (Bugzilla #574)
- * Version 1.0
- * 24-06-2002 Guido Serassio
- * Using the main function from check_group and sections
- * from wbinfo wrote win32_group
- *
- * This is a helper for the external ACL interface for Squid Cache
- *
- * It reads from the standard input the domain username and a list of
- * groups and tries to match it against the groups membership of the
- * specified username.
- *
- * Returns `OK' if the user belongs to a group or `ERR' otherwise, as
- * described on http://devel.squid-cache.org/external_acl/config.html
- *
- */
-
-#include "squid.h"
-#include "helper/protocol_defines.h"
-#include "rfc1738.h"
-#include "util.h"
-
-#if _SQUID_CYGWIN_
-#include <cwchar>
-int _wcsicmp(const wchar_t *, const wchar_t *);
-#endif
-
-#undef assert
-#include <cassert>
-#include <cctype>
-#include <cstring>
-#if HAVE_GETOPT_H
-#include <getopt.h>
-#endif
-#include <windows.h>
-#include <lm.h>
-#include <ntsecapi.h>
-
-int use_global = 0;
-int use_PDC_only = 0;
-const char *program_name;
-pid_t mypid;
-char *machinedomain;
-int use_case_insensitive_compare = 0;
-char *DefaultDomain = nullptr;
-const char NTV_VALID_DOMAIN_SEPARATOR[] = "\\/";
-
-static 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 nullptr;
-
- /* copy unicode buffer */
- WideCharToMultiByte(CP_ACP, 0, LsaStr.Buffer, LsaStr.Length, target, len, nullptr, nullptr);
-
- /* add null termination */
- target[len - 1] = '\0';
- return target;
-}
-
-static 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 = nullptr;
-
- /*
- * 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(nullptr, 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(
- nullptr,
- &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,
- (PVOID *) & ppdiDomainInfo);
- if (status) {
- debug("LsaQueryInformationPolicy Error: %ld\n", status);
- } else {
-
- /* Get name in usable 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 = nullptr;
- }
- }
- }
-
- /*
- * 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 0 on match, -1 if no match */
-static int
-wcstrcmparray(const wchar_t * str, const char **array)
-{
- WCHAR wszGroup[GNLEN + 1]; // Unicode Group
-
- while (*array) {
- MultiByteToWideChar(CP_ACP, 0, *array,
- strlen(*array) + 1, wszGroup, sizeof(wszGroup) / sizeof(wszGroup[0]));
- debug("Windows group: %S, Squid group: %S\n", str, wszGroup);
- if ((use_case_insensitive_compare ? _wcsicmp(str, wszGroup) : wcscmp(str, wszGroup)) == 0)
- return 0;
- ++array;
- }
- return -1;
-}
-
-/* returns 1 on success, 0 on failure */
-static int
-Valid_Local_Groups(char *UserName, const char **Groups)
-{
- int result = 0;
- char *Domain_Separator;
- WCHAR wszUserName[UNLEN + 1]; // Unicode user name
-
- LPLOCALGROUP_USERS_INFO_0 pBuf = nullptr;
- 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;
-
- if ((Domain_Separator = strchr(UserName, '/')) != NULL)
- *Domain_Separator = '\\';
-
- debug("Valid_Local_Groups: checking group membership of '%s'.\n", UserName);
-
- /* Convert ANSI User Name and Group to Unicode */
-
- MultiByteToWideChar(CP_ACP, 0, UserName,
- strlen(UserName) + 1, wszUserName, sizeof(wszUserName) / sizeof(wszUserName[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(
- nullptr,
- 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) {
- assert(pTmpBuf != NULL);
- if (pTmpBuf == NULL) {
- result = 0;
- break;
- }
- if (wcstrcmparray(pTmpBuf->lgrui0_name, Groups) == 0) {
- result = 1;
- break;
- }
- ++pTmpBuf;
- ++dwTotalCount;
- }
- }
- } else
- result = 0;
- /*
- * Free the allocated memory.
- */
- if (pBuf != NULL)
- NetApiBufferFree(pBuf);
- return result;
-}
-
-/* returns 1 on success, 0 on failure */
-static int
-Valid_Global_Groups(char *UserName, const char **Groups)
-{
- int result = 0;
- WCHAR wszUserName[UNLEN + 1]; // Unicode user name
-
- WCHAR wszLocalDomain[DNLEN + 1]; // Unicode Local Domain
-
- WCHAR wszUserDomain[DNLEN + 1]; // Unicode User Domain
-
- char NTDomain[DNLEN + UNLEN + 2];
- char *domain_qualify;
- char User[UNLEN + 1];
- size_t j;
-
- LPWSTR LclDCptr = nullptr;
- LPWSTR UsrDCptr = nullptr;
- LPGROUP_USERS_INFO_0 pUsrBuf = nullptr;
- LPGROUP_USERS_INFO_0 pTmpBuf;
- LPSERVER_INFO_101 pSrvBuf = nullptr;
- DWORD dwLevel = 0;
- DWORD dwPrefMaxLen = -1;
- DWORD dwEntriesRead = 0;
- DWORD dwTotalEntries = 0;
- NET_API_STATUS nStatus;
- DWORD i;
- DWORD dwTotalCount = 0;
-
- xstrncpy(NTDomain, UserName, sizeof(NTDomain));
-
- for (j = 0; j < strlen(NTV_VALID_DOMAIN_SEPARATOR); ++j) {
- if ((domain_qualify = strchr(NTDomain, NTV_VALID_DOMAIN_SEPARATOR[j])) != NULL)
- break;
- }
- if (domain_qualify == NULL) {
- xstrncpy(User, NTDomain, sizeof(User));
- xstrncpy(NTDomain, DefaultDomain, sizeof(NTDomain));
- } else {
- xstrncpy(User, domain_qualify + 1, sizeof(User));
- domain_qualify[0] = '\0';
- strlwr(NTDomain);
- }
-
- debug("Valid_Global_Groups: checking group membership of '%s\\%s'.\n", NTDomain, User);
-
- /* Convert ANSI User Name and Group to Unicode */
-
- MultiByteToWideChar(CP_ACP, 0, User,
- strlen(User) + 1, wszUserName,
- sizeof(wszUserName) / sizeof(wszUserName[0]));
- MultiByteToWideChar(CP_ACP, 0, machinedomain,
- strlen(machinedomain) + 1, wszLocalDomain, sizeof(wszLocalDomain) / sizeof(wszLocalDomain[0]));
-
- /* Call the NetServerGetInfo function for local computer, specifying level 101. */
- dwLevel = 101;
- nStatus = NetServerGetInfo(nullptr, dwLevel, (LPBYTE *) & pSrvBuf);
-
- if (nStatus == NERR_Success) {
- /* Check if we are running on a Domain Controller */
- if ((pSrvBuf->sv101_type & SV_TYPE_DOMAIN_CTRL) ||
- (pSrvBuf->sv101_type & SV_TYPE_DOMAIN_BAKCTRL)) {
- LclDCptr = nullptr;
- debug("Running on a DC.\n");
- } else
- nStatus = (use_PDC_only ? NetGetDCName(nullptr, wszLocalDomain, (LPBYTE *) & LclDCptr) : NetGetAnyDCName(nullptr, wszLocalDomain, (LPBYTE *) & LclDCptr));
- } else {
- fprintf(stderr, "%s: ERROR: NetServerGetInfo() failed.'\n", program_name);
- if (pSrvBuf != NULL)
- NetApiBufferFree(pSrvBuf);
- return result;
- }
-
- if (nStatus == NERR_Success) {
- debug("Using '%S' as DC for '%S' local domain.\n", LclDCptr, wszLocalDomain);
-
- if (strcmp(NTDomain, machinedomain) != 0) {
- MultiByteToWideChar(CP_ACP, 0, NTDomain,
- strlen(NTDomain) + 1, wszUserDomain, sizeof(wszUserDomain) / sizeof(wszUserDomain[0]));
- nStatus = (use_PDC_only ? NetGetDCName(LclDCptr, wszUserDomain, (LPBYTE *) & UsrDCptr) : NetGetAnyDCName(LclDCptr, wszUserDomain, (LPBYTE *) & UsrDCptr));
- if (nStatus != NERR_Success) {
- fprintf(stderr, "%s: ERROR: Can't find DC for user's domain '%s'\n", program_name, NTDomain);
- if (pSrvBuf != NULL)
- NetApiBufferFree(pSrvBuf);
- if (LclDCptr != NULL)
- NetApiBufferFree((LPVOID) LclDCptr);
- if (UsrDCptr != NULL)
- NetApiBufferFree((LPVOID) UsrDCptr);
- return result;
- }
- } else
- UsrDCptr = LclDCptr;
-
- debug("Using '%S' as DC for '%s' user's domain.\n", UsrDCptr, NTDomain);
- /*
- * Call the NetUserGetGroups function
- * specifying information level 0.
- */
- dwLevel = 0;
- nStatus = NetUserGetGroups(UsrDCptr,
- wszUserName,
- dwLevel,
- (LPBYTE *) & pUsrBuf,
- dwPrefMaxLen,
- &dwEntriesRead,
- &dwTotalEntries);
- /*
- * If the call succeeds,
- */
- if (nStatus == NERR_Success) {
- if ((pTmpBuf = pUsrBuf) != NULL) {
- for (i = 0; i < dwEntriesRead; ++i) {
- assert(pTmpBuf != NULL);
- if (pTmpBuf == NULL) {
- result = 0;
- break;
- }
- if (wcstrcmparray(pTmpBuf->grui0_name, Groups) == 0) {
- result = 1;
- break;
- }
- ++pTmpBuf;
- ++dwTotalCount;
- }
- }
- } else {
- result = 0;
- fprintf(stderr, "%s: ERROR: NetUserGetGroups() failed.'\n", program_name);
- }
- } else {
- fprintf(stderr, "%s: ERROR: Can't find DC for local domain '%s'\n", program_name, machinedomain);
- }
- /*
- * Free the allocated memory.
- */
- if (pSrvBuf != NULL)
- NetApiBufferFree(pSrvBuf);
- if (pUsrBuf != NULL)
- NetApiBufferFree(pUsrBuf);
- if ((UsrDCptr != NULL) && (UsrDCptr != LclDCptr))
- NetApiBufferFree((LPVOID) UsrDCptr);
- if (LclDCptr != NULL)
- NetApiBufferFree((LPVOID) LclDCptr);
- return result;
-}
-
-static void
-usage(const char *program)
-{
- fprintf(stderr, "Usage: %s [-D domain][-G][-P][-c][-d][-h]\n"
- " -D default user Domain\n"
- " -G enable Domain Global group mode\n"
- " -P use ONLY PDCs for group validation\n"
- " -c use case insensitive compare\n"
- " -d enable debugging\n"
- " -h this message\n",
- program);
-}
-
-static void
-process_options(int argc, char *argv[])
-{
- int opt;
-
- opterr = 0;
- while (-1 != (opt = getopt(argc, argv, "D:GPcdh"))) {
- switch (opt) {
- case 'D':
- DefaultDomain = xstrndup(optarg, DNLEN + 1);
- strlwr(DefaultDomain);
- break;
- case 'G':
- use_global = 1;
- break;
- case 'P':
- use_PDC_only = 1;
- break;
- case 'c':
- use_case_insensitive_compare = 1;
- break;
- case 'd':
- debug_enabled = 1;
- break;
- case 'h':
- usage(argv[0]);
- exit(EXIT_SUCCESS);
- case '?':
- opt = optopt;
- [[fallthrough]];
- default:
- fprintf(stderr, "%s: FATAL: Unknown option: -%c. Exiting\n", program_name, opt);
- usage(argv[0]);
- exit(EXIT_FAILURE);
- break; /* not reached */
- }
- }
- return;
-}
-
-int
-main(int argc, char *argv[])
-{
- char *p;
- char buf[HELPER_INPUT_BUFFER];
- char *username;
- char *group;
- const char *groups[512];
- int n;
-
- if (argc > 0) { /* should always be true */
- program_name = strrchr(argv[0], '/');
- if (program_name == NULL)
- program_name = argv[0];
- } else {
- program_name = "(unknown)";
- }
- mypid = getpid();
-
- setbuf(stdout, nullptr);
- setbuf(stderr, nullptr);
-
- /* Check Command Line */
- process_options(argc, argv);
-
- if (use_global) {
- if ((machinedomain = GetDomainName()) == NULL) {
- fprintf(stderr, "%s: FATAL: Can't read machine domain\n", program_name);
- exit(EXIT_FAILURE);
- }
- strlwr(machinedomain);
- if (!DefaultDomain)
- DefaultDomain = xstrdup(machinedomain);
- }
- debug("%s " VERSION " " SQUID_BUILD_INFO " starting up...\n", argv[0]);
- if (use_global) {
- debug("Domain Global group mode enabled using '%s' as default domain.\n", DefaultDomain);
- }
- if (use_case_insensitive_compare) {
- debug("Warning: running in case insensitive mode !!!\n");
- }
- if (use_PDC_only) {
- debug("Warning: using only PDCs for group validation !!!\n");
- }
-
- /* Main Loop */
- while (fgets(buf, HELPER_INPUT_BUFFER, stdin)) {
- if (NULL == strchr(buf, '\n')) {
- /* too large message received.. skip and deny */
- debug("%s: ERROR: Too large: %s\n", argv[0], buf);
- while (fgets(buf, HELPER_INPUT_BUFFER, stdin)) {
- debug("%s: ERROR: Too large..: %s\n", argv[0], buf);
- if (strchr(buf, '\n') != NULL)
- break;
- }
- SEND_BH(HLP_MSG("Input Too Long."));
- continue;
- }
- if ((p = strchr(buf, '\n')) != NULL)
- *p = '\0'; /* strip \n */
- if ((p = strchr(buf, '\r')) != NULL)
- *p = '\0'; /* strip \r */
-
- debug("Got '%s' from Squid (length: %d).\n", buf, strlen(buf));
-
- if (buf[0] == '\0') {
- SEND_BH(HLP_MSG("Invalid Request."));
- continue;
- }
- username = strtok(buf, " ");
- for (n = 0; (group = strtok(nullptr, " ")) != NULL; ++n) {
- rfc1738_unescape(group);
- groups[n] = group;
- }
- groups[n] = nullptr;
-
- if (NULL == username) {
- SEND_BH(HLP_MSG("Invalid Request. No Username."));
- continue;
- }
- rfc1738_unescape(username);
-
- if ((use_global ? Valid_Global_Groups(username, groups) : Valid_Local_Groups(username, groups))) {
- SEND_OK("");
- } else {
- SEND_ERR("");
- }
- }
- return EXIT_SUCCESS;
-}
-