Changeset 30 for trunk/samba/source/nsswitch/idmap.c
- Timestamp:
- Apr 25, 2007, 11:44:55 AM (18 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/samba/source/nsswitch/idmap.c
r26 r30 44 44 struct idmap_cache_ctx; 45 45 46 struct idmap_alloc_context { 47 const char *params; 48 struct idmap_alloc_methods *methods; 49 BOOL initialized; 50 }; 51 46 52 static TALLOC_CTX *idmap_ctx = NULL; 47 53 static struct idmap_cache_ctx *idmap_cache; … … 54 60 55 61 static struct idmap_alloc_backend *alloc_backends = NULL; 56 static struct idmap_alloc_ methods *alloc_methods= NULL;62 static struct idmap_alloc_context *idmap_alloc_ctx = NULL; 57 63 58 64 #define IDMAP_CHECK_RET(ret) do { if ( ! NT_STATUS_IS_OK(ret)) { DEBUG(2, ("ERROR: NTSTATUS = 0x%08x\n", NT_STATUS_V(ret))); goto done; } } while(0) 65 #define IDMAP_REPORT_RET(ret) do { if ( ! NT_STATUS_IS_OK(ret)) { DEBUG(2, ("ERROR: NTSTATUS = 0x%08x\n", NT_STATUS_V(ret))); } } while(0) 59 66 #define IDMAP_CHECK_ALLOC(mem) do { if (!mem) { DEBUG(0, ("Out of memory!\n")); ret = NT_STATUS_NO_MEMORY; goto done; } } while(0) 60 67 … … 83 90 84 91 return NULL; 92 } 93 94 BOOL idmap_is_offline(void) 95 { 96 return ( lp_winbind_offline_logon() && 97 get_global_winbindd_state_offline() ); 85 98 } 86 99 … … 204 217 { 205 218 /* close the alloc backend first before freeing idmap_ctx */ 206 if ( alloc_methods) {207 alloc_methods->close_fn();208 alloc_methods = NULL;219 if (idmap_alloc_ctx) { 220 idmap_alloc_ctx->methods->close_fn(); 221 idmap_alloc_ctx->methods = NULL; 209 222 } 210 223 alloc_backends = NULL; … … 255 268 { 256 269 NTSTATUS ret; 257 static NTSTATUS backend_init_status = NT_STATUS_UNSUCCESSFUL;270 static NTSTATUS idmap_init_status = NT_STATUS_UNSUCCESSFUL; 258 271 struct idmap_domain *dom; 259 272 char *compat_backend = NULL; 260 273 char *compat_params = NULL; 261 274 const char **dom_list = NULL; 262 char *alloc_backend ;275 char *alloc_backend = NULL; 263 276 BOOL default_already_defined = False; 264 277 BOOL pri_dom_is_in_list = False; … … 266 279 int i; 267 280 268 /* Always initialize the cache. We'll have to delay initialization269 of backends if we are offline */270 271 281 ret = idmap_init_cache(); 272 282 if ( !NT_STATUS_IS_OK(ret) ) 273 283 return ret; 274 284 275 if ( NT_STATUS_IS_OK(backend_init_status) ) {285 if (NT_STATUS_IS_OK(idmap_init_status)) 276 286 return NT_STATUS_OK; 277 }278 279 /* We can't reliably call intialization code here unless280 we are online */281 282 if ( get_global_winbindd_state_offline() ) {283 backend_init_status = NT_STATUS_FILE_IS_OFFLINE;284 return backend_init_status;285 }286 287 287 288 static_init_idmap; … … 322 323 compat_params = p + 1; 323 324 } 324 } 325 } else { 326 /* Back compatible: without idmap domains and explicit 327 idmap backend. Taking default idmap backend: tdb */ 328 329 compat = 1; 330 compat_backend = talloc_strdup( idmap_ctx, "tdb"); 331 compat_params = compat_backend; 332 } 333 325 334 326 335 if ( ! dom_list) { … … 415 424 talloc_set_destructor(dom, close_domain_destructor); 416 425 426 if (compat_params) { 427 dom->params = talloc_strdup(dom, compat_params); 428 IDMAP_CHECK_ALLOC(dom->params); 429 } else { 430 dom->params = NULL; 431 } 432 417 433 /* Finally instance a backend copy for this domain */ 418 ret = dom->methods->init(dom , compat_params);434 ret = dom->methods->init(dom); 419 435 if ( ! NT_STATUS_IS_OK(ret)) { 420 DEBUG(0, ("ERROR: Initialization failed for backend %s (domain %s) \n",436 DEBUG(0, ("ERROR: Initialization failed for backend %s (domain %s), deferred!\n", 421 437 parm_backend, dom->name)); 422 ret = NT_STATUS_UNSUCCESSFUL;423 goto done;424 438 } 425 439 idmap_domains = talloc_realloc(idmap_ctx, idmap_domains, struct idmap_domain *, i+1); … … 472 486 talloc_set_destructor(dom, close_domain_destructor); 473 487 488 if (compat_params) { 489 dom->params = talloc_strdup(dom, compat_params); 490 IDMAP_CHECK_ALLOC(dom->params); 491 } else { 492 dom->params = NULL; 493 } 494 474 495 /* Finally instance a backend copy for this domain */ 475 ret = dom->methods->init(dom , compat_params);496 ret = dom->methods->init(dom); 476 497 if ( ! NT_STATUS_IS_OK(ret)) { 477 498 DEBUG(0, ("ERROR: Initialization failed for idmap_nss ?!\n")); … … 516 537 talloc_set_destructor(dom, close_domain_destructor); 517 538 539 if (compat_params) { 540 dom->params = talloc_strdup(dom, compat_params); 541 IDMAP_CHECK_ALLOC(dom->params); 542 } else { 543 dom->params = NULL; 544 } 545 518 546 /* Finally instance a backend copy for this domain */ 519 ret = dom->methods->init(dom , compat_params);547 ret = dom->methods->init(dom); 520 548 if ( ! NT_STATUS_IS_OK(ret)) { 521 549 DEBUG(0, ("ERROR: Initialization failed for idmap_passdb ?!\n")); … … 562 590 563 591 564 /* **************************565 * initialize alloc module 566 */567 DEBUG(1, ("Initializing idmap alloc module\n")); 568 592 /* Initialize alloc module */ 593 594 DEBUG(3, ("Initializing idmap alloc module\n")); 595 596 alloc_backend = NULL; 569 597 if (compat) { 570 598 alloc_backend = talloc_strdup(idmap_ctx, compat_backend); … … 574 602 if (ab && (ab[0] != '\0')) { 575 603 alloc_backend = talloc_strdup(idmap_ctx, lp_idmap_alloc_backend()); 604 } 605 } 606 607 if ( alloc_backend ) { 608 609 idmap_alloc_ctx = talloc_zero(idmap_ctx, struct idmap_alloc_context); 610 IDMAP_CHECK_ALLOC(idmap_alloc_ctx); 611 612 idmap_alloc_ctx->methods = get_alloc_methods(alloc_backends, alloc_backend); 613 if ( ! idmap_alloc_ctx->methods) { 614 ret = smb_probe_module("idmap", alloc_backend); 615 if (NT_STATUS_IS_OK(ret)) { 616 idmap_alloc_ctx->methods = get_alloc_methods(alloc_backends, alloc_backend); 617 } 618 } 619 if (idmap_alloc_ctx->methods) { 620 621 if (compat_params) { 622 idmap_alloc_ctx->params = talloc_strdup(idmap_alloc_ctx, compat_params); 623 IDMAP_CHECK_ALLOC(idmap_alloc_ctx->params); 624 } else { 625 idmap_alloc_ctx->params = NULL; 626 } 627 628 ret = idmap_alloc_ctx->methods->init(idmap_alloc_ctx->params); 629 if ( ! NT_STATUS_IS_OK(ret)) { 630 DEBUG(0, ("ERROR: Initialization failed for alloc " 631 "backend %s, deferred!\n", alloc_backend)); 632 } else { 633 idmap_alloc_ctx->initialized = True; 634 } 576 635 } else { 577 alloc_backend = talloc_strdup(idmap_ctx, "tdb"); 578 } 579 } 580 IDMAP_CHECK_ALLOC(alloc_backend); 581 582 alloc_methods = get_alloc_methods(alloc_backends, alloc_backend); 583 if ( ! alloc_methods) { 584 ret = smb_probe_module("idmap", alloc_backend); 585 if (NT_STATUS_IS_OK(ret)) { 586 alloc_methods = get_alloc_methods(alloc_backends, alloc_backend); 587 } 588 } 589 if ( alloc_methods) { 590 ret = alloc_methods->init(compat_params); 591 if ( ! NT_STATUS_IS_OK(ret)) { 592 DEBUG(0, ("idmap_init: Initialization failed for alloc " 593 "backend %s\n", alloc_backend)); 594 ret = NT_STATUS_UNSUCCESSFUL; 595 goto done; 596 } 597 } else { 598 DEBUG(2, ("idmap_init: Unable to get methods for alloc backend %s\n", 599 alloc_backend)); 600 /* certain compat backends are just readonly */ 601 if ( compat ) 602 ret = NT_STATUS_OK; 603 else 604 ret = NT_STATUS_UNSUCCESSFUL; 605 } 606 636 DEBUG(2, ("idmap_init: Unable to get methods for alloc backend %s\n", 637 alloc_backend)); 638 /* certain compat backends are just readonly */ 639 if ( compat ) { 640 TALLOC_FREE(idmap_alloc_ctx); 641 ret = NT_STATUS_OK; 642 } else { 643 ret = NT_STATUS_UNSUCCESSFUL; 644 } 645 } 646 } 647 607 648 /* cleanpu temporary strings */ 608 649 TALLOC_FREE( compat_backend ); 609 610 backend_init_status = NT_STATUS_OK;650 651 idmap_init_status = NT_STATUS_OK; 611 652 612 653 return ret; … … 616 657 idmap_close(); 617 658 618 /* save the init status for later checks */619 backend_init_status = ret;620 621 659 return ret; 660 } 661 662 static NTSTATUS idmap_alloc_init(void) 663 { 664 NTSTATUS ret; 665 666 if (! NT_STATUS_IS_OK(ret = idmap_init())) { 667 return ret; 668 } 669 670 if ( ! idmap_alloc_ctx) { 671 return NT_STATUS_NOT_SUPPORTED; 672 } 673 674 if ( ! idmap_alloc_ctx->initialized) { 675 ret = idmap_alloc_ctx->methods->init(idmap_alloc_ctx->params); 676 if ( ! NT_STATUS_IS_OK(ret)) { 677 DEBUG(0, ("ERROR: Initialization failed for alloc " 678 "backend, deferred!\n")); 679 return ret; 680 } else { 681 idmap_alloc_ctx->initialized = True; 682 } 683 } 684 685 return NT_STATUS_OK; 622 686 } 623 687 … … 630 694 NTSTATUS ret; 631 695 632 if (! NT_STATUS_IS_OK(ret = idmap_ init())) {696 if (! NT_STATUS_IS_OK(ret = idmap_alloc_init())) { 633 697 return ret; 634 698 } 635 699 636 700 id->type = ID_TYPE_UID; 637 return alloc_methods->allocate_id(id);701 return idmap_alloc_ctx->methods->allocate_id(id); 638 702 } 639 703 … … 642 706 NTSTATUS ret; 643 707 644 if (! NT_STATUS_IS_OK(ret = idmap_ init())) {708 if (! NT_STATUS_IS_OK(ret = idmap_alloc_init())) { 645 709 return ret; 646 710 } 647 711 648 712 id->type = ID_TYPE_GID; 649 return alloc_methods->allocate_id(id);713 return idmap_alloc_ctx->methods->allocate_id(id); 650 714 } 651 715 … … 654 718 NTSTATUS ret; 655 719 656 if (! NT_STATUS_IS_OK(ret = idmap_ init())) {720 if (! NT_STATUS_IS_OK(ret = idmap_alloc_init())) { 657 721 return ret; 658 722 } 659 723 660 724 id->type = ID_TYPE_UID; 661 return alloc_methods->set_id_hwm(id);725 return idmap_alloc_ctx->methods->set_id_hwm(id); 662 726 } 663 727 … … 666 730 NTSTATUS ret; 667 731 668 if (! NT_STATUS_IS_OK(ret = idmap_ init())) {732 if (! NT_STATUS_IS_OK(ret = idmap_alloc_init())) { 669 733 return ret; 670 734 } 671 735 672 736 id->type = ID_TYPE_GID; 673 return alloc_methods->set_id_hwm(id);737 return idmap_alloc_ctx->methods->set_id_hwm(id); 674 738 } 675 739 … … 782 846 NTSTATUS ret; 783 847 struct idmap_domain *dom; 784 const char *domname, *name; 785 enum lsa_SidType sid_type; 786 BOOL wbret; 848 849 /* If we are offline we cannot lookup SIDs, deny mapping */ 850 if (idmap_is_offline()) { 851 return NT_STATUS_FILE_IS_OFFLINE; 852 } 787 853 788 854 ret = idmap_can_map(map, &dom); … … 790 856 return NT_STATUS_NONE_MAPPED; 791 857 } 792 793 /* by default calls to winbindd are disabled794 the following call will not recurse so this is safe */795 winbind_on();796 wbret = winbind_lookup_sid(ctx, map->sid, &domname, &name, &sid_type);797 winbind_off();798 858 799 859 /* check if this is a valid SID and then map it */ 800 if (wbret) { 801 switch (sid_type) { 802 case SID_NAME_USER: 803 ret = idmap_allocate_uid(&map->xid); 804 if ( ! NT_STATUS_IS_OK(ret)) { 805 /* can't allocate id, let's just leave it unmapped */ 806 DEBUG(2, ("uid allocation failed! Can't create mapping\n")); 807 return NT_STATUS_NONE_MAPPED; 808 } 809 break; 810 case SID_NAME_DOM_GRP: 811 case SID_NAME_ALIAS: 812 case SID_NAME_WKN_GRP: 813 ret = idmap_allocate_gid(&map->xid); 814 if ( ! NT_STATUS_IS_OK(ret)) { 815 /* can't allocate id, let's just leave it unmapped */ 816 DEBUG(2, ("gid allocation failed! Can't create mapping\n")); 817 return NT_STATUS_NONE_MAPPED; 818 } 819 break; 820 default: 821 /* invalid sid, let's just leave it unmapped */ 822 DEBUG(10, ("SID %s is UNKNOWN, skip mapping\n", sid_string_static(map->sid))); 860 switch (map->xid.type) { 861 case ID_TYPE_UID: 862 ret = idmap_allocate_uid(&map->xid); 863 if ( ! NT_STATUS_IS_OK(ret)) { 864 /* can't allocate id, let's just leave it unmapped */ 865 DEBUG(2, ("uid allocation failed! Can't create mapping\n")); 823 866 return NT_STATUS_NONE_MAPPED; 824 867 } 825 826 /* ok, got a new id, let's set a mapping */ 827 map->status = ID_MAPPED; 828 829 DEBUG(10, ("Setting mapping: %s <-> %s %lu\n", 830 sid_string_static(map->sid), 831 (map->xid.type == ID_TYPE_UID) ? "UID" : "GID", 832 (unsigned long)map->xid.id)); 833 ret = dom->methods->set_mapping(dom, map); 834 868 break; 869 case ID_TYPE_GID: 870 ret = idmap_allocate_gid(&map->xid); 835 871 if ( ! NT_STATUS_IS_OK(ret)) { 836 /* something wrong here :-( */ 837 DEBUG(2, ("Failed to commit mapping\n!")); 838 839 /* TODO: would it make sense to have an "unalloc_id function?" */ 840 872 /* can't allocate id, let's just leave it unmapped */ 873 DEBUG(2, ("gid allocation failed! Can't create mapping\n")); 841 874 return NT_STATUS_NONE_MAPPED; 842 875 } 843 } else { 844 DEBUG(2,("Invalid SID, not mapping %s (type %d)\n", 845 sid_string_static(map->sid), sid_type)); 876 break; 877 default: 878 /* invalid sid, let's just leave it unmapped */ 879 DEBUG(3,("idmap_new_mapping: Refusing to create a " 880 "mapping for an unspecified ID type.\n")); 881 return NT_STATUS_NONE_MAPPED; 882 } 883 884 /* ok, got a new id, let's set a mapping */ 885 map->status = ID_MAPPED; 886 887 DEBUG(10, ("Setting mapping: %s <-> %s %lu\n", 888 sid_string_static(map->sid), 889 (map->xid.type == ID_TYPE_UID) ? "UID" : "GID", 890 (unsigned long)map->xid.id)); 891 ret = dom->methods->set_mapping(dom, map); 892 893 if ( ! NT_STATUS_IS_OK(ret)) { 894 /* something wrong here :-( */ 895 DEBUG(2, ("Failed to commit mapping\n!")); 896 897 /* TODO: would it make sense to have an "unalloc_id function?" */ 898 846 899 return NT_STATUS_NONE_MAPPED; 847 900 } … … 897 950 _ids = ids; 898 951 899 /* make sure all maps are marked as in UNKNOWN status */900 for (i = 0; _ids[i]; i++) {901 _ids[i]->status = ID_UNKNOWN;902 }903 904 952 unmapped = NULL; 905 953 for (n = num_domains-1; n >= 0; n--) { /* cycle backwards */ … … 910 958 911 959 ret = dom->methods->unixids_to_sids(dom, _ids); 912 IDMAP_ CHECK_RET(ret);960 IDMAP_REPORT_RET(ret); 913 961 914 962 unmapped = NULL; 915 963 916 964 for (i = 0, u = 0; _ids[i]; i++) { 917 if (_ids[i]->status == ID_UNKNOWN || _ids[i]->status == ID_UNMAPPED) {965 if (_ids[i]->status != ID_MAPPED) { 918 966 unmapped = talloc_realloc(ctx, unmapped, struct id_map *, u + 2); 919 967 IDMAP_CHECK_ALLOC(unmapped); … … 935 983 if (unmapped) { 936 984 /* there are still unmapped ids, map them to the unix users/groups domains */ 985 /* except for expired entries, these will be returned as valid (offline mode) */ 937 986 for (i = 0; unmapped[i]; i++) { 987 if (unmapped[i]->status == ID_EXPIRED) continue; 938 988 switch (unmapped[i]->xid.type) { 939 989 case ID_TYPE_UID: … … 985 1035 uint32 idx; 986 1036 987 /* make sure they are unknown to start off */988 ids[i]->status = ID_UNKNOWN;989 990 1037 if ( (dom = find_idmap_domain_from_sid( ids[i]->sid )) == NULL ) { 991 /* no vailable idmap_domain. Move on */1038 /* no available idmap_domain. Move on */ 992 1039 continue; 993 1040 } … … 1017 1064 DEBUG(10, ("Query ids from domain %s\n", dom->name)); 1018 1065 ret = dom->methods->sids_to_unixids(dom, dom_ids[i]); 1019 IDMAP_ CHECK_RET(ret);1066 IDMAP_REPORT_RET(ret); 1020 1067 } 1021 1068 } … … 1025 1072 1026 1073 for (i = 0; ids[i]; i++) { 1074 /* NOTE: this will NOT touch ID_EXPIRED entries that the backend 1075 * was not able to confirm/deny (offline mode) */ 1027 1076 if (ids[i]->status == ID_UNKNOWN || ids[i]->status == ID_UNMAPPED) { 1028 1077 /* ok this is an unmapped one, see if we can map it */ … … 1035 1084 ids[i]->status = ID_UNMAPPED; 1036 1085 } else { 1037 /* Something very bad happened down there */ 1086 /* Something very bad happened down there 1087 * OR we are offline */ 1038 1088 ids[i]->status = ID_UNKNOWN; 1039 1089 } … … 1124 1174 /* let's see if there is any id mapping to be retieved from the backends */ 1125 1175 if (bi) { 1126 /* Only do query if we are online */1127 if ( lp_winbind_offline_logon() &&1128 get_global_winbindd_state_offline() )1129 {1130 ret = NT_STATUS_FILE_IS_OFFLINE;1131 goto done;1132 }1133 1176 1134 1177 ret = idmap_backends_unixids_to_sids(bids); … … 1139 1182 if (bids[i]->status == ID_MAPPED) { 1140 1183 ret = idmap_cache_set(idmap_cache, bids[i]); 1184 } else if (bids[i]->status == ID_EXPIRED) { 1185 /* the cache returned an expired entry and the backend was 1186 * was not able to clear the situation (offline). 1187 * This handles a previous NT_STATUS_SYNCHRONIZATION_REQUIRED 1188 * for disconnected mode, */ 1189 bids[i]->status = ID_MAPPED; 1141 1190 } else if (bids[i]->status == ID_UNKNOWN) { 1142 /* return an expired entry in the cache or an unknown */1143 /* this handles a previous NT_STATUS_SYNCHRONIZATION_REQUIRED1144 * for disconnected mode*/1145 idmap_cache_map_id(idmap_cache, ids[i]);1191 /* something bad here. We were not able to handle this for some 1192 * reason, mark it as unmapped and hope next time things will 1193 * settle down. */ 1194 bids[i]->status = ID_UNMAPPED; 1146 1195 } else { /* unmapped */ 1147 1196 ret = idmap_cache_set_negative_id(idmap_cache, bids[i]); … … 1230 1279 /* let's see if there is any id mapping to be retieved from the backends */ 1231 1280 if (bids) { 1232 /* Only do query if we are online */1233 if ( lp_winbind_offline_logon() &&1234 get_global_winbindd_state_offline() )1235 {1236 ret = NT_STATUS_FILE_IS_OFFLINE;1237 goto done;1238 }1239 1281 1240 1282 ret = idmap_backends_sids_to_unixids(bids); … … 1245 1287 if (bids[i]->status == ID_MAPPED) { 1246 1288 ret = idmap_cache_set(idmap_cache, bids[i]); 1289 } else if (bids[i]->status == ID_EXPIRED) { 1290 /* the cache returned an expired entry and the backend was 1291 * was not able to clear the situation (offline). 1292 * This handles a previous NT_STATUS_SYNCHRONIZATION_REQUIRED 1293 * for disconnected mode, */ 1294 bids[i]->status = ID_MAPPED; 1247 1295 } else if (bids[i]->status == ID_UNKNOWN) { 1248 /* return an expired entry in the cache or an unknown */1249 /* this handles a previous NT_STATUS_SYNCHRONIZATION_REQUIRED1250 * for disconnected mode*/1251 idmap_cache_map_id(idmap_cache, ids[i]);1252 } else { 1296 /* something bad here. We were not able to handle this for some 1297 * reason, mark it as unmapped and hope next time things will 1298 * settle down. */ 1299 bids[i]->status = ID_UNMAPPED; 1300 } else { /* unmapped */ 1253 1301 ret = idmap_cache_set_negative_sid(idmap_cache, bids[i]); 1254 1302 } … … 1322 1370 } 1323 1371 1324 allid.type = ID_TYPE_UID; 1325 allid.id = 0; 1326 alloc_methods->get_id_hwm(&allid); 1327 fprintf(dump, "USER HWM %lu\n", (unsigned long)allid.id); 1328 1329 allid.type = ID_TYPE_GID; 1330 allid.id = 0; 1331 alloc_methods->get_id_hwm(&allid); 1332 fprintf(dump, "GROUP HWM %lu\n", (unsigned long)allid.id); 1333 1372 if (NT_STATUS_IS_OK(ret = idmap_alloc_init())) { 1373 allid.type = ID_TYPE_UID; 1374 allid.id = 0; 1375 idmap_alloc_ctx->methods->get_id_hwm(&allid); 1376 fprintf(dump, "USER HWM %lu\n", (unsigned long)allid.id); 1377 1378 allid.type = ID_TYPE_GID; 1379 allid.id = 0; 1380 idmap_alloc_ctx->methods->get_id_hwm(&allid); 1381 fprintf(dump, "GROUP HWM %lu\n", (unsigned long)allid.id); 1382 } 1383 1334 1384 maps = talloc(idmap_ctx, struct id_map); 1335 1385 num_maps = 0; … … 1353 1403 sid_string_static(maps[i].sid)); 1354 1404 break; 1405 case ID_TYPE_NOT_SPECIFIED: 1406 break; 1355 1407 } 1356 1408 } … … 1382 1434 return ret; 1383 1435 } 1436
Note:
See TracChangeset
for help on using the changeset viewer.