503b97899c418edd7e59d45c5985bacb1c25a192
[samba.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    
9    This program is free software; you can redistribute it and/or modify
10    it under the terms of the GNU General Public License as published by
11    the Free Software Foundation; either version 2 of the License, or
12    (at your option) any later version.
13    
14    This program is distributed in the hope that it will be useful,
15    but WITHOUT ANY WARRANTY; without even the implied warranty of
16    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17    GNU General Public License for more details.
18    
19    You should have received a copy of the GNU General Public License
20    along with this program; if not, write to the Free Software
21    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22 */
23
24 #include "winbindd.h"
25
26 #undef DBGC_CLASS
27 #define DBGC_CLASS DBGC_WINBIND
28
29
30 /* Query display info for a domain.  This returns enough information plus a
31    bit extra to give an overview of domain users for the User Manager
32    application. */
33 static NTSTATUS query_user_list(struct winbindd_domain *domain,
34                                TALLOC_CTX *mem_ctx,
35                                uint32 *num_entries, 
36                                WINBIND_USERINFO **info)
37 {
38         SAM_ACCOUNT *sam_account = NULL;
39         NTSTATUS result;
40         uint32 i;
41
42         DEBUG(3,("pdb: query_user_list\n"));
43
44         if (NT_STATUS_IS_ERR(result = pdb_init_sam(&sam_account))) {
45                 return result;
46         }
47
48         i = 0;
49         *info = NULL;
50         
51         if (pdb_setsampwent(False)) {
52         
53                 while (pdb_getsampwent(sam_account)) {
54                 
55                         /* we return only nua accounts, or we will have duplicates */
56                         if (!idmap_check_sid_is_in_free_range(pdb_get_user_sid(sam_account))) {
57                                 continue;
58                         }
59
60                         *info = talloc_realloc(mem_ctx, *info, (i + 1) * sizeof(WINBIND_USERINFO));
61                         if (!(*info)) {
62                                 DEBUG(0,("query_user_list: out of memory!\n"));
63                                 result = NT_STATUS_NO_MEMORY;
64                                 break;
65                         }
66
67                         (*info)[i].user_sid = talloc(mem_ctx, sizeof(DOM_SID));
68                         (*info)[i].group_sid = talloc(mem_ctx, sizeof(DOM_SID));
69                         if (!((*info)[i].user_sid) || !((*info)[i].group_sid)) {
70                                 DEBUG(0,("query_user_list: out of memory!\n"));
71                                 result = NT_STATUS_NO_MEMORY;
72                                 break;
73                         }
74                         sid_copy((*info)[i].user_sid, pdb_get_user_sid(sam_account));
75                         sid_copy((*info)[i].group_sid, pdb_get_group_sid(sam_account));
76
77                         (*info)[i].acct_name = talloc_strdup(mem_ctx, pdb_get_username(sam_account));
78                         (*info)[i].full_name = talloc_strdup(mem_ctx, pdb_get_fullname(sam_account));
79                         if (!((*info)[i].acct_name) || !((*info)[i].full_name)) {
80                                 DEBUG(0,("query_user_list: out of memory!\n"));
81                                 result = NT_STATUS_NO_MEMORY;
82                                 break;
83                         }
84
85                         i++;
86
87                         if (NT_STATUS_IS_ERR(pdb_reset_sam(sam_account))) {
88                                 result = NT_STATUS_UNSUCCESSFUL;
89                                 break;
90                         }
91                 }
92
93                 *num_entries = i;
94                 result = NT_STATUS_OK;
95         
96         } else {
97                 result = NT_STATUS_UNSUCCESSFUL;
98         }
99
100         pdb_free_sam(&sam_account);
101         return result;
102 }
103
104 /* list all domain groups */
105 static NTSTATUS enum_dom_groups(struct winbindd_domain *domain,
106                                 TALLOC_CTX *mem_ctx,
107                                 uint32 *num_entries, 
108                                 struct acct_info **info)
109 {
110         NTSTATUS result = NT_STATUS_OK;
111
112         DEBUG(3,("pdb: enum_dom_groups (group support not implemented)\n"));
113
114         *num_entries = 0;
115         *info = 0;
116
117         return result;  
118 }
119
120 /* List all domain groups */
121
122 static NTSTATUS enum_local_groups(struct winbindd_domain *domain,
123                                 TALLOC_CTX *mem_ctx,
124                                 uint32 *num_entries, 
125                                 struct acct_info **info)
126 {
127         NTSTATUS result = NT_STATUS_OK;
128
129         DEBUG(3,("pdb: enum_local_groups (group support not implemented)\n"));
130
131         *num_entries = 0;
132         *info = 0;
133
134         return result;  
135 }
136
137 /* convert a single name to a sid in a domain */
138 static NTSTATUS name_to_sid(struct winbindd_domain *domain,
139                             TALLOC_CTX *mem_ctx,
140                             const char *name,
141                             DOM_SID *sid,
142                             enum SID_NAME_USE *type)
143 {
144         SAM_ACCOUNT *sam_account = NULL;
145         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
146
147         DEBUG(3,("pdb: name_to_sid name=%s (group support not implemented)\n", name));
148
149         if (NT_STATUS_IS_OK(pdb_init_sam(&sam_account))) {
150                 if (!pdb_getsampwnam(sam_account, name)) {
151                         result = NT_STATUS_UNSUCCESSFUL;
152                 } else { /* it is a sam user */
153                         sid_copy(sid, pdb_get_user_sid(sam_account));
154                         *type = SID_NAME_USER;
155                         result = NT_STATUS_OK;
156                 }
157         }
158
159         pdb_free_sam(&sam_account);
160         return result;  
161 }
162
163 /*
164   convert a domain SID to a user or group name
165 */
166 static NTSTATUS sid_to_name(struct winbindd_domain *domain,
167                             TALLOC_CTX *mem_ctx,
168                             DOM_SID *sid,
169                             char **name,
170                             enum SID_NAME_USE *type)
171 {
172         SAM_ACCOUNT *sam_account = NULL;
173         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
174         uint32 id;
175
176         DEBUG(3,("pdb: sid_to_name sid=%s\n", sid_string_static(sid)));
177
178         if (NT_STATUS_IS_OK(sid_to_uid(sid, &id))) { /* this is a user */
179
180                 if (NT_STATUS_IS_ERR(result = pdb_init_sam(&sam_account))) {
181                         return result;
182                 }
183         
184                 if (!pdb_getsampwsid(sam_account, sid)) {
185                         pdb_free_sam(&sam_account);
186                         return NT_STATUS_UNSUCCESSFUL;
187                 }
188         
189                 *name = talloc_strdup(mem_ctx, pdb_get_username(sam_account));  
190                 if (!(*name)) {
191                         DEBUG(0,("query_user: out of memory!\n"));
192                         pdb_free_sam(&sam_account);
193                         return NT_STATUS_NO_MEMORY;
194                 }
195
196                 pdb_free_sam(&sam_account);
197                 *type = SID_NAME_USER;
198                 result = NT_STATUS_OK;
199
200         } else if (NT_STATUS_IS_OK(sid_to_gid(sid, &id))) { /* this is a group */
201                 
202                 DEBUG(3,("pdb: sid_to_name: group support not implemented\n"));
203                 result = NT_STATUS_UNSUCCESSFUL;
204         }
205
206         return result;
207 }
208
209 /* Lookup user information from a rid or username. */
210 static NTSTATUS query_user(struct winbindd_domain *domain, 
211                            TALLOC_CTX *mem_ctx, 
212                            DOM_SID *user_sid, 
213                            WINBIND_USERINFO *user_info)
214 {
215         SAM_ACCOUNT *sam_account = NULL;
216         NTSTATUS result;
217
218         DEBUG(3,("pdb: query_user sid=%s\n", sid_string_static(user_sid)));
219
220         if (NT_STATUS_IS_ERR(result = pdb_init_sam(&sam_account))) {
221                 return result;
222         }
223         
224         if (!pdb_getsampwsid(sam_account, user_sid)) {
225                 pdb_free_sam(&sam_account);
226                 return NT_STATUS_UNSUCCESSFUL;
227         }
228
229         /* we return only nua accounts, or we will have duplicates */
230         if (!idmap_check_sid_is_in_free_range(user_sid)) {
231                 pdb_free_sam(&sam_account);
232                 return NT_STATUS_UNSUCCESSFUL;
233         }
234
235         user_info->user_sid = talloc(mem_ctx, sizeof(DOM_SID));
236         user_info->group_sid = talloc(mem_ctx, sizeof(DOM_SID));
237         if (!(user_info->user_sid) || !(user_info->group_sid)) {
238                 DEBUG(0,("query_user: out of memory!\n"));
239                 pdb_free_sam(&sam_account);
240                 return NT_STATUS_NO_MEMORY;
241         }
242         sid_copy(user_info->user_sid, pdb_get_user_sid(sam_account));
243         sid_copy(user_info->group_sid, pdb_get_group_sid(sam_account));
244
245         user_info->acct_name = talloc_strdup(mem_ctx, pdb_get_username(sam_account));
246         user_info->full_name = talloc_strdup(mem_ctx, pdb_get_fullname(sam_account));
247         if (!(user_info->acct_name) || !(user_info->full_name)) {
248                 DEBUG(0,("query_user: out of memory!\n"));
249                 pdb_free_sam(&sam_account);
250                 return NT_STATUS_NO_MEMORY;
251         }
252
253         pdb_free_sam(&sam_account);
254         return NT_STATUS_OK;
255 }                                   
256
257 /* Lookup groups a user is a member of.  I wish Unix had a call like this! */
258 static NTSTATUS lookup_usergroups(struct winbindd_domain *domain,
259                                   TALLOC_CTX *mem_ctx,
260                                   DOM_SID *user_sid,
261                                   uint32 *num_groups, DOM_SID ***user_gids)
262 {
263         NTSTATUS result = NT_STATUS_OK;
264
265         DEBUG(3,("pdb: lookup_usergroups (group support not implemented)\n"));
266
267         num_groups = 0;
268         user_gids = 0;
269
270         return result;
271 }
272
273
274 /* Lookup group membership given a rid.   */
275 static NTSTATUS lookup_groupmem(struct winbindd_domain *domain,
276                                 TALLOC_CTX *mem_ctx,
277                                 DOM_SID *group_sid, uint32 *num_names, 
278                                 DOM_SID ***sid_mem, char ***names, 
279                                 uint32 **name_types)
280 {
281         NTSTATUS result = NT_STATUS_NOT_IMPLEMENTED;
282
283         DEBUG(3,("pdb: lookup_groupmem (group support not implemented)\n"));
284
285         num_names = 0;
286         sid_mem = 0;
287         names = 0;
288         name_types = 0;
289
290         return result;
291 }
292
293 /* find the sequence number for a domain */
294 static NTSTATUS sequence_number(struct winbindd_domain *domain, uint32 *seq)
295 {
296         /* FIXME: we fake up the seq_num untill our passdb support it */
297         static uint32 seq_num;
298
299         DEBUG(3,("pdb: sequence_number\n"));
300
301         *seq = seq_num++;
302
303         return NT_STATUS_OK;
304 }
305
306 /* get a list of trusted domains */
307 static NTSTATUS trusted_domains(struct winbindd_domain *domain,
308                                 TALLOC_CTX *mem_ctx,
309                                 uint32 *num_domains,
310                                 char ***names,
311                                 char ***alt_names,
312                                 DOM_SID **dom_sids)
313 {
314         NTSTATUS result = NT_STATUS_NOT_IMPLEMENTED;
315
316         DEBUG(3,("pdb: trusted_domains (todo!)\n"));
317
318         return result;
319 }
320
321 /* find the domain sid for a domain */
322 static NTSTATUS domain_sid(struct winbindd_domain *domain, DOM_SID *sid)
323 {
324         DEBUG(3,("pdb: domain_sid\n"));
325
326         if (strcmp(domain->name, lp_workgroup())) {
327                 return NT_STATUS_INVALID_PARAMETER;
328         } else {
329                 sid_copy(sid, get_global_sam_sid());
330                 return NT_STATUS_OK;
331         }
332 }
333
334 /* find alternate names list for the domain 
335  * should we look for netbios aliases?? 
336                                 SSS     */
337 static NTSTATUS alternate_name(struct winbindd_domain *domain)
338 {
339         DEBUG(3,("pdb: alternate_name\n"));
340
341         return NT_STATUS_OK;
342 }
343
344
345 /* the rpc backend methods are exposed via this structure */
346 struct winbindd_methods passdb_methods = {
347         False,
348         query_user_list,
349         enum_dom_groups,
350         enum_local_groups,
351         name_to_sid,
352         sid_to_name,
353         query_user,
354         lookup_usergroups,
355         lookup_groupmem,
356         sequence_number,
357         trusted_domains,
358         domain_sid,
359         alternate_name
360 };