00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026 #include "includes.h"
00027 #include "winbindd.h"
00028
00029 #undef DBGC_CLASS
00030 #define DBGC_CLASS DBGC_IDMAP
00031
00032
00033 #define HWM_GROUP "GROUP HWM"
00034 #define HWM_USER "USER HWM"
00035
00036 static struct idmap_tdb_state {
00037
00038
00039 uid_t low_uid, high_uid;
00040 gid_t low_gid, high_gid;
00041
00042 } idmap_tdb_state;
00043
00044
00045
00046
00047
00048
00049 static int convert_fn(TDB_CONTEXT *tdb, TDB_DATA key, TDB_DATA data, void *state)
00050 {
00051 struct winbindd_domain *domain;
00052 char *p;
00053 DOM_SID sid;
00054 uint32 rid;
00055 fstring keystr;
00056 fstring dom_name;
00057 TDB_DATA key2;
00058 BOOL *failed = (BOOL *)state;
00059
00060 DEBUG(10,("Converting %s\n", key.dptr));
00061
00062 p = strchr(key.dptr, '/');
00063 if (!p)
00064 return 0;
00065
00066 *p = 0;
00067 fstrcpy(dom_name, key.dptr);
00068 *p++ = '/';
00069
00070 domain = find_domain_from_name(dom_name);
00071 if (domain == NULL) {
00072
00073 DEBUG(0,("Unable to find domain %s\n", dom_name ));
00074 DEBUG(0,("deleting record %s\n", key.dptr ));
00075
00076 if (tdb_delete(tdb, key) != 0) {
00077 DEBUG(0, ("Unable to delete record %s\n", key.dptr));
00078 *failed = True;
00079 return -1;
00080 }
00081
00082 return 0;
00083 }
00084
00085 rid = atoi(p);
00086
00087 sid_copy(&sid, &domain->sid);
00088 sid_append_rid(&sid, rid);
00089
00090 sid_to_string(keystr, &sid);
00091 key2.dptr = keystr;
00092 key2.dsize = strlen(keystr) + 1;
00093
00094 if (tdb_store(tdb, key2, data, TDB_INSERT) != 0) {
00095 DEBUG(0,("Unable to add record %s\n", key2.dptr ));
00096 *failed = True;
00097 return -1;
00098 }
00099
00100 if (tdb_store(tdb, data, key2, TDB_REPLACE) != 0) {
00101 DEBUG(0,("Unable to update record %s\n", data.dptr ));
00102 *failed = True;
00103 return -1;
00104 }
00105
00106 if (tdb_delete(tdb, key) != 0) {
00107 DEBUG(0,("Unable to delete record %s\n", key.dptr ));
00108 *failed = True;
00109 return -1;
00110 }
00111
00112 return 0;
00113 }
00114
00115
00116
00117
00118
00119 static BOOL idmap_tdb_convert(const char *idmap_name)
00120 {
00121 int32 vers;
00122 BOOL bigendianheader;
00123 BOOL failed = False;
00124 TDB_CONTEXT *idmap_tdb;
00125
00126 if (!(idmap_tdb = tdb_open_log(idmap_name, 0,
00127 TDB_DEFAULT, O_RDWR,
00128 0600))) {
00129 DEBUG(0, ("Unable to open idmap database\n"));
00130 return False;
00131 }
00132
00133 bigendianheader = (tdb_get_flags(idmap_tdb) & TDB_BIGENDIAN) ? True : False;
00134
00135 vers = tdb_fetch_int32(idmap_tdb, "IDMAP_VERSION");
00136
00137 if (((vers == -1) && bigendianheader) || (IREV(vers) == IDMAP_VERSION)) {
00138
00139
00140
00141
00142
00143
00144 int32 wm;
00145
00146 wm = tdb_fetch_int32(idmap_tdb, HWM_USER);
00147
00148 if (wm != -1) {
00149 wm = IREV(wm);
00150 } else {
00151 wm = idmap_tdb_state.low_uid;
00152 }
00153
00154 if (tdb_store_int32(idmap_tdb, HWM_USER, wm) == -1) {
00155 DEBUG(0, ("Unable to byteswap user hwm in idmap database\n"));
00156 tdb_close(idmap_tdb);
00157 return False;
00158 }
00159
00160 wm = tdb_fetch_int32(idmap_tdb, HWM_GROUP);
00161 if (wm != -1) {
00162 wm = IREV(wm);
00163 } else {
00164 wm = idmap_tdb_state.low_gid;
00165 }
00166
00167 if (tdb_store_int32(idmap_tdb, HWM_GROUP, wm) == -1) {
00168 DEBUG(0, ("Unable to byteswap group hwm in idmap database\n"));
00169 tdb_close(idmap_tdb);
00170 return False;
00171 }
00172 }
00173
00174
00175 tdb_traverse(idmap_tdb, convert_fn, &failed);
00176
00177 if (failed) {
00178 DEBUG(0, ("Problem during conversion\n"));
00179 tdb_close(idmap_tdb);
00180 return False;
00181 }
00182
00183 if (tdb_store_int32(idmap_tdb, "IDMAP_VERSION", IDMAP_VERSION) == -1) {
00184 DEBUG(0, ("Unable to dtore idmap version in databse\n"));
00185 tdb_close(idmap_tdb);
00186 return False;
00187 }
00188
00189 tdb_close(idmap_tdb);
00190 return True;
00191 }
00192
00193
00194
00195
00196
00197 BOOL idmap_tdb_upgrade(TALLOC_CTX *ctx, const char *tdbfile)
00198 {
00199 char *backup_name;
00200
00201 DEBUG(0, ("Upgrading winbindd_idmap.tdb from an old version\n"));
00202
00203 backup_name = talloc_asprintf(ctx, "%s.bak", tdbfile);
00204 if ( ! backup_name) {
00205 DEBUG(0, ("Out of memory!\n"));
00206 return False;
00207 }
00208
00209 if (backup_tdb(tdbfile, backup_name, 0) != 0) {
00210 DEBUG(0, ("Could not backup idmap database\n"));
00211 talloc_free(backup_name);
00212 return False;
00213 }
00214
00215 talloc_free(backup_name);
00216 return idmap_tdb_convert(tdbfile);
00217 }
00218
00219
00220
00221
00222
00223
00224 static TDB_CONTEXT *idmap_tdb_common_ctx;
00225 static int idmap_tdb_open_ref_count = 0;
00226
00227 static NTSTATUS idmap_tdb_open_db(TALLOC_CTX *memctx, TDB_CONTEXT **tdbctx)
00228 {
00229 NTSTATUS ret;
00230 TALLOC_CTX *ctx;
00231 SMB_STRUCT_STAT stbuf;
00232 char *tdbfile = NULL;
00233 int32 version;
00234 BOOL tdb_is_new = False;
00235
00236 if (idmap_tdb_open_ref_count) {
00237 idmap_tdb_open_ref_count++;
00238 *tdbctx = idmap_tdb_common_ctx;
00239 return NT_STATUS_OK;
00240 }
00241
00242
00243 ctx = talloc_new(memctx);
00244 if (!ctx) {
00245 DEBUG(0, ("Out of memory!\n"));
00246 return NT_STATUS_NO_MEMORY;
00247 }
00248
00249
00250 tdbfile = talloc_strdup(ctx, lock_path("winbindd_idmap.tdb"));
00251 if (!tdbfile) {
00252 DEBUG(0, ("Out of memory!\n"));
00253 ret = NT_STATUS_NO_MEMORY;
00254 goto done;
00255 }
00256
00257 if (!file_exist(tdbfile, &stbuf)) {
00258 tdb_is_new = True;
00259 }
00260
00261 DEBUG(10,("Opening tdbfile %s\n", tdbfile ));
00262
00263
00264 if (!(idmap_tdb_common_ctx = tdb_open_log(tdbfile, 0, TDB_DEFAULT, O_RDWR | O_CREAT, 0644))) {
00265 DEBUG(0, ("Unable to open idmap database\n"));
00266 ret = NT_STATUS_UNSUCCESSFUL;
00267 goto done;
00268 }
00269
00270 if (tdb_is_new) {
00271
00272
00273
00274
00275
00276 tdb_store_int32(idmap_tdb_common_ctx, "IDMAP_VERSION", IDMAP_VERSION);
00277 }
00278
00279
00280 version = tdb_fetch_int32(idmap_tdb_common_ctx, "IDMAP_VERSION");
00281 if (version != IDMAP_VERSION) {
00282
00283
00284 tdb_close(idmap_tdb_common_ctx);
00285
00286 if ( ! idmap_tdb_upgrade(ctx, tdbfile)) {
00287
00288 DEBUG(0, ("Unable to open idmap database, it's in an old formati, and upgrade failed!\n"));
00289 ret = NT_STATUS_INTERNAL_DB_ERROR;
00290 goto done;
00291 }
00292
00293
00294 if (!(idmap_tdb_common_ctx = tdb_open_log(tdbfile, 0, TDB_DEFAULT, O_RDWR | O_CREAT, 0644))) {
00295 DEBUG(0, ("Unable to open idmap database\n"));
00296 ret = NT_STATUS_UNSUCCESSFUL;
00297 goto done;
00298 }
00299 }
00300
00301 *tdbctx = idmap_tdb_common_ctx;
00302 idmap_tdb_open_ref_count++;
00303 ret = NT_STATUS_OK;
00304
00305 done:
00306 talloc_free(ctx);
00307 return ret;
00308 }
00309
00310
00311
00312
00313 BOOL idmap_tdb_tdb_close(TDB_CONTEXT *tdbctx)
00314 {
00315 if (tdbctx != idmap_tdb_common_ctx) {
00316 DEBUG(0, ("ERROR: Invalid tdb context!"));
00317 return False;
00318 }
00319
00320 idmap_tdb_open_ref_count--;
00321 if (idmap_tdb_open_ref_count) {
00322 return True;
00323 }
00324
00325 return tdb_close(idmap_tdb_common_ctx);
00326 }
00327
00328
00329
00330
00331
00332 static TDB_CONTEXT *idmap_alloc_tdb;
00333
00334
00335
00336
00337
00338 static NTSTATUS idmap_tdb_alloc_init( const char *params )
00339 {
00340 NTSTATUS ret;
00341 TALLOC_CTX *ctx;
00342 const char *range;
00343 uid_t low_uid = 0;
00344 uid_t high_uid = 0;
00345 gid_t low_gid = 0;
00346 gid_t high_gid = 0;
00347
00348
00349 ctx = talloc_new(NULL);
00350 if (!ctx) {
00351 DEBUG(0, ("Out of memory!\n"));
00352 return NT_STATUS_NO_MEMORY;
00353 }
00354
00355 ret = idmap_tdb_open_db(ctx, &idmap_alloc_tdb);
00356 if ( ! NT_STATUS_IS_OK(ret)) {
00357 talloc_free(ctx);
00358 return ret;
00359 }
00360
00361 talloc_free(ctx);
00362
00363
00364 idmap_tdb_state.low_uid = 0;
00365 idmap_tdb_state.high_uid = 0;
00366 idmap_tdb_state.low_gid = 0;
00367 idmap_tdb_state.high_gid = 0;
00368
00369 range = lp_parm_const_string(-1, "idmap alloc config", "range", NULL);
00370 if (range && range[0]) {
00371 unsigned low_id, high_id;
00372
00373 if (sscanf(range, "%u - %u", &low_id, &high_id) == 2) {
00374 if (low_id < high_id) {
00375 idmap_tdb_state.low_gid = idmap_tdb_state.low_uid = low_id;
00376 idmap_tdb_state.high_gid = idmap_tdb_state.high_uid = high_id;
00377 } else {
00378 DEBUG(1, ("ERROR: invalid idmap alloc range [%s]", range));
00379 }
00380 } else {
00381 DEBUG(1, ("ERROR: invalid syntax for idmap alloc config:range [%s]", range));
00382 }
00383 }
00384
00385
00386 if (lp_idmap_uid(&low_uid, &high_uid)) {
00387 idmap_tdb_state.low_uid = low_uid;
00388 idmap_tdb_state.high_uid = high_uid;
00389 }
00390
00391 if (lp_idmap_gid(&low_gid, &high_gid)) {
00392 idmap_tdb_state.low_gid = low_gid;
00393 idmap_tdb_state.high_gid = high_gid;
00394 }
00395
00396 if (idmap_tdb_state.high_uid <= idmap_tdb_state.low_uid) {
00397 DEBUG(1, ("idmap uid range missing or invalid\n"));
00398 DEBUGADD(1, ("idmap will be unable to map foreign SIDs\n"));
00399 return NT_STATUS_UNSUCCESSFUL;
00400 } else {
00401 uint32 low_id;
00402
00403 if (((low_id = tdb_fetch_int32(idmap_alloc_tdb, HWM_USER)) == -1) ||
00404 (low_id < idmap_tdb_state.low_uid)) {
00405 if (tdb_store_int32(idmap_alloc_tdb, HWM_USER, idmap_tdb_state.low_uid) == -1) {
00406 DEBUG(0, ("Unable to initialise user hwm in idmap database\n"));
00407 return NT_STATUS_INTERNAL_DB_ERROR;
00408 }
00409 }
00410 }
00411
00412 if (idmap_tdb_state.high_gid <= idmap_tdb_state.low_gid) {
00413 DEBUG(1, ("idmap gid range missing or invalid\n"));
00414 DEBUGADD(1, ("idmap will be unable to map foreign SIDs\n"));
00415 return NT_STATUS_UNSUCCESSFUL;
00416 } else {
00417 uint32 low_id;
00418
00419 if (((low_id = tdb_fetch_int32(idmap_alloc_tdb, HWM_GROUP)) == -1) ||
00420 (low_id < idmap_tdb_state.low_gid)) {
00421 if (tdb_store_int32(idmap_alloc_tdb, HWM_GROUP, idmap_tdb_state.low_gid) == -1) {
00422 DEBUG(0, ("Unable to initialise group hwm in idmap database\n"));
00423 return NT_STATUS_INTERNAL_DB_ERROR;
00424 }
00425 }
00426 }
00427
00428 return NT_STATUS_OK;
00429 }
00430
00431
00432
00433
00434
00435 static NTSTATUS idmap_tdb_allocate_id(struct unixid *xid)
00436 {
00437 BOOL ret;
00438 const char *hwmkey;
00439 const char *hwmtype;
00440 uint32_t high_hwm;
00441 uint32_t hwm;
00442
00443
00444 switch (xid->type) {
00445
00446 case ID_TYPE_UID:
00447 hwmkey = HWM_USER;
00448 hwmtype = "UID";
00449 high_hwm = idmap_tdb_state.high_uid;
00450 break;
00451
00452 case ID_TYPE_GID:
00453 hwmkey = HWM_GROUP;
00454 hwmtype = "GID";
00455 high_hwm = idmap_tdb_state.high_gid;
00456 break;
00457
00458 default:
00459 DEBUG(2, ("Invalid ID type (0x%x)\n", xid->type));
00460 return NT_STATUS_INVALID_PARAMETER;
00461 }
00462
00463 if ((hwm = tdb_fetch_int32(idmap_alloc_tdb, hwmkey)) == -1) {
00464 return NT_STATUS_INTERNAL_DB_ERROR;
00465 }
00466
00467
00468 if (hwm > high_hwm) {
00469 DEBUG(1, ("Fatal Error: %s range full!! (max: %lu)\n",
00470 hwmtype, (unsigned long)high_hwm));
00471 return NT_STATUS_UNSUCCESSFUL;
00472 }
00473
00474
00475 ret = tdb_change_uint32_atomic(idmap_alloc_tdb, hwmkey, &hwm, 1);
00476 if (!ret) {
00477 DEBUG(1, ("Fatal error while fetching a new %s value\n!", hwmtype));
00478 return NT_STATUS_UNSUCCESSFUL;
00479 }
00480
00481
00482 if (hwm > high_hwm) {
00483 DEBUG(1, ("Fatal Error: %s range full!! (max: %lu)\n",
00484 hwmtype, (unsigned long)high_hwm));
00485 return NT_STATUS_UNSUCCESSFUL;
00486 }
00487
00488 xid->id = hwm;
00489 DEBUG(10,("New %s = %d\n", hwmtype, hwm));
00490
00491 return NT_STATUS_OK;
00492 }
00493
00494
00495
00496
00497
00498 static NTSTATUS idmap_tdb_get_hwm(struct unixid *xid)
00499 {
00500 const char *hwmkey;
00501 const char *hwmtype;
00502 uint32_t hwm;
00503 uint32_t high_hwm;
00504
00505
00506 switch (xid->type) {
00507
00508 case ID_TYPE_UID:
00509 hwmkey = HWM_USER;
00510 hwmtype = "UID";
00511 high_hwm = idmap_tdb_state.high_uid;
00512 break;
00513
00514 case ID_TYPE_GID:
00515 hwmkey = HWM_GROUP;
00516 hwmtype = "GID";
00517 high_hwm = idmap_tdb_state.high_gid;
00518 break;
00519
00520 default:
00521 return NT_STATUS_INVALID_PARAMETER;
00522 }
00523
00524 if ((hwm = tdb_fetch_int32(idmap_alloc_tdb, hwmkey)) == -1) {
00525 return NT_STATUS_INTERNAL_DB_ERROR;
00526 }
00527
00528 xid->id = hwm;
00529
00530
00531 if (hwm >= high_hwm) {
00532 DEBUG(0, ("Warning: %s range full!! (max: %lu)\n",
00533 hwmtype, (unsigned long)high_hwm));
00534 }
00535
00536 return NT_STATUS_OK;
00537 }
00538
00539
00540
00541
00542
00543 static NTSTATUS idmap_tdb_set_hwm(struct unixid *xid)
00544 {
00545 const char *hwmkey;
00546 const char *hwmtype;
00547 uint32_t hwm;
00548 uint32_t high_hwm;
00549
00550
00551 switch (xid->type) {
00552
00553 case ID_TYPE_UID:
00554 hwmkey = HWM_USER;
00555 hwmtype = "UID";
00556 high_hwm = idmap_tdb_state.high_uid;
00557 break;
00558
00559 case ID_TYPE_GID:
00560 hwmkey = HWM_GROUP;
00561 hwmtype = "GID";
00562 high_hwm = idmap_tdb_state.high_gid;
00563 break;
00564
00565 default:
00566 return NT_STATUS_INVALID_PARAMETER;
00567 }
00568
00569 hwm = xid->id;
00570
00571 if ((hwm = tdb_store_int32(idmap_alloc_tdb, hwmkey, hwm)) == -1) {
00572 return NT_STATUS_INTERNAL_DB_ERROR;
00573 }
00574
00575
00576 if (hwm >= high_hwm) {
00577 DEBUG(0, ("Warning: %s range full!! (max: %lu)\n",
00578 hwmtype, (unsigned long)high_hwm));
00579 }
00580
00581 return NT_STATUS_OK;
00582 }
00583
00584
00585
00586
00587
00588 static NTSTATUS idmap_tdb_alloc_close(void)
00589 {
00590 if (idmap_alloc_tdb) {
00591 if (idmap_tdb_tdb_close(idmap_alloc_tdb) == 0) {
00592 return NT_STATUS_OK;
00593 } else {
00594 return NT_STATUS_UNSUCCESSFUL;
00595 }
00596 }
00597 return NT_STATUS_OK;
00598 }
00599
00600
00601
00602
00603
00604 struct idmap_tdb_context {
00605 TDB_CONTEXT *tdb;
00606 uint32_t filter_low_id;
00607 uint32_t filter_high_id;
00608 };
00609
00610
00611
00612
00613
00614 static NTSTATUS idmap_tdb_db_init(struct idmap_domain *dom)
00615 {
00616 NTSTATUS ret;
00617 struct idmap_tdb_context *ctx;
00618 char *config_option = NULL;
00619 const char *range;
00620
00621 ctx = talloc(dom, struct idmap_tdb_context);
00622 if ( ! ctx) {
00623 DEBUG(0, ("Out of memory!\n"));
00624 return NT_STATUS_NO_MEMORY;
00625 }
00626
00627 config_option = talloc_asprintf(ctx, "idmap config %s", dom->name);
00628 if ( ! config_option) {
00629 DEBUG(0, ("Out of memory!\n"));
00630 ret = NT_STATUS_NO_MEMORY;
00631 goto failed;
00632 }
00633
00634 ret = idmap_tdb_open_db(ctx, &ctx->tdb);
00635 if ( ! NT_STATUS_IS_OK(ret)) {
00636 goto failed;
00637 }
00638
00639 range = lp_parm_const_string(-1, config_option, "range", NULL);
00640 if (( ! range) ||
00641 (sscanf(range, "%u - %u", &ctx->filter_low_id, &ctx->filter_high_id) != 2) ||
00642 (ctx->filter_low_id > ctx->filter_high_id)) {
00643 ctx->filter_low_id = 0;
00644 ctx->filter_high_id = 0;
00645 }
00646
00647 dom->private_data = ctx;
00648 dom->initialized = True;
00649
00650 talloc_free(config_option);
00651 return NT_STATUS_OK;
00652
00653 failed:
00654 talloc_free(ctx);
00655 return ret;
00656 }
00657
00658
00659
00660
00661
00662 static NTSTATUS idmap_tdb_id_to_sid(struct idmap_tdb_context *ctx, struct id_map *map)
00663 {
00664 NTSTATUS ret;
00665 TDB_DATA key, data;
00666
00667 if (!ctx || !map) {
00668 return NT_STATUS_INVALID_PARAMETER;
00669 }
00670
00671
00672 if ((ctx->filter_low_id && (map->xid.id < ctx->filter_low_id)) ||
00673 (ctx->filter_high_id && (map->xid.id > ctx->filter_high_id))) {
00674 DEBUG(5, ("Requested id (%u) out of range (%u - %u). Filtered!\n",
00675 map->xid.id, ctx->filter_low_id, ctx->filter_high_id));
00676 return NT_STATUS_NONE_MAPPED;
00677 }
00678
00679 switch (map->xid.type) {
00680
00681 case ID_TYPE_UID:
00682 key.dptr = talloc_asprintf(ctx, "UID %lu", (unsigned long)map->xid.id);
00683 break;
00684
00685 case ID_TYPE_GID:
00686 key.dptr = talloc_asprintf(ctx, "GID %lu", (unsigned long)map->xid.id);
00687 break;
00688
00689 default:
00690 DEBUG(2, ("INVALID unix ID type: 0x02%x\n", map->xid.type));
00691 return NT_STATUS_INVALID_PARAMETER;
00692 }
00693
00694
00695 data.dptr = NULL;
00696
00697 if (key.dptr == NULL) {
00698 DEBUG(0, ("Out of memory!\n"));
00699 ret = NT_STATUS_NO_MEMORY;
00700 goto done;
00701 }
00702
00703 key.dsize = strlen(key.dptr) + 1;
00704
00705 DEBUG(10,("Fetching record %s\n", key.dptr));
00706
00707
00708 data = tdb_fetch(ctx->tdb, key);
00709
00710 if (!data.dptr) {
00711 DEBUG(10,("Record %s not found\n", key.dptr));
00712 ret = NT_STATUS_NONE_MAPPED;
00713 goto done;
00714 }
00715
00716 if (!string_to_sid(map->sid, data.dptr)) {
00717 DEBUG(10,("INVALID SID (%s) in record %s\n",
00718 data.dptr, key.dptr));
00719 ret = NT_STATUS_INTERNAL_DB_ERROR;
00720 goto done;
00721 }
00722
00723 DEBUG(10,("Found record %s -> %s\n", key.dptr, data.dptr));
00724 ret = NT_STATUS_OK;
00725
00726 done:
00727 SAFE_FREE(data.dptr);
00728 talloc_free(key.dptr);
00729 return ret;
00730 }
00731
00732
00733
00734
00735
00736 static NTSTATUS idmap_tdb_sid_to_id(struct idmap_tdb_context *ctx, struct id_map *map)
00737 {
00738 NTSTATUS ret;
00739 TDB_DATA key, data;
00740 unsigned long rec_id = 0;
00741
00742 if ((key.dptr = talloc_asprintf(ctx, "%s", sid_string_static(map->sid))) == NULL) {
00743 DEBUG(0, ("Out of memory!\n"));
00744 ret = NT_STATUS_NO_MEMORY;
00745 goto done;
00746 }
00747
00748 key.dsize = strlen(key.dptr) + 1;
00749
00750 DEBUG(10,("Fetching record %s\n", key.dptr));
00751
00752
00753 data = tdb_fetch(ctx->tdb, key);
00754 if (!data.dptr) {
00755 DEBUG(10,("Record %s not found\n", key.dptr));
00756 ret = NT_STATUS_NONE_MAPPED;
00757 goto done;
00758 }
00759
00760
00761 if (sscanf(data.dptr, "UID %lu", &rec_id) == 1) {
00762 map->xid.id = rec_id;
00763 map->xid.type = ID_TYPE_UID;
00764 DEBUG(10,("Found uid record %s -> %s \n", key.dptr, data.dptr ));
00765 ret = NT_STATUS_OK;
00766
00767 } else if (sscanf(data.dptr, "GID %lu", &rec_id) == 1) {
00768 map->xid.id = rec_id;
00769 map->xid.type = ID_TYPE_GID;
00770 DEBUG(10,("Found gid record %s -> %s \n", key.dptr, data.dptr ));
00771 ret = NT_STATUS_OK;
00772
00773 } else {
00774 DEBUG(2, ("Found INVALID record %s -> %s\n", key.dptr, data.dptr));
00775 ret = NT_STATUS_INTERNAL_DB_ERROR;
00776 }
00777
00778 SAFE_FREE(data.dptr);
00779
00780
00781 if ((ctx->filter_low_id && (map->xid.id < ctx->filter_low_id)) ||
00782 (ctx->filter_high_id && (map->xid.id > ctx->filter_high_id))) {
00783 DEBUG(5, ("Requested id (%u) out of range (%u - %u). Filtered!\n",
00784 map->xid.id, ctx->filter_low_id, ctx->filter_high_id));
00785 ret = NT_STATUS_NONE_MAPPED;
00786 }
00787
00788 done:
00789 talloc_free(key.dptr);
00790 return ret;
00791 }
00792
00793
00794
00795
00796
00797 static NTSTATUS idmap_tdb_unixids_to_sids(struct idmap_domain *dom, struct id_map **ids)
00798 {
00799 struct idmap_tdb_context *ctx;
00800 NTSTATUS ret;
00801 int i;
00802
00803
00804 if ( ! dom->initialized) {
00805 ret = idmap_tdb_db_init(dom);
00806 if ( ! NT_STATUS_IS_OK(ret)) {
00807 return ret;
00808 }
00809 }
00810
00811 ctx = talloc_get_type(dom->private_data, struct idmap_tdb_context);
00812
00813 for (i = 0; ids[i]; i++) {
00814 ret = idmap_tdb_id_to_sid(ctx, ids[i]);
00815 if ( ! NT_STATUS_IS_OK(ret)) {
00816
00817
00818 if (NT_STATUS_EQUAL(ret, NT_STATUS_NONE_MAPPED)) {
00819
00820
00821 ids[i]->status = ID_UNMAPPED;
00822 continue;
00823 }
00824
00825
00826 goto done;
00827 }
00828
00829
00830 ids[i]->status = ID_MAPPED;
00831 }
00832
00833 ret = NT_STATUS_OK;
00834
00835 done:
00836 return ret;
00837 }
00838
00839
00840
00841
00842
00843 static NTSTATUS idmap_tdb_sids_to_unixids(struct idmap_domain *dom, struct id_map **ids)
00844 {
00845 struct idmap_tdb_context *ctx;
00846 NTSTATUS ret;
00847 int i;
00848
00849
00850 if ( ! dom->initialized) {
00851 ret = idmap_tdb_db_init(dom);
00852 if ( ! NT_STATUS_IS_OK(ret)) {
00853 return ret;
00854 }
00855 }
00856
00857 ctx = talloc_get_type(dom->private_data, struct idmap_tdb_context);
00858
00859 for (i = 0; ids[i]; i++) {
00860 ret = idmap_tdb_sid_to_id(ctx, ids[i]);
00861 if ( ! NT_STATUS_IS_OK(ret)) {
00862
00863
00864 if (NT_STATUS_EQUAL(ret, NT_STATUS_NONE_MAPPED)) {
00865
00866
00867 ids[i]->status = ID_UNMAPPED;
00868 continue;
00869 }
00870
00871
00872 goto done;
00873 }
00874
00875
00876 ids[i]->status = ID_MAPPED;
00877 }
00878
00879 ret = NT_STATUS_OK;
00880
00881 done:
00882 return ret;
00883 }
00884
00885
00886
00887
00888
00889 static NTSTATUS idmap_tdb_set_mapping(struct idmap_domain *dom, const struct id_map *map)
00890 {
00891 struct idmap_tdb_context *ctx;
00892 NTSTATUS ret;
00893 TDB_DATA ksid, kid, data;
00894
00895
00896 if ( ! dom->initialized) {
00897 ret = idmap_tdb_db_init(dom);
00898 if ( ! NT_STATUS_IS_OK(ret)) {
00899 return ret;
00900 }
00901 }
00902
00903 if (!map || !map->sid) {
00904 return NT_STATUS_INVALID_PARAMETER;
00905 }
00906
00907 ksid.dptr = kid.dptr = data.dptr = NULL;
00908
00909
00910
00911 ctx = talloc_get_type(dom->private_data, struct idmap_tdb_context);
00912
00913 switch (map->xid.type) {
00914
00915 case ID_TYPE_UID:
00916 kid.dptr = talloc_asprintf(ctx, "UID %lu", (unsigned long)map->xid.id);
00917 break;
00918
00919 case ID_TYPE_GID:
00920 kid.dptr = talloc_asprintf(ctx, "GID %lu", (unsigned long)map->xid.id);
00921 break;
00922
00923 default:
00924 DEBUG(2, ("INVALID unix ID type: 0x02%x\n", map->xid.type));
00925 return NT_STATUS_INVALID_PARAMETER;
00926 }
00927
00928 if (kid.dptr == NULL) {
00929 DEBUG(0, ("ERROR: Out of memory!\n"));
00930 ret = NT_STATUS_NO_MEMORY;
00931 goto done;
00932 }
00933 kid.dsize = strlen(kid.dptr) + 1;
00934
00935 if ((ksid.dptr = talloc_asprintf(ctx, "%s", sid_string_static(map->sid))) == NULL) {
00936 DEBUG(0, ("Out of memory!\n"));
00937 ret = NT_STATUS_NO_MEMORY;
00938 goto done;
00939 }
00940 ksid.dsize = strlen(ksid.dptr) + 1;
00941
00942 DEBUG(10, ("Storing %s <-> %s map\n", ksid.dptr, kid.dptr));
00943
00944
00945
00946
00947
00948 if (tdb_chainlock(ctx->tdb, ksid) != 0) {
00949 DEBUG(10,("Failed to lock record %s. Error %s\n",
00950 ksid.dptr, tdb_errorstr(ctx->tdb) ));
00951 return NT_STATUS_UNSUCCESSFUL;
00952 }
00953
00954 data = tdb_fetch(ctx->tdb, ksid);
00955 if (data.dptr) {
00956 DEBUG(10, ("Deleting existing mapping %s <-> %s\n", data.dptr, ksid.dptr ));
00957 tdb_delete(ctx->tdb, data);
00958 tdb_delete(ctx->tdb, ksid);
00959 SAFE_FREE(data.dptr);
00960 }
00961
00962 data = tdb_fetch(ctx->tdb, kid);
00963 if (data.dptr) {
00964 DEBUG(10,("Deleting existing mapping %s <-> %s\n", data.dptr, kid.dptr ));
00965 tdb_delete(ctx->tdb, data);
00966 tdb_delete(ctx->tdb, kid);
00967 SAFE_FREE(data.dptr);
00968 }
00969
00970 if (tdb_store(ctx->tdb, ksid, kid, TDB_INSERT) == -1) {
00971 DEBUG(0, ("Error storing SID -> ID: %s\n", tdb_errorstr(ctx->tdb)));
00972 tdb_chainunlock(ctx->tdb, ksid);
00973 ret = NT_STATUS_UNSUCCESSFUL;
00974 goto done;
00975 }
00976 if (tdb_store(ctx->tdb, kid, ksid, TDB_INSERT) == -1) {
00977 DEBUG(0, ("Error stroing ID -> SID: %s\n", tdb_errorstr(ctx->tdb)));
00978
00979 tdb_delete(ctx->tdb, ksid);
00980 tdb_chainunlock(ctx->tdb, ksid);
00981 ret = NT_STATUS_UNSUCCESSFUL;
00982 goto done;
00983 }
00984
00985 tdb_chainunlock(ctx->tdb, ksid);
00986 DEBUG(10,("Stored %s <-> %s\n", ksid.dptr, kid.dptr));
00987 ret = NT_STATUS_OK;
00988
00989 done:
00990 talloc_free(ksid.dptr);
00991 talloc_free(kid.dptr);
00992 SAFE_FREE(data.dptr);
00993 return ret;
00994 }
00995
00996
00997
00998
00999
01000 static NTSTATUS idmap_tdb_remove_mapping(struct idmap_domain *dom, const struct id_map *map)
01001 {
01002 struct idmap_tdb_context *ctx;
01003 NTSTATUS ret;
01004 TDB_DATA ksid, kid, data;
01005
01006
01007 if ( ! dom->initialized) {
01008 ret = idmap_tdb_db_init(dom);
01009 if ( ! NT_STATUS_IS_OK(ret)) {
01010 return ret;
01011 }
01012 }
01013
01014 if (!map || !map->sid) {
01015 return NT_STATUS_INVALID_PARAMETER;
01016 }
01017
01018 ksid.dptr = kid.dptr = data.dptr = NULL;
01019
01020
01021
01022 ctx = talloc_get_type(dom->private_data, struct idmap_tdb_context);
01023
01024 switch (map->xid.type) {
01025
01026 case ID_TYPE_UID:
01027 kid.dptr = talloc_asprintf(ctx, "UID %lu", (unsigned long)map->xid.id);
01028 break;
01029
01030 case ID_TYPE_GID:
01031 kid.dptr = talloc_asprintf(ctx, "GID %lu", (unsigned long)map->xid.id);
01032 break;
01033
01034 default:
01035 DEBUG(2, ("INVALID unix ID type: 0x02%x\n", map->xid.type));
01036 return NT_STATUS_INVALID_PARAMETER;
01037 }
01038
01039 if (kid.dptr == NULL) {
01040 DEBUG(0, ("ERROR: Out of memory!\n"));
01041 ret = NT_STATUS_NO_MEMORY;
01042 goto done;
01043 }
01044 kid.dsize = strlen(kid.dptr) + 1;
01045
01046 if ((ksid.dptr = talloc_asprintf(ctx, "%s", sid_string_static(map->sid))) == NULL) {
01047 DEBUG(0, ("Out of memory!\n"));
01048 ret = NT_STATUS_NO_MEMORY;
01049 goto done;
01050 }
01051 ksid.dsize = strlen(ksid.dptr) + 1;
01052
01053 DEBUG(10, ("Checking %s <-> %s map\n", ksid.dptr, kid.dptr));
01054
01055
01056 if (tdb_chainlock(ctx->tdb, ksid) != 0) {
01057 DEBUG(10,("Failed to lock record %s. Error %s\n",
01058 ksid.dptr, tdb_errorstr(ctx->tdb) ));
01059 return NT_STATUS_UNSUCCESSFUL;
01060 }
01061
01062
01063 data = tdb_fetch(ctx->tdb, ksid);
01064 if (!data.dptr) {
01065 DEBUG(10,("Record %s not found\n", ksid.dptr));
01066 tdb_chainunlock(ctx->tdb, ksid);
01067 ret = NT_STATUS_NONE_MAPPED;
01068 goto done;
01069 }
01070
01071
01072 if ((data.dsize != kid.dsize) ||
01073 (memcmp(data.dptr, kid.dptr, data.dsize) != 0)) {
01074 DEBUG(10,("Specified SID does not map to specified ID\n"));
01075 DEBUGADD(10,("Actual mapping is %s -> %s\n", ksid.dptr, data.dptr));
01076 tdb_chainunlock(ctx->tdb, ksid);
01077 ret = NT_STATUS_NONE_MAPPED;
01078 goto done;
01079 }
01080
01081 DEBUG(10, ("Removing %s <-> %s map\n", ksid.dptr, kid.dptr));
01082
01083
01084
01085 DEBUG(10, ("Deleting existing mapping %s -> %s\n", ksid.dptr, kid.dptr ));
01086 tdb_delete(ctx->tdb, ksid);
01087
01088 DEBUG(10,("Deleting existing mapping %s -> %s\n", kid.dptr, ksid.dptr ));
01089 tdb_delete(ctx->tdb, kid);
01090
01091 tdb_chainunlock(ctx->tdb, ksid);
01092 ret = NT_STATUS_OK;
01093
01094 done:
01095 talloc_free(ksid.dptr);
01096 talloc_free(kid.dptr);
01097 SAFE_FREE(data.dptr);
01098 return ret;
01099 }
01100
01101
01102
01103
01104
01105 static NTSTATUS idmap_tdb_close(struct idmap_domain *dom)
01106 {
01107 struct idmap_tdb_context *ctx;
01108
01109 if (dom->private_data) {
01110 ctx = talloc_get_type(dom->private_data, struct idmap_tdb_context);
01111
01112 if (idmap_tdb_tdb_close(ctx->tdb) == 0) {
01113 return NT_STATUS_OK;
01114 } else {
01115 return NT_STATUS_UNSUCCESSFUL;
01116 }
01117 }
01118 return NT_STATUS_OK;
01119 }
01120
01121 struct dump_data {
01122 TALLOC_CTX *memctx;
01123 struct id_map **maps;
01124 int *num_maps;
01125 NTSTATUS ret;
01126 };
01127
01128 static int idmap_tdb_dump_one_entry(TDB_CONTEXT *tdb, TDB_DATA key, TDB_DATA value, void *pdata)
01129 {
01130 struct dump_data *data = talloc_get_type(pdata, struct dump_data);
01131 struct id_map *maps;
01132 int num_maps = *data->num_maps;
01133
01134
01135 if (strncmp(key.dptr, "S-", 2) == 0) {
01136
01137 maps = talloc_realloc(NULL, *data->maps, struct id_map, num_maps+1);
01138 if ( ! maps) {
01139 DEBUG(0, ("Out of memory!\n"));
01140 data->ret = NT_STATUS_NO_MEMORY;
01141 return -1;
01142 }
01143 *data->maps = maps;
01144 maps[num_maps].sid = talloc(maps, DOM_SID);
01145 if ( ! maps[num_maps].sid) {
01146 DEBUG(0, ("Out of memory!\n"));
01147 data->ret = NT_STATUS_NO_MEMORY;
01148 return -1;
01149 }
01150
01151 if (!string_to_sid(maps[num_maps].sid, key.dptr)) {
01152 DEBUG(10,("INVALID record %s\n", key.dptr));
01153
01154 return 0;
01155 }
01156
01157
01158 if (sscanf(value.dptr, "UID %u", &(maps[num_maps].xid.id)) == 1) {
01159 maps[num_maps].xid.type = ID_TYPE_UID;
01160 maps[num_maps].status = ID_MAPPED;
01161 *data->num_maps = num_maps + 1;
01162
01163
01164 } else
01165 if (sscanf(value.dptr, "GID %u", &(maps[num_maps].xid.id)) == 1) {
01166 maps[num_maps].xid.type = ID_TYPE_GID;
01167 maps[num_maps].status = ID_MAPPED;
01168 *data->num_maps = num_maps + 1;
01169
01170
01171 } else {
01172 maps[num_maps].status = ID_UNKNOWN;
01173 DEBUG(2, ("Found INVALID record %s -> %s\n", key.dptr, value.dptr));
01174
01175 }
01176 }
01177
01178 return 0;
01179 }
01180
01181
01182
01183
01184
01185 static NTSTATUS idmap_tdb_dump_data(struct idmap_domain *dom, struct id_map **maps, int *num_maps)
01186 {
01187 struct idmap_tdb_context *ctx;
01188 struct dump_data *data;
01189 NTSTATUS ret = NT_STATUS_OK;
01190
01191
01192 if ( ! dom->initialized) {
01193 ret = idmap_tdb_db_init(dom);
01194 if ( ! NT_STATUS_IS_OK(ret)) {
01195 return ret;
01196 }
01197 }
01198
01199 ctx = talloc_get_type(dom->private_data, struct idmap_tdb_context);
01200
01201 data = TALLOC_ZERO_P(ctx, struct dump_data);
01202 if ( ! data) {
01203 DEBUG(0, ("Out of memory!\n"));
01204 return NT_STATUS_NO_MEMORY;
01205 }
01206 data->maps = maps;
01207 data->num_maps = num_maps;
01208 data->ret = NT_STATUS_OK;
01209
01210 tdb_traverse(ctx->tdb, idmap_tdb_dump_one_entry, data);
01211
01212 if ( ! NT_STATUS_IS_OK(data->ret)) {
01213 ret = data->ret;
01214 }
01215
01216 talloc_free(data);
01217 return ret;
01218 }
01219
01220 static struct idmap_methods db_methods = {
01221
01222 .init = idmap_tdb_db_init,
01223 .unixids_to_sids = idmap_tdb_unixids_to_sids,
01224 .sids_to_unixids = idmap_tdb_sids_to_unixids,
01225 .set_mapping = idmap_tdb_set_mapping,
01226 .remove_mapping = idmap_tdb_remove_mapping,
01227 .dump_data = idmap_tdb_dump_data,
01228 .close_fn = idmap_tdb_close
01229 };
01230
01231 static struct idmap_alloc_methods db_alloc_methods = {
01232
01233 .init = idmap_tdb_alloc_init,
01234 .allocate_id = idmap_tdb_allocate_id,
01235 .get_id_hwm = idmap_tdb_get_hwm,
01236 .set_id_hwm = idmap_tdb_set_hwm,
01237 .close_fn = idmap_tdb_alloc_close
01238 };
01239
01240 NTSTATUS idmap_alloc_tdb_init(void)
01241 {
01242 return smb_register_idmap_alloc(SMB_IDMAP_INTERFACE_VERSION, "tdb", &db_alloc_methods);
01243 }
01244
01245 NTSTATUS idmap_tdb_init(void)
01246 {
01247 NTSTATUS ret;
01248
01249
01250 ret = idmap_alloc_tdb_init();
01251 if (! NT_STATUS_IS_OK(ret)) {
01252 return ret;
01253 }
01254 return smb_register_idmap(SMB_IDMAP_INTERFACE_VERSION, "tdb", &db_methods);
01255 }