Harald Welte | 21caf32 | 2022-07-16 14:06:46 +0200 | [diff] [blame] | 1 | # coding=utf-8 |
| 2 | |
| 3 | # (C) 2022 by Harald Welte <laforge@osmocom.org> |
| 4 | # |
| 5 | # This program is free software: you can redistribute it and/or modify |
| 6 | # it under the terms of the GNU General Public License as published by |
| 7 | # the Free Software Foundation, either version 2 of the License, or |
| 8 | # (at your option) any later version. |
| 9 | # |
| 10 | # This program is distributed in the hope that it will be useful, |
| 11 | # but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 13 | # GNU General Public License for more details. |
| 14 | # |
| 15 | # You should have received a copy of the GNU General Public License |
| 16 | # along with this program. If not, see <http://www.gnu.org/licenses/>. |
| 17 | |
| 18 | |
| 19 | from pySim.gsmtap import GsmtapMessage, GsmtapSource |
| 20 | from . import ApduSource, PacketType, CardReset |
| 21 | |
| 22 | from pySim.apdu.ts_102_221 import ApduCommands as UiccApduCommands |
| 23 | from pySim.apdu.ts_31_102 import ApduCommands as UsimApduCommands |
| 24 | from pySim.apdu.global_platform import ApduCommands as GpApduCommands |
| 25 | ApduCommands = UiccApduCommands + UsimApduCommands + GpApduCommands |
| 26 | |
| 27 | class GsmtapApduSource(ApduSource): |
| 28 | """ApduSource for handling GSMTAP-SIM messages received via UDP, such as |
| 29 | those generated by simtrace2-sniff. Note that *if* you use IP loopback |
| 30 | and localhost addresses (which is the default), you will need to start |
| 31 | this source before starting simtrace2-sniff, as otherwise the latter will |
| 32 | claim the GSMTAP UDP port. |
| 33 | """ |
| 34 | def __init__(self, bind_ip:str='127.0.0.1', bind_port:int=4729): |
| 35 | """Create a UDP socket for receiving GSMTAP-SIM messages. |
| 36 | Args: |
| 37 | bind_ip: IP address to which the socket should be bound (default: 127.0.0.1) |
| 38 | bind_port: UDP port number to which the socket should be bound (default: 4729) |
| 39 | """ |
| 40 | super().__init__() |
| 41 | self.gsmtap = GsmtapSource(bind_ip, bind_port) |
| 42 | |
| 43 | def read_packet(self) -> PacketType: |
| 44 | gsmtap_msg, addr = self.gsmtap.read_packet() |
| 45 | if gsmtap_msg['type'] != 'sim': |
| 46 | raise ValueError('Unsupported GSMTAP type %s' % gsmtap_msg['type']) |
| 47 | sub_type = gsmtap_msg['sub_type'] |
| 48 | if sub_type == 'apdu': |
| 49 | return ApduCommands.parse_cmd_bytes(gsmtap_msg['body']) |
| 50 | elif sub_type == 'atr': |
| 51 | # card has been reset |
| 52 | return CardReset() |
| 53 | elif sub_type in ['pps_req', 'pps_rsp']: |
| 54 | # simply ignore for now |
| 55 | pass |
| 56 | else: |
| 57 | raise ValueError('Unsupported GSMTAP-SIM sub-type %s' % sub_type) |