--------------------- PatchSet 10815 Date: 2009/07/19 15:06:02 Author: serassio Branch: nt Tag: (none) Log: Updated mswin_check_ad_group to version 2.0 Members: helpers/external_acl/mswin_ad_group/mswin_check_ad_group.c:1.1.2.3->1.1.2.4 helpers/external_acl/mswin_ad_group/mswin_check_ad_group.h:1.1.2.1->1.1.2.2 helpers/external_acl/mswin_ad_group/readme.txt:1.1.2.2->1.1.2.3 port/win32/mswin_check_ad_group/mswin_check_ad_group.dsp:1.1.2.1->1.1.2.2 Index: squid/helpers/external_acl/mswin_ad_group/mswin_check_ad_group.c =================================================================== RCS file: /cvsroot/squid-sf//squid/helpers/external_acl/mswin_ad_group/mswin_check_ad_group.c,v retrieving revision 1.1.2.3 retrieving revision 1.1.2.4 diff -u -r1.1.2.3 -r1.1.2.4 --- squid/helpers/external_acl/mswin_ad_group/mswin_check_ad_group.c 17 May 2008 09:46:52 -0000 1.1.2.3 +++ squid/helpers/external_acl/mswin_ad_group/mswin_check_ad_group.c 19 Jul 2009 15:06:02 -0000 1.1.2.4 @@ -2,7 +2,7 @@ * mswin_check_ad_group: lookup group membership in a Windows * Active Directory domain * - * (C)2008 Guido Serassio - Acme Consulting S.r.l. + * (C)2008-2009 Guido Serassio - Acme Consulting S.r.l. * * Authors: * Guido Serassio @@ -31,6 +31,13 @@ * * History: * + * Version 2.0 + * 20-07-2009 Guido Serassio + * Global groups support rewritten, now is based on ADSI. + * New Features: + * - support for Domain Local, Domain Global ad Universal + * groups + * - full group nesting support * Version 1.0 * 02-05-2008 Guido Serassio * First release, based on mswin_check_lm_group. @@ -66,13 +73,19 @@ #undef assert #include #include +#include +#include +#include +#include +#include #include -#include #include +#include #include "util.h" #define BUFSIZE 8192 /* the stdin buffer size */ +#define FETCH_NUM 8 int use_global = 0; char debug_enabled = 0; char *myname; @@ -81,9 +94,185 @@ int use_case_insensitive_compare = 0; char *DefaultDomain = NULL; const char NTV_VALID_DOMAIN_SEPARATOR[] = "\\/"; +int numberofgroups = 0; +int WIN32_COM_initialized = 0; +char * WIN32_ErrorMessage = NULL; +wchar_t ** User_Groups; +int User_Groups_Count = 0; #include "mswin_check_ad_group.h" +wchar_t * My_NameTranslate(wchar_t *, int, int); +char * Get_WIN32_ErrorMessage(HRESULT); + + +HRESULT GetLPBYTEtoOctetString(VARIANT *pVar, LPBYTE *ppByte) +{ + HRESULT hr = E_FAIL; + void HUGEP *pArray; + long lLBound, lUBound, cElements; + + if ((!pVar)||(!ppByte)) + return E_INVALIDARG; + if ((pVar->n1.n2.vt) != (VT_UI1|VT_ARRAY)) + return E_INVALIDARG; + + hr = SafeArrayGetLBound(V_ARRAY(pVar), 1, &lLBound); + hr = SafeArrayGetUBound(V_ARRAY(pVar), 1, &lUBound); + + cElements = lUBound-lLBound + 1; + hr = SafeArrayAccessData(V_ARRAY(pVar), &pArray); + if (SUCCEEDED(hr)) + { + LPBYTE pTemp = (LPBYTE)pArray; + *ppByte = (LPBYTE) CoTaskMemAlloc(cElements); + if (*ppByte) + memcpy(*ppByte, pTemp, cElements); + else + hr = E_OUTOFMEMORY; + } + SafeArrayUnaccessData(V_ARRAY(pVar)); + + return hr; +} + + +wchar_t * Get_primaryGroup(IADs *pUser) +{ + HRESULT hr; + VARIANT var ; + unsigned User_primaryGroupID; + char tmpSID[SECURITY_MAX_SID_SIZE*2]; + wchar_t * wc = NULL, * result = NULL; + int wcsize; + + VariantInit(&var) ; + + /* Get the primaryGroupID property */ + hr = pUser->lpVtbl->Get(pUser, L"primaryGroupID", &var); + if (SUCCEEDED(hr)) + { + User_primaryGroupID = var.n1.n2.n3.uintVal; + } else { + debug("Get_primaryGroup: cannot get primaryGroupID, ERROR: %s\n", Get_WIN32_ErrorMessage(hr)); + VariantClear(&var); + return result; + } + VariantClear(&var); + + /*Get the objectSid property */ + hr = pUser->lpVtbl->Get(pUser, L"objectSid", &var); + if (SUCCEEDED(hr)) + { + PSID pObjectSID; + LPBYTE pByte = NULL; + char * szSID = NULL; + hr = GetLPBYTEtoOctetString(&var, &pByte); + + pObjectSID = (PSID)pByte; + + /* Convert SID to string. */ + ConvertSidToStringSid(pObjectSID, &szSID); + CoTaskMemFree(pByte); + + *(strrchr(szSID,'-') + 1) = '\0'; + sprintf(tmpSID, "%s%u", szSID, User_primaryGroupID); + + wcsize = MultiByteToWideChar(CP_ACP, 0, tmpSID, -1, wc, 0); + wc = (wchar_t *)xmalloc(wcsize * sizeof(wchar_t)); + MultiByteToWideChar(CP_ACP, 0, tmpSID, -1, wc, wcsize); + LocalFree(szSID); + + result = My_NameTranslate(wc, ADS_NAME_TYPE_SID_OR_SID_HISTORY_NAME, ADS_NAME_TYPE_1779); + safe_free(wc); + + if (result == NULL) + debug("Get_primaryGroup: cannot get DN for %s.\n", tmpSID); + else + debug("Get_primaryGroup: Primary group DN: %S.\n", result); + } else + debug("Get_primaryGroup: cannot get objectSid, ERROR: %s\n", Get_WIN32_ErrorMessage(hr)); + VariantClear(&var); + return result; +} + + +char * Get_WIN32_ErrorMessage(HRESULT hr) +{ + FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | + FORMAT_MESSAGE_IGNORE_INSERTS, + NULL, + hr, + MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), + (LPTSTR) &WIN32_ErrorMessage, + 0, + NULL); + return WIN32_ErrorMessage; +} + + +wchar_t * My_NameTranslate(wchar_t * name, int in_format, int out_format) +{ + IADsNameTranslate *pNto; + HRESULT hr; + BSTR bstr; + wchar_t * wc; + + if (WIN32_COM_initialized == 0) { + CoInitialize(NULL); + WIN32_COM_initialized = 1; + } + + hr = CoCreateInstance(&CLSID_NameTranslate, + NULL, + CLSCTX_INPROC_SERVER, + &IID_IADsNameTranslate, + (void**)&pNto); + if(FAILED(hr)) { + debug("My_NameTranslate: cannot create COM instance, ERROR: %s\n", Get_WIN32_ErrorMessage(hr)); + return NULL; + } + + hr = pNto->lpVtbl->Init(pNto, ADS_NAME_INITTYPE_GC, L""); + if(FAILED(hr)) { + debug("My_NameTranslate: cannot initialise NameTranslate API, ERROR: %s\n", Get_WIN32_ErrorMessage(hr)); + pNto->lpVtbl->Release(pNto); + return NULL; + } + hr = pNto->lpVtbl->Set(pNto, in_format, name); + if(FAILED(hr)) { + debug("My_NameTranslate: cannot set translate of %S, ERROR: %s\n", name, Get_WIN32_ErrorMessage(hr)); + pNto->lpVtbl->Release(pNto); + return NULL; + } + hr = pNto->lpVtbl->Get(pNto, out_format, &bstr); + if(FAILED(hr)) { + debug("My_NameTranslate: cannot get translate of %S, ERROR: %s\n", name, Get_WIN32_ErrorMessage(hr)); + pNto->lpVtbl->Release(pNto); + return NULL; + } + debug("My_NameTranslate: %S translated to %S\n", name, bstr); + + wc = (wchar_t *)xmalloc((wcslen(bstr) + 1) * sizeof(wchar_t)); + wcscpy(wc, bstr); + SysFreeString(bstr); + pNto->lpVtbl->Release(pNto); + return wc; +} + + +wchar_t * GetLDAPPath(wchar_t * Base_DN) +{ + wchar_t * wc; + + wc = (wchar_t *)xmalloc((wcslen(Base_DN) + 8) * sizeof(wchar_t)); + + wcscpy(wc, L"LDAP://"); + wcscat(wc, Base_DN); + + return wc; +} + char * GetDomainName(void) @@ -126,7 +315,7 @@ debug("Not a Domain member\n"); } } else - debug("DsRoleGetPrimaryDomainInformation Error: %ld\n", netret); + debug("GetDomainName: ERROR DsRoleGetPrimaryDomainInformation returned: %s\n", Get_WIN32_ErrorMessage(netret)); /* * Free the allocated memory. @@ -137,6 +326,47 @@ return DomainName; } + +int add_User_Group(wchar_t * Group) +{ +wchar_t ** array; + + if (User_Groups_Count == 0) { + User_Groups = (wchar_t **)xmalloc(sizeof(wchar_t *)); + *User_Groups = NULL; + User_Groups_Count++; + } + + array = User_Groups; + while (*array) { + if (wcscmp(Group, *array) == 0) + return 0; + array++; + } + User_Groups = (wchar_t **)xrealloc(User_Groups, sizeof(wchar_t *) * (User_Groups_Count + 1)); + User_Groups[User_Groups_Count] = NULL; + User_Groups[User_Groups_Count - 1] = (wchar_t *)xmalloc((wcslen(Group) +1) * sizeof(wchar_t)); + wcscpy(User_Groups[User_Groups_Count - 1], Group); + User_Groups_Count ++; + + return 1; +} + + +/* returns 0 on match, -1 if no match */ +static int +wccmparray(const wchar_t * str, const wchar_t **array) +{ + while (*array) { + debug("Windows group: %S, Squid group: %S\n", str, *array); + if (wcscmp(str, *array) == 0) + return 0; + array++; + } + return -1; +} + + /* returns 0 on match, -1 if no match */ static int wcstrcmparray(const wchar_t * str, const char **array) @@ -154,13 +384,111 @@ return -1; } + +HRESULT Recursive_Memberof(IADs *pObj) +{ + VARIANT var ; + long lBound, uBound ; + HRESULT hr; + + VariantInit( &var ) ; + hr = pObj->lpVtbl->Get(pObj, L"memberOf", &var); + if (SUCCEEDED(hr)) + { + if ( VT_BSTR == var.n1.n2.vt ) { + if (add_User_Group(var.n1.n2.n3.bstrVal)) { + wchar_t * Group_Path; + IADs *pGrp; + + Group_Path = GetLDAPPath(var.n1.n2.n3.bstrVal); + hr = ADsGetObject(Group_Path, &IID_IADs, (void**) &pGrp); + if (SUCCEEDED(hr)) { + hr = Recursive_Memberof(pGrp); + pGrp->lpVtbl->Release(pGrp); + } + safe_free(Group_Path); + } + } else { + if (SUCCEEDED(SafeArrayGetLBound(V_ARRAY(&var), 1, &lBound)) && + SUCCEEDED(SafeArrayGetUBound(V_ARRAY(&var), 1, &uBound))) { + VARIANT elem ; + while (lBound <= uBound) { + hr = SafeArrayGetElement(V_ARRAY(&var), &lBound, &elem) ; + if (SUCCEEDED(hr)) { + if (add_User_Group(elem.n1.n2.n3.bstrVal)) { + wchar_t * Group_Path; + IADs *pGrp; + + Group_Path = GetLDAPPath(elem.n1.n2.n3.bstrVal); + hr = ADsGetObject(Group_Path, &IID_IADs, (void**) &pGrp); + if (SUCCEEDED(hr)) { + hr = Recursive_Memberof(pGrp); + pGrp->lpVtbl->Release(pGrp); + } + safe_free(Group_Path); + } + VariantClear(&elem) ; + } + ++lBound ; + } + } + } + VariantClear(&var) ; + } + return hr; +} + + +static wchar_t ** +build_groups_DN_array(const char **array, char * userdomain) +{ + wchar_t * wc = NULL; + int wcsize; + int source_group_format; + char Group[GNLEN + 1]; + + wchar_t ** wc_array, **entry; + + entry = wc_array = (wchar_t **)xmalloc((numberofgroups + 1) * sizeof(wchar_t *)); + + while (*array) { + if (strchr(*array, '/') != NULL) { + strncpy(Group, *array, GNLEN); + source_group_format = ADS_NAME_TYPE_CANONICAL; + } else { + source_group_format = ADS_NAME_TYPE_NT4; + if (strchr(*array, '\\') == NULL) { + strcpy(Group, userdomain); + strcat(Group, "\\"); + strncat(Group, *array, GNLEN - sizeof(userdomain) - 1); + } else + strncpy(Group, *array, GNLEN); + } + + wcsize = MultiByteToWideChar(CP_ACP, 0, Group, -1, wc, 0); + wc = (wchar_t *)xmalloc(wcsize * sizeof(wchar_t)); + MultiByteToWideChar(CP_ACP, 0, Group, -1, wc, wcsize); + *entry = My_NameTranslate(wc, source_group_format, ADS_NAME_TYPE_1779); + safe_free(wc); + array++; + if (*entry == NULL) { + debug("build_groups_DN_array: cannot get DN for '%s'.\n", Group); + continue; + } + entry++; + } + *entry = NULL; + return wc_array; +} + + /* returns 1 on success, 0 on failure */ int Valid_Local_Groups(char *UserName, const char **Groups) { int result = 0; char *Domain_Separator; - WCHAR wszUserName[UNLEN + 1]; // Unicode user name + WCHAR wszUserName[UNLEN + 1]; /* Unicode user name */ LPLOCALGROUP_USERS_INFO_0 pBuf; LPLOCALGROUP_USERS_INFO_0 pTmpBuf; @@ -220,8 +548,10 @@ dwTotalCount++; } } - } else + } else { + debug("Valid_Local_Groups: ERROR NetUserGetLocalGroups returned: %s\n", Get_WIN32_ErrorMessage(nStatus)); result = 0; + } /* * Free the allocated memory. */ @@ -236,26 +566,17 @@ Valid_Global_Groups(char *UserName, const char **Groups) { int result = 0; - WCHAR wszUserName[UNLEN + 1]; // Unicode user name - - WCHAR wszDomainControllerName[UNCLEN + 1]; - + WCHAR wszUser[DNLEN + UNLEN + 2]; /* Unicode user name */ char NTDomain[DNLEN + UNLEN + 2]; + char *domain_qualify = NULL; - char User[UNLEN + 1]; + char User[DNLEN + UNLEN + 2]; size_t j; - LPGROUP_USERS_INFO_0 pUsrBuf = NULL; - LPGROUP_USERS_INFO_0 pTmpBuf; - PDOMAIN_CONTROLLER_INFO pDCInfo = NULL; - DWORD dwLevel = 0; - DWORD dwPrefMaxLen = -1; - DWORD dwEntriesRead = 0; - DWORD dwTotalEntries = 0; - NET_API_STATUS nStatus; - DWORD i; - DWORD dwTotalCount = 0; - LPBYTE pBufTmp = NULL; + wchar_t * User_DN, * User_LDAP_path, * User_PrimaryGroup; + wchar_t ** wszGroups, ** tmp; + IADs *pUser; + HRESULT hr; strncpy(NTDomain, UserName, sizeof(NTDomain)); @@ -264,84 +585,87 @@ break; } if (domain_qualify == NULL) { - strcpy(User, NTDomain); - strcpy(NTDomain, DefaultDomain); + strncpy(User, DefaultDomain, DNLEN); + strcat(User, "\\"); + strncat(User, UserName, UNLEN); + strncpy(NTDomain, DefaultDomain, DNLEN); } else { - strcpy(User, domain_qualify + 1); + domain_qualify[0] = '\\'; + strncpy(User, NTDomain, DNLEN + UNLEN + 2); domain_qualify[0] = '\0'; - strlwr(NTDomain); } - debug("Valid_Global_Groups: checking group membership of '%s\\%s'.\n", NTDomain, User); + debug("Valid_Global_Groups: checking group membership of '%s'.\n", User); /* Convert ANSI User Name to Unicode */ MultiByteToWideChar(CP_ACP, 0, User, - strlen(User) + 1, wszUserName, - sizeof(wszUserName) / sizeof(wszUserName[0])); + strlen(User) + 1, wszUser, + sizeof(wszUser) / sizeof(wszUser[0])); - /* Query AD for a DC */ + /* Get CN of User */ + if ((User_DN = My_NameTranslate(wszUser, ADS_NAME_TYPE_NT4, ADS_NAME_TYPE_1779)) == NULL) + { + debug("Valid_Global_Groups: cannot get DN for '%s'.\n", User); + return result; + } - if (DsGetDcName(NULL, NTDomain, NULL, NULL, DS_IS_FLAT_NAME | DS_RETURN_FLAT_NAME, &pDCInfo) != NO_ERROR) { - fprintf(stderr, "%s DsGetDcName() failed.'\n", myname); - if (pDCInfo != NULL) - NetApiBufferFree(pDCInfo); - return result; - } - /* Convert ANSI Domain Controller Name to Unicode */ - - MultiByteToWideChar(CP_ACP, 0, pDCInfo->DomainControllerName, - strlen(pDCInfo->DomainControllerName) + 1, wszDomainControllerName, - sizeof(wszDomainControllerName) / sizeof(wszDomainControllerName[0])); - - debug("Using '%S' as DC for '%s' user's domain.\n", wszDomainControllerName, NTDomain); - debug("DC Active Directory Site is %s\n", pDCInfo->DcSiteName); - debug("Machine Active Directory Site is %s\n", pDCInfo->ClientSiteName); + wszGroups = build_groups_DN_array(Groups, NTDomain); - /* - * Call the NetUserGetGroups function - * specifying information level 0. - */ - dwLevel = 0; - pBufTmp = NULL; - nStatus = NetUserGetGroups(wszDomainControllerName, - wszUserName, - dwLevel, - &pBufTmp, - dwPrefMaxLen, - &dwEntriesRead, - &dwTotalEntries); - pUsrBuf = (LPGROUP_USERS_INFO_0) pBufTmp; - /* - * 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 NetUserGetGroups() failed.'\n", myname); + User_LDAP_path = GetLDAPPath(User_DN); + + safe_free(User_DN); + + hr = ADsGetObject(User_LDAP_path, &IID_IADs, (void**) &pUser); + if (SUCCEEDED(hr)) + { + wchar_t * User_PrimaryGroup_Path; + IADs *pGrp; + + User_PrimaryGroup = Get_primaryGroup(pUser); + if (User_PrimaryGroup == NULL) + debug("Valid_Global_Groups: cannot get Primary Group for '%s'.\n", User); + else { + add_User_Group(User_PrimaryGroup); + User_PrimaryGroup_Path = GetLDAPPath(User_PrimaryGroup); + hr = ADsGetObject(User_PrimaryGroup_Path, &IID_IADs, (void**) &pGrp); + if (SUCCEEDED(hr)) { + hr = Recursive_Memberof(pGrp); + pGrp->lpVtbl->Release(pGrp); + } + safe_free(User_PrimaryGroup_Path); + } + hr = Recursive_Memberof(pUser); + pUser->lpVtbl->Release(pUser); + + tmp = User_Groups; + while (*tmp) { + if (wccmparray(*tmp, wszGroups) == 0) { + result = 1; + break; + } + tmp++; + } + } else + debug("Valid_Global_Groups: ADsGetObject for %S failed, ERROR: %s\n", User_LDAP_path, Get_WIN32_ErrorMessage(hr)); + + safe_free(User_LDAP_path); + safe_free(User_PrimaryGroup); + tmp = wszGroups; + while (*tmp) { + safe_free(*tmp); + tmp++; } - /* - * Free the allocated memory. - */ - if (pUsrBuf != NULL) - NetApiBufferFree(pUsrBuf); - if (pDCInfo != NULL) - NetApiBufferFree((LPVOID) pDCInfo); + safe_free(wszGroups); + + tmp = User_Groups; + while (*tmp) { + safe_free(*tmp); + tmp++; + } + safe_free(User_Groups); + User_Groups_Count = 0; + return result; } @@ -350,8 +674,8 @@ { fprintf(stderr, "Usage: %s [-D domain][-G][-P][-c][-d][-h]\n" " -D default user Domain\n" - " -G enable Domain Global group mode\n" - " -c use case insensitive compare\n" + " -G enable Active Directory Global group mode\n" + " -c use case insensitive compare (local mode only)\n" " -d enable debugging\n" " -h this message\n", program); @@ -466,6 +790,7 @@ groups[n] = group; } groups[n] = NULL; + numberofgroups = n; if (NULL == username) { fprintf(stderr, "Invalid Request\n"); Index: squid/helpers/external_acl/mswin_ad_group/mswin_check_ad_group.h =================================================================== RCS file: /cvsroot/squid-sf//squid/helpers/external_acl/mswin_ad_group/mswin_check_ad_group.h,v retrieving revision 1.1.2.1 retrieving revision 1.1.2.2 diff -u -r1.1.2.1 -r1.1.2.2 --- squid/helpers/external_acl/mswin_ad_group/mswin_check_ad_group.h 3 May 2008 08:58:26 -0000 1.1.2.1 +++ squid/helpers/external_acl/mswin_ad_group/mswin_check_ad_group.h 19 Jul 2009 15:06:02 -0000 1.1.2.2 @@ -39,16 +39,22 @@ #include static char *__foo; extern char debug_enabled; +extern char * WIN32_ErrorMessage; #define debug(X...) if (debug_enabled) { \ fprintf(stderr,"%s[%d](%s:%d): ", myname, mypid, \ ((__foo=strrchr(__FILE__,'/'))==NULL?__FILE__:__foo+1),\ __LINE__);\ - fprintf(stderr,X); } + fprintf(stderr,X); \ + if (WIN32_ErrorMessage != NULL){ \ + LocalFree(WIN32_ErrorMessage); \ + WIN32_ErrorMessage = NULL; \ + } } #else /* DEBUG */ #define debug(X...) /* */ #endif /* DEBUG */ #else /* __GNUC__ */ extern char debug_enabled; +extern char * WIN32_ErrorMessage; static void debug(char *format,...) { @@ -62,6 +68,10 @@ vfprintf(stderr, format, args); fprintf(stderr, "\n"); va_end(args); + if (WIN32_ErrorMessage != NULL) { + LocalFree(WIN32_ErrorMessage); + WIN32_ErrorMessage = NULL; + } } #endif /* _SQUID_MSWIN_ */ #endif /* DEBUG */ Index: squid/helpers/external_acl/mswin_ad_group/readme.txt =================================================================== RCS file: /cvsroot/squid-sf//squid/helpers/external_acl/mswin_ad_group/readme.txt,v retrieving revision 1.1.2.2 retrieving revision 1.1.2.3 diff -u -r1.1.2.2 -r1.1.2.3 --- squid/helpers/external_acl/mswin_ad_group/readme.txt 17 May 2008 12:05:01 -0000 1.1.2.2 +++ squid/helpers/external_acl/mswin_ad_group/readme.txt 19 Jul 2009 15:06:02 -0000 1.1.2.3 @@ -1,5 +1,5 @@ -This is the readme.txt file for mswin_check_ad_group, an external +This is the readme.txt file for mswin_check_ad_group 2.0, an external helper for the External ACL Scheme for Squid. @@ -9,18 +9,36 @@ and tries to match it against the groups membership of the specified username. +Two running mode are available: + +- Local mode: +membership is checked against machine's local groups, cannot be used when +running on a Domain Controller. + +- Active Directory Global mode: +membership is checked against the whole Active Directory Forest of the +machine where Squid is running. + The minimal Windows version needed to run mswin_check_ad_group is a Windows 2000 SP4 member of an Active Directory Domain. +When running in Active Directory Global mode, all types of Active Directory +security groups are supported: +- Domain Global +- Domain Local +- Universal +and Active Directory group nesting is fully supported. + + ============== Program Syntax ============== -mswin_check_lm_group [-D domain][-G][-c][-d][-h] +mswin_check_ad_group [-D domain][-G][-c][-d][-h] -D domain specify the default user's domain --G start helper in Domain Global Group mode --c use case insensitive compare +-G start helper in Active Directory Global mode +-c use case insensitive compare (local mode only) -d enable debugging -h this message @@ -29,10 +47,23 @@ squid.conf usage ================ +When running in Active Directory Global mode, the AD Group can be specified using the +following syntax: + +1. Plain NT4 Group Name +2. Full NT4 Group Name +3. Active Directory Canonical name + +As Example: +1. Proxy-Users +2. MYDOMAIN\Proxy-Users +3. mydomain.local/Groups/Proxy-Users + + external_acl_type AD_global_group %LOGIN c:/squid/libexec/mswin_check_ad_group.exe -G external_acl_type NT_local_group %LOGIN c:/squid/libexec/mswin_check_ad_group.exe -acl GProxyUsers external AD_global_group GProxyUsers +acl GProxyUsers external AD_global_group MYDOMAIN\GProxyUsers acl LProxyUsers external NT_local_group LProxyUsers acl password proxy_auth REQUIRED @@ -40,7 +71,7 @@ http_access allow password LProxyUsers http_access deny all -In the previous example all validated AD users member of GProxyUsers Global +In the previous example all validated AD users member of MYDOMAIN\GProxyUsers domain group or member of LProxyUsers machine local group are allowed to use the cache. @@ -55,8 +86,9 @@ "Domain Users" NOTES: -- The standard group name comparison is case sensitive, so group name - must be specified with same case as in the Active Directory Domain. +- When running in local mode, the standard group name comparison is case + sensitive, so group name must be specified with same case as in the + local SAM database. It's possible to enable case insensitive group name comparison (-c), but on some not-english locales, the results can be unexpected. - Native WIN32 NTLM and Basic Helpers must be used without the Index: squid/port/win32/mswin_check_ad_group/mswin_check_ad_group.dsp =================================================================== RCS file: /cvsroot/squid-sf//squid/port/win32/mswin_check_ad_group/Attic/mswin_check_ad_group.dsp,v retrieving revision 1.1.2.1 retrieving revision 1.1.2.2 diff -u -r1.1.2.1 -r1.1.2.2 --- squid/port/win32/mswin_check_ad_group/mswin_check_ad_group.dsp 3 May 2008 08:58:26 -0000 1.1.2.1 +++ squid/port/win32/mswin_check_ad_group/mswin_check_ad_group.dsp 19 Jul 2009 15:06:02 -0000 1.1.2.2 @@ -53,7 +53,7 @@ # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386 -# ADD LINK32 netapi32.lib Advapi32.lib ws2_32.lib psapi.lib /nologo /subsystem:console /machine:I386 +# ADD LINK32 netapi32.lib Advapi32.lib ws2_32.lib psapi.lib ole32.lib oleaut32.lib ActiveDS.Lib ADsIID.lib /nologo /subsystem:console /machine:I386 # SUBTRACT LINK32 /pdb:none !ELSEIF "$(CFG)" == "mswin_check_ad_group - Win32 Debug" @@ -70,7 +70,7 @@ # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /YX /FD /GZ /c -# ADD CPP /nologo /G6 /MTd /W3 /Gm /GX /ZI /Od /I "../../../include" /I "../../../src" /I "../include" /D "_DEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D _FILE_OFFSET_BITS=64 /YX /FD /GZ /c +# ADD CPP /nologo /G6 /MTd /W3 /Gm /GX /ZI /Od /I "../../../include" /I "../../../src" /I "../include" /D "_DEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D _FILE_OFFSET_BITS=64 /FR /YX /FD /GZ /c # ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32 # ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 # ADD BASE RSC /l 0x410 /d "_DEBUG" @@ -80,7 +80,7 @@ # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept -# ADD LINK32 netapi32.lib Advapi32.lib ws2_32.lib psapi.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept +# ADD LINK32 netapi32.lib Advapi32.lib ws2_32.lib psapi.lib ole32.lib oleaut32.lib ActiveDS.Lib ADsIID.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept # SUBTRACT LINK32 /pdb:none !ENDIF