RIP BOOL. Convert BOOL -> bool. I found a few interesting
[kai/samba.git] / source3 / rpcclient / cmd_samr.c
index ca0b6e9624579484a0f4c5a9a4f825c5b036acae..931baf3534341059735e75ac5661367f3cc7ae9d 100644 (file)
@@ -9,7 +9,7 @@
 
    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,
@@ -18,8 +18,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"
@@ -34,7 +33,7 @@ static void display_sam_user_info_7(SAM_USER_INFO_7 *usr)
 {
        fstring temp;
 
-       unistr2_to_ascii(temp, &usr->uni_name, sizeof(temp)-1);
+       unistr2_to_ascii(temp, &usr->uni_name, sizeof(temp));
        printf("\tUser Name   :\t%s\n", temp);
 }
 
@@ -46,6 +45,14 @@ static void display_sam_user_info_9(SAM_USER_INFO_9 *usr)
        printf("\tPrimary group RID   :\tox%x\n", usr->rid_group);
 }
 
+/****************************************************************************
+ display sam_user_info_16 structure
+ ****************************************************************************/
+static void display_sam_user_info_16(SAM_USER_INFO_16 *usr)
+{
+       printf("\tAcct Flags   :\tox%x\n", usr->acb_info);
+}
+
 /****************************************************************************
  display sam_user_info_21 structure
  ****************************************************************************/
@@ -53,48 +60,48 @@ static void display_sam_user_info_21(SAM_USER_INFO_21 *usr)
 {
        fstring temp;
 
-       unistr2_to_ascii(temp, &usr->uni_user_name, sizeof(temp)-1);
+       unistr2_to_ascii(temp, &usr->uni_user_name, sizeof(temp));
        printf("\tUser Name   :\t%s\n", temp);
        
-       unistr2_to_ascii(temp, &usr->uni_full_name, sizeof(temp)-1);
+       unistr2_to_ascii(temp, &usr->uni_full_name, sizeof(temp));
        printf("\tFull Name   :\t%s\n", temp);
        
-       unistr2_to_ascii(temp, &usr->uni_home_dir, sizeof(temp)-1);
+       unistr2_to_ascii(temp, &usr->uni_home_dir, sizeof(temp));
        printf("\tHome Drive  :\t%s\n", temp);
        
-       unistr2_to_ascii(temp, &usr->uni_dir_drive, sizeof(temp)-1);
+       unistr2_to_ascii(temp, &usr->uni_dir_drive, sizeof(temp));
        printf("\tDir Drive   :\t%s\n", temp);
        
-       unistr2_to_ascii(temp, &usr->uni_profile_path, sizeof(temp)-1);
+       unistr2_to_ascii(temp, &usr->uni_profile_path, sizeof(temp));
        printf("\tProfile Path:\t%s\n", temp);
        
-       unistr2_to_ascii(temp, &usr->uni_logon_script, sizeof(temp)-1);
+       unistr2_to_ascii(temp, &usr->uni_logon_script, sizeof(temp));
        printf("\tLogon Script:\t%s\n", temp);
        
-       unistr2_to_ascii(temp, &usr->uni_acct_desc, sizeof(temp)-1);
+       unistr2_to_ascii(temp, &usr->uni_acct_desc, sizeof(temp));
        printf("\tDescription :\t%s\n", temp);
        
-       unistr2_to_ascii(temp, &usr->uni_workstations, sizeof(temp)-1);
+       unistr2_to_ascii(temp, &usr->uni_workstations, sizeof(temp));
        printf("\tWorkstations:\t%s\n", temp);
        
-       unistr2_to_ascii(temp, &usr->uni_unknown_str, sizeof(temp)-1);
+       unistr2_to_ascii(temp, &usr->uni_comment, sizeof(temp));
        printf("\tUnknown Str :\t%s\n", temp);
        
-       unistr2_to_ascii(temp, &usr->uni_munged_dial, sizeof(temp)-1);
+       unistr2_to_ascii(temp, &usr->uni_munged_dial, sizeof(temp));
        printf("\tRemote Dial :\t%s\n", temp);
        
        printf("\tLogon Time               :\t%s\n", 
-              http_timestring(nt_time_to_unix(&usr->logon_time)));
+              http_timestring(nt_time_to_unix(usr->logon_time)));
        printf("\tLogoff Time              :\t%s\n", 
-              http_timestring(nt_time_to_unix(&usr->logoff_time)));
+              http_timestring(nt_time_to_unix(usr->logoff_time)));
        printf("\tKickoff Time             :\t%s\n", 
-              http_timestring(nt_time_to_unix(&usr->kickoff_time)));
+              http_timestring(nt_time_to_unix(usr->kickoff_time)));
        printf("\tPassword last set Time   :\t%s\n", 
-              http_timestring(nt_time_to_unix(&usr->pass_last_set_time)));
+              http_timestring(nt_time_to_unix(usr->pass_last_set_time)));
        printf("\tPassword can change Time :\t%s\n", 
-              http_timestring(nt_time_to_unix(&usr->pass_can_change_time)));
+              http_timestring(nt_time_to_unix(usr->pass_can_change_time)));
        printf("\tPassword must change Time:\t%s\n", 
-              http_timestring(nt_time_to_unix(&usr->pass_must_change_time)));
+              http_timestring(nt_time_to_unix(usr->pass_must_change_time)));
        
        printf("\tunknown_2[0..31]...\n"); /* user passwords? */
        
@@ -114,40 +121,6 @@ static void display_sam_user_info_21(SAM_USER_INFO_21 *usr)
        }
 }
 
-static const char *display_time(NTTIME nttime)
-{
-       static fstring string;
-
-       float high;
-       float low;
-       int sec;
-       int days, hours, mins, secs;
-
-       if (nttime.high==0 && nttime.low==0)
-               return "Now";
-
-       if (nttime.high==0x80000000 && nttime.low==0)
-               return "Never";
-
-       high = 65536;   
-       high = high/10000;
-       high = high*65536;
-       high = high/1000;
-       high = high * (~nttime.high);
-
-       low = ~nttime.low;      
-       low = low/(1000*1000*10);
-
-       sec=high+low;
-
-       days=sec/(60*60*24);
-       hours=(sec - (days*60*60*24)) / (60*60);
-       mins=(sec - (days*60*60*24) - (hours*60*60) ) / 60;
-       secs=sec - (days*60*60*24) - (hours*60*60) - (mins*60);
-
-       fstr_sprintf(string, "%u days, %u hours, %u minutes, %u seconds", days, hours, mins, secs);
-       return (string);
-}
 
 static void display_password_properties(uint32 password_properties) 
 {
@@ -186,20 +159,20 @@ static void display_sam_unk_info_2(SAM_UNK_INFO_2 *info2)
 {
        fstring name;
 
-       unistr2_to_ascii(name, &info2->uni_domain, sizeof(name) - 1); 
+       unistr2_to_ascii(name, &info2->uni_domain, sizeof(name));
        printf("Domain:\t\t%s\n", name);
 
-       unistr2_to_ascii(name, &info2->uni_server, sizeof(name) - 1); 
+       unistr2_to_ascii(name, &info2->uni_server, sizeof(name));
        printf("Server:\t\t%s\n", name);
 
-       unistr2_to_ascii(name, &info2->uni_comment, sizeof(name) - 1); 
+       unistr2_to_ascii(name, &info2->uni_comment, sizeof(name));
        printf("Comment:\t%s\n", name);
 
        printf("Total Users:\t%d\n", info2->num_domain_usrs);
        printf("Total Groups:\t%d\n", info2->num_domain_grps);
        printf("Total Aliases:\t%d\n", info2->num_local_grps);
        
-       printf("Sequence No:\t%d\n", info2->seq_num.low);
+       printf("Sequence No:\t%llu\n", (unsigned long long)info2->seq_num);
 
        printf("Force Logoff:\t%d\n", (int)nt_time_to_unix_abs(&info2->logout));
 
@@ -208,6 +181,35 @@ static void display_sam_unk_info_2(SAM_UNK_INFO_2 *info2)
        printf("Unknown 6:\t0x%x\n", info2->unknown_6);
 }
 
+static void display_sam_unk_info_3(SAM_UNK_INFO_3 *info3)
+{
+       printf("Force Logoff:\t%d\n", (int)nt_time_to_unix_abs(&info3->logout));
+}
+
+static void display_sam_unk_info_4(SAM_UNK_INFO_4 *info4)
+{
+       fstring name;
+
+       unistr2_to_ascii(name, &info4->uni_comment, sizeof(name));
+       printf("Comment:\t%s\n", name);
+}
+
+static void display_sam_unk_info_5(SAM_UNK_INFO_5 *info5)
+{
+       fstring name;
+
+       unistr2_to_ascii(name, &info5->uni_domain, sizeof(name));
+       printf("Domain:\t\t%s\n", name);
+}
+
+static void display_sam_unk_info_6(SAM_UNK_INFO_6 *info6)
+{
+       fstring name;
+
+       unistr2_to_ascii(name, &info6->uni_server, sizeof(name));
+       printf("Server:\t\t%s\n", name);
+}
+
 static void display_sam_unk_info_7(SAM_UNK_INFO_7 *info7)
 {
        printf("Server Role:\t%s\n", server_role_str(info7->server_role));
@@ -215,10 +217,14 @@ static void display_sam_unk_info_7(SAM_UNK_INFO_7 *info7)
 
 static void display_sam_unk_info_8(SAM_UNK_INFO_8 *info8)
 {
-       printf("Sequence No:\t%d\n", info8->seq_num.low);
+       printf("Sequence No:\t%llu\n", (unsigned long long)info8->seq_num);
        printf("Domain Create Time:\t%s\n", 
-               http_timestring(nt_time_to_unix(&info8->domain_create_time)));
+               http_timestring(nt_time_to_unix(info8->domain_create_time)));
+}
 
+static void display_sam_unk_info_9(SAM_UNK_INFO_9 *info9)
+{
+       printf("unknown:\t%d (0x%08x)\n", info9->unknown, info9->unknown);
 }
 
 static void display_sam_unk_info_12(SAM_UNK_INFO_12 *info12)
@@ -228,6 +234,16 @@ static void display_sam_unk_info_12(SAM_UNK_INFO_12 *info12)
        printf("Lockout after bad attempts:                  %d\n", info12->bad_attempt_lockout);
 }
 
+static void display_sam_unk_info_13(SAM_UNK_INFO_13 *info13)
+{
+       printf("Sequence No:\t%llu\n", (unsigned long long)info13->seq_num);
+       printf("Domain Create Time:\t%s\n", 
+               http_timestring(nt_time_to_unix(info13->domain_create_time)));
+       printf("Unknown1:\t%d\n", info13->unknown1);
+       printf("Unknown2:\t%d\n", info13->unknown2);
+
+}
+
 static void display_sam_info_1(SAM_ENTRY1 *e1, SAM_STR1 *s1)
 {
        fstring tmp;
@@ -236,13 +252,13 @@ static void display_sam_info_1(SAM_ENTRY1 *e1, SAM_STR1 *s1)
        printf("RID: 0x%x ", e1->rid_user);
        printf("acb: 0x%x ", e1->acb_info);
 
-       unistr2_to_ascii(tmp, &s1->uni_acct_name, sizeof(tmp)-1);
+       unistr2_to_ascii(tmp, &s1->uni_acct_name, sizeof(tmp));
        printf("Account: %s\t", tmp);
 
-       unistr2_to_ascii(tmp, &s1->uni_full_name, sizeof(tmp)-1);
+       unistr2_to_ascii(tmp, &s1->uni_full_name, sizeof(tmp));
        printf("Name: %s\t", tmp);
 
-       unistr2_to_ascii(tmp, &s1->uni_acct_desc, sizeof(tmp)-1);
+       unistr2_to_ascii(tmp, &s1->uni_acct_desc, sizeof(tmp));
        printf("Desc: %s\n", tmp);
 }
 
@@ -254,10 +270,10 @@ static void display_sam_info_2(SAM_ENTRY2 *e2, SAM_STR2 *s2)
        printf("RID: 0x%x ", e2->rid_user);
        printf("acb: 0x%x ", e2->acb_info);
        
-       unistr2_to_ascii(tmp, &s2->uni_srv_name, sizeof(tmp)-1);
+       unistr2_to_ascii(tmp, &s2->uni_srv_name, sizeof(tmp));
        printf("Account: %s\t", tmp);
 
-       unistr2_to_ascii(tmp, &s2->uni_srv_desc, sizeof(tmp)-1);
+       unistr2_to_ascii(tmp, &s2->uni_srv_desc, sizeof(tmp));
        printf("Name: %s\n", tmp);
 
 }
@@ -270,10 +286,10 @@ static void display_sam_info_3(SAM_ENTRY3 *e3, SAM_STR3 *s3)
        printf("RID: 0x%x ", e3->rid_grp);
        printf("attr: 0x%x ", e3->attr);
        
-       unistr2_to_ascii(tmp, &s3->uni_grp_name, sizeof(tmp)-1);
+       unistr2_to_ascii(tmp, &s3->uni_grp_name, sizeof(tmp));
        printf("Account: %s\t", tmp);
 
-       unistr2_to_ascii(tmp, &s3->uni_grp_desc, sizeof(tmp)-1);
+       unistr2_to_ascii(tmp, &s3->uni_grp_desc, sizeof(tmp));
        printf("Name: %s\n", tmp);
 
 }
@@ -333,14 +349,14 @@ static NTSTATUS cmd_samr_query_user(struct rpc_pipe_client *cli,
        uint32 access_mask = MAXIMUM_ALLOWED_ACCESS;
        SAM_USERINFO_CTR *user_ctr;
        fstring server;
-       uint32 user_rid;
+       uint32 user_rid = 0;
        
        if ((argc < 2) || (argc > 4)) {
                printf("Usage: %s rid [info level] [access mask] \n", argv[0]);
                return NT_STATUS_OK;
        }
        
-       user_rid = strtoul(argv[1], NULL, 10);
+       sscanf(argv[1], "%i", &user_rid);
        
        if (argc > 2)
                sscanf(argv[2], "%i", &info_level);
@@ -402,15 +418,18 @@ static NTSTATUS cmd_samr_query_user(struct rpc_pipe_client *cli,
                goto done;
 
        switch (user_ctr->switch_value) {
-       case 21:
-               display_sam_user_info_21(user_ctr->info.id21);
-               break;
        case 7:
                display_sam_user_info_7(user_ctr->info.id7);
                break;
        case 9:
                display_sam_user_info_9(user_ctr->info.id9);
                break;
+       case 16:
+               display_sam_user_info_16(user_ctr->info.id16);
+               break;
+       case 21:
+               display_sam_user_info_21(user_ctr->info.id21);
+               break;
        default:
                printf("Unsupported infolevel: %d\n", info_level);
                break;
@@ -431,9 +450,9 @@ static void display_group_info1(GROUP_INFO1 *info1)
 {
        fstring temp;
 
-       unistr2_to_ascii(temp, &info1->uni_acct_name, sizeof(temp)-1);
+       unistr2_to_ascii(temp, &info1->uni_acct_name, sizeof(temp));
        printf("\tGroup Name:\t%s\n", temp);
-       unistr2_to_ascii(temp, &info1->uni_acct_desc, sizeof(temp)-1);
+       unistr2_to_ascii(temp, &info1->uni_acct_desc, sizeof(temp));
        printf("\tDescription:\t%s\n", temp);
        printf("\tGroup Attribute:%d\n", info1->group_attr);
        printf("\tNum Members:%d\n", info1->num_members);
@@ -446,7 +465,7 @@ static void display_group_info2(GROUP_INFO2 *info2)
 {
        fstring name;
 
-       unistr2_to_ascii(name, &info2->uni_acct_name, sizeof(name)-1);
+       unistr2_to_ascii(name, &info2->uni_acct_name, sizeof(name));
        printf("\tGroup Description:%s\n", name);
 }
 
@@ -467,7 +486,7 @@ static void display_group_info4(GROUP_INFO4 *info4)
 {
        fstring desc;
 
-       unistr2_to_ascii(desc, &info4->uni_acct_desc, sizeof(desc)-1);
+       unistr2_to_ascii(desc, &info4->uni_acct_desc, sizeof(desc));
        printf("\tGroup Description:%s\n", desc);
 }
 
@@ -478,9 +497,9 @@ static void display_group_info5(GROUP_INFO5 *info5)
 {
        fstring temp;
 
-       unistr2_to_ascii(temp, &info5->uni_acct_name, sizeof(temp)-1);
+       unistr2_to_ascii(temp, &info5->uni_acct_name, sizeof(temp));
        printf("\tGroup Name:\t%s\n", temp);
-       unistr2_to_ascii(temp, &info5->uni_acct_desc, sizeof(temp)-1);
+       unistr2_to_ascii(temp, &info5->uni_acct_desc, sizeof(temp));
        printf("\tDescription:\t%s\n", temp);
        printf("\tGroup Attribute:%d\n", info5->group_attr);
        printf("\tNum Members:%d\n", info5->num_members);
@@ -675,12 +694,18 @@ static NTSTATUS cmd_samr_query_useraliases(struct rpc_pipe_client *cli,
                        printf("%s is not a legal SID\n", argv[i]);
                        return NT_STATUS_INVALID_PARAMETER;
                }
-               add_sid_to_array(mem_ctx, &tmp_sid, &sids, &num_sids);
+               if (!add_sid_to_array(mem_ctx, &tmp_sid, &sids, &num_sids)) {
+                       return NT_STATUS_NO_MEMORY;
+               }
        }
 
-       sid2 = TALLOC_ARRAY(mem_ctx, DOM_SID2, num_sids);
-       if (sid2 == NULL)
-               return NT_STATUS_NO_MEMORY;
+       if (num_sids) {
+               sid2 = TALLOC_ARRAY(mem_ctx, DOM_SID2, num_sids);
+               if (sid2 == NULL)
+                       return NT_STATUS_NO_MEMORY;
+       } else {
+               sid2 = NULL;
+       }
 
        for (i=0; i<num_sids; i++) {
                sid_copy(&sid2[i].sid, &sids[i]);
@@ -742,6 +767,7 @@ static NTSTATUS cmd_samr_query_groupmem(struct rpc_pipe_client *cli,
        uint32 access_mask = MAXIMUM_ALLOWED_ACCESS;
        int i;
        fstring                 server;
+       unsigned int old_timeout;
        
        if ((argc < 2) || (argc > 3)) {
                printf("Usage: %s rid [access mask]\n", argv[0]);
@@ -776,10 +802,15 @@ static NTSTATUS cmd_samr_query_groupmem(struct rpc_pipe_client *cli,
        if (!NT_STATUS_IS_OK(result))
                goto done;
 
+       /* Make sure to wait for our DC's reply */
+       old_timeout = cli_set_timeout(cli->cli, MAX(cli->cli->timeout,30000)); /* 30 seconds. */
+
        result = rpccli_samr_query_groupmem(cli, mem_ctx, &group_pol,
                                         &num_members, &group_rids,
                                         &group_attrs);
 
+       cli_set_timeout(cli->cli, old_timeout);
+
        if (!NT_STATUS_IS_OK(result))
                goto done;
 
@@ -808,7 +839,7 @@ static NTSTATUS cmd_samr_enum_dom_users(struct rpc_pipe_client *cli,
        uint32 *dom_rids;
        uint32 access_mask = MAXIMUM_ALLOWED_ACCESS;
        uint32 acb_mask = ACB_NORMAL;
-       BOOL got_connect_pol = False, got_domain_pol = False;
+       bool got_connect_pol = False, got_domain_pol = False;
 
        if ((argc < 1) || (argc > 3)) {
                printf("Usage: %s [access_mask] [acb_mask]\n", argv[0]);
@@ -883,7 +914,7 @@ static NTSTATUS cmd_samr_enum_dom_groups(struct rpc_pipe_client *cli,
        uint32 start_idx, size, num_dom_groups, i;
        uint32 access_mask = MAXIMUM_ALLOWED_ACCESS;
        struct acct_info *dom_groups;
-       BOOL got_connect_pol = False, got_domain_pol = False;
+       bool got_connect_pol = False, got_domain_pol = False;
 
        if ((argc < 1) || (argc > 2)) {
                printf("Usage: %s [access_mask]\n", argv[0]);
@@ -956,7 +987,7 @@ static NTSTATUS cmd_samr_enum_als_groups(struct rpc_pipe_client *cli,
        uint32 start_idx, size, num_als_groups, i;
        uint32 access_mask = MAXIMUM_ALLOWED_ACCESS;
        struct acct_info *als_groups;
-       BOOL got_connect_pol = False, got_domain_pol = False;
+       bool got_connect_pol = False, got_domain_pol = False;
 
        if ((argc < 2) || (argc > 3)) {
                printf("Usage: %s builtin|domain [access mask]\n", argv[0]);
@@ -1192,7 +1223,7 @@ static NTSTATUS cmd_samr_query_dispinfo(struct rpc_pipe_client *cli,
        SAM_DISPINFO_4 info4;
        SAM_DISPINFO_5 info5;
        int loop_count = 0;
-       BOOL got_params = False; /* Use get_query_dispinfo_params() or not? */
+       bool got_params = False; /* Use get_query_dispinfo_params() or not? */
 
        if (argc > 6) {
                printf("Usage: %s [info level] [start index] [max entries] [max size] [access mask]\n", argv[0]);
@@ -1367,15 +1398,34 @@ static NTSTATUS cmd_samr_query_dominfo(struct rpc_pipe_client *cli,
        case 2:
                display_sam_unk_info_2(&ctr.info.inf2);
                break;
+       case 3:
+               display_sam_unk_info_3(&ctr.info.inf3);
+               break;
+       case 4:
+               display_sam_unk_info_4(&ctr.info.inf4);
+               break;
+       case 5:
+               display_sam_unk_info_5(&ctr.info.inf5);
+               break;
+       case 6:
+               display_sam_unk_info_6(&ctr.info.inf6);
+               break;
        case 7:
                display_sam_unk_info_7(&ctr.info.inf7);
                break;
        case 8:
                display_sam_unk_info_8(&ctr.info.inf8);
                break;
+       case 9:
+               display_sam_unk_info_9(&ctr.info.inf9);
+               break;
        case 12:
                display_sam_unk_info_12(&ctr.info.inf12);
                break;
+       case 13:
+               display_sam_unk_info_13(&ctr.info.inf13);
+               break;
+
        default:
                printf("cannot display domain info for switch value %d\n",
                       switch_level);
@@ -1618,9 +1668,15 @@ static NTSTATUS cmd_samr_lookup_names(struct rpc_pipe_client *cli,
        /* Look up names */
 
        num_names = argc - 2;
-       names = TALLOC_ARRAY(mem_ctx, const char *, num_names);
 
-       for (i = 0; i < argc - 2; i++)
+       if ((names = TALLOC_ARRAY(mem_ctx, const char *, num_names)) == NULL) {
+               rpccli_samr_close(cli, mem_ctx, &domain_pol);
+               rpccli_samr_close(cli, mem_ctx, &connect_pol);
+               result = NT_STATUS_NO_MEMORY;
+               goto done;
+       }
+
+       for (i = 0; i < num_names; i++)
                names[i] = argv[i + 2];
 
        result = rpccli_samr_lookup_names(cli, mem_ctx, &domain_pol,
@@ -1684,7 +1740,13 @@ static NTSTATUS cmd_samr_lookup_rids(struct rpc_pipe_client *cli,
        /* Look up rids */
 
        num_rids = argc - 2;
-       rids = TALLOC_ARRAY(mem_ctx, uint32, num_rids);
+
+       if ((rids = TALLOC_ARRAY(mem_ctx, uint32, num_rids)) == NULL) {
+               rpccli_samr_close(cli, mem_ctx, &domain_pol);
+               rpccli_samr_close(cli, mem_ctx, &connect_pol);
+               result = NT_STATUS_NO_MEMORY;
+               goto done;
+       }
 
        for (i = 0; i < argc - 2; i++)
                 sscanf(argv[i + 2], "%i", &rids[i]);
@@ -1707,6 +1769,78 @@ static NTSTATUS cmd_samr_lookup_rids(struct rpc_pipe_client *cli,
        return result;
 }
 
+/* Delete domain group */
+
+static NTSTATUS cmd_samr_delete_dom_group(struct rpc_pipe_client *cli, 
+                                         TALLOC_CTX *mem_ctx,
+                                         int argc, const char **argv) 
+{
+       NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
+       POLICY_HND connect_pol, domain_pol, group_pol;
+       uint32 access_mask = MAXIMUM_ALLOWED_ACCESS;
+
+       if ((argc < 2) || (argc > 3)) {
+               printf("Usage: %s groupname\n", argv[0]);
+               return NT_STATUS_OK;
+       }
+       
+       if (argc > 2)
+                sscanf(argv[2], "%x", &access_mask);
+
+       /* Get sam policy and domain handles */
+
+       result = try_samr_connects(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS, 
+                                  &connect_pol);
+
+       if (!NT_STATUS_IS_OK(result))
+               goto done;
+
+       result = rpccli_samr_open_domain(cli, mem_ctx, &connect_pol,
+                                     MAXIMUM_ALLOWED_ACCESS,
+                                     &domain_sid, &domain_pol);
+
+       if (!NT_STATUS_IS_OK(result))
+               goto done;
+
+       /* Get handle on group */
+
+       {
+               uint32 *group_rids, num_rids, *name_types;
+               uint32 flags = 0x000003e8; /* Unknown */
+
+               result = rpccli_samr_lookup_names(cli, mem_ctx, &domain_pol,
+                                              flags, 1, (const char **)&argv[1],
+                                              &num_rids, &group_rids,
+                                              &name_types);
+
+               if (!NT_STATUS_IS_OK(result))
+                       goto done;
+
+               result = rpccli_samr_open_group(cli, mem_ctx, &domain_pol,
+                                               access_mask,
+                                               group_rids[0], &group_pol);
+
+               if (!NT_STATUS_IS_OK(result))
+                       goto done;
+       }
+
+       /* Delete user */
+
+       result = rpccli_samr_delete_dom_group(cli, mem_ctx, &group_pol);
+
+       if (!NT_STATUS_IS_OK(result))
+               goto done;
+
+       /* Display results */
+
+       rpccli_samr_close(cli, mem_ctx, &group_pol);
+       rpccli_samr_close(cli, mem_ctx, &domain_pol);
+       rpccli_samr_close(cli, mem_ctx, &connect_pol);
+
+ done:
+       return result;
+}
+
 /* Delete domain user */
 
 static NTSTATUS cmd_samr_delete_dom_user(struct rpc_pipe_client *cli, 
@@ -1793,13 +1927,14 @@ static NTSTATUS cmd_samr_query_sec_obj(struct rpc_pipe_client *cli,
        uint32 user_rid = 0;
        TALLOC_CTX *ctx = NULL;
        SEC_DESC_BUF *sec_desc_buf=NULL;
-       BOOL domain = False;
+       bool domain = False;
 
        ctx=talloc_init("cmd_samr_query_sec_obj");
        
        if ((argc < 1) || (argc > 3)) {
                printf("Usage: %s [rid|-d] [sec_info]\n", argv[0]);
                printf("\tSpecify rid for security on user, -d for security on domain\n");
+               talloc_destroy(ctx);
                return NT_STATUS_OK;
        }
        
@@ -1856,7 +1991,7 @@ static NTSTATUS cmd_samr_query_sec_obj(struct rpc_pipe_client *cli,
        if (!NT_STATUS_IS_OK(result))
                goto done;
 
-       display_sec_desc(sec_desc_buf->sec);
+       display_sec_desc(sec_desc_buf->sd);
 
        rpccli_samr_close(cli, mem_ctx, &user_pol);
        rpccli_samr_close(cli, mem_ctx, &domain_pol);
@@ -1991,6 +2126,60 @@ done:
        return result;
 }
 
+/* Change user password */
+
+static NTSTATUS cmd_samr_chgpasswd2(struct rpc_pipe_client *cli, 
+                                   TALLOC_CTX *mem_ctx,
+                                   int argc, const char **argv) 
+{
+       POLICY_HND connect_pol, domain_pol;
+       NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
+       const char *user, *oldpass, *newpass;
+       uint32 access_mask = MAXIMUM_ALLOWED_ACCESS;
+
+       if (argc < 3) {
+               printf("Usage: %s username oldpass newpass\n", argv[0]);
+               return NT_STATUS_INVALID_PARAMETER;
+       }
+
+       user = argv[1];
+       oldpass = argv[2];
+       newpass = argv[3];
+       
+       /* Get sam policy handle */
+
+       result = try_samr_connects(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS, 
+                                  &connect_pol);
+
+       if (!NT_STATUS_IS_OK(result))
+               goto done;
+
+       /* Get domain policy handle */
+
+       result = rpccli_samr_open_domain(cli, mem_ctx, &connect_pol,
+                                     access_mask,
+                                     &domain_sid, &domain_pol);
+
+       if (!NT_STATUS_IS_OK(result))
+               goto done;
+
+       /* Change user password */
+       result = rpccli_samr_chgpasswd_user(cli, mem_ctx, user, newpass, oldpass);
+
+       if (!NT_STATUS_IS_OK(result))
+               goto done;
+
+       result = rpccli_samr_close(cli, mem_ctx, &domain_pol);
+       if (!NT_STATUS_IS_OK(result)) goto done;
+
+       result = rpccli_samr_close(cli, mem_ctx, &connect_pol);
+       if (!NT_STATUS_IS_OK(result)) goto done;
+
+ done:
+       return result;
+}
+
+
 /* Change user password */
 
 static NTSTATUS cmd_samr_chgpasswd3(struct rpc_pipe_client *cli, 
@@ -2093,12 +2282,14 @@ struct cmd_set samr_commands[] = {
        { "createdomalias",     RPC_RTYPE_NTSTATUS, cmd_samr_create_dom_alias,      NULL, PI_SAMR, NULL,        "Create domain alias",     "" },
        { "samlookupnames",     RPC_RTYPE_NTSTATUS, cmd_samr_lookup_names,          NULL, PI_SAMR, NULL,        "Look up names",           "" },
        { "samlookuprids",      RPC_RTYPE_NTSTATUS, cmd_samr_lookup_rids,           NULL, PI_SAMR, NULL,        "Look up names",           "" },
+       { "deletedomgroup",     RPC_RTYPE_NTSTATUS, cmd_samr_delete_dom_group,      NULL, PI_SAMR, NULL,        "Delete domain group",     "" },
        { "deletedomuser",      RPC_RTYPE_NTSTATUS, cmd_samr_delete_dom_user,       NULL, PI_SAMR, NULL,        "Delete domain user",      "" },
        { "samquerysecobj",     RPC_RTYPE_NTSTATUS, cmd_samr_query_sec_obj,         NULL, PI_SAMR, NULL, "Query SAMR security object",   "" },
        { "getdompwinfo",       RPC_RTYPE_NTSTATUS, cmd_samr_get_dom_pwinfo,        NULL, PI_SAMR, NULL, "Retrieve domain password info", "" },
        { "getusrdompwinfo",    RPC_RTYPE_NTSTATUS, cmd_samr_get_usrdom_pwinfo,     NULL, PI_SAMR, NULL, "Retrieve user domain password info", "" },
 
        { "lookupdomain",       RPC_RTYPE_NTSTATUS, cmd_samr_lookup_domain,         NULL, PI_SAMR, NULL, "Lookup Domain Name", "" },
+       { "chgpasswd2",         RPC_RTYPE_NTSTATUS, cmd_samr_chgpasswd2,            NULL, PI_SAMR, NULL, "Change user password", "" },
        { "chgpasswd3",         RPC_RTYPE_NTSTATUS, cmd_samr_chgpasswd3,            NULL, PI_SAMR, NULL, "Change user password", "" },
        { NULL }
 };