]> git.saurik.com Git - apple/security.git/blob - Security/tlsnke/tlsnketest/main.c
Security-57031.10.10.tar.gz
[apple/security.git] / Security / tlsnke / tlsnketest / main.c
1 /*
2 * Copyright (c) 2011-2014 Apple Inc. All Rights Reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
11 * file.
12 *
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
20 *
21 * @APPLE_LICENSE_HEADER_END@
22 */
23
24
25 #include <stdlib.h>
26 #include <stdio.h>
27 #include <string.h>
28
29 #include <unistd.h>
30 #include <sys/socket.h>
31 #include <netinet/in.h>
32 #include <arpa/inet.h>
33 #include <net/kext_net.h>
34 #include <pthread.h>
35 #include <netdb.h>
36 #include <fcntl.h>
37
38 #include <stdbool.h>
39
40 #include <AssertMacros.h>
41 #include "tlssocket.h"
42 #include "tlsnke.h"
43
44
45 static void print_data(const char *s, size_t l, const unsigned char *p)
46 {
47 printf("%s, %zu:",s, l);
48 for(int i=0; i<l; i++)
49 printf(" %02x", p[i]);
50 printf("\n");
51 }
52
53 static void *server_thread_func(void *arg)
54 {
55 int sock;
56 struct sockaddr_in server_addr;
57 int err;
58
59 if ((sock = socket(AF_INET, SOCK_DGRAM, 0)) == -1) {
60 perror("server socket");
61 exit(1);
62 }
63
64 // Dont use TLSSocket_Attach for the server:
65 // TLSSocket_Attach can only open one TLS socket at a time.
66 {
67 struct so_nke so_tlsnke;
68
69 memset(&so_tlsnke, 0, sizeof(so_tlsnke));
70 so_tlsnke.nke_handle = TLS_HANDLE_IP4;
71 err=setsockopt(sock, SOL_SOCKET, SO_NKE, &so_tlsnke, sizeof(so_tlsnke));
72 if(err<0) {
73 perror("attach (server)");
74 exit(err);
75 }
76 }
77
78 server_addr.sin_family = AF_INET;
79 server_addr.sin_port = htons(23232);
80 server_addr.sin_addr.s_addr = INADDR_ANY;
81 bzero(&(server_addr.sin_zero),8);
82
83 if (bind(sock, (struct sockaddr *)&server_addr, sizeof(struct sockaddr))
84 == -1) {
85 perror("Unable to bind");
86 exit(1);
87 }
88
89 printf("\nBound - Server Waiting for client on port 23232\n");
90 fflush(stdout);
91
92 while (1)
93 {
94 int rc;
95 SSLRecord rec;
96 rc=TLSSocket_Funcs.read((intptr_t)sock, &rec);
97 if(!rc) {
98 print_data("recvd", rec.contents.length, rec.contents.data);
99 rec.contents.data[rec.contents.length-1]=0;
100 printf("recvd: %ld, %s\n", rec.contents.length, rec.contents.data);
101 free(rec.contents.data);
102 } else {
103 printf("read failed: %d\n", rc);
104 }
105 }
106
107 close(sock);
108 return NULL;
109 }
110
111 static int create_client_socket(const char *hostname)
112 {
113 int sock;
114 int err;
115
116
117 printf("Create client socket\n");
118 sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
119 if(sock<0) {
120 perror("client socket");
121 return sock;
122 }
123
124
125 #if 1
126 err=TLSSocket_Attach(sock);
127 if(err<0) {
128 perror("TLSSocket_Attach (server)");
129 exit(err);
130 }
131 #endif
132
133
134 struct hostent *host;
135 struct sockaddr_in server_addr;
136
137 //host = gethostbyname("kruk.apple.com");
138 //host = gethostbyname("localhost");
139 host= gethostbyname(hostname);
140 if(!host) {
141 herror("host");
142 return -1;
143 }
144 server_addr.sin_family = AF_INET;
145 server_addr.sin_port = htons(23232);
146 server_addr.sin_addr = *((struct in_addr *)host->h_addr);
147 bzero(&(server_addr.sin_zero),8);
148
149 err = connect(sock, (struct sockaddr *)&server_addr,
150 sizeof(struct sockaddr));
151 if(err)
152 {
153 perror("connect");
154 return err;
155 }
156
157 return sock;
158 }
159
160 /* simple test */
161 static int kext_test(const char *hostname, int bypass)
162 {
163 int sock, i;
164 char send_data[1024];
165 int tlsfd;
166 pthread_t server_thread;
167
168 if(strcmp(hostname, "localhost")==0) {
169 pthread_create(&server_thread, NULL, server_thread_func, NULL);
170 // Just wait for the server to be setup
171 sleep(1);
172 }
173
174
175 sock = create_client_socket(hostname);
176
177 if(bypass) {
178 /* Have to open this after we attached the filter to the client socket */
179 tlsfd=open("/dev/tlsnke", O_RDWR);
180 if(tlsfd<0) {
181 perror("open tlsnke");
182 exit(1);
183 }
184 }
185
186
187 for(i=0; i<20;i++) {
188 int n;
189 ssize_t err;
190 n=sprintf(send_data, "Message #%d\n", i);
191 if(n<0) {
192 perror("sprintf");
193 exit(1);
194 }
195
196 printf("Client(1) sending %d bytes (\"%s\")\n", n, send_data);
197
198 if(bypass) {
199 err = write(tlsfd, send_data, n);
200 if(err<0) {
201 perror("write to tlsnke");
202 exit(1);
203 }
204 } else {
205 SSLRecord rec;
206
207 rec.contentType = SSL_RecordTypeAppData;
208 rec.protocolVersion = DTLS_Version_1_0;
209 rec.contents.data = (uint8_t *)send_data;
210 rec.contents.length = n;
211
212 err = TLSSocket_Funcs.write((intptr_t)sock, rec);
213 if(err<0) {
214 perror("write to socket");
215 exit(1);
216 }
217
218 /* serviceWriteQueue every 2 writes, this will trigger rdar://11348395 */
219 if(i&1) {
220 int err;
221 err = TLSSocket_Funcs.serviceWriteQueue((intptr_t)sock);
222 if(err<0) {
223 perror("service write queue");
224 exit(1);
225 }
226 }
227 }
228
229 sleep(1);
230 }
231
232 return 0;
233 }
234
235
236 /* handshake test */
237 int st_test();
238
239 /* echo test */
240 int dtls_client(const char *hostname, int bypass);
241
242 static
243 int usage(const char *argv0)
244 {
245 printf("Usage: %s <test> <hostname> <bypass>\n", argv0);
246 printf(" <test>: type of test: 's'imple, 'h'andshake or 'e'cho] (see below)\n");
247 printf(" <hostname>: hostname of server\n");
248 printf(" <bypass>: use /dev/tlsnke bypass test\n");
249
250 printf("\n 'S'imple test:\n"
251 "\tVery basic test with no handshake. DTLS packets are sent through the socket filter, non encrypted.\n"
252 "\tIf hostname is 'localhost', a local simple server will be created that will also use the tls filter,\n"
253 "\tsuch that the input path is tested.\n"
254 "\tOtherwise, a server on the other side is not required only the output path is tested. If there is no server replying\n"
255 "\tonly the ouput path will be tested. If a server is replying, input packet will be processed but are never read to userspace\n"
256 "\tif bypass=1, also send the same packet through the /dev/tlsnke interface, as if they were coming from utun\n");
257
258 printf("\n 'H'andshake:\n");
259 printf("\tTest SSL Handshake with various ciphers, between a local client going through the tlsnke\n"
260 "\tfilter, and a local server using only the userland SecureTransport.\n"
261 "\thostname and bypass are ignored.\n");
262
263 printf("\n 'E'cho:\n");
264 printf("\tTest to connect to an udp echo server indicated by hostname, on port 23232.\n"
265 "\tSet bypass=1 to use the /dev/tlsnke bsd device to send/recv the app data (emulate utun behaviour)\n");
266
267 printf("\n\tbypass=1 require the tlsnke kext to be compiled with TLS_TEST=1 (not the default in the build)\n");
268
269 return -1;
270 }
271
272 int main (int argc, const char * argv[])
273 {
274
275 printf("argv0=%s argc=%d\n", argv[0], argc);
276 if(argc<2)
277 return usage(argv[0]);
278
279 switch (argv[1][0]) {
280 case 's':
281 case 'S':
282 if(argc<3) return usage(argv[0]);
283 return kext_test(argv[2], atoi(argv[3])?1:0);
284 case 'h':
285 case 'H':
286 return st_test();
287 case 'e':
288 case 'E':
289 if(argc<3) return usage(argv[0]);
290 return dtls_client(argv[2], atoi(argv[3])?1:0);
291 default:
292 return usage(argv[0]);
293 }
294 }
295