xref: /netbsd/external/bsd/ntp/dist/lib/isc/win32/ntgroups.c (revision 6550d01e)
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