1 /* packet-dcerpc-atsvc.c
2 * Routines for SMB \pipe\atsvc packet disassembly
3 * Copyright 2003 Jean-Baptiste Marchand <jbm@hsc.fr>
5 * $Id: packet-dcerpc-atsvc.c,v 1.5 2004/01/19 20:10:33 jmayer Exp $
7 * Ethereal - Network traffic analyzer
8 * By Gerald Combs <gerald@ethereal.com>
9 * Copyright 1998 Gerald Combs
11 * This program is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU General Public License
13 * as published by the Free Software Foundation; either version 2
14 * of the License, or (at your option) any later version.
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
32 #include <epan/packet.h>
33 #include "packet-dcerpc.h"
34 #include "packet-dcerpc-nt.h"
35 #include "packet-dcerpc-atsvc.h"
39 static int proto_dcerpc_atsvc = -1;
41 static int hf_atsvc_server = -1;
42 static int hf_atsvc_command = -1;
43 static int hf_atsvc_opnum = -1;
44 static int hf_atsvc_rc = -1;
45 static int hf_atsvc_job_id = -1;
46 static int hf_atsvc_job_time = -1;
47 static int hf_atsvc_job_days_of_month = -1;
48 static int hf_atsvc_job_days_of_week = -1;
49 static int hf_atsvc_job_flags = -1;
50 static int hf_atsvc_min_job_id = -1;
51 static int hf_atsvc_max_job_id = -1;
52 static int hf_atsvc_job_flags_noninteractive = -1;
53 static int hf_atsvc_job_flags_add_current_date = -1;
54 static int hf_atsvc_job_flags_runs_today = -1;
55 static int hf_atsvc_job_flags_exec_error = -1;
56 static int hf_atsvc_job_flags_run_periodically = -1;
57 static int hf_atsvc_job_enum_hnd = -1;
58 static int hf_atsvc_jobs_count = -1;
59 static int hf_atsvc_enum_handle = -1;
60 static int hf_atsvc_pref_max = -1;
61 static int hf_atsvc_num_entries = -1;
62 static int hf_atsvc_total_entries = -1;
64 static gint ett_dcerpc_atsvc = -1;
65 static gint ett_dcerpc_atsvc_job = -1;
66 static gint ett_dcerpc_atsvc_job_flags = -1;
70 IDL [ uuid(1ff70682-0a51-30e8-076d-740be8cee98b),
72 IDL implicit_handle(handle_t rpc_binding)
77 static e_uuid_t uuid_dcerpc_atsvc = {
78 0x1ff70682, 0x0a51, 0x30e8,
79 { 0x07, 0x6d, 0x74, 0x0b, 0xe8, 0xce, 0xe9, 0x8b }
82 static guint16 ver_dcerpc_atsvc = 1;
91 IDL [unique] [string] wchar_t *Command;
96 atsvc_dissect_AT_INFO_fields(tvbuff_t *tvb, int offset,
97 packet_info *pinfo, proto_tree *tree, guint8 *drep)
99 proto_item *item = NULL;
100 proto_tree *flags_tree = NULL;
103 guint8 job_hour, job_min, job_sec;
105 dcerpc_info *di = (dcerpc_info *) pinfo->private_data;
107 offset = dissect_ndr_uint32(tvb, offset, pinfo, NULL, drep,
110 job_hour = job_time / 3600000;
111 job_min = (job_time - job_hour * 3600000) / 60000;
112 job_sec = (job_time - (job_hour * 3600000) - (job_min * 60000)) / 1000;
113 job_msec = (job_time - (job_hour * 3600000) - (job_min * 60000) - (job_sec * 1000));
115 proto_tree_add_uint_format(tree, hf_atsvc_job_time, tvb, offset - 4,
116 4, job_time, "Time: %02d:%02d:%02d:%03d", job_hour, job_min, job_sec, job_msec);
118 offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
119 hf_atsvc_job_days_of_month, NULL);
121 offset = dissect_ndr_uint8(tvb, offset, pinfo, tree, drep,
122 hf_atsvc_job_days_of_week, NULL);
124 offset = dissect_ndr_uint8(tvb, offset, pinfo, NULL, drep,
127 item = proto_tree_add_text(tree, tvb, offset-1, 1, "Flags: 0x%02x", job_flags);
128 flags_tree = proto_item_add_subtree(item, ett_dcerpc_atsvc_job_flags);
132 #define JOB_RUN_PERIODICALLY 0x01
133 #define JOB_EXEC_ERROR 0x02
134 #define JOB_RUNS_TODAY 0x04
135 #define JOB_ADD_CURRENT_DATE 0x08
136 #define JOB_NONINTERACTIVE 0x10
138 if (di->call_data->opnum == ATSVC_JOB_ADD) {
140 if (job_flags & JOB_RUN_PERIODICALLY) {
141 proto_tree_add_boolean(flags_tree, hf_atsvc_job_flags_run_periodically,
142 tvb, offset-1, 1, job_flags);
145 proto_tree_add_boolean(flags_tree, hf_atsvc_job_flags_run_periodically,
146 tvb, offset-1, 1, 0);
150 if (job_flags & JOB_ADD_CURRENT_DATE) {
151 proto_tree_add_boolean(flags_tree, hf_atsvc_job_flags_add_current_date,
152 tvb, offset-1, 1, job_flags);
155 proto_tree_add_boolean(flags_tree, hf_atsvc_job_flags_add_current_date,
156 tvb, offset-1, 1, 0);
160 if (job_flags & JOB_NONINTERACTIVE) {
161 proto_tree_add_boolean(flags_tree, hf_atsvc_job_flags_noninteractive,
162 tvb, offset-1, 1, job_flags);
165 proto_tree_add_boolean(flags_tree, hf_atsvc_job_flags_noninteractive,
166 tvb, offset-1, 1, job_flags);
171 if ((di->call_data->opnum == ATSVC_JOB_GETINFO)
172 || (di->call_data->opnum == ATSVC_JOB_ENUM)) {
175 if (job_flags & JOB_RUN_PERIODICALLY) {
176 proto_tree_add_boolean(flags_tree, hf_atsvc_job_flags_run_periodically,
177 tvb, offset-1, 1, job_flags);
180 proto_tree_add_boolean(flags_tree, hf_atsvc_job_flags_run_periodically,
181 tvb, offset-1, 1, 0);
185 if (job_flags & JOB_EXEC_ERROR) {
186 proto_tree_add_boolean(flags_tree, hf_atsvc_job_flags_exec_error,
187 tvb, offset-1, 1, job_flags);
190 proto_tree_add_boolean(flags_tree, hf_atsvc_job_flags_exec_error,
191 tvb, offset-1, 1, 0);
195 if (job_flags & JOB_RUNS_TODAY) {
196 proto_tree_add_boolean(flags_tree, hf_atsvc_job_flags_runs_today,
197 tvb, offset-1, 1, job_flags);
200 proto_tree_add_boolean(flags_tree, hf_atsvc_job_flags_runs_today,
201 tvb, offset-1, 1, 0);
204 if (job_flags & JOB_NONINTERACTIVE) {
205 proto_tree_add_boolean(flags_tree, hf_atsvc_job_flags_noninteractive,
206 tvb, offset-1, 1, job_flags);
209 proto_tree_add_boolean(flags_tree, hf_atsvc_job_flags_noninteractive,
210 tvb, offset-1, 1, job_flags);
217 offset = dissect_ndr_str_pointer_item(tvb, offset, pinfo, tree, drep,
218 NDR_POINTER_UNIQUE, "Command", hf_atsvc_command, 0);
224 atsvc_dissect_AT_INFO(tvbuff_t *tvb, int offset,
225 packet_info *pinfo, proto_tree *tree, guint8 *drep)
227 proto_item *item = NULL;
228 proto_tree *subtree = NULL;
231 item = proto_tree_add_text(tree, tvb, offset, -1, "Job");
232 subtree = proto_item_add_subtree(item, ett_dcerpc_atsvc_job);
235 offset = atsvc_dissect_AT_INFO_fields(tvb, offset, pinfo, subtree, drep);
244 IDL [in] [unique] [string] wchar_t *Servername,
245 IDL [in] [ref] AT_INFO *element_22,
246 IDL [out] [ref] long *JobId
251 atsvc_dissect_add_rqst(tvbuff_t *tvb, int offset,
252 packet_info *pinfo, proto_tree *tree, guint8 *drep)
254 offset = dissect_ndr_str_pointer_item(tvb, offset, pinfo, tree, drep,
255 NDR_POINTER_UNIQUE, "Server", hf_atsvc_server, 0);
257 offset = atsvc_dissect_AT_INFO(tvb, offset, pinfo, tree, drep);
263 atsvc_dissect_add_reply(tvbuff_t *tvb, int offset,
264 packet_info *pinfo, proto_tree *tree, guint8 *drep)
266 offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
267 hf_atsvc_job_id, NULL);
269 offset = dissect_ntstatus(tvb, offset, pinfo, tree, drep,
278 IDL [in] [unique] [string] wchar_t *Servername,
279 IDL [in] long MinJobId,
280 IDL [in] long MaxJobId,
285 atsvc_dissect_del_rqst(tvbuff_t *tvb, int offset,
286 packet_info *pinfo, proto_tree *tree, guint8 *drep)
288 offset = dissect_ndr_str_pointer_item(tvb, offset, pinfo, tree, drep,
289 NDR_POINTER_UNIQUE, "Server", hf_atsvc_server, 0);
291 offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
292 hf_atsvc_min_job_id, NULL);
294 offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
295 hf_atsvc_max_job_id, NULL);
301 atsvc_dissect_del_reply(tvbuff_t *tvb, int offset,
302 packet_info *pinfo, proto_tree *tree, guint8 *drep)
304 offset = dissect_ntstatus(tvb, offset, pinfo, tree, drep,
314 IDL long DaysOfMonth;
317 IDL [unique] [string] wchar_t *Command;
322 atsvc_dissect_AT_ENUM(tvbuff_t *tvb, int offset,
323 packet_info *pinfo, proto_tree *tree, guint8 *drep)
325 proto_item *item = NULL;
326 proto_tree *subtree = NULL;
329 offset = dissect_ndr_uint32(tvb, offset, pinfo, NULL, drep,
333 item = proto_tree_add_text(tree, tvb, offset, -1, "Job %d", job_id);
334 subtree = proto_item_add_subtree(item, ett_dcerpc_atsvc_job);
337 proto_tree_add_uint_format(subtree, hf_atsvc_job_id, tvb, offset - 4,
338 4, job_id, "Job ID: %d", job_id);
340 offset = atsvc_dissect_AT_INFO_fields(tvb, offset, pinfo, subtree, drep);
347 atsvc_dissect_ENUM_HANDLE(tvbuff_t *tvb, int offset,
348 packet_info *pinfo, proto_tree *tree,
351 offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
352 hf_atsvc_enum_handle, 0);
358 atsvc_dissect_AT_ENUM_array(tvbuff_t *tvb, int offset,
359 packet_info *pinfo, proto_tree *tree,
362 offset = dissect_ndr_ucarray(tvb, offset, pinfo, tree, drep,
363 atsvc_dissect_AT_ENUM);
370 IDL long EntriesRead;
371 IDL [size_is(EntriesRead)] [unique] AT_ENUM *first_entry;
372 IDL } AT_ENUM_CONTAINER;
376 atsvc_dissect_AT_ENUM_CONTAINER(tvbuff_t *tvb, int offset,
377 packet_info *pinfo, proto_tree *tree,
380 offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
381 hf_atsvc_num_entries, NULL);
383 offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
384 atsvc_dissect_AT_ENUM_array, NDR_POINTER_UNIQUE,
385 "AT_ENUM array:", -1);
392 IDL long NetrJobEnum(
393 IDL [in] [unique] [string] wchar_t *Servername,
394 IDL [in,out] [ref] AT_ENUM_CONTAINER *PointerToBuffer,
395 IDL [in] long PreferredMaximumLength,
396 IDL [out] [ref] long *TotalEntries,
397 IDL [in,out] [unique] long *ResumeHandle
402 atsvc_dissect_enum_rqst(tvbuff_t *tvb, int offset,
403 packet_info *pinfo, proto_tree *tree, guint8 *drep)
405 offset = dissect_ndr_str_pointer_item(tvb, offset, pinfo, tree, drep,
406 NDR_POINTER_UNIQUE, "Server", hf_atsvc_server, 0);
408 offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
409 atsvc_dissect_AT_ENUM_CONTAINER,
410 NDR_POINTER_REF, "Job list", -1);
412 offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
413 hf_atsvc_pref_max, 0);
415 offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
416 atsvc_dissect_ENUM_HANDLE,
417 NDR_POINTER_UNIQUE, "Enum Handle", -1);
423 atsvc_dissect_enum_reply(tvbuff_t *tvb, int offset,
424 packet_info *pinfo, proto_tree *tree, guint8 *drep)
426 offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
427 atsvc_dissect_AT_ENUM_CONTAINER,
428 NDR_POINTER_REF, "Job list", -1);
430 offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
431 hf_atsvc_total_entries, 0);
433 offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
434 atsvc_dissect_ENUM_HANDLE,
435 NDR_POINTER_UNIQUE, "Enum Handle", -1);
437 offset = dissect_ntstatus(tvb, offset, pinfo, tree, drep,
445 IDL long NetrJobGetInfo(
446 IDL [in] [unique] [string] wchar_t *Servername,
448 IDL [out] [ref] AT_INFO **PointerToBuffer
453 atsvc_dissect_getinfo_rqst(tvbuff_t *tvb, int offset,
454 packet_info *pinfo, proto_tree *tree, guint8 *drep)
456 offset = dissect_ndr_str_pointer_item(tvb, offset, pinfo, tree, drep,
457 NDR_POINTER_UNIQUE, "Server", hf_atsvc_server, 0);
459 offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
460 hf_atsvc_job_id, NULL);
466 atsvc_dissect_getinfo_reply(tvbuff_t *tvb, int offset,
467 packet_info *pinfo, proto_tree *tree, guint8 *drep)
469 offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
470 atsvc_dissect_AT_INFO, NDR_POINTER_UNIQUE,
473 offset = dissect_ntstatus(tvb, offset, pinfo, tree, drep,
479 static dcerpc_sub_dissector dcerpc_atsvc_dissectors[] = {
480 { ATSVC_JOB_ADD, "NetrJobAdd", atsvc_dissect_add_rqst, atsvc_dissect_add_reply },
481 { ATSVC_JOB_DEL, "NetrJobDel", atsvc_dissect_del_rqst, atsvc_dissect_del_reply },
482 { ATSVC_JOB_ENUM, "NetrJobEnum", atsvc_dissect_enum_rqst, atsvc_dissect_enum_reply },
483 { ATSVC_JOB_GETINFO, "NetrJobGetInfo", atsvc_dissect_getinfo_rqst, atsvc_dissect_getinfo_reply },
484 { 0, NULL, NULL, NULL }
487 static const value_string atsvc_job_day_of_month[] = {
517 { 0x10000000, "29" },
518 { 0x20000000, "30" },
519 { 0x40000000, "31" },
525 static const value_string atsvc_job_day_of_week[] = {
529 { 0x04, "Wednesday" },
530 { 0x08, "Thursday" },
532 { 0x20, "Saturday" },
537 static const true_false_string tfs_job_flags_type = {
538 "Job runs periodically",
542 static const true_false_string tfs_job_flags_exec_error = {
543 "Last job execution FAILED",
544 "Last job execution was successful"
547 static const true_false_string tfs_job_flags_runs_today = {
548 "Job is scheduled to execute today",
549 "Job is NOT scheduled to execute today"
552 static const true_false_string tfs_job_flags_add_current_date = {
553 "Job is scheduled relative to current day of month",
554 "Job is NOT scheduled relative to current day of month"
557 static const true_false_string tfs_job_flags_noninteractive = {
558 "Job is NOT interactive",
563 proto_register_dcerpc_atsvc(void)
566 static hf_register_info hf[] = {
569 { "Server", "atsvc.server", FT_STRING, BASE_NONE,
570 NULL, 0x0, "Server Name", HFILL}},
573 { "Command", "atsvc.command", FT_STRING, BASE_NONE,
574 NULL, 0x0, "Command to execute", HFILL}},
577 { "Operation", "atsvc.opnum", FT_UINT16, BASE_DEC,
578 NULL, 0x0, "Operation", HFILL }},
581 { "Return code", "atsvc.rc", FT_UINT32, BASE_HEX,
582 VALS(NT_errors), 0x0, "atsvc status code", HFILL }},
585 { "Job ID", "atsvc.job_id", FT_UINT32,
586 BASE_DEC, NULL, 0x0, "Job ID", HFILL}},
588 { &hf_atsvc_job_time,
589 { "Job time", "atsvc.job_time", FT_UINT32,
590 BASE_DEC, NULL, 0x0, "Job time", HFILL}},
592 { &hf_atsvc_job_days_of_month,
593 { "Job day of the month", "atsvc.job_day_of_month", FT_UINT32,
594 BASE_DEC, VALS(atsvc_job_day_of_month), 0x0, "Job day of the month", HFILL}},
596 { &hf_atsvc_job_days_of_week,
597 { "Job day of the week", "atsvc.job_day_of_week", FT_UINT8,
598 BASE_DEC, VALS(atsvc_job_day_of_week), 0x0, "Job day of the week", HFILL}},
600 { &hf_atsvc_job_flags,
601 { "Job flags", "atsvc.job_flags", FT_UINT8,
602 BASE_DEC, NULL, 0x0, "Job flags", HFILL}},
604 { &hf_atsvc_min_job_id,
605 { "Min job ID", "atsvc.min_id", FT_UINT32,
606 BASE_DEC, NULL, 0x0, "Min job ID", HFILL}},
608 { &hf_atsvc_max_job_id,
609 { "Max job ID", "atsvc.max_id", FT_UINT32,
610 BASE_DEC, NULL, 0x0, "Max job ID", HFILL}},
612 { &hf_atsvc_job_flags_run_periodically,
613 { "Job type", "atsvc.jobs.flags.type", FT_BOOLEAN, 8,
614 TFS(&tfs_job_flags_type), JOB_RUN_PERIODICALLY, "Job type", HFILL }},
616 { &hf_atsvc_job_flags_exec_error,
617 { "Last job execution status", "atsvc.jobs.flags.exec_error", FT_BOOLEAN, 8,
618 TFS(&tfs_job_flags_exec_error), JOB_EXEC_ERROR, "Last job execution status", HFILL }},
620 { &hf_atsvc_job_flags_runs_today,
621 { "Job schedule", "atsvc.jobs.flags.runs_today", FT_BOOLEAN, 8,
622 TFS(&tfs_job_flags_runs_today), JOB_RUNS_TODAY, "Job schedule", HFILL }},
624 { &hf_atsvc_job_flags_add_current_date,
625 { "Job relative to current day of month", "atsvc.jobs.flags.add_current_date", FT_BOOLEAN, 8,
626 TFS(&tfs_job_flags_add_current_date), JOB_ADD_CURRENT_DATE, "Job relative to current day of month", HFILL }},
628 { &hf_atsvc_job_flags_noninteractive,
629 { "Job interactive status", "atsvc.jobs.flags.noninteractive", FT_BOOLEAN, 8,
630 TFS(&tfs_job_flags_noninteractive), JOB_NONINTERACTIVE, "Job interactive status", HFILL }},
632 { &hf_atsvc_job_enum_hnd,
633 { "Handle", "atsvc.job.hnd", FT_BYTES, BASE_NONE, NULL, 0x0, "Context handle", HFILL }},
635 { &hf_atsvc_jobs_count,
636 { "Jobs count", "atsvc.jobs_count", FT_UINT32,
637 BASE_DEC, NULL, 0x0, "Number of jobs", HFILL}},
639 { &hf_atsvc_enum_handle,
640 { "Enumeration handle", "atsvc.enum_hnd", FT_BYTES,
641 BASE_HEX, NULL, 0x0, "Enumeration Handle", HFILL}},
643 { &hf_atsvc_pref_max,
644 { "Preferred max length", "atsvc.pref.max.len", FT_INT32,
645 BASE_DEC, NULL, 0x0, "Preferred max length", HFILL}},
647 { &hf_atsvc_num_entries,
648 { "Returned entries", "atsvc.num.entries", FT_INT32,
649 BASE_DEC, NULL, 0x0, "Number of returned entries", HFILL}},
651 { &hf_atsvc_total_entries,
652 { "Total entries", "atsvc.total.entries", FT_INT32,
653 BASE_DEC, NULL, 0x0, "Total number of available entries", HFILL}},
657 static gint *ett[] = {
659 &ett_dcerpc_atsvc_job,
660 &ett_dcerpc_atsvc_job_flags
664 proto_dcerpc_atsvc = proto_register_protocol(
665 "Microsoft Task Scheduler Service", "ATSVC", "atsvc");
667 proto_register_field_array(proto_dcerpc_atsvc, hf, array_length(hf));
669 proto_register_subtree_array(ett, array_length(ett));
675 proto_reg_handoff_dcerpc_atsvc(void)
677 /* register protocol as dcerpc */
680 proto_dcerpc_atsvc, ett_dcerpc_atsvc, &uuid_dcerpc_atsvc,
681 ver_dcerpc_atsvc, dcerpc_atsvc_dissectors, hf_atsvc_opnum);