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