s3:dom_sid Global replace of DOM_SID with struct dom_sid
[kai/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         struct 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         /* initialize the status to avoid suprise */
163         for (i = 0; ids[i]; i++) {
164                 ids[i]->status = ID_UNKNOWN;
165         }
166         
167         nt_status = _idmap_adex_init(dom, NULL);
168         if (!NT_STATUS_IS_OK(nt_status))
169                 return nt_status;
170
171         if ((cell = cell_list_head()) == NULL) {
172                 return NT_STATUS_INVALID_SERVER_STATE;
173         }
174
175         /* have to work through these one by one */
176         for (i = 0; ids[i]; i++) {
177                 NTSTATUS status;
178                 status = cell->provider->get_sid_from_id(ids[i]->sid,
179                                                          ids[i]->xid.id,
180                                                          ids[i]->xid.type);
181                 /* Fail if we cannot find any DC */
182                 if (NT_STATUS_EQUAL
183                     (status, NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND)) {
184                         return status;
185                 }
186
187                 if (!NT_STATUS_IS_OK(status)) {
188                         ids[i]->status = ID_UNMAPPED;
189                         all_mapped = false;
190                         continue;
191                 }
192
193                 ids[i]->status = ID_MAPPED;
194                 one_mapped = true;
195         }
196
197         return NT_STATUS_OK;
198 }
199
200 /**********************************************************************
201  *********************************************************************/
202
203 static NTSTATUS _idmap_adex_get_id_from_sid(struct
204                                                 idmap_domain
205                                                 *dom, struct
206                                                 id_map
207                                                 **ids)
208 {
209         int i;
210         bool one_mapped = false;
211         bool all_mapped = true;
212         NTSTATUS nt_status;
213         struct likewise_cell *cell;
214
215         /* initialize the status to avoid suprise */
216         for (i = 0; ids[i]; i++) {
217                 ids[i]->status = ID_UNKNOWN;
218         }
219         
220         nt_status = _idmap_adex_init(dom, NULL);
221         if (!NT_STATUS_IS_OK(nt_status))
222                 return nt_status;
223
224         if ((cell = cell_list_head()) == NULL) {
225                 return NT_STATUS_INVALID_SERVER_STATE;
226         }
227
228         /* have to work through these one by one */
229         for (i = 0; ids[i]; i++) {
230                 NTSTATUS status;
231                 status = cell->provider->get_id_from_sid(&ids[i]->xid.id,
232                                                          &ids[i]->xid.
233                                                          type, ids[i]->sid);
234                 /* Fail if we cannot find any DC */
235                 if (NT_STATUS_EQUAL
236                     (status, NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND)) {
237                         return status;
238                 }
239
240                 if (!NT_STATUS_IS_OK(status)) {
241                         ids[i]->status = ID_UNMAPPED;
242                         all_mapped = false;
243                         continue;
244                 }
245
246                 ids[i]->status = ID_MAPPED;
247                 one_mapped = true;
248         }
249
250         return NT_STATUS_OK;
251 }
252
253 /**********************************************************************
254  *********************************************************************/
255
256 static NTSTATUS _idmap_adex_set_mapping(struct
257                                             idmap_domain
258                                             *dom, const struct
259                                             id_map *map)
260 {
261         DEBUG(0, ("_idmap_adex_set_mapping: not implemented\n"));
262         return NT_STATUS_NOT_IMPLEMENTED;
263 }
264
265 /**********************************************************************
266  *********************************************************************/
267
268 static NTSTATUS _idmap_adex_remove_mapping(struct
269                                                idmap_domain
270                                                *dom, const
271                                                struct
272                                                id_map
273                                                *map)
274 {
275         DEBUG(0, ("_idmap_adex_remove_mapping: not implemented\n"));
276         return NT_STATUS_NOT_IMPLEMENTED;
277 }
278
279 /**********************************************************************
280  *********************************************************************/
281
282 static NTSTATUS _idmap_adex_dump(struct idmap_domain
283                                      *dom, struct id_map **maps, int *num_map)
284 {
285         return NT_STATUS_NOT_IMPLEMENTED;
286 }
287
288 /**********************************************************************
289  *********************************************************************/
290
291 static NTSTATUS _idmap_adex_close(struct idmap_domain
292                                       *dom)
293 {
294         /* FIXME!  need to do cleanup here */
295
296         return NT_STATUS_OK;
297 }
298
299 /*
300  * IdMap NSS plugin
301  */
302
303 /**********************************************************************
304  *********************************************************************/
305
306 static NTSTATUS _nss_adex_init(struct nss_domain_entry
307                                   *e)
308 {
309         return _idmap_adex_init(NULL, NULL);
310 }
311
312 /**********************************************************************
313  *********************************************************************/
314
315 static NTSTATUS _nss_adex_get_info(struct
316                                       nss_domain_entry *e,
317                                       const struct dom_sid * sid,
318                                       TALLOC_CTX * ctx,
319                                       ADS_STRUCT * ads,
320                                       LDAPMessage * msg,
321                                       const char **homedir,
322                                       const char **shell,
323                                       const char **gecos, gid_t * p_gid)
324 {
325         NTSTATUS nt_status;
326         struct likewise_cell *cell;
327
328         nt_status = _idmap_adex_init(NULL, NULL);
329         if (!NT_STATUS_IS_OK(nt_status))
330                 return nt_status;
331
332         if ((cell = cell_list_head()) == NULL) {
333                 return NT_STATUS_INVALID_SERVER_STATE;
334         }
335
336         return cell->provider->get_nss_info(sid, ctx, homedir,
337                                             shell, gecos, p_gid);
338 }
339
340 /**********************************************************************
341  *********************************************************************/
342
343 static NTSTATUS _nss_adex_map_to_alias(TALLOC_CTX * mem_ctx,
344                                        struct nss_domain_entry *e,
345                                        const char *name, char **alias)
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         nt_status = cell->provider->map_to_alias(mem_ctx, e->domain,
359                                                  name, alias);
360
361         /* go ahead and allow the cache mgr to mark this in
362            negative cache */
363
364         if (!NT_STATUS_IS_OK(nt_status))
365                 nt_status = NT_STATUS_NONE_MAPPED;
366
367 done:
368         return nt_status;
369 }
370
371 /**********************************************************************
372  *********************************************************************/
373
374 static NTSTATUS _nss_adex_map_from_alias(TALLOC_CTX * mem_ctx,
375                                          struct nss_domain_entry *e,
376                                          const char *alias, char **name)
377 {
378         NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
379         struct likewise_cell *cell = NULL;
380
381         nt_status = _idmap_adex_init(NULL, NULL);
382         BAIL_ON_NTSTATUS_ERROR(nt_status);
383
384         if ((cell = cell_list_head()) == NULL) {
385                 nt_status = NT_STATUS_INVALID_SERVER_STATE;
386                 BAIL_ON_NTSTATUS_ERROR(nt_status);
387         }
388
389
390         nt_status = cell->provider->map_from_alias(mem_ctx, e->domain,
391                                                    alias, name);
392
393         /* go ahead and allow the cache mgr to mark this in
394            negative cache */
395
396         if (!NT_STATUS_IS_OK(nt_status))
397                 nt_status = NT_STATUS_NONE_MAPPED;
398
399 done:
400         return nt_status;
401 }
402
403 /**********************************************************************
404  *********************************************************************/
405
406 static NTSTATUS _nss_adex_close(void)
407 {
408         return NT_STATUS_NOT_IMPLEMENTED;
409 }
410
411 /**********************************************************************
412  *********************************************************************/
413
414 static struct idmap_methods adex_idmap_methods = {
415
416         .init             = _idmap_adex_init,
417         .unixids_to_sids  = _idmap_adex_get_sid_from_id,
418         .sids_to_unixids  = _idmap_adex_get_id_from_sid,
419         .set_mapping      = _idmap_adex_set_mapping,
420         .remove_mapping   = _idmap_adex_remove_mapping,
421         .dump_data        = _idmap_adex_dump,
422         .close_fn         = _idmap_adex_close
423 };
424 static struct nss_info_methods adex_nss_methods = {
425         .init           = _nss_adex_init,
426         .get_nss_info   = _nss_adex_get_info,
427         .map_to_alias   = _nss_adex_map_to_alias,
428         .map_from_alias = _nss_adex_map_from_alias,
429         .close_fn       = _nss_adex_close
430 };
431
432 /**********************************************************************
433  Register with the idmap and idmap_nss subsystems. We have to protect
434  against the idmap and nss_info interfaces being in a half-registered
435  state.
436  **********************************************************************/
437 NTSTATUS idmap_adex_init(void)
438 {
439         static NTSTATUS idmap_status = NT_STATUS_UNSUCCESSFUL;
440         static NTSTATUS nss_status = NT_STATUS_UNSUCCESSFUL;
441         if (!NT_STATUS_IS_OK(idmap_status)) {
442                 idmap_status =
443                     smb_register_idmap(SMB_IDMAP_INTERFACE_VERSION,
444                                        "adex", &adex_idmap_methods);
445                 if (!NT_STATUS_IS_OK(idmap_status)) {
446                         DEBUG(0,
447                               ("idmap_centeris_init: Failed to register the adex"
448                                "idmap plugin.\n"));
449                         return idmap_status;
450                 }
451         }
452
453         if (!NT_STATUS_IS_OK(nss_status)) {
454                 nss_status =
455                     smb_register_idmap_nss(SMB_NSS_INFO_INTERFACE_VERSION,
456                                            "adex", &adex_nss_methods);
457                 if (!NT_STATUS_IS_OK(nss_status)) {
458                         DEBUG(0,
459                               ("idmap_adex_init: Failed to register the adex"
460                                "nss plugin.\n"));
461                         return nss_status;
462                 }
463         }
464
465         return NT_STATUS_OK;
466 }
467
468 static NTSTATUS nss_info_adex_init(void)
469 {
470         return idmap_adex_init();
471 }