2001-09-25 01:37:02 +00:00
|
|
|
/*
|
2018-02-23 09:53:12 +01:00
|
|
|
* Copyright (C) Internet Systems Consortium, Inc. ("ISC")
|
2001-09-25 01:37:02 +00:00
|
|
|
*
|
2016-06-27 14:56:38 +10:00
|
|
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
|
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
|
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
2018-02-23 09:53:12 +01:00
|
|
|
*
|
|
|
|
* See the COPYRIGHT file distributed with this work for additional
|
|
|
|
* information regarding copyright ownership.
|
2001-09-25 01:37:02 +00:00
|
|
|
*/
|
|
|
|
|
|
|
|
/*
|
2001-10-05 22:25:54 +00:00
|
|
|
* The NT Groups have two groups that are not well documented and are
|
|
|
|
* not normally seen: None and Everyone. A user account belongs to
|
|
|
|
* any number of groups, but if it is not a member of any group then
|
|
|
|
* it is a member of the None Group. The None group is not listed
|
|
|
|
* anywhere. You cannot remove an account from the none group except
|
|
|
|
* by making it a member of some other group, The second group is the
|
|
|
|
* Everyone group. All accounts, no matter how many groups that they
|
|
|
|
* belong to, also belong to the Everyone group. You cannot remove an
|
|
|
|
* account from the Everyone group.
|
2001-09-25 01:37:02 +00:00
|
|
|
*/
|
|
|
|
|
|
|
|
#ifndef UNICODE
|
|
|
|
#define UNICODE
|
2001-10-05 22:25:54 +00:00
|
|
|
#endif /* UNICODE */
|
2001-09-25 01:37:02 +00:00
|
|
|
|
2006-10-02 02:27:41 +00:00
|
|
|
/*
|
|
|
|
* Silence warnings.
|
|
|
|
*/
|
|
|
|
#define _CRT_SECURE_NO_DEPRECATE 1
|
|
|
|
|
2001-09-25 01:37:02 +00:00
|
|
|
#include <windows.h>
|
|
|
|
#include <assert.h>
|
|
|
|
#include <lm.h>
|
|
|
|
|
|
|
|
#include <isc/ntgroups.h>
|
2001-10-05 05:51:50 +00:00
|
|
|
#include <isc/result.h>
|
2001-09-25 01:37:02 +00:00
|
|
|
|
2001-10-06 01:10:06 +00:00
|
|
|
#define MAX_NAME_LENGTH 256
|
2001-09-25 01:37:02 +00:00
|
|
|
|
2019-08-08 13:52:44 +10:00
|
|
|
#define CHECK(op) \
|
|
|
|
do { result = (op); if (result != ISC_R_SUCCESS) { goto cleanup; } } while (0)
|
|
|
|
|
2001-10-05 05:51:50 +00:00
|
|
|
isc_result_t
|
2001-09-25 01:37:02 +00:00
|
|
|
isc_ntsecurity_getaccountgroups(char *username, char **GroupList,
|
|
|
|
unsigned int maxgroups,
|
2019-08-08 13:52:44 +10:00
|
|
|
unsigned int *totalGroups)
|
|
|
|
{
|
2001-09-25 01:37:02 +00:00
|
|
|
LPGROUP_USERS_INFO_0 pTmpBuf;
|
|
|
|
LPLOCALGROUP_USERS_INFO_0 pTmpLBuf;
|
|
|
|
DWORD i;
|
|
|
|
LPLOCALGROUP_USERS_INFO_0 pBuf = NULL;
|
|
|
|
LPGROUP_USERS_INFO_0 pgrpBuf = NULL;
|
|
|
|
DWORD dwLevel = 0;
|
|
|
|
DWORD dwFlags = LG_INCLUDE_INDIRECT;
|
|
|
|
DWORD dwPrefMaxLen = MAX_PREFERRED_LENGTH;
|
|
|
|
DWORD dwEntriesRead = 0;
|
|
|
|
DWORD dwTotalEntries = 0;
|
|
|
|
NET_API_STATUS nStatus;
|
2009-09-29 04:38:23 +00:00
|
|
|
size_t retlen;
|
2001-10-05 05:51:50 +00:00
|
|
|
wchar_t user[MAX_NAME_LENGTH];
|
2019-08-08 13:52:44 +10:00
|
|
|
isc_result_t result;
|
|
|
|
|
|
|
|
*totalGroups = 0;
|
2001-09-25 01:37:02 +00:00
|
|
|
|
|
|
|
retlen = mbstowcs(user, username, MAX_NAME_LENGTH);
|
2019-08-08 13:52:44 +10:00
|
|
|
if (retlen == (size_t) (-1)) {
|
|
|
|
return (ISC_R_FAILURE);
|
|
|
|
}
|
2001-09-25 01:37:02 +00:00
|
|
|
|
|
|
|
/*
|
2009-09-29 23:48:04 +00:00
|
|
|
* Call the NetUserGetLocalGroups function
|
2001-09-25 01:37:02 +00:00
|
|
|
* specifying information level 0.
|
|
|
|
*
|
2009-09-29 23:48:04 +00:00
|
|
|
* The LG_INCLUDE_INDIRECT flag specifies that the
|
|
|
|
* function should also return the names of the local
|
2001-09-25 01:37:02 +00:00
|
|
|
* groups in which the user is indirectly a member.
|
|
|
|
*/
|
2019-08-08 13:52:44 +10:00
|
|
|
nStatus = NetUserGetLocalGroups(NULL, user, dwLevel, dwFlags,
|
|
|
|
(LPBYTE *) &pBuf, dwPrefMaxLen,
|
|
|
|
&dwEntriesRead, &dwTotalEntries);
|
2001-09-25 01:37:02 +00:00
|
|
|
/*
|
2001-10-05 05:51:50 +00:00
|
|
|
* See if the call succeeds,
|
2001-09-25 01:37:02 +00:00
|
|
|
*/
|
2001-10-05 05:51:50 +00:00
|
|
|
if (nStatus != NERR_Success) {
|
2019-08-08 13:52:44 +10:00
|
|
|
if (nStatus == ERROR_ACCESS_DENIED) {
|
2001-10-05 05:51:50 +00:00
|
|
|
return (ISC_R_NOPERM);
|
2019-08-08 13:52:44 +10:00
|
|
|
}
|
|
|
|
if (nStatus == ERROR_MORE_DATA) {
|
2001-10-05 05:51:50 +00:00
|
|
|
return (ISC_R_NOSPACE);
|
2019-08-08 13:52:44 +10:00
|
|
|
}
|
|
|
|
if (nStatus == NERR_UserNotFound) {
|
2001-10-05 05:51:50 +00:00
|
|
|
dwEntriesRead = 0;
|
2019-08-08 13:52:44 +10:00
|
|
|
}
|
2001-10-05 05:51:50 +00:00
|
|
|
}
|
2001-09-28 23:34:55 +00:00
|
|
|
|
2001-10-05 05:51:50 +00:00
|
|
|
if (pBuf != NULL) {
|
|
|
|
pTmpLBuf = pBuf;
|
2001-09-25 01:37:02 +00:00
|
|
|
/*
|
|
|
|
* Loop through the entries
|
|
|
|
*/
|
2009-09-29 23:48:04 +00:00
|
|
|
for (i = 0;
|
2001-10-05 05:51:50 +00:00
|
|
|
(i < dwEntriesRead && *totalGroups < maxgroups); i++) {
|
2001-09-25 01:37:02 +00:00
|
|
|
assert(pTmpLBuf != NULL);
|
2019-08-08 13:52:44 +10:00
|
|
|
if (pTmpLBuf == NULL) {
|
2001-09-25 01:37:02 +00:00
|
|
|
break;
|
2019-08-08 13:52:44 +10:00
|
|
|
}
|
2001-09-25 01:37:02 +00:00
|
|
|
retlen = wcslen(pTmpLBuf->lgrui0_name);
|
|
|
|
GroupList[*totalGroups] = (char *) malloc(retlen +1);
|
2019-08-08 13:52:44 +10:00
|
|
|
if (GroupList[*totalGroups] == NULL) {
|
|
|
|
CHECK(ISC_R_NOMEMORY);
|
|
|
|
}
|
2001-10-05 05:51:50 +00:00
|
|
|
|
2001-09-25 01:37:02 +00:00
|
|
|
retlen = wcstombs(GroupList[*totalGroups],
|
2019-08-08 13:52:44 +10:00
|
|
|
pTmpLBuf->lgrui0_name, retlen);
|
|
|
|
if (retlen == (size_t) (-1)) {
|
|
|
|
free(GroupList[*totalGroups]);
|
|
|
|
CHECK(ISC_R_FAILURE);
|
|
|
|
}
|
2001-09-25 01:37:02 +00:00
|
|
|
GroupList[*totalGroups][retlen] = '\0';
|
2019-08-08 13:52:44 +10:00
|
|
|
if (strcmp(GroupList[*totalGroups], "None") == 0) {
|
2001-09-25 01:37:02 +00:00
|
|
|
free(GroupList[*totalGroups]);
|
2019-08-08 13:52:44 +10:00
|
|
|
} else {
|
2001-09-25 01:37:02 +00:00
|
|
|
(*totalGroups)++;
|
2019-08-08 13:52:44 +10:00
|
|
|
}
|
2001-09-25 01:37:02 +00:00
|
|
|
pTmpLBuf++;
|
|
|
|
}
|
|
|
|
}
|
2001-10-05 05:51:50 +00:00
|
|
|
/* Free the allocated memory. */
|
2019-08-08 13:52:44 +10:00
|
|
|
/* cppcheck-suppress duplicateCondition */
|
2001-09-25 01:37:02 +00:00
|
|
|
if (pBuf != NULL)
|
|
|
|
NetApiBufferFree(pBuf);
|
|
|
|
|
2009-09-29 23:48:04 +00:00
|
|
|
|
2001-09-25 01:37:02 +00:00
|
|
|
/*
|
|
|
|
* Call the NetUserGetGroups function, specifying level 0.
|
|
|
|
*/
|
2019-08-08 13:52:44 +10:00
|
|
|
nStatus = NetUserGetGroups(NULL, user, dwLevel,
|
|
|
|
(LPBYTE*)&pgrpBuf, dwPrefMaxLen,
|
|
|
|
&dwEntriesRead, &dwTotalEntries);
|
2001-09-25 01:37:02 +00:00
|
|
|
/*
|
2001-10-05 05:51:50 +00:00
|
|
|
* See if the call succeeds,
|
2001-09-25 01:37:02 +00:00
|
|
|
*/
|
2001-10-05 05:51:50 +00:00
|
|
|
if (nStatus != NERR_Success) {
|
2019-08-08 13:52:44 +10:00
|
|
|
if (nStatus == ERROR_ACCESS_DENIED) {
|
2001-10-05 05:51:50 +00:00
|
|
|
return (ISC_R_NOPERM);
|
2019-08-08 13:52:44 +10:00
|
|
|
}
|
|
|
|
if (nStatus == ERROR_MORE_DATA) {
|
2001-10-05 05:51:50 +00:00
|
|
|
return (ISC_R_NOSPACE);
|
2019-08-08 13:52:44 +10:00
|
|
|
}
|
|
|
|
if (nStatus == NERR_UserNotFound) {
|
2001-10-05 05:51:50 +00:00
|
|
|
dwEntriesRead = 0;
|
2019-08-08 13:52:44 +10:00
|
|
|
}
|
2001-10-05 05:51:50 +00:00
|
|
|
}
|
2009-09-29 23:48:04 +00:00
|
|
|
|
2001-10-05 05:51:50 +00:00
|
|
|
if (pgrpBuf != NULL) {
|
|
|
|
pTmpBuf = pgrpBuf;
|
2001-09-25 01:37:02 +00:00
|
|
|
/*
|
|
|
|
* Loop through the entries
|
|
|
|
*/
|
2009-09-29 23:48:04 +00:00
|
|
|
for (i = 0;
|
2001-10-05 05:51:50 +00:00
|
|
|
(i < dwEntriesRead && *totalGroups < maxgroups); i++) {
|
2001-09-25 01:37:02 +00:00
|
|
|
assert(pTmpBuf != NULL);
|
|
|
|
|
2019-08-08 13:52:44 +10:00
|
|
|
if (pTmpBuf == NULL) {
|
2001-09-25 01:37:02 +00:00
|
|
|
break;
|
2019-08-08 13:52:44 +10:00
|
|
|
}
|
2001-09-25 01:37:02 +00:00
|
|
|
retlen = wcslen(pTmpBuf->grui0_name);
|
|
|
|
GroupList[*totalGroups] = (char *) malloc(retlen +1);
|
2019-08-08 13:52:44 +10:00
|
|
|
if (GroupList[*totalGroups] == NULL) {
|
|
|
|
CHECK(ISC_R_NOMEMORY);
|
|
|
|
}
|
2001-10-05 05:51:50 +00:00
|
|
|
|
2001-09-25 01:37:02 +00:00
|
|
|
retlen = wcstombs(GroupList[*totalGroups],
|
|
|
|
pTmpBuf->grui0_name, retlen);
|
2019-08-08 13:52:44 +10:00
|
|
|
if (retlen == (size_t) (-1)) {
|
|
|
|
free(GroupList[*totalGroups]);
|
|
|
|
CHECK(ISC_R_FAILURE);
|
|
|
|
}
|
2001-09-25 01:37:02 +00:00
|
|
|
GroupList[*totalGroups][retlen] = '\0';
|
2019-08-08 13:52:44 +10:00
|
|
|
if (strcmp(GroupList[*totalGroups], "None") == 0) {
|
2001-09-25 01:37:02 +00:00
|
|
|
free(GroupList[*totalGroups]);
|
2019-08-08 13:52:44 +10:00
|
|
|
} else {
|
2001-09-25 01:37:02 +00:00
|
|
|
(*totalGroups)++;
|
2019-08-08 13:52:44 +10:00
|
|
|
}
|
2001-09-25 01:37:02 +00:00
|
|
|
pTmpBuf++;
|
|
|
|
}
|
|
|
|
}
|
2001-10-05 05:51:50 +00:00
|
|
|
/*
|
|
|
|
* Free the allocated memory.
|
|
|
|
*/
|
2019-08-08 13:52:44 +10:00
|
|
|
/* cppcheck-suppress duplicateCondition */
|
|
|
|
if (pgrpBuf != NULL) {
|
2001-09-25 01:37:02 +00:00
|
|
|
NetApiBufferFree(pgrpBuf);
|
2019-08-08 13:52:44 +10:00
|
|
|
}
|
2001-09-25 01:37:02 +00:00
|
|
|
|
2001-10-05 05:51:50 +00:00
|
|
|
return (ISC_R_SUCCESS);
|
2019-08-08 13:52:44 +10:00
|
|
|
|
|
|
|
cleanup:
|
|
|
|
while (--(*totalGroups) > 0) {
|
|
|
|
free(GroupList[*totalGroups]);
|
|
|
|
}
|
|
|
|
return (result);
|
2001-09-25 01:37:02 +00:00
|
|
|
}
|