2 * Copyright (c) 2011-2014 Apple Inc. All Rights Reserved.
4 * @APPLE_LICENSE_HEADER_START@
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
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.
21 * @APPLE_LICENSE_HEADER_END@
25 #include <Security/Security.h>
26 #include <Security/SecBase.h>
28 #include "../sslViewer/sslAppUtils.h"
31 #include <sys/types.h>
32 #include <sys/socket.h>
33 #include <netinet/in.h>
34 #include <arpa/inet.h>
37 #include <unistd.h> /* close() */
38 #include <string.h> /* memset() */
43 #include <securityd/spi.h>
48 #include "ssl-utils.h"
50 static void dumppacket(const unsigned char *data
, unsigned long len
)
55 if((i
&0xf)==0) printf("%04lx :",i
);
56 printf(" %02x", data
[i
]);
57 if((i
&0xf)==0xf) printf("\n");
63 /* 2K should be enough for everybody */
65 static unsigned char readBuffer
[MTU
];
66 static unsigned int readOff
=0;
67 static size_t readLeft
=0;
71 SSLConnectionRef connection
,
75 int fd
= (int)connection
;
77 uint8_t *d
=readBuffer
;
81 len
= read(fd
, readBuffer
, MTU
);
85 readLeft
=(size_t) len
;
86 printf("SocketRead: %ld bytes... epoch: %02x seq=%02x%02x\n",
87 len
, d
[4], d
[9], d
[10]);
92 // printf("SocketRead: EAGAIN\n");
94 /* nonblocking, no data */
95 return errSSLWouldBlock
;
103 if(readLeft
<*dataLength
) {
104 *dataLength
=readLeft
;
107 memcpy(data
, readBuffer
+readOff
, *dataLength
);
108 readLeft
-=*dataLength
;
109 readOff
+=*dataLength
;
112 return errSecSuccess
;
118 OSStatus
SocketWrite(
119 SSLConnectionRef connection
,
121 size_t *dataLength
) /* IN/OUT */
123 int fd
= (int)connection
;
125 OSStatus err
= errSecSuccess
;
126 const uint8_t *d
=data
;
130 /* drop 1/8 packets */
131 printf("SocketWrite: Drop %ld bytes... epoch: %02x seq=%02x%02x\n",
132 *dataLength
, d
[4], d
[9], d
[10]);
133 return errSecSuccess
;
137 len
= send(fd
, data
, *dataLength
, 0);
140 *dataLength
=(size_t)len
;
142 printf("SocketWrite: Sent %ld bytes... epoch: %02x seq=%02x%02x\n",
143 len
, d
[4], d
[9], d
[10]);
151 /* nonblocking, no data */
152 err
= errSSLWouldBlock
;
155 perror("SocketWrite");
165 int main(int argc
, char **argv
)
167 struct sockaddr_in sa
; /* server address for bind */
168 struct sockaddr_in ca
; /* client address for connect */
178 if ((fd
=socket(AF_INET
, SOCK_DGRAM
, 0))==-1) {
183 time_t seed
=time(NULL
);
184 // time_t seed=1298952496;
185 srand((unsigned)seed
);
186 printf("Random drop initialized with seed = %lu\n", seed
);
188 memset((char *) &sa
, 0, sizeof(sa
));
189 sa
.sin_family
= AF_INET
;
190 sa
.sin_port
= htons(PORT
);
191 sa
.sin_addr
.s_addr
= htonl(INADDR_ANY
);
193 if(bind (fd
, (struct sockaddr
*)&sa
, sizeof(sa
))==-1)
199 printf("Waiting for first packet...\n");
201 socklen_t slen
=sizeof(ca
);
203 if((l
=recvfrom(fd
, &b
, 1, MSG_PEEK
, (struct sockaddr
*)&ca
, &slen
))==-1)
209 printf("Received packet from %s (%ld), connecting...\n", inet_ntoa(ca
.sin_addr
), l
);
211 if(connect(fd
, (struct sockaddr
*)&ca
, sizeof(ca
))==-1)
217 /* Change to non blocking */
218 fcntl(fd
, F_SETFL
, O_NONBLOCK
);
221 SSLConnectionRef c
=(SSLConnectionRef
)(intptr_t)fd
;
225 SSLContextRef ctx
= NULL
;
227 SSLClientCertificateState certState
;
228 SSLCipherSuite negCipher
;
231 * Set up a SecureTransport session.
233 ortn
= SSLNewDatagramContext(true, &ctx
);
235 printSslErrStr("SSLNewDatagramContext", ortn
);
239 ortn
= SSLSetIOFuncs(ctx
, SocketRead
, SocketWrite
);
241 printSslErrStr("SSLSetIOFuncs", ortn
);
245 ortn
= SSLSetConnection(ctx
, c
);
247 printSslErrStr("SSLSetConnection", ortn
);
251 ortn
= SSLSetDatagramHelloCookie(ctx
, &ca
, 32);
253 printSslErrStr("SSLSetDatagramHelloCookie", ortn
);
257 ortn
= SSLSetMaxDatagramRecordSize(ctx
, 400);
259 printSslErrStr("SSLSetMaxDatagramRecordSize", ortn
);
263 /* Lets not verify the cert, which is a random test cert */
264 ortn
= SSLSetEnableCertVerify(ctx
, false);
266 printSslErrStr("SSLSetEnableCertVerify", ortn
);
270 ortn
= SSLSetCertificate(ctx
, server_chain());
272 printSslErrStr("SSLSetCertificate", ortn
);
276 ortn
= SSLSetClientSideAuthenticate(ctx
, kAlwaysAuthenticate
);
278 printSslErrStr("SSLSetCertificate", ortn
);
282 printf("Server Handshake...\n");
284 ortn
= SSLHandshake(ctx
);
285 if(ortn
== errSSLWouldBlock
) {
286 /* keep UI responsive */
289 } while (ortn
== errSSLWouldBlock
);
292 printSslErrStr("SSLHandshake", ortn
);
296 SSLGetClientCertificateState(ctx
, &certState
);
297 SSLGetNegotiatedCipher(ctx
, &negCipher
);
299 printf("Server Handshake done. Cipher is %s\n", sslGetCipherSuiteString(negCipher
));
301 unsigned char buffer
[MTU
];
305 while((ortn
=SSLRead(ctx
, buffer
, MTU
, &readLen
))==errSSLWouldBlock
);
307 printSslErrStr("SSLRead", ortn
);
311 printf("Received %lu bytes:\n", readLen
);
312 dumppacket(buffer
, readLen
);
314 ortn
=SSLWrite(ctx
, buffer
, readLen
, &len
);
316 printSslErrStr("SSLRead", ortn
);
319 printf("Echoing %lu bytes\n", len
);
322 SSLDisposeContext(ctx
);