1
0
mirror of https://github.com/samba-team/samba.git synced 2024-12-23 17:34:34 +03:00

adding some enumerate services code, client and server.

This commit is contained in:
Luke Leighton 0001-01-01 00:00:00 +00:00
parent 501617307f
commit dacf5b152b
9 changed files with 397 additions and 98 deletions

View File

@ -487,6 +487,7 @@ void pwdb_set_must_change_time(char *p, int max_len, time_t t);
void pwdb_set_last_set_time(char *p, int max_len, time_t t);
void pwdb_sethexpwd(char *p, const char *pwd, uint16 acct_ctrl);
BOOL pwdb_gethexpwd(const char *p, char *pwd);
BOOL pwdb_init_myworkgroup(void);
BOOL pwdb_initialise(BOOL is_server);
/*The following definitions come from lib/util_sid.c */
@ -746,6 +747,7 @@ BOOL make_oem_passwd_hash(char data[516], const char *passwd, uchar old_pw_hash[
/*The following definitions come from libsmb/smberr.c */
char *smb_err_msg(uint8 class, uint32 num);
char *smb_errstr(char *inbuf);
/*The following definitions come from locking/locking.c */
@ -1778,7 +1780,8 @@ BOOL do_svc_open_sc_man(struct cli_state *cli, uint16 fnum,
BOOL do_svc_enum_svcs(struct cli_state *cli, uint16 fnum,
POLICY_HND *hnd,
uint32 services_type, uint32 services_state,
uint32 buf_size, uint32 *resume_hnd);
uint32 buf_size, uint32 *resume_hnd,
ENUM_SRVC_STATUS **svcs);
BOOL do_svc_close(struct cli_state *cli, uint16 fnum, POLICY_HND *hnd);
/*The following definitions come from rpc_client/cli_wkssvc.c */
@ -2503,8 +2506,14 @@ void make_svc_r_open_sc_man(SVC_R_OPEN_SC_MAN *r_u, POLICY_HND *hnd,
void svc_io_r_open_sc_man(char *desc, SVC_R_OPEN_SC_MAN *r_u, prs_struct *ps, int depth);
void make_svc_q_enum_svcs_status(SVC_Q_ENUM_SVCS_STATUS *q_c, POLICY_HND *hnd,
uint32 service_type, uint32 service_state,
uint32 buf_size, uint32 enum_hnd );
uint32 buf_size, uint32 resume_hnd );
void svc_io_q_enum_svcs_status(char *desc, SVC_Q_ENUM_SVCS_STATUS *q_u, prs_struct *ps, int depth);
void make_svc_r_enum_svcs_status(SVC_R_ENUM_SVCS_STATUS *r_c,
ENUM_SRVC_STATUS *svcs, uint32 more_buf_size,
uint32 num_svcs, uint32 resume_hnd,
uint32 dos_status);
void svc_io_r_enum_svcs_status(char *desc, SVC_R_ENUM_SVCS_STATUS *svc, prs_struct *ps, int depth);
void svc_io_svc_status(char *desc, SVC_STATUS *svc, prs_struct *ps, int depth);
void make_svc_q_close(SVC_Q_CLOSE *q_c, POLICY_HND *hnd);
void svc_io_q_close(char *desc, SVC_Q_CLOSE *q_u, prs_struct *ps, int depth);
void svc_io_r_close(char *desc, SVC_R_CLOSE *r_u, prs_struct *ps, int depth);

View File

@ -65,14 +65,14 @@ typedef struct svc_status_info
} SVC_STATUS;
/* ENUM_SVC_STATUS */
/* ENUM_SRVC_STATUS */
typedef struct enum_svc_status_info
{
UNISTR uni_srvc_name;
UNISTR uni_disp_name;
SVC_STATUS status;
} ENUM_SVC_STATUS;
} ENUM_SRVC_STATUS;
/* SVC_Q_ENUM_SVCS_STATUS */
typedef struct q_svc_enum_svcs_status_info
@ -89,8 +89,11 @@ typedef struct q_svc_enum_svcs_status_info
typedef struct r_svc_enum_svcs_status_info
{
uint32 buf_size; /* service buffer size */
ENUM_SVC_STATUS *svcs;
uint32 status; /* return status */
ENUM_SRVC_STATUS *svcs;
uint32 more_buf_size;
uint32 num_svcs;
ENUM_HND resume_hnd; /* resume handle */
uint32 dos_status; /* return status, DOS error code (wow!) */
} SVC_R_ENUM_SVCS_STATUS;

View File

@ -144,38 +144,51 @@ struct
{-1,NULL,NULL}};
/****************************************************************************
return a SMB error string from a SMB buffer
****************************************************************************/
char *smb_err_msg(uint8 class, uint32 num)
{
static pstring ret;
int i,j;
for (i=0;err_classes[i].class;i++)
{
if (err_classes[i].code == class)
{
err_code_struct *err = err_classes[i].err_msgs;
if (err != NULL)
{
for (j=0;err[j].name;j++)
{
if (num == err[j].code)
{
if (DEBUGLEVEL > 0)
{
slprintf(ret, sizeof(ret) - 1, "%s - %s (%s)",err_classes[i].class,
err[j].name,err[j].message);
}
else
{
slprintf(ret, sizeof(ret) - 1, "%s - %s",err_classes[i].class,err[j].name);
}
return ret;
}
}
}
}
slprintf(ret, sizeof(ret) - 1, "%s - %d",err_classes[i].class, num);
return ret;
}
slprintf(ret, sizeof(ret) - 1, "Error: Unknown error (%d,%d)",class,num);
return(ret);
}
/****************************************************************************
return a SMB error string from a SMB buffer
****************************************************************************/
char *smb_errstr(char *inbuf)
{
static pstring ret;
int class = CVAL(inbuf,smb_rcls);
int num = SVAL(inbuf,smb_err);
int i,j;
for (i=0;err_classes[i].class;i++)
if (err_classes[i].code == class)
{
if (err_classes[i].err_msgs)
{
err_code_struct *err = err_classes[i].err_msgs;
for (j=0;err[j].name;j++)
if (num == err[j].code)
{
if (DEBUGLEVEL > 0)
slprintf(ret, sizeof(ret) - 1, "%s - %s (%s)",err_classes[i].class,
err[j].name,err[j].message);
else
slprintf(ret, sizeof(ret) - 1, "%s - %s",err_classes[i].class,err[j].name);
return ret;
}
}
slprintf(ret, sizeof(ret) - 1, "%s - %d",err_classes[i].class,num);
return ret;
}
slprintf(ret, sizeof(ret) - 1, "Error: Unknown error (%d,%d)",class,num);
return(ret);
return smb_err_msg(CVAL(inbuf,smb_rcls), SVAL(inbuf,smb_err));
}

View File

@ -97,7 +97,8 @@ do a SVC Enumerate Services
BOOL do_svc_enum_svcs(struct cli_state *cli, uint16 fnum,
POLICY_HND *hnd,
uint32 services_type, uint32 services_state,
uint32 buf_size, uint32 *resume_hnd)
uint32 buf_size, uint32 *resume_hnd,
ENUM_SRVC_STATUS **svcs)
{
prs_struct rbuf;
prs_struct buf;
@ -123,7 +124,6 @@ BOOL do_svc_enum_svcs(struct cli_state *cli, uint16 fnum,
/* send the data on \PIPE\ */
if (rpc_api_pipe_req(cli, fnum, SVC_ENUM_SVCS_STATUS, &buf, &rbuf))
{
#if 0
SVC_R_ENUM_SVCS_STATUS r_o;
BOOL p;
@ -132,22 +132,19 @@ BOOL do_svc_enum_svcs(struct cli_state *cli, uint16 fnum,
svc_io_r_enum_svcs_status("", &r_o, &rbuf, 0);
p = rbuf.offset != 0;
if (p && r_o.status != 0)
if (p && r_o.dos_status != 0)
{
/* report error code */
DEBUG(0,("SVC_ENUM_SVCS_STATUS: %s\n", get_nt_error_msg(r_o.status)));
p = False;
DEBUG(0,("SVC_ENUM_SVCS_STATUS: %s\n", smb_err_msg(ERRDOS, r_o.dos_status)));
p = r_o.dos_status != ERRmoredata;
}
if (p)
{
/* ok, at last: we're happy. return the policy handle */
memcpy(hnd, r_o.pol.data, sizeof(hnd->data));
(*svcs) = r_o.svcs;
(*resume_hnd) = get_enum_hnd(&r_o.resume_hnd);
valid_pol = True;
}
#else
valid_pol = True;
#endif
}
prs_mem_free(&rbuf);

View File

@ -343,7 +343,6 @@ void smb_io_unistr(char *desc, UNISTR *uni, prs_struct *ps, int depth)
prs_debug(ps, depth, desc, "smb_io_unistr");
depth++;
prs_align(ps);
prs_unistr("unistr", ps, depth, uni);
}

View File

@ -237,21 +237,22 @@ BOOL prs_unistr3(BOOL charmode, char *name, UNISTR3 *str, prs_struct *ps, int de
BOOL prs_unistr(char *name, prs_struct *ps, int depth, UNISTR *str)
{
char *q = mem_data(&(ps->data), ps->offset);
int i = 0;
int i = -1;
uint8 *start = (uint8*)q;
if (q == NULL) return False;
do
do
{
i++;
RW_SVAL(ps->io, q, str->buffer[i],0);
q += 2;
i++;
} while ((i < sizeof(str->buffer) / sizeof(str->buffer[0])) &&
}
while ((i < sizeof(str->buffer) / sizeof(str->buffer[0])) &&
(str->buffer[i] != 0));
ps->offset += i*2;
ps->offset += (i+1)*2;
dump_data(5+depth, (char *)start, i * 2);

View File

@ -134,6 +134,204 @@ void svc_io_q_enum_svcs_status(char *desc, SVC_Q_ENUM_SVCS_STATUS *q_u, prs_str
smb_io_enum_hnd("resume_hnd", &(q_u->resume_hnd), ps, depth);
}
/*******************************************************************
makes an SVC_R_ENUM_SVCS_STATUS structure.
********************************************************************/
void make_svc_r_enum_svcs_status(SVC_R_ENUM_SVCS_STATUS *r_c,
ENUM_SRVC_STATUS *svcs, uint32 more_buf_size,
uint32 num_svcs, uint32 resume_hnd,
uint32 dos_status)
{
if (r_c == NULL) return;
DEBUG(5,("make_svc_r_enum_svcs_status\n"));
r_c->svcs = svcs;
r_c->more_buf_size = more_buf_size;
r_c->num_svcs = num_svcs;
make_enum_hnd(&r_c->resume_hnd, resume_hnd);
r_c->dos_status = dos_status;
}
/*******************************************************************
reads or writes a SVC_R_ENUM_SVCS_STATUS structure.
this is another wierd structure. WHY oh WHY can the microsoft teams
not COMMUNICATE and get some CONSISTENCY TO THEIR DATA STRUCTURES!
ARGH!
********************************************************************/
void svc_io_r_enum_svcs_status(char *desc, SVC_R_ENUM_SVCS_STATUS *svc, prs_struct *ps, int depth)
{
int i;
if (svc == NULL) return;
prs_debug(ps, depth, desc, "svc_io_r_enum_svcs_status");
depth++;
prs_align(ps);
/*
* format is actually as laid out in SVC_R_ENUM_SVCS_STATUS.
* the reason for all the jumping about, which is horrible
* and can be avoided, is due to the use of offsets instead
* of pointers.
*
* if i ever find out that these offsets are in fact non-zero
* tokens just like pointer-tokens, i am going to go MAD.
*/
if (ps->io)
{
/* reading */
uint32 buf_offset;
uint32 new_offset;
prs_uint32("buf_size", ps, depth, &(svc->buf_size));
buf_offset = ps->offset;
ps->offset = buf_offset + svc->buf_size;
prs_uint32("more_buf_size", ps, depth, &(svc->more_buf_size));
prs_uint32("num_svcs", ps, depth, &(svc->num_svcs));
smb_io_enum_hnd("resume_hnd", &(svc->resume_hnd), ps, depth);
prs_uint32("dos_status", ps, depth, &(svc->dos_status));
new_offset = ps->offset;
ps->offset = buf_offset;
svc->svcs = Realloc(NULL, svc->num_svcs * sizeof(ENUM_SRVC_STATUS));
if (svc->svcs == NULL)
{
DEBUG(0,("svc_io_r_enum_svcs_status: Realloc failed\n"));
ps->offset = 0x7fffffff;
return;
}
bzero(svc->svcs, svc->num_svcs * sizeof(ENUM_SRVC_STATUS));
for (i = 0; i < svc->num_svcs; i++)
{
fstring name;
uint32 old_offset;
uint32 srvc_offset;
uint32 disp_offset;
prs_uint32("srvc_offset", ps, depth, &srvc_offset);
prs_uint32("disp_offset", ps, depth, &disp_offset);
svc_io_svc_status("status", &svc->svcs[i].status, ps, depth);
old_offset = ps->offset;
ps->offset = buf_offset + srvc_offset;
slprintf(name, sizeof(name)-1, "srvc[%02d]", i);
smb_io_unistr(name, &svc->svcs[i].uni_srvc_name, ps, depth);
ps->offset = buf_offset + disp_offset;
slprintf(name, sizeof(name)-1, "disp[%02d]", i);
smb_io_unistr(name, &svc->svcs[i].uni_disp_name, ps, depth);
ps->offset = old_offset;
}
ps->offset = new_offset;
}
else
{
/* writing */
uint32 buf_offset;
uint32 old_buf_offset;
uint32 srvc_offset = 9 * sizeof(uint32) * svc->num_svcs;
prs_uint32_pre("buf_size", ps, depth, &svc->buf_size, &buf_offset);
old_buf_offset = ps->offset;
srvc_offset += old_buf_offset;
if (svc->svcs == NULL)
{
return;
}
for (i = 0; i < svc->num_svcs; i++)
{
fstring name;
uint32 old_offset;
/*
* store unicode string offset and unicode string
*/
srvc_offset -= old_buf_offset;
prs_uint32("srvc_offset", ps, depth, &srvc_offset);
srvc_offset += old_buf_offset;
slprintf(name, sizeof(name)-1, "srvc[%02d]", i);
old_offset = ps->offset;
ps->offset = srvc_offset;
smb_io_unistr(name, &svc->svcs[i].uni_srvc_name, ps, depth);
srvc_offset = ps->offset;
ps->offset = old_offset;
/*
* store unicode string offset and unicode string
*/
srvc_offset -= old_buf_offset;
prs_uint32("disp_offset", ps, depth, &srvc_offset);
srvc_offset += old_buf_offset;
slprintf(name, sizeof(name)-1, "disp[%02d]", i);
old_offset = ps->offset;
ps->offset = srvc_offset;
smb_io_unistr(name, &svc->svcs[i].uni_disp_name, ps, depth);
srvc_offset = ps->offset;
ps->offset = old_offset;
/*
* store status info
*/
svc_io_svc_status("status", &svc->svcs[i].status, ps, depth);
}
prs_uint32_post("buf_size", ps, depth, &svc->buf_size, buf_offset, srvc_offset - buf_offset - sizeof(uint32));
ps->offset = srvc_offset;
prs_uint32("more_buf_size", ps, depth, &(svc->more_buf_size));
prs_uint32("num_svcs", ps, depth, &(svc->num_svcs));
smb_io_enum_hnd("resume_hnd", &(svc->resume_hnd), ps, depth);
prs_uint32("dos_status", ps, depth, &(svc->dos_status));
}
}
/*******************************************************************
reads or writes a structure.
********************************************************************/
void svc_io_svc_status(char *desc, SVC_STATUS *svc, prs_struct *ps, int depth)
{
if (svc == NULL) return;
prs_debug(ps, depth, desc, "svc_io_svc_status");
depth++;
prs_align(ps);
prs_uint32("svc_type", ps, depth, &(svc->svc_type));
prs_uint32("current_state", ps, depth, &(svc->current_state));
prs_uint32("controls_accepted", ps, depth, &(svc->controls_accepted));
prs_uint32("win32_exit_code", ps, depth, &(svc->win32_exit_code));
prs_uint32("svc_specific_exit_code", ps, depth, &(svc->svc_specific_exit_code));
prs_uint32("check_point", ps, depth, &(svc->check_point));
prs_uint32("wait_hint", ps, depth, &(svc->wait_hint));
}
/*******************************************************************
makes an SVC_Q_CLOSE structure.
********************************************************************/
@ -180,48 +378,3 @@ void svc_io_r_close(char *desc, SVC_R_CLOSE *r_u, prs_struct *ps, int depth)
prs_uint32("status", ps, depth, &(r_u->status));
}
#if 0
/*******************************************************************
reads or writes a SEC_DESC_BUF structure.
********************************************************************/
void sec_io_desc_buf(char *desc, SEC_DESC_BUF *sec, prs_struct *ps, int depth)
{
uint32 off_len;
uint32 old_offset;
uint32 size;
if (sec == NULL) return;
prs_debug(ps, depth, desc, "sec_io_desc_buf");
depth++;
prs_align(ps);
prs_uint32_pre("max_len", ps, depth, &(sec->max_len), &off_max_len);
old_offset = ps->offset;
if (sec->len != 0 && ps->io)
{
/* reading */
sec->sec = malloc(sizeof(*sec->sec));
ZERO_STRUCTP(sec->sec);
if (sec->sec == NULL)
{
DEBUG(0,("INVALID SEC_DESC\n"));
ps->offset = 0xfffffffe;
return;
}
}
/* reading, length is non-zero; writing, descriptor is non-NULL */
if ((sec->len != 0 || (!ps->io)) && sec->sec != NULL)
{
sec_io_desc("sec ", sec->sec, ps, depth);
}
size = ps->offset - old_offset;
prs_uint32_post("max_len", ps, depth, &(sec->max_len), off_max_len, size == 0 ? sec->max_len : size);
}
#endif

View File

@ -120,6 +120,119 @@ static void api_svc_open_sc_man( uint16 vuid, prs_struct *data,
svc_reply_open_sc_man(&q_u, rdata);
}
static char *dummy_services[] =
{
"imapd",
"popd",
"smbd",
"nmbd",
"httpd",
"inetd",
"syslogd",
NULL
};
/*******************************************************************
svc_reply_enum_svcs_status
********************************************************************/
static void svc_reply_enum_svcs_status(SVC_Q_ENUM_SVCS_STATUS *q_u,
prs_struct *rdata)
{
uint32 dos_status = 0;
SVC_R_ENUM_SVCS_STATUS r_u;
ENUM_SRVC_STATUS *svcs = NULL;
int num_svcs = 0;
int buf_size = 0;
int i = get_enum_hnd(&q_u->resume_hnd);
uint32 resume_hnd = 0;
int max_buf_size = 0x80;
ZERO_STRUCT(r_u);
DEBUG(5,("svc_enum_svcs_status: %d\n", __LINE__));
if (dos_status == 0x0 && find_lsa_policy_by_hnd(&q_u->pol) == -1)
{
dos_status = 0xC000000 | NT_STATUS_INVALID_HANDLE;
}
if (dos_status == 0x0)
{
DEBUG(5,("svc_enum_svcs_status:\n"));
while (dummy_services[i] != NULL)
{
ENUM_SRVC_STATUS *svc = NULL;
buf_size += strlen(dummy_services[i] + 1) * 2;
buf_size += 9 * sizeof(uint32);
DEBUG(10,("buf_size: %d q_u->buf_size: %d\n",
buf_size, q_u->buf_size));
if (buf_size > q_u->buf_size)
{
if (buf_size >= max_buf_size)
{
resume_hnd = i;
}
break;
}
num_svcs++;
svcs = Realloc(svcs, num_svcs * sizeof(ENUM_SRVC_STATUS));
if (svcs == NULL)
{
dos_status = ERRnomem;
num_svcs = 0;
break;
}
svc = &svcs[num_svcs-1];
ZERO_STRUCTP(svc);
make_unistr(&svc->uni_srvc_name, dummy_services[i]);
make_unistr(&svc->uni_disp_name, dummy_services[i]);
DEBUG(10,("show service: %s\n", dummy_services[i]));
i++;
}
}
/*
* check for finished condition: no resume handle and last buffer fits
*/
if (resume_hnd == 0 && buf_size <= q_u->buf_size)
{
/* this indicates, along with resume_hnd of 0, an end. */
max_buf_size = 0;
}
make_svc_r_enum_svcs_status(&r_u, svcs, max_buf_size, num_svcs, resume_hnd, dos_status);
/* store the response in the SMB stream */
svc_io_r_enum_svcs_status("", &r_u, rdata, 0);
if (svcs != NULL)
{
free(svcs);
}
DEBUG(5,("svc_enum_svcs_status: %d\n", __LINE__));
}
/*******************************************************************
api_svc_enum_svcs_status
********************************************************************/
static void api_svc_enum_svcs_status( uint16 vuid, prs_struct *data,
prs_struct *rdata )
{
SVC_Q_ENUM_SVCS_STATUS q_u;
svc_io_q_enum_svcs_status("", &q_u, data, 0);
svc_reply_enum_svcs_status(&q_u, rdata);
}
/*******************************************************************
array of \PIPE\svcctl operations
********************************************************************/
@ -127,6 +240,7 @@ static struct api_struct api_svc_cmds[] =
{
{ "SVC_CLOSE" , SVC_CLOSE , api_svc_close },
{ "SVC_OPEN_SC_MAN" , SVC_OPEN_SC_MAN , api_svc_open_sc_man },
{ "SVC_ENUM_SVCS_STATUS", SVC_ENUM_SVCS_STATUS, api_svc_enum_svcs_status },
{ NULL, 0 , NULL }
};

View File

@ -46,6 +46,7 @@ void cmd_svc_enum(struct client_info *info)
BOOL res1 = True;
int i;
uint32 resume_hnd = 0;
ENUM_SRVC_STATUS *svcs = NULL;
POLICY_HND sc_man_pol;
fstring full_keyname;
@ -65,11 +66,20 @@ void cmd_svc_enum(struct client_info *info)
srv_name, NULL, 0x80000004,
&sc_man_pol) : False;
do
{
/* enumerate services */
res1 = res ? do_svc_enum_svcs(smb_cli, fnum,
&sc_man_pol,
0x00000030, 0x00000003,
0x00000200, &resume_hnd) : False;
0x00000080, &resume_hnd, &svcs) : False;
} while (resume_hnd != 0);
if (svcs != NULL)
{
free(svcs);
}
#if 0
if (res1 && num_subkeys > 0)