xref: /minix3/external/bsd/bind/dist/lib/isc/win32/ntgroups.c (revision 00b67f09dd46474d133c95011a48590a8e8f94c7)
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