sync'ing up for 3.0alpha20 release
[tprouty/samba.git] / source / groupdb / groupdb.c
1 /* 
2    Unix SMB/CIFS implementation.
3    Password and authentication handling
4    Copyright (C) Jeremy Allison 1996-1998
5    Copyright (C) Luke Kenneth Casson Leighton 1996-1998
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 /*
25  * NOTE. All these functions are abstracted into a structure
26  * that points to the correct function for the selected database. JRA.
27  */
28
29 static struct groupdb_ops *gpdb_ops;
30
31 /***************************************************************
32  Initialise the group db operations.
33 ***************************************************************/
34
35 BOOL initialise_group_db(void)
36 {
37   if (gpdb_ops)
38   {
39     return True;
40   }
41
42 #ifdef WITH_LDAP
43   gpdb_ops = ldap_initialise_group_db();
44 #else 
45   gpdb_ops = file_initialise_group_db();
46 #endif 
47
48   return (gpdb_ops != NULL);
49 }
50
51 /*
52  * Functions that return/manipulate a DOMAIN_GRP.
53  */
54
55 /************************************************************************
56  Utility function to search group database by gid: the DOMAIN_GRP
57  structure does not have a gid member, so we have to convert here
58  from gid to group rid.
59 *************************************************************************/
60 DOMAIN_GRP *iterate_getgroupgid(gid_t gid, DOMAIN_GRP_MEMBER **mem, int *num_mem)
61 {
62         return iterate_getgrouprid(pwdb_gid_to_group_rid(gid), mem, num_mem);
63 }
64
65 /************************************************************************
66  Utility function to search group database by rid.  use this if your database
67  does not have search facilities.
68 *************************************************************************/
69 DOMAIN_GRP *iterate_getgrouprid(uint32 rid, DOMAIN_GRP_MEMBER **mem, int *num_mem)
70 {
71         DOMAIN_GRP *grp = NULL;
72         void *fp = NULL;
73
74         DEBUG(10, ("search by rid: 0x%x\n", rid));
75
76         /* Open the group database file - not for update. */
77         fp = startgroupent(False);
78
79         if (fp == NULL)
80         {
81                 DEBUG(0, ("unable to open group database.\n"));
82                 return NULL;
83         }
84
85         while ((grp = getgroupent(fp, mem, num_mem)) != NULL && grp->rid != rid)
86         {
87         }
88
89         if (grp != NULL)
90         {
91                 DEBUG(10, ("found group %s by rid: 0x%x\n", grp->name, rid));
92         }
93
94         endgroupent(fp);
95         return grp;
96 }
97
98 /************************************************************************
99  Utility function to search group database by name.  use this if your database
100  does not have search facilities.
101 *************************************************************************/
102 DOMAIN_GRP *iterate_getgroupnam(char *name, DOMAIN_GRP_MEMBER **mem, int *num_mem)
103 {
104         DOMAIN_GRP *grp = NULL;
105         void *fp = NULL;
106
107         DEBUG(10, ("search by name: %s\n", name));
108
109         /* Open the group database file - not for update. */
110         fp = startgroupent(False);
111
112         if (fp == NULL)
113         {
114                 DEBUG(0, ("unable to open group database.\n"));
115                 return NULL;
116         }
117
118         while ((grp = getgroupent(fp, mem, num_mem)) != NULL && !strequal(grp->name, name))
119         {
120         }
121
122         if (grp != NULL)
123         {
124                 DEBUG(10, ("found by name: %s\n", name));
125         }
126
127         endgroupent(fp);
128         return grp;
129 }
130
131 /*************************************************************************
132  Routine to return the next entry in the smbdomaingroup list.
133  *************************************************************************/
134 BOOL add_domain_group(DOMAIN_GRP **grps, int *num_grps, DOMAIN_GRP *grp)
135 {
136         DOMAIN_GRP *tgrps;
137
138         if (grps == NULL || num_grps == NULL || grp == NULL)
139                 return False;
140
141         tgrps = Realloc((*grps), ((*num_grps)+1) * sizeof(DOMAIN_GRP));
142         if (tgrps == NULL) {
143                 SAFE_FREE(*grps);
144                 return False;
145         } else
146                 (*grps) = tgrps;
147
148         DEBUG(10,("adding group %s(%s)\n", grp->name, grp->comment));
149
150         fstrcpy((*grps)[(*num_grps)].name   , grp->name);
151         fstrcpy((*grps)[(*num_grps)].comment, grp->comment);
152         (*grps)[(*num_grps)].attr = grp->attr;
153         (*grps)[(*num_grps)].rid  = grp->rid ;
154
155         (*num_grps)++;
156
157         return True;
158 }
159
160 /*************************************************************************
161  checks to see if a user is a member of a domain group
162  *************************************************************************/
163 static BOOL user_is_member(char *user_name, DOMAIN_GRP_MEMBER *mem, int num_mem)
164 {
165         int i;
166         for (i = 0; i < num_mem; i++)
167         {
168                 DEBUG(10,("searching against user %s...\n", mem[i].name));
169                 if (strequal(mem[i].name, user_name))
170                 {
171                         DEBUG(10,("searching for user %s: found\n", user_name));
172                         return True;
173                 }
174         }
175         DEBUG(10,("searching for user %s: not found\n", user_name));
176         return False;
177 }
178
179 /*************************************************************************
180  gets an array of groups that a user is in.  use this if your database
181  does not have search facilities
182  *************************************************************************/
183 BOOL iterate_getusergroupsnam(char *user_name, DOMAIN_GRP **grps, int *num_grps)
184 {
185         DOMAIN_GRP *grp;
186         DOMAIN_GRP_MEMBER *mem = NULL;
187         int num_mem = 0;
188         void *fp = NULL;
189
190         DEBUG(10, ("search for usergroups by name: %s\n", user_name));
191
192         if (user_name == NULL || grp == NULL || num_grps == NULL)
193         {
194                 return False;
195         }
196
197         (*grps) = NULL;
198         (*num_grps) = 0;
199
200         /* Open the group database file - not for update. */
201         fp = startgroupent(False);
202
203         if (fp == NULL)
204         {
205                 DEBUG(0, ("unable to open group database.\n"));
206                 return False;
207         }
208
209         /* iterate through all groups.  search members for required user */
210         while ((grp = getgroupent(fp, &mem, &num_mem)) != NULL)
211         {
212                 DEBUG(5,("group name %s members: %d\n", grp->name, num_mem));
213                 if (num_mem != 0 && mem != NULL)
214                 {
215                         BOOL ret = True;
216                         if (user_is_member(user_name, mem, num_mem))
217                         {
218                                 ret = add_domain_group(grps, num_grps, grp);
219                         }
220
221                         SAFE_FREE(mem);
222                         num_mem = 0;
223
224                         if (!ret)
225                         {
226                                 (*num_grps) = 0;
227                                 break;
228                         }
229                 }
230         }
231
232         if ((*num_grps) != 0)
233         {
234                 DEBUG(10, ("found %d user groups:\n", (*num_grps)));
235         }
236
237         endgroupent(fp);
238         return True;
239 }
240
241 /*************************************************************************
242  gets an array of groups that a user is in.  use this if your database
243  does not have search facilities
244  *************************************************************************/
245 BOOL enumdomgroups(DOMAIN_GRP **grps, int *num_grps)
246 {
247         DOMAIN_GRP *grp;
248         void *fp = NULL;
249
250         DEBUG(10, ("enum user groups\n"));
251
252         if (grp == NULL || num_grps == NULL)
253         {
254                 return False;
255         }
256
257         (*grps) = NULL;
258         (*num_grps) = 0;
259
260         /* Open the group database file - not for update. */
261         fp = startgroupent(False);
262
263         if (fp == NULL)
264         {
265                 DEBUG(0, ("unable to open group database.\n"));
266                 return False;
267         }
268
269         /* iterate through all groups. */
270         while ((grp = getgroupent(fp, NULL, NULL)) != NULL)
271         {
272                 if (!add_domain_group(grps, num_grps, grp))
273                 {
274                         DEBUG(0,("unable to add group while enumerating\n"));
275                         return False;
276                 }
277         }
278
279         if ((*num_grps) != 0)
280         {
281                 DEBUG(10, ("found %d user groups:\n", (*num_grps)));
282         }
283
284         endgroupent(fp);
285         return True;
286 }
287
288 /***************************************************************
289  Start to enumerate the group database list. Returns a void pointer
290  to ensure no modification outside this module.
291 ****************************************************************/
292
293 void *startgroupent(BOOL update)
294 {
295   return gpdb_ops->startgroupent(update);
296 }
297
298 /***************************************************************
299  End enumeration of the group database list.
300 ****************************************************************/
301
302 void endgroupent(void *vp)
303 {
304   gpdb_ops->endgroupent(vp);
305 }
306
307 /*************************************************************************
308  Routine to return the next entry in the group database list.
309  *************************************************************************/
310
311 DOMAIN_GRP *getgroupent(void *vp, DOMAIN_GRP_MEMBER **mem, int *num_mem)
312 {
313         return gpdb_ops->getgroupent(vp, mem, num_mem);
314 }
315
316 /************************************************************************
317  Routine to add an entry to the group database file.
318 *************************************************************************/
319
320 BOOL add_group_entry(DOMAIN_GRP *newgrp)
321 {
322         return gpdb_ops->add_group_entry(newgrp);
323 }
324
325 /************************************************************************
326  Routine to search the group database file for an entry matching the groupname.
327  and then replace the entry.
328 ************************************************************************/
329
330 BOOL mod_group_entry(DOMAIN_GRP* grp)
331 {
332         return gpdb_ops->mod_group_entry(grp);
333 }
334
335 /************************************************************************
336  Routine to search group database by name.
337 *************************************************************************/
338
339 DOMAIN_GRP *getgroupnam(char *name, DOMAIN_GRP_MEMBER **mem, int *num_mem)
340 {
341         return gpdb_ops->getgroupnam(name, mem, num_mem);
342 }
343
344 /************************************************************************
345  Routine to search group database by group rid.
346 *************************************************************************/
347
348 DOMAIN_GRP *getgrouprid(uint32 group_rid, DOMAIN_GRP_MEMBER **mem, int *num_mem)
349 {
350         return gpdb_ops->getgrouprid(group_rid, mem, num_mem);
351 }
352
353 /************************************************************************
354  Routine to search group database by gid.
355 *************************************************************************/
356
357 DOMAIN_GRP *getgroupgid(gid_t gid, DOMAIN_GRP_MEMBER **mem, int *num_mem)
358 {
359         return gpdb_ops->getgroupgid(gid, mem, num_mem);
360 }
361
362 /*************************************************************************
363  gets an array of groups that a user is in.
364  *************************************************************************/
365 BOOL getusergroupsnam(char *user_name, DOMAIN_GRP **grp, int *num_grps)
366 {
367         return gpdb_ops->getusergroupsnam(user_name, grp, num_grps);
368 }
369
370 /*************************************************************
371  initialises a DOMAIN_GRP.
372  **************************************************************/
373
374 void gpdb_init_grp(DOMAIN_GRP *grp)
375 {
376         if (grp == NULL) return;
377         ZERO_STRUCTP(grp);
378 }
379