1# SPDX-License-Identifier: GPL-2.0-only
2# This file is part of Scapy
3# See https://scapy.net/ for more information
4# Copyright (C) Gabriel Potter
5
6"""
7Very partial RPC definitions for the following interfaces:
8- wkssvc (v1.0): 6BFFD098-A112-3610-9833-46C3F87E345A
9"""
10
11from enum import IntEnum
12import uuid
13
14from scapy.fields import StrFixedLenField
15from scapy.layers.dcerpc import (
16 register_dcerpc_interface,
17 DceRpcOp,
18 NDRConfPacketListField,
19 NDRConfVarStrLenFieldUtf16,
20 NDRConfVarStrNullFieldUtf16,
21 NDRFullPointerField,
22 NDRInt3264EnumField,
23 NDRIntField,
24 NDRPacket,
25 NDRPacketField,
26 NDRShortField,
27 NDRUnionField,
28)
29
30
31class LPWKSTA_INFO_100(NDRPacket):
32 ALIGNMENT = (4, 8)
33 fields_desc = [
34 NDRIntField("wki100_platform_id", 0),
35 NDRFullPointerField(
36 NDRConfVarStrNullFieldUtf16("wki100_computername", ""), deferred=True
37 ),
38 NDRFullPointerField(
39 NDRConfVarStrNullFieldUtf16("wki100_langroup", ""), deferred=True
40 ),
41 NDRIntField("wki100_ver_major", 0),
42 NDRIntField("wki100_ver_minor", 0),
43 ]
44
45
46class NetrWkstaGetInfo_Request(NDRPacket):
47 fields_desc = [
48 NDRFullPointerField(NDRConfVarStrNullFieldUtf16("ServerName", "")),
49 NDRIntField("Level", 0),
50 ]
51
52
53class NetrWkstaGetInfo_Response(NDRPacket):
54 fields_desc = [
55 NDRUnionField(
56 [
57 (
58 NDRFullPointerField(
59 NDRPacketField(
60 "WkstaInfo", LPWKSTA_INFO_100(), LPWKSTA_INFO_100
61 )
62 ),
63 (
64 (lambda pkt: getattr(pkt, "Level", None) == 100),
65 (lambda _, val: val.tag == 100),
66 ),
67 ),
68 ],
69 StrFixedLenField("WkstaInfo", "", length=0),
70 align=(4, 8),
71 switch_fmt=("L", "L"),
72 ),
73 NDRIntField("status", 0),
74 ]
75
76
77class NET_COMPUTER_NAME_TYPE(IntEnum):
78 NetPrimaryComputerName = 0
79 NetAlternateComputerNames = 1
80 NetAllComputerNames = 2
81 NetComputerNameTypeMax = 3
82
83
84class PUNICODE_STRING(NDRPacket):
85 ALIGNMENT = (4, 8)
86 fields_desc = [
87 NDRShortField("Length", None, size_of="Buffer", adjust=lambda _, x: (x * 2)),
88 NDRShortField(
89 "MaximumLength", None, size_of="Buffer", adjust=lambda _, x: (x * 2)
90 ),
91 NDRFullPointerField(
92 NDRConfVarStrLenFieldUtf16(
93 "Buffer", "", length_from=lambda pkt: (pkt.Length // 2)
94 ),
95 deferred=True,
96 ),
97 ]
98
99
100class PNET_COMPUTER_NAME_ARRAY(NDRPacket):
101 ALIGNMENT = (4, 8)
102 fields_desc = [
103 NDRIntField("EntryCount", None, size_of="ComputerNames"),
104 NDRFullPointerField(
105 NDRConfPacketListField(
106 "ComputerNames",
107 [PUNICODE_STRING()],
108 PUNICODE_STRING,
109 count_from=lambda pkt: pkt.EntryCount,
110 ),
111 deferred=True,
112 ),
113 ]
114
115
116class NetrEnumerateComputerNames_Request(NDRPacket):
117 fields_desc = [
118 NDRFullPointerField(NDRConfVarStrNullFieldUtf16("ServerName", "")),
119 NDRInt3264EnumField("NameType", 0, NET_COMPUTER_NAME_TYPE),
120 NDRIntField("Reserved", 0),
121 ]
122
123
124class NetrEnumerateComputerNames_Response(NDRPacket):
125 fields_desc = [
126 NDRFullPointerField(
127 NDRPacketField(
128 "ComputerNames", PNET_COMPUTER_NAME_ARRAY(), PNET_COMPUTER_NAME_ARRAY
129 )
130 ),
131 NDRIntField("status", 0),
132 ]
133
134
135WKSSVC_OPNUMS = {
136 0: DceRpcOp(NetrWkstaGetInfo_Request, NetrWkstaGetInfo_Response),
137 30: DceRpcOp(
138 NetrEnumerateComputerNames_Request, NetrEnumerateComputerNames_Response
139 ),
140}
141register_dcerpc_interface(
142 name="wkssvc",
143 uuid=uuid.UUID("6BFFD098-A112-3610-9833-46C3F87E345A"),
144 version="1.0",
145 opnums=WKSSVC_OPNUMS,
146)