[GLUE] Rsync SAMBA_3_2_0 SVN r25598 in order to create the v3-2-test branch.
[samba.git] / source / rpc_parse / parse_samr.c
index 58ba3e8689954c8008a4eb4bbcc4598259588240..407aae66e373076d0f3b6a5c126f434d04276c4f 100644 (file)
@@ -6,12 +6,12 @@
  *  Copyright (C) Paul Ashton                  1997-2000,
  *  Copyright (C) Elrond                            2000,
  *  Copyright (C) Jeremy Allison                    2001,
- *  Copyright (C) Jean François Micouleau      1998-2001,
+ *  Copyright (C) Jean François Micouleau      1998-2001,
  *  Copyright (C) Jim McDonough <jmcd@us.ibm.com>   2002.
  *  
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; either version 2 of the License, or
+ *  the Free Software Foundation; either version 3 of the License, or
  *  (at your option) any later version.
  *  
  *  This program is distributed in the hope that it will be useful,
@@ -20,8 +20,7 @@
  *  GNU General Public License for more details.
  *  
  *  You should have received a copy of the GNU General Public License
- *  along with this program; if not, write to the Free Software
- *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *  along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
 #include "includes.h"
@@ -557,7 +556,7 @@ void init_unk_info2(SAM_UNK_INFO_2 * u_2,
 
        u_2->seq_num = seq_num;
 
-
+       
        u_2->unknown_4 = 0x00000001;
        u_2->server_role = server_role;
        u_2->unknown_6 = 0x00000001;
@@ -3328,7 +3327,7 @@ BOOL samr_io_r_enum_domains(const char *desc, SAMR_R_ENUM_DOMAINS * r_u,
                if(!prs_uint32("num_entries3", ps, depth, &r_u->num_entries3))
                        return False;
 
-               if (UNMARSHALLING(ps)) {
+               if (UNMARSHALLING(ps) && r_u->num_entries2) {
                        r_u->sam = PRS_ALLOC_MEM(ps,SAM_ENTRY,r_u->num_entries2);
                        r_u->uni_dom_name = PRS_ALLOC_MEM(ps,UNISTR2,r_u->num_entries2);
                }
@@ -3467,7 +3466,7 @@ BOOL samr_io_r_enum_dom_groups(const char *desc, SAMR_R_ENUM_DOM_GROUPS * r_u,
                if(!prs_uint32("num_entries3", ps, depth, &r_u->num_entries3))
                        return False;
 
-               if (UNMARSHALLING(ps)) {
+               if (UNMARSHALLING(ps) && r_u->num_entries2) {
                        r_u->sam = PRS_ALLOC_MEM(ps,SAM_ENTRY,r_u->num_entries2);
                        r_u->uni_grp_name = PRS_ALLOC_MEM(ps,UNISTR2,r_u->num_entries2);
                }
@@ -4175,7 +4174,11 @@ void init_samr_q_lookup_rids(TALLOC_CTX *ctx, SAMR_Q_LOOKUP_RIDS * q_u,
        q_u->flags = flags;
        q_u->ptr = 0;
        q_u->num_rids2 = num_rids;
-       q_u->rid = TALLOC_ZERO_ARRAY(ctx, uint32, num_rids );
+       if (num_rids) {
+               q_u->rid = TALLOC_ZERO_ARRAY(ctx, uint32, num_rids );
+       } else {
+               q_u->rid = NULL;
+       }
        if (q_u->rid == NULL) {
                q_u->num_rids1 = 0;
                q_u->num_rids2 = 0;
@@ -4764,9 +4767,14 @@ BOOL samr_io_r_query_aliasmem(const char *desc, SAMR_R_QUERY_ALIASMEM * r_u,
                if(!prs_uint32("num_sids1", ps, depth, &r_u->num_sids1))
                        return False;
 
-               ptr_sid = TALLOC_ARRAY(ps->mem_ctx, uint32, r_u->num_sids1);
-               if (!ptr_sid) {
-                       return False;
+               /* We must always use talloc here even when marshalling. */
+               if (r_u->num_sids1) {
+                       ptr_sid = TALLOC_ARRAY(ps->mem_ctx, uint32, r_u->num_sids1);
+                       if (!ptr_sid) {
+                               return False;
+                       }
+               } else {
+                       ptr_sid = NULL;
                }
                
                for (i = 0; i < r_u->num_sids1; i++) {
@@ -4776,7 +4784,14 @@ BOOL samr_io_r_query_aliasmem(const char *desc, SAMR_R_QUERY_ALIASMEM * r_u,
                }
                
                if (UNMARSHALLING(ps)) {
-                       r_u->sid = TALLOC_ARRAY(ps->mem_ctx, DOM_SID2, r_u->num_sids1);
+                       if (r_u->num_sids1) {
+                               r_u->sid = TALLOC_ARRAY(ps->mem_ctx, DOM_SID2, r_u->num_sids1);
+                               if (!r_u->sid) {
+                                       return False;
+                               }
+                       } else {
+                               r_u->sid = NULL;
+                       }
                }
                
                for (i = 0; i < r_u->num_sids1; i++) {
@@ -4814,11 +4829,16 @@ NTSTATUS init_samr_q_lookup_names(TALLOC_CTX *ctx, SAMR_Q_LOOKUP_NAMES * q_u,
        q_u->ptr = 0;
        q_u->num_names2 = num_names;
 
-       if (!(q_u->hdr_name = TALLOC_ZERO_ARRAY(ctx, UNIHDR, num_names)))
-               return NT_STATUS_NO_MEMORY;
+       if (num_names) {
+               if (!(q_u->hdr_name = TALLOC_ZERO_ARRAY(ctx, UNIHDR, num_names)))
+                       return NT_STATUS_NO_MEMORY;
 
-       if (!(q_u->uni_name = TALLOC_ZERO_ARRAY(ctx, UNISTR2, num_names)))
-               return NT_STATUS_NO_MEMORY;
+               if (!(q_u->uni_name = TALLOC_ZERO_ARRAY(ctx, UNISTR2, num_names)))
+                       return NT_STATUS_NO_MEMORY;
+       } else {
+               q_u->hdr_name = NULL;
+               q_u->uni_name = NULL;
+       }
 
        for (i = 0; i < num_names; i++) {
                init_unistr2(&q_u->uni_name[i], name[i], UNI_FLAGS_NONE);       /* unicode string for machine account */
@@ -4908,16 +4928,12 @@ NTSTATUS init_samr_r_lookup_names(TALLOC_CTX *ctx, SAMR_R_LOOKUP_NAMES * r_u,
                if (!(r_u->types = TALLOC_ZERO_ARRAY(ctx, uint32, num_rids)))
                        return NT_STATUS_NO_MEMORY;
 
-               if (!r_u->rids || !r_u->types)
-                       goto empty;
-
                for (i = 0; i < num_rids; i++) {
                        r_u->rids[i] = rid[i];
                        r_u->types[i] = type[i];
                }
        } else {
 
-  empty:
                r_u->num_types1 = 0;
                r_u->ptr_types = 0;
                r_u->num_types2 = 0;
@@ -4971,12 +4987,13 @@ BOOL samr_io_r_lookup_names(const char *desc, SAMR_R_LOOKUP_NAMES * r_u,
                        return False;
                }
 
-               if (UNMARSHALLING(ps))
+               if (UNMARSHALLING(ps) && r_u->num_rids2) {
                        r_u->rids = PRS_ALLOC_MEM(ps, uint32, r_u->num_rids2);
 
-               if (!r_u->rids) {
-                       DEBUG(0, ("NULL rids in samr_io_r_lookup_names\n"));
-                       return False;
+                       if (!r_u->rids) {
+                               DEBUG(0, ("NULL rids in samr_io_r_lookup_names\n"));
+                               return False;
+                       }
                }
 
                for (i = 0; i < r_u->num_rids2; i++) {
@@ -5000,12 +5017,13 @@ BOOL samr_io_r_lookup_names(const char *desc, SAMR_R_LOOKUP_NAMES * r_u,
                        return False;
                }
 
-               if (UNMARSHALLING(ps))
+               if (UNMARSHALLING(ps) && r_u->num_types2) {
                        r_u->types = PRS_ALLOC_MEM(ps, uint32, r_u->num_types2);
 
-               if (!r_u->types) {
-                       DEBUG(0, ("NULL types in samr_io_r_lookup_names\n"));
-                       return False;
+                       if (!r_u->types) {
+                               DEBUG(0, ("NULL types in samr_io_r_lookup_names\n"));
+                               return False;
+                       }
                }
 
                for (i = 0; i < r_u->num_types2; i++) {
@@ -5842,6 +5860,25 @@ void init_sam_user_info23A(SAM_USER_INFO_23 * usr, NTTIME * logon_time,  /* all z
        }
 }
 
+
+/*************************************************************************
+ init_samr_user_info25P
+ fields_present = ACCT_NT_PWD_SET | ACCT_LM_PWD_SET | ACCT_FLAGS
+*************************************************************************/
+
+void init_sam_user_info25P(SAM_USER_INFO_25 * usr,
+                          uint32 fields_present, uint32 acb_info,
+                          char newpass[532])
+{
+       usr->fields_present = fields_present;
+       ZERO_STRUCT(usr->padding1);
+       ZERO_STRUCT(usr->padding2);
+
+       usr->acb_info = acb_info;
+       memcpy(usr->pass, newpass, sizeof(usr->pass));
+}
+
+
 /*******************************************************************
 reads or writes a structure.
 ********************************************************************/
@@ -6036,9 +6073,26 @@ static BOOL sam_io_user_info25(const char *desc, SAM_USER_INFO_25 * usr, prs_str
        if(!prs_uint32("fields_present ", ps, depth, &usr->fields_present))
                return False;
 
-       if(!prs_uint32s(False, "unknown_5      ", ps, depth, usr->unknown_5, 5))
+       if(!prs_uint16("logon_divs    ", ps, depth, &usr->logon_divs))  /* logon divisions per week */
+               return False;
+       if(!prs_align(ps))
+               return False;
+       if(!prs_uint32("ptr_logon_hrs ", ps, depth, &usr->ptr_logon_hrs))
+               return False;
+
+       if(!prs_uint16("bad_password_count     ", ps, depth, &usr->bad_password_count))
+               return False;
+       if(!prs_uint16("logon_count     ", ps, depth, &usr->logon_count))
+               return False;
+
+       if(!prs_uint8s(False, "padding1      ", ps, depth, usr->padding1, sizeof(usr->padding1)))
+               return False;
+       if(!prs_uint8("passmustchange ", ps, depth, &usr->passmustchange))
+               return False;
+       if(!prs_uint8("padding2       ", ps, depth, &usr->padding2))
                return False;
 
+
        if(!prs_uint8s(False, "password      ", ps, depth, usr->pass, sizeof(usr->pass)))
                return False;
 
@@ -6074,13 +6128,11 @@ static BOOL sam_io_user_info25(const char *desc, SAM_USER_INFO_25 * usr, prs_str
        if(!smb_io_unistr2("uni_munged_dial ", &usr->uni_munged_dial, usr->hdr_munged_dial.buffer, ps, depth))
                return False;
 
-#if 0 /* JRA - unknown... */
        /* ok, this is only guess-work (as usual) */
        if (usr->ptr_logon_hrs) {
                if(!sam_io_logon_hrs("logon_hrs", &usr->logon_hrs, ps, depth))
                        return False;
        } 
-#endif
 
        return True;
 }
@@ -6200,6 +6252,7 @@ NTSTATUS init_sam_user_info21A(SAM_USER_INFO_21 *usr, struct samu *pw, DOM_SID *
                        pass_last_set_time, pass_can_change_time,
                        pass_must_change_time;
                        
+       time_t must_change_time;
        const char*             user_name = pdb_get_username(pw);
        const char*             full_name = pdb_get_fullname(pw);
        const char*             home_dir  = pdb_get_homedir(pw);
@@ -6220,16 +6273,20 @@ NTSTATUS init_sam_user_info21A(SAM_USER_INFO_21 *usr, struct samu *pw, DOM_SID *
        if (munged_dial) {
                munged_dial_blob = base64_decode_data_blob(munged_dial);
        } else {
-               munged_dial_blob = data_blob(NULL, 0);
+               munged_dial_blob = data_blob_null;
        }
 
        /* Create NTTIME structs */
-       unix_to_nt_time (&logon_time,           pdb_get_logon_time(pw));
-       unix_to_nt_time (&logoff_time,          pdb_get_logoff_time(pw));
+       unix_to_nt_time (&logon_time,           pdb_get_logon_time(pw));
+       unix_to_nt_time (&logoff_time,  pdb_get_logoff_time(pw));
        unix_to_nt_time (&kickoff_time,         pdb_get_kickoff_time(pw));
-       unix_to_nt_time (&pass_last_set_time,   pdb_get_pass_last_set_time(pw));
-       unix_to_nt_time (&pass_can_change_time, pdb_get_pass_can_change_time(pw));
-       unix_to_nt_time (&pass_must_change_time,pdb_get_pass_must_change_time(pw));
+       unix_to_nt_time (&pass_last_set_time, pdb_get_pass_last_set_time(pw));
+       unix_to_nt_time (&pass_can_change_time,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())
+               unix_to_nt_time_abs(&pass_must_change_time, must_change_time);
+       else
+               unix_to_nt_time(&pass_must_change_time, must_change_time);
        
        /* structure assignment */
        usr->logon_time            = logon_time;
@@ -6256,8 +6313,10 @@ NTSTATUS init_sam_user_info21A(SAM_USER_INFO_21 *usr, struct samu *pw, DOM_SID *
                return NT_STATUS_UNSUCCESSFUL;
        }
 
+       become_root();  
        group_sid = pdb_get_group_sid(pw);
-       
+       unbecome_root();
+
        if (!sid_peek_check_rid(domain_sid, group_sid, &group_rid)) {
                fstring group_sid_string;
                fstring domain_sid_string;
@@ -6468,7 +6527,7 @@ void init_sam_user_info20A(SAM_USER_INFO_20 *usr, struct samu *pw)
        if (munged_dial) {
                blob = base64_decode_data_blob(munged_dial);
        } else {
-               blob = data_blob(NULL, 0);
+               blob = data_blob_null;
        }
 
        init_unistr2_from_datablob(&usr->uni_munged_dial, &blob);
@@ -6584,13 +6643,13 @@ static void init_samr_userinfo_ctr(SAM_USERINFO_CTR * ctr, DATA_BLOB *sess_key,
        switch (switch_value) {
        case 0x18:
                SamOEMhashBlob(ctr->info.id24->pass, 516, sess_key);
-               dump_data(100, (char *)sess_key->data, sess_key->length);
-               dump_data(100, (char *)ctr->info.id24->pass, 516);
+               dump_data(100, sess_key->data, sess_key->length);
+               dump_data(100, ctr->info.id24->pass, 516);
                break;
        case 0x17:
                SamOEMhashBlob(ctr->info.id23->pass, 516, sess_key);
-               dump_data(100, (char *)sess_key->data, sess_key->length);
-               dump_data(100, (char *)ctr->info.id23->pass, 516);
+               dump_data(100, sess_key->data, sess_key->length);
+               dump_data(100, ctr->info.id23->pass, 516);
                break;
        case 0x07:
                break;
@@ -6893,9 +6952,9 @@ void init_samr_q_set_userinfo2(SAMR_Q_SET_USERINFO2 * q_u,
        case 18:
                SamOEMhashBlob(ctr->info.id18->lm_pwd, 16, sess_key);
                SamOEMhashBlob(ctr->info.id18->nt_pwd, 16, sess_key);
-               dump_data(100, (char *)sess_key->data, sess_key->length);
-               dump_data(100, (char *)ctr->info.id18->lm_pwd, 16);
-               dump_data(100, (char *)ctr->info.id18->nt_pwd, 16);
+               dump_data(100, sess_key->data, sess_key->length);
+               dump_data(100, ctr->info.id18->lm_pwd, 16);
+               dump_data(100, ctr->info.id18->nt_pwd, 16);
                break;
        }
 }
@@ -7705,6 +7764,14 @@ BOOL samr_io_r_chgpasswd_user3(const char *desc, SAMR_R_CHGPASSWD_USER3 *r_u,
        if (!prs_uint32("ptr_info", ps, depth, &r_u->ptr_info))
                return False;
 
+       /* special case: Windows 2000 can return stub data here saying
+          NT_STATUS_NOT_SUPPORTED */
+
+       if ( NT_STATUS_EQUAL( NT_STATUS_NOT_SUPPORTED, NT_STATUS(r_u->ptr_info)) ) {
+               r_u->status = NT_STATUS_NOT_SUPPORTED;
+               return True;
+       }
+
        if (r_u->ptr_info && r_u->info != NULL) {
                /* SAM_UNK_INFO_1 */
                if (!sam_io_unk_info1("info", r_u->info, ps, depth))