diff options
Diffstat (limited to 'lib/isc/win32/ntgroups.c')
-rw-r--r-- | lib/isc/win32/ntgroups.c | 177 |
1 files changed, 177 insertions, 0 deletions
diff --git a/lib/isc/win32/ntgroups.c b/lib/isc/win32/ntgroups.c new file mode 100644 index 0000000..e3a45ca --- /dev/null +++ b/lib/isc/win32/ntgroups.c @@ -0,0 +1,177 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * 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/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + + +/* + * 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. + */ + +#ifndef UNICODE +#define UNICODE +#endif /* UNICODE */ + +/* + * Silence warnings. + */ +#define _CRT_SECURE_NO_DEPRECATE 1 + +#include <windows.h> +#include <assert.h> +#include <lm.h> + +#include <isc/ntgroups.h> +#include <isc/result.h> + +#define MAX_NAME_LENGTH 256 + +isc_result_t +isc_ntsecurity_getaccountgroups(char *username, char **GroupList, + unsigned int maxgroups, + unsigned int *totalGroups) { + 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; + size_t retlen; + wchar_t user[MAX_NAME_LENGTH]; + + retlen = mbstowcs(user, username, MAX_NAME_LENGTH); + + *totalGroups = 0; + /* + * Call the NetUserGetLocalGroups function + * specifying information level 0. + * + * The LG_INCLUDE_INDIRECT flag specifies that the + * function should also return the names of the local + * groups in which the user is indirectly a member. + */ + nStatus = NetUserGetLocalGroups(NULL, + user, + dwLevel, + dwFlags, + (LPBYTE *) &pBuf, + dwPrefMaxLen, + &dwEntriesRead, + &dwTotalEntries); + /* + * See if the call succeeds, + */ + if (nStatus != NERR_Success) { + if (nStatus == ERROR_ACCESS_DENIED) + return (ISC_R_NOPERM); + if (nStatus == ERROR_MORE_DATA) + return (ISC_R_NOSPACE); + if (nStatus == NERR_UserNotFound) + dwEntriesRead = 0; + } + + if (pBuf != NULL) { + pTmpLBuf = pBuf; + /* + * Loop through the entries + */ + for (i = 0; + (i < dwEntriesRead && *totalGroups < maxgroups); i++) { + assert(pTmpLBuf != NULL); + if (pTmpLBuf == NULL) + break; + retlen = wcslen(pTmpLBuf->lgrui0_name); + GroupList[*totalGroups] = (char *) malloc(retlen +1); + if (GroupList[*totalGroups] == NULL) + return (ISC_R_NOMEMORY); + + retlen = wcstombs(GroupList[*totalGroups], + pTmpLBuf->lgrui0_name, retlen); + GroupList[*totalGroups][retlen] = '\0'; + if (strcmp(GroupList[*totalGroups], "None") == 0) + free(GroupList[*totalGroups]); + else + (*totalGroups)++; + pTmpLBuf++; + } + } + /* Free the allocated memory. */ + if (pBuf != NULL) + NetApiBufferFree(pBuf); + + + /* + * Call the NetUserGetGroups function, specifying level 0. + */ + nStatus = NetUserGetGroups(NULL, + user, + dwLevel, + (LPBYTE*)&pgrpBuf, + dwPrefMaxLen, + &dwEntriesRead, + &dwTotalEntries); + /* + * See if the call succeeds, + */ + if (nStatus != NERR_Success) { + if (nStatus == ERROR_ACCESS_DENIED) + return (ISC_R_NOPERM); + if (nStatus == ERROR_MORE_DATA) + return (ISC_R_NOSPACE); + if (nStatus == NERR_UserNotFound) + dwEntriesRead = 0; + } + + if (pgrpBuf != NULL) { + pTmpBuf = pgrpBuf; + /* + * Loop through the entries + */ + for (i = 0; + (i < dwEntriesRead && *totalGroups < maxgroups); i++) { + assert(pTmpBuf != NULL); + + if (pTmpBuf == NULL) + break; + retlen = wcslen(pTmpBuf->grui0_name); + GroupList[*totalGroups] = (char *) malloc(retlen +1); + if (GroupList[*totalGroups] == NULL) + return (ISC_R_NOMEMORY); + + retlen = wcstombs(GroupList[*totalGroups], + pTmpBuf->grui0_name, retlen); + GroupList[*totalGroups][retlen] = '\0'; + if (strcmp(GroupList[*totalGroups], "None") == 0) + free(GroupList[*totalGroups]); + else + (*totalGroups)++; + pTmpBuf++; + } + } + /* + * Free the allocated memory. + */ + if (pgrpBuf != NULL) + NetApiBufferFree(pgrpBuf); + + return (ISC_R_SUCCESS); +} |