Merge branch 'master' of ssh://git.samba.org/data/git/samba
[jra/samba/.git] / source3 / rpc_server / srv_samr_nt.c
index cbcd4de60c37efcf279ecaf0daca4c9aa70d6441..0b8cb35a84372790730e920c3ea603e0f04e8d18 100644 (file)
@@ -73,7 +73,6 @@ struct samr_info {
        uint32 status; /* some sort of flag.  best to record it.  comes from opnum 0x39 */
        uint32 acc_granted;
        DISP_INFO *disp_info;
-       TALLOC_CTX *mem_ctx;
 };
 
 static const struct generic_mapping sam_generic_mapping = {
@@ -357,11 +356,13 @@ static DISP_INFO *get_samr_dispinfo_by_sid(DOM_SID *psid)
  Create a samr_info struct.
 ********************************************************************/
 
-static struct samr_info *get_samr_info_by_sid(DOM_SID *psid)
+static int samr_info_destructor(struct samr_info *info);
+
+static struct samr_info *get_samr_info_by_sid(TALLOC_CTX *mem_ctx,
+                                             DOM_SID *psid)
 {
        struct samr_info *info;
        fstring sid_str;
-       TALLOC_CTX *mem_ctx;
 
        if (psid) {
                sid_to_fstring(sid_str, psid);
@@ -369,10 +370,10 @@ static struct samr_info *get_samr_info_by_sid(DOM_SID *psid)
                fstrcpy(sid_str,"(NULL)");
        }
 
-       mem_ctx = talloc_init("samr_info for domain sid %s", sid_str);
-
-       if ((info = TALLOC_ZERO_P(mem_ctx, struct samr_info)) == NULL)
+       if ((info = TALLOC_ZERO_P(mem_ctx, struct samr_info)) == NULL) {
                return NULL;
+       }
+       talloc_set_destructor(info, samr_info_destructor);
 
        DEBUG(10,("get_samr_info_by_sid: created new info for sid %s\n", sid_str));
        if (psid) {
@@ -382,7 +383,6 @@ static struct samr_info *get_samr_info_by_sid(DOM_SID *psid)
                DEBUG(10,("get_samr_info_by_sid: created new info for NULL sid.\n"));
                info->builtin_domain = False;
        }
-       info->mem_ctx = mem_ctx;
 
        info->disp_info = get_samr_dispinfo_by_sid(psid);
 
@@ -433,22 +433,15 @@ static void free_samr_cache(DISP_INFO *disp_info)
        unbecome_root();
 }
 
-/*******************************************************************
- Function to free the per handle data.
- ********************************************************************/
-
-static void free_samr_info(void *ptr)
+static int samr_info_destructor(struct samr_info *info)
 {
-       struct samr_info *info=(struct samr_info *) ptr;
-
        /* Only free the dispinfo cache if no one bothered to set up
           a timeout. */
 
        if (info->disp_info && info->disp_info->cache_timeout_event == NULL) {
                free_samr_cache(info->disp_info);
        }
-
-       talloc_destroy(info->mem_ctx);
+       return 0;
 }
 
 /*******************************************************************
@@ -457,7 +450,7 @@ static void free_samr_info(void *ptr)
 
 static void disp_info_cache_idle_timeout_handler(struct event_context *ev_ctx,
                                                 struct timed_event *te,
-                                                const struct timeval *now,
+                                                struct timeval now,
                                                 void *private_data)
 {
        DISP_INFO *disp_info = (DISP_INFO *)private_data;
@@ -486,7 +479,6 @@ static void set_disp_info_cache_timeout(DISP_INFO *disp_info, time_t secs_fromno
        disp_info->cache_timeout_event = event_add_timed(
                smbd_event_context(), NULL,
                timeval_current_ofs(secs_fromnow, 0),
-               "disp_info_cache_idle_timeout_handler",
                disp_info_cache_idle_timeout_handler, (void *)disp_info);
 }
 
@@ -653,12 +645,12 @@ NTSTATUS _samr_OpenDomain(pipes_struct *p,
        }
 
        /* associate the domain SID with the (unique) handle. */
-       if ((info = get_samr_info_by_sid(r->in.sid))==NULL)
+       if ((info = get_samr_info_by_sid(p->mem_ctx, r->in.sid))==NULL)
                return NT_STATUS_NO_MEMORY;
        info->acc_granted = acc_granted;
 
        /* get a (unique) handle.  open a policy on it. */
-       if (!create_policy_hnd(p, r->out.domain_handle, free_samr_info, (void *)info))
+       if (!create_policy_hnd(p, r->out.domain_handle, info))
                return NT_STATUS_OBJECT_NAME_NOT_FOUND;
 
        DEBUG(5,("_samr_OpenDomain: %d\n", __LINE__));
@@ -1181,9 +1173,7 @@ NTSTATUS _samr_EnumDomainGroups(pipes_struct *p,
 
        *r->out.sam = samr_array;
        *r->out.num_entries = num_groups;
-       /* this was missing, IMHO:
        *r->out.resume_handle = num_groups + *r->in.resume_handle;
-       */
 
        DEBUG(5,("_samr_EnumDomainGroups: %d\n", __LINE__));
 
@@ -1764,14 +1754,12 @@ NTSTATUS _samr_QueryAliasInfo(pipes_struct *p,
 
        switch (r->in.level) {
        case ALIASINFOALL:
-               init_samr_alias_info1(&alias_info->all,
-                                     alias_name,
-                                     1,
-                                     alias_description);
+               alias_info->all.name.string             = alias_name;
+               alias_info->all.num_members             = 1; /* ??? */
+               alias_info->all.description.string      = alias_description;
                break;
        case ALIASINFODESCRIPTION:
-               init_samr_alias_info3(&alias_info->description,
-                                     alias_description);
+               alias_info->description.string          = alias_description;
                break;
        default:
                return NT_STATUS_INVALID_INFO_CLASS;
@@ -1928,6 +1916,7 @@ NTSTATUS _samr_ChangePasswordUser3(pipes_struct *p,
        uint32 reject_reason;
        struct samr_DomInfo1 *dominfo = NULL;
        struct samr_ChangeReject *reject = NULL;
+       uint32_t tmp;
 
        DEBUG(5,("_samr_ChangePasswordUser3: %d\n", __LINE__));
 
@@ -1960,9 +1949,7 @@ NTSTATUS _samr_ChangePasswordUser3(pipes_struct *p,
        if (NT_STATUS_EQUAL(status, NT_STATUS_PASSWORD_RESTRICTION) ||
            NT_STATUS_EQUAL(status, NT_STATUS_ACCOUNT_RESTRICTION)) {
 
-               uint32 min_pass_len,pass_hist,password_properties;
                time_t u_expire, u_min_age;
-               NTTIME nt_expire, nt_min_age;
                uint32 account_policy_temp;
 
                dominfo = TALLOC_ZERO_P(p->mem_ctx, struct samr_DomInfo1);
@@ -1979,14 +1966,14 @@ NTSTATUS _samr_ChangePasswordUser3(pipes_struct *p,
 
                /* AS ROOT !!! */
 
-               pdb_get_account_policy(AP_MIN_PASSWORD_LEN, &account_policy_temp);
-               min_pass_len = account_policy_temp;
+               pdb_get_account_policy(AP_MIN_PASSWORD_LEN, &tmp);
+               dominfo->min_password_length = tmp;
 
-               pdb_get_account_policy(AP_PASSWORD_HISTORY, &account_policy_temp);
-               pass_hist = account_policy_temp;
+               pdb_get_account_policy(AP_PASSWORD_HISTORY, &tmp);
+               dominfo->password_history_length = tmp;
 
-               pdb_get_account_policy(AP_USER_MUST_LOGON_TO_CHG_PASS, &account_policy_temp);
-               password_properties = account_policy_temp;
+               pdb_get_account_policy(AP_USER_MUST_LOGON_TO_CHG_PASS,
+                                      &dominfo->password_properties);
 
                pdb_get_account_policy(AP_MAX_PASSWORD_AGE, &account_policy_temp);
                u_expire = account_policy_temp;
@@ -1998,20 +1985,13 @@ NTSTATUS _samr_ChangePasswordUser3(pipes_struct *p,
 
                unbecome_root();
 
-               unix_to_nt_time_abs(&nt_expire, u_expire);
-               unix_to_nt_time_abs(&nt_min_age, u_min_age);
+               unix_to_nt_time_abs((NTTIME *)&dominfo->max_password_age, u_expire);
+               unix_to_nt_time_abs((NTTIME *)&dominfo->min_password_age, u_min_age);
 
                if (lp_check_password_script() && *lp_check_password_script()) {
-                       password_properties |= DOMAIN_PASSWORD_COMPLEX;
+                       dominfo->password_properties |= DOMAIN_PASSWORD_COMPLEX;
                }
 
-               init_samr_DomInfo1(dominfo,
-                                  min_pass_len,
-                                  pass_hist,
-                                  password_properties,
-                                  u_expire,
-                                  u_min_age);
-
                reject->reason = reject_reason;
 
                *r->out.dominfo = dominfo;
@@ -2079,7 +2059,7 @@ NTSTATUS _samr_LookupRids(pipes_struct *p,
                return NT_STATUS_INVALID_HANDLE;
 
        status = access_check_samr_function(acc_granted,
-                                           SAMR_DOMAIN_ACCESS_ENUM_ACCOUNTS,
+                                           0, /* Don't know the acc_bits yet */
                                            "_samr_LookupRids");
        if (!NT_STATUS_IS_OK(status)) {
                return status;
@@ -2207,12 +2187,12 @@ NTSTATUS _samr_OpenUser(pipes_struct *p,
        TALLOC_FREE(sampass);
 
        /* associate the user's SID and access bits with the new handle. */
-       if ((info = get_samr_info_by_sid(&sid)) == NULL)
+       if ((info = get_samr_info_by_sid(p->mem_ctx, &sid)) == NULL)
                return NT_STATUS_NO_MEMORY;
        info->acc_granted = acc_granted;
 
        /* get a (unique) handle.  open a policy on it. */
-       if (!create_policy_hnd(p, user_pol, free_samr_info, (void *)info))
+       if (!create_policy_hnd(p, user_pol, info))
                return NT_STATUS_OBJECT_NAME_NOT_FOUND;
 
        return NT_STATUS_OK;
@@ -2260,14 +2240,6 @@ static NTSTATUS get_user_info_5(TALLOC_CTX *mem_ctx,
 {
        const DOM_SID *sid_user, *sid_group;
        uint32_t rid, primary_gid;
-       NTTIME last_logon, last_logoff, last_password_change,
-              acct_expiry;
-       const char *account_name, *full_name, *home_directory, *home_drive,
-                  *logon_script, *profile_path, *description,
-                  *workstations, *comment;
-       struct samr_LogonHours logon_hours;
-
-       ZERO_STRUCTP(r);
 
        sid_user = pdb_get_user_sid(pw);
 
@@ -2291,42 +2263,26 @@ static NTSTATUS get_user_info_5(TALLOC_CTX *mem_ctx,
                return NT_STATUS_UNSUCCESSFUL;
        }
 
-       unix_to_nt_time(&last_logon, pdb_get_logon_time(pw));
-       unix_to_nt_time(&last_logoff, pdb_get_logoff_time(pw));
-       unix_to_nt_time(&acct_expiry, pdb_get_kickoff_time(pw));
-       unix_to_nt_time(&last_password_change, pdb_get_pass_last_set_time(pw));
-
-       account_name = talloc_strdup(mem_ctx, pdb_get_username(pw));
-       full_name = talloc_strdup(mem_ctx, pdb_get_fullname(pw));
-       home_directory = talloc_strdup(mem_ctx, pdb_get_homedir(pw));
-       home_drive = talloc_strdup(mem_ctx, pdb_get_dir_drive(pw));
-       logon_script = talloc_strdup(mem_ctx, pdb_get_logon_script(pw));
-       profile_path = talloc_strdup(mem_ctx, pdb_get_profile_path(pw));
-       description = talloc_strdup(mem_ctx, pdb_get_acct_desc(pw));
-       workstations = talloc_strdup(mem_ctx, pdb_get_workstations(pw));
-       comment = talloc_strdup(mem_ctx, pdb_get_comment(pw));
-
-       logon_hours = get_logon_hours_from_pdb(mem_ctx, pw);
-
-       init_samr_user_info5(r,
-                            account_name,
-                            full_name,
-                            rid,
-                            primary_gid,
-                            home_directory,
-                            home_drive,
-                            logon_script,
-                            profile_path,
-                            description,
-                            workstations,
-                            last_logon,
-                            last_logoff,
-                            logon_hours,
-                            pdb_get_bad_password_count(pw),
-                            pdb_get_logon_count(pw),
-                            last_password_change,
-                            acct_expiry,
-                            pdb_get_acct_ctrl(pw));
+       unix_to_nt_time(&r->last_logon, pdb_get_logon_time(pw));
+       unix_to_nt_time(&r->last_logoff, pdb_get_logoff_time(pw));
+       unix_to_nt_time(&r->acct_expiry, pdb_get_kickoff_time(pw));
+       unix_to_nt_time(&r->last_password_change, pdb_get_pass_last_set_time(pw));
+
+       r->account_name.string  = talloc_strdup(mem_ctx, pdb_get_username(pw));
+       r->full_name.string     = talloc_strdup(mem_ctx, pdb_get_fullname(pw));
+       r->home_directory.string= talloc_strdup(mem_ctx, pdb_get_homedir(pw));
+       r->home_drive.string    = talloc_strdup(mem_ctx, pdb_get_dir_drive(pw));
+       r->logon_script.string  = talloc_strdup(mem_ctx, pdb_get_logon_script(pw));
+       r->profile_path.string  = talloc_strdup(mem_ctx, pdb_get_profile_path(pw));
+       r->description.string   = talloc_strdup(mem_ctx, pdb_get_acct_desc(pw));
+       r->workstations.string  = talloc_strdup(mem_ctx, pdb_get_workstations(pw));
+
+       r->logon_hours          = get_logon_hours_from_pdb(mem_ctx, pw);
+       r->rid                  = rid;
+       r->primary_gid          = primary_gid;
+       r->acct_flags           = pdb_get_acct_ctrl(pw);
+       r->bad_password_count   = pdb_get_bad_password_count(pw);
+       r->logon_count          = pdb_get_logon_count(pw);
 
        return NT_STATUS_OK;
 }
@@ -2339,17 +2295,11 @@ static NTSTATUS get_user_info_7(TALLOC_CTX *mem_ctx,
                                struct samr_UserInfo7 *r,
                                struct samu *smbpass)
 {
-       const char *account_name = NULL;
-
-       ZERO_STRUCTP(r);
-
-       account_name = talloc_strdup(mem_ctx, pdb_get_username(smbpass));
-       if (!account_name) {
+       r->account_name.string = talloc_strdup(mem_ctx, pdb_get_username(smbpass));
+       if (!r->account_name.string) {
                return NT_STATUS_NO_MEMORY;
        }
 
-       init_samr_user_info7(r, account_name);
-
        return NT_STATUS_OK;
 }
 
@@ -2361,9 +2311,7 @@ static NTSTATUS get_user_info_9(TALLOC_CTX *mem_ctx,
                                struct samr_UserInfo9 *r,
                                struct samu *smbpass)
 {
-       ZERO_STRUCTP(r);
-
-       init_samr_user_info9(r, pdb_get_group_rid(smbpass));
+       r->primary_gid = pdb_get_group_rid(smbpass);
 
        return NT_STATUS_OK;
 }
@@ -2376,9 +2324,7 @@ static NTSTATUS get_user_info_16(TALLOC_CTX *mem_ctx,
                                 struct samr_UserInfo16 *r,
                                 struct samu *smbpass)
 {
-       ZERO_STRUCTP(r);
-
-       init_samr_user_info16(r, pdb_get_acct_ctrl(smbpass));
+       r->acct_flags = pdb_get_acct_ctrl(smbpass);
 
        return NT_STATUS_OK;
 }
@@ -2430,8 +2376,11 @@ static NTSTATUS get_user_info_18(pipes_struct *p,
                return NT_STATUS_ACCOUNT_DISABLED;
        }
 
-       init_samr_user_info18(r, pdb_get_lanman_passwd(smbpass),
-                             pdb_get_nt_passwd(smbpass));
+       r->lm_pwd_active = true;
+       r->nt_pwd_active = true;
+       memcpy(r->lm_pwd.hash, pdb_get_lanman_passwd(smbpass), 16);
+       memcpy(r->nt_pwd.hash, pdb_get_nt_passwd(smbpass), 16);
+       r->password_expired = 0; /* FIXME */
 
        TALLOC_FREE(smbpass);
 
@@ -2470,7 +2419,7 @@ static NTSTATUS get_user_info_20(TALLOC_CTX *mem_ctx,
                return status;
        }
 
-       init_samr_user_info20(r, parameters);
+       r->parameters = *parameters;
 
        return NT_STATUS_OK;
 }
@@ -2488,14 +2437,8 @@ static NTSTATUS get_user_info_21(TALLOC_CTX *mem_ctx,
        NTSTATUS status;
        const DOM_SID *sid_user, *sid_group;
        uint32_t rid, primary_gid;
-       NTTIME last_logon, last_logoff, last_password_change,
-              acct_expiry, allow_password_change, force_password_change;
+       NTTIME force_password_change;
        time_t must_change_time;
-       uint8_t password_expired;
-       const char *account_name, *full_name, *home_directory, *home_drive,
-                  *logon_script, *profile_path, *description,
-                  *workstations, *comment;
-       struct samr_LogonHours logon_hours;
        struct lsa_BinaryString *parameters = NULL;
        const char *munged_dial = NULL;
        DATA_BLOB blob;
@@ -2524,11 +2467,11 @@ static NTSTATUS get_user_info_21(TALLOC_CTX *mem_ctx,
                return NT_STATUS_UNSUCCESSFUL;
        }
 
-       unix_to_nt_time(&last_logon, pdb_get_logon_time(pw));
-       unix_to_nt_time(&last_logoff, pdb_get_logoff_time(pw));
-       unix_to_nt_time(&acct_expiry, pdb_get_kickoff_time(pw));
-       unix_to_nt_time(&last_password_change, pdb_get_pass_last_set_time(pw));
-       unix_to_nt_time(&allow_password_change, pdb_get_pass_can_change_time(pw));
+       unix_to_nt_time(&r->last_logon, pdb_get_logon_time(pw));
+       unix_to_nt_time(&r->last_logoff, pdb_get_logoff_time(pw));
+       unix_to_nt_time(&r->acct_expiry, pdb_get_kickoff_time(pw));
+       unix_to_nt_time(&r->last_password_change, pdb_get_pass_last_set_time(pw));
+       unix_to_nt_time(&r->allow_password_change, pdb_get_pass_can_change_time(pw));
 
        must_change_time = pdb_get_pass_must_change_time(pw);
        if (must_change_time == get_time_t_max()) {
@@ -2537,12 +2480,6 @@ static NTSTATUS get_user_info_21(TALLOC_CTX *mem_ctx,
                unix_to_nt_time(&force_password_change, must_change_time);
        }
 
-       if (pdb_get_pass_must_change_time(pw) == 0) {
-               password_expired = PASS_MUST_CHANGE_AT_NEXT_LOGON;
-       } else {
-               password_expired = 0;
-       }
-
        munged_dial = pdb_get_munged_dial(pw);
        if (munged_dial) {
                blob = base64_decode_data_blob(munged_dial);
@@ -2556,17 +2493,33 @@ static NTSTATUS get_user_info_21(TALLOC_CTX *mem_ctx,
                return status;
        }
 
-       account_name = talloc_strdup(mem_ctx, pdb_get_username(pw));
-       full_name = talloc_strdup(mem_ctx, pdb_get_fullname(pw));
-       home_directory = talloc_strdup(mem_ctx, pdb_get_homedir(pw));
-       home_drive = talloc_strdup(mem_ctx, pdb_get_dir_drive(pw));
-       logon_script = talloc_strdup(mem_ctx, pdb_get_logon_script(pw));
-       profile_path = talloc_strdup(mem_ctx, pdb_get_profile_path(pw));
-       description = talloc_strdup(mem_ctx, pdb_get_acct_desc(pw));
-       workstations = talloc_strdup(mem_ctx, pdb_get_workstations(pw));
-       comment = talloc_strdup(mem_ctx, pdb_get_comment(pw));
+       r->force_password_change        = force_password_change;
+
+       r->account_name.string          = talloc_strdup(mem_ctx, pdb_get_username(pw));
+       r->full_name.string             = talloc_strdup(mem_ctx, pdb_get_fullname(pw));
+       r->home_directory.string        = talloc_strdup(mem_ctx, pdb_get_homedir(pw));
+       r->home_drive.string            = talloc_strdup(mem_ctx, pdb_get_dir_drive(pw));
+       r->logon_script.string          = talloc_strdup(mem_ctx, pdb_get_logon_script(pw));
+       r->profile_path.string          = talloc_strdup(mem_ctx, pdb_get_profile_path(pw));
+       r->description.string           = talloc_strdup(mem_ctx, pdb_get_acct_desc(pw));
+       r->workstations.string          = talloc_strdup(mem_ctx, pdb_get_workstations(pw));
+       r->comment.string               = talloc_strdup(mem_ctx, pdb_get_comment(pw));
+
+       r->logon_hours                  = get_logon_hours_from_pdb(mem_ctx, pw);
+       r->parameters                   = *parameters;
+       r->rid                          = rid;
+       r->primary_gid                  = primary_gid;
+       r->acct_flags                   = pdb_get_acct_ctrl(pw);
+       r->bad_password_count           = pdb_get_bad_password_count(pw);
+       r->logon_count                  = pdb_get_logon_count(pw);
+       r->fields_present               = pdb_build_fields_present(pw);
+       r->password_expired             = (pdb_get_pass_must_change_time(pw) == 0) ?
+                                               PASS_MUST_CHANGE_AT_NEXT_LOGON : 0;
+       r->country_code                 = 0;
+       r->code_page                    = 0;
+       r->lm_password_set              = 0;
+       r->nt_password_set              = 0;
 
-       logon_hours = get_logon_hours_from_pdb(mem_ctx, pw);
 #if 0
 
        /*
@@ -2581,35 +2534,6 @@ static NTSTATUS get_user_info_21(TALLOC_CTX *mem_ctx,
 
 #endif
 
-       init_samr_user_info21(r,
-                             last_logon,
-                             last_logoff,
-                             last_password_change,
-                             acct_expiry,
-                             allow_password_change,
-                             force_password_change,
-                             account_name,
-                             full_name,
-                             home_directory,
-                             home_drive,
-                             logon_script,
-                             profile_path,
-                             description,
-                             workstations,
-                             comment,
-                             parameters,
-                             rid,
-                             primary_gid,
-                             pdb_get_acct_ctrl(pw),
-                             pdb_build_fields_present(pw),
-                             logon_hours,
-                             pdb_get_bad_password_count(pw),
-                             pdb_get_logon_count(pw),
-                             0, /* country_code */
-                             0, /* code_page */
-                             0, /* nt_password_set */
-                             0, /* lm_password_set */
-                             password_expired);
 
        return NT_STATUS_OK;
 }
@@ -2634,7 +2558,7 @@ NTSTATUS _samr_QueryUserInfo(pipes_struct *p,
                return NT_STATUS_INVALID_HANDLE;
 
        status = access_check_samr_function(info->acc_granted,
-                                           SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
+                                           SAMR_USER_ACCESS_GET_ATTRIBUTES,
                                            "_samr_QueryUserInfo");
        if (!NT_STATUS_IS_OK(status)) {
                return status;
@@ -2871,23 +2795,16 @@ NTSTATUS _samr_QueryDomainInfo(pipes_struct *p,
        NTSTATUS status = NT_STATUS_OK;
        struct samr_info *info = NULL;
        union samr_DomainInfo *dom_info;
-       uint32 min_pass_len,pass_hist,password_properties;
        time_t u_expire, u_min_age;
-       NTTIME nt_expire, nt_min_age;
 
        time_t u_lock_duration, u_reset_time;
-       NTTIME nt_lock_duration, nt_reset_time;
-       uint32 lockout;
-       time_t u_logout;
-       NTTIME nt_logout;
+       uint32_t u_logout;
 
        uint32 account_policy_temp;
 
        time_t seq_num;
        uint32 server_role;
 
-       uint32 num_users=0, num_groups=0, num_aliases=0;
-
        DEBUG(5,("_samr_QueryDomainInfo: %d\n", __LINE__));
 
        dom_info = TALLOC_ZERO_P(p->mem_ctx, union samr_DomainInfo);
@@ -2914,14 +2831,15 @@ NTSTATUS _samr_QueryDomainInfo(pipes_struct *p,
 
                        /* AS ROOT !!! */
 
-                       pdb_get_account_policy(AP_MIN_PASSWORD_LEN, &account_policy_temp);
-                       min_pass_len = account_policy_temp;
+                       pdb_get_account_policy(AP_MIN_PASSWORD_LEN,
+                                              &account_policy_temp);
+                       dom_info->info1.min_password_length = account_policy_temp;
 
                        pdb_get_account_policy(AP_PASSWORD_HISTORY, &account_policy_temp);
-                       pass_hist = account_policy_temp;
+                       dom_info->info1.password_history_length = account_policy_temp;
 
-                       pdb_get_account_policy(AP_USER_MUST_LOGON_TO_CHG_PASS, &account_policy_temp);
-                       password_properties = account_policy_temp;
+                       pdb_get_account_policy(AP_USER_MUST_LOGON_TO_CHG_PASS,
+                               &dom_info->info1.password_properties);
 
                        pdb_get_account_policy(AP_MAX_PASSWORD_AGE, &account_policy_temp);
                        u_expire = account_policy_temp;
@@ -2933,19 +2851,13 @@ NTSTATUS _samr_QueryDomainInfo(pipes_struct *p,
 
                        unbecome_root();
 
-                       unix_to_nt_time_abs(&nt_expire, u_expire);
-                       unix_to_nt_time_abs(&nt_min_age, u_min_age);
+                       unix_to_nt_time_abs((NTTIME *)&dom_info->info1.max_password_age, u_expire);
+                       unix_to_nt_time_abs((NTTIME *)&dom_info->info1.min_password_age, u_min_age);
 
                        if (lp_check_password_script() && *lp_check_password_script()) {
-                               password_properties |= DOMAIN_PASSWORD_COMPLEX;
+                               dom_info->info1.password_properties |= DOMAIN_PASSWORD_COMPLEX;
                        }
 
-                       init_samr_DomInfo1(&dom_info->info1,
-                                          (uint16)min_pass_len,
-                                          (uint16)pass_hist,
-                                          password_properties,
-                                          nt_expire,
-                                          nt_min_age);
                        break;
                case 0x02:
 
@@ -2953,14 +2865,13 @@ NTSTATUS _samr_QueryDomainInfo(pipes_struct *p,
 
                        /* AS ROOT !!! */
 
-                       num_users = count_sam_users(info->disp_info, ACB_NORMAL);
-                       num_groups = count_sam_groups(info->disp_info);
-                       num_aliases = count_sam_aliases(info->disp_info);
+                       dom_info->general.num_users     = count_sam_users(info->disp_info, ACB_NORMAL);
+                       dom_info->general.num_groups    = count_sam_groups(info->disp_info);
+                       dom_info->general.num_aliases   = count_sam_aliases(info->disp_info);
 
-                       pdb_get_account_policy(AP_TIME_TO_LOGOUT, &account_policy_temp);
-                       u_logout = account_policy_temp;
+                       pdb_get_account_policy(AP_TIME_TO_LOGOUT, &u_logout);
 
-                       unix_to_nt_time_abs(&nt_logout, u_logout);
+                       unix_to_nt_time_abs(&dom_info->general.force_logoff_time, u_logout);
 
                        if (!pdb_get_seq_num(&seq_num))
                                seq_num = time(NULL);
@@ -2973,18 +2884,14 @@ NTSTATUS _samr_QueryDomainInfo(pipes_struct *p,
                        if (lp_server_role() == ROLE_DOMAIN_BDC)
                                server_role = ROLE_DOMAIN_BDC;
 
-                       init_samr_DomGeneralInformation(&dom_info->general,
-                                                       nt_logout,
-                                                       lp_serverstring(),
-                                                       lp_workgroup(),
-                                                       global_myname(),
-                                                       seq_num,
-                                                       DOMAIN_SERVER_ENABLED,
-                                                       server_role,
-                                                       1,
-                                                       num_users,
-                                                       num_groups,
-                                                       num_aliases);
+                       dom_info->general.oem_information.string        = lp_serverstring();
+                       dom_info->general.domain_name.string            = lp_workgroup();
+                       dom_info->general.primary.string                = global_myname();
+                       dom_info->general.sequence_num                  = seq_num;
+                       dom_info->general.domain_server_state           = DOMAIN_SERVER_ENABLED;
+                       dom_info->general.role                          = server_role;
+                       dom_info->general.unknown3                      = 1;
+
                        break;
                case 0x03:
 
@@ -3002,34 +2909,27 @@ NTSTATUS _samr_QueryDomainInfo(pipes_struct *p,
 
                        unbecome_root();
 
-                       unix_to_nt_time_abs(&nt_logout, u_logout);
-
-                       init_samr_DomInfo3(&dom_info->info3,
-                                          nt_logout);
+                       unix_to_nt_time_abs(&dom_info->info3.force_logoff_time, u_logout);
 
                        break;
                case 0x04:
-                       init_samr_DomOEMInformation(&dom_info->oem,
-                                                   lp_serverstring());
+                       dom_info->oem.oem_information.string = lp_serverstring();
                        break;
                case 0x05:
-                       init_samr_DomInfo5(&dom_info->info5,
-                                          get_global_sam_name());
+                       dom_info->info5.domain_name.string = get_global_sam_name();
                        break;
                case 0x06:
                        /* NT returns its own name when a PDC. win2k and later
                         * only the name of the PDC if itself is a BDC (samba4
                         * idl) */
-                       init_samr_DomInfo6(&dom_info->info6,
-                                          global_myname());
+                       dom_info->info6.primary.string = global_myname();
                        break;
                case 0x07:
                        server_role = ROLE_DOMAIN_PDC;
                        if (lp_server_role() == ROLE_DOMAIN_BDC)
                                server_role = ROLE_DOMAIN_BDC;
 
-                       init_samr_DomInfo7(&dom_info->info7,
-                                          server_role);
+                       dom_info->info7.role = server_role;
                        break;
                case 0x08:
 
@@ -3045,9 +2945,9 @@ NTSTATUS _samr_QueryDomainInfo(pipes_struct *p,
 
                        unbecome_root();
 
-                       init_samr_DomInfo8(&dom_info->info8,
-                                          seq_num,
-                                          0);
+                       dom_info->info8.sequence_num = seq_num;
+                       dom_info->info8.domain_create_time = 0;
+
                        break;
                case 0x0c:
 
@@ -3064,21 +2964,20 @@ NTSTATUS _samr_QueryDomainInfo(pipes_struct *p,
                        pdb_get_account_policy(AP_RESET_COUNT_TIME, &account_policy_temp);
                        u_reset_time = account_policy_temp * 60;
 
-                       pdb_get_account_policy(AP_BAD_ATTEMPT_LOCKOUT, &account_policy_temp);
-                       lockout = account_policy_temp;
+                       pdb_get_account_policy(AP_BAD_ATTEMPT_LOCKOUT,
+                                              &account_policy_temp);
+                       dom_info->info12.lockout_threshold = account_policy_temp;
 
                        /* !AS ROOT */
 
                        unbecome_root();
 
-                       unix_to_nt_time_abs(&nt_lock_duration, u_lock_duration);
-                       unix_to_nt_time_abs(&nt_reset_time, u_reset_time);
+                       unix_to_nt_time_abs(&dom_info->info12.lockout_duration,
+                                           u_lock_duration);
+                       unix_to_nt_time_abs(&dom_info->info12.lockout_window,
+                                           u_reset_time);
 
-                       init_samr_DomInfo12(&dom_info->info12,
-                                           nt_lock_duration,
-                                           nt_reset_time,
-                                           (uint16)lockout);
-                       break;
+                       break;
                default:
                        return NT_STATUS_INVALID_INFO_CLASS;
        }
@@ -3255,7 +3154,7 @@ NTSTATUS _samr_CreateUser2(pipes_struct *p,
        }
 
        /* associate the user's SID with the new handle. */
-       if ((info = get_samr_info_by_sid(&sid)) == NULL) {
+       if ((info = get_samr_info_by_sid(p->mem_ctx, &sid)) == NULL) {
                return NT_STATUS_NO_MEMORY;
        }
 
@@ -3264,7 +3163,7 @@ NTSTATUS _samr_CreateUser2(pipes_struct *p,
        info->acc_granted = acc_granted;
 
        /* get a (unique) handle.  open a policy on it. */
-       if (!create_policy_hnd(p, user_pol, free_samr_info, (void *)info)) {
+       if (!create_policy_hnd(p, user_pol, info)) {
                return NT_STATUS_OBJECT_NAME_NOT_FOUND;
        }
 
@@ -3316,7 +3215,7 @@ NTSTATUS _samr_Connect(pipes_struct *p,
        /* set up the SAMR connect_anon response */
 
        /* associate the user's SID with the new handle. */
-       if ((info = get_samr_info_by_sid(NULL)) == NULL)
+       if ((info = get_samr_info_by_sid(p->mem_ctx, NULL)) == NULL)
                return NT_STATUS_NO_MEMORY;
 
        /* don't give away the farm but this is probably ok.  The SAMR_ACCESS_ENUM_DOMAINS
@@ -3329,7 +3228,7 @@ NTSTATUS _samr_Connect(pipes_struct *p,
        info->acc_granted = des_access & (SAMR_ACCESS_ENUM_DOMAINS|SAMR_ACCESS_OPEN_DOMAIN);
 
        /* get a (unique) handle.  open a policy on it. */
-       if (!create_policy_hnd(p, r->out.connect_handle, free_samr_info, (void *)info))
+       if (!create_policy_hnd(p, r->out.connect_handle, info))
                return NT_STATUS_OBJECT_NAME_NOT_FOUND;
 
        return NT_STATUS_OK;
@@ -3383,14 +3282,14 @@ NTSTATUS _samr_Connect2(pipes_struct *p,
                return nt_status;
 
        /* associate the user's SID and access granted with the new handle. */
-       if ((info = get_samr_info_by_sid(NULL)) == NULL)
+       if ((info = get_samr_info_by_sid(p->mem_ctx, NULL)) == NULL)
                return NT_STATUS_NO_MEMORY;
 
        info->acc_granted = acc_granted;
        info->status = r->in.access_mask; /* this looks so wrong... - gd */
 
        /* get a (unique) handle.  open a policy on it. */
-       if (!create_policy_hnd(p, r->out.connect_handle, free_samr_info, (void *)info))
+       if (!create_policy_hnd(p, r->out.connect_handle, info))
                return NT_STATUS_OBJECT_NAME_NOT_FOUND;
 
        DEBUG(5,("%s: %d\n", fn, __LINE__));
@@ -3620,13 +3519,13 @@ NTSTATUS _samr_OpenAlias(pipes_struct *p,
        }
 
        /* associate the alias SID with the new handle. */
-       if ((info = get_samr_info_by_sid(&sid)) == NULL)
+       if ((info = get_samr_info_by_sid(p->mem_ctx, &sid)) == NULL)
                return NT_STATUS_NO_MEMORY;
 
        info->acc_granted = acc_granted;
 
        /* get a (unique) handle.  open a policy on it. */
-       if (!create_policy_hnd(p, alias_pol, free_samr_info, (void *)info))
+       if (!create_policy_hnd(p, alias_pol, info))
                return NT_STATUS_OBJECT_NAME_NOT_FOUND;
 
        return NT_STATUS_OK;
@@ -3699,29 +3598,62 @@ static bool set_user_info_16(struct samr_UserInfo16 *id16,
  set_user_info_18
  ********************************************************************/
 
-static bool set_user_info_18(struct samr_UserInfo18 *id18,
-                            struct samu *pwd)
+static NTSTATUS set_user_info_18(struct samr_UserInfo18 *id18,
+                                TALLOC_CTX *mem_ctx,
+                                DATA_BLOB *session_key,
+                                struct samu *pwd)
 {
        if (id18 == NULL) {
                DEBUG(2, ("set_user_info_18: id18 is NULL\n"));
-               return False;
+               return NT_STATUS_INVALID_PARAMETER;
        }
 
-       if (!pdb_set_lanman_passwd (pwd, id18->lm_pwd.hash, PDB_CHANGED)) {
-               return False;
+       if (id18->nt_pwd_active || id18->lm_pwd_active) {
+               if (!session_key->length) {
+                       return NT_STATUS_NO_USER_SESSION_KEY;
+               }
        }
-       if (!pdb_set_nt_passwd     (pwd, id18->nt_pwd.hash, PDB_CHANGED)) {
-               return False;
+
+       if (id18->nt_pwd_active) {
+
+               DATA_BLOB in, out;
+
+               in = data_blob_const(id18->nt_pwd.hash, 16);
+               out = data_blob_talloc_zero(mem_ctx, 16);
+
+               sess_crypt_blob(&out, &in, session_key, false);
+
+               if (!pdb_set_nt_passwd(pwd, out.data, PDB_CHANGED)) {
+                       return NT_STATUS_ACCESS_DENIED;
+               }
+
+               pdb_set_pass_last_set_time(pwd, time(NULL), PDB_CHANGED);
        }
-       if (!pdb_set_pass_last_set_time (pwd, time(NULL), PDB_CHANGED)) {
-               return False;
+
+       if (id18->lm_pwd_active) {
+
+               DATA_BLOB in, out;
+
+               in = data_blob_const(id18->lm_pwd.hash, 16);
+               out = data_blob_talloc_zero(mem_ctx, 16);
+
+               sess_crypt_blob(&out, &in, session_key, false);
+
+               if (!pdb_set_lanman_passwd(pwd, out.data, PDB_CHANGED)) {
+                       return NT_STATUS_ACCESS_DENIED;
+               }
+
+               pdb_set_pass_last_set_time(pwd, time(NULL), PDB_CHANGED);
        }
 
-       if(!NT_STATUS_IS_OK(pdb_update_sam_account(pwd))) {
-               return False;
-       }
+       if (id18->password_expired) {
+               pdb_set_pass_last_set_time(pwd, 0, PDB_CHANGED);
+       } else {
+               /* FIXME */
+               pdb_set_pass_last_set_time(pwd, time(NULL), PDB_CHANGED);
+       }
 
-       return True;
+       return pdb_update_sam_account(pwd);
 }
 
 /*******************************************************************
@@ -3856,8 +3788,8 @@ static NTSTATUS set_user_info_23(TALLOC_CTX *mem_ctx,
                return NT_STATUS_ACCESS_DENIED;
        }
 
-       if ((id23->info.fields_present & SAMR_FIELD_PASSWORD) ||
-           (id23->info.fields_present & SAMR_FIELD_PASSWORD2)) {
+       if ((id23->info.fields_present & SAMR_FIELD_NT_PASSWORD_PRESENT) ||
+           (id23->info.fields_present & SAMR_FIELD_LM_PASSWORD_PRESENT)) {
 
                DEBUG(5, ("Attempting administrator password change (level 23) for user %s\n",
                          pdb_get_username(pwd)));
@@ -4178,9 +4110,10 @@ NTSTATUS _samr_SetUserInfo(pipes_struct *p,
 
                case 18:
                        /* Used by AS/U JRA. */
-                       if (!set_user_info_18(&info->info18, pwd)) {
-                               status = NT_STATUS_ACCESS_DENIED;
-                       }
+                       status = set_user_info_18(&info->info18,
+                                                 p->mem_ctx,
+                                                 &p->server_info->user_session_key,
+                                                 pwd);
                        break;
 
                case 20:
@@ -5007,7 +4940,7 @@ NTSTATUS _samr_CreateDomainGroup(pipes_struct *p,
 
        sid_compose(&info_sid, get_global_sam_sid(), *r->out.rid);
 
-       if ((info = get_samr_info_by_sid(&info_sid)) == NULL)
+       if ((info = get_samr_info_by_sid(p->mem_ctx, &info_sid)) == NULL)
                return NT_STATUS_NO_MEMORY;
 
        /* they created it; let the user do what he wants with it */
@@ -5015,7 +4948,7 @@ NTSTATUS _samr_CreateDomainGroup(pipes_struct *p,
        info->acc_granted = GENERIC_RIGHTS_GROUP_ALL_ACCESS;
 
        /* get a (unique) handle.  open a policy on it. */
-       if (!create_policy_hnd(p, r->out.group_handle, free_samr_info, (void *)info))
+       if (!create_policy_hnd(p, r->out.group_handle, info))
                return NT_STATUS_OBJECT_NAME_NOT_FOUND;
 
        force_flush_samr_cache(disp_info);
@@ -5099,7 +5032,7 @@ NTSTATUS _samr_CreateDomAlias(pipes_struct *p,
                return NT_STATUS_ACCESS_DENIED;
        }
 
-       if ((info = get_samr_info_by_sid(&info_sid)) == NULL)
+       if ((info = get_samr_info_by_sid(p->mem_ctx, &info_sid)) == NULL)
                return NT_STATUS_NO_MEMORY;
 
        /* they created it; let the user do what he wants with it */
@@ -5107,7 +5040,7 @@ NTSTATUS _samr_CreateDomAlias(pipes_struct *p,
        info->acc_granted = GENERIC_RIGHTS_ALIAS_ALL_ACCESS;
 
        /* get a (unique) handle.  open a policy on it. */
-       if (!create_policy_hnd(p, r->out.alias_handle, free_samr_info, (void *)info))
+       if (!create_policy_hnd(p, r->out.alias_handle, info))
                return NT_STATUS_OBJECT_NAME_NOT_FOUND;
 
        force_flush_samr_cache(disp_info);
@@ -5173,24 +5106,20 @@ NTSTATUS _samr_QueryGroupInfo(pipes_struct *p,
                                return status;
                        }
 
-                       init_samr_group_info1(&info->all,
-                                             group_name,
-                                             attributes,
-                                             num_members,
-                                             group_description);
+                       info->all.name.string           = group_name;
+                       info->all.attributes            = attributes;
+                       info->all.num_members           = num_members;
+                       info->all.description.string    = group_description;
                        break;
                }
                case 2:
-                       init_samr_group_info2(&info->name,
-                                             group_name);
+                       info->name.string = group_name;
                        break;
                case 3:
-                       init_samr_group_info3(&info->attributes,
-                                             attributes);
+                       info->attributes.attributes = attributes;
                        break;
                case 4:
-                       init_samr_group_info4(&info->description,
-                                             group_description);
+                       info->description.string = group_description;
                        break;
                case 5: {
                        /*
@@ -5208,11 +5137,10 @@ NTSTATUS _samr_QueryGroupInfo(pipes_struct *p,
                                return status;
                        }
                        */
-                       init_samr_group_info5(&info->all2,
-                                             group_name,
-                                             attributes,
-                                             0, /* num_members - in w2k3 this is always 0 */
-                                             group_description);
+                       info->all2.name.string          = group_name;
+                       info->all2.attributes           = attributes;
+                       info->all2.num_members          = 0; /* num_members - in w2k3 this is always 0 */
+                       info->all2.description.string   = group_description;
 
                        break;
                }
@@ -5483,7 +5411,7 @@ NTSTATUS _samr_OpenGroup(pipes_struct *p,
        sid_append_rid(&info_sid, r->in.rid);
        sid_to_fstring(sid_string, &info_sid);
 
-       if ((info = get_samr_info_by_sid(&info_sid)) == NULL)
+       if ((info = get_samr_info_by_sid(p->mem_ctx, &info_sid)) == NULL)
                return NT_STATUS_NO_MEMORY;
 
        info->acc_granted = acc_granted;
@@ -5498,7 +5426,7 @@ NTSTATUS _samr_OpenGroup(pipes_struct *p,
                return NT_STATUS_NO_SUCH_GROUP;
 
        /* get a (unique) handle.  open a policy on it. */
-       if (!create_policy_hnd(p, r->out.group_handle, free_samr_info, (void *)info))
+       if (!create_policy_hnd(p, r->out.group_handle, info))
                return NT_STATUS_OBJECT_NAME_NOT_FOUND;
 
        return NT_STATUS_OK;