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