Does CFHostGetAddressing() support ipv6 DNS entries? - ios

I am trying to use CFHostGetAddressing to do a simple DNS lookup. However, I notice that it returns an array of sockaddr structs, which I guess means it can only do IPV4.
Is there a way to support DNS entries with IPV6 addresses in iOS? Perhaps a similar API that returns an array of sockaddr_storage structs?

The CFHostGetAddressing() documentation might be misleading, because struct sockaddr
is a structure that covers all the common elements of the various socket addresses (IPv4, IPv6, ...). It is usually only used to pass a generic pointer to the socket functions.
Actually CFHostGetAddressing() works well with IPv6. It returns an array of CFData elements where each element contains a struct sockaddr_in or a struct sockaddr_in6.
Using the code from your previous question as a starting point, the following should work:
let hostRef = CFHostCreateWithName(kCFAllocatorDefault, "localhost").takeRetainedValue()
var resolved = CFHostStartInfoResolution(hostRef, CFHostInfoType.Addresses, nil)
let addresses = CFHostGetAddressing(hostRef, &resolved).takeRetainedValue() as NSArray
for addr in addresses as [NSData] {
var sockaddr = UnsafePointer<sockaddr_storage>.alloc(1)
addr.getBytes(sockaddr, length: sizeof(sockaddr_storage))
// ...
sockaddr.destroy()
}

Related

Difference b/w self.packetFlow.ReadBytes vs socket read

I am trying to read data from packet tunnel NEPacketTunnelProvider.
Right now what i am doing is trying to read the data using
self.packetFlow.readPackets { [weak self] (packets: [Data], protocols: [NSNumber]) in }
function.
It seems to be working fine. But now i want to read the packets by using the network handle of self.packetFlow function like this
let tunFd = self.packetFlow.value(forKeyPath: "socket.fileDescriptor") as! Int32
and use this file descriptor to read the packet data from the tunnel. like this
char *buffer1 = malloc(1024);
ssize_t length = read(tunFd, buffer1, 1024);
But now when i read the data from socket like this. It seems like data is not similar to what i am receiving earlier using the self.packetFlow.
Does anybody else know why it is happening. and what should i do get the similar data as in self.packetFlow.readPackets..
Any pointer of help will be appreciated.
I found the answer or my own query. There are 4 bytes of extra protocol information added to the data while we use file descriptor. We need to handle it as well.

OBJ-C wipe NSData content before nullifying it

For security reasons we need Always to wipe sensitive data from memory.
Usually it is not something that i see done in IOS but for apps and need extended security it is very important.
The Data that Usually needs to be wiped if NSData and NSString objects (pointing to nil does not wipe the data and it is a security breach)
I've managed to wipe my NSStrings with the code below (When password is NSString):
unsigned char *charPass;
if (password != nil) {
charPass = (unsigned char*) CFStringGetCStringPtr((CFStringRef) password, CFStringGetSystemEncoding());
memset(charPass, 0, [password length]);
password = nil;
}
Big remark on this implementation: You HAVE to check for NULL before calling the charPass or it might crash. There is NO guarantee that CFStringGetCStringPtr will return a value!
When password is NSData It suppose to be even more strait forward and the code bellow suppose to work:
memset([password bytes], 0, [password length]);
But this gives me a compilation error:
No matching function for call to 'memset'
I can't find a workaround to point to the password address and wipe the bytes over there like I did with the string (bytes method should let me do just that from what I understand but it doesn't compile for some reason that I cant figure out)
Any one has an idea for this?
10x
Your string deallocator is fragile. You write:
Big remark on this implementation: You HAVE to check for NULL before calling the charPass or it might crash. There is NO guarantee that CFStringGetCStringPtr will return a value!
This is documented behaviour as CFString (and hence NSString) does not guarantee you direct access to its internal buffer. You don't say what how you handle this situation, but if you don't erase the memory you presumably have a security problem.
In the case you do get a valid pointer back you are using the wrong byte count. The call [password length] returns:
The number of UTF-16 code units in the receiver.
which is not the same as the number of bytes. However CFStringGetCStringPtr returns:
A pointer to a C string or NULL if the internal storage of theString does not allow this to be returned efficiently.
If you have a C string you can use C library function strlen() to find its length.
To address the case when CFStringGetCStringPtr returns NULL you could create the string yourself as a CFString and supply a custom CFAllocater. You shouldn't need to write a complete allocator yourself, instead you could build one based on the system one. You can get the default allocators CFAllocatorContext which will return you the function pointers the system uses. You can then create a new CFAllocator based of a CFAllocatorContext which is a copy of the default one except you've changed the deallocate and reallocate pointers to functions which you have implemented in terms of the default allocate, reallocate and deallocate but also call memset appropriately to clear out memory.
Once you've done that doing your security wipe comes down to making sure these custom created CFString objects, aka NSString objects, are deallocated before your app quits.
You can find out about CFAllocator, CFAllocatorContext etc. in Memory Management Programming Guide for Core Foundation.
Which brings us to your actual question, how to zero an NSData. Here you are in luck an NSData object is a CFData object, and CFData's CFDataGetBytePtr, unlike CFStringGetCStringPtr, is guaranteed to return a pointer to the actual bytes, straight from the documentation:
This function is guaranteed to return a pointer to a CFData object's internal bytes. CFData, unlike CFString, does not hide its internal storage.
So code following your pattern for CFString will work here. Note that using NSData's bytes is not guaranteed in the documentation to call CFDataGetBytePtr, it could for example call CFDataGetBytes and return a copy of the bytes, use the CFData functions.
HTH
While I cannot speak for the actual safety of doing this, your problem is that NSData's bytes method returns a const void *
https://developer.apple.com/documentation/foundation/nsdata/1410616-bytes?language=objc
You can cast it to a void * if you want by
memset((void *)[password bytes], 0, [password length]);
If you use a NSMutableData, you won't have to do this.

NativeScript: Get string from interop.reference

To start, here is my code:
var buffer = malloc(interop.sizeof(interop.types.UTF8CString));
var fillBuffer = mac.getBytes(buffer);
var bytes = new interop.Reference(interop.types.UTF8CString, buffer);
var hexMac = bytes[0];
The variable 'Mac' is an NSData objected retrieved from CoreBluetooth. It is the scan response from a BLE device, which contains the peripheral's MAC address (00:0b:57:a2:fb:a0).
This problem is linked to THIS question I had posted earlier.
The solution provided is great; however, I cannot seem to implement this in nativescript :
(instancetype)stringWithFormat:(NSString *)format, ...;
Intellisense tells me the method doesnt exist on type NSString.
Due to that issue, I decided to go another route (as you can tell). I am filling a buffer with the bytes of the MAC address. In the code above, bytes[0] equates to 0xb57a2fba0.
I am now trying to convert that (which is an interop.Reference) into a string that I can store on the back-end (preferably in the xx:xx:xx:xx:xx format).
I have been at this all weekend, and cannot seem to find a solution. I even broke down objc!foundation.d.ts to figure out if stringWithFormat was supported, to no avail.
The nativescript community slack was unable to provide a resolution as well.
Please help if you can!
I don't know anything about NativeScript at all, but given the other code you wrote, I assume you're calling +alloc first, and so mean to use -initWithFormat: (an instance method that initializes) rather than +stringWithFormat: (a class method which handles allocation and initialization).

How to send structure data in socket programming?

I'm studying c socket programming lately,so I write an example for practice of Client–server model. I use structure as message data to send to server, server processes the data. when i run in the IOS simulator, it's right, but in the device it's wrong, I find that the structure data which the server receives from the devices client is different from the client message data! I'm sorry my English is very bad.
my structure code is:
typedef struct Message
{
char msg[4000];
char name[256];
bool isBroadcast;
bool islogin;
USER userInfo;
}__attribute__((packed)) MessageType;
user code is :
typedef struct user
{
int id_number;
char name[256];
char password[20];
char *p_chatlog;
struct sockaddr user_addr;
int sock;
} __attribute__((packed)) USER;
send code is :
MessageType *loginMsg = (MessageType *)malloc(sizeof(MessageType));
bzero(loginMsg, sizeof(MessageType));
loginMsg->islogin = true;
const char *name_str = [userName.text UTF8String];
memcpy(&(loginMsg->userInfo.name), name_str, strlen(name_str));
const char *password_str = [password.text UTF8String];
memcpy(&(loginMsg->userInfo.password), password_str, strlen(password_str));
write(m_sock, loginMsg, sizeof(MessageType));
free(loginMsg);
server receive code use read() function, then make the receive chars transform structure type.
I would suggest that you make sure you send the data in network byte order; use the htonl, htons and ntohl, ntohs system functions. Different devices may well be a different endianness. Also, you probably shouldn't just send a struct over the network, even in network byte order, you would be better devising a simple protocol to send the data you require - it's more maintainable and flexible. You also can't guarantee your write has sent all of the data you requested, you should check the return results of both your read and write to ensure you have the amount you expect.
Incidentally, it is recommended to avoid the POSIX networking library for iOS and use the native implementation where possible.

CFStreamCreatePairWithSocketToCFHost CFStreamCreatePairWithSocketToHost and allocations

Can some one please give me the difference between CFStreamCreatePairWithSocketToCFHost and CFStreamCreatePairWithSocketToHost calls.
Also what is a CFAllocator and what is the meaning if that is NULL or kCFAllocatorDefault. Since its a kCFAllocatorDefault is a const can someone explain the beleifits of kCFAllocatorDefault or is it the for historical purposes only?
The difference between CFStreamCreatePairWithSocketToCFHost and CFStreamCreatePairWithSocketToHost is simply the way the address is passed in.
In CFStreamCreatePairWithSocketToHost, you can simply define a CFStringRef (or NSString) to represent the domain / ip of the host.
With the CFHost version, however, it gives you control over the address via the sockaddr_in struct, defined in <netinet/in.h>. You create a CFHostRef in a manner similar to the following:
struct sockaddr_in ip4addr; // note that this only works for ipv4, for ipv6 you need struct sockaddr_in6.
ip4addr.sin_family = AF_INET;
ip4addr.sin_port = htons(3490);
inet_pton(AF_INET, "10.0.0.1", &ip4addr.sin_addr);
CFDataRef sockData = CFDataCreate(NULL, &ip4addr, sizeof(ip4addr));
CFHostRef host = CFHostCreateWithAddress(NULL, sockData);
// use 'host' to create your stream
CFRelease(host);
CFRelease(sockData);
This gives you some (mostly unnecessary) control over what you do with the socket itself, for most situations, the CFHost version is not necessary.
For CFAllocator's, once again, the documentation is your friend. It is used as CoreFoundation's way for debugging malloc, free, and realloc calls throughout the code.
It is an object that allows you to write your own methods for allocating memory for an object, and kCFAllocatorDefault uses the standard malloc, free, and realloc calls used by the system. Passing NULL for a CFAllocator works exactly the same as kCFAllocatorDefault, the code just uses the system calls.

Resources