auth: Move wbcAuthUserInfo_to_netr_SamInfo3 to the top level
[nivanova/samba-autobuild/.git] / source3 / auth / server_info.c
index ca35ba76a1467b445bdf585fe2ef53218c44b408..df0be5418f2fd559fa8c592e1a7edff9ca76c53a 100644 (file)
 */
 
 #include "includes.h"
+#include "auth.h"
 #include "../lib/crypto/arcfour.h"
 #include "../librpc/gen_ndr/netlogon.h"
 #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
 #define DBGC_CLASS DBGC_AUTH
 
-/* FIXME: do we really still need this ? */
-static int server_info_dtor(struct auth_serversupplied_info *server_info)
-{
-       TALLOC_FREE(server_info->info3);
-       ZERO_STRUCTP(server_info);
-       return 0;
-}
-
 /***************************************************************************
  Make a server_info struct. Free with TALLOC_FREE().
 ***************************************************************************/
@@ -44,14 +38,12 @@ struct auth_serversupplied_info *make_server_info(TALLOC_CTX *mem_ctx)
 {
        struct auth_serversupplied_info *result;
 
-       result = TALLOC_ZERO_P(mem_ctx, struct auth_serversupplied_info);
+       result = talloc_zero(mem_ctx, struct auth_serversupplied_info);
        if (result == NULL) {
                DEBUG(0, ("talloc failed\n"));
                return NULL;
        }
 
-       talloc_set_destructor(result, server_info_dtor);
-
        /* Initialise the uid and gid values to something non-zero
           which may save us from giving away root access if there
           is a bug in allocating these fields. */
@@ -68,8 +60,6 @@ struct auth_serversupplied_info *make_server_info(TALLOC_CTX *mem_ctx)
 *****************************************************************************/
 
 NTSTATUS serverinfo_to_SamInfo2(struct auth_serversupplied_info *server_info,
-                               uint8_t *pipe_session_key,
-                               size_t pipe_session_key_len,
                                struct netr_SamInfo2 *sam2)
 {
        struct netr_SamInfo3 *info3;
@@ -79,25 +69,17 @@ NTSTATUS serverinfo_to_SamInfo2(struct auth_serversupplied_info *server_info,
                return NT_STATUS_NO_MEMORY;
        }
 
-       if (server_info->user_session_key.length) {
+       if (server_info->session_key.length) {
                memcpy(info3->base.key.key,
-                      server_info->user_session_key.data,
+                      server_info->session_key.data,
                       MIN(sizeof(info3->base.key.key),
-                          server_info->user_session_key.length));
-               if (pipe_session_key) {
-                       arcfour_crypt(info3->base.key.key,
-                                     pipe_session_key, 16);
-               }
+                          server_info->session_key.length));
        }
        if (server_info->lm_session_key.length) {
                memcpy(info3->base.LMSessKey.key,
                       server_info->lm_session_key.data,
                       MIN(sizeof(info3->base.LMSessKey.key),
                           server_info->lm_session_key.length));
-               if (pipe_session_key) {
-                       arcfour_crypt(info3->base.LMSessKey.key,
-                                     pipe_session_key, 8);
-               }
        }
 
        sam2->base = info3->base;
@@ -111,8 +93,6 @@ NTSTATUS serverinfo_to_SamInfo2(struct auth_serversupplied_info *server_info,
 *****************************************************************************/
 
 NTSTATUS serverinfo_to_SamInfo3(const struct auth_serversupplied_info *server_info,
-                               uint8_t *pipe_session_key,
-                               size_t pipe_session_key_len,
                                struct netr_SamInfo3 *sam3)
 {
        struct netr_SamInfo3 *info3;
@@ -122,25 +102,17 @@ NTSTATUS serverinfo_to_SamInfo3(const struct auth_serversupplied_info *server_in
                return NT_STATUS_NO_MEMORY;
        }
 
-       if (server_info->user_session_key.length) {
+       if (server_info->session_key.length) {
                memcpy(info3->base.key.key,
-                      server_info->user_session_key.data,
+                      server_info->session_key.data,
                       MIN(sizeof(info3->base.key.key),
-                          server_info->user_session_key.length));
-               if (pipe_session_key) {
-                       arcfour_crypt(info3->base.key.key,
-                                     pipe_session_key, 16);
-               }
+                          server_info->session_key.length));
        }
        if (server_info->lm_session_key.length) {
                memcpy(info3->base.LMSessKey.key,
                       server_info->lm_session_key.data,
                       MIN(sizeof(info3->base.LMSessKey.key),
                           server_info->lm_session_key.length));
-               if (pipe_session_key) {
-                       arcfour_crypt(info3->base.LMSessKey.key,
-                                     pipe_session_key, 8);
-               }
        }
 
        sam3->base = info3->base;
@@ -157,8 +129,6 @@ NTSTATUS serverinfo_to_SamInfo3(const struct auth_serversupplied_info *server_in
 *****************************************************************************/
 
 NTSTATUS serverinfo_to_SamInfo6(struct auth_serversupplied_info *server_info,
-                               uint8_t *pipe_session_key,
-                               size_t pipe_session_key_len,
                                struct netr_SamInfo6 *sam6)
 {
        struct pdb_domain_info *dominfo;
@@ -180,25 +150,17 @@ NTSTATUS serverinfo_to_SamInfo6(struct auth_serversupplied_info *server_info,
                return NT_STATUS_NO_MEMORY;
        }
 
-       if (server_info->user_session_key.length) {
+       if (server_info->session_key.length) {
                memcpy(info3->base.key.key,
-                      server_info->user_session_key.data,
+                      server_info->session_key.data,
                       MIN(sizeof(info3->base.key.key),
-                          server_info->user_session_key.length));
-               if (pipe_session_key) {
-                       arcfour_crypt(info3->base.key.key,
-                                     pipe_session_key, 16);
-               }
+                          server_info->session_key.length));
        }
        if (server_info->lm_session_key.length) {
                memcpy(info3->base.LMSessKey.key,
                       server_info->lm_session_key.data,
                       MIN(sizeof(info3->base.LMSessKey.key),
                           server_info->lm_session_key.length));
-               if (pipe_session_key) {
-                       arcfour_crypt(info3->base.LMSessKey.key,
-                                     pipe_session_key, 8);
-               }
        }
 
        sam6->base = info3->base;
@@ -272,14 +234,9 @@ static NTSTATUS group_sids_to_info3(struct netr_SamInfo3 *info3,
        for (i = 0; i < num_sids; i++) {
                ok = sid_peek_check_rid(domain_sid, &sids[i], &rid);
                if (ok) {
-
-                       /* if it is the primary gid, skip it, we
-                        * obviously already have it */
-                       if (info3->base.primary_gid == rid) continue;
-
                        /* store domain group rid */
-                       groups->rids[i].rid = rid;
-                       groups->rids[i].attributes = attributes;
+                       groups->rids[groups->count].rid = rid;
+                       groups->rids[groups->count].attributes = attributes;
                        groups->count++;
                        continue;
                }
@@ -393,9 +350,9 @@ NTSTATUS samu_to_SamInfo3(TALLOC_CTX *mem_ctx,
                }
        }
 
-       unix_to_nt_time(&info3->base.last_logon, pdb_get_logon_time(samu));
-       unix_to_nt_time(&info3->base.last_logoff, get_time_t_max());
-       unix_to_nt_time(&info3->base.acct_expiry, get_time_t_max());
+       unix_to_nt_time(&info3->base.logon_time, pdb_get_logon_time(samu));
+       unix_to_nt_time(&info3->base.logoff_time, get_time_t_max());
+       unix_to_nt_time(&info3->base.kickoff_time, get_time_t_max());
        unix_to_nt_time(&info3->base.last_password_change,
                        pdb_get_pass_last_set_time(samu));
        unix_to_nt_time(&info3->base.allow_password_change,
@@ -437,6 +394,13 @@ NTSTATUS samu_to_SamInfo3(TALLOC_CTX *mem_ctx,
        info3->base.logon_count = pdb_get_logon_count(samu);
        info3->base.bad_password_count = pdb_get_bad_password_count(samu);
 
+       info3->base.logon_domain.string = talloc_strdup(info3,
+                                                 pdb_get_domain(samu));
+       RET_NOMEM(info3->base.logon_domain.string);
+
+       info3->base.domain_sid = dom_sid_dup(info3, &domain_sid);
+       RET_NOMEM(info3->base.domain_sid);
+
        status = pdb_enum_group_memberships(mem_ctx, samu,
                                            &group_sids, &gids,
                                            &num_group_sids);
@@ -467,19 +431,146 @@ NTSTATUS samu_to_SamInfo3(TALLOC_CTX *mem_ctx,
                RET_NOMEM(info3->base.logon_server.string);
        }
 
-       info3->base.domain.string = talloc_strdup(info3,
-                                                 pdb_get_domain(samu));
-       RET_NOMEM(info3->base.domain.string);
-
-       info3->base.domain_sid = dom_sid_dup(info3, &domain_sid);
-       RET_NOMEM(info3->base.domain_sid);
-
        info3->base.acct_flags = pdb_get_acct_ctrl(samu);
 
        *_info3 = info3;
        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 is_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, try to create the group_sid from the
+                * passwd group id.
+                */
+
+               /*
+                * This can lead to a primary group of S-1-22-2-XX which
+                * will be rejected by other Samba code.
+                */
+               gid_to_sid(&group_sid, pwd->pw_gid);
+
+               ZERO_STRUCT(domain_sid);
+
+               /*
+                * If we are a unix group, set the group_sid to the
+                * 'Domain Users' RID of 513 which will always resolve to a
+                * name.
+                */
+               if (sid_check_is_in_unix_groups(&group_sid)) {
+                       sid_compose(&group_sid,
+                                   get_global_sam_sid(),
+                                   DOMAIN_RID_USERS);
+               }
+       }
+
+       /* Make sure we have a valid group sid */
+       is_null = is_null_sid(&group_sid);
+       if (is_null) {
+               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 { \
@@ -521,139 +612,3 @@ struct netr_SamInfo3 *copy_netr_SamInfo3(TALLOC_CTX *mem_ctx,
        return info3;
 }
 
-static NTSTATUS wbcsids_to_samr_RidWithAttributeArray(
-                               TALLOC_CTX *mem_ctx,
-                               struct samr_RidWithAttributeArray *groups,
-                               const struct dom_sid *domain_sid,
-                               const struct wbcSidWithAttr *sids,
-                               size_t num_sids)
-{
-       unsigned int i;
-       bool ok;
-
-       groups->rids = talloc_array(mem_ctx,
-                                   struct samr_RidWithAttribute, num_sids);
-       if (!groups->rids) {
-               return NT_STATUS_NO_MEMORY;
-       }
-
-       /* a wbcDomainSid is the same as a dom_sid */
-       for (i = 0; i < num_sids; i++) {
-               ok = sid_peek_check_rid(domain_sid,
-                                       (const struct dom_sid *)&sids[i].sid,
-                                       &groups->rids[i].rid);
-               if (!ok) continue;
-
-               groups->rids[i].attributes = SE_GROUP_MANDATORY |
-                                            SE_GROUP_ENABLED_BY_DEFAULT |
-                                            SE_GROUP_ENABLED;
-               groups->count++;
-       }
-
-       return NT_STATUS_OK;
-}
-
-struct netr_SamInfo3 *wbcAuthUserInfo_to_netr_SamInfo3(TALLOC_CTX *mem_ctx,
-                                       const struct wbcAuthUserInfo *info)
-{
-       struct netr_SamInfo3 *info3;
-       struct dom_sid user_sid;
-       struct dom_sid group_sid;
-       struct dom_sid domain_sid;
-       NTSTATUS status;
-       bool ok;
-
-       memcpy(&user_sid, &info->sids[0].sid, sizeof(user_sid));
-       memcpy(&group_sid, &info->sids[1].sid, sizeof(group_sid));
-
-       info3 = talloc_zero(mem_ctx, struct netr_SamInfo3);
-       if (!info3) return NULL;
-
-       info3->base.last_logon = info->logon_time;
-       info3->base.last_logoff = info->logoff_time;
-       info3->base.acct_expiry = info->kickoff_time;
-       unix_to_nt_time(&info3->base.last_password_change, info->pass_last_set_time);
-       unix_to_nt_time(&info3->base.allow_password_change,
-                       info->pass_can_change_time);
-       unix_to_nt_time(&info3->base.force_password_change,
-                       info->pass_must_change_time);
-
-       if (info->account_name) {
-               info3->base.account_name.string =
-                               talloc_strdup(info3, info->account_name);
-               RET_NOMEM(info3->base.account_name.string);
-       }
-       if (info->full_name) {
-               info3->base.full_name.string =
-                               talloc_strdup(info3, info->full_name);
-               RET_NOMEM(info3->base.full_name.string);
-       }
-       if (info->logon_script) {
-               info3->base.logon_script.string =
-                               talloc_strdup(info3, info->logon_script);
-               RET_NOMEM(info3->base.logon_script.string);
-       }
-       if (info->profile_path) {
-               info3->base.profile_path.string =
-                               talloc_strdup(info3, info->profile_path);
-               RET_NOMEM(info3->base.profile_path.string);
-       }
-       if (info->home_directory) {
-               info3->base.home_directory.string =
-                               talloc_strdup(info3, info->home_directory);
-               RET_NOMEM(info3->base.home_directory.string);
-       }
-       if (info->home_drive) {
-               info3->base.home_drive.string =
-                               talloc_strdup(info3, info->home_drive);
-               RET_NOMEM(info3->base.home_drive.string);
-       }
-
-       info3->base.logon_count = info->logon_count;
-       info3->base.bad_password_count = info->bad_password_count;
-
-       sid_copy(&domain_sid, &user_sid);
-       sid_split_rid(&domain_sid, &info3->base.rid);
-
-       ok = sid_peek_check_rid(&domain_sid, &group_sid,
-                               &info3->base.primary_gid);
-       if (!ok) {
-               DEBUG(1, ("The primary group sid domain does not"
-                         "match user sid domain for user: %s\n",
-                         info->account_name));
-               TALLOC_FREE(info3);
-               return NULL;
-       }
-
-       status = wbcsids_to_samr_RidWithAttributeArray(info3,
-                                                      &info3->base.groups,
-                                                      &domain_sid,
-                                                      &info->sids[1],
-                                                      info->num_sids - 1);
-       if (!NT_STATUS_IS_OK(status)) {
-               TALLOC_FREE(info3);
-               return NULL;
-       }
-
-       info3->base.user_flags = info->user_flags;
-       memcpy(info3->base.key.key, info->user_session_key, 16);
-
-       if (info->logon_server) {
-               info3->base.logon_server.string =
-                               talloc_strdup(info3, info->logon_server);
-               RET_NOMEM(info3->base.logon_server.string);
-       }
-       if (info->domain_name) {
-               info3->base.domain.string =
-                               talloc_strdup(info3, info->domain_name);
-               RET_NOMEM(info3->base.domain.string);
-       }
-
-       info3->base.domain_sid = dom_sid_dup(info3, &domain_sid);
-       RET_NOMEM(info3->base.domain_sid);
-
-       memcpy(info3->base.LMSessKey.key, info->lm_session_key, 8);
-       info3->base.acct_flags = info->acct_flags;
-
-       return info3;
-}