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