ntgroups.c revision 290001
1/* 2 * Copyright (C) 2004, 2006, 2007, 2009 Internet Systems Consortium, Inc. ("ISC") 3 * Copyright (C) 2001 Internet Software Consortium. 4 * 5 * Permission to use, copy, modify, and/or distribute this software for any 6 * purpose with or without fee is hereby granted, provided that the above 7 * copyright notice and this permission notice appear in all copies. 8 * 9 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH 10 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 11 * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, 12 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 13 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE 14 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 15 * PERFORMANCE OF THIS SOFTWARE. 16 */ 17 18/* $Id: ntgroups.c,v 1.12 2009/09/29 23:48:04 tbox Exp $ */ 19 20/* 21 * The NT Groups have two groups that are not well documented and are 22 * not normally seen: None and Everyone. A user account belongs to 23 * any number of groups, but if it is not a member of any group then 24 * it is a member of the None Group. The None group is not listed 25 * anywhere. You cannot remove an account from the none group except 26 * by making it a member of some other group, The second group is the 27 * Everyone group. All accounts, no matter how many groups that they 28 * belong to, also belong to the Everyone group. You cannot remove an 29 * account from the Everyone group. 30 */ 31 32#ifndef UNICODE 33#define UNICODE 34#endif /* UNICODE */ 35 36/* 37 * Silence warnings. 38 */ 39#define _CRT_SECURE_NO_DEPRECATE 1 40 41#include <windows.h> 42#include <assert.h> 43#include <lm.h> 44 45#include <isc/ntgroups.h> 46#include <isc/result.h> 47 48#define MAX_NAME_LENGTH 256 49 50isc_result_t 51isc_ntsecurity_getaccountgroups(char *username, char **GroupList, 52 unsigned int maxgroups, 53 unsigned int *totalGroups) { 54 LPGROUP_USERS_INFO_0 pTmpBuf; 55 LPLOCALGROUP_USERS_INFO_0 pTmpLBuf; 56 DWORD i; 57 LPLOCALGROUP_USERS_INFO_0 pBuf = NULL; 58 LPGROUP_USERS_INFO_0 pgrpBuf = NULL; 59 DWORD dwLevel = 0; 60 DWORD dwFlags = LG_INCLUDE_INDIRECT; 61 DWORD dwPrefMaxLen = MAX_PREFERRED_LENGTH; 62 DWORD dwEntriesRead = 0; 63 DWORD dwTotalEntries = 0; 64 NET_API_STATUS nStatus; 65 DWORD dwTotalCount = 0; 66 size_t retlen; 67 wchar_t user[MAX_NAME_LENGTH]; 68 69 retlen = mbstowcs(user, username, MAX_NAME_LENGTH); 70 71 *totalGroups = 0; 72 /* 73 * Call the NetUserGetLocalGroups function 74 * specifying information level 0. 75 * 76 * The LG_INCLUDE_INDIRECT flag specifies that the 77 * function should also return the names of the local 78 * groups in which the user is indirectly a member. 79 */ 80 nStatus = NetUserGetLocalGroups(NULL, 81 user, 82 dwLevel, 83 dwFlags, 84 (LPBYTE *) &pBuf, 85 dwPrefMaxLen, 86 &dwEntriesRead, 87 &dwTotalEntries); 88 /* 89 * See if the call succeeds, 90 */ 91 if (nStatus != NERR_Success) { 92 if (nStatus == ERROR_ACCESS_DENIED) 93 return (ISC_R_NOPERM); 94 if (nStatus == ERROR_MORE_DATA) 95 return (ISC_R_NOSPACE); 96 if (nStatus == NERR_UserNotFound) 97 dwEntriesRead = 0; 98 } 99 100 dwTotalCount = 0; 101 if (pBuf != NULL) { 102 pTmpLBuf = pBuf; 103 /* 104 * Loop through the entries 105 */ 106 for (i = 0; 107 (i < dwEntriesRead && *totalGroups < maxgroups); i++) { 108 assert(pTmpLBuf != NULL); 109 if (pTmpLBuf == NULL) 110 break; 111 retlen = wcslen(pTmpLBuf->lgrui0_name); 112 GroupList[*totalGroups] = (char *) malloc(retlen +1); 113 if (GroupList[*totalGroups] == NULL) 114 return (ISC_R_NOMEMORY); 115 116 retlen = wcstombs(GroupList[*totalGroups], 117 pTmpLBuf->lgrui0_name, retlen); 118 GroupList[*totalGroups][retlen] = '\0'; 119 if (strcmp(GroupList[*totalGroups], "None") == 0) 120 free(GroupList[*totalGroups]); 121 else 122 (*totalGroups)++; 123 pTmpLBuf++; 124 } 125 } 126 /* Free the allocated memory. */ 127 if (pBuf != NULL) 128 NetApiBufferFree(pBuf); 129 130 131 /* 132 * Call the NetUserGetGroups function, specifying level 0. 133 */ 134 nStatus = NetUserGetGroups(NULL, 135 user, 136 dwLevel, 137 (LPBYTE*)&pgrpBuf, 138 dwPrefMaxLen, 139 &dwEntriesRead, 140 &dwTotalEntries); 141 /* 142 * See if the call succeeds, 143 */ 144 if (nStatus != NERR_Success) { 145 if (nStatus == ERROR_ACCESS_DENIED) 146 return (ISC_R_NOPERM); 147 if (nStatus == ERROR_MORE_DATA) 148 return (ISC_R_NOSPACE); 149 if (nStatus == NERR_UserNotFound) 150 dwEntriesRead = 0; 151 } 152 153 if (pgrpBuf != NULL) { 154 pTmpBuf = pgrpBuf; 155 /* 156 * Loop through the entries 157 */ 158 for (i = 0; 159 (i < dwEntriesRead && *totalGroups < maxgroups); i++) { 160 assert(pTmpBuf != NULL); 161 162 if (pTmpBuf == NULL) 163 break; 164 retlen = wcslen(pTmpBuf->grui0_name); 165 GroupList[*totalGroups] = (char *) malloc(retlen +1); 166 if (GroupList[*totalGroups] == NULL) 167 return (ISC_R_NOMEMORY); 168 169 retlen = wcstombs(GroupList[*totalGroups], 170 pTmpBuf->grui0_name, retlen); 171 GroupList[*totalGroups][retlen] = '\0'; 172 if (strcmp(GroupList[*totalGroups], "None") == 0) 173 free(GroupList[*totalGroups]); 174 else 175 (*totalGroups)++; 176 pTmpBuf++; 177 } 178 } 179 /* 180 * Free the allocated memory. 181 */ 182 if (pgrpBuf != NULL) 183 NetApiBufferFree(pgrpBuf); 184 185 return (ISC_R_SUCCESS); 186} 187