1
2
3 """Remote Procedure Call."""
4
5 import struct
6 import dpkt
7
8
9 CALL = 0
10 REPLY = 1
11
12
13 AUTH_NONE = AUTH_NULL = 0
14 AUTH_UNIX = 1
15 AUTH_SHORT = 2
16 AUTH_DES = 3
17
18
19 MSG_ACCEPTED = 0
20 MSG_DENIED = 1
21
22
23 SUCCESS = 0
24 PROG_UNAVAIL = 1
25 PROG_MISMATCH = 2
26 PROC_UNAVAIL = 3
27 GARBAGE_ARGS = 4
28 SYSTEM_ERR = 5
29
30
31 RPC_MISMATCH = 0
32 AUTH_ERROR = 1
33
34 -class RPC(dpkt.Packet):
35 __hdr__ = (
36 ('xid', 'I', 0),
37 ('dir', 'I', CALL)
38 )
39 - class Auth(dpkt.Packet):
40 __hdr__ = (('flavor', 'I', AUTH_NONE), )
46 return 8 + len(self.data)
48 return self.pack_hdr() + struct.pack('>I', len(self.data)) + \
49 str(self.data)
50
51 - class Call(dpkt.Packet):
52 __hdr__ = (
53 ('rpcvers', 'I', 2),
54 ('prog', 'I', 0),
55 ('vers', 'I', 0),
56 ('proc', 'I', 0)
57 )
59 dpkt.Packet.unpack(self, buf)
60 self.cred = RPC.Auth(self.data)
61 self.verf = RPC.Auth(self.data[len(self.cred):])
62 self.data = self.data[len(self.cred) + len(self.verf):]
70
71 - class Reply(dpkt.Packet):
72 __hdr__ = (('stat', 'I', MSG_ACCEPTED), )
73
75 __hdr__ = (('stat', 'I', SUCCESS), )
77 self.verf = RPC.Auth(buf)
78 buf = buf[len(self.verf):]
79 self.stat = struct.unpack('>I', buf[:4])[0]
80 if self.stat == SUCCESS:
81 self.data = buf[4:]
82 elif self.stat == PROG_MISMATCH:
83 self.low, self.high = struct.unpack('>II', buf[4:12])
84 self.data = buf[12:]
86 if self.stat == PROG_MISMATCH: n = 8
87 else: n = 0
88 return len(self.verf) + 4 + n + len(self.data)
90 if self.stat == PROG_MISMATCH:
91 return str(self.verf) + struct.pack('>III', self.stat,
92 self.low, self.high) + self.data
93 return str(self.verf) + dpkt.Packet.__str__(self)
94
96 __hdr__ = (('stat', 'I', AUTH_ERROR), )
98 dpkt.Packet.unpack(self, buf)
99 if self.stat == RPC_MISMATCH:
100 self.low, self.high = struct.unpack('>II', self.data[:8])
101 self.data = self.data[8:]
102 elif self.stat == AUTH_ERROR:
103 self.why = struct.unpack('>I', self.data[:4])[0]
104 self.data = self.data[4:]
106 if self.stat == RPC_MISMATCH: n = 8
107 elif self.stat == AUTH_ERROR: n =4
108 else: n = 0
109 return 4 + n + len(self.data)
111 if self.stat == RPC_MISMATCH:
112 return struct.pack('>III', self.stat, self.low,
113 self.high) + self.data
114 elif self.stat == AUTH_ERROR:
115 return struct.pack('>II', self.stat, self.why) + self.data
116 return dpkt.Packet.__str__(self)
117
124
126 dpkt.Packet.unpack(self, buf)
127 if self.dir == CALL:
128 self.data = self.call = self.Call(self.data)
129 elif self.dir == REPLY:
130 self.data = self.reply = self.Reply(self.data)
131
133 l = []
134 while buf:
135 if buf.startswith('\x00\x00\x00\x01'):
136 p = cls(buf[4:])
137 l.append(p)
138 buf = p.data
139 elif buf.startswith('\x00\x00\x00\x00'):
140 break
141 else:
142 raise dpkt.UnpackError, 'invalid XDR list'
143 return l
144
146 return '\x00\x00\x00\x01'.join(map(str, args)) + '\x00\x00\x00\x00'
147