1 /* packet-dcerpc-svcctl.c
2 * Routines for SMB \PIPE\svcctl packet disassembly
3 * Copyright 2003, Tim Potter <tpot@samba.org>
4 * Copyright 2003, Ronnie Sahlberg, added function dissectors
6 * $Id: packet-dcerpc-svcctl.c,v 1.7 2003/04/28 04:44:54 tpot Exp $
8 * Ethereal - Network traffic analyzer
9 * By Gerald Combs <gerald@ethereal.com>
10 * Copyright 1998 Gerald Combs
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * 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-svcctl.h"
35 #include "packet-dcerpc-nt.h"
37 #include "packet-smb-common.h"
39 static int proto_dcerpc_svcctl = -1;
40 static int hf_svcctl_opnum = -1;
41 static int hf_svcctl_machinename = -1;
42 static int hf_svcctl_database = -1;
43 static int hf_svcctl_access_mask = -1;
44 static int hf_svcctl_scm_rights_connect = -1;
45 static int hf_svcctl_scm_rights_create_service = -1;
46 static int hf_svcctl_scm_rights_enumerate_service = -1;
47 static int hf_svcctl_scm_rights_lock = -1;
48 static int hf_svcctl_scm_rights_query_lock_status = -1;
49 static int hf_svcctl_scm_rights_modify_boot_config = -1;
50 static int hf_svcctl_hnd = -1;
51 static int hf_svcctl_lock = -1;
52 static int hf_svcctl_rc = -1;
53 static int hf_svcctl_size = -1;
54 static int hf_svcctl_required_size = -1;
55 static int hf_svcctl_is_locked = -1;
56 static int hf_svcctl_lock_duration = -1;
57 static int hf_svcctl_lock_owner = -1;
58 static int hf_svcctl_service_type = -1;
59 static int hf_svcctl_service_state = -1;
60 static int hf_svcctl_resume = -1;
62 static gint ett_dcerpc_svcctl = -1;
64 static e_uuid_t uuid_dcerpc_svcctl = {
65 0x367abb81, 0x9844, 0x35f1,
66 { 0xad, 0x32, 0x98, 0xf0, 0x38, 0x00, 0x10, 0x03 }
69 static guint16 ver_dcerpc_svcctl = 2;
74 svcctl_dissect_pointer_long(tvbuff_t *tvb, int offset,
75 packet_info *pinfo, proto_tree *tree,
80 di=pinfo->private_data;
81 offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
87 svcctl_scm_specific_rights(tvbuff_t *tvb, gint offset, proto_tree *tree,
90 proto_tree_add_boolean(tree, hf_svcctl_scm_rights_modify_boot_config, tvb, offset, 4, access);
91 proto_tree_add_boolean(tree, hf_svcctl_scm_rights_query_lock_status, tvb, offset, 4, access);
92 proto_tree_add_boolean(tree, hf_svcctl_scm_rights_lock, tvb, offset, 4, access);
93 proto_tree_add_boolean(tree, hf_svcctl_scm_rights_enumerate_service, tvb, offset, 4, access);
94 proto_tree_add_boolean(tree, hf_svcctl_scm_rights_create_service, tvb, offset, 4, access);
95 proto_tree_add_boolean(tree, hf_svcctl_scm_rights_connect, tvb, offset, 4, access);
98 struct access_mask_info svcctl_scm_access_mask_info = {
100 svcctl_scm_specific_rights
104 * IDL long OpenSCManager(
105 * IDL [in] [string] [unique] char *MachineName,
106 * IDL [in] [string] [unique] char *DatabaseName,
107 * IDL [in] long access_mask,
108 * IDL [out] SC_HANDLE handle,
112 svcctl_dissect_OpenSCManager_rqst(tvbuff_t *tvb, int offset,
113 packet_info *pinfo, proto_tree *tree,
117 offset = dissect_ndr_pointer_cb(
118 tvb, offset, pinfo, tree, drep,
119 dissect_ndr_char_cvstring, NDR_POINTER_UNIQUE,
120 "MachineName", hf_svcctl_machinename, cb_str_postprocess,
121 GINT_TO_POINTER(CB_STR_COL_INFO | CB_STR_SAVE | 1));
124 offset = dissect_ndr_pointer_cb(
125 tvb, offset, pinfo, tree, drep,
126 dissect_ndr_char_cvstring, NDR_POINTER_UNIQUE,
127 "Database", hf_svcctl_database, cb_str_postprocess,
128 GINT_TO_POINTER(CB_STR_COL_INFO | 1));
131 offset = dissect_nt_access_mask(
132 tvb, offset, pinfo, tree, drep, hf_svcctl_access_mask,
133 &svcctl_scm_access_mask_info);
139 svcctl_dissect_OpenSCManager_reply(tvbuff_t *tvb, int offset,
140 packet_info *pinfo, proto_tree *tree,
143 dcerpc_info *di = (dcerpc_info *)pinfo->private_data;
144 dcerpc_call_value *dcv = (dcerpc_call_value *)di->call_data;
145 e_ctx_hnd policy_hnd;
147 int start_offset = offset;
149 /* We need the value of the policy handle and status before we
150 can retrieve the policy handle name. Then we can insert
151 the policy handle with the name in the proto tree. */
153 offset = dissect_nt_policy_hnd(
154 tvb, offset, pinfo, NULL, drep, hf_svcctl_hnd, &policy_hnd,
157 offset = dissect_ndr_uint32(
158 tvb, offset, pinfo, NULL, drep, hf_svcctl_rc, &status);
162 /* Associate the returned svcctl with a name */
164 if (dcv->private_data) {
167 pol_name = g_strdup_printf(
169 (char *)dcv->private_data);
171 dcerpc_smb_store_pol_name(&policy_hnd, pol_name);
174 g_free(dcv->private_data);
175 dcv->private_data = NULL;
181 offset = start_offset;
183 offset = dissect_nt_policy_hnd(
184 tvb, offset, pinfo, tree, drep, hf_svcctl_hnd, &policy_hnd,
187 offset = dissect_doserror(
188 tvb, offset, pinfo, tree, drep, hf_svcctl_rc, &status);
196 * IDL BOOL CloseServiceHandle(
197 * IDL [in][out] SC_HANDLE handle
201 svcctl_dissect_CloseServiceHandle_rqst(tvbuff_t *tvb, int offset,
202 packet_info *pinfo, proto_tree *tree,
205 e_ctx_hnd policy_hnd;
210 offset = dissect_nt_policy_hnd(
211 tvb, offset, pinfo, tree, drep, hf_svcctl_hnd, &policy_hnd,
214 dcerpc_smb_fetch_pol(&policy_hnd, &pol_name, NULL, NULL);
216 if (check_col(pinfo->cinfo, COL_INFO) && pol_name)
217 col_append_fstr(pinfo->cinfo, COL_INFO, ", %s",
224 svcctl_dissect_CloseServiceHandle_reply(tvbuff_t *tvb, int offset,
225 packet_info *pinfo, proto_tree *tree,
228 offset = dissect_nt_policy_hnd(
229 tvb, offset, pinfo, tree, drep, hf_svcctl_hnd, NULL,
232 offset = dissect_doserror(
233 tvb, offset, pinfo, tree, drep, hf_svcctl_rc, NULL);
241 * IDL long LockServiceDatabase(
242 * IDL [in] SC_HANDLE dbhandle,
243 * IDL [out] SC_HANDLE lock,
247 svcctl_dissect_LockServiceDatabase_rqst(tvbuff_t *tvb, int offset,
248 packet_info *pinfo, proto_tree *tree,
251 offset = dissect_nt_policy_hnd(
252 tvb, offset, pinfo, tree, drep, hf_svcctl_hnd, NULL,
258 svcctl_dissect_LockServiceDatabase_reply(tvbuff_t *tvb, int offset,
259 packet_info *pinfo, proto_tree *tree,
262 offset = dissect_nt_policy_hnd(
263 tvb, offset, pinfo, tree, drep, hf_svcctl_lock, NULL,
266 offset = dissect_doserror(
267 tvb, offset, pinfo, tree, drep, hf_svcctl_rc, NULL);
275 * IDL long UnlockServiceDatabase(
276 * IDL [in][out] SC_HANDLE lock,
280 svcctl_dissect_UnlockServiceDatabase_rqst(tvbuff_t *tvb, int offset,
281 packet_info *pinfo, proto_tree *tree,
284 offset = dissect_nt_policy_hnd(
285 tvb, offset, pinfo, tree, drep, hf_svcctl_lock, NULL,
291 svcctl_dissect_UnlockServiceDatabase_reply(tvbuff_t *tvb, int offset,
292 packet_info *pinfo, proto_tree *tree,
295 offset = dissect_nt_policy_hnd(
296 tvb, offset, pinfo, tree, drep, hf_svcctl_lock, NULL,
299 offset = dissect_doserror(
300 tvb, offset, pinfo, tree, drep, hf_svcctl_rc, NULL);
307 * IDL typedef struct {
308 * IDL long is_locked,
309 * IDL [unique][string] char *lock_owner,
310 * IDL long lock_duration,
314 svcctl_dissect_QUERY_SERVICE_LOCK_STATUS(tvbuff_t *tvb, int offset,
315 packet_info *pinfo, proto_tree *tree,
318 offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
319 hf_svcctl_is_locked, NULL);
321 offset = dissect_ndr_pointer(
322 tvb, offset, pinfo, tree, drep,
323 dissect_ndr_char_cvstring, NDR_POINTER_UNIQUE,
324 "Owner", hf_svcctl_lock_owner);
326 offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
327 hf_svcctl_lock_duration, NULL);
333 * IDL long QueryServiceLockStatus(
334 * IDL [in] SC_HANDLE db_handle,
335 * IDL [in] long buf_size,
336 * IDL [out][ref] QUERY_SERVICE_LOCK_STATUS *status,
337 * IDL [out][ref] long *required_buf_size
341 svcctl_dissect_QueryServiceLockStatus_rqst(tvbuff_t *tvb, int offset,
342 packet_info *pinfo, proto_tree *tree,
345 offset = dissect_nt_policy_hnd(
346 tvb, offset, pinfo, tree, drep, hf_svcctl_hnd, NULL,
349 offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
350 hf_svcctl_size, NULL);
355 svcctl_dissect_QueryServiceLockStatus_reply(tvbuff_t *tvb, int offset,
356 packet_info *pinfo, proto_tree *tree,
359 offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
360 svcctl_dissect_QUERY_SERVICE_LOCK_STATUS, NDR_POINTER_REF,
363 offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
364 hf_svcctl_required_size, NULL);
366 offset = dissect_doserror(
367 tvb, offset, pinfo, tree, drep, hf_svcctl_rc, NULL);
374 #define SERVICE_DRIVER 0x0b
375 #define SERVICE_WIN32 0x30
376 static const value_string svcctl_service_type_vals[] = {
377 { SERVICE_DRIVER, "SERVICE_DRIVER" },
378 { SERVICE_WIN32, "SERVICE_WIN32" },
382 #define SERVICE_ACTIVE 0x01
383 #define SERVICE_INACTIVE 0x02
384 #define SERVICE_STATE_ALL 0x03
385 static const value_string svcctl_service_status_vals[] = {
386 { SERVICE_ACTIVE, "SERVICE_ACTIVE" },
387 { SERVICE_INACTIVE, "SERVICE_INACTIVE" },
388 { SERVICE_STATE_ALL, "SERVICE_STATE_ALL" },
393 * IDL long EnumServicesStatus(
394 * IDL [in] SC_HANDLE db_handle,
395 * IDL [in] long type,
396 * IDL [in] long status,
397 * IDL [in] long buf_size,
398 * IDL [in][unique] long *resume_handle,
402 svcctl_dissect_EnumServicesStatus_rqst(tvbuff_t *tvb, int offset,
403 packet_info *pinfo, proto_tree *tree,
406 offset = dissect_nt_policy_hnd(
407 tvb, offset, pinfo, tree, drep, hf_svcctl_hnd, NULL,
410 offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
411 hf_svcctl_service_type, NULL);
413 offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
414 hf_svcctl_service_state, NULL);
416 offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
417 hf_svcctl_size, NULL);
419 offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
420 svcctl_dissect_pointer_long, NDR_POINTER_UNIQUE,
421 "Resume Handle", hf_svcctl_resume);
430 static dcerpc_sub_dissector dcerpc_svcctl_dissectors[] = {
431 { SVC_CLOSE_SERVICE_HANDLE, "CloseServiceHandle",
432 svcctl_dissect_CloseServiceHandle_rqst,
433 svcctl_dissect_CloseServiceHandle_reply },
434 { SVC_STOP_SERVICE, "Stop", NULL, NULL },
435 { SVC_DELETE, "Delete", NULL, NULL },
436 { SVC_LOCK_SERVICE_DATABASE, "LockServiceDatabase",
437 svcctl_dissect_LockServiceDatabase_rqst,
438 svcctl_dissect_LockServiceDatabase_reply },
439 { SVC_GET_SVC_SEC, "Get security", NULL, NULL },
440 { SVC_UNLOCK_SERVICE_DATABASE, "UnlockServiceDatabase",
441 svcctl_dissect_UnlockServiceDatabase_rqst,
442 svcctl_dissect_UnlockServiceDatabase_reply },
443 { SVC_CHANGE_SVC_CONFIG, "Change config", NULL, NULL },
444 { SVC_ENUM_SVCS_STATUS, "Enum status", NULL, NULL },
445 { SVC_OPEN_SC_MAN, "Open SC Manager", NULL, NULL },
446 { SVC_OPEN_SERVICE, "Open service", NULL, NULL },
447 { SVC_QUERY_SVC_CONFIG, "Query config", NULL, NULL },
448 { SVC_START_SERVICE, "Start", NULL, NULL },
449 { SVC_QUERY_DISP_NAME, "Query display name", NULL, NULL },
450 { SVC_ENUM_SERVICES_STATUS, "EnumServicesStatus",
451 svcctl_dissect_EnumServicesStatus_rqst,
453 { SVC_OPEN_SC_MANAGER, "OpenSCManager",
454 svcctl_dissect_OpenSCManager_rqst,
455 svcctl_dissect_OpenSCManager_reply },
456 { SVC_OPEN_SERVICE_A, "Open Service A", NULL, NULL },
457 { SVC_QUERY_SERVICE_LOCK_STATUS, "QueryServiceLockStatus",
458 svcctl_dissect_QueryServiceLockStatus_rqst,
459 svcctl_dissect_QueryServiceLockStatus_reply },
460 {0, NULL, NULL, NULL}
463 static const value_string svcctl_opnum_vals[] = {
464 { SVC_CLOSE_SERVICE_HANDLE, "CloseServiceHandle" },
465 { SVC_STOP_SERVICE, "StopService" },
466 { SVC_DELETE, "DeleteService" },
467 { SVC_LOCK_SERVICE_DATABASE, "LockServiceDatabase" },
468 { SVC_GET_SVC_SEC, "QueryServiceObjectSecurity" },
469 { SVC_UNLOCK_SERVICE_DATABASE, "UnockServiceDatabase" },
470 { SVC_CHANGE_SVC_CONFIG, "Change config" },
471 { SVC_ENUM_SVCS_STATUS, "Enum status" },
472 { SVC_OPEN_SC_MAN, "Open SC Manager" },
473 { SVC_OPEN_SERVICE, "Open service" },
474 { SVC_QUERY_SVC_CONFIG, "Query config" },
475 { SVC_START_SERVICE, "Start" },
476 { SVC_QUERY_DISP_NAME, "Query display name" },
477 { SVC_ENUM_SERVICES_STATUS, "EnumServicesStatus" },
478 { SVC_OPEN_SC_MANAGER, "OpenSCManager" },
479 { SVC_OPEN_SERVICE_A, "Open Service A" },
480 { SVC_QUERY_SERVICE_LOCK_STATUS, "QueryServiceLockStatus" },
486 proto_register_dcerpc_svcctl(void)
488 static hf_register_info hf[] = {
490 { "Operation", "svcctl.opnum", FT_UINT16, BASE_DEC,
491 VALS(svcctl_opnum_vals), 0x0, "Operation", HFILL }},
492 { &hf_svcctl_machinename,
493 { "MachineName", "svcctl.machinename", FT_STRING, BASE_NONE,
494 NULL, 0x0, "Name of the host we want to open the database on", HFILL }},
495 { &hf_svcctl_database,
496 { "Database", "svcctl.database", FT_STRING, BASE_NONE,
497 NULL, 0x0, "Name of the database to open", HFILL }},
498 { &hf_svcctl_access_mask,
499 { "Access Mask", "svcctl.access_mask", FT_UINT32, BASE_HEX,
500 NULL, 0x0, "SVCCTL Access Mask", HFILL }},
501 { &hf_svcctl_scm_rights_connect,
502 { "Connect", "svcctl.scm_rights_connect", FT_BOOLEAN, 32,
503 TFS(&flags_set_truth), 0x00000001, "SVCCTL Rights to connect to SCM", HFILL }},
504 { &hf_svcctl_scm_rights_create_service,
505 { "Create Service", "svcctl.scm_rights_create_service", FT_BOOLEAN, 32,
506 TFS(&flags_set_truth), 0x00000002, "SVCCTL Rights to create services", HFILL }},
507 { &hf_svcctl_scm_rights_enumerate_service,
508 { "Enumerate Service", "svcctl.scm_rights_enumerate_service", FT_BOOLEAN, 32,
509 TFS(&flags_set_truth), 0x00000004, "SVCCTL Rights to enumerate services", HFILL }},
510 { &hf_svcctl_scm_rights_lock,
511 { "Lock", "svcctl.scm_rights_lock", FT_BOOLEAN, 32,
512 TFS(&flags_set_truth), 0x00000008, "SVCCTL Rights to lock database", HFILL }},
513 { &hf_svcctl_scm_rights_query_lock_status,
514 { "Query Lock Status", "svcctl.scm_rights_query_lock_status", FT_BOOLEAN, 32,
515 TFS(&flags_set_truth), 0x00000010, "SVCCTL Rights to query database lock status", HFILL }},
516 { &hf_svcctl_scm_rights_modify_boot_config,
517 { "Modify Boot Config", "svcctl.scm_rights_modify_boot_config", FT_BOOLEAN, 32,
518 TFS(&flags_set_truth), 0x00000020, "SVCCTL Rights to modify boot config", HFILL }},
520 { "Context Handle", "svcctl.hnd", FT_BYTES, BASE_NONE,
521 NULL, 0x0, "SVCCTL Context handle", HFILL }},
523 { "Lock", "svcctl.lock", FT_BYTES, BASE_NONE,
524 NULL, 0x0, "SVCCTL Database Lock", HFILL }},
526 { "Return code", "svcctl.rc", FT_UINT32, BASE_HEX,
527 VALS(DOS_errors), 0x0, "SVCCTL return code", HFILL }},
529 { "Size", "svcctl.size", FT_UINT32, BASE_DEC,
530 NULL, 0x0, "SVCCTL size of buffer", HFILL }},
531 { &hf_svcctl_required_size,
532 { "Required Size", "svcctl.required_size", FT_UINT32, BASE_DEC,
533 NULL, 0x0, "SVCCTL required size of buffer for data to fit", HFILL }},
534 { &hf_svcctl_is_locked,
535 { "IsLocked", "svcctl.is_locked", FT_UINT32, BASE_DEC,
536 NULL, 0x0, "SVCCTL whether the database is locked or not", HFILL }},
537 { &hf_svcctl_lock_duration,
538 { "Duration", "svcctl.lock_duration", FT_UINT32, BASE_DEC,
539 NULL, 0x0, "SVCCTL number of seconds the database has been locked", HFILL }},
540 { &hf_svcctl_lock_owner,
541 { "Owner", "svcctl.lock_owner", FT_STRING, BASE_NONE,
542 NULL, 0x0, "SVCCTL the user that holds the database lock", HFILL }},
543 { &hf_svcctl_service_type,
544 { "Type", "svcctl.service_type", FT_UINT32, BASE_DEC,
545 VALS(svcctl_service_type_vals), 0x0, "SVCCTL type of service", HFILL }},
547 { &hf_svcctl_service_state,
548 { "State", "svcctl.service_state", FT_UINT32, BASE_DEC,
549 VALS(svcctl_service_status_vals), 0x0, "SVCCTL service state", HFILL }},
551 { "Resume Handle", "svcctl.resume", FT_UINT32, BASE_DEC,
552 NULL, 0x0, "SVCCTL resume handle", HFILL }},
555 static gint *ett[] = {
559 proto_dcerpc_svcctl = proto_register_protocol(
560 "Microsoft Service Control", "SVCCTL", "svcctl");
562 proto_register_field_array(proto_dcerpc_svcctl, hf, array_length(hf));
563 proto_register_subtree_array(ett, array_length(ett));
567 proto_reg_handoff_dcerpc_svcctl(void)
569 /* Register protocol as dcerpc */
571 dcerpc_init_uuid(proto_dcerpc_svcctl, ett_dcerpc_svcctl,
572 &uuid_dcerpc_svcctl, ver_dcerpc_svcctl,
573 dcerpc_svcctl_dissectors, hf_svcctl_opnum);