s3-idmap: only include idmap headers where needed.
[metze/samba/wip.git] / source3 / winbindd / idmap_adex / idmap_adex.c
1 /*
2  * idmap_adex: Support for D Forests
3  *
4  * Copyright (C) Gerald (Jerry) Carter 2006-2008
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19  */
20
21 #include "includes.h"
22 #include "ads.h"
23 #include "idmap.h"
24 #include "idmap_adex.h"
25 #include "nss_info.h"
26 #include "secrets.h"
27
28 #undef DBGC_CLASS
29 #define DBGC_CLASS DBGC_IDMAP
30
31 #define WINBIND_CCACHE_NAME "MEMORY:winbind_ccache"
32
33 NTSTATUS init_module(void);
34
35 /*
36  * IdMap backend
37  */
38
39 /********************************************************************
40  Basic init function responsible for determining our current mode
41  (standalone or using Centeris Cells).  This must return success or
42  it will be dropped from the idmap backend list.
43  *******************************************************************/
44
45 static NTSTATUS _idmap_adex_init(struct idmap_domain *dom,
46                                      const char *params)
47 {
48         ADS_STRUCT *ads = NULL;
49         ADS_STATUS status;
50         static NTSTATUS init_status = NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND;
51         struct dom_sid domain_sid;
52         fstring dcname;
53         struct sockaddr_storage ip;
54         struct likewise_cell *lwcell;
55
56         if (NT_STATUS_IS_OK(init_status))
57                 return NT_STATUS_OK;
58
59         /* Silently fail if we are not a member server in security = ads */
60
61         if ((lp_server_role() != ROLE_DOMAIN_MEMBER) ||
62             (lp_security() != SEC_ADS)) {
63                 init_status = NT_STATUS_INVALID_SERVER_STATE;
64                 BAIL_ON_NTSTATUS_ERROR(init_status);
65         }
66
67         /* fetch our domain SID first */
68
69         if (!secrets_fetch_domain_sid(lp_workgroup(), &domain_sid)) {
70                 init_status = NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
71                 BAIL_ON_NTSTATUS_ERROR(init_status);
72         }
73
74         /* reuse the same ticket cache as winbindd */
75
76         setenv("KRB5CCNAME", WINBIND_CCACHE_NAME, 1);
77
78         /* Establish a connection to a DC */
79
80         if ((ads = ads_init(lp_realm(), lp_workgroup(), NULL)) == NULL) {
81                 init_status = NT_STATUS_NO_MEMORY;
82                 BAIL_ON_NTSTATUS_ERROR(init_status);
83         }
84
85         ads->auth.password =
86             secrets_fetch_machine_password(lp_workgroup(), NULL, NULL);
87         ads->auth.realm = SMB_STRDUP(lp_realm());
88
89         /* get the DC name here to setup the server affinity cache and
90            local krb5.conf */
91
92         get_dc_name(lp_workgroup(), lp_realm(), dcname, &ip);
93
94         status = ads_connect(ads);
95         if (!ADS_ERR_OK(status)) {
96                 DEBUG(0, ("_idmap_adex_init: ads_connect() failed! (%s)\n",
97                           ads_errstr(status)));
98         }
99         init_status = ads_ntstatus(status);
100         BAIL_ON_NTSTATUS_ERROR(init_status);
101
102
103         /* Find out cell membership */
104
105         init_status = cell_locate_membership(ads);
106         if (!NT_STATUS_IS_OK(init_status)) {
107                 DEBUG(0,("LWI: Fail to locate cell membership (%s).",
108                          nt_errstr(init_status)));
109                 goto done;
110         }
111
112         /* Fill in the cell information */
113
114         lwcell = cell_list_head();
115
116         init_status = cell_lookup_settings(lwcell);
117         BAIL_ON_NTSTATUS_ERROR(init_status);
118
119         /* Miscellaneous setup.  E.g. set up the list of GC
120            servers and domain list for our forest (does not actually
121            connect). */
122
123         init_status = gc_init_list();
124         BAIL_ON_NTSTATUS_ERROR(init_status);
125
126         init_status = domain_init_list();
127         BAIL_ON_NTSTATUS_ERROR(init_status);
128
129 done:
130         if (!NT_STATUS_IS_OK(init_status)) {
131                 DEBUG(1,("Likewise initialization failed (%s)\n",
132                          nt_errstr(init_status)));
133         }
134
135         /* cleanup */
136
137         if (!NT_STATUS_IS_OK(init_status)) {
138                 cell_list_destroy();
139
140                 /* init_status stores the failure reason but we need to
141                    return success or else idmap_init() will drop us from the
142                    backend list */
143                 return NT_STATUS_OK;
144         }
145
146         init_status = NT_STATUS_OK;
147
148         return init_status;
149 }
150
151 /**********************************************************************
152  *********************************************************************/
153
154 static NTSTATUS _idmap_adex_get_sid_from_id(struct
155                                                 idmap_domain
156                                                 *dom, struct
157                                                 id_map
158                                                 **ids)
159 {
160         int i;
161         bool one_mapped = false;
162         bool all_mapped = true;
163         NTSTATUS nt_status;
164         struct likewise_cell *cell;
165
166         /* initialize the status to avoid suprise */
167         for (i = 0; ids[i]; i++) {
168                 ids[i]->status = ID_UNKNOWN;
169         }
170         
171         nt_status = _idmap_adex_init(dom, NULL);
172         if (!NT_STATUS_IS_OK(nt_status))
173                 return nt_status;
174
175         if ((cell = cell_list_head()) == NULL) {
176                 return NT_STATUS_INVALID_SERVER_STATE;
177         }
178
179         /* have to work through these one by one */
180         for (i = 0; ids[i]; i++) {
181                 NTSTATUS status;
182                 status = cell->provider->get_sid_from_id(ids[i]->sid,
183                                                          ids[i]->xid.id,
184                                                          ids[i]->xid.type);
185                 /* Fail if we cannot find any DC */
186                 if (NT_STATUS_EQUAL
187                     (status, NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND)) {
188                         return status;
189                 }
190
191                 if (!NT_STATUS_IS_OK(status)) {
192                         ids[i]->status = ID_UNMAPPED;
193                         all_mapped = false;
194                         continue;
195                 }
196
197                 ids[i]->status = ID_MAPPED;
198                 one_mapped = true;
199         }
200
201         return NT_STATUS_OK;
202 }
203
204 /**********************************************************************
205  *********************************************************************/
206
207 static NTSTATUS _idmap_adex_get_id_from_sid(struct
208                                                 idmap_domain
209                                                 *dom, struct
210                                                 id_map
211                                                 **ids)
212 {
213         int i;
214         bool one_mapped = false;
215         bool all_mapped = true;
216         NTSTATUS nt_status;
217         struct likewise_cell *cell;
218
219         /* initialize the status to avoid suprise */
220         for (i = 0; ids[i]; i++) {
221                 ids[i]->status = ID_UNKNOWN;
222         }
223         
224         nt_status = _idmap_adex_init(dom, NULL);
225         if (!NT_STATUS_IS_OK(nt_status))
226                 return nt_status;
227
228         if ((cell = cell_list_head()) == NULL) {
229                 return NT_STATUS_INVALID_SERVER_STATE;
230         }
231
232         /* have to work through these one by one */
233         for (i = 0; ids[i]; i++) {
234                 NTSTATUS status;
235                 status = cell->provider->get_id_from_sid(&ids[i]->xid.id,
236                                                          &ids[i]->xid.
237                                                          type, ids[i]->sid);
238                 /* Fail if we cannot find any DC */
239                 if (NT_STATUS_EQUAL
240                     (status, NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND)) {
241                         return status;
242                 }
243
244                 if (!NT_STATUS_IS_OK(status)) {
245                         ids[i]->status = ID_UNMAPPED;
246                         all_mapped = false;
247                         continue;
248                 }
249
250                 ids[i]->status = ID_MAPPED;
251                 one_mapped = true;
252         }
253
254         return NT_STATUS_OK;
255 }
256
257 /**********************************************************************
258  *********************************************************************/
259
260 static NTSTATUS _idmap_adex_close(struct idmap_domain
261                                       *dom)
262 {
263         /* FIXME!  need to do cleanup here */
264
265         return NT_STATUS_OK;
266 }
267
268 /*
269  * IdMap NSS plugin
270  */
271
272 /**********************************************************************
273  *********************************************************************/
274
275 static NTSTATUS _nss_adex_init(struct nss_domain_entry
276                                   *e)
277 {
278         return _idmap_adex_init(NULL, NULL);
279 }
280
281 /**********************************************************************
282  *********************************************************************/
283
284 static NTSTATUS _nss_adex_get_info(struct
285                                       nss_domain_entry *e,
286                                       const struct dom_sid * sid,
287                                       TALLOC_CTX * ctx,
288                                       ADS_STRUCT * ads,
289                                       LDAPMessage * msg,
290                                       const char **homedir,
291                                       const char **shell,
292                                       const char **gecos, gid_t * p_gid)
293 {
294         NTSTATUS nt_status;
295         struct likewise_cell *cell;
296
297         nt_status = _idmap_adex_init(NULL, NULL);
298         if (!NT_STATUS_IS_OK(nt_status))
299                 return nt_status;
300
301         if ((cell = cell_list_head()) == NULL) {
302                 return NT_STATUS_INVALID_SERVER_STATE;
303         }
304
305         return cell->provider->get_nss_info(sid, ctx, homedir,
306                                             shell, gecos, p_gid);
307 }
308
309 /**********************************************************************
310  *********************************************************************/
311
312 static NTSTATUS _nss_adex_map_to_alias(TALLOC_CTX * mem_ctx,
313                                        struct nss_domain_entry *e,
314                                        const char *name, char **alias)
315 {
316         NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
317         struct likewise_cell *cell = NULL;
318
319         nt_status = _idmap_adex_init(NULL, NULL);
320         BAIL_ON_NTSTATUS_ERROR(nt_status);
321
322         if ((cell = cell_list_head()) == NULL) {
323                 nt_status = NT_STATUS_INVALID_SERVER_STATE;
324                 BAIL_ON_NTSTATUS_ERROR(nt_status);
325         }
326
327         nt_status = cell->provider->map_to_alias(mem_ctx, e->domain,
328                                                  name, alias);
329
330         /* go ahead and allow the cache mgr to mark this in
331            negative cache */
332
333         if (!NT_STATUS_IS_OK(nt_status))
334                 nt_status = NT_STATUS_NONE_MAPPED;
335
336 done:
337         return nt_status;
338 }
339
340 /**********************************************************************
341  *********************************************************************/
342
343 static NTSTATUS _nss_adex_map_from_alias(TALLOC_CTX * mem_ctx,
344                                          struct nss_domain_entry *e,
345                                          const char *alias, char **name)
346 {
347         NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
348         struct likewise_cell *cell = NULL;
349
350         nt_status = _idmap_adex_init(NULL, NULL);
351         BAIL_ON_NTSTATUS_ERROR(nt_status);
352
353         if ((cell = cell_list_head()) == NULL) {
354                 nt_status = NT_STATUS_INVALID_SERVER_STATE;
355                 BAIL_ON_NTSTATUS_ERROR(nt_status);
356         }
357
358
359         nt_status = cell->provider->map_from_alias(mem_ctx, e->domain,
360                                                    alias, name);
361
362         /* go ahead and allow the cache mgr to mark this in
363            negative cache */
364
365         if (!NT_STATUS_IS_OK(nt_status))
366                 nt_status = NT_STATUS_NONE_MAPPED;
367
368 done:
369         return nt_status;
370 }
371
372 /**********************************************************************
373  *********************************************************************/
374
375 static NTSTATUS _nss_adex_close(void)
376 {
377         return NT_STATUS_NOT_IMPLEMENTED;
378 }
379
380 /**********************************************************************
381  *********************************************************************/
382
383 static struct idmap_methods adex_idmap_methods = {
384
385         .init             = _idmap_adex_init,
386         .unixids_to_sids  = _idmap_adex_get_sid_from_id,
387         .sids_to_unixids  = _idmap_adex_get_id_from_sid,
388         .close_fn         = _idmap_adex_close
389 };
390 static struct nss_info_methods adex_nss_methods = {
391         .init           = _nss_adex_init,
392         .get_nss_info   = _nss_adex_get_info,
393         .map_to_alias   = _nss_adex_map_to_alias,
394         .map_from_alias = _nss_adex_map_from_alias,
395         .close_fn       = _nss_adex_close
396 };
397
398 /**********************************************************************
399  Register with the idmap and idmap_nss subsystems. We have to protect
400  against the idmap and nss_info interfaces being in a half-registered
401  state.
402  **********************************************************************/
403 NTSTATUS idmap_adex_init(void)
404 {
405         static NTSTATUS idmap_status = NT_STATUS_UNSUCCESSFUL;
406         static NTSTATUS nss_status = NT_STATUS_UNSUCCESSFUL;
407         if (!NT_STATUS_IS_OK(idmap_status)) {
408                 idmap_status =
409                     smb_register_idmap(SMB_IDMAP_INTERFACE_VERSION,
410                                        "adex", &adex_idmap_methods);
411                 if (!NT_STATUS_IS_OK(idmap_status)) {
412                         DEBUG(0,
413                               ("idmap_centeris_init: Failed to register the adex"
414                                "idmap plugin.\n"));
415                         return idmap_status;
416                 }
417         }
418
419         if (!NT_STATUS_IS_OK(nss_status)) {
420                 nss_status =
421                     smb_register_idmap_nss(SMB_NSS_INFO_INTERFACE_VERSION,
422                                            "adex", &adex_nss_methods);
423                 if (!NT_STATUS_IS_OK(nss_status)) {
424                         DEBUG(0,
425                               ("idmap_adex_init: Failed to register the adex"
426                                "nss plugin.\n"));
427                         return nss_status;
428                 }
429         }
430
431         return NT_STATUS_OK;
432 }
433
434 static NTSTATUS nss_info_adex_init(void)
435 {
436         return idmap_adex_init();
437 }