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 #include "includes.h"
00026 #include "winbindd.h"
00027
00028 #ifdef HAVE_ADS
00029
00030 #undef DBGC_CLASS
00031 #define DBGC_CLASS DBGC_WINBIND
00032
00033 extern struct winbindd_methods reconnect_methods;
00034
00035
00036
00037
00038
00039 static ADS_STRUCT *ads_cached_connection(struct winbindd_domain *domain)
00040 {
00041 ADS_STRUCT *ads;
00042 ADS_STATUS status;
00043 fstring dc_name;
00044 struct in_addr dc_ip;
00045
00046 DEBUG(10,("ads_cached_connection\n"));
00047
00048 if (domain->private_data) {
00049
00050 time_t expire;
00051 time_t now = time(NULL);
00052
00053
00054 ads = (ADS_STRUCT *)domain->private_data;
00055
00056 expire = MIN(ads->auth.tgt_expire, ads->auth.tgs_expire);
00057
00058 DEBUG(7, ("Current tickets expire in %d seconds (at %d, time is now %d)\n",
00059 (uint32)expire-(uint32)now, (uint32) expire, (uint32) now));
00060
00061 if ( ads->config.realm && (expire > now)) {
00062 return ads;
00063 } else {
00064
00065 DEBUG(7,("Deleting expired krb5 credential cache\n"));
00066 ads->is_mine = True;
00067 ads_destroy( &ads );
00068 ads_kdestroy("MEMORY:winbind_ccache");
00069 domain->private_data = NULL;
00070 }
00071 }
00072
00073
00074 setenv("KRB5CCNAME", "MEMORY:winbind_ccache", 1);
00075
00076 ads = ads_init(domain->alt_name, domain->name, NULL);
00077 if (!ads) {
00078 DEBUG(1,("ads_init for domain %s failed\n", domain->name));
00079 return NULL;
00080 }
00081
00082
00083
00084 SAFE_FREE(ads->auth.password);
00085 SAFE_FREE(ads->auth.realm);
00086
00087 if ( IS_DC ) {
00088 DOM_SID sid;
00089 time_t last_set_time;
00090
00091 if ( !secrets_fetch_trusted_domain_password( domain->name, &ads->auth.password, &sid, &last_set_time ) ) {
00092 ads_destroy( &ads );
00093 return NULL;
00094 }
00095 ads->auth.realm = SMB_STRDUP( ads->server.realm );
00096 strupper_m( ads->auth.realm );
00097 }
00098 else {
00099 struct winbindd_domain *our_domain = domain;
00100
00101 ads->auth.password = secrets_fetch_machine_password(lp_workgroup(), NULL, NULL);
00102
00103
00104
00105
00106 if ( !domain->primary )
00107 our_domain = find_our_domain();
00108
00109 if ( our_domain->alt_name[0] != '\0' ) {
00110 ads->auth.realm = SMB_STRDUP( our_domain->alt_name );
00111 strupper_m( ads->auth.realm );
00112 }
00113 else
00114 ads->auth.realm = SMB_STRDUP( lp_realm() );
00115 }
00116
00117 ads->auth.renewable = WINBINDD_PAM_AUTH_KRB5_RENEW_TIME;
00118
00119
00120
00121
00122
00123 get_dc_name( ads->server.workgroup, ads->server.realm, dc_name, &dc_ip );
00124
00125 status = ads_connect(ads);
00126 if (!ADS_ERR_OK(status) || !ads->config.realm) {
00127 DEBUG(1,("ads_connect for domain %s failed: %s\n",
00128 domain->name, ads_errstr(status)));
00129 ads_destroy(&ads);
00130
00131
00132
00133 if (status.error_type == ENUM_ADS_ERROR_SYSTEM &&
00134 status.err.rc == ECONNREFUSED) {
00135
00136 DEBUG(1,("Trying MSRPC methods\n"));
00137 domain->backend = &reconnect_methods;
00138 }
00139 return NULL;
00140 }
00141
00142
00143
00144
00145
00146 ads->is_mine = False;
00147
00148 domain->private_data = (void *)ads;
00149 return ads;
00150 }
00151
00152
00153
00154 static NTSTATUS query_user_list(struct winbindd_domain *domain,
00155 TALLOC_CTX *mem_ctx,
00156 uint32 *num_entries,
00157 WINBIND_USERINFO **info)
00158 {
00159 ADS_STRUCT *ads = NULL;
00160 const char *attrs[] = { "*", NULL };
00161 int i, count;
00162 ADS_STATUS rc;
00163 LDAPMessage *res = NULL;
00164 LDAPMessage *msg = NULL;
00165 NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
00166
00167 *num_entries = 0;
00168
00169 DEBUG(3,("ads: query_user_list\n"));
00170
00171 ads = ads_cached_connection(domain);
00172
00173 if (!ads) {
00174 domain->last_status = NT_STATUS_SERVER_DISABLED;
00175 goto done;
00176 }
00177
00178 rc = ads_search_retry(ads, &res, "(objectCategory=user)", attrs);
00179 if (!ADS_ERR_OK(rc) || !res) {
00180 DEBUG(1,("query_user_list ads_search: %s\n", ads_errstr(rc)));
00181 goto done;
00182 }
00183
00184 count = ads_count_replies(ads, res);
00185 if (count == 0) {
00186 DEBUG(1,("query_user_list: No users found\n"));
00187 goto done;
00188 }
00189
00190 (*info) = TALLOC_ZERO_ARRAY(mem_ctx, WINBIND_USERINFO, count);
00191 if (!*info) {
00192 status = NT_STATUS_NO_MEMORY;
00193 goto done;
00194 }
00195
00196 i = 0;
00197
00198 for (msg = ads_first_entry(ads, res); msg; msg = ads_next_entry(ads, msg)) {
00199 char *name, *gecos = NULL;
00200 char *homedir = NULL;
00201 char *shell = NULL;
00202 uint32 group;
00203 uint32 atype;
00204 DOM_SID user_sid;
00205 gid_t primary_gid = (gid_t)-1;
00206
00207 if (!ads_pull_uint32(ads, msg, "sAMAccountType", &atype) ||
00208 ads_atype_map(atype) != SID_NAME_USER) {
00209 DEBUG(1,("Not a user account? atype=0x%x\n", atype));
00210 continue;
00211 }
00212
00213 name = ads_pull_username(ads, mem_ctx, msg);
00214
00215 if ( ads_pull_sid( ads, msg, "objectSid", &user_sid ) ) {
00216 status = nss_get_info( domain->name, &user_sid, mem_ctx,
00217 ads, msg, &homedir, &shell, &gecos,
00218 &primary_gid );
00219 }
00220
00221 if (gecos == NULL) {
00222 gecos = ads_pull_string(ads, mem_ctx, msg, "name");
00223 }
00224
00225 if (!ads_pull_sid(ads, msg, "objectSid",
00226 &(*info)[i].user_sid)) {
00227 DEBUG(1,("No sid for %s !?\n", name));
00228 continue;
00229 }
00230 if (!ads_pull_uint32(ads, msg, "primaryGroupID", &group)) {
00231 DEBUG(1,("No primary group for %s !?\n", name));
00232 continue;
00233 }
00234
00235 (*info)[i].acct_name = name;
00236 (*info)[i].full_name = gecos;
00237 (*info)[i].homedir = homedir;
00238 (*info)[i].shell = shell;
00239 (*info)[i].primary_gid = primary_gid;
00240 sid_compose(&(*info)[i].group_sid, &domain->sid, group);
00241 i++;
00242 }
00243
00244 (*num_entries) = i;
00245 status = NT_STATUS_OK;
00246
00247 DEBUG(3,("ads query_user_list gave %d entries\n", (*num_entries)));
00248
00249 done:
00250 if (res)
00251 ads_msgfree(ads, res);
00252
00253 return status;
00254 }
00255
00256
00257 static NTSTATUS enum_dom_groups(struct winbindd_domain *domain,
00258 TALLOC_CTX *mem_ctx,
00259 uint32 *num_entries,
00260 struct acct_info **info)
00261 {
00262 ADS_STRUCT *ads = NULL;
00263 const char *attrs[] = {"userPrincipalName", "sAMAccountName",
00264 "name", "objectSid", NULL};
00265 int i, count;
00266 ADS_STATUS rc;
00267 LDAPMessage *res = NULL;
00268 LDAPMessage *msg = NULL;
00269 NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
00270 const char *filter;
00271 BOOL enum_dom_local_groups = False;
00272
00273 *num_entries = 0;
00274
00275 DEBUG(3,("ads: enum_dom_groups\n"));
00276
00277
00278 if ( domain->native_mode && strequal(lp_realm(), domain->alt_name) ) {
00279 enum_dom_local_groups = True;
00280 }
00281
00282
00283
00284
00285
00286
00287
00288
00289
00290
00291
00292
00293
00294
00295
00296
00297
00298
00299 filter = talloc_asprintf(mem_ctx, "(&(objectCategory=group)(&(groupType:dn:%s:=%d)(!(groupType:dn:%s:=%d))))",
00300 ADS_LDAP_MATCHING_RULE_BIT_AND, GROUP_TYPE_SECURITY_ENABLED,
00301 ADS_LDAP_MATCHING_RULE_BIT_AND,
00302 enum_dom_local_groups ? GROUP_TYPE_BUILTIN_LOCAL_GROUP : GROUP_TYPE_RESOURCE_GROUP);
00303
00304 if (filter == NULL) {
00305 status = NT_STATUS_NO_MEMORY;
00306 goto done;
00307 }
00308
00309 ads = ads_cached_connection(domain);
00310
00311 if (!ads) {
00312 domain->last_status = NT_STATUS_SERVER_DISABLED;
00313 goto done;
00314 }
00315
00316 rc = ads_search_retry(ads, &res, filter, attrs);
00317 if (!ADS_ERR_OK(rc) || !res) {
00318 DEBUG(1,("enum_dom_groups ads_search: %s\n", ads_errstr(rc)));
00319 goto done;
00320 }
00321
00322 count = ads_count_replies(ads, res);
00323 if (count == 0) {
00324 DEBUG(1,("enum_dom_groups: No groups found\n"));
00325 goto done;
00326 }
00327
00328 (*info) = TALLOC_ZERO_ARRAY(mem_ctx, struct acct_info, count);
00329 if (!*info) {
00330 status = NT_STATUS_NO_MEMORY;
00331 goto done;
00332 }
00333
00334 i = 0;
00335
00336 for (msg = ads_first_entry(ads, res); msg; msg = ads_next_entry(ads, msg)) {
00337 char *name, *gecos;
00338 DOM_SID sid;
00339 uint32 rid;
00340
00341 name = ads_pull_username(ads, mem_ctx, msg);
00342 gecos = ads_pull_string(ads, mem_ctx, msg, "name");
00343 if (!ads_pull_sid(ads, msg, "objectSid", &sid)) {
00344 DEBUG(1,("No sid for %s !?\n", name));
00345 continue;
00346 }
00347
00348 if (!sid_peek_check_rid(&domain->sid, &sid, &rid)) {
00349 DEBUG(1,("No rid for %s !?\n", name));
00350 continue;
00351 }
00352
00353 fstrcpy((*info)[i].acct_name, name);
00354 fstrcpy((*info)[i].acct_desc, gecos);
00355 (*info)[i].rid = rid;
00356 i++;
00357 }
00358
00359 (*num_entries) = i;
00360
00361 status = NT_STATUS_OK;
00362
00363 DEBUG(3,("ads enum_dom_groups gave %d entries\n", (*num_entries)));
00364
00365 done:
00366 if (res)
00367 ads_msgfree(ads, res);
00368
00369 return status;
00370 }
00371
00372
00373 static NTSTATUS enum_local_groups(struct winbindd_domain *domain,
00374 TALLOC_CTX *mem_ctx,
00375 uint32 *num_entries,
00376 struct acct_info **info)
00377 {
00378
00379
00380
00381
00382
00383
00384
00385
00386
00387
00388 *num_entries = 0;
00389
00390 return NT_STATUS_OK;
00391 }
00392
00393
00394
00395
00396
00397 static BOOL dn_lookup(ADS_STRUCT *ads, TALLOC_CTX *mem_ctx,
00398 const char *dn,
00399 char **name, uint32 *name_type, DOM_SID *sid)
00400 {
00401 LDAPMessage *res = NULL;
00402 const char *attrs[] = {"userPrincipalName", "sAMAccountName",
00403 "objectSid", "sAMAccountType", NULL};
00404 ADS_STATUS rc;
00405 uint32 atype;
00406 DEBUG(3,("ads: dn_lookup\n"));
00407
00408 rc = ads_search_retry_dn(ads, &res, dn, attrs);
00409
00410 if (!ADS_ERR_OK(rc) || !res) {
00411 goto failed;
00412 }
00413
00414 (*name) = ads_pull_username(ads, mem_ctx, res);
00415
00416 if (!ads_pull_uint32(ads, res, "sAMAccountType", &atype)) {
00417 goto failed;
00418 }
00419 (*name_type) = ads_atype_map(atype);
00420
00421 if (!ads_pull_sid(ads, res, "objectSid", sid)) {
00422 goto failed;
00423 }
00424
00425 if (res)
00426 ads_msgfree(ads, res);
00427
00428 return True;
00429
00430 failed:
00431 if (res)
00432 ads_msgfree(ads, res);
00433
00434 return False;
00435 }
00436
00437
00438 static NTSTATUS query_user(struct winbindd_domain *domain,
00439 TALLOC_CTX *mem_ctx,
00440 const DOM_SID *sid,
00441 WINBIND_USERINFO *info)
00442 {
00443 ADS_STRUCT *ads = NULL;
00444 const char *attrs[] = { "*", NULL };
00445 ADS_STATUS rc;
00446 int count;
00447 LDAPMessage *msg = NULL;
00448 char *ldap_exp;
00449 char *sidstr;
00450 uint32 group_rid;
00451 NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
00452
00453 DEBUG(3,("ads: query_user\n"));
00454
00455 if ( (ads = ads_cached_connection(domain)) == NULL ) {
00456 domain->last_status = NT_STATUS_SERVER_DISABLED;
00457 goto done;
00458 }
00459
00460 sidstr = sid_binstring(sid);
00461 asprintf(&ldap_exp, "(objectSid=%s)", sidstr);
00462 rc = ads_search_retry(ads, &msg, ldap_exp, attrs);
00463 free(ldap_exp);
00464 free(sidstr);
00465 if (!ADS_ERR_OK(rc) || !msg) {
00466 DEBUG(1,("query_user(sid=%s) ads_search: %s\n",
00467 sid_string_static(sid), ads_errstr(rc)));
00468 goto done;
00469 }
00470
00471 count = ads_count_replies(ads, msg);
00472 if (count != 1) {
00473 DEBUG(1,("query_user(sid=%s): Not found\n",
00474 sid_string_static(sid)));
00475 goto done;
00476 }
00477
00478 info->acct_name = ads_pull_username(ads, mem_ctx, msg);
00479
00480 info->primary_gid = (gid_t)-1;
00481 nss_get_info( domain->name, sid, mem_ctx, ads, msg,
00482 &info->homedir, &info->shell, &info->full_name, &info->primary_gid );
00483
00484 if (info->full_name == NULL) {
00485 info->full_name = ads_pull_string(ads, mem_ctx, msg, "name");
00486 }
00487
00488 if (!ads_pull_uint32(ads, msg, "primaryGroupID", &group_rid)) {
00489 DEBUG(1,("No primary group for %s !?\n",
00490 sid_string_static(sid)));
00491 goto done;
00492 }
00493
00494 sid_copy(&info->user_sid, sid);
00495 sid_compose(&info->group_sid, &domain->sid, group_rid);
00496
00497 status = NT_STATUS_OK;
00498
00499 DEBUG(3,("ads query_user gave %s\n", info->acct_name));
00500 done:
00501 if (msg)
00502 ads_msgfree(ads, msg);
00503
00504 return status;
00505 }
00506
00507
00508
00509 static NTSTATUS lookup_usergroups_member(struct winbindd_domain *domain,
00510 TALLOC_CTX *mem_ctx,
00511 const char *user_dn,
00512 DOM_SID *primary_group,
00513 size_t *p_num_groups, DOM_SID **user_sids)
00514 {
00515 ADS_STATUS rc;
00516 NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
00517 int count;
00518 LDAPMessage *res = NULL;
00519 LDAPMessage *msg = NULL;
00520 char *ldap_exp;
00521 ADS_STRUCT *ads;
00522 const char *group_attrs[] = {"objectSid", NULL};
00523 char *escaped_dn;
00524 size_t num_groups = 0;
00525
00526 DEBUG(3,("ads: lookup_usergroups_member\n"));
00527
00528 ads = ads_cached_connection(domain);
00529
00530 if (!ads) {
00531 domain->last_status = NT_STATUS_SERVER_DISABLED;
00532 goto done;
00533 }
00534
00535 if (!(escaped_dn = escape_ldap_string_alloc(user_dn))) {
00536 status = NT_STATUS_NO_MEMORY;
00537 goto done;
00538 }
00539
00540 if (!(ldap_exp = talloc_asprintf(mem_ctx, "(&(member=%s)(objectCategory=group))", escaped_dn))) {
00541 DEBUG(1,("lookup_usergroups(dn=%s) asprintf failed!\n", user_dn));
00542 SAFE_FREE(escaped_dn);
00543 status = NT_STATUS_NO_MEMORY;
00544 goto done;
00545 }
00546
00547 SAFE_FREE(escaped_dn);
00548
00549 rc = ads_search_retry(ads, &res, ldap_exp, group_attrs);
00550
00551 if (!ADS_ERR_OK(rc) || !res) {
00552 DEBUG(1,("lookup_usergroups ads_search member=%s: %s\n", user_dn, ads_errstr(rc)));
00553 return ads_ntstatus(rc);
00554 }
00555
00556 count = ads_count_replies(ads, res);
00557
00558 *user_sids = NULL;
00559 num_groups = 0;
00560
00561
00562 if (!add_sid_to_array(mem_ctx, primary_group, user_sids, &num_groups)) {
00563 status = NT_STATUS_NO_MEMORY;
00564 goto done;
00565 }
00566
00567 if (count > 0) {
00568 for (msg = ads_first_entry(ads, res); msg;
00569 msg = ads_next_entry(ads, msg)) {
00570 DOM_SID group_sid;
00571
00572 if (!ads_pull_sid(ads, msg, "objectSid", &group_sid)) {
00573 DEBUG(1,("No sid for this group ?!?\n"));
00574 continue;
00575 }
00576
00577
00578 if (sid_check_is_in_builtin(&group_sid)) {
00579 continue;
00580 }
00581
00582 if (!add_sid_to_array(mem_ctx, &group_sid, user_sids,
00583 &num_groups)) {
00584 status = NT_STATUS_NO_MEMORY;
00585 goto done;
00586 }
00587 }
00588
00589 }
00590
00591 *p_num_groups = num_groups;
00592 status = (user_sids != NULL) ? NT_STATUS_OK : NT_STATUS_NO_MEMORY;
00593
00594 DEBUG(3,("ads lookup_usergroups (member) succeeded for dn=%s\n", user_dn));
00595 done:
00596 if (res)
00597 ads_msgfree(ads, res);
00598
00599 return status;
00600 }
00601
00602
00603
00604 static NTSTATUS lookup_usergroups_memberof(struct winbindd_domain *domain,
00605 TALLOC_CTX *mem_ctx,
00606 const char *user_dn,
00607 DOM_SID *primary_group,
00608 size_t *p_num_groups, DOM_SID **user_sids)
00609 {
00610 ADS_STATUS rc;
00611 NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
00612 int count;
00613 LDAPMessage *res = NULL;
00614 ADS_STRUCT *ads;
00615 const char *attrs[] = {"memberOf", NULL};
00616 size_t num_groups = 0;
00617 DOM_SID *group_sids = NULL;
00618 int i;
00619
00620 DEBUG(3,("ads: lookup_usergroups_memberof\n"));
00621
00622 ads = ads_cached_connection(domain);
00623
00624 if (!ads) {
00625 domain->last_status = NT_STATUS_SERVER_DISABLED;
00626 goto done;
00627 }
00628
00629 rc = ads_search_retry_extended_dn(ads, &res, user_dn, attrs,
00630 ADS_EXTENDED_DN_HEX_STRING);
00631
00632 if (!ADS_ERR_OK(rc) || !res) {
00633 DEBUG(1,("lookup_usergroups_memberof ads_search member=%s: %s\n",
00634 user_dn, ads_errstr(rc)));
00635 return ads_ntstatus(rc);
00636 }
00637
00638 count = ads_count_replies(ads, res);
00639
00640 if (count == 0) {
00641 status = NT_STATUS_NO_SUCH_USER;
00642 goto done;
00643 }
00644
00645 *user_sids = NULL;
00646 num_groups = 0;
00647
00648
00649 if (!add_sid_to_array(mem_ctx, primary_group, user_sids, &num_groups)) {
00650 status = NT_STATUS_NO_MEMORY;
00651 goto done;
00652 }
00653
00654 count = ads_pull_sids_from_extendeddn(ads, mem_ctx, res, "memberOf",
00655 ADS_EXTENDED_DN_HEX_STRING,
00656 &group_sids);
00657 if (count == 0) {
00658 DEBUG(1,("No memberOf for this user?!?\n"));
00659 status = NT_STATUS_NO_MEMORY;
00660 goto done;
00661 }
00662
00663 for (i=0; i<count; i++) {
00664
00665
00666 if (sid_check_is_in_builtin(&group_sids[i])) {
00667 continue;
00668 }
00669
00670 if (!add_sid_to_array(mem_ctx, &group_sids[i], user_sids,
00671 &num_groups)) {
00672 status = NT_STATUS_NO_MEMORY;
00673 goto done;
00674 }
00675
00676 }
00677
00678 *p_num_groups = num_groups;
00679 status = (*user_sids != NULL) ? NT_STATUS_OK : NT_STATUS_NO_MEMORY;
00680
00681 DEBUG(3,("ads lookup_usergroups (memberof) succeeded for dn=%s\n", user_dn));
00682 done:
00683 TALLOC_FREE(group_sids);
00684 if (res)
00685 ads_msgfree(ads, res);
00686
00687 return status;
00688 }
00689
00690
00691
00692 static NTSTATUS lookup_usergroups(struct winbindd_domain *domain,
00693 TALLOC_CTX *mem_ctx,
00694 const DOM_SID *sid,
00695 uint32 *p_num_groups, DOM_SID **user_sids)
00696 {
00697 ADS_STRUCT *ads = NULL;
00698 const char *attrs[] = {"tokenGroups", "primaryGroupID", NULL};
00699 ADS_STATUS rc;
00700 int count;
00701 LDAPMessage *msg = NULL;
00702 char *user_dn = NULL;
00703 DOM_SID *sids;
00704 int i;
00705 DOM_SID primary_group;
00706 uint32 primary_group_rid;
00707 fstring sid_string;
00708 NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
00709 size_t num_groups = 0;
00710
00711 DEBUG(3,("ads: lookup_usergroups\n"));
00712 *p_num_groups = 0;
00713
00714 status = lookup_usergroups_cached(domain, mem_ctx, sid,
00715 p_num_groups, user_sids);
00716 if (NT_STATUS_IS_OK(status)) {
00717 return NT_STATUS_OK;
00718 }
00719
00720 ads = ads_cached_connection(domain);
00721
00722 if (!ads) {
00723 domain->last_status = NT_STATUS_SERVER_DISABLED;
00724 status = NT_STATUS_SERVER_DISABLED;
00725 goto done;
00726 }
00727
00728 rc = ads_search_retry_sid(ads, &msg, sid, attrs);
00729
00730 if (!ADS_ERR_OK(rc)) {
00731 status = ads_ntstatus(rc);
00732 DEBUG(1,("lookup_usergroups(sid=%s) ads_search tokenGroups: %s\n",
00733 sid_to_string(sid_string, sid), ads_errstr(rc)));
00734 goto done;
00735 }
00736
00737 count = ads_count_replies(ads, msg);
00738 if (count != 1) {
00739 status = NT_STATUS_UNSUCCESSFUL;
00740 DEBUG(1,("lookup_usergroups(sid=%s) ads_search tokenGroups: "
00741 "invalid number of results (count=%d)\n",
00742 sid_to_string(sid_string, sid), count));
00743 goto done;
00744 }
00745
00746 if (!msg) {
00747 DEBUG(1,("lookup_usergroups(sid=%s) ads_search tokenGroups: NULL msg\n",
00748 sid_to_string(sid_string, sid)));
00749 status = NT_STATUS_UNSUCCESSFUL;
00750 goto done;
00751 }
00752
00753 user_dn = ads_get_dn(ads, msg);
00754 if (user_dn == NULL) {
00755 status = NT_STATUS_NO_MEMORY;
00756 goto done;
00757 }
00758
00759 if (!ads_pull_uint32(ads, msg, "primaryGroupID", &primary_group_rid)) {
00760 DEBUG(1,("%s: No primary group for sid=%s !?\n",
00761 domain->name, sid_to_string(sid_string, sid)));
00762 goto done;
00763 }
00764
00765 sid_copy(&primary_group, &domain->sid);
00766 sid_append_rid(&primary_group, primary_group_rid);
00767
00768 count = ads_pull_sids(ads, mem_ctx, msg, "tokenGroups", &sids);
00769
00770
00771
00772
00773
00774
00775
00776 if (count == 0) {
00777
00778
00779
00780
00781
00782
00783 status = lookup_usergroups_memberof(domain, mem_ctx, user_dn,
00784 &primary_group,
00785 &num_groups, user_sids);
00786 *p_num_groups = (uint32)num_groups;
00787 if (NT_STATUS_IS_OK(status)) {
00788 goto done;
00789 }
00790
00791
00792
00793
00794 status = lookup_usergroups_member(domain, mem_ctx, user_dn,
00795 &primary_group,
00796 &num_groups, user_sids);
00797 *p_num_groups = (uint32)num_groups;
00798 goto done;
00799 }
00800
00801 *user_sids = NULL;
00802 num_groups = 0;
00803
00804 if (!add_sid_to_array(mem_ctx, &primary_group, user_sids, &num_groups)) {
00805 status = NT_STATUS_NO_MEMORY;
00806 goto done;
00807 }
00808
00809 for (i=0;i<count;i++) {
00810
00811
00812 if (sid_check_is_in_builtin(&sids[i])) {
00813 continue;
00814 }
00815
00816 if (!add_sid_to_array_unique(mem_ctx, &sids[i],
00817 user_sids, &num_groups)) {
00818 status = NT_STATUS_NO_MEMORY;
00819 goto done;
00820 }
00821 }
00822
00823 *p_num_groups = (uint32)num_groups;
00824 status = (*user_sids != NULL) ? NT_STATUS_OK : NT_STATUS_NO_MEMORY;
00825
00826 DEBUG(3,("ads lookup_usergroups (tokenGroups) succeeded for sid=%s\n",
00827 sid_to_string(sid_string, sid)));
00828 done:
00829 ads_memfree(ads, user_dn);
00830 ads_msgfree(ads, msg);
00831 return status;
00832 }
00833
00834
00835
00836
00837 static NTSTATUS lookup_groupmem(struct winbindd_domain *domain,
00838 TALLOC_CTX *mem_ctx,
00839 const DOM_SID *group_sid, uint32 *num_names,
00840 DOM_SID **sid_mem, char ***names,
00841 uint32 **name_types)
00842 {
00843 ADS_STATUS rc;
00844 int count;
00845 LDAPMessage *res=NULL;
00846 ADS_STRUCT *ads = NULL;
00847 char *ldap_exp;
00848 NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
00849 char *sidstr;
00850 char **members;
00851 int i;
00852 size_t num_members;
00853 fstring sid_string;
00854 BOOL more_values;
00855 const char **attrs;
00856 uint32 first_usn;
00857 uint32 current_usn;
00858 int num_retries = 0;
00859
00860 DEBUG(10,("ads: lookup_groupmem %s sid=%s\n", domain->name,
00861 sid_string_static(group_sid)));
00862
00863 *num_names = 0;
00864
00865 ads = ads_cached_connection(domain);
00866
00867 if (!ads) {
00868 domain->last_status = NT_STATUS_SERVER_DISABLED;
00869 goto done;
00870 }
00871
00872 if ((sidstr = sid_binstring(group_sid)) == NULL) {
00873 status = NT_STATUS_NO_MEMORY;
00874 goto done;
00875 }
00876
00877
00878 if (!(ldap_exp = talloc_asprintf(mem_ctx, "(objectSid=%s)",sidstr))) {
00879 SAFE_FREE(sidstr);
00880 DEBUG(1, ("ads: lookup_groupmem: tallloc_asprintf for ldap_exp failed!\n"));
00881 status = NT_STATUS_NO_MEMORY;
00882 goto done;
00883 }
00884 SAFE_FREE(sidstr);
00885
00886 members = NULL;
00887 num_members = 0;
00888
00889 if ((attrs = TALLOC_ARRAY(mem_ctx, const char *, 3)) == NULL) {
00890 status = NT_STATUS_NO_MEMORY;
00891 goto done;
00892 }
00893
00894 attrs[1] = talloc_strdup(mem_ctx, "usnChanged");
00895 attrs[2] = NULL;
00896
00897 do {
00898 if (num_members == 0)
00899 attrs[0] = talloc_strdup(mem_ctx, "member");
00900
00901 DEBUG(10, ("Searching for attrs[0] = %s, attrs[1] = %s\n", attrs[0], attrs[1]));
00902
00903 rc = ads_search_retry(ads, &res, ldap_exp, attrs);
00904
00905 if (!ADS_ERR_OK(rc) || !res) {
00906 DEBUG(1,("ads: lookup_groupmem ads_search: %s\n",
00907 ads_errstr(rc)));
00908 status = ads_ntstatus(rc);
00909 goto done;
00910 }
00911
00912 count = ads_count_replies(ads, res);
00913 if (count == 0)
00914 break;
00915
00916 if (num_members == 0) {
00917 if (!ads_pull_uint32(ads, res, "usnChanged", &first_usn)) {
00918 DEBUG(1, ("ads: lookup_groupmem could not pull usnChanged!\n"));
00919 goto done;
00920 }
00921 }
00922
00923 if (!ads_pull_uint32(ads, res, "usnChanged", ¤t_usn)) {
00924 DEBUG(1, ("ads: lookup_groupmem could not pull usnChanged!\n"));
00925 goto done;
00926 }
00927
00928 if (first_usn != current_usn) {
00929 DEBUG(5, ("ads: lookup_groupmem USN on this record changed"
00930 " - restarting search\n"));
00931 if (num_retries < 5) {
00932 num_retries++;
00933 num_members = 0;
00934 ads_msgfree(ads, res);
00935 res = NULL;
00936 continue;
00937 } else {
00938 DEBUG(5, ("ads: lookup_groupmem USN on this record changed"
00939 " - restarted search too many times, aborting!\n"));
00940 status = NT_STATUS_UNSUCCESSFUL;
00941 goto done;
00942 }
00943 }
00944
00945 members = ads_pull_strings_range(ads, mem_ctx, res,
00946 "member",
00947 members,
00948 &attrs[0],
00949 &num_members,
00950 &more_values);
00951
00952 ads_msgfree(ads, res);
00953 res = NULL;
00954
00955 if ((members == NULL) || (num_members == 0))
00956 break;
00957
00958 } while (more_values);
00959
00960
00961
00962
00963
00964 if (num_members) {
00965 (*sid_mem) = TALLOC_ZERO_ARRAY(mem_ctx, DOM_SID, num_members);
00966 (*name_types) = TALLOC_ZERO_ARRAY(mem_ctx, uint32, num_members);
00967 (*names) = TALLOC_ZERO_ARRAY(mem_ctx, char *, num_members);
00968
00969 if ((members == NULL) || (*sid_mem == NULL) ||
00970 (*name_types == NULL) || (*names == NULL)) {
00971 DEBUG(1, ("talloc failed\n"));
00972 status = NT_STATUS_NO_MEMORY;
00973 goto done;
00974 }
00975 } else {
00976 (*sid_mem) = NULL;
00977 (*name_types) = NULL;
00978 (*names) = NULL;
00979 }
00980
00981 for (i=0;i<num_members;i++) {
00982 uint32 name_type;
00983 char *name;
00984 DOM_SID sid;
00985
00986 if (dn_lookup(ads, mem_ctx, members[i], &name, &name_type, &sid)) {
00987 (*names)[*num_names] = name;
00988 (*name_types)[*num_names] = name_type;
00989 sid_copy(&(*sid_mem)[*num_names], &sid);
00990 (*num_names)++;
00991 }
00992 }
00993
00994 status = NT_STATUS_OK;
00995 DEBUG(3,("ads lookup_groupmem for sid=%s\n", sid_to_string(sid_string, group_sid)));
00996 done:
00997
00998 if (res)
00999 ads_msgfree(ads, res);
01000
01001 return status;
01002 }
01003
01004
01005 static NTSTATUS sequence_number(struct winbindd_domain *domain, uint32 *seq)
01006 {
01007 ADS_STRUCT *ads = NULL;
01008 ADS_STATUS rc;
01009
01010 DEBUG(3,("ads: fetch sequence_number for %s\n", domain->name));
01011
01012 *seq = DOM_SEQUENCE_NONE;
01013
01014 ads = ads_cached_connection(domain);
01015
01016 if (!ads) {
01017 domain->last_status = NT_STATUS_SERVER_DISABLED;
01018 return NT_STATUS_UNSUCCESSFUL;
01019 }
01020
01021 rc = ads_USN(ads, seq);
01022
01023 if (!ADS_ERR_OK(rc)) {
01024
01025
01026
01027 if (domain->private_data) {
01028 ads = (ADS_STRUCT *)domain->private_data;
01029 ads->is_mine = True;
01030 ads_destroy(&ads);
01031 ads_kdestroy("MEMORY:winbind_ccache");
01032 domain->private_data = NULL;
01033 }
01034 }
01035 return ads_ntstatus(rc);
01036 }
01037
01038
01039 static NTSTATUS trusted_domains(struct winbindd_domain *domain,
01040 TALLOC_CTX *mem_ctx,
01041 uint32 *num_domains,
01042 char ***names,
01043 char ***alt_names,
01044 DOM_SID **dom_sids)
01045 {
01046 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
01047 struct ds_domain_trust *domains = NULL;
01048 int count = 0;
01049 int i;
01050 uint32 flags = DS_DOMAIN_IN_FOREST | DS_DOMAIN_DIRECT_OUTBOUND;
01051 struct rpc_pipe_client *cli;
01052
01053 DEBUG(3,("ads: trusted_domains\n"));
01054
01055 *num_domains = 0;
01056 *alt_names = NULL;
01057 *names = NULL;
01058 *dom_sids = NULL;
01059
01060 result = cm_connect_netlogon(domain, &cli);
01061
01062 if (!NT_STATUS_IS_OK(result)) {
01063 DEBUG(5, ("trusted_domains: Could not open a connection to %s "
01064 "for PIPE_NETLOGON (%s)\n",
01065 domain->name, nt_errstr(result)));
01066 return NT_STATUS_UNSUCCESSFUL;
01067 }
01068
01069 if ( NT_STATUS_IS_OK(result) ) {
01070 result = rpccli_ds_enum_domain_trusts(cli, mem_ctx,
01071 cli->cli->desthost,
01072 flags, &domains,
01073 (unsigned int *)&count);
01074 }
01075
01076 if ( NT_STATUS_IS_OK(result) && count) {
01077
01078
01079
01080 if ( !(*names = TALLOC_ARRAY(mem_ctx, char *, count)) ) {
01081 DEBUG(0, ("trusted_domains: out of memory\n"));
01082 return NT_STATUS_NO_MEMORY;
01083 }
01084
01085 if ( !(*alt_names = TALLOC_ARRAY(mem_ctx, char *, count)) ) {
01086 DEBUG(0, ("trusted_domains: out of memory\n"));
01087 return NT_STATUS_NO_MEMORY;
01088 }
01089
01090 if ( !(*dom_sids = TALLOC_ARRAY(mem_ctx, DOM_SID, count)) ) {
01091 DEBUG(0, ("trusted_domains: out of memory\n"));
01092 return NT_STATUS_NO_MEMORY;
01093 }
01094
01095
01096
01097 for (i = 0; i < count; i++) {
01098 (*names)[i] = domains[i].netbios_domain;
01099 (*alt_names)[i] = domains[i].dns_domain;
01100
01101 sid_copy(&(*dom_sids)[i], &domains[i].sid);
01102 }
01103
01104 *num_domains = count;
01105 }
01106
01107 return result;
01108 }
01109
01110
01111 struct winbindd_methods ads_methods = {
01112 True,
01113 query_user_list,
01114 enum_dom_groups,
01115 enum_local_groups,
01116 msrpc_name_to_sid,
01117 msrpc_sid_to_name,
01118 msrpc_rids_to_names,
01119 query_user,
01120 lookup_usergroups,
01121 msrpc_lookup_useraliases,
01122 lookup_groupmem,
01123 sequence_number,
01124 msrpc_lockout_policy,
01125 msrpc_password_policy,
01126 trusted_domains,
01127 };
01128
01129 #endif