df0d7552402007690d25f5b5444a1e52f73d05d6
[samba.git] / source / groupdb / groupldap.c
1 /* 
2    Unix SMB/Netbios implementation.
3    Version 2.0.
4    LDAP domain 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 DOMAIN_GRP domgrp;
39
40
41 /***************************************************************
42   Get group and membership information.
43  ****************************************************************/
44
45 static DOMAIN_GRP *ldapgroup_getgrp(DOMAIN_GRP *group,
46                              DOMAIN_GRP_MEMBER **members, int *num_membs)
47 {
48         fstring temp;
49         char **values;
50         DOMAIN_GRP_MEMBER *memblist;
51         int i;
52
53         if(!ldap_entry)
54                 return NULL;
55
56         if(!ldap_get_attribute("cn", group->name)) {
57                 DEBUG(0, ("Missing cn\n"));
58                 return NULL; }
59
60         DEBUG(2,("Retrieving group [%s]\n", group->name));
61
62         if(ldap_get_attribute("rid", temp)) {
63                 group->rid = atoi(temp);
64         } else {
65                 DEBUG(0, ("Missing rid\n"));
66                 return NULL;
67         }
68
69         if(!ldap_get_attribute("description", group->comment))
70                 group->comment[0] = 0;
71
72         group->attr = 0x7;
73
74         if(!members || !num_membs) {
75                 ldap_entry = ldap_next_entry(ldap_struct, ldap_entry);
76                 return group;
77         }
78
79         if(values = ldap_get_values(ldap_struct, ldap_entry, "uidMember")) {
80
81                 DEBUG(0, ("Need to return NT names here\n"));
82
83                 *num_membs = i = ldap_count_values(values);
84                 *members = memblist = malloc(i * sizeof(DOMAIN_GRP_MEMBER));
85
86                 do {
87                         fstrcpy(memblist[--i].name, values[i]);
88                         memblist[i].attr = 0x7;
89                 } while(i > 0);
90
91                 ldap_value_free(values);
92
93         } else {
94                 *num_membs = 0;
95                 *members = NULL;
96         }
97
98         ldap_entry = ldap_next_entry(ldap_struct, ldap_entry);
99         return group;
100 }
101
102
103 /************************************************************************
104   Queues the necessary modifications to save a DOMAIN_GRP structure
105  ************************************************************************/
106
107 static void ldapgroup_grpmods(DOMAIN_GRP *group, LDAPMod ***mods,
108                               int operation)
109 {
110         fstring temp;
111
112         *mods = NULL;
113
114         if(operation == LDAP_MOD_ADD) { /* immutable attributes */
115                 ldap_make_mod(mods, LDAP_MOD_ADD, "objectClass", "sambaGroup");
116                 ldap_make_mod(mods, LDAP_MOD_ADD, "cn", group->name);
117
118                 slprintf(temp, sizeof(temp)-1, "%d", (gid_t)(-1));
119                 ldap_make_mod(mods, LDAP_MOD_ADD, "gidNumber", temp);
120
121                 slprintf(temp, sizeof(temp)-1, "%d", group->rid);
122                 ldap_make_mod(mods, LDAP_MOD_ADD, "rid", temp);
123         }
124
125         ldap_make_mod(mods, operation, "description", group->comment);
126 }
127
128
129 /***************************************************************
130   Begin/end domain group enumeration.
131  ****************************************************************/
132
133 static void *ldapgroup_enumfirst(BOOL update)
134 {
135         int server_role = lp_server_role();
136
137         if (server_role == ROLE_DOMAIN_NONE ||
138                         server_role == ROLE_DOMAIN_MEMBER)
139                 return NULL;
140
141         if (!ldap_open_connection(False))
142                 return NULL;
143
144         ldap_search_for("objectclass=sambaGroup");
145
146         return ldap_struct;
147 }
148
149 static void ldapgroup_enumclose(void *vp)
150 {
151         ldap_close_connection();
152 }
153
154
155 /*************************************************************************
156   Save/restore the current position in a query
157  *************************************************************************/
158
159 static SMB_BIG_UINT ldapgroup_getdbpos(void *vp)
160 {
161         return (SMB_BIG_UINT)((ulong)ldap_entry);
162 }
163
164 static BOOL ldapgroup_setdbpos(void *vp, SMB_BIG_UINT tok)
165 {
166         ldap_entry = (LDAPMessage *)((ulong)tok);
167         return (True);
168 }
169
170
171 /*************************************************************************
172   Return information about domain groups and their members.
173  *************************************************************************/
174
175 static DOMAIN_GRP *ldapgroup_getgrpbynam(const char *name,
176                DOMAIN_GRP_MEMBER **members, int *num_membs)
177 {
178         fstring filter;
179         DOMAIN_GRP *ret;
180
181         if(!ldap_open_connection(False))
182                 return (False);
183
184         slprintf(filter, sizeof(filter)-1,
185                  "(&(cn=%s)(objectClass=sambaGroup))", name);
186         ldap_search_for(filter);
187
188         ret = ldapgroup_getgrp(&domgrp, members, num_membs);
189
190         ldap_close_connection();
191         return ret;
192 }
193
194 static DOMAIN_GRP *ldapgroup_getgrpbygid(gid_t grp_id,
195                DOMAIN_GRP_MEMBER **members, int *num_membs)
196 {
197         fstring filter;
198         DOMAIN_GRP *ret;
199
200         if(!ldap_open_connection(False))
201                 return (False);
202
203         slprintf(filter, sizeof(filter)-1,
204                  "(&(gidNumber=%d)(objectClass=sambaGroup))", grp_id);
205         ldap_search_for(filter);
206
207         ret = ldapgroup_getgrp(&domgrp, members, num_membs);
208
209         ldap_close_connection();
210         return ret;
211 }
212
213 static DOMAIN_GRP *ldapgroup_getgrpbyrid(uint32 grp_rid,
214                DOMAIN_GRP_MEMBER **members, int *num_membs)
215 {
216         fstring filter;
217         DOMAIN_GRP *ret;
218
219         if(!ldap_open_connection(False))
220                 return (False);
221
222         slprintf(filter, sizeof(filter)-1,
223                  "(&(rid=%d)(objectClass=sambaGroup))", grp_rid);
224         ldap_search_for(filter);
225
226         ret = ldapgroup_getgrp(&domgrp, members, num_membs);
227
228         ldap_close_connection();
229         return ret;
230 }
231
232 static DOMAIN_GRP *ldapgroup_getcurrentgrp(void *vp,
233                DOMAIN_GRP_MEMBER **members, int *num_membs)
234 {
235         return ldapgroup_getgrp(&domgrp, members, num_membs);
236 }
237
238
239 /*************************************************************************
240   Add/modify domain groups.
241  *************************************************************************/
242
243 static BOOL ldapgroup_addgrp(DOMAIN_GRP *group)
244 {
245         LDAPMod **mods;
246
247         ldapgroup_grpmods(group, &mods, LDAP_MOD_ADD); 
248         return ldap_makemods("cn", group->name, mods, True);
249 }
250
251 static BOOL ldapgroup_modgrp(DOMAIN_GRP *group)
252 {
253         LDAPMod **mods;
254
255         ldapgroup_grpmods(group, &mods, LDAP_MOD_REPLACE);
256         return ldap_makemods("cn", group->name, mods, False);
257 }
258
259
260 /*************************************************************************
261   Return domain groups that a user is in.
262  *************************************************************************/
263
264 static BOOL ldapgroup_getusergroups(const char *name, DOMAIN_GRP **groups,
265                                     int *num_grps)
266 {
267         DOMAIN_GRP *grouplist;
268         fstring filter;
269         int i;
270
271         slprintf(filter, sizeof(pstring)-1,
272                  "(&(uidMember=%s)(objectclass=sambaGroup))", name);
273         ldap_search_for(filter);
274
275         *num_grps = i = ldap_count_entries(ldap_struct, ldap_results);
276
277         if(!i) {
278                 *groups = NULL;
279                 return (True);
280         }
281
282         *groups = grouplist = malloc(i * sizeof(DOMAIN_GRP));
283         do {
284                 i--;
285         } while(ldapgroup_getgrp(&grouplist[i], NULL, NULL) && (i > 0));
286
287         return (True);
288 }
289
290
291 static struct groupdb_ops ldapgroup_ops =
292 {
293         ldapgroup_enumfirst,
294         ldapgroup_enumclose,
295         ldapgroup_getdbpos,
296         ldapgroup_setdbpos,
297
298         ldapgroup_getgrpbynam,
299         ldapgroup_getgrpbygid,
300         ldapgroup_getgrpbyrid,
301         ldapgroup_getcurrentgrp,
302
303         ldapgroup_addgrp,
304         ldapgroup_modgrp,
305
306         ldapgroup_getusergroups
307 };
308
309 struct groupdb_ops *ldap_initialise_group_db(void)
310 {
311         return &ldapgroup_ops;
312 }
313
314 #else
315  void groupldap_dummy_function(void);
316  void groupldap_dummy_function(void) { } /* stop some compilers complaining */
317 #endif
318