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_WINBIND
00031
00032 static NTSTATUS enum_groups_internal(struct winbindd_domain *domain,
00033 TALLOC_CTX *mem_ctx,
00034 uint32 *num_entries,
00035 struct acct_info **info,
00036 enum lsa_SidType sidtype)
00037 {
00038 struct pdb_search *search;
00039 struct samr_displayentry *entries;
00040 int i;
00041 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
00042
00043 if (sidtype == SID_NAME_ALIAS) {
00044 search = pdb_search_aliases(&domain->sid);
00045 } else {
00046 search = pdb_search_groups();
00047 }
00048
00049 if (search == NULL) goto done;
00050
00051 *num_entries = pdb_search_entries(search, 0, 0xffffffff, &entries);
00052 if (*num_entries == 0) {
00053
00054 result = NT_STATUS_OK;
00055 goto done;
00056 }
00057
00058 *info = TALLOC_ARRAY(mem_ctx, struct acct_info, *num_entries);
00059 if (*info == NULL) {
00060 result = NT_STATUS_NO_MEMORY;
00061 goto done;
00062 }
00063
00064 for (i=0; i<*num_entries; i++) {
00065 fstrcpy((*info)[i].acct_name, entries[i].account_name);
00066 fstrcpy((*info)[i].acct_desc, entries[i].description);
00067 (*info)[i].rid = entries[i].rid;
00068 }
00069
00070 result = NT_STATUS_OK;
00071 done:
00072 pdb_search_destroy(search);
00073 return result;
00074 }
00075
00076
00077 static NTSTATUS enum_local_groups(struct winbindd_domain *domain,
00078 TALLOC_CTX *mem_ctx,
00079 uint32 *num_entries,
00080 struct acct_info **info)
00081 {
00082 return enum_groups_internal(domain,
00083 mem_ctx,
00084 num_entries,
00085 info,
00086 SID_NAME_ALIAS);
00087 }
00088
00089
00090 static NTSTATUS name_to_sid(struct winbindd_domain *domain,
00091 TALLOC_CTX *mem_ctx,
00092 const char *domain_name,
00093 const char *name,
00094 DOM_SID *sid,
00095 enum lsa_SidType *type)
00096 {
00097 DEBUG(10, ("Finding name %s\n", name));
00098
00099 if ( !lookup_name( mem_ctx, name, LOOKUP_NAME_ALL,
00100 NULL, NULL, sid, type ) )
00101 {
00102 return NT_STATUS_NONE_MAPPED;
00103 }
00104
00105 return NT_STATUS_OK;
00106 }
00107
00108
00109
00110
00111 static NTSTATUS sid_to_name(struct winbindd_domain *domain,
00112 TALLOC_CTX *mem_ctx,
00113 const DOM_SID *sid,
00114 char **domain_name,
00115 char **name,
00116 enum lsa_SidType *type)
00117 {
00118 const char *dom, *nam;
00119
00120 DEBUG(10, ("Converting SID %s\n", sid_string_static(sid)));
00121
00122
00123 if (!sid_check_is_in_builtin(sid) &&
00124 !sid_check_is_in_our_domain(sid)) {
00125 DEBUG(0, ("Possible deadlock: Trying to lookup SID %s with "
00126 "passdb backend\n", sid_string_static(sid)));
00127 return NT_STATUS_NONE_MAPPED;
00128 }
00129
00130 if (!lookup_sid(mem_ctx, sid, &dom, &nam, type)) {
00131 return NT_STATUS_NONE_MAPPED;
00132 }
00133
00134 *domain_name = talloc_strdup(mem_ctx, dom);
00135 *name = talloc_strdup(mem_ctx, nam);
00136
00137 return NT_STATUS_OK;
00138 }
00139
00140 static NTSTATUS rids_to_names(struct winbindd_domain *domain,
00141 TALLOC_CTX *mem_ctx,
00142 const DOM_SID *domain_sid,
00143 uint32 *rids,
00144 size_t num_rids,
00145 char **domain_name,
00146 char ***names,
00147 enum lsa_SidType **types)
00148 {
00149 size_t i;
00150 bool have_mapped;
00151 bool have_unmapped;
00152
00153 *domain_name = NULL;
00154 *names = NULL;
00155 *types = NULL;
00156
00157 if (!num_rids) {
00158 return NT_STATUS_OK;
00159 }
00160
00161 *names = TALLOC_ARRAY(mem_ctx, char *, num_rids);
00162 *types = TALLOC_ARRAY(mem_ctx, enum lsa_SidType, num_rids);
00163
00164 if ((*names == NULL) || (*types == NULL)) {
00165 return NT_STATUS_NO_MEMORY;
00166 }
00167
00168 have_mapped = have_unmapped = false;
00169
00170 for (i=0; i<num_rids; i++) {
00171 DOM_SID sid;
00172 const char *dom = NULL, *nam = NULL;
00173 enum lsa_SidType type = SID_NAME_UNKNOWN;
00174
00175 if (!sid_compose(&sid, domain_sid, rids[i])) {
00176 return NT_STATUS_INTERNAL_ERROR;
00177 }
00178
00179 if (!lookup_sid(mem_ctx, &sid, &dom, &nam, &type)) {
00180 have_unmapped = true;
00181 (*types)[i] = SID_NAME_UNKNOWN;
00182 (*names)[i] = talloc_strdup(mem_ctx, "");
00183 } else {
00184 have_mapped = true;
00185 (*types)[i] = type;
00186 (*names)[i] = CONST_DISCARD(char *, nam);
00187 }
00188
00189 if (domain_name == NULL) {
00190 *domain_name = CONST_DISCARD(char *, dom);
00191 } else {
00192 char *dname = CONST_DISCARD(char *, dom);
00193 TALLOC_FREE(dname);
00194 }
00195 }
00196
00197 if (!have_mapped) {
00198 return NT_STATUS_NONE_MAPPED;
00199 }
00200 if (!have_unmapped) {
00201 return NT_STATUS_OK;
00202 }
00203 return STATUS_SOME_UNMAPPED;
00204 }
00205
00206
00207 static NTSTATUS lookup_usergroups(struct winbindd_domain *domain,
00208 TALLOC_CTX *mem_ctx,
00209 const DOM_SID *user_sid,
00210 uint32 *num_groups, DOM_SID **user_gids)
00211 {
00212 NTSTATUS result;
00213 DOM_SID *groups = NULL;
00214 gid_t *gids = NULL;
00215 size_t ngroups = 0;
00216 struct samu *user;
00217
00218 if ( (user = samu_new(mem_ctx)) == NULL ) {
00219 return NT_STATUS_NO_MEMORY;
00220 }
00221
00222 if (!pdb_getsampwsid(user, user_sid ) ) {
00223 return NT_STATUS_NO_SUCH_USER;
00224 }
00225
00226 result = pdb_enum_group_memberships( mem_ctx, user, &groups, &gids, &ngroups );
00227
00228 TALLOC_FREE( user );
00229
00230 *num_groups = (uint32)ngroups;
00231 *user_gids = groups;
00232
00233 return result;
00234 }
00235
00236 static NTSTATUS lookup_useraliases(struct winbindd_domain *domain,
00237 TALLOC_CTX *mem_ctx,
00238 uint32 num_sids, const DOM_SID *sids,
00239 uint32 *p_num_aliases, uint32 **rids)
00240 {
00241 NTSTATUS result;
00242 size_t num_aliases = 0;
00243
00244 result = pdb_enum_alias_memberships(mem_ctx, &domain->sid,
00245 sids, num_sids, rids, &num_aliases);
00246
00247 *p_num_aliases = num_aliases;
00248 return result;
00249 }
00250
00251
00252 static NTSTATUS sequence_number(struct winbindd_domain *domain, uint32 *seq)
00253 {
00254 BOOL result;
00255 time_t seq_num;
00256
00257 result = pdb_get_seq_num(&seq_num);
00258 if (!result) {
00259 *seq = 1;
00260 }
00261
00262 *seq = (int) seq_num;
00263
00264 return NT_STATUS_OK;
00265 }
00266
00267 static NTSTATUS lockout_policy(struct winbindd_domain *domain,
00268 TALLOC_CTX *mem_ctx,
00269 SAM_UNK_INFO_12 *policy)
00270 {
00271
00272 return NT_STATUS_NOT_IMPLEMENTED;
00273 }
00274
00275 static NTSTATUS password_policy(struct winbindd_domain *domain,
00276 TALLOC_CTX *mem_ctx,
00277 SAM_UNK_INFO_1 *policy)
00278 {
00279 uint32 min_pass_len,pass_hist,password_properties;
00280 time_t u_expire, u_min_age;
00281 NTTIME nt_expire, nt_min_age;
00282 uint32 account_policy_temp;
00283
00284 if ((policy = TALLOC_ZERO_P(mem_ctx, SAM_UNK_INFO_1)) == NULL) {
00285 return NT_STATUS_NO_MEMORY;
00286 }
00287
00288 if (!pdb_get_account_policy(AP_MIN_PASSWORD_LEN, &account_policy_temp)) {
00289 return NT_STATUS_ACCESS_DENIED;
00290 }
00291 min_pass_len = account_policy_temp;
00292
00293 if (!pdb_get_account_policy(AP_PASSWORD_HISTORY, &account_policy_temp)) {
00294 return NT_STATUS_ACCESS_DENIED;
00295 }
00296 pass_hist = account_policy_temp;
00297
00298 if (!pdb_get_account_policy(AP_USER_MUST_LOGON_TO_CHG_PASS, &account_policy_temp)) {
00299 return NT_STATUS_ACCESS_DENIED;
00300 }
00301 password_properties = account_policy_temp;
00302
00303 if (!pdb_get_account_policy(AP_MAX_PASSWORD_AGE, &account_policy_temp)) {
00304 return NT_STATUS_ACCESS_DENIED;
00305 }
00306 u_expire = account_policy_temp;
00307
00308 if (!pdb_get_account_policy(AP_MIN_PASSWORD_AGE, &account_policy_temp)) {
00309 return NT_STATUS_ACCESS_DENIED;
00310 }
00311 u_min_age = account_policy_temp;
00312
00313 unix_to_nt_time_abs(&nt_expire, u_expire);
00314 unix_to_nt_time_abs(&nt_min_age, u_min_age);
00315
00316 init_unk_info1(policy, (uint16)min_pass_len, (uint16)pass_hist,
00317 password_properties, nt_expire, nt_min_age);
00318
00319 return NT_STATUS_OK;
00320 }
00321
00322
00323
00324
00325
00326
00327 static NTSTATUS builtin_enum_dom_groups(struct winbindd_domain *domain,
00328 TALLOC_CTX *mem_ctx,
00329 uint32 *num_entries,
00330 struct acct_info **info)
00331 {
00332
00333 *num_entries = 0;
00334 *info = NULL;
00335 return NT_STATUS_OK;
00336 }
00337
00338
00339
00340
00341 static NTSTATUS builtin_query_user_list(struct winbindd_domain *domain,
00342 TALLOC_CTX *mem_ctx,
00343 uint32 *num_entries,
00344 WINBIND_USERINFO **info)
00345 {
00346
00347 *num_entries = 0;
00348 *info = NULL;
00349 return NT_STATUS_OK;
00350 }
00351
00352
00353 static NTSTATUS builtin_query_user(struct winbindd_domain *domain,
00354 TALLOC_CTX *mem_ctx,
00355 const DOM_SID *user_sid,
00356 WINBIND_USERINFO *user_info)
00357 {
00358 return NT_STATUS_NO_SUCH_USER;
00359 }
00360
00361 static NTSTATUS builtin_lookup_groupmem(struct winbindd_domain *domain,
00362 TALLOC_CTX *mem_ctx,
00363 const DOM_SID *group_sid, uint32 *num_names,
00364 DOM_SID **sid_mem, char ***names,
00365 uint32 **name_types)
00366 {
00367 *num_names = 0;
00368 *sid_mem = NULL;
00369 *names = NULL;
00370 *name_types = 0;
00371 return NT_STATUS_NO_SUCH_GROUP;
00372 }
00373
00374
00375 static NTSTATUS builtin_trusted_domains(struct winbindd_domain *domain,
00376 TALLOC_CTX *mem_ctx,
00377 uint32 *num_domains,
00378 char ***names,
00379 char ***alt_names,
00380 DOM_SID **dom_sids)
00381 {
00382 *num_domains = 0;
00383 *names = NULL;
00384 *alt_names = NULL;
00385 *dom_sids = NULL;
00386 return NT_STATUS_OK;
00387 }
00388
00389
00390
00391
00392
00393
00394 static NTSTATUS sam_enum_dom_groups(struct winbindd_domain *domain,
00395 TALLOC_CTX *mem_ctx,
00396 uint32 *num_entries,
00397 struct acct_info **info)
00398 {
00399 return enum_groups_internal(domain,
00400 mem_ctx,
00401 num_entries,
00402 info,
00403 SID_NAME_DOM_GRP);
00404 }
00405
00406 static NTSTATUS sam_query_user_list(struct winbindd_domain *domain,
00407 TALLOC_CTX *mem_ctx,
00408 uint32 *num_entries,
00409 WINBIND_USERINFO **info)
00410 {
00411 struct pdb_search *ps = pdb_search_users(ACB_NORMAL);
00412 struct samr_displayentry *entries = NULL;
00413 uint32 i;
00414
00415 *num_entries = 0;
00416 *info = NULL;
00417
00418 if (!ps) {
00419 return NT_STATUS_NO_MEMORY;
00420 }
00421
00422 *num_entries = pdb_search_entries(ps,
00423 1, 0xffffffff,
00424 &entries);
00425
00426 *info = TALLOC_ZERO_ARRAY(mem_ctx, WINBIND_USERINFO, *num_entries);
00427 if (!(*info)) {
00428 pdb_search_destroy(ps);
00429 return NT_STATUS_NO_MEMORY;
00430 }
00431
00432 for (i = 0; i < *num_entries; i++) {
00433 struct samr_displayentry *e = &entries[i];
00434
00435 (*info)[i].acct_name = talloc_strdup(mem_ctx, e->account_name );
00436 (*info)[i].full_name = talloc_strdup(mem_ctx, e->fullname );
00437 (*info)[i].homedir = NULL;
00438 (*info)[i].shell = NULL;
00439 sid_compose(&(*info)[i].user_sid, &domain->sid, e->rid);
00440
00441
00442
00443
00444
00445
00446
00447
00448
00449 sid_compose(&(*info)[i].group_sid, &domain->sid,
00450 DOMAIN_GROUP_RID_USERS);
00451 }
00452
00453 pdb_search_destroy(ps);
00454 return NT_STATUS_OK;
00455 }
00456
00457
00458 static NTSTATUS sam_query_user(struct winbindd_domain *domain,
00459 TALLOC_CTX *mem_ctx,
00460 const DOM_SID *user_sid,
00461 WINBIND_USERINFO *user_info)
00462 {
00463 struct samu *sampass = NULL;
00464 fstring sidstr;
00465
00466 ZERO_STRUCTP(user_info);
00467
00468 if (!sid_check_is_in_our_domain(user_sid)) {
00469 return NT_STATUS_NO_SUCH_USER;
00470 }
00471
00472 sid_to_string(sidstr, user_sid);
00473 DEBUG(10,("sam_query_user: getting samu info for sid %s\n",
00474 sidstr ));
00475
00476 if (!(sampass = samu_new(mem_ctx))) {
00477 return NT_STATUS_NO_MEMORY;
00478 }
00479
00480 if (!pdb_getsampwsid(sampass, user_sid)) {
00481 TALLOC_FREE(sampass);
00482 return NT_STATUS_NO_SUCH_USER;
00483 }
00484
00485 if (pdb_get_group_sid(sampass) == NULL) {
00486 TALLOC_FREE(sampass);
00487 return NT_STATUS_NO_SUCH_GROUP;
00488 }
00489
00490 sid_to_string(sidstr, sampass->group_sid);
00491 DEBUG(10,("sam_query_user: group sid %s\n", sidstr ));
00492
00493 sid_copy(&user_info->user_sid, user_sid);
00494 sid_copy(&user_info->group_sid, sampass->group_sid);
00495
00496 user_info->acct_name = talloc_strdup(mem_ctx, sampass->username ?
00497 sampass->username : "");
00498 user_info->full_name = talloc_strdup(mem_ctx, sampass->full_name ?
00499 sampass->full_name : "");
00500 user_info->homedir = talloc_strdup(mem_ctx, sampass->home_dir ?
00501 sampass->home_dir : "");
00502 if (sampass->unix_pw && sampass->unix_pw->pw_shell) {
00503 user_info->shell = talloc_strdup(mem_ctx, sampass->unix_pw->pw_shell);
00504 } else {
00505 user_info->shell = talloc_strdup(mem_ctx, "");
00506 }
00507 user_info->primary_gid = sampass->unix_pw ? sampass->unix_pw->pw_gid : (gid_t)-1;
00508
00509 TALLOC_FREE(sampass);
00510 return NT_STATUS_OK;
00511 }
00512
00513
00514 static NTSTATUS sam_lookup_groupmem(struct winbindd_domain *domain,
00515 TALLOC_CTX *mem_ctx,
00516 const DOM_SID *group_sid, uint32 *num_names,
00517 DOM_SID **sid_mem, char ***names,
00518 uint32 **name_types)
00519 {
00520 size_t i, num_members, num_mapped;
00521 uint32 *rids;
00522 NTSTATUS result;
00523 const DOM_SID **sids;
00524 struct lsa_dom_info *lsa_domains;
00525 struct lsa_name_info *lsa_names;
00526 TALLOC_CTX *tmp_ctx;
00527
00528 if (!sid_check_is_in_our_domain(group_sid)) {
00529
00530 return NT_STATUS_NO_SUCH_GROUP;
00531 }
00532
00533 if (!(tmp_ctx = talloc_init("lookup_groupmem"))) {
00534 return NT_STATUS_NO_MEMORY;
00535 }
00536
00537 result = pdb_enum_group_members(tmp_ctx, group_sid, &rids,
00538 &num_members);
00539 if (!NT_STATUS_IS_OK(result)) {
00540 TALLOC_FREE(tmp_ctx);
00541 return result;
00542 }
00543
00544 if (num_members == 0) {
00545 *num_names = 0;
00546 *sid_mem = NULL;
00547 *names = NULL;
00548 *name_types = NULL;
00549 TALLOC_FREE(tmp_ctx);
00550 return NT_STATUS_OK;
00551 }
00552
00553 *sid_mem = TALLOC_ARRAY(mem_ctx, DOM_SID, num_members);
00554 *names = TALLOC_ARRAY(mem_ctx, char *, num_members);
00555 *name_types = TALLOC_ARRAY(mem_ctx, uint32, num_members);
00556 sids = TALLOC_ARRAY(tmp_ctx, const DOM_SID *, num_members);
00557
00558 if (((*sid_mem) == NULL) || ((*names) == NULL) ||
00559 ((*name_types) == NULL) || (sids == NULL)) {
00560 TALLOC_FREE(tmp_ctx);
00561 return NT_STATUS_NO_MEMORY;
00562 }
00563
00564
00565
00566
00567
00568
00569 for (i=0; i<num_members; i++) {
00570 DOM_SID *sid = &((*sid_mem)[i]);
00571 if (!sid_compose(sid, &domain->sid, rids[i])) {
00572 TALLOC_FREE(tmp_ctx);
00573 return NT_STATUS_INTERNAL_ERROR;
00574 }
00575 sids[i] = sid;
00576 }
00577
00578 result = lookup_sids(tmp_ctx, num_members, sids, 1,
00579 &lsa_domains, &lsa_names);
00580 if (!NT_STATUS_IS_OK(result)) {
00581 TALLOC_FREE(tmp_ctx);
00582 return result;
00583 }
00584
00585 num_mapped = 0;
00586 for (i=0; i<num_members; i++) {
00587 if (lsa_names[i].type != SID_NAME_USER) {
00588 DEBUG(2, ("Got %s as group member -- ignoring\n",
00589 sid_type_lookup(lsa_names[i].type)));
00590 continue;
00591 }
00592 if (!((*names)[i] = talloc_strdup((*names),
00593 lsa_names[i].name))) {
00594 TALLOC_FREE(tmp_ctx);
00595 return NT_STATUS_NO_MEMORY;
00596 }
00597
00598 (*name_types)[i] = lsa_names[i].type;
00599
00600 num_mapped += 1;
00601 }
00602
00603 *num_names = num_mapped;
00604
00605 TALLOC_FREE(tmp_ctx);
00606 return NT_STATUS_OK;
00607 }
00608
00609
00610 static NTSTATUS sam_trusted_domains(struct winbindd_domain *domain,
00611 TALLOC_CTX *mem_ctx,
00612 uint32 *num_domains,
00613 char ***names,
00614 char ***alt_names,
00615 DOM_SID **dom_sids)
00616 {
00617 NTSTATUS nt_status;
00618 struct trustdom_info **domains;
00619 int i;
00620 TALLOC_CTX *tmp_ctx;
00621
00622 *num_domains = 0;
00623 *names = NULL;
00624 *alt_names = NULL;
00625 *dom_sids = NULL;
00626
00627 if (!(tmp_ctx = talloc_init("trusted_domains"))) {
00628 return NT_STATUS_NO_MEMORY;
00629 }
00630
00631 nt_status = secrets_trusted_domains(tmp_ctx, num_domains,
00632 &domains);
00633 if (!NT_STATUS_IS_OK(nt_status)) {
00634 TALLOC_FREE(tmp_ctx);
00635 return nt_status;
00636 }
00637
00638 if (*num_domains) {
00639 *names = TALLOC_ARRAY(mem_ctx, char *, *num_domains);
00640 *alt_names = TALLOC_ARRAY(mem_ctx, char *, *num_domains);
00641 *dom_sids = TALLOC_ARRAY(mem_ctx, DOM_SID, *num_domains);
00642
00643 if ((*alt_names == NULL) || (*names == NULL) || (*dom_sids == NULL)) {
00644 TALLOC_FREE(tmp_ctx);
00645 return NT_STATUS_NO_MEMORY;
00646 }
00647 } else {
00648 *names = NULL;
00649 *alt_names = NULL;
00650 *dom_sids = NULL;
00651 }
00652
00653 for (i=0; i<*num_domains; i++) {
00654 (*alt_names)[i] = NULL;
00655 if (!((*names)[i] = talloc_strdup((*names),
00656 domains[i]->name))) {
00657 TALLOC_FREE(tmp_ctx);
00658 return NT_STATUS_NO_MEMORY;
00659 }
00660 sid_copy(&(*dom_sids)[i], &domains[i]->sid);
00661 }
00662
00663 TALLOC_FREE(tmp_ctx);
00664 return NT_STATUS_OK;
00665 }
00666
00667
00668 struct winbindd_methods builtin_passdb_methods = {
00669 false,
00670 builtin_query_user_list,
00671 builtin_enum_dom_groups,
00672 enum_local_groups,
00673 name_to_sid,
00674 sid_to_name,
00675 rids_to_names,
00676 builtin_query_user,
00677 lookup_usergroups,
00678 lookup_useraliases,
00679 builtin_lookup_groupmem,
00680 sequence_number,
00681 lockout_policy,
00682 password_policy,
00683 builtin_trusted_domains,
00684 };
00685
00686
00687 struct winbindd_methods sam_passdb_methods = {
00688 false,
00689 sam_query_user_list,
00690 sam_enum_dom_groups,
00691 enum_local_groups,
00692 name_to_sid,
00693 sid_to_name,
00694 rids_to_names,
00695 sam_query_user,
00696 lookup_usergroups,
00697 lookup_useraliases,
00698 sam_lookup_groupmem,
00699 sequence_number,
00700 lockout_policy,
00701 password_policy,
00702 sam_trusted_domains,
00703 };