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
50 isc_result_t
isc_ntsecurity_getaccountgroups(char * username,char ** GroupList,unsigned int maxgroups,unsigned int * totalGroups)51 isc_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