74int _wcsicmp(
const wchar_t *,
const wchar_t *);
128 long lLBound, lUBound, cElements;
130 if ((!pVar) || (!ppByte))
132 if ((pVar->n1.n2.vt) != (VT_UI1 | VT_ARRAY))
135 hr = SafeArrayGetLBound(V_ARRAY(pVar), 1, &lLBound);
136 hr = SafeArrayGetUBound(V_ARRAY(pVar), 1, &lUBound);
138 cElements = lUBound - lLBound + 1;
139 hr = SafeArrayAccessData(V_ARRAY(pVar), &pArray);
141 LPBYTE pTemp = (LPBYTE) pArray;
142 *ppByte = (LPBYTE) CoTaskMemAlloc(cElements);
144 memcpy(*ppByte, pTemp, cElements);
148 SafeArrayUnaccessData(V_ARRAY(pVar));
158 unsigned User_primaryGroupID;
159 char tmpSID[SECURITY_MAX_SID_SIZE * 2];
160 wchar_t *wc =
nullptr, *result =
nullptr;
166 hr = pUser->lpVtbl->Get(pUser, L
"primaryGroupID", &var);
168 User_primaryGroupID = var.n1.n2.n3.uintVal;
177 hr = pUser->lpVtbl->Get(pUser, L
"objectSid", &var);
180 LPBYTE pByte =
nullptr;
181 char *szSID =
nullptr;
184 pObjectSID = (PSID) pByte;
187 ConvertSidToStringSid(pObjectSID, &szSID);
188 CoTaskMemFree(pByte);
190 *(strrchr(szSID,
'-') + 1) =
'\0';
191 snprintf(tmpSID,
sizeof(tmpSID)-1,
"%s%u", szSID, User_primaryGroupID);
193 wcsize = MultiByteToWideChar(CP_ACP, 0, tmpSID, -1, wc, 0);
194 wc = (
wchar_t *)
xmalloc(wcsize *
sizeof(
wchar_t));
195 MultiByteToWideChar(CP_ACP, 0, tmpSID, -1, wc, wcsize);
198 result =
My_NameTranslate(wc, ADS_NAME_TYPE_SID_OR_SID_HISTORY_NAME, ADS_NAME_TYPE_1779);
202 debug(
"Get_primaryGroup: cannot get DN for %s.\n", tmpSID);
204 debug(
"Get_primaryGroup: Primary group DN: %S.\n", result);
214 FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM |
215 FORMAT_MESSAGE_IGNORE_INSERTS,
218 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
228 IADsNameTranslate *pNto;
234 hr = CoInitialize(
NULL);
242 hr = CoCreateInstance(&CLSID_NameTranslate,
244 CLSCTX_INPROC_SERVER,
245 &IID_IADsNameTranslate,
252 hr = pNto->lpVtbl->Init(pNto, ADS_NAME_INITTYPE_GC, L
"");
255 pNto->lpVtbl->Release(pNto);
259 hr = pNto->lpVtbl->Set(pNto, in_format, name);
262 pNto->lpVtbl->Release(pNto);
265 hr = pNto->lpVtbl->Get(pNto, out_format, &bstr);
268 pNto->lpVtbl->Release(pNto);
271 debug(
"My_NameTranslate: %S translated to %S\n", name, bstr);
273 wc = (
wchar_t *)
xmalloc((wcslen(bstr) + 1) *
sizeof(wchar_t));
276 pNto->lpVtbl->Release(pNto);
285 wc = (
wchar_t *)
xmalloc((wcslen(Base_DN) + 8) *
sizeof(wchar_t));
288 wcscpy(wc, L
"LDAP://");
290 wcscpy(wc, L
"GC://");
299 static char *DomainName =
nullptr;
300 PDSROLE_PRIMARY_DOMAIN_INFO_BASIC pDSRoleInfo;
303 if ((netret = DsRoleGetPrimaryDomainInformation(
nullptr, DsRolePrimaryDomainInfoBasic, (PBYTE *) & pDSRoleInfo) == ERROR_SUCCESS)) {
308 if ((pDSRoleInfo->MachineRole == DsRole_RoleMemberWorkstation) ||
309 (pDSRoleInfo->MachineRole == DsRole_RoleMemberServer) ||
310 (pDSRoleInfo->MachineRole == DsRole_RoleBackupDomainController) ||
311 (pDSRoleInfo->MachineRole == DsRole_RolePrimaryDomainController)) {
313 size_t len = wcslen(pDSRoleInfo->DomainNameFlat);
317 DomainName = (
char *)
xmalloc(len + 1);
320 WideCharToMultiByte(CP_ACP, 0, pDSRoleInfo->DomainNameFlat, -1, DomainName, len,
nullptr,
nullptr);
323 DomainName[len] =
'\0';
328 debug(
"Member of Domain %s\n", DomainName);
329 debug(
"Into forest %S\n", pDSRoleInfo->DomainForestName);
332 debug(
"Not a Domain member\n");
340 if (pDSRoleInfo !=
NULL)
341 DsRoleFreeMemory(pDSRoleInfo);
358 if (wcscmp(Group, *array) == 0)
376 debug(
"Windows group: %S, Squid group: %S\n", str, *array);
377 if (wcscmp(str, *array) == 0)
388 WCHAR wszGroup[GNLEN + 1];
391 MultiByteToWideChar(CP_ACP, 0, *array,
392 strlen(*array) + 1, wszGroup,
sizeof(wszGroup) /
sizeof(wszGroup[0]));
393 debug(
"Windows group: %S, Squid group: %S\n", str, wszGroup);
409 hr = pObj->lpVtbl->Get(pObj, L
"memberOf", &var);
411 if (VT_BSTR == var.n1.n2.vt) {
417 hr = ADsGetObject(Group_Path, &IID_IADs, (
void **) &pGrp);
420 pGrp->lpVtbl->Release(pGrp);
423 hr = ADsGetObject(Group_Path, &IID_IADs, (
void **) &pGrp);
426 pGrp->lpVtbl->Release(pGrp);
434 if (SUCCEEDED(SafeArrayGetLBound(V_ARRAY(&var), 1, &lBound)) &&
435 SUCCEEDED(SafeArrayGetUBound(V_ARRAY(&var), 1, &uBound))) {
437 while (lBound <= uBound) {
438 hr = SafeArrayGetElement(V_ARRAY(&var), &lBound, &elem);
445 hr = ADsGetObject(Group_Path, &IID_IADs, (
void **) &pGrp);
448 pGrp->lpVtbl->Release(pGrp);
451 hr = ADsGetObject(Group_Path, &IID_IADs, (
void **) &pGrp);
454 pGrp->lpVtbl->Release(pGrp);
474 if (hr != E_ADS_PROPERTY_NOT_FOUND)
483 wchar_t *wc =
nullptr;
485 int source_group_format;
486 char Group[GNLEN + 1];
488 wchar_t **wc_array, **entry;
493 if (strchr(*array,
'/') !=
NULL) {
494 strncpy(Group, *array, GNLEN);
495 source_group_format = ADS_NAME_TYPE_CANONICAL;
497 source_group_format = ADS_NAME_TYPE_NT4;
498 if (strchr(*array,
'\\') ==
NULL) {
499 strcpy(Group, userdomain);
501 strncat(Group, *array, GNLEN -
sizeof(userdomain) - 1);
503 strncpy(Group, *array, GNLEN);
506 wcsize = MultiByteToWideChar(CP_ACP, 0, Group, -1, wc, 0);
507 wc = (
wchar_t *)
xmalloc(wcsize *
sizeof(
wchar_t));
508 MultiByteToWideChar(CP_ACP, 0, Group, -1, wc, wcsize);
512 if (*entry ==
NULL) {
513 debug(
"build_groups_DN_array: cannot get DN for '%s'.\n", Group);
527 char *Domain_Separator;
528 WCHAR wszUserName[UNLEN + 1];
530 LPLOCALGROUP_USERS_INFO_0 pBuf;
531 LPLOCALGROUP_USERS_INFO_0 pTmpBuf;
533 DWORD dwFlags = LG_INCLUDE_INDIRECT;
534 DWORD dwPrefMaxLen = -1;
535 DWORD dwEntriesRead = 0;
536 DWORD dwTotalEntries = 0;
537 NET_API_STATUS nStatus;
539 DWORD dwTotalCount = 0;
540 LPBYTE pBufTmp =
nullptr;
542 if ((Domain_Separator = strchr(UserName,
'/')) !=
NULL)
543 *Domain_Separator =
'\\';
545 debug(
"Valid_Local_Groups: checking group membership of '%s'.\n", UserName);
549 MultiByteToWideChar(CP_ACP, 0, UserName,
550 strlen(UserName) + 1, wszUserName,
sizeof(wszUserName) /
sizeof(wszUserName[0]));
560 nStatus = NetUserGetLocalGroups(
nullptr,
568 pBuf = (LPLOCALGROUP_USERS_INFO_0) pBufTmp;
572 if (nStatus == NERR_Success) {
573 if ((pTmpBuf = pBuf) !=
NULL) {
574 for (i = 0; i < dwEntriesRead; ++i) {
576 if (pTmpBuf ==
NULL) {
596 NetApiBufferFree(pBuf);
605 WCHAR wszUser[DNLEN + UNLEN + 2];
606 char NTDomain[DNLEN + UNLEN + 2];
608 char *domain_qualify =
nullptr;
609 char User[DNLEN + UNLEN + 2];
612 wchar_t *User_DN, *User_LDAP_path, *User_PrimaryGroup;
613 wchar_t **wszGroups, **tmp;
617 strncpy(NTDomain, UserName,
sizeof(NTDomain));
623 if (domain_qualify ==
NULL) {
626 strncat(User, UserName, UNLEN);
629 domain_qualify[0] =
'\\';
630 strncpy(User, NTDomain, DNLEN + UNLEN + 2);
631 domain_qualify[0] =
'\0';
634 debug(
"Valid_Global_Groups: checking group membership of '%s'.\n", User);
638 MultiByteToWideChar(CP_ACP, 0, User,
639 strlen(User) + 1, wszUser,
640 sizeof(wszUser) /
sizeof(wszUser[0]));
644 debug(
"Valid_Global_Groups: cannot get DN for '%s'.\n", User);
651 hr = ADsGetObject(User_LDAP_path, &IID_IADs, (
void **) &pUser);
653 wchar_t *User_PrimaryGroup_Path;
657 if (User_PrimaryGroup ==
NULL)
658 debug(
"Valid_Global_Groups: cannot get Primary Group for '%s'.\n", User);
662 hr = ADsGetObject(User_PrimaryGroup_Path, &IID_IADs, (
void **) &pGrp);
665 pGrp->lpVtbl->Release(pGrp);
668 hr = ADsGetObject(User_PrimaryGroup_Path, &IID_IADs, (
void **) &pGrp);
671 pGrp->lpVtbl->Release(pGrp);
679 pUser->lpVtbl->Release(pUser);
682 hr = ADsGetObject(User_LDAP_path, &IID_IADs, (
void **) &pUser);
685 pUser->lpVtbl->Release(pUser);
724 fprintf(stderr,
"Usage: %s [-D domain][-G][-c][-d][-h]\n"
725 " -D default user Domain\n"
726 " -G enable Active Directory Global group mode\n"
727 " -c use case insensitive compare (local mode only)\n"
728 " -d enable debugging\n"
729 " -h this message\n",
739 while (-1 != (opt =
getopt(argc, argv,
"D:Gcdh"))) {
761 fprintf(stderr,
"%s: FATAL: Unknown option: -%c. Exiting\n",
program_name, opt);
776 const char *groups[512];
788 setbuf(stdout,
nullptr);
789 setbuf(stderr,
nullptr);
796 fprintf(stderr,
"%s: FATAL: Can't read machine domain\n",
program_name);
803 debug(
"%s " VERSION " " SQUID_BUILD_INFO
" starting up...\n", argv[0]);
805 debug(
"Domain Global group mode enabled using '%s' as default domain.\n",
DefaultDomain);
807 debug(
"Warning: running in case insensitive mode !!!\n");
813 if (
NULL == strchr(buf,
'\n')) {
815 fprintf(stderr,
"%s: ERROR: Too large: %s\n", argv[0], buf);
817 fprintf(stderr,
"%s: ERROR: Too large..: %s\n", argv[0], buf);
818 if (strchr(buf,
'\n') !=
NULL)
824 if ((p = strchr(buf,
'\n')) !=
NULL)
826 if ((p = strchr(buf,
'\r')) !=
NULL)
829 debug(
"Got '%s' from Squid (length: %d).\n", buf, strlen(buf));
831 if (buf[0] ==
'\0') {
835 username = strtok(buf,
" ");
836 for (n = 0; (group = strtok(
nullptr,
" ")) !=
NULL; ++n) {
843 if (
NULL == username) {
#define HELPER_INPUT_BUFFER
void debug(const char *format,...)
int main(int argc, char *argv[])
int WIN32_COM_initialized
char * WIN32_ErrorMessage
HRESULT Recursive_Memberof(IADs *pObj)
static int wcstrcmparray(const wchar_t *str, const char **array)
const char NTV_VALID_DOMAIN_SEPARATOR[]
wchar_t * Get_primaryGroup(IADs *pUser)
void process_options(int argc, char *argv[])
char * GetDomainName(void)
int use_case_insensitive_compare
static wchar_t ** build_groups_DN_array(const char **array, char *userdomain)
int Valid_Global_Groups(char *UserName, const char **Groups)
wchar_t * GetLDAPPath(wchar_t *Base_DN, int query_mode)
HRESULT GetLPBYTEtoOctetString(VARIANT *pVar, LPBYTE *ppByte)
static int wccmparray(const wchar_t *str, const wchar_t **array)
char * Get_WIN32_ErrorMessage(HRESULT)
int Valid_Local_Groups(char *UserName, const char **Groups)
wchar_t * My_NameTranslate(wchar_t *, int, int)
int add_User_Group(wchar_t *Group)
static void usage(const char *program)
int getopt(int nargc, char *const *nargv, const char *ostr)
std::vector< ServiceGroupPointer > Groups
void rfc1738_unescape(char *url)
void * xrealloc(void *s, size_t sz)
char * xstrndup(const char *s, size_t n)