diff --git a/source3/include/proto.h b/source3/include/proto.h index de2d6f476c4..e8d232645a1 100644 --- a/source3/include/proto.h +++ b/source3/include/proto.h @@ -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); diff --git a/source3/include/rpc_svcctl.h b/source3/include/rpc_svcctl.h index 42419282189..451fdaa459a 100644 --- a/source3/include/rpc_svcctl.h +++ b/source3/include/rpc_svcctl.h @@ -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; diff --git a/source3/libsmb/smberr.c b/source3/libsmb/smberr.c index c2d8884d738..4fd9165c69b 100644 --- a/source3/libsmb/smberr.c +++ b/source3/libsmb/smberr.c @@ -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)); } diff --git a/source3/rpc_client/cli_svcctl.c b/source3/rpc_client/cli_svcctl.c index 90d74188dac..3535c90391f 100644 --- a/source3/rpc_client/cli_svcctl.c +++ b/source3/rpc_client/cli_svcctl.c @@ -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); diff --git a/source3/rpc_parse/parse_misc.c b/source3/rpc_parse/parse_misc.c index fdc67d09059..6b3fc9415eb 100644 --- a/source3/rpc_parse/parse_misc.c +++ b/source3/rpc_parse/parse_misc.c @@ -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); } diff --git a/source3/rpc_parse/parse_prs.c b/source3/rpc_parse/parse_prs.c index 75432627ab8..ef327f01a18 100644 --- a/source3/rpc_parse/parse_prs.c +++ b/source3/rpc_parse/parse_prs.c @@ -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); diff --git a/source3/rpc_parse/parse_svc.c b/source3/rpc_parse/parse_svc.c index 2134d86f47b..2ebab5aea5e 100644 --- a/source3/rpc_parse/parse_svc.c +++ b/source3/rpc_parse/parse_svc.c @@ -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 diff --git a/source3/rpc_server/srv_svcctl.c b/source3/rpc_server/srv_svcctl.c index be990639465..6cf9b8cd228 100644 --- a/source3/rpc_server/srv_svcctl.c +++ b/source3/rpc_server/srv_svcctl.c @@ -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 } }; diff --git a/source3/rpcclient/cmd_svcctl.c b/source3/rpcclient/cmd_svcctl.c index 63f0d9651ca..4f0978e17ff 100644 --- a/source3/rpcclient/cmd_svcctl.c +++ b/source3/rpcclient/cmd_svcctl.c @@ -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)