]>
Commit | Line | Data |
---|---|---|
d8f41ccd A |
1 | /* |
2 | * Copyright (c) 2012-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 | ||
427c49bc A |
24 | |
25 | /* | |
26 | * dtlsEchoClient.c | |
27 | * Security | |
28 | * | |
d8f41ccd | 29 | * Copyright (c) 2011-2014 Apple Inc. All Rights Reserved. |
427c49bc A |
30 | * |
31 | */ | |
32 | ||
33 | #include <Security/Security.h> | |
34 | ||
35 | #include "ssl-utils.h" | |
36 | ||
37 | #include <stdlib.h> | |
38 | #include <sys/types.h> | |
39 | #include <sys/socket.h> | |
40 | #include <netinet/in.h> | |
41 | #include <arpa/inet.h> | |
42 | #include <stdio.h> | |
43 | #include <errno.h> | |
44 | #include <unistd.h> /* close() */ | |
45 | #include <string.h> /* memset() */ | |
46 | #include <fcntl.h> | |
47 | #include <time.h> | |
48 | ||
49 | #include "tlssocket.h" | |
50 | ||
51 | #define SERVER "10.0.2.1" | |
52 | #define PORT 23232 | |
53 | #define BUFLEN 128 | |
54 | #define COUNT 10 | |
55 | ||
56 | #if 0 | |
57 | static void dumppacket(const unsigned char *data, unsigned long len) | |
58 | { | |
59 | unsigned long i; | |
60 | for(i=0;i<len;i++) | |
61 | { | |
62 | if((i&0xf)==0) printf("%04lx :",i); | |
63 | printf(" %02x", data[i]); | |
64 | if((i&0xf)==0xf) printf("\n"); | |
65 | } | |
66 | printf("\n"); | |
67 | } | |
68 | #endif | |
69 | ||
70 | ||
71 | /* print a '.' every few seconds to keep UI alive while connecting */ | |
72 | static time_t lastTime = (time_t)0; | |
73 | #define TIME_INTERVAL 3 | |
74 | ||
75 | static void sslOutputDot() | |
76 | { | |
77 | time_t thisTime = time(0); | |
78 | ||
79 | if((thisTime - lastTime) >= TIME_INTERVAL) { | |
80 | printf("."); fflush(stdout); | |
81 | lastTime = thisTime; | |
82 | } | |
83 | } | |
84 | ||
85 | static void printSslErrStr( | |
86 | const char *op, | |
87 | OSStatus err) | |
88 | { | |
89 | printf("*** %s: %ld\n", op, (long)err); | |
90 | } | |
91 | ||
92 | /* 2K should be enough for everybody */ | |
93 | #define MTU 2048 | |
94 | ||
95 | ||
96 | int dtls_client(const char *hostname, int bypass); | |
97 | ||
98 | int dtls_client(const char *hostname, int bypass) | |
99 | { | |
100 | int fd; | |
101 | int tlsfd; | |
102 | struct sockaddr_in sa; | |
103 | ||
104 | printf("Running dtls_client test with hostname=%s, bypass=%d\n", hostname, bypass); | |
105 | ||
106 | if ((fd=socket(AF_INET, SOCK_DGRAM, 0))==-1) { | |
107 | perror("socket"); | |
108 | exit(-1); | |
109 | } | |
110 | ||
111 | memset((char *) &sa, 0, sizeof(sa)); | |
112 | sa.sin_family = AF_INET; | |
113 | sa.sin_port = htons(PORT); | |
114 | if (inet_aton(hostname, &sa.sin_addr)==0) { | |
115 | fprintf(stderr, "inet_aton() failed\n"); | |
116 | exit(1); | |
117 | } | |
118 | ||
119 | if(connect(fd, (struct sockaddr *)&sa, sizeof(sa))==-1) | |
120 | { | |
121 | perror("connect"); | |
122 | return errno; | |
123 | } | |
124 | ||
125 | /* Change to non blocking io */ | |
126 | fcntl(fd, F_SETFL, O_NONBLOCK); | |
127 | ||
128 | SSLRecordContextRef c=(intptr_t)fd; | |
129 | ||
130 | ||
131 | OSStatus ortn; | |
132 | SSLContextRef ctx = NULL; | |
133 | ||
134 | SSLClientCertificateState certState; | |
135 | SSLCipherSuite negCipher; | |
136 | SSLProtocol negVersion; | |
137 | ||
138 | /* | |
139 | * Set up a SecureTransport session. | |
140 | */ | |
141 | ||
142 | ctx = SSLCreateContextWithRecordFuncs(kCFAllocatorDefault, kSSLClientSide, kSSLDatagramType, &TLSSocket_Funcs); | |
143 | if(!ctx) { | |
144 | printSslErrStr("SSLCreateContextWithRecordFuncs", -1); | |
145 | return -1; | |
146 | } | |
147 | ||
148 | printf("Attaching filter\n"); | |
149 | ortn = TLSSocket_Attach(fd); | |
150 | if(ortn) { | |
151 | printSslErrStr("TLSSocket_Attach", ortn); | |
152 | return ortn; | |
153 | } | |
154 | ||
155 | if(bypass) { | |
156 | tlsfd = open("/dev/tlsnke", O_RDWR); | |
157 | if(tlsfd<0) { | |
158 | perror("opening tlsnke dev"); | |
159 | exit(-1); | |
160 | } | |
161 | } | |
162 | ||
163 | ortn = SSLSetRecordContext(ctx, c); | |
164 | if(ortn) { | |
165 | printSslErrStr("SSLSetRecordContext", ortn); | |
166 | return ortn; | |
167 | } | |
168 | ||
169 | ortn = SSLSetMaxDatagramRecordSize(ctx, 600); | |
170 | if(ortn) { | |
171 | printSslErrStr("SSLSetMaxDatagramRecordSize", ortn); | |
172 | return ortn; | |
173 | } | |
174 | ||
175 | /* Lets not verify the cert, which is a random test cert */ | |
176 | ortn = SSLSetEnableCertVerify(ctx, false); | |
177 | if(ortn) { | |
178 | printSslErrStr("SSLSetEnableCertVerify", ortn); | |
179 | return ortn; | |
180 | } | |
181 | ||
182 | ortn = SSLSetCertificate(ctx, server_chain()); | |
183 | if(ortn) { | |
184 | printSslErrStr("SSLSetCertificate", ortn); | |
185 | return ortn; | |
186 | } | |
187 | ||
188 | printf("Handshake...\n"); | |
189 | ||
190 | do { | |
191 | ortn = SSLHandshake(ctx); | |
192 | if(ortn == errSSLWouldBlock) { | |
193 | /* keep UI responsive */ | |
194 | sslOutputDot(); | |
195 | } | |
196 | } while (ortn == errSSLWouldBlock); | |
197 | ||
198 | ||
199 | SSLGetClientCertificateState(ctx, &certState); | |
200 | SSLGetNegotiatedCipher(ctx, &negCipher); | |
201 | SSLGetNegotiatedProtocolVersion(ctx, &negVersion); | |
202 | ||
203 | int count; | |
204 | size_t len; | |
205 | ssize_t sreadLen, swriteLen; | |
206 | size_t readLen, writeLen; | |
207 | ||
208 | char buffer[BUFLEN]; | |
209 | ||
210 | count = 0; | |
211 | while(count<COUNT) { | |
212 | int timeout = 10000; | |
213 | ||
214 | snprintf(buffer, BUFLEN, "Message %d", count); | |
215 | len = strlen(buffer); | |
216 | ||
217 | if(bypass) { | |
218 | /* Send data through the side channel, kind of like utun would */ | |
219 | swriteLen=write(tlsfd, buffer, len); | |
220 | if(swriteLen<0) { | |
221 | perror("write to tlsfd"); | |
222 | break; | |
223 | } | |
224 | writeLen=swriteLen; | |
225 | } else { | |
226 | ortn=SSLWrite(ctx, buffer, len, &writeLen); | |
227 | if(ortn) { | |
228 | printSslErrStr("SSLWrite", ortn); | |
229 | break; | |
230 | } | |
231 | } | |
232 | ||
233 | printf("Wrote %lu bytes\n", writeLen); | |
234 | ||
235 | count++; | |
236 | ||
237 | if(bypass) { | |
238 | do { | |
239 | sreadLen=read(tlsfd, buffer, BUFLEN); | |
240 | } while((sreadLen==-1) && (errno==EAGAIN) && (timeout--)); | |
241 | if((sreadLen==-1) && (errno==EAGAIN)) { | |
242 | printf("Read timeout...\n"); | |
243 | continue; | |
244 | } | |
245 | if(sreadLen<0) { | |
246 | perror("read from tlsfd"); | |
247 | break; | |
248 | } | |
249 | readLen=sreadLen; | |
250 | } | |
251 | else { | |
252 | do { | |
253 | ortn=SSLRead(ctx, buffer, BUFLEN, &readLen); | |
254 | } while((ortn==errSSLWouldBlock) && (timeout--)); | |
255 | if(ortn==errSSLWouldBlock) { | |
256 | printf("SSLRead timeout...\n"); | |
257 | continue; | |
258 | } | |
259 | if(ortn) { | |
260 | printSslErrStr("SSLRead", ortn); | |
261 | break; | |
262 | } | |
263 | } | |
264 | ||
265 | buffer[readLen]=0; | |
266 | printf("Received %lu bytes: %s\n", readLen, buffer); | |
267 | ||
268 | } | |
269 | ||
270 | SSLClose(ctx); | |
271 | ||
272 | SSLDisposeContext(ctx); | |
273 | ||
274 | return ortn; | |
275 | } | |
276 |