1
0
mirror of https://github.com/samba-team/samba.git synced 2025-01-12 09:18:10 +03:00

added samuserset2 rpcclient command to test ACB_XXX bit-setting on

samr opcode 0x25.  _yet_ another failed attempt to get nt5rc2 to join
a samba domain.  what _is_ it with this stuff, dammit?
This commit is contained in:
Luke Leighton 0001-01-01 00:00:00 +00:00
parent 3df7c903c5
commit c3913f8ae2
7 changed files with 571 additions and 11 deletions

View File

@ -1874,7 +1874,7 @@ BOOL do_reg_query_key(struct cli_state *cli, uint16 fnum, POLICY_HND *hnd,
BOOL do_reg_unknown_1a(struct cli_state *cli, uint16 fnum, POLICY_HND *hnd, uint32 *unk);
BOOL do_reg_query_info(struct cli_state *cli, uint16 fnum, POLICY_HND *hnd,
const char* val_name,
uint32 *type, BUFFER2 *buf);
uint32 *type, BUFFER2 *buffer);
BOOL do_reg_set_key_sec(struct cli_state *cli, uint16 fnum, POLICY_HND *hnd,
uint32 sec_buf_size, SEC_DESC *sec_buf);
BOOL do_reg_get_key_sec(struct cli_state *cli, uint16 fnum, POLICY_HND *hnd,
@ -1933,6 +1933,10 @@ BOOL delete_samr_dom_alias(struct cli_state *cli, uint16 fnum,
BOOL get_samr_query_aliasmem(struct cli_state *cli, uint16 fnum,
const POLICY_HND *pol_open_domain,
uint32 alias_rid, uint32 *num_mem, DOM_SID2 *sid);
BOOL set_samr_set_userinfo2(struct cli_state *cli, uint16 fnum,
POLICY_HND *pol_open_domain,
uint32 info_level,
uint32 user_rid, void *usr);
BOOL set_samr_set_userinfo(struct cli_state *cli, uint16 fnum,
POLICY_HND *pol_open_domain,
uint32 info_level,
@ -1940,7 +1944,7 @@ BOOL set_samr_set_userinfo(struct cli_state *cli, uint16 fnum,
BOOL get_samr_query_userinfo(struct cli_state *cli, uint16 fnum,
POLICY_HND *pol_open_domain,
uint32 info_level,
uint32 user_rid, SAM_USER_INFO_21 *usr);
uint32 user_rid, void *usr);
BOOL get_samr_query_groupinfo(struct cli_state *cli, uint16 fnum,
const POLICY_HND *pol_open_domain,
uint32 info_level,
@ -2056,6 +2060,9 @@ BOOL samr_query_usergroups(struct cli_state *cli, uint16 fnum,
BOOL samr_query_groupinfo(struct cli_state *cli, uint16 fnum,
POLICY_HND *pol,
uint16 switch_value, GROUP_INFO_CTR* ctr);
BOOL samr_set_userinfo2(struct cli_state *cli, uint16 fnum,
POLICY_HND *pol, uint16 switch_value,
void* usr);
BOOL samr_set_userinfo(struct cli_state *cli, uint16 fnum,
POLICY_HND *pol, uint16 switch_value, void* usr);
BOOL samr_query_userinfo(struct cli_state *cli, uint16 fnum,
@ -2942,6 +2949,14 @@ BOOL samr_io_q_set_userinfo(char *desc, SAMR_Q_SET_USERINFO *q_u, prs_struct *ps
void free_samr_q_set_userinfo(SAMR_Q_SET_USERINFO *q_u);
BOOL make_samr_r_set_userinfo(SAMR_R_SET_USERINFO *r_u, uint32 status);
BOOL samr_io_r_set_userinfo(char *desc, SAMR_R_SET_USERINFO *r_u, prs_struct *ps, int depth);
BOOL make_samr_q_set_userinfo2(SAMR_Q_SET_USERINFO2 *q_u,
POLICY_HND *hnd,
uint16 switch_value, void *info);
BOOL samr_io_q_set_userinfo2(char *desc, SAMR_Q_SET_USERINFO2 *q_u, prs_struct *ps, int depth);
void free_samr_q_set_userinfo2(SAMR_Q_SET_USERINFO2 *q_u);
BOOL make_samr_r_set_userinfo2(SAMR_R_SET_USERINFO2 *r_u,
uint32 status);
BOOL samr_io_r_set_userinfo2(char *desc, SAMR_R_SET_USERINFO2 *r_u, prs_struct *ps, int depth);
BOOL make_samr_q_connect(SAMR_Q_CONNECT *q_u,
const char *srv_name, uint32 unknown_0);
BOOL samr_io_q_connect(char *desc, SAMR_Q_CONNECT *q_u, prs_struct *ps, int depth);
@ -3492,6 +3507,7 @@ void cmd_sam_enum_users(struct client_info *info);
void cmd_sam_query_groupmem(struct client_info *info);
void cmd_sam_query_group(struct client_info *info);
void cmd_sam_query_user(struct client_info *info);
void cmd_sam_set_userinfo2(struct client_info *info);
void cmd_sam_set_userinfo(struct client_info *info);
void cmd_sam_query_dispinfo(struct client_info *info);
void cmd_sam_query_dominfo(struct client_info *info);

View File

@ -114,11 +114,12 @@ SamrTestPrivateFunctionsUser
#define SAMR_QUERY_ALIASMEM 0x21
#define SAMR_OPEN_USER 0x22
#define SAMR_QUERY_USERINFO 0x24
#define SAMR_SET_USERINFO2 0x25
#define SAMR_QUERY_USERGROUPS 0x27
#define SAMR_CREATE_USER 0x32
#define SAMR_SET_USERINFO 0x3A
#define SAMR_QUERY_USERINFO 0x24
#define SAMR_QUERY_USERGROUPS 0x27
#define SAMR_QUERY_DISPINFO 0x28
#define SAMR_GET_USRDOM_PWINFO 0x2c
@ -141,6 +142,13 @@ typedef struct logon_hours_info
} LOGON_HRS;
/* SAM_USER_INFO_16 */
typedef struct sam_user_info_16
{
uint16 acb_info; /* account info (ACB_xxxx bit-mask) */
} SAM_USER_INFO_16;
/* SAM_USER_INFO_23 */
typedef struct sam_user_info_23
{
@ -1152,6 +1160,29 @@ typedef struct r_samr_query_usergroup_info
} SAMR_R_QUERY_USERGROUPS;
/* SAMR_Q_SET_USERINFO2 - set sam info */
typedef struct q_samr_set_user_info2
{
POLICY_HND pol; /* policy handle associated with user */
uint16 switch_value; /* 0x0010 */
uint16 switch_value2; /* 0x0010 */
union
{
SAM_USER_INFO_16 *id16; /* auth-level 0x10 */
void* id; /* to make typecasting easy */
} info;
} SAMR_Q_SET_USERINFO2;
/* SAMR_R_SET_USERINFO2 - set sam info */
typedef struct r_samr_set_user_info2
{
uint32 status; /* return status */
} SAMR_R_SET_USERINFO2;
/* SAMR_Q_SET_USERINFO - set sam info */
typedef struct q_samr_set_user_info
{

View File

@ -304,6 +304,41 @@ BOOL get_samr_query_aliasmem(struct cli_state *cli, uint16 fnum,
return samr_close(cli, fnum,&pol_open_alias) && ret;
}
/****************************************************************************
do a SAMR set user info
****************************************************************************/
BOOL set_samr_set_userinfo2(struct cli_state *cli, uint16 fnum,
POLICY_HND *pol_open_domain,
uint32 info_level,
uint32 user_rid, void *usr)
{
POLICY_HND pol_open_user;
BOOL ret = True;
if (pol_open_domain == NULL || usr == NULL) return False;
/* send open domain (on user sid) */
if (!samr_open_user(cli, fnum,
pol_open_domain,
0x000601b4, user_rid,
&pol_open_user))
{
return False;
}
/* send user info query */
if (!samr_set_userinfo2(cli, fnum,
&pol_open_user,
info_level, usr))
{
DEBUG(5,("samr_set_userinfo: error in query user info, level 0x%x\n",
info_level));
ret = False;
}
return samr_close(cli, fnum,&pol_open_user) && ret;
}
/****************************************************************************
do a SAMR set user info
****************************************************************************/
@ -345,15 +380,13 @@ do a SAMR query user info
BOOL get_samr_query_userinfo(struct cli_state *cli, uint16 fnum,
POLICY_HND *pol_open_domain,
uint32 info_level,
uint32 user_rid, SAM_USER_INFO_21 *usr)
uint32 user_rid, void *usr)
{
POLICY_HND pol_open_user;
BOOL ret = True;
if (pol_open_domain == NULL || usr == NULL) return False;
bzero(usr, sizeof(*usr));
/* send open domain (on user sid) */
if (!samr_open_user(cli, fnum,
pol_open_domain,
@ -366,7 +399,7 @@ BOOL get_samr_query_userinfo(struct cli_state *cli, uint16 fnum,
/* send user info query */
if (!samr_query_userinfo(cli, fnum,
&pol_open_user,
info_level, (void*)usr))
info_level, usr))
{
DEBUG(5,("samr_query_userinfo: error in query user info, level 0x%x\n",
info_level));
@ -2556,6 +2589,62 @@ BOOL samr_query_groupinfo(struct cli_state *cli, uint16 fnum,
return valid_query;
}
/****************************************************************************
do a SAMR Set User Info
****************************************************************************/
BOOL samr_set_userinfo2(struct cli_state *cli, uint16 fnum,
POLICY_HND *pol, uint16 switch_value,
void* usr)
{
prs_struct data;
prs_struct rdata;
SAMR_Q_SET_USERINFO2 q_o;
BOOL valid_query = False;
DEBUG(4,("SAMR Set User Info 2. level: %d\n", switch_value));
if (pol == NULL || usr == NULL || switch_value == 0) return False;
/* create and send a MSRPC command with api SAMR_SET_USERINFO2 */
prs_init(&data , 1024, 4, SAFETY_MARGIN, False);
prs_init(&rdata, 0 , 4, SAFETY_MARGIN, True );
/* store the parameters */
make_samr_q_set_userinfo2(&q_o, pol, switch_value, usr);
/* turn parameters into data stream */
samr_io_q_set_userinfo2("", &q_o, &data, 0);
/* send the data on \PIPE\ */
if (rpc_api_pipe_req(cli, fnum, SAMR_SET_USERINFO2, &data, &rdata))
{
SAMR_R_SET_USERINFO2 r_o;
BOOL p;
samr_io_r_set_userinfo2("", &r_o, &rdata, 0);
p = rdata.offset != 0;
if (p && r_o.status != 0)
{
/* report error code */
DEBUG(4,("SAMR_R_QUERY_USERINFO2: %s\n", get_nt_error_msg(r_o.status)));
p = False;
}
if (p)
{
valid_query = True;
}
}
prs_mem_free(&data );
prs_mem_free(&rdata );
return valid_query;
}
/****************************************************************************
do a SAMR Set User Info
****************************************************************************/

View File

@ -4931,7 +4931,7 @@ static BOOL sam_io_user_info24(char *desc, SAM_USER_INFO_24 *usr, prs_struct *p
{
if (usr == NULL) return False;
prs_debug(ps, depth, desc, "lsa_io_user_info");
prs_debug(ps, depth, desc, "sam_io_user_info24");
depth++;
prs_align(ps);
@ -5166,6 +5166,24 @@ BOOL make_sam_user_info23A(SAM_USER_INFO_23 *usr,
return True;
}
/*******************************************************************
reads or writes a structure.
********************************************************************/
static BOOL sam_io_user_info16(char *desc, SAM_USER_INFO_16 *usr, prs_struct *ps, int depth)
{
if (usr == NULL) return False;
prs_debug(ps, depth, desc, "sam_io_user_info16");
depth++;
prs_align(ps);
prs_uint16("acb_info", ps, depth, &(usr->acb_info));
prs_align(ps);
return True;
}
/*******************************************************************
reads or writes a structure.
********************************************************************/
@ -5173,7 +5191,7 @@ static BOOL sam_io_user_info23(char *desc, SAM_USER_INFO_23 *usr, prs_struct *p
{
if (usr == NULL) return False;
prs_debug(ps, depth, desc, "lsa_io_user_info");
prs_debug(ps, depth, desc, "sam_io_user_info23");
depth++;
prs_align(ps);
@ -5364,7 +5382,7 @@ static BOOL sam_io_user_info21(char *desc, SAM_USER_INFO_21 *usr, prs_struct *p
{
if (usr == NULL) return False;
prs_debug(ps, depth, desc, "lsa_io_user_info");
prs_debug(ps, depth, desc, "sam_io_user_info21");
depth++;
prs_align(ps);
@ -5767,6 +5785,143 @@ BOOL samr_io_r_set_userinfo(char *desc, SAMR_R_SET_USERINFO *r_u, prs_struct *p
return True;
}
/*******************************************************************
makes a SAMR_Q_SET_USERINFO2 structure.
********************************************************************/
BOOL make_samr_q_set_userinfo2(SAMR_Q_SET_USERINFO2 *q_u,
POLICY_HND *hnd,
uint16 switch_value, void *info)
{
if (q_u == NULL || hnd == NULL) return False;
DEBUG(5,("make_samr_q_set_userinfo2\n"));
memcpy(&(q_u->pol), hnd, sizeof(q_u->pol));
q_u->switch_value = switch_value;
q_u->switch_value2 = switch_value;
q_u->info.id = info;
switch (switch_value)
{
case 0x10:
{
break;
}
default:
{
DEBUG(4,("make_samr_q_set_userinfo2: unsupported switch level\n"));
return False;
}
}
return True;
}
/*******************************************************************
reads or writes a structure.
********************************************************************/
BOOL samr_io_q_set_userinfo2(char *desc, SAMR_Q_SET_USERINFO2 *q_u, prs_struct *ps, int depth)
{
if (q_u == NULL) return False;
prs_debug(ps, depth, desc, "samr_io_q_set_userinfo2");
depth++;
prs_align(ps);
smb_io_pol_hnd("pol", &(q_u->pol), ps, depth);
prs_align(ps);
prs_uint16("switch_value ", ps, depth, &(q_u->switch_value ));
prs_uint16("switch_value2", ps, depth, &(q_u->switch_value2));
prs_align(ps);
switch (q_u->switch_value)
{
case 0:
{
break;
}
case 16:
{
if (ps->io)
{
/* reading */
q_u->info.id = (SAM_USER_INFO_16*)Realloc(NULL,
sizeof(*q_u->info.id16));
}
if (q_u->info.id == NULL)
{
DEBUG(2,("samr_io_q_query_userinfo2: info pointer not initialised\n"));
return False;
}
sam_io_user_info16("", q_u->info.id16, ps, depth);
break;
}
default:
{
DEBUG(2,("samr_io_q_query_userinfo2: unknown switch level\n"));
break;
}
}
prs_align(ps);
if (!ps->io)
{
/* writing */
free_samr_q_set_userinfo2(q_u);
}
return True;
}
/*******************************************************************
frees a structure.
********************************************************************/
void free_samr_q_set_userinfo2(SAMR_Q_SET_USERINFO2 *q_u)
{
if (q_u->info.id == NULL)
{
free(q_u->info.id);
}
q_u->info.id = NULL;
}
/*******************************************************************
makes a SAMR_R_SET_USERINFO2 structure.
********************************************************************/
BOOL make_samr_r_set_userinfo2(SAMR_R_SET_USERINFO2 *r_u,
uint32 status)
{
if (r_u == NULL) return False;
DEBUG(5,("make_samr_r_set_userinfo2\n"));
r_u->status = status; /* return status */
return True;
}
/*******************************************************************
reads or writes a structure.
********************************************************************/
BOOL samr_io_r_set_userinfo2(char *desc, SAMR_R_SET_USERINFO2 *r_u, prs_struct *ps, int depth)
{
if (r_u == NULL) return False;
prs_debug(ps, depth, desc, "samr_io_r_set_userinfo2");
depth++;
prs_align(ps);
prs_uint32("status", ps, depth, &(r_u->status));
return True;
}
/*******************************************************************
makes a SAMR_Q_CONNECT structure.
********************************************************************/

View File

@ -2121,6 +2121,31 @@ static BOOL set_user_info_23(SAM_USER_INFO_23 *id23, uint32 rid)
return mod_sam21pwd_entry(&new_pwd, True);
}
/*******************************************************************
set_user_info_16
********************************************************************/
static BOOL set_user_info_16(SAM_USER_INFO_16 *id16, uint32 rid)
{
struct sam_passwd *pwd = getsam21pwrid(rid);
struct sam_passwd new_pwd;
if (id16 == NULL)
{
DEBUG(5, ("set_user_info_16: NULL id16\n"));
return False;
}
if (pwd == NULL)
{
return False;
}
copy_sam_passwd(&new_pwd, pwd);
new_pwd.acct_ctrl = id16->acb_info;
return mod_sam21pwd_entry(&new_pwd, True);
}
/*******************************************************************
api_samr_query_userinfo
********************************************************************/
@ -2132,6 +2157,87 @@ static void api_samr_query_userinfo( pipes_struct *p, prs_struct *data, prs_stru
}
/*******************************************************************
samr_reply_set_userinfo2
********************************************************************/
static void samr_reply_set_userinfo2(SAMR_Q_SET_USERINFO2 *q_u,
prs_struct *rdata, uchar user_sess_key[16])
{
SAMR_R_SET_USERINFO2 r_u;
uint32 status = 0x0;
uint32 rid = 0x0;
DEBUG(5,("samr_reply_set_userinfo2: %d\n", __LINE__));
/* search for the handle */
if (status == 0x0 && (find_lsa_policy_by_hnd(&(q_u->pol)) == -1))
{
status = 0xC0000000 | NT_STATUS_INVALID_HANDLE;
}
/* find the user's rid */
if (status == 0x0 && (rid = get_lsa_policy_samr_rid(&(q_u->pol))) == 0xffffffff)
{
status = 0xC0000000 | NT_STATUS_OBJECT_TYPE_MISMATCH;
}
DEBUG(5,("samr_reply_set_userinfo2: rid:0x%x\n", rid));
/* ok! user info levels (there are lots: see MSDEV help), off we go... */
if (status == 0x0 && q_u->info.id == NULL)
{
DEBUG(5,("samr_reply_set_userinfo2: NULL info level\n"));
status = 0xC0000000 | NT_STATUS_INVALID_INFO_CLASS;
}
if (status == 0x0)
{
switch (q_u->switch_value)
{
case 16:
{
SAM_USER_INFO_16 *id16 = q_u->info.id16;
status = set_user_info_16(id16, rid) ? 0 : (0xC0000000 | NT_STATUS_ACCESS_DENIED);
break;
}
default:
{
status = 0xC0000000 | NT_STATUS_INVALID_INFO_CLASS;
break;
}
}
}
make_samr_r_set_userinfo2(&r_u, status);
/* store the response in the SMB stream */
samr_io_r_set_userinfo2("", &r_u, rdata, 0);
DEBUG(5,("samr_reply_set_userinfo2: %d\n", __LINE__));
}
/*******************************************************************
api_samr_set_userinfo2
********************************************************************/
static void api_samr_set_userinfo2( pipes_struct *p, prs_struct *data, prs_struct *rdata)
{
user_struct *vuser = get_valid_user_struct(p->vuid);
SAMR_Q_SET_USERINFO2 q_u;
ZERO_STRUCT(q_u);
samr_io_q_set_userinfo2("", &q_u, data, 0);
samr_reply_set_userinfo2(&q_u, rdata, vuser->dc.user_sess_key);
if (q_u.info.id != NULL)
{
free(q_u.info.id);
}
}
/*******************************************************************
samr_reply_set_userinfo
********************************************************************/
@ -3038,6 +3144,7 @@ static struct api_struct api_samr_cmds [] =
{ "SAMR_OPEN_USER" , SAMR_OPEN_USER , api_samr_open_user },
{ "SAMR_QUERY_USERINFO" , SAMR_QUERY_USERINFO , api_samr_query_userinfo },
{ "SAMR_SET_USERINFO" , SAMR_SET_USERINFO , api_samr_set_userinfo },
{ "SAMR_SET_USERINFO2" , SAMR_SET_USERINFO2 , api_samr_set_userinfo2 },
{ "SAMR_QUERY_DOMAIN_INFO", SAMR_QUERY_DOMAIN_INFO, api_samr_query_dom_info },
{ "SAMR_QUERY_USERGROUPS" , SAMR_QUERY_USERGROUPS , api_samr_query_usergroups },
{ "SAMR_QUERY_DISPINFO" , SAMR_QUERY_DISPINFO , api_samr_query_dispinfo },

View File

@ -2570,6 +2570,162 @@ void cmd_sam_query_user(struct client_info *info)
}
/****************************************************************************
experimental SAM user set.
****************************************************************************/
void cmd_sam_set_userinfo2(struct client_info *info)
{
uint16 fnum;
fstring srv_name;
fstring domain;
fstring sid_str;
DOM_SID sid;
BOOL res = True;
BOOL res1 = True;
uint32 argc = 0;
char **argv = NULL;
uint32 cp_argc = 0;
char **cp_argv = NULL;
extern int optind;
int opt;
BOOL set_acb_bits = False;
fstring user_name;
fstring tmp;
char *names[1];
uint32 num_rids;
uint32 rid[MAX_LOOKUP_SIDS];
uint32 type[MAX_LOOKUP_SIDS];
POLICY_HND sam_pol;
POLICY_HND pol_dom;
SAM_USER_INFO_16 usr16;
uint16 acb_set = 0x0;
fstrcpy(domain, info->dom.level5_dom);
sid_copy(&sid, &info->dom.level5_sid);
if (sid.num_auths == 0)
{
report(out_hnd, "please use 'lsaquery' first, to ascertain the SID\n");
return;
}
/* create arguments array */
while (next_token(NULL, tmp, NULL, sizeof(tmp)))
{
add_chars_to_array(&argc, &argv, tmp);
}
cp_argc = argc;
cp_argv = argv;
if (cp_argc < 2)
{
report(out_hnd, "samuserset2 <name> [-s <acb_bits>]\n");
return;
}
safe_strcpy(user_name, cp_argv[0], sizeof(user_name));
cp_argc--;
cp_argv++;
optind = -1;
while ((opt = getopt(cp_argc, cp_argv,"s:")) != EOF)
{
switch (opt)
{
case 's':
{
set_acb_bits = True;
acb_set = get_number(optarg);
break;
}
}
}
fstrcpy(srv_name, "\\\\");
fstrcat(srv_name, info->dest_host);
strupper(srv_name);
sid_to_string(sid_str, &sid);
report(out_hnd, "SAM Set User Info: %s\n", user_name);
/* open SAMR session. negotiate credentials */
res = res ? cli_nt_session_open(smb_cli, PIPE_SAMR, &fnum) : False;
/* establish a connection. */
res = res ? samr_connect(smb_cli, fnum,
srv_name, 0x02000000,
&sam_pol) : False;
/* connect to the domain */
res = res ? samr_open_domain(smb_cli, fnum,
&sam_pol, 0x02000000, &sid,
&pol_dom) : False;
/* look up user rid */
names[0] = user_name;
res1 = res ? samr_query_lookup_names(smb_cli, fnum,
&pol_dom, 0x3e8,
1, names,
&num_rids, rid, type) : False;
/* send set user info */
if (res1 && num_rids == 1 && get_samr_query_userinfo(smb_cli, fnum,
&pol_dom,
0x10, rid[0],
(void*)&usr16))
{
void *usr = NULL;
uint32 switch_value = 0;
if (set_acb_bits)
{
usr16.acb_info |= acb_set;
}
if (True)
{
SAM_USER_INFO_16 *p = malloc(sizeof(SAM_USER_INFO_16));
p->acb_info = usr16.acb_info;
usr = (void*)p;
switch_value = 16;
}
if (usr != NULL)
{
res1 = set_samr_set_userinfo2(smb_cli, fnum,
&pol_dom,
switch_value, rid[0], usr);
}
}
res = res ? samr_close(smb_cli, fnum,
&sam_pol) : False;
res = res ? samr_close(smb_cli, fnum,
&pol_dom) : False;
/* close the session */
cli_nt_session_close(smb_cli, fnum);
if (res1)
{
report(out_hnd, "Set User Info: OK\n");
DEBUG(5,("cmd_sam_query_user: succeeded\n"));
}
else
{
report(out_hnd, "Set User Info: Failed\n");
DEBUG(5,("cmd_sam_query_user: failed\n"));
}
free_char_array(argc, argv);
}
/****************************************************************************
experimental SAM user set.
****************************************************************************/

View File

@ -441,6 +441,12 @@ commands[] =
"NT SAM Password Change",
{COMPL_NONE, COMPL_NONE}
},
{
"samuserset2",
cmd_sam_set_userinfo2,
"<username> [-s acb_bits] SAM User Set Info 2 (experimental!)",
{COMPL_SAMUSR, COMPL_NONE}
},
{
"samuserset",
cmd_sam_set_userinfo,