Finally committing my LDAP changes.
[samba.git] / source3 / groupdb / builtinldap.c
1 /* 
2    Unix SMB/Netbios implementation.
3    Version 2.0.
4    LDAP builtin group database for SAMBA
5    Copyright (C) Matthew Chapman 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
23 #include "includes.h"
24
25 #ifdef WITH_LDAP
26
27 #include <lber.h>
28 #include <ldap.h>
29
30 extern int DEBUGLEVEL;
31
32 /* Internal state */
33 extern LDAP *ldap_struct;
34 extern LDAPMessage *ldap_results;
35 extern LDAPMessage *ldap_entry;
36
37 /* Static structure filled for requests */
38 static LOCAL_GRP localgrp;
39
40
41 /***************************************************************
42   Get group and membership information.
43  ****************************************************************/
44
45 static LOCAL_GRP *ldapbuiltin_getgrp(LOCAL_GRP *group,
46                      LOCAL_GRP_MEMBER **members, int *num_membs)
47 {
48         fstring temp;
49         char **values;
50         LOCAL_GRP_MEMBER *memblist;
51         char *value, *sep;
52         int i;
53
54         if(!ldap_entry)
55                 return NULL;
56
57         if(!ldap_get_attribute("cn", group->name)) {
58                 DEBUG(0, ("Missing cn\n"));
59                 return NULL; }
60         
61         DEBUG(2,("Retrieving builtin alias [%s]\n", group->name));
62
63         if(ldap_get_attribute("rid", temp)) {
64                 group->rid = strtol(temp, NULL, 16);
65         } else {
66                 DEBUG(0, ("Missing rid\n"));
67                 return NULL;
68         }
69
70         if(!ldap_get_attribute("description", group->comment))
71                 group->comment[0] = 0;
72
73         if(!members || !num_membs) {
74                 ldap_entry = ldap_next_entry(ldap_struct, ldap_entry);
75                 return group;
76         }
77
78         if(values = ldap_get_values(ldap_struct, ldap_entry, "member")) {
79
80                 *num_membs = i = ldap_count_values(values);
81                 *members = memblist = malloc(i * sizeof(LOCAL_GRP_MEMBER));
82
83                 do {
84                         value = values[--i];
85
86                         if(!(sep = strchr(value, ','))) {
87                                 DEBUG(0, ("Malformed alias member\n"));
88                                 return NULL;
89                         }
90                         *(sep++) = 0;
91                         fstrcpy(memblist[i].name, value);
92
93                         if(!(value = strchr(sep, ','))) {
94                                 DEBUG(0, ("Malformed alias member\n"));
95                                 return NULL;
96                         }
97                         *(value++) = 0;
98                         string_to_sid(&memblist[i].sid, sep);
99
100                         if((memblist[i].sid_use = atoi(value))
101                                         >= SID_NAME_UNKNOWN)
102                                 DEBUG(0, ("Invalid SID use in alias"));
103
104                 } while(i > 0);
105
106                 ldap_value_free(values);
107
108         } else {
109                 *num_membs = 0;
110                 *members = NULL;
111         }
112
113         return group;
114 }
115
116
117 /************************************************************************
118   Queues the necessary modifications to save a LOCAL_GRP structure
119  ************************************************************************/
120
121 static void ldapbuiltin_grpmods(LOCAL_GRP *group, LDAPMod ***mods,
122                         int operation)
123 {
124         fstring temp;
125
126         *mods = NULL;
127
128         if(operation == LDAP_MOD_ADD) { /* immutable attributes */
129                 ldap_make_mod(mods, LDAP_MOD_ADD, "objectClass", "sambaBuiltin");
130                 ldap_make_mod(mods, LDAP_MOD_ADD, "cn", group->name);
131
132                 slprintf(temp, sizeof(temp)-1, "%x", group->rid);
133                 ldap_make_mod(mods, LDAP_MOD_ADD, "rid", temp);
134         }
135
136         ldap_make_mod(mods, operation, "description", group->comment);
137 }
138
139
140 /************************************************************************
141   Create a builtin alias member entry
142  ************************************************************************/
143
144 static BOOL ldapbuiltin_memmods(DOM_SID *user_sid, LDAPMod ***mods,
145                               int operation)
146 {
147         pstring member;
148         pstring sid_str;
149         fstring name;
150         uint8 type;
151
152         if (lookup_sid(user_sid, name, &type))
153                 return (False);
154         sid_to_string(sid_str, user_sid);
155
156         slprintf(member, sizeof(member)-1, "%s,%s,%d", name, sid_str, type);
157
158         *mods = NULL;
159         ldap_make_mod(mods, operation, "member", member);
160         return True;
161 }
162
163
164 /***************************************************************
165   Begin/end smbgrp enumeration.
166  ****************************************************************/
167
168 static void *ldapbuiltin_enumfirst(BOOL update)
169 {
170         if (lp_server_role() == ROLE_DOMAIN_NONE)
171                 return NULL;
172
173         if (!ldap_connect())
174                 return NULL;
175
176         ldap_search_for("objectClass=sambaBuiltin");
177
178         return ldap_struct;
179 }
180
181 static void ldapbuiltin_enumclose(void *vp)
182 {
183         ldap_disconnect();
184 }
185
186
187 /*************************************************************************
188   Save/restore the current position in a query
189  *************************************************************************/
190
191 static SMB_BIG_UINT ldapbuiltin_getdbpos(void *vp)
192 {
193         return (SMB_BIG_UINT)((ulong)ldap_entry);
194 }
195
196 static BOOL ldapbuiltin_setdbpos(void *vp, SMB_BIG_UINT tok)
197 {
198         ldap_entry = (LDAPMessage *)((ulong)tok);
199         return (True);
200 }
201
202
203 /*************************************************************************
204   Return limited smb_passwd information, and group membership.
205  *************************************************************************/
206
207 static LOCAL_GRP *ldapbuiltin_getgrpbynam(const char *name,
208                LOCAL_GRP_MEMBER **members, int *num_membs)
209 {
210         fstring filter;
211         LOCAL_GRP *ret;
212
213         if(!ldap_connect())
214                 return (False);
215
216         slprintf(filter, sizeof(filter)-1,
217                  "(&(cn=%s)(objectClass=sambaBuiltin))", name);
218         ldap_search_for(filter);
219
220         ret = ldapbuiltin_getgrp(&localgrp, members, num_membs);
221
222         ldap_disconnect();
223         return ret;
224 }
225
226 static LOCAL_GRP *ldapbuiltin_getgrpbygid(gid_t grp_id,
227                LOCAL_GRP_MEMBER **members, int *num_membs)
228 {
229         fstring filter;
230         LOCAL_GRP *ret;
231
232         if(!ldap_connect())
233                 return (False);
234
235         slprintf(filter, sizeof(filter)-1,
236                  "(&(gidNumber=%d)(objectClass=sambaBuiltin))", grp_id);
237         ldap_search_for(filter);
238         ret = ldapbuiltin_getgrp(&localgrp, members, num_membs);
239
240         ldap_disconnect();
241         return ret;
242 }
243
244 static LOCAL_GRP *ldapbuiltin_getgrpbyrid(uint32 grp_rid,
245                LOCAL_GRP_MEMBER **members, int *num_membs)
246 {
247         fstring filter;
248         LOCAL_GRP *ret;
249
250         if(!ldap_connect())
251                 return (False);
252
253         slprintf(filter, sizeof(filter)-1,
254                  "(&(rid=%x)(objectClass=sambaBuiltin))", grp_rid);
255         ldap_search_for(filter);
256         ret = ldapbuiltin_getgrp(&localgrp, members, num_membs);
257
258         ldap_disconnect();
259         return ret;
260 }
261
262 static LOCAL_GRP *ldapbuiltin_getcurrentgrp(void *vp,
263                LOCAL_GRP_MEMBER **members, int *num_membs)
264 {
265         return ldapbuiltin_getgrp(&localgrp, members, num_membs);
266 }
267
268
269 /*************************************************************************
270   Add/modify/delete builtin aliases.
271  *************************************************************************/
272
273 static BOOL ldapbuiltin_addgrp(LOCAL_GRP *group)
274 {
275         LDAPMod **mods;
276
277         if (!ldap_allocaterid(&group->rid))
278         {
279             DEBUG(0,("RID generation failed\n"));
280             return (False);
281         }
282
283         ldapbuiltin_grpmods(group, &mods, LDAP_MOD_ADD); 
284         return ldap_makemods("cn", group->name, mods, True);
285 }
286
287 static BOOL ldapbuiltin_modgrp(LOCAL_GRP *group)
288 {
289         LDAPMod **mods;
290
291         ldapbuiltin_grpmods(group, &mods, LDAP_MOD_REPLACE);
292         return ldap_makemods("cn", group->name, mods, False);
293 }
294
295 static BOOL ldapbuiltin_delgrp(uint32 grp_rid)
296 {
297         fstring filter;
298         char *dn;
299         int err;
300
301         if (!ldap_connect())
302                 return (False);
303
304         slprintf(filter, sizeof(filter)-1,
305                  "(&(rid=%x)(objectClass=sambaBuiltin))", grp_rid);
306         ldap_search_for(filter);
307
308         if (!ldap_entry || !(dn = ldap_get_dn(ldap_struct, ldap_entry)))
309         {
310                 ldap_disconnect();
311                 return (False);
312         }
313
314         err = ldap_delete_s(ldap_struct, dn);
315         free(dn);
316         ldap_disconnect();
317
318         if (err != LDAP_SUCCESS)
319         {
320                 DEBUG(0, ("delete: %s\n", ldap_err2string(err)));
321                 return (False);
322         }
323
324         return True;
325 }
326
327
328 /*************************************************************************
329   Add users to/remove users from aliases.
330  *************************************************************************/
331
332 static BOOL ldapbuiltin_addmem(uint32 grp_rid, DOM_SID *user_sid)
333 {
334         LDAPMod **mods;
335         fstring rid_str;
336
337         slprintf(rid_str, sizeof(rid_str)-1, "%x", grp_rid);
338
339         if(!ldapbuiltin_memmods(user_sid, &mods, LDAP_MOD_ADD))
340                 return (False);
341
342         return ldap_makemods("rid", rid_str, mods, False);
343 }
344
345 static BOOL ldapbuiltin_delmem(uint32 grp_rid, DOM_SID *user_sid)
346 {
347         LDAPMod **mods;
348         fstring rid_str;
349
350         slprintf(rid_str, sizeof(rid_str)-1, "%x", grp_rid);
351
352         if(!ldapbuiltin_memmods(user_sid, &mods, LDAP_MOD_DELETE))
353                 return (False);
354
355         return ldap_makemods("rid", rid_str, mods, False);
356 }
357
358
359 /*************************************************************************
360   Return builtin aliases that a user is in.
361  *************************************************************************/
362
363 static BOOL ldapbuiltin_getusergroups(const char *name,
364                         LOCAL_GRP **groups, int *num_grps)
365 {
366         LOCAL_GRP *grouplist;
367         fstring filter;
368         int i;
369
370         if(!ldap_connect())
371                 return (False);
372
373         slprintf(filter, sizeof(pstring)-1,
374                  "(&(member=%s,*)(objectclass=sambaBuiltin))", name);
375         ldap_search_for(filter);
376
377         *num_grps = i = ldap_count_entries(ldap_struct, ldap_results);
378
379         if(!i) {
380                 *groups = NULL;
381                 ldap_disconnect();
382                 return (True);
383         }
384
385         *groups = grouplist = malloc(i * sizeof(LOCAL_GRP));
386         do {
387                 i--;
388         } while(ldapbuiltin_getgrp(&grouplist[i], NULL, NULL) && (i > 0));
389
390         ldap_disconnect();
391         return (True);
392 }
393
394
395 static struct aliasdb_ops ldapbuiltin_ops =
396 {
397         ldapbuiltin_enumfirst,
398         ldapbuiltin_enumclose,
399         ldapbuiltin_getdbpos,
400         ldapbuiltin_setdbpos,
401
402         ldapbuiltin_getgrpbynam,
403         ldapbuiltin_getgrpbygid,
404         ldapbuiltin_getgrpbyrid,
405         ldapbuiltin_getcurrentgrp,
406
407         ldapbuiltin_addgrp,
408         ldapbuiltin_modgrp,
409         ldapbuiltin_delgrp,
410
411         ldapbuiltin_addmem,
412         ldapbuiltin_delmem,
413
414         ldapbuiltin_getusergroups
415 };
416
417 struct aliasdb_ops *ldap_initialise_builtin_db(void)
418 {
419         return &ldapbuiltin_ops;
420 }
421
422 #else
423  void builtinldap_dummy_function(void);
424  void builtinldap_dummy_function(void) { } /* stop some compilers complaining */
425 #endif
426