nameserver response not all data returned - dns

When I do a request to a nameserver which has dnssec the response is sometimes incomplete
i looked around on the web and found some information regarding the issue
2.3.4 Size limits
https://www.rfc-editor.org/rfc/rfc1035
It saysUDP messages 512 octets or less
To receive a bigger response I need EDNS0 so i can receive a max of 4096 bytes.I can't really figure out how to use/enable EDNS0
EDNS0 info:
https://www.rfc-editor.org/rfc/rfc2671
EDIT
i have to send an OPT RR with my request to get more data back. i have an example from microsoft, but they use a type RRSIG. i want to use a type ANY.
http://img266.imageshack.us/img266/6707/optf.png
The question:
can someone explain how EDNS0 works and why my opt rr is not working.(i use the same as the microsoft example)
thx in advance:)

For some odd reason my request is working now.
Request i send:
01 01 01 00 00 01 00 00 00 00 00 01". domain2dns($domainname) ."00 00 ff 00 01 00 00 29 10 00 00 00 00 00 00 00
explanation of the EDNS part
Name: 00
Type: 00 29
UDP Payload size: 10 00
Higher bits in extended RCODE:00
EDNS0 version: 00
Z: 00 00
Data Lenght: 00 00
NAME - - domain name -- empty (root domain)
TYPE - - u_int16_t ---- OPT
CLASS - u_int16_t ---- sender's UDP payload size
TTL - - - u_int32_t ---- extended RCODE and flags
RDLEN - u_int16_t ---- describes RDATA
RDATA - octet stream - {attribute,value} pairs
Problem solved
thx guys :)

Related

Why RDATA in EDNS(0) resource record has 1 octet?

I want to understand why EDNS(0) resource records contains an extra octet? I read RFC 6891 and RFC 1035. It says nothing about case when RDLENGHT == 0 but RDATA == "\0".
To test this here python code
import binascii
import socket
def send_udp_message(message, address, port):
"""send_udp_message sends a message to UDP server
message should be a hexadecimal encoded string
"""
message = message.replace(" ", "").replace("\n", "")
server_address = (address, port)
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
try:
sock.sendto(binascii.unhexlify(message), server_address)
data, _ = sock.recvfrom(4096)
finally:
sock.close()
return binascii.hexlify(data).decode("utf-8")
def format_hex(hex):
"""format_hex returns a pretty version of a hex string"""
octets = [hex[i:i+2] for i in range(0, len(hex), 2)]
pairs = [" ".join(octets[i:i+2]) for i in range(0, len(octets), 2)]
return "\n".join(pairs)
message = "AA AA 01 00 00 01 00 00 00 00 00 01 " \
"07 65 78 61 6d 70 6c 65 03 63 6f 6d 00 00 01 00 01 "
# EDNS(0) resource record
message += "00 00 " # NAME
message += "29 00 " # TYPE
message += "FF 00 00 80 " # TTL
message += "00 00 " # RDLENGTH
# message += "00" # RDATA
response = send_udp_message(message, "8.8.8.8", 53)
print(format_hex(response))
Dns query returns here error. But if uncomment RDATA line it returns success.
You misread section §6.1.2 of RFC 6891, so the RFCs are not "lies".
It says:
+------------+--------------+------------------------------+
| Field Name | Field Type | Description |
+------------+--------------+------------------------------+
| NAME | domain name | MUST be 0 (root domain) |
| TYPE | u_int16_t | OPT (41) |
| CLASS | u_int16_t | requestor's UDP payload size |
| TTL | u_int32_t | extended RCODE and flags |
| RDLEN | u_int16_t | length of all RDATA |
| RDATA | octet stream | {attribute,value} pairs |
+------------+--------------+------------------------------+
so 6 pieces of information while your code has only 5 pieces:
# EDNS(0) resource record
message += "00 00 " # NAME
message += "29 00 " # TYPE
message += "FF 00 00 80 " # TTL
message += "00 00 " # RDLENGTH
# message += "00" # RDATA
You are missing the CLASS between TYPE and TTL, hence things are not interpreted the way you think they are.
You are also misreading how the bytes work for the name.
It is not:
00 00 NAME
29 00 TYPE
FF 00 00 80 TTL
00 00 RDLENGTH
but really:
00 NAME (root domain per EDNS(0) specification, which is a sole zero)
00 29 TYPE (41, per specification)
00 FF CLASS (255, considered as payload)
00 00 80 00 TTL, read as 00 = EXTENDED-CODE, 00 = VERSION (mandatory), 80 = DO set plus everything else 0 as the final 00 byte, per specification
00 RDLENGTH
and the final item RDLENGTH is then not properly formatted per the RFC 1035 specification as it is 2 bytes (16 bits).
Once you comment your last line, RDLENGTH becomes 00 00 and then is valid.
And there is indeed no RDATA part in your message.
What you believe being a 00 value in RDATA is in fact the last byte of RDLENGTH but you did not parse the stream correctly.
Had you used dnspython as advised to you, you would have seen the problem immediately with the proper mapping of fields:
In [1]: import dns
In [2]: import dns.message
In [10]: stream = 'AA AA 01 00 00 01 00 00 00 00 00 01 07 65 78 61 6d 70 6c 65 03 63 6f 6d 00 00 01 00 01 00 00 29 00 FF 00 00 80 00 00 00'
In [11]: data=''.join(chr(int(x, base=16)) for x in stream.split(' '))
In [12]: m = dns.message.from_wire(data)
In [13]: print m
id 43690
opcode QUERY
rcode NOERROR
flags RD
edns 0
eflags DO
payload 255
;QUESTION
example.com. IN A
;ANSWER
;AUTHORITY
;ADDITIONAL
Had you wanted to do that you could have simulated the expected bytes stream that way:
(starting from your message)
In [31]: m = dns.message.from_wire(data)
In [32]: print m
id 43690
opcode QUERY
rcode NOERROR
flags RD
edns 0
eflags DO
payload 255
;QUESTION
example.com. IN A
;ANSWER
;AUTHORITY
;ADDITIONAL
(creating a new one to look like yours)
In [39]: mm = dns.message.make_query('example.com.', 'A', use_edns=0, payload=255, want_dnssec=True)
In [40]: mm.id=43690
In [41]: print mm
id 43690
opcode QUERY
rcode NOERROR
flags RD
edns 0
eflags DO
payload 255
;QUESTION
example.com. IN A
;ANSWER
;AUTHORITY
;ADDITIONAL
(now looking at its wire representation)
In [46]: print ' '.join(hex(ord(d)) for d in mm.to_wire())
0xaa 0xaa 0x1 0x0 0x0 0x1 0x0 0x0 0x0 0x0 0x0 0x1 0x7 0x65 0x78 0x61 0x6d 0x70 0x6c 0x65 0x3 0x63 0x6f 0x6d 0x0 0x0 0x1 0x0 0x1 0x0 0x0 0x29 0x0 0xff 0x0 0x0 0x80 0x0 0x0 0x0
Comparing with your bytestream:
dnspython: AA AA 01 00 00 01 00 00 00 00 00 01 07 65 78 61 6d 70 6c 65 03 63 6f 6d 00 00 01 00 01 00 00 29 00 FF 00 00 80 00 00 00
you: AA AA 01 00 00 01 00 00 00 00 00 01 07 65 78 61 6d 70 6c 65 03 63 6f 6d 00 00 01 00 01 00 00 29 00 FF 00 00 80 00 00
Note the missing final 00 being in your commented line.
This shows that existing good libraries, as dnspython is, really help sometimes better understanding RFCs or other specifications. And in the world of DNS there are many RFCs, sometimes conflicting between each other, with ambiguous parts, etc. So using existing libraries for tests and/or studying their source code really helps, if you want this advice.

Comparing big files

So I've got really big .bin files with bytes written in them. They have 96-bit numbers written in them as two's complement numbers (still no ASCII, only bytes). Now I have to write an assembly program to sort the numbers in this files and save it to another file (don't ask why, assembly class). I've done it for a file with 32k numbers, like this:
./main < inSort32Kx96b.bin > XD.bin
diff outSort32Kx96b.bin XD.bin
The file outSort32Kx96b.bin is given to me by my teacher. So now diff doesn't output anything, they are identical (I can check that with hexdump or mcview). But I got another file inSort1Kx96b.bin. And I also sort it. But then diff says:
Binary files outSort1Kx96b.bin and XD.bin differ
#Edit:
cmp gave the number of byte where those 2 files differ. Now I can see the difference:
So the difference appears from 0x000017C0. Then I don't know now. If they are written as two's complement numbers in little endian order, then which one is bigger, f.e
00 00 00 00 00 00 00 81 00 00 00 00
or
00 00 00 00 00 00 00 7F 00 00 00 00
?
A hexdump shows you the single bytes in big endian order. If a bunch of bytes have to be interpreted as a number, only the byte order is reversed.
little endian big endian (C notation)
AB CD EF = 0xEFCDAB
01 02 03 04 05 06 07 08 09 10 11 12 = 0x121110090807060504030201
Let's translate your examples to big endian order:
0x000000008100000000000000
0x000000007F00000000000000
You can see that the first number is bigger.
"Two's complement number" is not a very clear expression. Better is "signed integer". The sign which shows whether the number is positive or negativ, is the very first bit of the number. This bit can be found at the begginning of a big endian number and the end of a little endian number.
Positive:
00 00 00 00 00 00 00 81 00 00 00 00 = 0x000000008100000000000000
00 00 00 00 00 00 00 81 00 00 00 10 = 0x100000008100000000000000
00 00 00 00 00 00 00 81 00 00 00 7F = 0x7F0000008100000000000000
Negativ:
00 00 00 00 00 00 00 81 00 00 00 80 = 0x800000008100000000000000
00 00 00 00 00 00 00 81 00 00 00 CD = 0xCD0000008100000000000000
00 00 00 00 00 00 00 81 00 00 00 F0 = 0xF00000008100000000000000

Error 0x6700 in securechannel.processSecurity(apdu)

I want to generate gp secure channel 01. my trace is:
Send: 80 50 00 00 08 00 00 00 00 00 00 00 00
Recv: 00 00 00 00 00 00 00 00 00 00 FF 02 00 02 0E 5A 8F F4 57 DD 35 5C 49 A6 8B 15 E9 A5 9000
so I have :
Card challenge= 00 02 0E 5A 8F F4 57 DD
Host challenge=00 00 00 00 00 00 00 00
according SPC01: image
Derivation data== 8F F4 57 DD 00 00 00 00 00 02 0E 5A 00 00 00 00
IV=0000000000000000
c_ENC: 404142434445464748494A4B4C4D4E4F
according this image and 3Des online
session s_ENC= C72F032C8BAD55D4D2579295CCF0A6CA
now :
hot-auth_data = card challenge + host challenge + pad
host-auth= 00020E5A8FF457DD00000000000000008000000000000000
s_ENC=C72F032C8BAD55D4D2579295CCF0A6CA
IV=0000000000000000
===========
result= 93CC77E144488A031BFFCCC62EB3B5C233A485F8255FE90E
Host cryptogram= 33A485F8255FE90E
but when I send :
848200000833A485F8255FE90E
I have error 0x6700 in method SDInstruction in line
short len = sc.processSecurity(apdu);
public void process(APDU apdu) throws ISOException {
if (selectingApplet()) {
return;
}
byte[] buffer = apdu.getBuffer();
switch (buffer[ISO7816.OFFSET_INS]) {
case ISO7816.INS_SELECT:
select();
return;
case INS_INIT_UPDATE:
case INS_EXT_AUTH:
SDInstruction(apdu);
break;
}
}
private void SDInstruction(APDU apdu)
{
byte[] buf = apdu.getBuffer();
byte cla = buf[ISO7816.OFFSET_CLA];
byte ins = buf[ISO7816.OFFSET_INS];
apdu.setIncomingAndReceive();
if(ins == INS_INIT_UPDATE)
sc = GPSystem.getSecureChannel();
short len = sc.processSecurity(apdu);
apdu.setOutgoing();
apdu.setOutgoingLength(len);
apdu.sendBytes(ISO7816.OFFSET_CDATA, (short) len);
}
Your card is using SCP02 and not SCP01.
Given the response to the INITIALIZE UPDATE command:
00 00 00 00 00 00 00 00 00 00 FF 02 00 02 0E 5A 8F F4 57 DD 35 5C 49 A6 8B 15 E9 A5 9000
The highlighted part is the "Key Information" which contains:
"Key Version Number" -- in your trace 0xFF
"Secure Channel Protocol Identifier" -- in your trace it is 0x02 indicating SCP02
See the Global Platform Card Specification for further reference (sections describing the INITIALIZE UPDATE command).
So you need to establish the secure channel with the card according to the SCP02.
Some additional (random) notes:
be sure to check the "i" secure channel parameter encoded inside the "Card Recognition Data" (tag '64') as well
you might want to look at the method GlobalPlatform.openSecureChannel() and the inner class GlobalPlatform.SCP0102Wrapper in the GlobalPlatformPro tool source code
Good luck!
According to the GlobalPlatform specification, the EXTERNAL AUTHENTICATE command has to include the host cryptogram as well as the MAC. Both are 8 bytes long, hence, your command should be 16 bytes in total.
If you want to implement the generation of this MAC value yourself, you can follow the description in the GlobalPlatform spec. But I suggest you to make use of available open source implementation. For example: GPJ is a Java implementation of the GlobalPlatform specification and has all commands that you need. You can take a look at the class GlobalPlatformService, where you will find the implementation of the secure channel protocol. GPDroid (github.com/mobilesec/secure-element-gpdroid) is a wrapper for this project on Android.

Unable to identify AFL on a smart card

I'm working to get useful data from a VISA (such as PAN, expiry date...) credit card using a list of AIDs I got stuck.
I have been able to access to all the data manually. Using the next tutorial: http://www.openscdp.org/scripts/tutorial/emv/reademv.html
>>00 A4 04 00 07 A0 00 00 00 03 10 10 00
In ASCII:
<<o<EM>„<BEL> <0><0><0><ETX><DLE><DLE>¥<SO>P<EOT>VISA¿<FF><ENQ>ŸM<STX><VT><LF><0>
In Hexadecimal:
<<6F 19 84 07 A0 00 00 00 03 10 10 A5 0E 50 04 56 49 53 41 BF 0C 05 9F 4D 02 0B 0A 90 00
After that I used:
>>33 00 B2 01 0C 00 //sfi1, rec1
...
...
>>33 00 B2 10 FC 00 //sfi31, rec16
I continued with the tutorial and learned that the proper way to obtain the data was using GPO (Get Processing Options) command. And tried that next:
>>80 A8 00 00 0D 83 0B 00 00 00 00 00 00 00 00 00 00 00 00 // pdo = 83 0B 00 00 00 00 00 00 00 00 00 00 00 which suposse to be the correct one for VISA.
<< 69 85
So the condition of use is not satisfied.
>> 80 A8 00 00 02 83 00 00 //pdo= 83 00 that should work with every non visa card
<< 80 0E 3C 00 08 01 01 00 10 01 04 00 18 01 03 01 90 00
If this response is correct and it looks quite well for me as it starts by 80 and ends by 90 00, I am not able to identify AFL which I think that would make me possible to determine the PAN, expiry date... Can somebody help me?
The FCI that you received in response to the select command (00 A4 0400 07 A0000000031010 00) decodes to
6F 19 (File Control Information (FCI) Template)
84 07 (Dedicated File (DF) Name)
A0000000031010
A5 0E (File Control Information (FCI) Proprietary Template)
50 04 (Application Label)
56495341 ("VISA")
BF0C 05 (File Control Information (FCI) Issuer Discretionary Data)
9F4D 02 (Log Entry)
0B0A (SFI = 11; # of records = 10)
This FCI does not include any PDOL (processing options data list). Consequently, you need to assume a default value for the PDOL (which is an empty list for your card type). Consequently, the PDOL-related data field in the GET PROCESSING OPTIONS command must be empty:
83 00
Where 0x83 is the tag for PDOL-related data and 0x00 is a length of zero bytes.
Thus, the correct GPO command is (as you already found out):
80 A8 0000 02 8300 00
You got the response
800E3C00080101001001040018010301 9000
This decodes to
80 0E (Response Message Template Format 1)
3C00 (Application Interchange Profile)
08010100 10010400 18010301 (Application File Locator)
Consequently, the Application File Locator contains the following three entries:
08010100: SFI = 1, first record = 1, last record = 1, records involved in offline data authentication = 0
10010400: SFI = 2, first record = 1, last record = 4, records involved in offline data authentication = 0
18010301: SFI = 3, first record = 1, last record = 3, records involved in offline data authentication = 1
Consequently, you can read those record with the READ RECORD commands:
00 B2 010C 00
00 B2 0114 00
00 B2 0214 00
00 B2 0314 00
00 B2 0414 00
00 B2 011C 00
00 B2 021C 00
00 B2 031C 00

what is "num_regions" returned by the ioctl (VFIO_DEVICE_GET_REGION_INFO) in vfio

I am trying to understand how vfio works on pci.
I have read https://www.kernel.org/doc/Documentation/vfio.txt, and I am writting a test based on it.
At some point,my code looks like this:
/* Get pci device information (number of regions and interrupts...) */
ret = ioctl(vfio_dev_fd, VFIO_DEVICE_GET_INFO, &device_info);
if (ret) {
printf(" %s cannot get device info, "
"error %i (%s)\n", pci_addr, errno, strerror(errno));
close(vfio_dev_fd);
return -1;
}
printf ("found %d regions in the device\n", device_info.num_regions);
What I do not understand is that the last printf shows 9 (nine) regions!
Looking at the config space of my PCI device I can see:
cat /sys/bus/pci/devices/0000\:06\:00.0/config | hd
00000000 e4 14 81 16 00 04 10 00 10 00 00 02 10 00 00 00 |................|
00000010 04 00 de f3 00 00 00 00 04 00 df f3 00 00 00 00 |................|
00000020 00 00 00 00 00 00 00 00 00 00 00 00 28 10 6e 02 |............(.n.|
00000030 00 00 00 00 48 00 00 00 00 00 00 00 0a 01 00 00 |....H...........|
00000040
I am new to PCI, but my interpretation of this is that there are only two BARSs on this board (0 and 2). And I though that max number of regions (BARs?) was 6 on PCI.
There is nevertheless a little indication that I am misunderstanding something: the kernel doc mentioned above states:
For PCI devices, config space is a region
So that could lead to 3 regions for the board I am looking at... Still it says 9...
What is a PCI region for pci_vfio? how are they numbered and accessed?...
Thanks.
From vfio.h:
/*
* The VFIO-PCI bus driver makes use of the following fixed region and
* IRQ index mapping. Unimplemented regions return a size of zero.
* Unimplemented IRQ types return a count of zero.
*/
enum {
VFIO_PCI_BAR0_REGION_INDEX,
VFIO_PCI_BAR1_REGION_INDEX,
VFIO_PCI_BAR2_REGION_INDEX,
VFIO_PCI_BAR3_REGION_INDEX,
VFIO_PCI_BAR4_REGION_INDEX,
VFIO_PCI_BAR5_REGION_INDEX,
VFIO_PCI_ROM_REGION_INDEX,
VFIO_PCI_CONFIG_REGION_INDEX,
/*
* Expose VGA regions defined for PCI base class 03, subclass 00.
* This includes I/O port ranges 0x3b0 to 0x3bb and 0x3c0 to 0x3df
* as well as the MMIO range 0xa0000 to 0xbffff. Each implemented
* range is found at it's identity mapped offset from the region
* offset, for example 0x3b0 is region_info.offset + 0x3b0. Areas
* between described ranges are unimplemented.
*/
VFIO_PCI_VGA_REGION_INDEX,
VFIO_PCI_NUM_REGIONS
};
So, these additional regions are a way to provide access to configuration space, option ROM and VGA-specific I/O (ports and legacy framebuffer 0xa0000...0xbffff window).

Resources