Removed version number from file header.
[kai/samba.git] / source3 / lib / util_getent.c
1 /*
2    Unix SMB/CIFS implementation.
3    Samba utility functions
4    Copyright (C) Simo Sorce 2001
5    Copyright (C) Jeremy Allison 2001
6
7    This program is free software; you can redistribute it and/or modify
8    it under the terms of the GNU General Public License as published by
9    the Free Software Foundation; either version 2 of the License, or
10    (at your option) any later version.
11    
12    This program is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15    GNU General Public License for more details.
16    
17    You should have received a copy of the GNU General Public License
18    along with this program; if not, write to the Free Software
19    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 */
21
22 #include "includes.h"
23
24 #if 0
25 static void print_grent_list(struct sys_grent *glist)
26 {
27         DEBUG(100, ("print_grent_list: %x\n", glist ));
28         while (glist) {
29                 DEBUG(100,("glist: %x ", glist));
30                 if (glist->gr_name)
31                         DEBUG(100,(": gr_name = (%x) %s ", glist->gr_name, glist->gr_name));
32                 if (glist->gr_passwd)
33                         DEBUG(100,(": gr_passwd = (%x) %s ", glist->gr_passwd, glist->gr_passwd));
34                 if (glist->gr_mem) {
35                         int i;
36                         for (i = 0; glist->gr_mem[i]; i++)
37                                 DEBUG(100,(" : gr_mem[%d] = (%x) %s ", i, glist->gr_mem[i], glist->gr_mem[i]));
38                 }
39                 DEBUG(100,(": gr_next = %x\n", glist->next ));
40                 glist = glist->next;
41         }
42         DEBUG(100,("FINISHED !\n\n"));
43 }
44 #endif
45
46 /****************************************************************
47  Returns a single linked list of group entries.
48  Use grent_free() to free it after use.
49 ****************************************************************/
50
51 struct sys_grent * getgrent_list(void)
52 {
53         struct sys_grent *glist;
54         struct sys_grent *gent;
55         struct group *grp;
56         
57         gent = (struct sys_grent *) malloc(sizeof(struct sys_grent));
58         if (gent == NULL) {
59                 DEBUG (0, ("Out of memory in getgrent_list!\n"));
60                 return NULL;
61         }
62         memset(gent, '\0', sizeof(struct sys_grent));
63         glist = gent;
64         
65         setgrent();
66         grp = getgrent();
67         if (grp == NULL) {
68                 endgrent();
69                 SAFE_FREE(glist);
70                 return NULL;
71         }
72
73         while (grp != NULL) {
74                 int i,num;
75                 
76                 if (grp->gr_name) {
77                         if ((gent->gr_name = strdup(grp->gr_name)) == NULL)
78                                 goto err;
79                 }
80                 if (grp->gr_passwd) {
81                         if ((gent->gr_passwd = strdup(grp->gr_passwd)) == NULL)
82                                 goto err;
83                 }
84                 gent->gr_gid = grp->gr_gid;
85                 
86                 /* number of strings in gr_mem */
87                 for (num = 0; grp->gr_mem[num]; num++)
88                         ;
89                 
90                 /* alloc space for gr_mem string pointers */
91                 if ((gent->gr_mem = (char **) malloc((num+1) * sizeof(char *))) == NULL)
92                         goto err;
93
94                 memset(gent->gr_mem, '\0', (num+1) * sizeof(char *));
95
96                 for (i=0; i < num; i++) {
97                         if ((gent->gr_mem[i] = strdup(grp->gr_mem[i])) == NULL)
98                                 goto err;
99                 }
100                 gent->gr_mem[num] = NULL;
101                 
102                 grp = getgrent();
103                 if (grp) {
104                         gent->next = (struct sys_grent *) malloc(sizeof(struct sys_grent));
105                         if (gent->next == NULL)
106                                 goto err;
107                         gent = gent->next;
108                         memset(gent, '\0', sizeof(struct sys_grent));
109                 }
110         }
111         
112         endgrent();
113         return glist;
114
115   err:
116
117         endgrent();
118         DEBUG(0, ("Out of memory in getgrent_list!\n"));
119         grent_free(glist);
120         return NULL;
121 }
122
123 /****************************************************************
124  Free the single linked list of group entries made by
125  getgrent_list()
126 ****************************************************************/
127
128 void grent_free (struct sys_grent *glist)
129 {
130         while (glist) {
131                 struct sys_grent *prev;
132                 
133                 SAFE_FREE(glist->gr_name);
134                 SAFE_FREE(glist->gr_passwd);
135                 if (glist->gr_mem) {
136                         int i;
137                         for (i = 0; glist->gr_mem[i]; i++)
138                                 SAFE_FREE(glist->gr_mem[i]);
139                         SAFE_FREE(glist->gr_mem);
140                 }
141                 prev = glist;
142                 glist = glist->next;
143                 SAFE_FREE(prev);
144         }
145 }
146
147 /****************************************************************
148  Returns a single linked list of passwd entries.
149  Use pwent_free() to free it after use.
150 ****************************************************************/
151
152 struct sys_pwent * getpwent_list(void)
153 {
154         struct sys_pwent *plist;
155         struct sys_pwent *pent;
156         struct passwd *pwd;
157         
158         pent = (struct sys_pwent *) malloc(sizeof(struct sys_pwent));
159         if (pent == NULL) {
160                 DEBUG (0, ("Out of memory in getpwent_list!\n"));
161                 return NULL;
162         }
163         plist = pent;
164         
165         setpwent();
166         pwd = getpwent();
167         while (pwd != NULL) {
168                 memset(pent, '\0', sizeof(struct sys_pwent));
169                 if (pwd->pw_name) {
170                         if ((pent->pw_name = strdup(pwd->pw_name)) == NULL)
171                                 goto err;
172                 }
173                 if (pwd->pw_passwd) {
174                         if ((pent->pw_passwd = strdup(pwd->pw_passwd)) == NULL)
175                                 goto err;
176                 }
177                 pent->pw_uid = pwd->pw_uid;
178                 pent->pw_gid = pwd->pw_gid;
179                 if (pwd->pw_gecos) {
180                         if ((pent->pw_name = strdup(pwd->pw_gecos)) == NULL)
181                                 goto err;
182                 }
183                 if (pwd->pw_dir) {
184                         if ((pent->pw_name = strdup(pwd->pw_dir)) == NULL)
185                                 goto err;
186                 }
187                 if (pwd->pw_shell) {
188                         if ((pent->pw_name = strdup(pwd->pw_shell)) == NULL)
189                                 goto err;
190                 }
191
192                 pwd = getpwent();
193                 if (pwd) {
194                         pent->next = (struct sys_pwent *) malloc(sizeof(struct sys_pwent));
195                         if (pent->next == NULL)
196                                 goto err;
197                         pent = pent->next;
198                 }
199         }
200         
201         endpwent();
202         return plist;
203
204   err:
205
206         endpwent();
207         DEBUG(0, ("Out of memory in getpwent_list!\n"));
208         pwent_free(plist);
209         return NULL;
210 }
211
212 /****************************************************************
213  Free the single linked list of passwd entries made by
214  getpwent_list()
215 ****************************************************************/
216
217 void pwent_free (struct sys_pwent *plist)
218 {
219         while (plist) {
220                 struct sys_pwent *prev;
221                 
222                 SAFE_FREE(plist->pw_name);
223                 SAFE_FREE(plist->pw_passwd);
224                 SAFE_FREE(plist->pw_gecos);
225                 SAFE_FREE(plist->pw_dir);
226                 SAFE_FREE(plist->pw_shell);
227
228                 prev = plist;
229                 plist = plist->next;
230                 SAFE_FREE(prev);
231         }
232 }
233
234 /****************************************************************
235  Add the individual group users onto the list.
236 ****************************************************************/
237
238 static struct sys_userlist *add_members_to_userlist(struct sys_userlist *list_head, const struct group *grp)
239 {
240         size_t num_users, i;
241
242         /* Count the number of users. */
243         for (num_users = 0; grp->gr_mem[num_users]; num_users++)
244                 ;
245
246         for (i = 0; i < num_users; i++) {
247                 struct sys_userlist *entry = (struct sys_userlist *)malloc(sizeof(*entry));
248                 size_t len = strlen(grp->gr_mem[i])+1;
249                 if (entry == NULL) {
250                         free_userlist(list_head);
251                         return NULL;
252                 }
253                 entry->unix_name = (char *)malloc(len);
254                 if (entry->unix_name == NULL) {
255                         SAFE_FREE(entry);
256                         free_userlist(list_head);
257                         return NULL;
258                 }
259                 safe_strcpy(entry->unix_name, grp->gr_mem[i],len);
260                 DLIST_ADD(list_head, entry);
261         }
262         return list_head;
263 }
264
265 /****************************************************************
266  Get the list of UNIX users in a group.
267  We have to enumerate the /etc/group file as some UNIX getgrnam()
268  calls won't do that for us (notably Tru64 UNIX).
269 ****************************************************************/
270
271 struct sys_userlist *get_users_in_group(const char *gname)
272 {
273         struct sys_userlist *list_head = NULL;
274         struct group *gptr;
275         fstring domain;
276         fstring groupname;
277         DOM_SID sid;
278         enum SID_NAME_USE name_type;
279
280         (void) split_domain_and_name(gname, domain, groupname);
281
282         /*
283          * If we're doing this via winbindd, don't do the
284          * entire group list enumeration as we know this is
285          * pointless (and slow).
286          */
287
288         if (winbind_lookup_name(domain, groupname, &sid, &name_type) && name_type == SID_NAME_DOM_GRP) {
289                 if ((gptr = (struct group *)getgrnam(gname)) == NULL)
290                         return NULL;
291                 return add_members_to_userlist(list_head, gptr);
292         }
293
294         setgrent();
295         while((gptr = getgrent()) != NULL) {
296                 if (strequal(gname, gptr->gr_name)) {
297                         list_head = add_members_to_userlist(list_head, gptr);
298                         if (list_head == NULL)
299                                 return NULL;
300                 }
301         }
302         endgrent();
303         return list_head;
304 }
305
306 /****************************************************************
307  Free list allocated above.
308 ****************************************************************/
309
310 void free_userlist(struct sys_userlist *list_head)
311 {
312         while (list_head) {
313                 struct sys_userlist *old_head = list_head;
314                 DLIST_REMOVE(list_head, list_head);
315                 SAFE_FREE(old_head->unix_name);
316                 SAFE_FREE(old_head);
317         }
318 }