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