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