Finally committing my LDAP changes.
[samba.git] / source / groupdb / aliasldap.c
1 /* 
2    Unix SMB/Netbios implementation.
3    Version 2.0.
4    LDAP local 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 *ldapalias_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 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 ldapalias_grpmods(LOCAL_GRP *group, LDAPMod ***mods, int operation)
122 {
123         fstring temp;
124
125         *mods = NULL;
126
127         if(operation == LDAP_MOD_ADD) { /* immutable attributes */
128                 ldap_make_mod(mods, LDAP_MOD_ADD, "objectClass", "sambaAlias");
129                 ldap_make_mod(mods, LDAP_MOD_ADD, "cn", group->name);
130
131                 slprintf(temp, sizeof(temp)-1, "%x", group->rid);
132                 ldap_make_mod(mods, LDAP_MOD_ADD, "rid", temp);
133         }
134
135         ldap_make_mod(mods, operation, "description", group->comment);
136 }
137
138
139 /************************************************************************
140   Create a alias member entry
141  ************************************************************************/
142
143 static BOOL ldapalias_memmods(DOM_SID *user_sid, LDAPMod ***mods,
144                               int operation)
145 {
146         pstring member;
147         pstring sid_str;
148         fstring name;
149         uint8 type;
150
151         if (lookup_sid(user_sid, name, &type))
152                 return (False);
153         sid_to_string(sid_str, user_sid);
154
155         slprintf(member, sizeof(member)-1, "%s,%s,%d", name, sid_str, type);
156
157         *mods = NULL;
158         ldap_make_mod(mods, operation, "member", member);
159         return True;
160 }
161
162
163 /***************************************************************
164   Begin/end smbgrp enumeration.
165  ****************************************************************/
166
167 static void *ldapalias_enumfirst(BOOL update)
168 {
169         if (lp_server_role() == ROLE_DOMAIN_NONE)
170                 return NULL;
171
172         if (!ldap_connect())
173                 return NULL;
174
175         ldap_search_for("objectClass=sambaAlias");
176
177         return ldap_struct;
178 }
179
180 static void ldapalias_enumclose(void *vp)
181 {
182         ldap_disconnect();
183 }
184
185
186 /*************************************************************************
187   Save/restore the current position in a query
188  *************************************************************************/
189
190 static SMB_BIG_UINT ldapalias_getdbpos(void *vp)
191 {
192         return (SMB_BIG_UINT)((ulong)ldap_entry);
193 }
194
195 static BOOL ldapalias_setdbpos(void *vp, SMB_BIG_UINT tok)
196 {
197         ldap_entry = (LDAPMessage *)((ulong)tok);
198         return (True);
199 }
200
201
202 /*************************************************************************
203   Return limited smb_passwd information, and group membership.
204  *************************************************************************/
205
206 static LOCAL_GRP *ldapalias_getgrpbynam(const char *name,
207                LOCAL_GRP_MEMBER **members, int *num_membs)
208 {
209         fstring filter;
210         LOCAL_GRP *ret;
211
212         if(!ldap_connect())
213                 return (False);
214
215         slprintf(filter, sizeof(filter)-1,
216                  "(&(cn=%s)(objectClass=sambaAlias))", name);
217         ldap_search_for(filter);
218
219         ret = ldapalias_getgrp(&localgrp, members, num_membs);
220
221         ldap_disconnect();
222         return ret;
223 }
224
225 static LOCAL_GRP *ldapalias_getgrpbygid(gid_t grp_id,
226                LOCAL_GRP_MEMBER **members, int *num_membs)
227 {
228         fstring filter;
229         LOCAL_GRP *ret;
230
231         if(!ldap_connect())
232                 return (False);
233
234         slprintf(filter, sizeof(filter)-1,
235                  "(&(gidNumber=%d)(objectClass=sambaAlias))", grp_id);
236         ldap_search_for(filter);
237         ret = ldapalias_getgrp(&localgrp, members, num_membs);
238
239         ldap_disconnect();
240         return ret;
241 }
242
243 static LOCAL_GRP *ldapalias_getgrpbyrid(uint32 grp_rid,
244                LOCAL_GRP_MEMBER **members, int *num_membs)
245 {
246         fstring filter;
247         LOCAL_GRP *ret;
248
249         if(!ldap_connect())
250                 return (False);
251
252         slprintf(filter, sizeof(filter)-1,
253                  "(&(rid=%x)(objectClass=sambaAlias))", grp_rid);
254         ldap_search_for(filter);
255         ret = ldapalias_getgrp(&localgrp, members, num_membs);
256
257         ldap_disconnect();
258         return ret;
259 }
260
261 static LOCAL_GRP *ldapalias_getcurrentgrp(void *vp,
262                LOCAL_GRP_MEMBER **members, int *num_membs)
263 {
264         return ldapalias_getgrp(&localgrp, members, num_membs);
265 }
266
267
268 /*************************************************************************
269   Add/modify/delete aliases.
270  *************************************************************************/
271
272 static BOOL ldapalias_addgrp(LOCAL_GRP *group)
273 {
274         LDAPMod **mods;
275
276         if (!ldap_allocaterid(&group->rid))
277         {
278                 DEBUG(0,("RID generation failed\n"));
279                 return (False);
280         }
281
282         ldapalias_grpmods(group, &mods, LDAP_MOD_ADD); 
283         return ldap_makemods("cn", group->name, mods, True);
284 }
285
286 static BOOL ldapalias_modgrp(LOCAL_GRP *group)
287 {
288         LDAPMod **mods;
289
290         ldapalias_grpmods(group, &mods, LDAP_MOD_REPLACE);
291         return ldap_makemods("cn", group->name, mods, False);
292 }
293
294 static BOOL ldapalias_delgrp(uint32 grp_rid)
295 {
296         fstring filter;
297         char *dn;
298         int err;
299
300         if (!ldap_connect())
301                 return (False);
302
303         slprintf(filter, sizeof(filter)-1,
304                  "(&(rid=%x)(objectClass=sambaAlias))", grp_rid);
305         ldap_search_for(filter);
306
307         if (!ldap_entry || !(dn = ldap_get_dn(ldap_struct, ldap_entry)))
308         {
309                 ldap_disconnect();
310                 return (False);
311         }
312
313         err = ldap_delete_s(ldap_struct, dn);
314         free(dn);
315         ldap_disconnect();
316
317         if (err != LDAP_SUCCESS)
318         {
319                 DEBUG(0, ("delete: %s\n", ldap_err2string(err)));
320                 return (False);
321         }
322
323         return True;
324 }
325
326
327 /*************************************************************************
328   Add users to/remove users from aliases.
329  *************************************************************************/
330
331 static BOOL ldapalias_addmem(uint32 grp_rid, DOM_SID *user_sid)
332 {
333         LDAPMod **mods;
334         fstring rid_str;
335
336         slprintf(rid_str, sizeof(rid_str)-1, "%x", grp_rid);
337
338         if(!ldapalias_memmods(user_sid, &mods, LDAP_MOD_ADD))
339                 return (False);
340
341         return ldap_makemods("rid", rid_str, mods, False);
342 }
343
344 static BOOL ldapalias_delmem(uint32 grp_rid, DOM_SID *user_sid)
345 {
346         LDAPMod **mods;
347         fstring rid_str;
348
349         slprintf(rid_str, sizeof(rid_str)-1, "%x", grp_rid);
350
351         if(!ldapalias_memmods(user_sid, &mods, LDAP_MOD_DELETE))
352                 return (False);
353
354         return ldap_makemods("rid", rid_str, mods, False);
355 }
356
357
358 /*************************************************************************
359   Return aliases that a user is in.
360  *************************************************************************/
361
362 static BOOL ldapalias_getusergroups(const char *name, LOCAL_GRP **groups,
363                                     int *num_grps)
364 {
365         LOCAL_GRP *grouplist;
366         fstring filter;
367         int i;
368
369         if(!ldap_connect())
370                 return (False);
371
372         slprintf(filter, sizeof(pstring)-1,
373                  "(&(member=%s,*)(objectclass=sambaAlias))", name);
374         ldap_search_for(filter);
375
376         *num_grps = i = ldap_count_entries(ldap_struct, ldap_results);
377
378         if(!i) {
379                 *groups = NULL;
380                 ldap_disconnect();
381                 return (True);
382         }
383
384         *groups = grouplist = malloc(i * sizeof(LOCAL_GRP));
385         do {
386                 i--;
387         } while(ldapalias_getgrp(&grouplist[i], NULL, NULL) && (i > 0));
388
389         ldap_disconnect();
390         return (True);
391 }
392
393
394 static struct aliasdb_ops ldapalias_ops =
395 {
396         ldapalias_enumfirst,
397         ldapalias_enumclose,
398         ldapalias_getdbpos,
399         ldapalias_setdbpos,
400
401         ldapalias_getgrpbynam,
402         ldapalias_getgrpbygid,
403         ldapalias_getgrpbyrid,
404         ldapalias_getcurrentgrp,
405
406         ldapalias_addgrp,
407         ldapalias_modgrp,
408         ldapalias_delgrp,
409
410         ldapalias_addmem,
411         ldapalias_delmem,
412
413         ldapalias_getusergroups
414 };
415
416 struct aliasdb_ops *ldap_initialise_alias_db(void)
417 {
418         return &ldapalias_ops;
419 }
420
421 #else
422  void aliasldap_dummy_function(void);
423  void aliasldap_dummy_function(void) { } /* stop some compilers complaining */
424 #endif
425