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 29NTSTATUS 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 41static 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 125done: 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 150static 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 203static 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 256static 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 268static 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 282static 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 291static 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 306static NTSTATUS _nss_adex_init(struct nss_domain_entry 307 *e) 308{ 309 return _idmap_adex_init(NULL, NULL); 310} 311 312/********************************************************************** 313 *********************************************************************/ 314 315static NTSTATUS _nss_adex_get_info(struct 316 nss_domain_entry *e, 317 const 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 343static 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 367done: 368 return nt_status; 369} 370 371/********************************************************************** 372 *********************************************************************/ 373 374static 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 399done: 400 return nt_status; 401} 402 403/********************************************************************** 404 *********************************************************************/ 405 406static NTSTATUS _nss_adex_close(void) 407{ 408 return NT_STATUS_NOT_IMPLEMENTED; 409} 410 411/********************************************************************** 412 *********************************************************************/ 413 414static 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}; 424static 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 **********************************************************************/ 437NTSTATUS 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 468static NTSTATUS nss_info_adex_init(void) 469{ 470 return idmap_adex_init(); 471} 472