1# Copyright (c) 2003-2016 CORE Security Technologies
2#
3# This software is provided under under a slightly modified version
4# of the Apache Software License. See the accompanying LICENSE file
5# for more information.
6#
7# Author: Alberto Solino (@agsolino)
8#
9# Description:
10#   [MS-TSCH] ATSVC Interface implementation
11#
12#   Best way to learn how to use these calls is to grab the protocol standard
13#   so you understand what the call does, and then read the test case located
14#   at https://github.com/CoreSecurity/impacket/tree/master/impacket/testcases/SMB_RPC
15#
16#   Some calls have helper functions, which makes it even easier to use.
17#   They are located at the end of this file.
18#   Helper functions start with "h"<name of the call>.
19#   There are test cases for them too.
20#
21from impacket.dcerpc.v5.ndr import NDRCALL, NDRSTRUCT, NDRPOINTER, NDRUniConformantArray
22from impacket.dcerpc.v5.dtypes import DWORD, LPWSTR, UCHAR, ULONG, LPDWORD, NULL
23from impacket import hresult_errors
24from impacket.uuid import uuidtup_to_bin
25from impacket.dcerpc.v5.rpcrt import DCERPCException
26
27MSRPC_UUID_ATSVC  = uuidtup_to_bin(('1FF70682-0A51-30E8-076D-740BE8CEE98B','1.0'))
28
29class DCERPCSessionError(DCERPCException):
30    def __init__(self, error_string=None, error_code=None, packet=None):
31        DCERPCException.__init__(self, error_string, error_code, packet)
32
33    def __str__( self ):
34        key = self.error_code
35        if hresult_errors.ERROR_MESSAGES.has_key(key):
36            error_msg_short = hresult_errors.ERROR_MESSAGES[key][0]
37            error_msg_verbose = hresult_errors.ERROR_MESSAGES[key][1]
38            return 'TSCH SessionError: code: 0x%x - %s - %s' % (self.error_code, error_msg_short, error_msg_verbose)
39        else:
40            return 'TSCH SessionError: unknown error code: 0x%x' % self.error_code
41
42################################################################################
43# CONSTANTS
44################################################################################
45ATSVC_HANDLE = LPWSTR
46# 2.3.1 Constant Values
47CNLEN = 15
48DNLEN = CNLEN
49UNLEN = 256
50MAX_BUFFER_SIZE = (DNLEN+UNLEN+1+1)
51
52# 2.3.7 Flags
53TASK_FLAG_INTERACTIVE                  = 0x1
54TASK_FLAG_DELETE_WHEN_DONE             = 0x2
55TASK_FLAG_DISABLED                     = 0x4
56TASK_FLAG_START_ONLY_IF_IDLE           = 0x10
57TASK_FLAG_KILL_ON_IDLE_END             = 0x20
58TASK_FLAG_DONT_START_IF_ON_BATTERIES   = 0x40
59TASK_FLAG_KILL_IF_GOING_ON_BATTERIES   = 0x80
60TASK_FLAG_RUN_ONLY_IF_DOCKED           = 0x100
61TASK_FLAG_HIDDEN                       = 0x200
62TASK_FLAG_RUN_IF_CONNECTED_TO_INTERNET = 0x400
63TASK_FLAG_RESTART_ON_IDLE_RESUME       = 0x800
64TASK_FLAG_SYSTEM_REQUIRED              = 0x1000
65TASK_FLAG_RUN_ONLY_IF_LOGGED_ON        = 0x2000
66
67################################################################################
68# STRUCTURES
69################################################################################
70# 2.3.4 AT_INFO
71class AT_INFO(NDRSTRUCT):
72    structure =  (
73        ('JobTime',DWORD),
74        ('DaysOfMonth',DWORD),
75        ('DaysOfWeek',UCHAR),
76        ('Flags',UCHAR),
77        ('Command',LPWSTR),
78    )
79
80class LPAT_INFO(NDRPOINTER):
81    referent = (
82        ('Data',AT_INFO),
83    )
84
85# 2.3.6 AT_ENUM
86class AT_ENUM(NDRSTRUCT):
87    structure =  (
88        ('JobId',DWORD),
89        ('JobTime',DWORD),
90        ('DaysOfMonth',DWORD),
91        ('DaysOfWeek',UCHAR),
92        ('Flags',UCHAR),
93        ('Command',LPWSTR),
94    )
95
96class AT_ENUM_ARRAY(NDRUniConformantArray):
97    item = AT_ENUM
98
99class LPAT_ENUM_ARRAY(NDRPOINTER):
100    referent = (
101        ('Data',AT_ENUM_ARRAY),
102    )
103
104# 2.3.5 AT_ENUM_CONTAINER
105class AT_ENUM_CONTAINER(NDRSTRUCT):
106    structure =  (
107        ('EntriesRead',DWORD),
108        ('Buffer',LPAT_ENUM_ARRAY),
109    )
110
111################################################################################
112# RPC CALLS
113################################################################################
114# 3.2.5.2.1 NetrJobAdd (Opnum 0)
115class NetrJobAdd(NDRCALL):
116    opnum = 0
117    structure = (
118        ('ServerName',ATSVC_HANDLE),
119        ('pAtInfo', AT_INFO),
120    )
121
122class NetrJobAddResponse(NDRCALL):
123    structure = (
124        ('pJobId',DWORD),
125        ('ErrorCode',ULONG),
126    )
127
128# 3.2.5.2.2 NetrJobDel (Opnum 1)
129class NetrJobDel(NDRCALL):
130    opnum = 1
131    structure = (
132        ('ServerName',ATSVC_HANDLE),
133        ('MinJobId', DWORD),
134        ('MaxJobId', DWORD),
135    )
136
137class NetrJobDelResponse(NDRCALL):
138    structure = (
139        ('ErrorCode',ULONG),
140    )
141
142# 3.2.5.2.3 NetrJobEnum (Opnum 2)
143class NetrJobEnum(NDRCALL):
144    opnum = 2
145    structure = (
146        ('ServerName',ATSVC_HANDLE),
147        ('pEnumContainer', AT_ENUM_CONTAINER),
148        ('PreferedMaximumLength', DWORD),
149        ('pResumeHandle', DWORD),
150    )
151
152class NetrJobEnumResponse(NDRCALL):
153    structure = (
154        ('pEnumContainer', AT_ENUM_CONTAINER),
155        ('pTotalEntries', DWORD),
156        ('pResumeHandle',LPDWORD),
157        ('ErrorCode',ULONG),
158    )
159
160# 3.2.5.2.4 NetrJobGetInfo (Opnum 3)
161class NetrJobGetInfo(NDRCALL):
162    opnum = 3
163    structure = (
164        ('ServerName',ATSVC_HANDLE),
165        ('JobId', DWORD),
166    )
167
168class NetrJobGetInfoResponse(NDRCALL):
169    structure = (
170        ('ppAtInfo', LPAT_INFO),
171        ('ErrorCode',ULONG),
172    )
173
174################################################################################
175# OPNUMs and their corresponding structures
176################################################################################
177OPNUMS = {
178 0 : (NetrJobAdd,NetrJobAddResponse ),
179 1 : (NetrJobDel,NetrJobDelResponse ),
180 2 : (NetrJobEnum,NetrJobEnumResponse ),
181 3 : (NetrJobGetInfo,NetrJobGetInfoResponse ),
182}
183
184################################################################################
185# HELPER FUNCTIONS
186################################################################################
187def hNetrJobAdd(dce, serverName = NULL, atInfo = NULL):
188    netrJobAdd = NetrJobAdd()
189    netrJobAdd['ServerName'] = serverName
190    netrJobAdd['pAtInfo'] = atInfo
191    return dce.request(netrJobAdd)
192
193def hNetrJobDel(dce, serverName = NULL, minJobId = 0, maxJobId = 0):
194    netrJobDel = NetrJobDel()
195    netrJobDel['ServerName'] = serverName
196    netrJobDel['MinJobId'] = minJobId
197    netrJobDel['MaxJobId'] = maxJobId
198    return dce.request(netrJobDel)
199
200def hNetrJobEnum(dce, serverName = NULL, pEnumContainer = NULL, preferedMaximumLength = 0xffffffff):
201    netrJobEnum = NetrJobEnum()
202    netrJobEnum['ServerName'] = serverName
203    netrJobEnum['pEnumContainer']['Buffer'] = pEnumContainer
204    netrJobEnum['PreferedMaximumLength'] = preferedMaximumLength
205    return dce.request(netrJobEnum)
206
207def hNetrJobGetInfo(dce, serverName = NULL, jobId = 0):
208    netrJobGetInfo = NetrJobGetInfo()
209    netrJobGetInfo['ServerName'] = serverName
210    netrJobGetInfo['JobId'] = jobId
211    return dce.request(netrJobGetInfo)