1# This file is part of Scapy 2# See http://www.secdev.org/projects/scapy for more information 3# Copyright (C) Lucas Preston <lucas.preston@infinite.io> 4# This program is published under a GPLv2 license 5 6# scapy.contrib.description = NFS Mount v3 7# scapy.contrib.status = loads 8 9from scapy.contrib.oncrpc import RPC, RPC_Call 10from scapy.packet import Packet, bind_layers 11from scapy.fields import IntField, StrLenField, IntEnumField, PacketField, \ 12 ConditionalField, FieldListField 13from scapy.contrib.nfs import File_Object 14 15mountstat3 = { 16 0: 'MNT3_OK', 17 1: 'MNT3ERR_PERM', 18 2: 'MNT3ERR_NOENT', 19 5: 'MNT3ERR_IO', 20 13: 'MNT3ERR_ACCES', 21 20: 'MNT3ERR_NOTDIR', 22 22: 'MNT3ERR_INVAL', 23 63: 'MNT3ERR_NAMETOOLONG', 24 10004: 'MNT3ERR_NOTSUPP', 25 10006: 'MNT3ERR_SERVERFAULT' 26} 27 28 29class Path(Packet): 30 name = 'Path' 31 fields_desc = [ 32 IntField('length', 0), 33 StrLenField('path', '', length_from=lambda pkt: pkt.length), 34 StrLenField('fill', '', length_from=lambda pkt: (4 - pkt.length) % 4) 35 ] 36 37 def extract_padding(self, s): 38 return '', s 39 40 def set(self, path, length=None, fill=None): 41 if length is None: 42 length = len(path) 43 if fill is None: 44 fill = b'\x00' * ((4 - len(path)) % 4) 45 self.length = length 46 self.path = path 47 self.fill = fill 48 49 50class NULL_Call(Packet): 51 name = 'MOUNT NULL Call' 52 fields_desc = [] 53 54 55class NULL_Reply(Packet): 56 name = 'MOUNT NULL Reply' 57 fields_desc = [] 58 59 60bind_layers(RPC, NULL_Call, mtype=0) 61bind_layers(RPC, NULL_Reply, mtype=1) 62bind_layers(RPC_Call, NULL_Call, program=100005, procedure=0, pversion=3) 63 64 65class MOUNT_Call(Packet): 66 name = 'MOUNT Call' 67 fields_desc = [ 68 PacketField('path', Path(), Path) 69 ] 70 71 72class MOUNT_Reply(Packet): 73 name = 'MOUNT Reply' 74 fields_desc = [ 75 IntEnumField('status', 0, mountstat3), 76 ConditionalField( 77 PacketField('filehandle', File_Object(), File_Object), 78 lambda pkt: pkt.status == 0 79 ), 80 ConditionalField(IntField('flavors', 0), lambda pkt: pkt.status == 0), 81 ConditionalField( 82 FieldListField( 83 'flavor', None, IntField('', None), 84 count_from=lambda pkt: pkt.flavors 85 ), 86 lambda pkt: pkt.status == 0 87 ) 88 ] 89 90 def get_filehandle(self): 91 if self.status == 0: 92 return self.filehandle.fh 93 return None 94 95 96bind_layers(RPC, MOUNT_Call, mtype=0) 97bind_layers(RPC, MOUNT_Reply, mtype=1) 98bind_layers(RPC_Call, MOUNT_Call, program=100005, procedure=1, pversion=3) 99 100 101class UNMOUNT_Call(Packet): 102 name = 'UNMOUNT Call' 103 fields_desc = [ 104 PacketField('path', Path(), Path) 105 ] 106 107 108class UNMOUNT_Reply(Packet): 109 name = 'UNMOUNT Reply' 110 fields_desc = [] 111 112 113bind_layers(RPC, UNMOUNT_Call, mtype=0) 114bind_layers(RPC, UNMOUNT_Reply, mtype=1) 115bind_layers( 116 RPC_Call, UNMOUNT_Call, program=100005, procedure=3, pversion=3 117) 118