How to send structure data in socket programming? - ios

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.

Related

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.

realtime network statistics on iOS

I know it is possible to check the traffic usage of wifi and Data through built-in settings in iphone. But is there any solution like a library or function to fetch realtime network usage (upload/download) of the device? (like a real time netstat)
Reachability is one of the things that I found with regard to the mentioned.
http://developer.apple.com/library/ios/#samplecode/Reachability/Introduction/Intro.html#//apple_ref/doc/uid/DTS40007324-Intro-DontLinkElementID_2
this app does something similar:
https://itunes.apple.com/us/app/data-control-manage-data-usage/id390646992?mt=8
Does anyone know what class to call or look for what certain method to access the real time traffic?
I hope that my question is understandable.
There is no high level API to support this, but since iOS is simply a rather pretty unix, you can of course go to the standard APIs.
In this case you would be looking for getifaddrs, which retrieves the in memory structures describing the various interfaces on the device.
You then have to parse these C structures, to get the interface details you want.
The getifaddr interface is documented ( man getifaddr), so you can use this.
I'll add a bit of code, but first a few caveats.
Apple don't really bother maintaining this stuff, so the network counts are 32 bit, so you have to handle 4Gb roll over.
The packet counts are mostly there, I think the tx packet count is always 0, but who is interested in packet counts anyway.
You can probably find better code here by searching for getifaddrs, but here is a short version to get you started.
#include <sys/types.h>
#include <sys/sysctl.h>
#include <sys/socket.h>
#include <ifaddrs.h>
#include <net/if_var.h>
struct ifaddrs* addrs;
int getIFAddrsResult = getifaddrs(&addrs);
if (getIFAddrsResult == 0)
{
struct ifaddrs* addrsPtr = addrs; // need to keep original for freeifaddrs
while (addrsPtr != NULL)
{
NSString *name = [NSString stringWithFormat:#"%s",addrsPtr->ifa_name];
//NSLog(#"ifa_name %s == %#\n", cursor->ifa_name,name);
// names of interfaces: en0 is WiFi ,pdp_ip0 is WWAN
if (addrsPtr->ifa_addr->sa_family == AF_LINK)
{
const struct if_data* stats = (const struct if_data *) addrsPtr->ifa_data;
// We only consider the active data interface, and that will normally be the '0' interface.
if ([name isEqualToString:#"en0"])
{
// Wifi
// look at stats->ifi_obytes & ifi_ibytes
} else if ([name isEqualToString:#"pdp_ip0"])
{
// mobile broad band
} else {
// could be bluetooth, usb, ad hoc wifi, out of band signalling...
}
}
addrsPtr = addrsPtr->ifa_next;
}
freeifaddrs(addrs);
} else {
NSLog(#"getifaddrs failed with error : %s", strerror(getIFAddrsResult));
return nil;
}
P.S. I'm going for my diamond resurrect old questions badge :)
There is no such API in iOS, the App that you mentioned (and all similar apps), rely on an API provided by the carrier (or parsing the carriers website). If you want to implement this kind of App, I'm afraid you have to find something for every possible carrier you are interested in.

pjsip send sms how to

I'm trying to send sms messages through pjsip without luck so far.
The account gets registered on a server and I get a register success response but I can't find any good tutorials that show how to send sms.
I found this book online but it still doesn't give me any examples of how to use this library:
http://www.scribd.com/doc/90092246/Pjsip-Dev-Guide#outer_page_48
I know I'm supposed to use:
pjsip_endpt_create_request(pjsip_endpoint *endpt, const pjsip_method method, const pj_str_t *target, const pj_str_t *from, const pj_str_t *to, , const pj_str_t *call_id, int cseq, const pj_str_t *text, pjsip_tx_data **p_tdata);
pjsip_endpt_acquire_transport(pjsip_endpoint *endpt, pjsip_transport_type_e type, const pj_sockaddr_t *remote, int addr_len, const pjsip_tpselector *sel, pjsip_transport **p_tp)
but apart from these, I have no idea.
Note: I don't want instant messaging, I want the texts to be delivered as SMS if possible.
And it needs to be done in pjsip, no other library (no flexibility unfortunately).
Thanks in advance!
Okay, here I am answering my own question related to pjsip again. I wish this library had proper documentation where the function calls were explained a better way on what they do.
1 thing that confused me was that there in this developer's guide: http://www.pjsip.org/release/0.5.4/PJSIP-Dev-Guide.pdf
there are 2 topics. 1 is message elements and how to create a request. The other is instant messaging. I wasn't exactly sure which was required for SMS. Turns out, its the instant messaging.
The only needed function is:
pjsua_im_send(pjsua_acc_id acc_id, const pj_str_t *to, const pj_str_t *mime_type, const pj_str_t *content, const pjsua_msg_data *msg_data, void *user_data);
1st variable acc_id is what gets initialized at the beginning of the application SIP registration.
2nd variable is the number you want the message to be sent to. I initialized it as such:
"sip:16476804556#sipserverdomain.com"
3rd variable is for sending MIME's. I didn't use this. so it's NULL.
4th variable is the message body itself.
For example:
pj_str_t text;
const char *msgText = [#"Hello there!" UTF8String];
text = pj_str((char*)msgText);
then I passed: &text to the function.
5th variable is the msg data. Again, didn't use it. It's NULL.
6th variable is user data. Didn't use this either. NULL.
And finally, this is what the function call looked like:
pjsua_im_send(app._sip_acc_id, &to, NULL, &text, NULL, NULL);
Hope this helps someone out there having a similar problem!
-c0d3Junk13
A SMS is essentially an email delivered to phonenumber#serviceprovider.com. I have not used pjsip, however I was able to use the Chilkat library to deliver SMS quite easily. For example code to send an email, you can find it on their website.

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.

Best Place to Store Included AWS Credentials in an iOS Application

I plan on using the AWS SDK for iOS for an upcoming project. I need to store credentials for AWS with the packed application. Where is the most secure place to place them? I know that storing them in a pList would be a bad idea. Is it better to just 'hard-code' it into a class that will be compiled? Is there any risk there?
I believe that completely hiding the credentials is theoretically impossible. That is, if your compiled code can read them, then in theory so can anyone with access to the compiled code. But imperfect security is still worth something. I'd guess that most attackers would just look through the binary for strings that look like secret keys, and not go to the trouble of decompiling the code and trying to interpret how it works, so one way to hide the credentials would be to store them in an encoded form, then decode them as needed. This way the decoding algorithm becomes your key, and an attacker would have to find and understand it to extract your credentials.
Here's a fairly simple way to do it using a random XOR mask. Replace the following bogus password with yours, and remember to keep the NULL terminator (\0) in place. Compile and run this code as a standalone program:
#include <stdio.h>
#define PAD_LENGTH 32
int main() {
int i;
char c;
// start with the password
char password[PAD_LENGTH] = "My AWS Password\0";
// make a random pad to encrypt it
printf("PAD:\n{");
char pad[PAD_LENGTH];
for (i = 0; i < PAD_LENGTH; i++) {
c = arc4random() & 0xFF;
pad[i] = c;
printf("%#02x", c & 0xFF);
if (i < PAD_LENGTH - 1) printf(",");
}
printf("}\n");
// make an encrypted version of the password
printf("KEY:\n{");
for (i = 0; i < PAD_LENGTH; i++) {
c = pad[i] ^ password[i];
printf("%#02x", c & 0xFF);
if (i < PAD_LENGTH - 1) printf(",");
}
printf("}\n");
return(0);
}
Then copy the generated pad and key into code like this (which will actually get included with your app):
#define PAD_LENGTH 32
char pad[PAD_LENGTH] = {0x83,0x26,0x8a,0x8b,0xee,0xab,0x6,0xed,0x2e,0x99,0xff,0x23,0x7f,0xef,0xc8,0x8,0x6b,0x8e,0xa4,0x64,0x6d,0xb,0x7,0xd2,0x6a,0x39,0x60,0xa4,0xa9,0xad,0xea,0xb8};
char key[PAD_LENGTH] = {0xce,0x5f,0xaa,0xca,0xb9,0xf8,0x26,0xbd,0x4f,0xea,0x8c,0x54,0x10,0x9d,0xac,0x8,0x6b,0x8e,0xa4,0x64,0x6d,0xb,0x7,0xd2,0x6a,0x39,0x60,0xa4,0xa9,0xad,0xea,0xb8};
for (int i = 0; i < PAD_LENGTH; i++) {
key[i] = key[i] ^ pad[i];
}
NSString *password = [NSString stringWithCString:key encoding:NSASCIIStringEncoding];
Since this is on a public forum, you might want to change a few things, like making the pads a different length, splitting them up and rejoining them with code, reordering them, etc. You could also store the pad and key in distant parts of the code. A truly skilled and dedicated attacker is going to be able to find your password no matter what, but the basic idea is that most people scanning the binary for a password will not find it as such.
Have you looked at the Data Protection API?
What are the new "iOS data protection APIs"?
There are various options depending on your security needs.
This question may help also.
Data Protection on iOS
The video from a conference this year was useful.
http://developer.apple.com/videos/wwdc/2010
you should use AWS Identity and Access Management (IAM): http://aws.amazon.com/iam/
you can find more information about AWS Credential Management in Mobile Applications on http://aws.amazon.com/articles/4611615499399490

Resources