]>
Commit | Line | Data |
---|---|---|
427c49bc A |
1 | /* |
2 | * dtlsEchoClient.c | |
3 | * Security | |
4 | * | |
5 | * Created by Fabrice Gautier on 1/31/11. | |
6 | * Copyright 2011 Apple, Inc. All rights reserved. | |
7 | * | |
8 | */ | |
9 | ||
10 | #include <Security/Security.h> | |
11 | #include <Security/SecBase.h> | |
12 | ||
13 | #include "../sslViewer/sslAppUtils.h" | |
14 | ||
15 | #include <stdlib.h> | |
16 | #include <sys/types.h> | |
17 | #include <sys/socket.h> | |
18 | #include <netinet/in.h> | |
19 | #include <arpa/inet.h> | |
20 | #include <stdio.h> | |
21 | #include <errno.h> | |
22 | #include <unistd.h> /* close() */ | |
23 | #include <string.h> /* memset() */ | |
24 | #include <fcntl.h> | |
25 | #include <time.h> | |
26 | ||
27 | #ifdef NO_SERVER | |
28 | #include <securityd/spi.h> | |
29 | #endif | |
30 | ||
31 | #include "ssl-utils.h" | |
32 | ||
33 | #define SERVER "127.0.0.1" | |
34 | //#define SERVER "17.201.58.114" | |
35 | #define PORT 23232 | |
36 | #define BUFLEN 128 | |
37 | #define COUNT 10 | |
38 | ||
39 | #if 0 | |
40 | static void dumppacket(const unsigned char *data, unsigned long len) | |
41 | { | |
42 | unsigned long i; | |
43 | for(i=0;i<len;i++) | |
44 | { | |
45 | if((i&0xf)==0) printf("%04lx :",i); | |
46 | printf(" %02x", data[i]); | |
47 | if((i&0xf)==0xf) printf("\n"); | |
48 | } | |
49 | printf("\n"); | |
50 | } | |
51 | #endif | |
52 | ||
53 | /* 2K should be enough for everybody */ | |
54 | #define MTU 2048 | |
55 | static unsigned char readBuffer[MTU]; | |
56 | static unsigned int readOff=0; | |
57 | static size_t readLeft=0; | |
58 | ||
59 | static | |
60 | OSStatus SocketRead( | |
61 | SSLConnectionRef connection, | |
62 | void *data, | |
63 | size_t *dataLength) | |
64 | { | |
65 | int fd = (int)connection; | |
66 | ssize_t len; | |
67 | uint8_t *d=readBuffer; | |
68 | ||
69 | if(readLeft==0) | |
70 | { | |
71 | len = read(fd, readBuffer, MTU); | |
72 | ||
73 | if(len>0) { | |
74 | readOff=0; | |
75 | readLeft=(size_t) len; | |
76 | printf("SocketRead: %ld bytes... epoch: %02x seq=%02x%02x\n", | |
77 | len, d[4], d[9], d[10]); | |
78 | ||
79 | } else { | |
80 | int theErr = errno; | |
81 | switch(theErr) { | |
82 | case EAGAIN: | |
83 | //printf("SocketRead: EAGAIN\n"); | |
84 | *dataLength=0; | |
85 | /* nonblocking, no data */ | |
86 | return errSSLWouldBlock; | |
87 | default: | |
88 | perror("SocketRead"); | |
89 | return errSecIO; | |
90 | } | |
91 | } | |
92 | } | |
93 | ||
94 | if(readLeft<*dataLength) { | |
95 | *dataLength=readLeft; | |
96 | } | |
97 | ||
98 | memcpy(data, readBuffer+readOff, *dataLength); | |
99 | readLeft-=*dataLength; | |
100 | readOff+=*dataLength; | |
101 | ||
102 | return errSecSuccess; | |
103 | ||
104 | } | |
105 | ||
106 | static | |
107 | OSStatus SocketWrite( | |
108 | SSLConnectionRef connection, | |
109 | const void *data, | |
110 | size_t *dataLength) /* IN/OUT */ | |
111 | { | |
112 | int fd = (int)connection; | |
113 | ssize_t len; | |
114 | OSStatus err = errSecSuccess; | |
115 | const uint8_t *d=data; | |
116 | ||
117 | #if 0 | |
118 | if((rand()&3)==1) { | |
119 | ||
120 | /* drop 1/8th packets */ | |
121 | printf("SocketWrite: Drop %ld bytes... epoch: %02x seq=%02x%02x\n", | |
122 | *dataLength, d[4], d[9], d[10]); | |
123 | return errSecSuccess; | |
124 | ||
125 | } | |
126 | #endif | |
127 | ||
128 | len = send(fd, data, *dataLength, 0); | |
129 | ||
130 | if(len>0) { | |
131 | *dataLength=(size_t)len; | |
132 | printf("SocketWrite: Sent %ld bytes... epoch: %02x seq=%02x%02x\n", | |
133 | len, d[4], d[9], d[10]); | |
134 | return err; | |
135 | } | |
136 | ||
137 | int theErr = errno; | |
138 | switch(theErr) { | |
139 | case EAGAIN: | |
140 | /* nonblocking, no data */ | |
141 | err = errSSLWouldBlock; | |
142 | break; | |
143 | default: | |
144 | perror("SocketWrite"); | |
145 | err = errSecIO; | |
146 | break; | |
147 | } | |
148 | ||
149 | return err; | |
150 | ||
151 | } | |
152 | ||
153 | ||
154 | int main(int argc, char **argv) | |
155 | { | |
156 | int fd; | |
157 | struct sockaddr_in sa; | |
158 | ||
159 | if ((fd=socket(AF_INET, SOCK_DGRAM, 0))==-1) { | |
160 | perror("socket"); | |
161 | exit(-1); | |
162 | } | |
163 | ||
164 | #ifdef NO_SERVER | |
165 | # if DEBUG | |
166 | securityd_init(); | |
167 | # endif | |
168 | #endif | |
169 | ||
170 | memset((char *) &sa, 0, sizeof(sa)); | |
171 | sa.sin_family = AF_INET; | |
172 | sa.sin_port = htons(PORT); | |
173 | if (inet_aton(SERVER, &sa.sin_addr)==0) { | |
174 | fprintf(stderr, "inet_aton() failed\n"); | |
175 | exit(1); | |
176 | } | |
177 | ||
178 | time_t seed=time(NULL); | |
179 | // time_t seed=1298952499; | |
180 | srand((unsigned)seed); | |
181 | printf("Random drop initialized with seed = %lu\n", seed); | |
182 | ||
183 | if(connect(fd, (struct sockaddr *)&sa, sizeof(sa))==-1) | |
184 | { | |
185 | perror("connect"); | |
186 | return errno; | |
187 | } | |
188 | ||
189 | /* Change to non blocking io */ | |
190 | fcntl(fd, F_SETFL, O_NONBLOCK); | |
191 | ||
192 | SSLConnectionRef c=(SSLConnectionRef)(intptr_t)fd; | |
193 | ||
194 | ||
195 | OSStatus ortn; | |
196 | SSLContextRef ctx = NULL; | |
197 | ||
198 | SSLClientCertificateState certState; | |
199 | SSLCipherSuite negCipher; | |
200 | SSLProtocol negVersion; | |
201 | ||
202 | /* | |
203 | * Set up a SecureTransport session. | |
204 | */ | |
205 | ortn = SSLNewDatagramContext(false, &ctx); | |
206 | if(ortn) { | |
207 | printSslErrStr("SSLNewDatagramContext", ortn); | |
208 | return ortn; | |
209 | } | |
210 | ortn = SSLSetIOFuncs(ctx, SocketRead, SocketWrite); | |
211 | if(ortn) { | |
212 | printSslErrStr("SSLSetIOFuncs", ortn); | |
213 | return ortn; | |
214 | } | |
215 | ||
216 | ortn = SSLSetConnection(ctx, c); | |
217 | if(ortn) { | |
218 | printSslErrStr("SSLSetConnection", ortn); | |
219 | return ortn; | |
220 | } | |
221 | ||
222 | ortn = SSLSetMaxDatagramRecordSize(ctx, 600); | |
223 | if(ortn) { | |
224 | printSslErrStr("SSLSetMaxDatagramRecordSize", ortn); | |
225 | return ortn; | |
226 | } | |
227 | ||
228 | /* Lets not verify the cert, which is a random test cert */ | |
229 | ortn = SSLSetEnableCertVerify(ctx, false); | |
230 | if(ortn) { | |
231 | printSslErrStr("SSLSetEnableCertVerify", ortn); | |
232 | return ortn; | |
233 | } | |
234 | ||
235 | ortn = SSLSetCertificate(ctx, server_chain()); | |
236 | if(ortn) { | |
237 | printSslErrStr("SSLSetCertificate", ortn); | |
238 | return ortn; | |
239 | } | |
240 | ||
241 | do { | |
242 | ortn = SSLHandshake(ctx); | |
243 | if(ortn == errSSLWouldBlock) { | |
244 | /* keep UI responsive */ | |
245 | sslOutputDot(); | |
246 | } | |
247 | } while (ortn == errSSLWouldBlock); | |
248 | ||
249 | ||
250 | SSLGetClientCertificateState(ctx, &certState); | |
251 | SSLGetNegotiatedCipher(ctx, &negCipher); | |
252 | SSLGetNegotiatedProtocolVersion(ctx, &negVersion); | |
253 | ||
254 | int count; | |
255 | size_t len, readLen, writeLen; | |
256 | char buffer[BUFLEN]; | |
257 | ||
258 | count = 0; | |
259 | while(count<COUNT) { | |
260 | int timeout = 10000; | |
261 | ||
262 | snprintf(buffer, BUFLEN, "Message %d", count); | |
263 | len = strlen(buffer); | |
264 | ||
265 | ortn=SSLWrite(ctx, buffer, len, &writeLen); | |
266 | if(ortn) { | |
267 | printSslErrStr("SSLWrite", ortn); | |
268 | break; | |
269 | } | |
270 | printf("Wrote %lu bytes\n", writeLen); | |
271 | ||
272 | count++; | |
273 | ||
274 | do { | |
275 | ortn=SSLRead(ctx, buffer, BUFLEN, &readLen); | |
276 | } while((ortn==errSSLWouldBlock) && (timeout--)); | |
277 | if(ortn==errSSLWouldBlock) { | |
278 | printf("Echo timeout...\n"); | |
279 | continue; | |
280 | } | |
281 | if(ortn) { | |
282 | printSslErrStr("SSLRead", ortn); | |
283 | break; | |
284 | } | |
285 | buffer[readLen]=0; | |
286 | printf("Received %lu bytes: %s\n", readLen, buffer); | |
287 | ||
288 | } | |
289 | ||
290 | SSLClose(ctx); | |
291 | ||
292 | SSLDisposeContext(ctx); | |
293 | ||
294 | return ortn; | |
295 | } |