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