s3-auth: session keys in validation level 6 samlogon replies are *not* encrypted.
[kai/samba.git] / source3 / auth / server_info.c
index c7cd72bb876894eb1d084383c9b24b7d57d32951..02bf689b2c2db2d8e7f1bd6c48cd447ab5ce90b4 100644 (file)
 */
 
 #include "includes.h"
+#include "auth.h"
 #include "../lib/crypto/arcfour.h"
 #include "../librpc/gen_ndr/netlogon.h"
-#include "../libcli/security/dom_sid.h"
+#include "../libcli/security/security.h"
+#include "rpc_client/util_netlogon.h"
+#include "nsswitch/libwbclient/wbclient.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().
 ***************************************************************************/
@@ -41,14 +37,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. */
@@ -76,11 +70,11 @@ 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));
+                          server_info->session_key.length));
                if (pipe_session_key) {
                        arcfour_crypt(info3->base.key.key,
                                      pipe_session_key, 16);
@@ -107,7 +101,7 @@ NTSTATUS serverinfo_to_SamInfo2(struct auth_serversupplied_info *server_info,
  already be initialized and is used as the talloc parent for its members.
 *****************************************************************************/
 
-NTSTATUS serverinfo_to_SamInfo3(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)
@@ -119,11 +113,11 @@ NTSTATUS serverinfo_to_SamInfo3(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));
+                          server_info->session_key.length));
                if (pipe_session_key) {
                        arcfour_crypt(info3->base.key.key,
                                      pipe_session_key, 16);
@@ -177,25 +171,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;
@@ -230,7 +216,7 @@ static NTSTATUS append_netr_SidAttr(TALLOC_CTX *mem_ctx,
        if (*sids == NULL) {
                return NT_STATUS_NO_MEMORY;
        }
-       (*sids)[t].sid = sid_dup_talloc(*sids, asid);
+       (*sids)[t].sid = dom_sid_dup(*sids, asid);
        if ((*sids)[t].sid == NULL) {
                return NT_STATUS_NO_MEMORY;
        }
@@ -240,7 +226,7 @@ static NTSTATUS append_netr_SidAttr(TALLOC_CTX *mem_ctx,
        return NT_STATUS_OK;
 }
 
-/* Fils the samr_RidWithAttributeArray with the provided sids.
+/* Fills the samr_RidWithAttributeArray with the provided sids.
  * If it happens that we have additional groups that do not belong
  * to the domain, add their sids as extra sids */
 static NTSTATUS group_sids_to_info3(struct netr_SamInfo3 *info3,
@@ -269,14 +255,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;
                }
@@ -310,7 +291,7 @@ NTSTATUS samu_to_SamInfo3(TALLOC_CTX *mem_ctx,
        const struct dom_sid *group_sid;
        struct dom_sid domain_sid;
        struct dom_sid *group_sids;
-       size_t num_group_sids = 0;
+       uint32_t num_group_sids = 0;
        const char *tmp;
        gid_t *gids;
        NTSTATUS status;
@@ -333,7 +314,7 @@ NTSTATUS samu_to_SamInfo3(TALLOC_CTX *mem_ctx,
 
        /* check if this is a "Unix Users" domain user,
         * we need to handle it in a special way if that's the case */
-       if (dom_sid_compare_domain(user_sid, &global_sid_Unix_Users) == 0) {
+       if (sid_check_is_in_unix_users(user_sid)) {
                /* in info3 you can only set rids for the user and the
                 * primary group, and the domain sid must be that of
                 * the sam domain.
@@ -359,7 +340,7 @@ NTSTATUS samu_to_SamInfo3(TALLOC_CTX *mem_ctx,
 
        /* check if this is a "Unix Groups" domain group,
         * if so we need special handling */
-       if (dom_sid_compare_domain(group_sid, &global_sid_Unix_Groups) == 0) {
+       if (sid_check_is_in_unix_groups(group_sid)) {
                /* in info3 you can only set rids for the user and the
                 * primary group, and the domain sid must be that of
                 * the sam domain.
@@ -390,9 +371,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,
@@ -434,6 +415,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);
@@ -464,13 +452,6 @@ 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 = sid_dup_talloc(info3, &domain_sid);
-       RET_NOMEM(info3->base.domain_sid);
-
        info3->base.acct_flags = pdb_get_acct_ctrl(samu);
 
        *_info3 = info3;
@@ -490,66 +471,15 @@ struct netr_SamInfo3 *copy_netr_SamInfo3(TALLOC_CTX *mem_ctx,
 {
        struct netr_SamInfo3 *info3;
        unsigned int i;
+       NTSTATUS status;
 
        info3 = talloc_zero(mem_ctx, struct netr_SamInfo3);
        if (!info3) return NULL;
 
-       /* first copy all, then realloc pointers */
-       info3->base = orig->base;
-
-       if (orig->base.account_name.string) {
-               info3->base.account_name.string =
-                       talloc_strdup(info3, orig->base.account_name.string);
-               RET_NOMEM(info3->base.account_name.string);
-       }
-       if (orig->base.full_name.string) {
-               info3->base.full_name.string =
-                       talloc_strdup(info3, orig->base.full_name.string);
-               RET_NOMEM(info3->base.full_name.string);
-       }
-       if (orig->base.logon_script.string) {
-               info3->base.logon_script.string =
-                       talloc_strdup(info3, orig->base.logon_script.string);
-               RET_NOMEM(info3->base.logon_script.string);
-       }
-       if (orig->base.profile_path.string) {
-               info3->base.profile_path.string =
-                       talloc_strdup(info3, orig->base.profile_path.string);
-               RET_NOMEM(info3->base.profile_path.string);
-       }
-       if (orig->base.home_directory.string) {
-               info3->base.home_directory.string =
-                       talloc_strdup(info3, orig->base.home_directory.string);
-               RET_NOMEM(info3->base.home_directory.string);
-       }
-       if (orig->base.home_drive.string) {
-               info3->base.home_drive.string =
-                       talloc_strdup(info3, orig->base.home_drive.string);
-               RET_NOMEM(info3->base.home_drive.string);
-       }
-
-       if (orig->base.groups.count) {
-               info3->base.groups.rids = (struct samr_RidWithAttribute *)
-                       talloc_memdup(info3, orig->base.groups.rids,
-                               (sizeof(struct samr_RidWithAttribute) *
-                                       orig->base.groups.count));
-               RET_NOMEM(info3->base.groups.rids);
-       }
-
-       if (orig->base.logon_server.string) {
-               info3->base.logon_server.string =
-                       talloc_strdup(info3, orig->base.logon_server.string);
-               RET_NOMEM(info3->base.logon_server.string);
-       }
-       if (orig->base.domain.string) {
-               info3->base.domain.string =
-                       talloc_strdup(info3, orig->base.domain.string);
-               RET_NOMEM(info3->base.domain.string);
-       }
-
-       if (orig->base.domain_sid) {
-               info3->base.domain_sid = sid_dup_talloc(info3, orig->base.domain_sid);
-               RET_NOMEM(info3->base.domain_sid);
+       status = copy_netr_SamBaseInfo(info3, &orig->base, &info3->base);
+       if (!NT_STATUS_IS_OK(status)) {
+               TALLOC_FREE(info3);
+               return NULL;
        }
 
        if (orig->sidcount) {
@@ -558,7 +488,7 @@ struct netr_SamInfo3 *copy_netr_SamInfo3(TALLOC_CTX *mem_ctx,
                                           orig->sidcount);
                RET_NOMEM(info3->sids);
                for (i = 0; i < orig->sidcount; i++) {
-                       info3->sids[i].sid = sid_dup_talloc(info3->sids,
+                       info3->sids[i].sid = dom_sid_dup(info3->sids,
                                                            orig->sids[i].sid);
                        RET_NOMEM(info3->sids[i].sid);
                        info3->sids[i].attributes =
@@ -576,7 +506,7 @@ static NTSTATUS wbcsids_to_samr_RidWithAttributeArray(
                                const struct wbcSidWithAttr *sids,
                                size_t num_sids)
 {
-       unsigned int i;
+       unsigned int i, j = 0;
        bool ok;
 
        groups->rids = talloc_array(mem_ctx,
@@ -589,15 +519,58 @@ static NTSTATUS wbcsids_to_samr_RidWithAttributeArray(
        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);
+                                       &groups->rids[j].rid);
                if (!ok) continue;
 
-               groups->rids[i].attributes = SE_GROUP_MANDATORY |
+               groups->rids[j].attributes = SE_GROUP_MANDATORY |
                                             SE_GROUP_ENABLED_BY_DEFAULT |
                                             SE_GROUP_ENABLED;
-               groups->count++;
+               j++;
        }
 
+       groups->count = j;
+       return NT_STATUS_OK;
+}
+
+static NTSTATUS wbcsids_to_netr_SidAttrArray(
+                               const struct dom_sid *domain_sid,
+                               const struct wbcSidWithAttr *sids,
+                               size_t num_sids,
+                               TALLOC_CTX *mem_ctx,
+                               struct netr_SidAttr **_info3_sids,
+                               uint32_t *info3_num_sids)
+{
+       unsigned int i, j = 0;
+       struct netr_SidAttr *info3_sids;
+
+       info3_sids = talloc_array(mem_ctx, struct netr_SidAttr, num_sids);
+       if (info3_sids == NULL) {
+               return NT_STATUS_NO_MEMORY;
+       }
+
+       /* a wbcDomainSid is the same as a dom_sid */
+       for (i = 0; i < num_sids; i++) {
+               const struct dom_sid *sid;
+
+               sid = (const struct dom_sid *)&sids[i].sid;
+
+               if (dom_sid_in_domain(domain_sid, sid)) {
+                       continue;
+               }
+
+               info3_sids[j].sid = dom_sid_dup(info3_sids, sid);
+               if (info3_sids[j].sid == NULL) {
+                       talloc_free(info3_sids);
+                       return NT_STATUS_NO_MEMORY;
+               }
+               info3_sids[j].attributes = SE_GROUP_MANDATORY |
+                                          SE_GROUP_ENABLED_BY_DEFAULT |
+                                          SE_GROUP_ENABLED;
+               j++;
+       }
+
+       *info3_num_sids = j;
+       *_info3_sids = info3_sids;
        return NT_STATUS_OK;
 }
 
@@ -617,12 +590,14 @@ struct netr_SamInfo3 *wbcAuthUserInfo_to_netr_SamInfo3(TALLOC_CTX *mem_ctx,
        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;
-       info3->base.last_password_change = info->pass_last_set_time;
-       info3->base.allow_password_change = info->pass_can_change_time;
-       info3->base.force_password_change = info->pass_must_change_time;
+       info3->base.logon_time = info->logon_time;
+       info3->base.logoff_time = info->logoff_time;
+       info3->base.kickoff_time = 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 =
@@ -681,6 +656,17 @@ struct netr_SamInfo3 *wbcAuthUserInfo_to_netr_SamInfo3(TALLOC_CTX *mem_ctx,
                return NULL;
        }
 
+       status = wbcsids_to_netr_SidAttrArray(&domain_sid,
+                                             &info->sids[1],
+                                             info->num_sids - 1,
+                                             info3,
+                                             &info3->sids,
+                                             &info3->sidcount);
+       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);
 
@@ -690,12 +676,12 @@ struct netr_SamInfo3 *wbcAuthUserInfo_to_netr_SamInfo3(TALLOC_CTX *mem_ctx,
                RET_NOMEM(info3->base.logon_server.string);
        }
        if (info->domain_name) {
-               info3->base.domain.string =
+               info3->base.logon_domain.string =
                                talloc_strdup(info3, info->domain_name);
-               RET_NOMEM(info3->base.domain.string);
+               RET_NOMEM(info3->base.logon_domain.string);
        }
 
-       info3->base.domain_sid = sid_dup_talloc(info3, &domain_sid);
+       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);