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
00027
00028 #include "includes.h"
00029
00030 #undef DBGC_CLASS
00031 #define DBGC_CLASS DBGC_IDMAP
00032
00033 #define WINBIND_CCACHE_NAME "MEMORY:winbind_ccache"
00034
00035 #define IDMAP_AD_MAX_IDS 30
00036 #define CHECK_ALLOC_DONE(mem) do { \
00037 if (!mem) { \
00038 DEBUG(0, ("Out of memory!\n")); \
00039 ret = NT_STATUS_NO_MEMORY; \
00040 goto done; \
00041 } \
00042 } while (0)
00043
00044 struct idmap_ad_context {
00045 uint32_t filter_low_id;
00046 uint32_t filter_high_id;
00047 };
00048
00049 NTSTATUS init_module(void);
00050
00051 static ADS_STRUCT *ad_idmap_ads = NULL;
00052 static struct posix_schema *ad_schema = NULL;
00053 static enum wb_posix_mapping ad_map_type = WB_POSIX_MAP_UNKNOWN;
00054
00055
00056
00057
00058 static ADS_STRUCT *ad_idmap_cached_connection_internal(void)
00059 {
00060 ADS_STRUCT *ads;
00061 ADS_STATUS status;
00062 BOOL local = False;
00063 fstring dc_name;
00064 struct in_addr dc_ip;
00065
00066 if (ad_idmap_ads != NULL) {
00067
00068 time_t expire;
00069 time_t now = time(NULL);
00070
00071 ads = ad_idmap_ads;
00072
00073 expire = MIN(ads->auth.tgt_expire, ads->auth.tgs_expire);
00074
00075
00076 DEBUG(7, ("Current tickets expire in %d seconds (at %d, time is now %d)\n",
00077 (uint32)expire-(uint32)now, (uint32) expire, (uint32) now));
00078
00079 if ( ads->config.realm && (expire > time(NULL))) {
00080 return ads;
00081 } else {
00082
00083 DEBUG(7,("Deleting expired krb5 credential cache\n"));
00084 ads->is_mine = True;
00085 ads_destroy( &ads );
00086 ads_kdestroy(WINBIND_CCACHE_NAME);
00087 ad_idmap_ads = NULL;
00088 TALLOC_FREE( ad_schema );
00089 }
00090 }
00091
00092 if (!local) {
00093
00094 setenv("KRB5CCNAME", WINBIND_CCACHE_NAME, 1);
00095 }
00096
00097 if ( (ads = ads_init(lp_realm(), lp_workgroup(), NULL)) == NULL ) {
00098 DEBUG(1,("ads_init failed\n"));
00099 return NULL;
00100 }
00101
00102
00103 SAFE_FREE(ads->auth.password);
00104 ads->auth.password = secrets_fetch_machine_password(lp_workgroup(), NULL, NULL);
00105
00106 SAFE_FREE(ads->auth.realm);
00107 ads->auth.realm = SMB_STRDUP(lp_realm());
00108
00109
00110
00111 get_dc_name( NULL, ads->auth.realm, dc_name, &dc_ip );
00112
00113 status = ads_connect(ads);
00114 if (!ADS_ERR_OK(status)) {
00115 DEBUG(1, ("ad_idmap_init: failed to connect to AD\n"));
00116 ads_destroy(&ads);
00117 return NULL;
00118 }
00119
00120 ads->is_mine = False;
00121
00122 ad_idmap_ads = ads;
00123
00124 return ads;
00125 }
00126
00127
00128
00129
00130 static ADS_STRUCT *ad_idmap_cached_connection(void)
00131 {
00132 ADS_STRUCT *ads = ad_idmap_cached_connection_internal();
00133
00134 if ( !ads )
00135 return NULL;
00136
00137
00138
00139
00140 if ( ad_schema )
00141 return ads;
00142
00143
00144
00145 if ( (ad_map_type == WB_POSIX_MAP_SFU) ||
00146 (ad_map_type == WB_POSIX_MAP_RFC2307) )
00147 {
00148 ADS_STATUS schema_status;
00149
00150 schema_status = ads_check_posix_schema_mapping( NULL, ads, ad_map_type, &ad_schema);
00151 if ( !ADS_ERR_OK(schema_status) ) {
00152 DEBUG(2,("ad_idmap_cached_connection: Failed to obtain schema details!\n"));
00153 return NULL;
00154 }
00155 }
00156
00157 return ads;
00158 }
00159
00160
00161
00162
00163 static NTSTATUS idmap_ad_initialize(struct idmap_domain *dom)
00164 {
00165 struct idmap_ad_context *ctx;
00166 char *config_option;
00167 const char *range = NULL;
00168 const char *schema_mode = NULL;
00169
00170 if ( (ctx = TALLOC_ZERO_P(dom, struct idmap_ad_context)) == NULL ) {
00171 DEBUG(0, ("Out of memory!\n"));
00172 return NT_STATUS_NO_MEMORY;
00173 }
00174
00175 if ( (config_option = talloc_asprintf(ctx, "idmap config %s", dom->name)) == NULL ) {
00176 DEBUG(0, ("Out of memory!\n"));
00177 talloc_free(ctx);
00178 return NT_STATUS_NO_MEMORY;
00179 }
00180
00181
00182 range = lp_parm_const_string(-1, config_option, "range", NULL);
00183 if (range && range[0]) {
00184 if ((sscanf(range, "%u - %u", &ctx->filter_low_id, &ctx->filter_high_id) != 2) ||
00185 (ctx->filter_low_id > ctx->filter_high_id)) {
00186 DEBUG(1, ("ERROR: invalid filter range [%s]", range));
00187 ctx->filter_low_id = 0;
00188 ctx->filter_high_id = 0;
00189 }
00190 }
00191
00192
00193 if ( ad_map_type == WB_POSIX_MAP_UNKNOWN )
00194 ad_map_type = WB_POSIX_MAP_RFC2307;
00195 schema_mode = lp_parm_const_string(-1, config_option, "schema_mode", NULL);
00196 if ( schema_mode && schema_mode[0] ) {
00197 if ( strequal(schema_mode, "sfu") )
00198 ad_map_type = WB_POSIX_MAP_SFU;
00199 else if ( strequal(schema_mode, "rfc2307" ) )
00200 ad_map_type = WB_POSIX_MAP_RFC2307;
00201 else
00202 DEBUG(0,("idmap_ad_initialize: Unknown schema_mode (%s)\n",
00203 schema_mode));
00204 }
00205
00206 dom->private_data = ctx;
00207 dom->initialized = True;
00208
00209 talloc_free(config_option);
00210
00211 return NT_STATUS_OK;
00212 }
00213
00214
00215
00216
00217
00218 static struct id_map *find_map_by_id(struct id_map **maps, enum id_type type, uint32_t id)
00219 {
00220 int i;
00221
00222 for (i = 0; maps[i] && i<IDMAP_AD_MAX_IDS; i++) {
00223 if ((maps[i]->xid.type == type) && (maps[i]->xid.id == id)) {
00224 return maps[i];
00225 }
00226 }
00227
00228 return NULL;
00229 }
00230
00231
00232
00233
00234
00235 static struct id_map *find_map_by_sid(struct id_map **maps, DOM_SID *sid)
00236 {
00237 int i;
00238
00239 for (i = 0; maps[i] && i<IDMAP_AD_MAX_IDS; i++) {
00240 if (sid_equal(maps[i]->sid, sid)) {
00241 return maps[i];
00242 }
00243 }
00244
00245 return NULL;
00246 }
00247
00248
00249
00250
00251 static NTSTATUS idmap_ad_unixids_to_sids(struct idmap_domain *dom, struct id_map **ids)
00252 {
00253 NTSTATUS ret;
00254 TALLOC_CTX *memctx;
00255 struct idmap_ad_context *ctx;
00256 ADS_STATUS rc;
00257 ADS_STRUCT *ads;
00258 const char *attrs[] = { "sAMAccountType",
00259 "objectSid",
00260 NULL,
00261 NULL,
00262 NULL };
00263 LDAPMessage *res = NULL;
00264 LDAPMessage *entry = NULL;
00265 char *filter = NULL;
00266 int idx = 0;
00267 int bidx = 0;
00268 int count;
00269 int i;
00270 char *u_filter = NULL;
00271 char *g_filter = NULL;
00272
00273
00274 if (idmap_is_offline()) {
00275 return NT_STATUS_FILE_IS_OFFLINE;
00276 }
00277
00278
00279 if ( ! dom->initialized) {
00280 ret = idmap_ad_initialize(dom);
00281 if ( ! NT_STATUS_IS_OK(ret)) {
00282 return ret;
00283 }
00284 }
00285
00286 ctx = talloc_get_type(dom->private_data, struct idmap_ad_context);
00287
00288 if ( (memctx = talloc_new(ctx)) == NULL ) {
00289 DEBUG(0, ("Out of memory!\n"));
00290 return NT_STATUS_NO_MEMORY;
00291 }
00292
00293 if ( (ads = ad_idmap_cached_connection()) == NULL ) {
00294 DEBUG(1, ("ADS uninitialized\n"));
00295 ret = NT_STATUS_UNSUCCESSFUL;
00296 goto done;
00297 }
00298
00299 attrs[2] = ad_schema->posix_uidnumber_attr;
00300 attrs[3] = ad_schema->posix_gidnumber_attr;
00301
00302 again:
00303 bidx = idx;
00304 for (i = 0; (i < IDMAP_AD_MAX_IDS) && ids[idx]; i++, idx++) {
00305 switch (ids[idx]->xid.type) {
00306 case ID_TYPE_UID:
00307 if ( ! u_filter) {
00308 u_filter = talloc_asprintf(memctx, "(&(|"
00309 "(sAMAccountType=%d)"
00310 "(sAMAccountType=%d)"
00311 "(sAMAccountType=%d))(|",
00312 ATYPE_NORMAL_ACCOUNT,
00313 ATYPE_WORKSTATION_TRUST,
00314 ATYPE_INTERDOMAIN_TRUST);
00315 }
00316 u_filter = talloc_asprintf_append(u_filter, "(%s=%lu)",
00317 ad_schema->posix_uidnumber_attr,
00318 (unsigned long)ids[idx]->xid.id);
00319 CHECK_ALLOC_DONE(u_filter);
00320 break;
00321
00322 case ID_TYPE_GID:
00323 if ( ! g_filter) {
00324 g_filter = talloc_asprintf(memctx, "(&(|"
00325 "(sAMAccountType=%d)"
00326 "(sAMAccountType=%d))(|",
00327 ATYPE_SECURITY_GLOBAL_GROUP,
00328 ATYPE_SECURITY_LOCAL_GROUP);
00329 }
00330 g_filter = talloc_asprintf_append(g_filter, "(%s=%lu)",
00331 ad_schema->posix_gidnumber_attr,
00332 (unsigned long)ids[idx]->xid.id);
00333 CHECK_ALLOC_DONE(g_filter);
00334 break;
00335
00336 default:
00337 DEBUG(3, ("Error: mapping requested but Unknown ID type\n"));
00338 ids[idx]->status = ID_UNKNOWN;
00339 continue;
00340 }
00341 }
00342 filter = talloc_asprintf(memctx, "(|");
00343 CHECK_ALLOC_DONE(filter);
00344 if ( u_filter) {
00345 filter = talloc_asprintf_append(filter, "%s))", u_filter);
00346 CHECK_ALLOC_DONE(filter);
00347 TALLOC_FREE(u_filter);
00348 }
00349 if ( g_filter) {
00350 filter = talloc_asprintf_append(filter, "%s))", g_filter);
00351 CHECK_ALLOC_DONE(filter);
00352 TALLOC_FREE(g_filter);
00353 }
00354 filter = talloc_asprintf_append(filter, ")");
00355 CHECK_ALLOC_DONE(filter);
00356
00357 rc = ads_search_retry(ads, &res, filter, attrs);
00358 if (!ADS_ERR_OK(rc)) {
00359 DEBUG(1, ("ERROR: ads search returned: %s\n", ads_errstr(rc)));
00360 ret = NT_STATUS_UNSUCCESSFUL;
00361 goto done;
00362 }
00363
00364 if ( (count = ads_count_replies(ads, res)) == 0 ) {
00365 DEBUG(10, ("No IDs found\n"));
00366 }
00367
00368 entry = res;
00369 for (i = 0; (i < count) && entry; i++) {
00370 DOM_SID sid;
00371 enum id_type type;
00372 struct id_map *map;
00373 uint32_t id;
00374 uint32_t atype;
00375
00376 if (i == 0) {
00377 entry = ads_first_entry(ads, entry);
00378 } else {
00379 entry = ads_next_entry(ads, entry);
00380 }
00381
00382 if ( !entry ) {
00383 DEBUG(2, ("ERROR: Unable to fetch ldap entries from results\n"));
00384 break;
00385 }
00386
00387
00388 if (!ads_pull_sid(ads, entry, "objectSid", &sid)) {
00389 DEBUG(2, ("Could not retrieve SID from entry\n"));
00390 continue;
00391 }
00392
00393
00394 if (!ads_pull_uint32(ads, entry, "sAMAccountType", &atype)) {
00395 DEBUG(1, ("could not get SAM account type\n"));
00396 continue;
00397 }
00398
00399 switch (atype & 0xF0000000) {
00400 case ATYPE_SECURITY_GLOBAL_GROUP:
00401 case ATYPE_SECURITY_LOCAL_GROUP:
00402 type = ID_TYPE_GID;
00403 break;
00404 case ATYPE_NORMAL_ACCOUNT:
00405 case ATYPE_WORKSTATION_TRUST:
00406 case ATYPE_INTERDOMAIN_TRUST:
00407 type = ID_TYPE_UID;
00408 break;
00409 default:
00410 DEBUG(1, ("unrecognized SAM account type %08x\n", atype));
00411 continue;
00412 }
00413
00414 if (!ads_pull_uint32(ads, entry, (type==ID_TYPE_UID) ?
00415 ad_schema->posix_uidnumber_attr :
00416 ad_schema->posix_gidnumber_attr,
00417 &id))
00418 {
00419 DEBUG(1, ("Could not get unix ID\n"));
00420 continue;
00421 }
00422
00423 if ((id == 0) ||
00424 (ctx->filter_low_id && (id < ctx->filter_low_id)) ||
00425 (ctx->filter_high_id && (id > ctx->filter_high_id))) {
00426 DEBUG(5, ("Requested id (%u) out of range (%u - %u). Filtered!\n",
00427 id, ctx->filter_low_id, ctx->filter_high_id));
00428 continue;
00429 }
00430
00431 map = find_map_by_id(&ids[bidx], type, id);
00432 if (!map) {
00433 DEBUG(2, ("WARNING: couldn't match result with requested ID\n"));
00434 continue;
00435 }
00436
00437 sid_copy(map->sid, &sid);
00438
00439
00440 map->status = ID_MAPPED;
00441
00442 DEBUG(10, ("Mapped %s -> %lu (%d)\n",
00443 sid_string_static(map->sid),
00444 (unsigned long)map->xid.id,
00445 map->xid.type));
00446 }
00447
00448 if (res) {
00449 ads_msgfree(ads, res);
00450 }
00451
00452 if (ids[idx]) {
00453 goto again;
00454 }
00455
00456 ret = NT_STATUS_OK;
00457
00458
00459 for (i = 0; ids[i]; i++) {
00460 if (ids[i]->status != ID_MAPPED)
00461 ids[i]->status = ID_UNMAPPED;
00462 }
00463
00464 done:
00465 talloc_free(memctx);
00466 return ret;
00467 }
00468
00469
00470
00471
00472 static NTSTATUS idmap_ad_sids_to_unixids(struct idmap_domain *dom, struct id_map **ids)
00473 {
00474 NTSTATUS ret;
00475 TALLOC_CTX *memctx;
00476 struct idmap_ad_context *ctx;
00477 ADS_STATUS rc;
00478 ADS_STRUCT *ads;
00479 const char *attrs[] = { "sAMAccountType",
00480 "objectSid",
00481 NULL,
00482 NULL,
00483 NULL };
00484 LDAPMessage *res = NULL;
00485 LDAPMessage *entry = NULL;
00486 char *filter = NULL;
00487 int idx = 0;
00488 int bidx = 0;
00489 int count;
00490 int i;
00491 char *sidstr;
00492
00493
00494 if (idmap_is_offline()) {
00495 return NT_STATUS_FILE_IS_OFFLINE;
00496 }
00497
00498
00499 if ( ! dom->initialized) {
00500 ret = idmap_ad_initialize(dom);
00501 if ( ! NT_STATUS_IS_OK(ret)) {
00502 return ret;
00503 }
00504 }
00505
00506 ctx = talloc_get_type(dom->private_data, struct idmap_ad_context);
00507
00508 if ( (memctx = talloc_new(ctx)) == NULL ) {
00509 DEBUG(0, ("Out of memory!\n"));
00510 return NT_STATUS_NO_MEMORY;
00511 }
00512
00513 if ( (ads = ad_idmap_cached_connection()) == NULL ) {
00514 DEBUG(1, ("ADS uninitialized\n"));
00515 ret = NT_STATUS_UNSUCCESSFUL;
00516 goto done;
00517 }
00518
00519 attrs[2] = ad_schema->posix_uidnumber_attr;
00520 attrs[3] = ad_schema->posix_gidnumber_attr;
00521
00522 again:
00523 filter = talloc_asprintf(memctx, "(&(|"
00524 "(sAMAccountType=%d)(sAMAccountType=%d)(sAMAccountType=%d)"
00525 "(sAMAccountType=%d)(sAMAccountType=%d)"
00526 ")(|",
00527 ATYPE_NORMAL_ACCOUNT, ATYPE_WORKSTATION_TRUST, ATYPE_INTERDOMAIN_TRUST,
00528 ATYPE_SECURITY_GLOBAL_GROUP, ATYPE_SECURITY_LOCAL_GROUP);
00529
00530 CHECK_ALLOC_DONE(filter);
00531
00532 bidx = idx;
00533 for (i = 0; (i < IDMAP_AD_MAX_IDS) && ids[idx]; i++, idx++) {
00534
00535 sidstr = sid_binstring(ids[idx]->sid);
00536 filter = talloc_asprintf_append(filter, "(objectSid=%s)", sidstr);
00537
00538 free(sidstr);
00539 CHECK_ALLOC_DONE(filter);
00540 }
00541 filter = talloc_asprintf_append(filter, "))");
00542 CHECK_ALLOC_DONE(filter);
00543 DEBUG(10, ("Filter: [%s]\n", filter));
00544
00545 rc = ads_search_retry(ads, &res, filter, attrs);
00546 if (!ADS_ERR_OK(rc)) {
00547 DEBUG(1, ("ERROR: ads search returned: %s\n", ads_errstr(rc)));
00548 ret = NT_STATUS_UNSUCCESSFUL;
00549 goto done;
00550 }
00551
00552 if ( (count = ads_count_replies(ads, res)) == 0 ) {
00553 DEBUG(10, ("No IDs found\n"));
00554 }
00555
00556 entry = res;
00557 for (i = 0; (i < count) && entry; i++) {
00558 DOM_SID sid;
00559 enum id_type type;
00560 struct id_map *map;
00561 uint32_t id;
00562 uint32_t atype;
00563
00564 if (i == 0) {
00565 entry = ads_first_entry(ads, entry);
00566 } else {
00567 entry = ads_next_entry(ads, entry);
00568 }
00569
00570 if ( !entry ) {
00571 DEBUG(2, ("ERROR: Unable to fetch ldap entries from results\n"));
00572 break;
00573 }
00574
00575
00576 if (!ads_pull_sid(ads, entry, "objectSid", &sid)) {
00577 DEBUG(2, ("Could not retrieve SID from entry\n"));
00578 continue;
00579 }
00580
00581 map = find_map_by_sid(&ids[bidx], &sid);
00582 if (!map) {
00583 DEBUG(2, ("WARNING: couldn't match result with requested SID\n"));
00584 continue;
00585 }
00586
00587
00588 if (!ads_pull_uint32(ads, entry, "sAMAccountType", &atype)) {
00589 DEBUG(1, ("could not get SAM account type\n"));
00590 continue;
00591 }
00592
00593 switch (atype & 0xF0000000) {
00594 case ATYPE_SECURITY_GLOBAL_GROUP:
00595 case ATYPE_SECURITY_LOCAL_GROUP:
00596 type = ID_TYPE_GID;
00597 break;
00598 case ATYPE_NORMAL_ACCOUNT:
00599 case ATYPE_WORKSTATION_TRUST:
00600 case ATYPE_INTERDOMAIN_TRUST:
00601 type = ID_TYPE_UID;
00602 break;
00603 default:
00604 DEBUG(1, ("unrecognized SAM account type %08x\n", atype));
00605 continue;
00606 }
00607
00608 if (!ads_pull_uint32(ads, entry, (type==ID_TYPE_UID) ?
00609 ad_schema->posix_uidnumber_attr :
00610 ad_schema->posix_gidnumber_attr,
00611 &id))
00612 {
00613 DEBUG(1, ("Could not get unix ID\n"));
00614 continue;
00615 }
00616 if ((id == 0) ||
00617 (ctx->filter_low_id && (id < ctx->filter_low_id)) ||
00618 (ctx->filter_high_id && (id > ctx->filter_high_id))) {
00619 DEBUG(5, ("Requested id (%u) out of range (%u - %u). Filtered!\n",
00620 id, ctx->filter_low_id, ctx->filter_high_id));
00621 continue;
00622 }
00623
00624
00625 map->xid.type = type;
00626 map->xid.id = id;
00627 map->status = ID_MAPPED;
00628
00629 DEBUG(10, ("Mapped %s -> %lu (%d)\n",
00630 sid_string_static(map->sid),
00631 (unsigned long)map->xid.id,
00632 map->xid.type));
00633 }
00634
00635 if (res) {
00636 ads_msgfree(ads, res);
00637 }
00638
00639 if (ids[idx]) {
00640 goto again;
00641 }
00642
00643 ret = NT_STATUS_OK;
00644
00645
00646 for (i = 0; ids[i]; i++) {
00647 if (ids[i]->status != ID_MAPPED)
00648 ids[i]->status = ID_UNMAPPED;
00649 }
00650
00651 done:
00652 talloc_free(memctx);
00653 return ret;
00654 }
00655
00656
00657
00658
00659 static NTSTATUS idmap_ad_close(struct idmap_domain *dom)
00660 {
00661 ADS_STRUCT *ads = ad_idmap_ads;
00662
00663 if (ads != NULL) {
00664
00665 ads->is_mine = True;
00666 ads_destroy( &ads );
00667 ad_idmap_ads = NULL;
00668 }
00669
00670 TALLOC_FREE( ad_schema );
00671
00672 return NT_STATUS_OK;
00673 }
00674
00675
00676
00677
00678
00679
00680
00681
00682
00683 static NTSTATUS nss_sfu_init( struct nss_domain_entry *e )
00684 {
00685
00686
00687
00688 if ( (ad_map_type != WB_POSIX_MAP_UNKNOWN) &&
00689 (ad_map_type != WB_POSIX_MAP_SFU) )
00690 {
00691 DEBUG(0,("nss_sfu_init: Posix Map type has already been set. "
00692 "Mixed schema models not supported!\n"));
00693 return NT_STATUS_NOT_SUPPORTED;
00694 }
00695
00696 ad_map_type = WB_POSIX_MAP_SFU;
00697
00698 return NT_STATUS_OK;
00699 }
00700
00701 static NTSTATUS nss_rfc2307_init( struct nss_domain_entry *e )
00702 {
00703
00704
00705
00706 if ( (ad_map_type != WB_POSIX_MAP_UNKNOWN) &&
00707 (ad_map_type != WB_POSIX_MAP_RFC2307) )
00708 {
00709 DEBUG(0,("nss_rfc2307_init: Posix Map type has already been set. "
00710 "Mixed schema models not supported!\n"));
00711 return NT_STATUS_NOT_SUPPORTED;
00712 }
00713
00714 ad_map_type = WB_POSIX_MAP_RFC2307;
00715
00716 return NT_STATUS_OK;
00717 }
00718
00719
00720
00721
00722 static NTSTATUS nss_ad_get_info( struct nss_domain_entry *e,
00723 const DOM_SID *sid,
00724 TALLOC_CTX *ctx,
00725 ADS_STRUCT *ads,
00726 LDAPMessage *msg,
00727 char **homedir,
00728 char **shell,
00729 char **gecos,
00730 uint32 *gid )
00731 {
00732 ADS_STRUCT *ads_internal = NULL;
00733
00734
00735 if (idmap_is_offline()) {
00736 return NT_STATUS_FILE_IS_OFFLINE;
00737 }
00738
00739
00740
00741
00742 ads_internal = ad_idmap_cached_connection();
00743
00744 if ( !ads_internal || !ad_schema )
00745 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
00746
00747 if ( !homedir || !shell || !gecos )
00748 return NT_STATUS_INVALID_PARAMETER;
00749
00750 *homedir = ads_pull_string( ads, ctx, msg, ad_schema->posix_homedir_attr );
00751 *shell = ads_pull_string( ads, ctx, msg, ad_schema->posix_shell_attr );
00752 *gecos = ads_pull_string( ads, ctx, msg, ad_schema->posix_gecos_attr );
00753
00754 if ( gid ) {
00755 if ( !ads_pull_uint32(ads, msg, ad_schema->posix_gidnumber_attr, gid ) )
00756 *gid = (uint32)-1;
00757 }
00758
00759 return NT_STATUS_OK;
00760 }
00761
00762
00763
00764
00765 static NTSTATUS nss_ad_close( void )
00766 {
00767
00768
00769 return NT_STATUS_OK;
00770 }
00771
00772
00773
00774
00775
00776 static struct idmap_methods ad_methods = {
00777 .init = idmap_ad_initialize,
00778 .unixids_to_sids = idmap_ad_unixids_to_sids,
00779 .sids_to_unixids = idmap_ad_sids_to_unixids,
00780 .close_fn = idmap_ad_close
00781 };
00782
00783
00784
00785
00786 static struct nss_info_methods nss_rfc2307_methods = {
00787 .init = nss_rfc2307_init,
00788 .get_nss_info = nss_ad_get_info,
00789 .close_fn = nss_ad_close
00790 };
00791
00792 static struct nss_info_methods nss_sfu_methods = {
00793 .init = nss_sfu_init,
00794 .get_nss_info = nss_ad_get_info,
00795 .close_fn = nss_ad_close
00796 };
00797
00798
00799
00800
00801
00802
00803 NTSTATUS idmap_ad_init(void)
00804 {
00805 static NTSTATUS status_idmap_ad = NT_STATUS_UNSUCCESSFUL;
00806 static NTSTATUS status_nss_rfc2307 = NT_STATUS_UNSUCCESSFUL;
00807 static NTSTATUS status_nss_sfu = NT_STATUS_UNSUCCESSFUL;
00808
00809
00810
00811
00812 if ( !NT_STATUS_IS_OK(status_idmap_ad) ) {
00813 status_idmap_ad = smb_register_idmap(SMB_IDMAP_INTERFACE_VERSION,
00814 "ad", &ad_methods);
00815 if ( !NT_STATUS_IS_OK(status_idmap_ad) )
00816 return status_idmap_ad;
00817 }
00818
00819 if ( !NT_STATUS_IS_OK( status_nss_rfc2307 ) ) {
00820 status_nss_rfc2307 = smb_register_idmap_nss(SMB_NSS_INFO_INTERFACE_VERSION,
00821 "rfc2307", &nss_rfc2307_methods );
00822 if ( !NT_STATUS_IS_OK(status_nss_rfc2307) )
00823 return status_nss_rfc2307;
00824 }
00825
00826 if ( !NT_STATUS_IS_OK( status_nss_sfu ) ) {
00827 status_nss_sfu = smb_register_idmap_nss(SMB_NSS_INFO_INTERFACE_VERSION,
00828 "sfu", &nss_sfu_methods );
00829 if ( !NT_STATUS_IS_OK(status_nss_sfu) )
00830 return status_nss_sfu;
00831 }
00832
00833 return NT_STATUS_OK;
00834 }
00835