📄 win32_check_group.c
字号:
/* * 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 comparation. * 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 "config.h"#ifdef _SQUID_CYGWIN_#include <wchar.h>int _wcsicmp(const wchar_t *, const wchar_t *);#endif#if HAVE_STDIO_H#include <stdio.h>#endif#if HAVE_CTYPE_H#include <ctype.h>#endif#ifdef HAVE_STRING_H#include <string.h>#endif#if HAVE_GETOPT_H#include <getopt.h>#endif#undef assert#include <assert.h>#include <windows.h>#include <lm.h>#include <ntsecapi.h>#include "util.h"#define BUFSIZE 8192 /* the stdin buffer size */int use_global = 0;int use_PDC_only = 0;char debug_enabled = 0;char *myname;pid_t mypid;char *machinedomain;int use_case_insensitive_compare = 0;char *DefaultDomain = NULL;const char NTV_VALID_DOMAIN_SEPARATOR[] = "\\/";#include "win32_check_group.h"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 = NULL; PWKSTA_INFO_100 pwkiWorkstationInfo; DWORD netret; char *DomainName = NULL; LPBYTE pwkiWorkstationInfoTmp; /* * 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, &pwkiWorkstationInfoTmp); pwkiWorkstationInfo = (PWKSTA_INFO_100) pwkiWorkstationInfoTmp; 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 { PVOID ppdiDomainInfoTmp; /* * You have a handle to the policy object. Now, get the * domain information using LsaQueryInformationPolicy. */ status = LsaQueryInformationPolicy(PolicyHandle, PolicyPrimaryDomainInformation, &ppdiDomainInfoTmp); ppdiDomainInfo = (PPOLICY_PRIMARY_DOMAIN_INFO) ppdiDomainInfoTmp; 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 0 on match, -1 if no match */static intwcstrcmparray(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 */intValid_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; 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; LPBYTE pBufTmp = NULL; 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(NULL, wszUserName, dwLevel, dwFlags, &pBufTmp, dwPrefMaxLen, &dwEntriesRead, &dwTotalEntries); pBuf = (LPLOCALGROUP_USERS_INFO_0) pBufTmp; /* * 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;/*
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -