/* * Copyright (c) 2011-2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this * file. * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. * * @APPLE_LICENSE_HEADER_END@ */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include "tlssocket.h" #include "tlsnke.h" static void print_data(const char *s, size_t l, const unsigned char *p) { printf("%s, %zu:",s, l); for(int i=0; ih_addr); bzero(&(server_addr.sin_zero),8); err = connect(sock, (struct sockaddr *)&server_addr, sizeof(struct sockaddr)); if(err) { perror("connect"); return err; } return sock; } /* simple test */ static int kext_test(const char *hostname, int bypass) { int sock, i; char send_data[1024]; int tlsfd; pthread_t server_thread; if(strcmp(hostname, "localhost")==0) { pthread_create(&server_thread, NULL, server_thread_func, NULL); // Just wait for the server to be setup sleep(1); } sock = create_client_socket(hostname); if(bypass) { /* Have to open this after we attached the filter to the client socket */ tlsfd=open("/dev/tlsnke", O_RDWR); if(tlsfd<0) { perror("open tlsnke"); exit(1); } } for(i=0; i<20;i++) { int n; ssize_t err; n=sprintf(send_data, "Message #%d\n", i); if(n<0) { perror("sprintf"); exit(1); } printf("Client(1) sending %d bytes (\"%s\")\n", n, send_data); if(bypass) { err = write(tlsfd, send_data, n); if(err<0) { perror("write to tlsnke"); exit(1); } } else { SSLRecord rec; rec.contentType = SSL_RecordTypeAppData; rec.protocolVersion = DTLS_Version_1_0; rec.contents.data = (uint8_t *)send_data; rec.contents.length = n; err = TLSSocket_Funcs.write((intptr_t)sock, rec); if(err<0) { perror("write to socket"); exit(1); } /* serviceWriteQueue every 2 writes, this will trigger rdar://11348395 */ if(i&1) { int err; err = TLSSocket_Funcs.serviceWriteQueue((intptr_t)sock); if(err<0) { perror("service write queue"); exit(1); } } } sleep(1); } return 0; } /* handshake test */ int st_test(); /* echo test */ int dtls_client(const char *hostname, int bypass); static int usage(const char *argv0) { printf("Usage: %s \n", argv0); printf(" : type of test: 's'imple, 'h'andshake or 'e'cho] (see below)\n"); printf(" : hostname of server\n"); printf(" : use /dev/tlsnke bypass test\n"); printf("\n 'S'imple test:\n" "\tVery basic test with no handshake. DTLS packets are sent through the socket filter, non encrypted.\n" "\tIf hostname is 'localhost', a local simple server will be created that will also use the tls filter,\n" "\tsuch that the input path is tested.\n" "\tOtherwise, a server on the other side is not required only the output path is tested. If there is no server replying\n" "\tonly the ouput path will be tested. If a server is replying, input packet will be processed but are never read to userspace\n" "\tif bypass=1, also send the same packet through the /dev/tlsnke interface, as if they were coming from utun\n"); printf("\n 'H'andshake:\n"); printf("\tTest SSL Handshake with various ciphers, between a local client going through the tlsnke\n" "\tfilter, and a local server using only the userland SecureTransport.\n" "\thostname and bypass are ignored.\n"); printf("\n 'E'cho:\n"); printf("\tTest to connect to an udp echo server indicated by hostname, on port 23232.\n" "\tSet bypass=1 to use the /dev/tlsnke bsd device to send/recv the app data (emulate utun behaviour)\n"); printf("\n\tbypass=1 require the tlsnke kext to be compiled with TLS_TEST=1 (not the default in the build)\n"); return -1; } int main (int argc, const char * argv[]) { printf("argv0=%s argc=%d\n", argv[0], argc); if(argc<2) return usage(argv[0]); switch (argv[1][0]) { case 's': case 'S': if(argc<3) return usage(argv[0]); return kext_test(argv[2], atoi(argv[3])?1:0); case 'h': case 'H': return st_test(); case 'e': case 'E': if(argc<3) return usage(argv[0]); return dtls_client(argv[2], atoi(argv[3])?1:0); default: return usage(argv[0]); } }