s3-auth: Add passwd_to_SamInfo3().
authorAndreas Schneider <asn@samba.org>
Fri, 13 Dec 2013 18:08:34 +0000 (19:08 +0100)
committerAndrew Bartlett <abartlet@samba.org>
Tue, 4 Feb 2014 22:41:25 +0000 (11:41 +1300)
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 <gd@samba.org>
Signed-off-by: Guenther Deschner <gd@samba.org>
Signed-off-by: Andreas Schneider <asn@samba.org>
Reviewed-by: Andrew Bartlett <abartlet@samba.org>
source3/auth/proto.h
source3/auth/server_info.c

index 76661fc833a5aefcfb41dfc7df5d062f852b9bed..8385e66582053e557dee343860bda00bb6407aab 100644 (file)
@@ -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,
index d2b7d6e938f0483701e70cd267965463db615492..46d817880a05b4ee7e219a386294dd185d30738b 100644 (file)
@@ -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 { \