74int _wcsicmp(
const wchar_t *,
const wchar_t *);
146 long lLBound, lUBound, cElements;
148 if ((!pVar) || (!ppByte))
150 if ((pVar->vt) != (VT_UI1 | VT_ARRAY))
153 hr = SafeArrayGetLBound(V_ARRAY(pVar), 1, &lLBound);
154 hr = SafeArrayGetUBound(V_ARRAY(pVar), 1, &lUBound);
156 cElements = lUBound - lLBound + 1;
157 hr = SafeArrayAccessData(V_ARRAY(pVar), &pArray);
159 LPBYTE pTemp = (LPBYTE) pArray;
160 *ppByte = (LPBYTE) CoTaskMemAlloc(cElements);
162 memcpy(*ppByte, pTemp, cElements);
166 SafeArrayUnaccessData(V_ARRAY(pVar));
176 unsigned User_primaryGroupID;
177 char tmpSID[SECURITY_MAX_SID_SIZE * 2];
178 wchar_t *wc =
nullptr, *result =
nullptr;
184 static const auto primaryGroupIdStr = SysAllocString(L
"primaryGroupID");
185 hr = pUser->Get(primaryGroupIdStr, &var);
187 User_primaryGroupID = var.uintVal;
196 static const auto objectSidStr = SysAllocString(L
"objectSid");
197 hr = pUser->Get(objectSidStr, &var);
200 LPBYTE pByte =
nullptr;
201 char *szSID =
nullptr;
204 pObjectSID = (PSID) pByte;
207 ConvertSidToStringSid(pObjectSID, &szSID);
208 CoTaskMemFree(pByte);
210 *(strrchr(szSID,
'-') + 1) =
'\0';
211 snprintf(tmpSID,
sizeof(tmpSID)-1,
"%s%u", szSID, User_primaryGroupID);
213 wcsize = MultiByteToWideChar(CP_ACP, 0, tmpSID, -1, wc, 0);
214 wc = (
wchar_t *)
xmalloc(wcsize *
sizeof(
wchar_t));
215 MultiByteToWideChar(CP_ACP, 0, tmpSID, -1, wc, wcsize);
218 result =
My_NameTranslate(wc, ADS_NAME_TYPE_SID_OR_SID_HISTORY_NAME, ADS_NAME_TYPE_1779);
222 debug(
"Get_primaryGroup: cannot get DN for %s.\n", tmpSID);
224 debug(
"Get_primaryGroup: Primary group DN: %S.\n", result);
235 FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM |
236 FORMAT_MESSAGE_IGNORE_INSERTS,
239 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
249 IADsNameTranslate *pNto;
254 hr = CoInitialize(
nullptr);
262 hr = CoCreateInstance(CLSID_NameTranslate,
264 CLSCTX_INPROC_SERVER,
265 IID_IADsNameTranslate,
272 static const auto emptyStr = SysAllocString(L
"");
273 hr = pNto->Init(ADS_NAME_INITTYPE_GC, emptyStr);
280 hr = pNto->Set(in_format, name);
287 hr = pNto->Get(out_format, &bstr);
293 debug(
"My_NameTranslate: %S translated to %S\n", name, bstr);
295 wc = (
wchar_t *)
xmalloc((wcslen(bstr) + 1) *
sizeof(wchar_t));
307 wc = (
wchar_t *)
xmalloc((wcslen(Base_DN) + 8) *
sizeof(wchar_t));
310 wcscpy(wc, L
"LDAP://");
312 wcscpy(wc, L
"GC://");
321 static char *DomainName =
nullptr;
322 PDSROLE_PRIMARY_DOMAIN_INFO_BASIC pDSRoleInfo =
nullptr;
325 if ((netret = DsRoleGetPrimaryDomainInformation(
nullptr, DsRolePrimaryDomainInfoBasic, (PBYTE *) & pDSRoleInfo)) == ERROR_SUCCESS) {
330 if ((pDSRoleInfo->MachineRole == DsRole_RoleMemberWorkstation) ||
331 (pDSRoleInfo->MachineRole == DsRole_RoleMemberServer) ||
332 (pDSRoleInfo->MachineRole == DsRole_RoleBackupDomainController) ||
333 (pDSRoleInfo->MachineRole == DsRole_RolePrimaryDomainController)) {
335 size_t len = wcslen(pDSRoleInfo->DomainNameFlat);
339 DomainName = (
char *)
xmalloc(len + 1);
342 WideCharToMultiByte(CP_ACP, 0, pDSRoleInfo->DomainNameFlat, -1, DomainName, len,
nullptr,
nullptr);
345 DomainName[len] =
'\0';
350 debug(
"Member of Domain %s\n", DomainName);
351 debug(
"Into forest %S\n", pDSRoleInfo->DomainForestName);
354 debug(
"Not a Domain member\n");
364 DsRoleFreeMemory(pDSRoleInfo);
381 if (wcscmp(Group, *array) == 0)
402 debug(
"Windows group: %S, Squid group: %S\n", str, *array);
403 if (wcscmp(str, *array) == 0)
414 WCHAR wszGroup[GNLEN + 1];
417 MultiByteToWideChar(CP_ACP, 0, *array,
418 strlen(*array) + 1, wszGroup,
sizeof(wszGroup) /
sizeof(wszGroup[0]));
419 debug(
"Windows group: %S, Squid group: %S\n", str, wszGroup);
435 static const auto memberOfStr = SysAllocString(L
"memberOf");
436 hr = pObj->Get(memberOfStr, &var);
438 if (VT_BSTR == var.vt) {
444 hr = ADsGetObject(Group_Path, IID_IADs, (
void **) &pGrp);
450 hr = ADsGetObject(Group_Path, IID_IADs, (
void **) &pGrp);
463 if (SUCCEEDED(SafeArrayGetLBound(V_ARRAY(&var), 1, &lBound)) &&
464 SUCCEEDED(SafeArrayGetUBound(V_ARRAY(&var), 1, &uBound))) {
466 while (lBound <= uBound) {
467 hr = SafeArrayGetElement(V_ARRAY(&var), &lBound, &elem);
474 hr = ADsGetObject(Group_Path, IID_IADs, (
void **) &pGrp);
480 hr = ADsGetObject(Group_Path, IID_IADs, (
void **) &pGrp);
506 if (hr != E_ADS_PROPERTY_NOT_FOUND)
515 wchar_t *wc =
nullptr;
517 int source_group_format;
518 char Group[GNLEN + 1];
520 wchar_t **wc_array, **entry;
525 if (strchr(*array,
'/')) {
527 source_group_format = ADS_NAME_TYPE_CANONICAL;
529 source_group_format = ADS_NAME_TYPE_NT4;
530 if (!strchr(*array,
'\\')) {
531 strcpy(Group, userdomain);
533 strncat(Group, *array, GNLEN -
sizeof(userdomain) - 1);
538 wcsize = MultiByteToWideChar(CP_ACP, 0, Group, -1, wc, 0);
539 wc = (
wchar_t *)
xmalloc(wcsize *
sizeof(
wchar_t));
540 MultiByteToWideChar(CP_ACP, 0, Group, -1, wc, wcsize);
545 debug(
"build_groups_DN_array: cannot get DN for '%s'.\n", Group);
559 char *Domain_Separator;
560 WCHAR wszUserName[UNLEN + 1];
562 LPLOCALGROUP_USERS_INFO_0 pBuf;
563 LPLOCALGROUP_USERS_INFO_0 pTmpBuf;
565 DWORD dwFlags = LG_INCLUDE_INDIRECT;
566 DWORD dwPrefMaxLen = -1;
567 DWORD dwEntriesRead = 0;
568 DWORD dwTotalEntries = 0;
569 NET_API_STATUS nStatus;
571 DWORD dwTotalCount = 0;
572 LPBYTE pBufTmp =
nullptr;
574 if ((Domain_Separator = strchr(UserName,
'/')))
575 *Domain_Separator =
'\\';
577 debug(
"Valid_Local_Groups: checking group membership of '%s'.\n", UserName);
581 MultiByteToWideChar(CP_ACP, 0, UserName,
582 strlen(UserName) + 1, wszUserName,
sizeof(wszUserName) /
sizeof(wszUserName[0]));
592 nStatus = NetUserGetLocalGroups(
nullptr,
600 pBuf = (LPLOCALGROUP_USERS_INFO_0) pBufTmp;
604 if (nStatus == NERR_Success) {
605 if ((pTmpBuf = pBuf)) {
606 for (i = 0; i < dwEntriesRead; ++i) {
627 NetApiBufferFree(pBuf);
636 WCHAR wszUser[DNLEN + UNLEN + 2];
637 char NTDomain[DNLEN + UNLEN + 2];
639 char *domain_qualify =
nullptr;
640 char User[DNLEN + UNLEN + 2];
643 wchar_t *User_DN =
nullptr, *User_LDAP_path =
nullptr;
644 wchar_t *User_PrimaryGroup =
nullptr;
648 xstrncpy(NTDomain, UserName,
sizeof(NTDomain));
654 if (!domain_qualify) {
657 strncat(User, UserName, UNLEN);
660 domain_qualify[0] =
'\\';
661 xstrncpy(User, NTDomain, DNLEN + UNLEN + 2);
662 domain_qualify[0] =
'\0';
665 debug(
"Valid_Global_Groups: checking group membership of '%s'.\n", User);
669 MultiByteToWideChar(CP_ACP, 0, User,
670 strlen(User) + 1, wszUser,
671 sizeof(wszUser) /
sizeof(wszUser[0]));
674 if (!(User_DN =
My_NameTranslate(wszUser, ADS_NAME_TYPE_NT4, ADS_NAME_TYPE_1779))) {
675 debug(
"Valid_Global_Groups: cannot get DN for '%s'.\n", User);
682 hr = ADsGetObject(User_LDAP_path, IID_IADs, (
void **) &pUser);
684 wchar_t *User_PrimaryGroup_Path;
688 if (!User_PrimaryGroup) {
689 debug(
"Valid_Global_Groups: cannot get Primary Group for '%s'.\n", User);
693 hr = ADsGetObject(User_PrimaryGroup_Path, IID_IADs, (
void **) &pGrp);
699 hr = ADsGetObject(User_PrimaryGroup_Path, IID_IADs, (
void **) &pGrp);
715 hr = ADsGetObject(User_LDAP_path, IID_IADs, (
void **) &pUser);
738 auto tmp = wszGroups;
759 fprintf(stderr,
"Usage: %s [-D domain][-G][-c][-d][-h]\n"
760 " -D default user Domain\n"
761 " -G enable Active Directory Global group mode\n"
762 " -c use case insensitive compare (local mode only)\n"
763 " -d enable debugging\n"
764 " -h this message\n",
774 while (-1 != (opt =
getopt(argc, argv,
"D:Gcdh"))) {
796 fprintf(stderr,
"%s: FATAL: Unknown option: -%c. Exiting\n",
program_name, opt);
811 const char *groups[512];
820 setbuf(stdout,
nullptr);
821 setbuf(stderr,
nullptr);
828 fprintf(stderr,
"%s: FATAL: Can't read machine domain\n",
program_name);
837 debug(
"Domain Global group mode enabled using '%s' as default domain.\n",
DefaultDomain);
839 debug(
"Warning: running in case insensitive mode !!!\n");
845 if (!strchr(buf,
'\n')) {
847 fprintf(stderr,
"%s: ERROR: Too large: %s\n", argv[0], buf);
849 fprintf(stderr,
"%s: ERROR: Too large..: %s\n", argv[0], buf);
850 if (strchr(buf,
'\n'))
856 if ((p = strchr(buf,
'\n')))
858 if ((p = strchr(buf,
'\r')))
861 debug(
"Got '%s' from Squid (length: %zu).\n", buf, strlen(buf));
863 if (buf[0] ==
'\0') {
867 username = strtok(buf,
" ");
868 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)