import HEAD into svn+ssh://svn.samba.org/home/svn/samba/trunk
[metze/old/v3-2-winbind-ndr.git] / source / nsswitch / winbindd_passdb.c
1 /* 
2    Unix SMB/CIFS implementation.
3
4    Winbind rpc backend functions
5
6    Copyright (C) Tim Potter 2000-2001,2003
7    Copyright (C) Simo Sorce 2003
8    Copyright (C) Volker Lendecke 2004
9    
10    This program is free software; you can redistribute it and/or modify
11    it under the terms of the GNU General Public License as published by
12    the Free Software Foundation; either version 2 of the License, or
13    (at your option) any later version.
14    
15    This program is distributed in the hope that it will be useful,
16    but WITHOUT ANY WARRANTY; without even the implied warranty of
17    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18    GNU General Public License for more details.
19    
20    You should have received a copy of the GNU General Public License
21    along with this program; if not, write to the Free Software
22    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23 */
24
25 #include "includes.h"
26 #include "winbindd.h"
27
28 #undef DBGC_CLASS
29 #define DBGC_CLASS DBGC_WINBIND
30
31 static void
32 add_member(const char *domain, const char *user,
33            char **members, int *num_members)
34 {
35         fstring name;
36
37         fill_domain_username(name, domain, user);
38         safe_strcat(name, ",", sizeof(name)-1);
39         string_append(members, name);
40         *num_members += 1;
41 }
42
43 /**********************************************************************
44  Add member users resulting from sid. Expand if it is a domain group.
45 **********************************************************************/
46
47 static void
48 add_expanded_sid(const DOM_SID *sid, char **members, int *num_members)
49 {
50         DOM_SID dom_sid;
51         uint32 rid;
52         struct winbindd_domain *domain;
53         int i;
54
55         char *name = NULL;
56         enum SID_NAME_USE type;
57
58         uint32 num_names;
59         DOM_SID **sid_mem;
60         char **names;
61         uint32 *types;
62
63         NTSTATUS result;
64
65         TALLOC_CTX *mem_ctx = talloc_init("add_expanded_sid");
66
67         if (mem_ctx == NULL) {
68                 DEBUG(1, ("talloc_init failed\n"));
69                 return;
70         }
71
72         sid_copy(&dom_sid, sid);
73         sid_split_rid(&dom_sid, &rid);
74
75         domain = find_domain_from_sid(&dom_sid);
76
77         if (domain == NULL) {
78                 DEBUG(3, ("Could not find domain for sid %s\n",
79                           sid_string_static(sid)));
80                 goto done;
81         }
82
83         result = domain->methods->sid_to_name(domain, mem_ctx, sid,
84                                               &name, &type);
85
86         if (!NT_STATUS_IS_OK(result)) {
87                 DEBUG(3, ("sid_to_name failed for sid %s\n",
88                           sid_string_static(sid)));
89                 goto done;
90         }
91
92         DEBUG(10, ("Found name %s, type %d\n", name, type));
93
94         if (type == SID_NAME_USER) {
95                 add_member(domain->name, name, members, num_members);
96                 goto done;
97         }
98
99         if (type != SID_NAME_DOM_GRP) {
100                 DEBUG(10, ("Alias member %s neither user nor group, ignore\n",
101                            name));
102                 goto done;
103         }
104
105         /* Expand the domain group */
106
107         result = domain->methods->lookup_groupmem(domain, mem_ctx,
108                                                   sid, &num_names,
109                                                   &sid_mem, &names,
110                                                   &types);
111
112         if (!NT_STATUS_IS_OK(result)) {
113                 DEBUG(10, ("Could not lookup group members for %s: %s\n",
114                            name, nt_errstr(result)));
115                 goto done;
116         }
117
118         for (i=0; i<num_names; i++) {
119                 DEBUG(10, ("Adding group member SID %s\n",
120                            sid_string_static(sid_mem[i])));
121
122                 if (types[i] != SID_NAME_USER) {
123                         DEBUG(1, ("Hmmm. Member %s of group %s is no user. "
124                                   "Ignoring.\n", names[i], name));
125                         continue;
126                 }
127
128                 add_member(domain->name, names[i], members, num_members);
129         }
130
131  done:
132         talloc_destroy(mem_ctx);
133         return;
134 }
135
136 BOOL fill_passdb_alias_grmem(struct winbindd_domain *domain,
137                              DOM_SID *group_sid, 
138                              int *num_gr_mem, char **gr_mem, int *gr_mem_len)
139 {
140         DOM_SID *members;
141         int i, num_members;
142
143         *num_gr_mem = 0;
144         *gr_mem = NULL;
145         *gr_mem_len = 0;
146
147         if (!pdb_enum_aliasmem(group_sid, &members, &num_members))
148                 return True;
149
150         for (i=0; i<num_members; i++) {
151                 add_expanded_sid(&members[i], gr_mem, num_gr_mem);
152         }
153
154         SAFE_FREE(members);
155
156         if (*gr_mem != NULL) {
157                 int len;
158
159                 /* We have at least one member, strip off the last "," */
160                 len = strlen(*gr_mem);
161                 (*gr_mem)[len-1] = '\0';
162                 *gr_mem_len = len;
163         }
164
165         return True;
166 }
167
168 /* Query display info for a domain.  This returns enough information plus a
169    bit extra to give an overview of domain users for the User Manager
170    application. */
171 static NTSTATUS query_user_list(struct winbindd_domain *domain,
172                                TALLOC_CTX *mem_ctx,
173                                uint32 *num_entries, 
174                                WINBIND_USERINFO **info)
175 {
176         /* We don't have users */
177         *num_entries = 0;
178         *info = NULL;
179         return NT_STATUS_OK;
180 }
181
182 /* list all domain groups */
183 static NTSTATUS enum_dom_groups(struct winbindd_domain *domain,
184                                 TALLOC_CTX *mem_ctx,
185                                 uint32 *num_entries, 
186                                 struct acct_info **info)
187 {
188         /* We don't have domain groups */
189         *num_entries = 0;
190         *info = NULL;
191         return NT_STATUS_OK;
192 }
193
194 /* List all domain groups */
195
196 static NTSTATUS enum_local_groups(struct winbindd_domain *domain,
197                                 TALLOC_CTX *mem_ctx,
198                                 uint32 *num_entries, 
199                                 struct acct_info **info)
200 {
201         struct acct_info *talloced_info;
202
203         /* Hmm. One billion aliases should be enough for a start */
204
205         if (!pdb_enum_aliases(&domain->sid, 0, 1000000000,
206                               num_entries, info)) {
207                 /* Nothing to report, just exit. */
208                 return NT_STATUS_OK;
209         }
210
211         talloced_info = (struct acct_info *)
212                 talloc_memdup(mem_ctx, *info,
213                               *num_entries * sizeof(struct acct_info));
214
215         SAFE_FREE(*info);
216         *info = talloced_info;
217
218         return NT_STATUS_OK;
219 }
220
221 /* convert a single name to a sid in a domain */
222 static NTSTATUS name_to_sid(struct winbindd_domain *domain,
223                             TALLOC_CTX *mem_ctx,
224                             const char *name,
225                             DOM_SID *sid,
226                             enum SID_NAME_USE *type)
227 {
228         DEBUG(10, ("Finding name %s\n", name));
229
230         if (!pdb_find_alias(name, sid))
231                 return NT_STATUS_NONE_MAPPED;
232
233         *type = SID_NAME_ALIAS;
234         return NT_STATUS_OK;
235 }
236
237 /*
238   convert a domain SID to a user or group name
239 */
240 static NTSTATUS sid_to_name(struct winbindd_domain *domain,
241                             TALLOC_CTX *mem_ctx,
242                             const DOM_SID *sid,
243                             char **name,
244                             enum SID_NAME_USE *type)
245 {
246         struct acct_info info;
247
248         DEBUG(10, ("Converting SID %s\n", sid_string_static(sid)));
249
250         if (!pdb_get_aliasinfo(sid, &info))
251                 return NT_STATUS_NONE_MAPPED;
252
253         *name = talloc_strdup(mem_ctx, info.acct_name);
254         *type = SID_NAME_ALIAS;
255
256         return NT_STATUS_OK;
257 }
258
259 /* Lookup user information from a rid or username. */
260 static NTSTATUS query_user(struct winbindd_domain *domain, 
261                            TALLOC_CTX *mem_ctx, 
262                            const DOM_SID *user_sid,
263                            WINBIND_USERINFO *user_info)
264 {
265         return NT_STATUS_NO_SUCH_USER;
266 }
267
268 /* Lookup groups a user is a member of.  I wish Unix had a call like this! */
269 static NTSTATUS lookup_usergroups(struct winbindd_domain *domain,
270                                   TALLOC_CTX *mem_ctx,
271                                   const DOM_SID *user_sid,
272                                   uint32 *num_groups, DOM_SID ***user_gids)
273 {
274         return NT_STATUS_NO_SUCH_USER;
275 }
276
277
278 /* Lookup group membership given a rid.   */
279 static NTSTATUS lookup_groupmem(struct winbindd_domain *domain,
280                                 TALLOC_CTX *mem_ctx,
281                                 const DOM_SID *group_sid, uint32 *num_names, 
282                                 DOM_SID ***sid_mem, char ***names, 
283                                 uint32 **name_types)
284 {
285         return NT_STATUS_OK;
286 }
287
288 /* find the sequence number for a domain */
289 static NTSTATUS sequence_number(struct winbindd_domain *domain, uint32 *seq)
290 {
291         *seq = 1;
292         return NT_STATUS_OK;
293 }
294
295 /* get a list of trusted domains */
296 static NTSTATUS trusted_domains(struct winbindd_domain *domain,
297                                 TALLOC_CTX *mem_ctx,
298                                 uint32 *num_domains,
299                                 char ***names,
300                                 char ***alt_names,
301                                 DOM_SID **dom_sids)
302 {
303         return NT_STATUS_OK;
304 }
305
306 /* find the domain sid for a domain */
307 static NTSTATUS domain_sid(struct winbindd_domain *domain, DOM_SID *sid)
308 {
309         sid_copy(sid, &domain->sid);
310         return NT_STATUS_OK;
311 }
312
313 /* find alternate names list for the domain 
314  * should we look for netbios aliases?? 
315                                 SSS     */
316 static NTSTATUS alternate_name(struct winbindd_domain *domain)
317 {
318         DEBUG(3,("pdb: alternate_name\n"));
319
320         return NT_STATUS_OK;
321 }
322
323
324 /* the rpc backend methods are exposed via this structure */
325 struct winbindd_methods passdb_methods = {
326         False,
327         query_user_list,
328         enum_dom_groups,
329         enum_local_groups,
330         name_to_sid,
331         sid_to_name,
332         query_user,
333         lookup_usergroups,
334         lookup_groupmem,
335         sequence_number,
336         trusted_domains,
337         domain_sid,
338         alternate_name
339 };