Changeset 745 for trunk/server/source3/winbindd/idmap_tdb2.c
- Timestamp:
- Nov 27, 2012, 4:43:17 PM (13 years ago)
- Location:
- trunk/server
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/server
- Property svn:mergeinfo changed
/vendor/current merged: 581,587,591,594,597,600,615,618,740
- Property svn:mergeinfo changed
-
trunk/server/source3/winbindd/idmap_tdb2.c
r414 r745 15 15 Copyright (C) Jeremy Allison 2006 16 16 Copyright (C) Simo Sorce 2003-2006 17 17 Copyright (C) Michael Adam 2009-2010 18 18 19 This program is free software; you can redistribute it and/or modify 19 20 it under the terms of the GNU General Public License as published by 20 21 the Free Software Foundation; either version 2 of the License, or 21 22 (at your option) any later version. 22 23 23 24 This program is distributed in the hope that it will be useful, 24 25 but WITHOUT ANY WARRANTY; without even the implied warranty of 25 26 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 26 27 GNU General Public License for more details. 27 28 28 29 You should have received a copy of the GNU General Public License 29 30 along with this program; if not, write to the Free Software … … 32 33 33 34 #include "includes.h" 35 #include "system/filesys.h" 34 36 #include "winbindd.h" 37 #include "idmap.h" 38 #include "idmap_rw.h" 39 #include "dbwrap.h" 40 #include "../libcli/security/dom_sid.h" 41 #include "util_tdb.h" 35 42 36 43 #undef DBGC_CLASS 37 44 #define DBGC_CLASS DBGC_IDMAP 45 46 struct idmap_tdb2_context { 47 struct db_context *db; 48 const char *script; /* script to provide idmaps */ 49 struct idmap_rw_ops *rw_ops; 50 }; 38 51 39 52 /* High water mark keys */ … … 41 54 #define HWM_USER "USER HWM" 42 55 43 static struct idmap_tdb2_state { 44 /* User and group id pool */ 45 uid_t low_uid, high_uid; /* Range of uids to allocate */ 46 gid_t low_gid, high_gid; /* Range of gids to allocate */ 47 const char *idmap_script; 48 } idmap_tdb2_state; 49 50 51 52 /* handle to the permanent tdb */ 53 static struct db_context *idmap_tdb2; 54 55 static NTSTATUS idmap_tdb2_alloc_load(void); 56 57 static NTSTATUS idmap_tdb2_load_ranges(void) 58 { 59 uid_t low_uid = 0; 60 uid_t high_uid = 0; 61 gid_t low_gid = 0; 62 gid_t high_gid = 0; 63 64 if (!lp_idmap_uid(&low_uid, &high_uid)) { 65 DEBUG(1, ("idmap uid missing\n")); 66 return NT_STATUS_UNSUCCESSFUL; 67 } 68 69 if (!lp_idmap_gid(&low_gid, &high_gid)) { 70 DEBUG(1, ("idmap gid missing\n")); 71 return NT_STATUS_UNSUCCESSFUL; 72 } 73 74 idmap_tdb2_state.low_uid = low_uid; 75 idmap_tdb2_state.high_uid = high_uid; 76 idmap_tdb2_state.low_gid = low_gid; 77 idmap_tdb2_state.high_gid = high_gid; 78 79 if (idmap_tdb2_state.high_uid <= idmap_tdb2_state.low_uid) { 80 DEBUG(1, ("idmap uid range missing or invalid\n")); 81 DEBUGADD(1, ("idmap will be unable to map foreign SIDs\n")); 82 return NT_STATUS_UNSUCCESSFUL; 83 } 84 85 if (idmap_tdb2_state.high_gid <= idmap_tdb2_state.low_gid) { 86 DEBUG(1, ("idmap gid range missing or invalid\n")); 87 DEBUGADD(1, ("idmap will be unable to map foreign SIDs\n")); 88 return NT_STATUS_UNSUCCESSFUL; 56 57 /* 58 * check and initialize high/low water marks in the db 59 */ 60 static NTSTATUS idmap_tdb2_init_hwm(struct idmap_domain *dom) 61 { 62 NTSTATUS status; 63 uint32 low_id; 64 struct idmap_tdb2_context *ctx; 65 66 ctx = talloc_get_type(dom->private_data, struct idmap_tdb2_context); 67 68 /* Create high water marks for group and user id */ 69 70 low_id = dbwrap_fetch_int32(ctx->db, HWM_USER); 71 if ((low_id == -1) || (low_id < dom->low_id)) { 72 status = dbwrap_trans_store_int32(ctx->db, HWM_USER, 73 dom->low_id); 74 if (!NT_STATUS_IS_OK(status)) { 75 DEBUG(0, ("Unable to initialise user hwm in idmap " 76 "database: %s\n", nt_errstr(status))); 77 return NT_STATUS_INTERNAL_DB_ERROR; 78 } 79 } 80 81 low_id = dbwrap_fetch_int32(ctx->db, HWM_GROUP); 82 if ((low_id == -1) || (low_id < dom->low_id)) { 83 status = dbwrap_trans_store_int32(ctx->db, HWM_GROUP, 84 dom->low_id); 85 if (!NT_STATUS_IS_OK(status)) { 86 DEBUG(0, ("Unable to initialise group hwm in idmap " 87 "database: %s\n", nt_errstr(status))); 88 return NT_STATUS_INTERNAL_DB_ERROR; 89 } 89 90 } 90 91 91 92 return NT_STATUS_OK; 92 93 } 94 93 95 94 96 /* 95 97 open the permanent tdb 96 98 */ 97 static NTSTATUS idmap_tdb2_open_db( void)99 static NTSTATUS idmap_tdb2_open_db(struct idmap_domain *dom) 98 100 { 99 101 char *db_path; 100 101 if (idmap_tdb2) { 102 struct idmap_tdb2_context *ctx; 103 104 ctx = talloc_get_type(dom->private_data, struct idmap_tdb2_context); 105 106 if (ctx->db) { 102 107 /* its already open */ 103 108 return NT_STATUS_OK; 104 109 } 105 110 106 db_path = lp_parm_talloc_string(-1, "tdb", "idmap2.tdb", NULL); 107 if (db_path == NULL) { 108 /* fall back to the private directory, which, despite 109 its name, is usually on shared storage */ 110 db_path = talloc_asprintf(NULL, "%s/idmap2.tdb", lp_private_dir()); 111 } 111 db_path = talloc_asprintf(NULL, "%s/idmap2.tdb", lp_private_dir()); 112 112 NT_STATUS_HAVE_NO_MEMORY(db_path); 113 113 114 114 /* Open idmap repository */ 115 idmap_tdb2 = db_open(NULL, db_path, 0, TDB_DEFAULT, O_RDWR|O_CREAT, 0644);115 ctx->db = db_open(ctx, db_path, 0, TDB_DEFAULT, O_RDWR|O_CREAT, 0644); 116 116 TALLOC_FREE(db_path); 117 117 118 if ( idmap_tdb2== NULL) {118 if (ctx->db == NULL) { 119 119 DEBUG(0, ("Unable to open idmap_tdb2 database '%s'\n", 120 120 db_path)); … … 122 122 } 123 123 124 /* load the ranges and high/low water marks */ 125 return idmap_tdb2_alloc_load(); 126 } 127 128 129 /* 130 load the idmap allocation ranges and high/low water marks 131 */ 132 static NTSTATUS idmap_tdb2_alloc_load(void) 133 { 134 NTSTATUS status; 135 uint32 low_id; 136 137 /* see if a idmap script is configured */ 138 idmap_tdb2_state.idmap_script = lp_parm_const_string(-1, "idmap", 139 "script", NULL); 140 141 if (idmap_tdb2_state.idmap_script) { 142 DEBUG(1, ("using idmap script '%s'\n", 143 idmap_tdb2_state.idmap_script)); 144 } 145 146 /* load ranges */ 147 148 status = idmap_tdb2_load_ranges(); 149 if (!NT_STATUS_IS_OK(status)) { 150 return status; 151 } 152 153 /* Create high water marks for group and user id */ 154 155 low_id = dbwrap_fetch_int32(idmap_tdb2, HWM_USER); 156 if ((low_id == -1) || (low_id < idmap_tdb2_state.low_uid)) { 157 if (!NT_STATUS_IS_OK(dbwrap_trans_store_int32( 158 idmap_tdb2, HWM_USER, 159 idmap_tdb2_state.low_uid))) { 160 DEBUG(0, ("Unable to initialise user hwm in idmap " 161 "database\n")); 162 return NT_STATUS_INTERNAL_DB_ERROR; 163 } 164 } 165 166 low_id = dbwrap_fetch_int32(idmap_tdb2, HWM_GROUP); 167 if ((low_id == -1) || (low_id < idmap_tdb2_state.low_gid)) { 168 if (!NT_STATUS_IS_OK(dbwrap_trans_store_int32( 169 idmap_tdb2, HWM_GROUP, 170 idmap_tdb2_state.low_gid))) { 171 DEBUG(0, ("Unable to initialise group hwm in idmap " 172 "database\n")); 173 return NT_STATUS_INTERNAL_DB_ERROR; 174 } 175 } 176 177 return NT_STATUS_OK; 178 } 179 180 181 /* 182 Initialise idmap alloc database. 183 */ 184 static NTSTATUS idmap_tdb2_alloc_init(const char *params) 185 { 186 /* nothing to do - we want to avoid opening the permanent 187 database if possible. Instead we load the params when we 188 first need it. */ 189 return NT_STATUS_OK; 124 return idmap_tdb2_init_hwm(dom); 190 125 } 191 126 … … 248 183 } 249 184 250 static NTSTATUS idmap_tdb2_allocate_id(struct unixid *xid) 185 static NTSTATUS idmap_tdb2_allocate_id(struct idmap_domain *dom, 186 struct unixid *xid) 251 187 { 252 188 const char *hwmkey; … … 256 192 NTSTATUS status; 257 193 struct idmap_tdb2_allocate_id_context state; 258 259 status = idmap_tdb2_open_db(); 194 struct idmap_tdb2_context *ctx; 195 196 status = idmap_tdb2_open_db(dom); 260 197 NT_STATUS_NOT_OK_RETURN(status); 198 199 ctx = talloc_get_type(dom->private_data, struct idmap_tdb2_context); 261 200 262 201 /* Get current high water mark */ … … 266 205 hwmkey = HWM_USER; 267 206 hwmtype = "UID"; 268 high_hwm = idmap_tdb2_state.high_uid;269 207 break; 270 208 … … 272 210 hwmkey = HWM_GROUP; 273 211 hwmtype = "GID"; 274 high_hwm = idmap_tdb2_state.high_gid;275 212 break; 276 213 … … 279 216 return NT_STATUS_INVALID_PARAMETER; 280 217 } 218 219 high_hwm = dom->high_id; 281 220 282 221 state.hwm = hwm; … … 285 224 state.hwmkey = hwmkey; 286 225 287 status = dbwrap_trans_do( idmap_tdb2, idmap_tdb2_allocate_id_action,226 status = dbwrap_trans_do(ctx->db, idmap_tdb2_allocate_id_action, 288 227 &state); 289 228 290 229 if (NT_STATUS_IS_OK(status)) { 291 230 xid->id = state.hwm; 292 DEBUG(10,("New %s = %d\n", hwmtype, hwm));231 DEBUG(10,("New %s = %d\n", hwmtype, state.hwm)); 293 232 } else { 294 233 DEBUG(1, ("Error allocating a new %s\n", hwmtype)); … … 298 237 } 299 238 300 /* 301 Get current highest id. 302 */ 303 static NTSTATUS idmap_tdb2_get_hwm(struct unixid *xid) 304 { 305 const char *hwmkey; 306 const char *hwmtype; 307 uint32_t hwm; 308 uint32_t high_hwm; 309 NTSTATUS status; 310 311 status = idmap_tdb2_open_db(); 312 NT_STATUS_NOT_OK_RETURN(status); 313 314 /* Get current high water mark */ 315 switch (xid->type) { 316 317 case ID_TYPE_UID: 318 hwmkey = HWM_USER; 319 hwmtype = "UID"; 320 high_hwm = idmap_tdb2_state.high_uid; 321 break; 322 323 case ID_TYPE_GID: 324 hwmkey = HWM_GROUP; 325 hwmtype = "GID"; 326 high_hwm = idmap_tdb2_state.high_gid; 327 break; 328 329 default: 330 return NT_STATUS_INVALID_PARAMETER; 331 } 332 333 if ((hwm = dbwrap_fetch_int32(idmap_tdb2, hwmkey)) == -1) { 334 return NT_STATUS_INTERNAL_DB_ERROR; 335 } 336 337 xid->id = hwm; 338 339 /* Warn if it is out of range */ 340 if (hwm >= high_hwm) { 341 DEBUG(0, ("Warning: %s range full!! (max: %lu)\n", 342 hwmtype, (unsigned long)high_hwm)); 343 } 344 345 return NT_STATUS_OK; 346 } 347 348 /* 349 Set high id. 350 */ 351 static NTSTATUS idmap_tdb2_set_hwm(struct unixid *xid) 352 { 353 /* not supported, or we would invalidate the cache tdb on 354 other nodes */ 355 DEBUG(0,("idmap_tdb2_set_hwm not supported\n")); 356 return NT_STATUS_NOT_SUPPORTED; 357 } 358 359 /* 360 Close the alloc tdb 361 */ 362 static NTSTATUS idmap_tdb2_alloc_close(void) 363 { 364 /* don't actually close it */ 365 return NT_STATUS_OK; 239 /** 240 * Allocate a new unix-ID. 241 * For now this is for the default idmap domain only. 242 * Should be extended later on. 243 */ 244 static NTSTATUS idmap_tdb2_get_new_id(struct idmap_domain *dom, 245 struct unixid *id) 246 { 247 NTSTATUS ret; 248 249 if (!strequal(dom->name, "*")) { 250 DEBUG(3, ("idmap_tdb2_get_new_id: " 251 "Refusing creation of mapping for domain'%s'. " 252 "Currently only supported for the default " 253 "domain \"*\".\n", 254 dom->name)); 255 return NT_STATUS_NOT_IMPLEMENTED; 256 } 257 258 ret = idmap_tdb2_allocate_id(dom, id); 259 260 return ret; 366 261 } 367 262 … … 369 264 IDMAP MAPPING TDB BACKEND 370 265 */ 371 struct idmap_tdb2_context { 372 uint32_t filter_low_id; 373 uint32_t filter_high_id; 374 }; 266 267 static NTSTATUS idmap_tdb2_set_mapping(struct idmap_domain *dom, 268 const struct id_map *map); 375 269 376 270 /* 377 271 Initialise idmap database. 378 272 */ 379 static NTSTATUS idmap_tdb2_db_init(struct idmap_domain *dom, 380 const char *params) 273 static NTSTATUS idmap_tdb2_db_init(struct idmap_domain *dom) 381 274 { 382 275 NTSTATUS ret; 383 276 struct idmap_tdb2_context *ctx; 384 NTSTATUS status; 385 386 status = idmap_tdb2_open_db(); 387 NT_STATUS_NOT_OK_RETURN(status); 388 389 ctx = talloc(dom, struct idmap_tdb2_context); 277 char *config_option = NULL; 278 const char * idmap_script = NULL; 279 280 ctx = talloc_zero(dom, struct idmap_tdb2_context); 390 281 if ( ! ctx) { 391 282 DEBUG(0, ("Out of memory!\n")); … … 393 284 } 394 285 395 if (strequal(dom->name, "*")) { 396 uid_t low_uid = 0; 397 uid_t high_uid = 0; 398 gid_t low_gid = 0; 399 gid_t high_gid = 0; 400 401 ctx->filter_low_id = 0; 402 ctx->filter_high_id = 0; 403 404 if (lp_idmap_uid(&low_uid, &high_uid)) { 405 ctx->filter_low_id = low_uid; 406 ctx->filter_high_id = high_uid; 407 } else { 408 DEBUG(3, ("Warning: 'idmap uid' not set!\n")); 409 } 410 411 if (lp_idmap_gid(&low_gid, &high_gid)) { 412 if ((low_gid != low_uid) || (high_gid != high_uid)) { 413 DEBUG(1, ("Warning: 'idmap uid' and 'idmap gid'" 414 " ranges do not agree -- building " 415 "intersection\n")); 416 ctx->filter_low_id = MAX(ctx->filter_low_id, 417 low_gid); 418 ctx->filter_high_id = MIN(ctx->filter_high_id, 419 high_gid); 420 } 421 } else { 422 DEBUG(3, ("Warning: 'idmap gid' not set!\n")); 423 } 424 } else { 425 char *config_option = NULL; 426 const char *range; 427 config_option = talloc_asprintf(ctx, "idmap config %s", dom->name); 428 if ( ! config_option) { 429 DEBUG(0, ("Out of memory!\n")); 430 ret = NT_STATUS_NO_MEMORY; 431 goto failed; 432 } 433 434 range = lp_parm_const_string(-1, config_option, "range", NULL); 435 if (( ! range) || 436 (sscanf(range, "%u - %u", &ctx->filter_low_id, &ctx->filter_high_id) != 2)) 437 { 438 ctx->filter_low_id = 0; 439 ctx->filter_high_id = 0; 440 } 441 442 talloc_free(config_option); 443 } 444 445 if (ctx->filter_low_id > ctx->filter_high_id) { 446 ctx->filter_low_id = 0; 447 ctx->filter_high_id = 0; 448 } 286 config_option = talloc_asprintf(ctx, "idmap config %s", dom->name); 287 if (config_option == NULL) { 288 DEBUG(0, ("Out of memory!\n")); 289 ret = NT_STATUS_NO_MEMORY; 290 goto failed; 291 } 292 ctx->script = lp_parm_const_string(-1, config_option, "script", "NULL"); 293 talloc_free(config_option); 294 295 idmap_script = lp_parm_const_string(-1, "idmap", "script", NULL); 296 if (idmap_script != NULL) { 297 DEBUG(0, ("Warning: 'idmap:script' is deprecated. " 298 " Please use 'idmap config * : script' instead!\n")); 299 } 300 301 if (strequal(dom->name, "*") && ctx->script == NULL) { 302 /* fall back to idmap:script for backwards compatibility */ 303 ctx->script = idmap_script; 304 } 305 306 if (ctx->script) { 307 DEBUG(1, ("using idmap script '%s'\n", ctx->script)); 308 } 309 310 ctx->rw_ops = talloc_zero(ctx, struct idmap_rw_ops); 311 if (ctx->rw_ops == NULL) { 312 DEBUG(0, ("Out of memory!\n")); 313 ret = NT_STATUS_NO_MEMORY; 314 goto failed; 315 } 316 317 ctx->rw_ops->get_new_id = idmap_tdb2_get_new_id; 318 ctx->rw_ops->set_mapping = idmap_tdb2_set_mapping; 449 319 450 320 dom->private_data = ctx; 321 322 ret = idmap_tdb2_open_db(dom); 323 if (!NT_STATUS_IS_OK(ret)) { 324 goto failed; 325 } 451 326 452 327 return NT_STATUS_OK; … … 456 331 return ret; 457 332 } 333 334 335 /** 336 * store a mapping in the database. 337 */ 458 338 459 339 struct idmap_tdb2_set_mapping_context { … … 503 383 done: 504 384 talloc_free(tmp_ctx); 385 return ret; 386 } 387 388 static NTSTATUS idmap_tdb2_set_mapping(struct idmap_domain *dom, const struct id_map *map) 389 { 390 struct idmap_tdb2_context *ctx; 391 NTSTATUS ret; 392 char *ksidstr, *kidstr; 393 struct idmap_tdb2_set_mapping_context state; 394 395 if (!map || !map->sid) { 396 return NT_STATUS_INVALID_PARAMETER; 397 } 398 399 ksidstr = kidstr = NULL; 400 401 /* TODO: should we filter a set_mapping using low/high filters ? */ 402 403 ctx = talloc_get_type(dom->private_data, struct idmap_tdb2_context); 404 405 switch (map->xid.type) { 406 407 case ID_TYPE_UID: 408 kidstr = talloc_asprintf(ctx, "UID %lu", (unsigned long)map->xid.id); 409 break; 410 411 case ID_TYPE_GID: 412 kidstr = talloc_asprintf(ctx, "GID %lu", (unsigned long)map->xid.id); 413 break; 414 415 default: 416 DEBUG(2, ("INVALID unix ID type: 0x02%x\n", map->xid.type)); 417 return NT_STATUS_INVALID_PARAMETER; 418 } 419 420 if (kidstr == NULL) { 421 DEBUG(0, ("ERROR: Out of memory!\n")); 422 ret = NT_STATUS_NO_MEMORY; 423 goto done; 424 } 425 426 ksidstr = sid_string_talloc(ctx, map->sid); 427 if (ksidstr == NULL) { 428 DEBUG(0, ("Out of memory!\n")); 429 ret = NT_STATUS_NO_MEMORY; 430 goto done; 431 } 432 433 state.ksidstr = ksidstr; 434 state.kidstr = kidstr; 435 436 ret = dbwrap_trans_do(ctx->db, idmap_tdb2_set_mapping_action, 437 &state); 438 439 done: 440 talloc_free(ksidstr); 441 talloc_free(kidstr); 442 return ret; 443 } 444 445 /** 446 * Create a new mapping for an unmapped SID, also allocating a new ID. 447 * This should be run inside a transaction. 448 * 449 * TODO: 450 * Properly integrate this with multi domain idmap config: 451 * Currently, the allocator is default-config only. 452 */ 453 static NTSTATUS idmap_tdb2_new_mapping(struct idmap_domain *dom, struct id_map *map) 454 { 455 NTSTATUS ret; 456 struct idmap_tdb2_context *ctx; 457 458 ctx = talloc_get_type(dom->private_data, struct idmap_tdb2_context); 459 460 ret = idmap_rw_new_mapping(dom, ctx->rw_ops, map); 461 505 462 return ret; 506 463 } … … 531 488 unsigned long v; 532 489 533 cmd = talloc_asprintf(ctx, "%s ", idmap_tdb2_state.idmap_script);490 cmd = talloc_asprintf(ctx, "%s ", ctx->script); 534 491 NT_STATUS_HAVE_NO_MEMORY(cmd); 535 492 … … 562 519 if (!string_to_sid(map->sid, &line[4])) { 563 520 DEBUG(0,("Bad SID in '%s' from idmap script %s\n", 564 line, idmap_tdb2_state.idmap_script));521 line, ctx->script)); 565 522 return NT_STATUS_NONE_MAPPED; 566 523 } 567 524 } else { 568 525 DEBUG(0,("Bad reply '%s' from idmap script %s\n", 569 line, idmap_tdb2_state.idmap_script));526 line, ctx->script)); 570 527 return NT_STATUS_NONE_MAPPED; 571 528 } … … 579 536 Single id to sid lookup function. 580 537 */ 581 static NTSTATUS idmap_tdb2_id_to_sid(struct idmap_ tdb2_context *ctx, struct id_map *map)538 static NTSTATUS idmap_tdb2_id_to_sid(struct idmap_domain *dom, struct id_map *map) 582 539 { 583 540 NTSTATUS ret; … … 585 542 char *keystr; 586 543 NTSTATUS status; 587 588 status = idmap_tdb2_open_db(); 544 struct idmap_tdb2_context *ctx; 545 546 547 if (!dom || !map) { 548 return NT_STATUS_INVALID_PARAMETER; 549 } 550 551 status = idmap_tdb2_open_db(dom); 589 552 NT_STATUS_NOT_OK_RETURN(status); 590 553 591 if (!ctx || !map) { 592 return NT_STATUS_INVALID_PARAMETER; 593 } 554 ctx = talloc_get_type(dom->private_data, struct idmap_tdb2_context); 594 555 595 556 /* apply filters before checking */ 596 if ((ctx->filter_low_id && (map->xid.id < ctx->filter_low_id)) || 597 (ctx->filter_high_id && (map->xid.id > ctx->filter_high_id))) { 557 if (!idmap_unix_id_is_in_range(map->xid.id, dom)) { 598 558 DEBUG(5, ("Requested id (%u) out of range (%u - %u). Filtered!\n", 599 map->xid.id, ctx->filter_low_id, ctx->filter_high_id));559 map->xid.id, dom->low_id, dom->high_id)); 600 560 return NT_STATUS_NONE_MAPPED; 601 561 } … … 606 566 keystr = talloc_asprintf(ctx, "UID %lu", (unsigned long)map->xid.id); 607 567 break; 608 568 609 569 case ID_TYPE_GID: 610 570 keystr = talloc_asprintf(ctx, "GID %lu", (unsigned long)map->xid.id); … … 616 576 } 617 577 618 /* final SAFE_FREE safe */619 data.dptr = NULL;620 621 578 if (keystr == NULL) { 622 579 DEBUG(0, ("Out of memory!\n")); … … 628 585 629 586 /* Check if the mapping exists */ 630 data = dbwrap_fetch_bystring( idmap_tdb2, keystr, keystr);587 data = dbwrap_fetch_bystring(ctx->db, keystr, keystr); 631 588 632 589 if (!data.dptr) { … … 635 592 636 593 DEBUG(10,("Record %s not found\n", keystr)); 637 if ( idmap_tdb2_state.idmap_script == NULL) {594 if (ctx->script == NULL) { 638 595 ret = NT_STATUS_NONE_MAPPED; 639 596 goto done; … … 641 598 642 599 ret = idmap_tdb2_script(ctx, map, "IDTOSID %s", keystr); 643 644 /* store it on shared storage */645 600 if (!NT_STATUS_IS_OK(ret)) { 646 601 goto done; … … 656 611 store_state.kidstr = keystr; 657 612 658 ret = dbwrap_trans_do( idmap_tdb2, idmap_tdb2_set_mapping_action,613 ret = dbwrap_trans_do(ctx->db, idmap_tdb2_set_mapping_action, 659 614 &store_state); 660 615 goto done; 661 616 } 662 617 663 618 if (!string_to_sid(map->sid, (const char *)data.dptr)) { 664 619 DEBUG(10,("INVALID SID (%s) in record %s\n", … … 680 635 Single sid to id lookup function. 681 636 */ 682 static NTSTATUS idmap_tdb2_sid_to_id(struct idmap_ tdb2_context *ctx, struct id_map *map)637 static NTSTATUS idmap_tdb2_sid_to_id(struct idmap_domain *dom, struct id_map *map) 683 638 { 684 639 NTSTATUS ret; … … 686 641 char *keystr; 687 642 unsigned long rec_id = 0; 643 struct idmap_tdb2_context *ctx; 688 644 TALLOC_CTX *tmp_ctx = talloc_stackframe(); 689 645 690 ret = idmap_tdb2_open_db( );646 ret = idmap_tdb2_open_db(dom); 691 647 NT_STATUS_NOT_OK_RETURN(ret); 648 649 ctx = talloc_get_type(dom->private_data, struct idmap_tdb2_context); 692 650 693 651 keystr = sid_string_talloc(tmp_ctx, map->sid); … … 701 659 702 660 /* Check if sid is present in database */ 703 data = dbwrap_fetch_bystring( idmap_tdb2, tmp_ctx, keystr);661 data = dbwrap_fetch_bystring(ctx->db, tmp_ctx, keystr); 704 662 if (!data.dptr) { 705 663 char *idstr; … … 708 666 DEBUG(10,(__location__ " Record %s not found\n", keystr)); 709 667 710 if ( idmap_tdb2_state.idmap_script == NULL) {668 if (ctx->script == NULL) { 711 669 ret = NT_STATUS_NONE_MAPPED; 712 670 goto done; 713 671 } 714 672 715 673 ret = idmap_tdb2_script(ctx, map, "SIDTOID %s", keystr); 716 /* store it on shared storage */717 674 if (!NT_STATUS_IS_OK(ret)) { 675 goto done; 676 } 677 678 /* apply filters before returning result */ 679 if (!idmap_unix_id_is_in_range(map->xid.id, dom)) { 680 DEBUG(5, ("Script returned id (%u) out of range " 681 "(%u - %u). Filtered!\n", 682 map->xid.id, dom->low_id, dom->high_id)); 683 ret = NT_STATUS_NONE_MAPPED; 718 684 goto done; 719 685 } … … 730 696 store_state.kidstr = idstr; 731 697 732 ret = dbwrap_trans_do( idmap_tdb2, idmap_tdb2_set_mapping_action,698 ret = dbwrap_trans_do(ctx->db, idmap_tdb2_set_mapping_action, 733 699 &store_state); 734 700 goto done; … … 751 717 DEBUG(2, ("Found INVALID record %s -> %s\n", keystr, (const char *)data.dptr)); 752 718 ret = NT_STATUS_INTERNAL_DB_ERROR; 753 } 754 719 goto done; 720 } 721 755 722 /* apply filters before returning result */ 756 if ((ctx->filter_low_id && (map->xid.id < ctx->filter_low_id)) || 757 (ctx->filter_high_id && (map->xid.id > ctx->filter_high_id))) { 723 if (!idmap_unix_id_is_in_range(map->xid.id, dom)) { 758 724 DEBUG(5, ("Requested id (%u) out of range (%u - %u). Filtered!\n", 759 map->xid.id, ctx->filter_low_id, ctx->filter_high_id));725 map->xid.id, dom->low_id, dom->high_id)); 760 726 ret = NT_STATUS_NONE_MAPPED; 761 727 } … … 771 737 static NTSTATUS idmap_tdb2_unixids_to_sids(struct idmap_domain *dom, struct id_map **ids) 772 738 { 773 struct idmap_tdb2_context *ctx;774 739 NTSTATUS ret; 775 740 int i; … … 779 744 ids[i]->status = ID_UNKNOWN; 780 745 } 781 782 ctx = talloc_get_type(dom->private_data, struct idmap_tdb2_context);783 746 784 747 for (i = 0; ids[i]; i++) { 785 ret = idmap_tdb2_id_to_sid( ctx, ids[i]);748 ret = idmap_tdb2_id_to_sid(dom, ids[i]); 786 749 if ( ! NT_STATUS_IS_OK(ret)) { 787 750 … … 793 756 continue; 794 757 } 795 758 796 759 /* some fatal error occurred, return immediately */ 797 760 goto done; … … 811 774 lookup a set of sids. 812 775 */ 776 777 struct idmap_tdb2_sids_to_unixids_context { 778 struct idmap_domain *dom; 779 struct id_map **ids; 780 bool allocate_unmapped; 781 }; 782 783 static NTSTATUS idmap_tdb2_sids_to_unixids_action(struct db_context *db, 784 void *private_data) 785 { 786 struct idmap_tdb2_sids_to_unixids_context *state; 787 int i; 788 NTSTATUS ret = NT_STATUS_OK; 789 790 state = (struct idmap_tdb2_sids_to_unixids_context *)private_data; 791 792 DEBUG(10, ("idmap_tdb2_sids_to_unixids_action: " 793 " domain: [%s], allocate: %s\n", 794 state->dom->name, 795 state->allocate_unmapped ? "yes" : "no")); 796 797 for (i = 0; state->ids[i]; i++) { 798 if ((state->ids[i]->status == ID_UNKNOWN) || 799 /* retry if we could not map in previous run: */ 800 (state->ids[i]->status == ID_UNMAPPED)) 801 { 802 NTSTATUS ret2; 803 804 ret2 = idmap_tdb2_sid_to_id(state->dom, state->ids[i]); 805 if (!NT_STATUS_IS_OK(ret2)) { 806 807 /* if it is just a failed mapping, continue */ 808 if (NT_STATUS_EQUAL(ret2, NT_STATUS_NONE_MAPPED)) { 809 810 /* make sure it is marked as unmapped */ 811 state->ids[i]->status = ID_UNMAPPED; 812 ret = STATUS_SOME_UNMAPPED; 813 } else { 814 /* some fatal error occurred, return immediately */ 815 ret = ret2; 816 goto done; 817 } 818 } else { 819 /* all ok, id is mapped */ 820 state->ids[i]->status = ID_MAPPED; 821 } 822 } 823 824 if ((state->ids[i]->status == ID_UNMAPPED) && 825 state->allocate_unmapped) 826 { 827 ret = idmap_tdb2_new_mapping(state->dom, state->ids[i]); 828 if (!NT_STATUS_IS_OK(ret)) { 829 goto done; 830 } 831 } 832 } 833 834 done: 835 return ret; 836 } 837 813 838 static NTSTATUS idmap_tdb2_sids_to_unixids(struct idmap_domain *dom, struct id_map **ids) 814 839 { 840 NTSTATUS ret; 841 int i; 842 struct idmap_tdb2_sids_to_unixids_context state; 815 843 struct idmap_tdb2_context *ctx; 816 NTSTATUS ret; 817 int i;844 845 ctx = talloc_get_type(dom->private_data, struct idmap_tdb2_context); 818 846 819 847 /* initialize the status to avoid suprise */ … … 821 849 ids[i]->status = ID_UNKNOWN; 822 850 } 823 824 ctx = talloc_get_type(dom->private_data, struct idmap_tdb2_context); 825 826 for (i = 0; ids[i]; i++) { 827 ret = idmap_tdb2_sid_to_id(ctx, ids[i]); 828 if ( ! NT_STATUS_IS_OK(ret)) { 829 830 /* if it is just a failed mapping continue */ 831 if (NT_STATUS_EQUAL(ret, NT_STATUS_NONE_MAPPED)) { 832 833 /* make sure it is marked as unmapped */ 834 ids[i]->status = ID_UNMAPPED; 835 continue; 836 } 837 838 /* some fatal error occurred, return immediately */ 839 goto done; 840 } 841 842 /* all ok, id is mapped */ 843 ids[i]->status = ID_MAPPED; 844 } 845 846 ret = NT_STATUS_OK; 847 848 done: 849 return ret; 850 } 851 852 853 /* 854 set a mapping. 855 */ 856 857 static NTSTATUS idmap_tdb2_set_mapping(struct idmap_domain *dom, const struct id_map *map) 858 { 859 struct idmap_tdb2_context *ctx; 860 NTSTATUS ret; 861 char *ksidstr, *kidstr; 862 struct idmap_tdb2_set_mapping_context state; 863 864 if (!map || !map->sid) { 865 return NT_STATUS_INVALID_PARAMETER; 866 } 867 868 ksidstr = kidstr = NULL; 869 870 /* TODO: should we filter a set_mapping using low/high filters ? */ 871 872 ctx = talloc_get_type(dom->private_data, struct idmap_tdb2_context); 873 874 switch (map->xid.type) { 875 876 case ID_TYPE_UID: 877 kidstr = talloc_asprintf(ctx, "UID %lu", (unsigned long)map->xid.id); 878 break; 879 880 case ID_TYPE_GID: 881 kidstr = talloc_asprintf(ctx, "GID %lu", (unsigned long)map->xid.id); 882 break; 883 884 default: 885 DEBUG(2, ("INVALID unix ID type: 0x02%x\n", map->xid.type)); 886 return NT_STATUS_INVALID_PARAMETER; 887 } 888 889 if (kidstr == NULL) { 890 DEBUG(0, ("ERROR: Out of memory!\n")); 891 ret = NT_STATUS_NO_MEMORY; 892 goto done; 893 } 894 895 if (!(ksidstr = sid_string_talloc(ctx, map->sid))) { 896 DEBUG(0, ("Out of memory!\n")); 897 ret = NT_STATUS_NO_MEMORY; 898 goto done; 899 } 900 901 state.ksidstr = ksidstr; 902 state.kidstr = kidstr; 903 904 ret = dbwrap_trans_do(idmap_tdb2, idmap_tdb2_set_mapping_action, 905 &state); 906 907 done: 908 talloc_free(ksidstr); 909 talloc_free(kidstr); 910 return ret; 911 } 912 913 /* 914 remove a mapping. 915 */ 916 static NTSTATUS idmap_tdb2_remove_mapping(struct idmap_domain *dom, const struct id_map *map) 917 { 918 /* not supported as it would invalidate the cache tdb on other 919 nodes */ 920 DEBUG(0,("idmap_tdb2_remove_mapping not supported\n")); 921 return NT_STATUS_NOT_SUPPORTED; 922 } 923 924 /* 925 Close the idmap tdb instance 926 */ 927 static NTSTATUS idmap_tdb2_close(struct idmap_domain *dom) 928 { 929 /* don't do anything */ 930 return NT_STATUS_OK; 931 } 932 933 934 /* 935 Dump all mappings out 936 */ 937 static NTSTATUS idmap_tdb2_dump_data(struct idmap_domain *dom, struct id_map **maps, int *num_maps) 938 { 939 DEBUG(0,("idmap_tdb2_dump_data not supported\n")); 940 return NT_STATUS_NOT_SUPPORTED; 941 } 851 852 state.dom = dom; 853 state.ids = ids; 854 state.allocate_unmapped = false; 855 856 ret = idmap_tdb2_sids_to_unixids_action(ctx->db, &state); 857 858 if (NT_STATUS_EQUAL(ret, STATUS_SOME_UNMAPPED) && !dom->read_only) { 859 state.allocate_unmapped = true; 860 ret = dbwrap_trans_do(ctx->db, 861 idmap_tdb2_sids_to_unixids_action, 862 &state); 863 } 864 865 return ret; 866 } 867 942 868 943 869 static struct idmap_methods db_methods = { … … 945 871 .unixids_to_sids = idmap_tdb2_unixids_to_sids, 946 872 .sids_to_unixids = idmap_tdb2_sids_to_unixids, 947 .set_mapping = idmap_tdb2_set_mapping, 948 .remove_mapping = idmap_tdb2_remove_mapping, 949 .dump_data = idmap_tdb2_dump_data, 950 .close_fn = idmap_tdb2_close 873 .allocate_id = idmap_tdb2_get_new_id 951 874 }; 952 875 953 static struct idmap_alloc_methods db_alloc_methods = {954 .init = idmap_tdb2_alloc_init,955 .allocate_id = idmap_tdb2_allocate_id,956 .get_id_hwm = idmap_tdb2_get_hwm,957 .set_id_hwm = idmap_tdb2_set_hwm,958 .close_fn = idmap_tdb2_alloc_close959 };960 961 876 NTSTATUS idmap_tdb2_init(void) 962 877 { 963 NTSTATUS ret;964 965 /* register both backends */966 ret = smb_register_idmap_alloc(SMB_IDMAP_INTERFACE_VERSION, "tdb2", &db_alloc_methods);967 if (! NT_STATUS_IS_OK(ret)) {968 DEBUG(0, ("Unable to register idmap alloc tdb2 module: %s\n", get_friendly_nt_error_msg(ret)));969 return ret;970 }971 972 878 return smb_register_idmap(SMB_IDMAP_INTERFACE_VERSION, "tdb2", &db_methods); 973 879 }
Note:
See TracChangeset
for help on using the changeset viewer.