Web Server TLS / SSL handshake

2

I'm developing a webserver on objetive-c for Iphone and implemented TLS / SSL for encrypted communication with a self sign certificate, presented in the links below.

I have tested the connection using wget of Ubuntu to create a client and connect to the server.

The problem is when the client connects to the server I would like to force it to use the client certificate ie to make a handshake, at the moment I can not do the same, the client establishes the connection with or without certificate.

#import "WebServerSecurity.h"
#import <sys/socket.h>
#import <netinet/in.h>

@implementation WebServerSecurity
{
    CFSocketRef socket;
}
static WebServerSecurity *webServerSecurity;
static CFReadStreamRef readStream = NULL;
static CFWriteStreamRef writeStream = NULL;
static NSInputStream *inputStream=nil;
static NSOutputStream *outputStream=nil;



-(void)startServer
{
    webServerSecurity=self;
    /************************* CREATE SOCKET ******************************/
    CFSocketContext ctx={0,(__bridge void *)(self),NULL,NULL,NULL};
    socket = CFSocketCreate(kCFAllocatorDefault, PF_INET, SOCK_STREAM, IPPROTO_TCP, kCFSocketAcceptCallBack, *(CFSocketCallBack)handleConnect, &ctx);
    if (!socket)
    {
        NSLog(@"[Server] Unable to create socket.");
        return;
    }

    /************************* BIND SOCKET ******************************/
    struct sockaddr_in address;
    memset(&address, 0, sizeof(address));
    address.sin_len = sizeof(address);
    address.sin_family = AF_INET;
    address.sin_port = htons(8080);
    address.sin_addr.s_addr = INADDR_ANY;

    CFDataRef addressData = CFDataCreate(kCFAllocatorDefault, (UInt8 *)&address, sizeof(address));


    if (CFSocketSetAddress(socket, addressData) != kCFSocketSuccess)
    {
        NSLog(@"[Server] Unable to bind socket to address.");
        return;
    }

    CFRelease(addressData);
    CFRunLoopSourceRef socketSource=CFSocketCreateRunLoopSource(kCFAllocatorDefault, socket, 0);
    CFRunLoopAddSource(CFRunLoopGetCurrent(), socketSource, kCFRunLoopDefaultMode);

}



static void handleConnect (CFSocketRef _socket,CFSocketCallBack type, CFDataRef address,const void *data,void *info)
{
    /************************************* CREATE INPUT AND OUTPUT STREAM ********************/
    CFSocketNativeHandle sock = *(CFSocketNativeHandle *) data;

    CFStreamCreatePairWithSocket(kCFAllocatorDefault, sock,&readStream, &writeStream);

    if (!readStream || !writeStream)
    {
        close(sock);
        NSLog(@"CFStreamCreatePairWithSocket() failed\n");
        return;
    }
    /*****************************************************************************************/


    /************************************* CONFIGURE CERTIFICATE AND OPEN CONNECTION *****************************/

    NSString *certificatePath = [[NSBundle mainBundle]pathForResource:@"server" ofType:@"p12"];
    NSData *certicateData = [NSData dataWithContentsOfFile:certificatePath];

    CFArrayRef keyRef;
    OSStatus status =SecPKCS12Import((__bridge CFDataRef)certicateData,(__bridge CFDictionaryRef)@{(__bridge NSString*)kSecImportExportPassphrase :@"etpick9816"}, &keyRef);

    if(status!=noErr)
    {
        NSLog(@"PKCS12 import error %i",(int)status);
        return;
    }
    CFDictionaryRef identityDict=CFArrayGetValueAtIndex(keyRef, 0);
    SecIdentityRef identityRef=(SecIdentityRef)CFDictionaryGetValue(identityDict, kSecImportItemIdentity);

    SecCertificateRef certificate;
    status = SecIdentityCopyCertificate(identityRef, &certificate);

    if (status != noErr)
    {
        NSLog(@"sec identity copy failed: %i", (int)status);
        return;
    }


    NSArray *certificates = [NSArray arrayWithObjects:(__bridge id)identityRef, (__bridge id)certificate, nil];

    inputStream=(__bridge NSInputStream*)readStream;
    outputStream=(__bridge NSOutputStream*)writeStream;


    CFReadStreamSetProperty(readStream, kCFStreamPropertyShouldCloseNativeSocket, kCFBooleanTrue);
    CFWriteStreamSetProperty(writeStream, kCFStreamPropertyShouldCloseNativeSocket, kCFBooleanTrue);

    CFReadStreamSetProperty(readStream, kCFStreamPropertySocketSecurityLevel, kCFStreamSocketSecurityLevelNegotiatedSSL);
    CFWriteStreamSetProperty(writeStream, kCFStreamPropertySocketSecurityLevel, kCFStreamSocketSecurityLevelNegotiatedSSL);

    CFReadStreamSetProperty(readStream, kCFStreamPropertySSLPeerTrust, kCFStreamPropertySSLPeerTrust);
    CFWriteStreamSetProperty(writeStream, kCFStreamPropertySSLPeerTrust, kCFStreamPropertySSLPeerTrust);

    NSDictionary *settings = @{(id)kCFStreamSSLCertificates:certificates,(id)kCFStreamSSLIsServer:@YES};
    CFReadStreamSetProperty(readStream, kCFStreamPropertySSLSettings, (CFDictionaryRef)settings);
    CFWriteStreamSetProperty(writeStream, kCFStreamPropertySSLSettings, (CFDictionaryRef)settings);

    [inputStream setDelegate:webServerSecurity];
    [outputStream setDelegate:webServerSecurity];

    [inputStream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
    [outputStream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];


    CFReadStreamOpen(readStream);
    CFWriteStreamOpen(writeStream);

    /*****************************************************************************************/

}
-(void)close
{

    NSLog(@"Closing streams.");
    CFSocketInvalidate(socket);
}

- (void)stream:(NSStream *)theStream handleEvent:(NSStreamEvent)streamEvent
{

    switch (streamEvent)
    {
        case NSStreamEventOpenCompleted:
        {
            NSLog(@"Stream opened");
            break;
        }
        case NSStreamEventHasSpaceAvailable:
        {

            if(theStream == outputStream)
            {

                break;
            }
        }
        case NSStreamEventHasBytesAvailable:
        {
            if (theStream == inputStream)
            {

                [self readRequest];

                NSString * str = [NSString stringWithFormat:
                                  @"GET / HTTP/1.0\r\n\r\n"];
                const uint8_t * rawstring =(const uint8_t *)[str UTF8String];
                [outputStream write:rawstring maxLength:str.length];
                [outputStream close];


            }
            break;

        }
        case NSStreamEventErrorOccurred:
        {
            NSLog(@"Can not connect to the host!");

            break;
        }
        case NSStreamEventEndEncountered:
        {
            NSLog(@"EventEndEncountered");

            [theStream close];
            [theStream removeFromRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
            theStream=nil;
            break;
        }
        default:
        {
            NSLog(@"Unknown event");
        }
    }
}


-(void)readRequest
{
     NSLog(@"inputStream is ready.");

    uint8_t buf[1024];
    unsigned int len = 0;

    NSMutableData* data=[[NSMutableData alloc] init];

    while ([inputStream hasBytesAvailable])
    {
        len = [inputStream read:buf maxLength:sizeof(buf)];
        if(len > 0)
            [data appendBytes: (const void *)buf length:len];
    }
    [inputStream close];
    NSString *dataReceived = [[NSString alloc] initWithData:data encoding:NSASCIIStringEncoding];
    NSLog(@"Data received:(%@)",dataReceived); 

}
@end
    
asked by anonymous 06.10.2015 / 16:43

0 answers