From 1bb11c7744df6928cb8a096373ab920366b38770 Mon Sep 17 00:00:00 2001 From: Andreas Schneider Date: Fri, 13 Dec 2013 19:08:34 +0100 Subject: [PATCH] s3-auth: Add passwd_to_SamInfo3(). First this function tries to contacts winbind if the user is a domain user to get valid information about it. If winbind isn't running it will try to create everything from the passwd struct. This is not always reliable but works in most cases. It improves the current situation which doesn't talk to winbind at all. Pair-Programmed-With: Guenther Deschner Signed-off-by: Guenther Deschner Signed-off-by: Andreas Schneider Reviewed-by: Andrew Bartlett --- source3/auth/proto.h | 4 ++ source3/auth/server_info.c | 116 +++++++++++++++++++++++++++++++++++++ 2 files changed, 120 insertions(+) diff --git a/source3/auth/proto.h b/source3/auth/proto.h index 76661fc833a..8385e665820 100644 --- a/source3/auth/proto.h +++ b/source3/auth/proto.h @@ -286,6 +286,10 @@ NTSTATUS samu_to_SamInfo3(TALLOC_CTX *mem_ctx, const char *login_server, struct netr_SamInfo3 **_info3, struct extra_auth_info *extra); +NTSTATUS passwd_to_SamInfo3(TALLOC_CTX *mem_ctx, + const char *unix_username, + const struct passwd *pwd, + struct netr_SamInfo3 **pinfo3); struct netr_SamInfo3 *copy_netr_SamInfo3(TALLOC_CTX *mem_ctx, struct netr_SamInfo3 *orig); struct netr_SamInfo3 *wbcAuthUserInfo_to_netr_SamInfo3(TALLOC_CTX *mem_ctx, diff --git a/source3/auth/server_info.c b/source3/auth/server_info.c index d2b7d6e938f..46d817880a0 100644 --- a/source3/auth/server_info.c +++ b/source3/auth/server_info.c @@ -24,6 +24,7 @@ #include "../libcli/security/security.h" #include "rpc_client/util_netlogon.h" #include "nsswitch/libwbclient/wbclient.h" +#include "lib/winbind_util.h" #include "passdb.h" #undef DBGC_CLASS @@ -436,6 +437,121 @@ NTSTATUS samu_to_SamInfo3(TALLOC_CTX *mem_ctx, return NT_STATUS_OK; } +NTSTATUS passwd_to_SamInfo3(TALLOC_CTX *mem_ctx, + const char *unix_username, + const struct passwd *pwd, + struct netr_SamInfo3 **pinfo3) +{ + struct netr_SamInfo3 *info3; + NTSTATUS status; + TALLOC_CTX *tmp_ctx; + const char *domain_name = NULL; + const char *user_name = NULL; + struct dom_sid domain_sid; + struct dom_sid user_sid; + struct dom_sid group_sid; + enum lsa_SidType type; + uint32_t num_sids = 0; + struct dom_sid *user_sids = NULL; + bool ok; + + tmp_ctx = talloc_stackframe(); + + ok = lookup_name_smbconf(tmp_ctx, + unix_username, + LOOKUP_NAME_ALL, + &domain_name, + &user_name, + &user_sid, + &type); + if (!ok) { + status = NT_STATUS_NO_SUCH_USER; + goto done; + } + + if (type != SID_NAME_USER) { + status = NT_STATUS_NO_SUCH_USER; + goto done; + } + + ok = winbind_lookup_usersids(tmp_ctx, + &user_sid, + &num_sids, + &user_sids); + /* Check if winbind is running */ + if (ok) { + /* + * Winbind is running and the first element of the user_sids + * is the primary group. + */ + if (num_sids > 0) { + group_sid = user_sids[0]; + } + } else { + /* + * Winbind is not running, create the group_sid from the + * group id. + */ + gid_to_sid(&group_sid, pwd->pw_gid); + } + + /* Make sure we have a valid group sid */ + ok = !is_null_sid(&group_sid); + if (!ok) { + status = NT_STATUS_NO_SUCH_USER; + goto done; + } + + /* Construct a netr_SamInfo3 from the information we have */ + info3 = talloc_zero(tmp_ctx, struct netr_SamInfo3); + if (!info3) { + status = NT_STATUS_NO_MEMORY; + goto done; + } + + info3->base.account_name.string = talloc_strdup(info3, unix_username); + if (info3->base.account_name.string == NULL) { + status = NT_STATUS_NO_MEMORY; + goto done; + } + + ZERO_STRUCT(domain_sid); + + sid_copy(&domain_sid, &user_sid); + sid_split_rid(&domain_sid, &info3->base.rid); + info3->base.domain_sid = dom_sid_dup(info3, &domain_sid); + + ok = sid_peek_check_rid(&domain_sid, &group_sid, + &info3->base.primary_gid); + if (!ok) { + DEBUG(1, ("The primary group domain sid(%s) does not " + "match the domain sid(%s) for %s(%s)\n", + sid_string_dbg(&group_sid), + sid_string_dbg(&domain_sid), + unix_username, + sid_string_dbg(&user_sid))); + status = NT_STATUS_INVALID_SID; + goto done; + } + + info3->base.acct_flags = ACB_NORMAL; + + if (num_sids) { + status = group_sids_to_info3(info3, user_sids, num_sids); + if (!NT_STATUS_IS_OK(status)) { + goto done; + } + } + + *pinfo3 = talloc_steal(mem_ctx, info3); + + status = NT_STATUS_OK; +done: + talloc_free(tmp_ctx); + + return status; +} + #undef RET_NOMEM #define RET_NOMEM(ptr) do { \