75int _wcsicmp(
const wchar_t *,
const wchar_t *);
147 long lLBound, lUBound, cElements;
149 if ((!pVar) || (!ppByte))
151 if ((pVar->vt) != (VT_UI1 | VT_ARRAY))
154 hr = SafeArrayGetLBound(V_ARRAY(pVar), 1, &lLBound);
155 hr = SafeArrayGetUBound(V_ARRAY(pVar), 1, &lUBound);
157 cElements = lUBound - lLBound + 1;
158 hr = SafeArrayAccessData(V_ARRAY(pVar), &pArray);
160 LPBYTE pTemp = (LPBYTE) pArray;
161 *ppByte = (LPBYTE) CoTaskMemAlloc(cElements);
163 memcpy(*ppByte, pTemp, cElements);
167 SafeArrayUnaccessData(V_ARRAY(pVar));
177 unsigned User_primaryGroupID;
178 char tmpSID[SECURITY_MAX_SID_SIZE * 2];
179 wchar_t *wc =
nullptr, *result =
nullptr;
185 static const auto primaryGroupIdStr = SysAllocString(L
"primaryGroupID");
186 hr = pUser->Get(primaryGroupIdStr, &var);
188 User_primaryGroupID = var.uintVal;
197 static const auto objectSidStr = SysAllocString(L
"objectSid");
198 hr = pUser->Get(objectSidStr, &var);
201 LPBYTE pByte =
nullptr;
202 char *szSID =
nullptr;
205 pObjectSID = (PSID) pByte;
208 ConvertSidToStringSid(pObjectSID, &szSID);
209 CoTaskMemFree(pByte);
211 *(strrchr(szSID,
'-') + 1) =
'\0';
212 snprintf(tmpSID,
sizeof(tmpSID)-1,
"%s%u", szSID, User_primaryGroupID);
214 wcsize = MultiByteToWideChar(CP_ACP, 0, tmpSID, -1, wc, 0);
215 wc = (
wchar_t *)
xmalloc(wcsize *
sizeof(
wchar_t));
216 MultiByteToWideChar(CP_ACP, 0, tmpSID, -1, wc, wcsize);
219 result =
My_NameTranslate(wc, ADS_NAME_TYPE_SID_OR_SID_HISTORY_NAME, ADS_NAME_TYPE_1779);
223 debug(
"Get_primaryGroup: cannot get DN for %s.\n", tmpSID);
225 debug(
"Get_primaryGroup: Primary group DN: %S.\n", result);
236 FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM |
237 FORMAT_MESSAGE_IGNORE_INSERTS,
240 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
250 IADsNameTranslate *pNto;
255 hr = CoInitialize(
nullptr);
263 hr = CoCreateInstance(CLSID_NameTranslate,
265 CLSCTX_INPROC_SERVER,
266 IID_IADsNameTranslate,
273 static const auto emptyStr = SysAllocString(L
"");
274 hr = pNto->Init(ADS_NAME_INITTYPE_GC, emptyStr);
281 hr = pNto->Set(in_format, name);
288 hr = pNto->Get(out_format, &bstr);
294 debug(
"My_NameTranslate: %S translated to %S\n", name, bstr);
296 wc = (
wchar_t *)
xmalloc((wcslen(bstr) + 1) *
sizeof(wchar_t));
308 wc = (
wchar_t *)
xmalloc((wcslen(Base_DN) + 8) *
sizeof(wchar_t));
311 wcscpy(wc, L
"LDAP://");
313 wcscpy(wc, L
"GC://");
322 static char *DomainName =
nullptr;
323 PDSROLE_PRIMARY_DOMAIN_INFO_BASIC pDSRoleInfo =
nullptr;
326 if ((netret = DsRoleGetPrimaryDomainInformation(
nullptr, DsRolePrimaryDomainInfoBasic, (PBYTE *) & pDSRoleInfo)) == ERROR_SUCCESS) {
331 if ((pDSRoleInfo->MachineRole == DsRole_RoleMemberWorkstation) ||
332 (pDSRoleInfo->MachineRole == DsRole_RoleMemberServer) ||
333 (pDSRoleInfo->MachineRole == DsRole_RoleBackupDomainController) ||
334 (pDSRoleInfo->MachineRole == DsRole_RolePrimaryDomainController)) {
336 size_t len = wcslen(pDSRoleInfo->DomainNameFlat);
340 DomainName = (
char *)
xmalloc(len + 1);
343 WideCharToMultiByte(CP_ACP, 0, pDSRoleInfo->DomainNameFlat, -1, DomainName, len,
nullptr,
nullptr);
346 DomainName[len] =
'\0';
351 debug(
"Member of Domain %s\n", DomainName);
352 debug(
"Into forest %S\n", pDSRoleInfo->DomainForestName);
355 debug(
"Not a Domain member\n");
365 DsRoleFreeMemory(pDSRoleInfo);
382 if (wcscmp(Group, *array) == 0)
403 debug(
"Windows group: %S, Squid group: %S\n", str, *array);
404 if (wcscmp(str, *array) == 0)
415 WCHAR wszGroup[GNLEN + 1];
418 MultiByteToWideChar(CP_ACP, 0, *array,
419 strlen(*array) + 1, wszGroup,
sizeof(wszGroup) /
sizeof(wszGroup[0]));
420 debug(
"Windows group: %S, Squid group: %S\n", str, wszGroup);
436 static const auto memberOfStr = SysAllocString(L
"memberOf");
437 hr = pObj->Get(memberOfStr, &var);
439 if (VT_BSTR == var.vt) {
445 hr = ADsGetObject(Group_Path, IID_IADs, (
void **) &pGrp);
451 hr = ADsGetObject(Group_Path, IID_IADs, (
void **) &pGrp);
464 if (SUCCEEDED(SafeArrayGetLBound(V_ARRAY(&var), 1, &lBound)) &&
465 SUCCEEDED(SafeArrayGetUBound(V_ARRAY(&var), 1, &uBound))) {
467 while (lBound <= uBound) {
468 hr = SafeArrayGetElement(V_ARRAY(&var), &lBound, &elem);
475 hr = ADsGetObject(Group_Path, IID_IADs, (
void **) &pGrp);
481 hr = ADsGetObject(Group_Path, IID_IADs, (
void **) &pGrp);
507 if (hr != E_ADS_PROPERTY_NOT_FOUND)
516 wchar_t *wc =
nullptr;
518 int source_group_format;
519 char Group[GNLEN + 1];
521 wchar_t **wc_array, **entry;
526 if (strchr(*array,
'/')) {
528 source_group_format = ADS_NAME_TYPE_CANONICAL;
530 source_group_format = ADS_NAME_TYPE_NT4;
531 if (!strchr(*array,
'\\')) {
532 strcpy(Group, userdomain);
534 strncat(Group, *array, GNLEN -
sizeof(userdomain) - 1);
539 wcsize = MultiByteToWideChar(CP_ACP, 0, Group, -1, wc, 0);
540 wc = (
wchar_t *)
xmalloc(wcsize *
sizeof(
wchar_t));
541 MultiByteToWideChar(CP_ACP, 0, Group, -1, wc, wcsize);
546 debug(
"build_groups_DN_array: cannot get DN for '%s'.\n", Group);
560 char *Domain_Separator;
561 WCHAR wszUserName[UNLEN + 1];
563 LPLOCALGROUP_USERS_INFO_0 pBuf;
564 LPLOCALGROUP_USERS_INFO_0 pTmpBuf;
566 DWORD dwFlags = LG_INCLUDE_INDIRECT;
567 DWORD dwPrefMaxLen = -1;
568 DWORD dwEntriesRead = 0;
569 DWORD dwTotalEntries = 0;
570 NET_API_STATUS nStatus;
572 DWORD dwTotalCount = 0;
573 LPBYTE pBufTmp =
nullptr;
575 if ((Domain_Separator = strchr(UserName,
'/')))
576 *Domain_Separator =
'\\';
578 debug(
"Valid_Local_Groups: checking group membership of '%s'.\n", UserName);
582 MultiByteToWideChar(CP_ACP, 0, UserName,
583 strlen(UserName) + 1, wszUserName,
sizeof(wszUserName) /
sizeof(wszUserName[0]));
593 nStatus = NetUserGetLocalGroups(
nullptr,
601 pBuf = (LPLOCALGROUP_USERS_INFO_0) pBufTmp;
605 if (nStatus == NERR_Success) {
606 if ((pTmpBuf = pBuf)) {
607 for (i = 0; i < dwEntriesRead; ++i) {
628 NetApiBufferFree(pBuf);
637 WCHAR wszUser[DNLEN + UNLEN + 2];
638 char NTDomain[DNLEN + UNLEN + 2];
640 char *domain_qualify =
nullptr;
641 char User[DNLEN + UNLEN + 2];
644 wchar_t *User_DN =
nullptr, *User_LDAP_path =
nullptr;
645 wchar_t *User_PrimaryGroup =
nullptr;
649 xstrncpy(NTDomain, UserName,
sizeof(NTDomain));
655 if (!domain_qualify) {
658 strncat(User, UserName, UNLEN);
661 domain_qualify[0] =
'\\';
662 xstrncpy(User, NTDomain, DNLEN + UNLEN + 2);
663 domain_qualify[0] =
'\0';
666 debug(
"Valid_Global_Groups: checking group membership of '%s'.\n", User);
670 MultiByteToWideChar(CP_ACP, 0, User,
671 strlen(User) + 1, wszUser,
672 sizeof(wszUser) /
sizeof(wszUser[0]));
675 if (!(User_DN =
My_NameTranslate(wszUser, ADS_NAME_TYPE_NT4, ADS_NAME_TYPE_1779))) {
676 debug(
"Valid_Global_Groups: cannot get DN for '%s'.\n", User);
683 hr = ADsGetObject(User_LDAP_path, IID_IADs, (
void **) &pUser);
685 wchar_t *User_PrimaryGroup_Path;
689 if (!User_PrimaryGroup) {
690 debug(
"Valid_Global_Groups: cannot get Primary Group for '%s'.\n", User);
694 hr = ADsGetObject(User_PrimaryGroup_Path, IID_IADs, (
void **) &pGrp);
700 hr = ADsGetObject(User_PrimaryGroup_Path, IID_IADs, (
void **) &pGrp);
716 hr = ADsGetObject(User_LDAP_path, IID_IADs, (
void **) &pUser);
739 auto tmp = wszGroups;
760 fprintf(stderr,
"Usage: %s [-D domain][-G][-c][-d][-h]\n"
761 " -D default user Domain\n"
762 " -G enable Active Directory Global group mode\n"
763 " -c use case insensitive compare (local mode only)\n"
764 " -d enable debugging\n"
765 " -h this message\n",
775 while (-1 != (opt =
getopt(argc, argv,
"D:Gcdh"))) {
797 fprintf(stderr,
"%s: FATAL: Unknown option: -%c. Exiting\n",
program_name, opt);
812 const char *groups[512];
821 setbuf(stdout,
nullptr);
822 setbuf(stderr,
nullptr);
829 fprintf(stderr,
"%s: FATAL: Can't read machine domain\n",
program_name);
838 debug(
"Domain Global group mode enabled using '%s' as default domain.\n",
DefaultDomain);
840 debug(
"Warning: running in case insensitive mode !!!\n");
846 if (!strchr(buf,
'\n')) {
848 fprintf(stderr,
"%s: ERROR: Too large: %s\n", argv[0], buf);
850 fprintf(stderr,
"%s: ERROR: Too large..: %s\n", argv[0], buf);
851 if (strchr(buf,
'\n'))
857 if ((p = strchr(buf,
'\n')))
859 if ((p = strchr(buf,
'\r')))
862 debug(
"Got '%s' from Squid (length: %zu).\n", buf, strlen(buf));
864 if (buf[0] ==
'\0') {
868 username = strtok(buf,
" ");
869 for (n = 0; (group = strtok(
nullptr,
" ")); ++n) {
#define HELPER_INPUT_BUFFER
void debug(const char *format,...)
static int Valid_Local_Groups(char *UserName, const char **Groups)
static int Valid_Global_Groups(char *UserName, const char **Groups)
int WIN32_COM_initialized
static bool wStrIsInArray(const wchar_t *str, wchar_t **array)
char * WIN32_ErrorMessage
static char * GetDomainName(void)
static int wcstrcmparray(const wchar_t *str, const char **array)
static wchar_t * My_NameTranslate(wchar_t *, int, int)
static HRESULT GetLPBYTEtoOctetString(VARIANT *pVar, LPBYTE *ppByte)
static void CloseCOM(void)
static void process_options(int argc, char *argv[])
const char NTV_VALID_DOMAIN_SEPARATOR[]
int use_case_insensitive_compare
static wchar_t ** build_groups_DN_array(const char **array, char *userdomain)
static char * Get_WIN32_ErrorMessage(HRESULT)
static HRESULT Recursive_Memberof(IADs *pObj)
static int add_User_Group(wchar_t *Group)
static wchar_t * Get_primaryGroup(IADs *pUser)
static wchar_t * GetLDAPPath(wchar_t *Base_DN, int query_mode)
int getopt(int nargc, char *const *nargv, const char *ostr)
void rfc1738_unescape(char *url)
void * xrealloc(void *s, size_t sz)
char * xstrncpy(char *dst, const char *src, size_t n)
char * xstrndup(const char *s, size_t n)