]>
Commit | Line | Data |
---|---|---|
d8f41ccd A |
1 | |
2 | #include <stdbool.h> | |
3 | #include <pthread.h> | |
4 | #include <fcntl.h> | |
5 | #include <sys/mman.h> | |
6 | #include <unistd.h> | |
7 | ||
8 | #include <CoreFoundation/CoreFoundation.h> | |
9 | ||
10 | #include <AssertMacros.h> | |
11 | #include <Security/SecureTransportPriv.h> /* SSLSetOption */ | |
12 | #include <Security/SecureTransport.h> | |
13 | #include <Security/SecPolicy.h> | |
14 | #include <Security/SecTrust.h> | |
15 | #include <Security/SecIdentity.h> | |
16 | #include <Security/SecIdentityPriv.h> | |
17 | #include <Security/SecCertificatePriv.h> | |
18 | #include <Security/SecKeyPriv.h> | |
19 | #include <Security/SecItem.h> | |
20 | #include <Security/SecRandom.h> | |
21 | ||
22 | #include <utilities/array_size.h> | |
23 | #include <string.h> | |
24 | #include <sys/types.h> | |
25 | #include <sys/socket.h> | |
26 | #include <errno.h> | |
27 | #include <stdlib.h> | |
28 | #include <mach/mach_time.h> | |
29 | ||
30 | #include <stdio.h> | |
31 | #include <unistd.h> | |
32 | #include <strings.h> | |
33 | #include <sys/types.h> | |
34 | #include <sys/socket.h> | |
35 | #include <netinet/in.h> | |
36 | #include <arpa/inet.h> | |
37 | #include <netdb.h> | |
38 | #include <errno.h> | |
39 | ||
40 | ||
41 | #if TARGET_OS_IPHONE | |
42 | #include <Security/SecRSAKey.h> | |
43 | #endif | |
44 | ||
45 | #include "ssl_regressions.h" | |
46 | #include "ssl-utils.h" | |
47 | ||
48 | typedef struct { | |
49 | SSLContextRef st; | |
50 | int comm; | |
51 | CFArrayRef certs; | |
52 | } ssl_test_handle; | |
53 | ||
54 | ||
55 | // MARK: - | |
56 | // MARK: SecureTransport support | |
57 | ||
58 | #if 0 | |
59 | static void hexdump(const uint8_t *bytes, size_t len) { | |
60 | size_t ix; | |
61 | printf("socket write(%p, %lu)\n", bytes, len); | |
62 | for (ix = 0; ix < len; ++ix) { | |
63 | if (!(ix % 16)) | |
64 | printf("\n"); | |
65 | printf("%02X ", bytes[ix]); | |
66 | } | |
67 | printf("\n"); | |
68 | } | |
69 | #else | |
70 | #define hexdump(bytes, len) | |
71 | #endif | |
72 | ||
73 | ||
74 | /* Listen to on port */ | |
75 | static int SocketListen(int port) | |
76 | { | |
77 | struct sockaddr_in sa; | |
78 | int sock; | |
79 | int val = 1; | |
80 | ||
81 | if ((sock=socket(AF_INET, SOCK_STREAM, 0))==-1) { | |
82 | perror("socket"); | |
83 | return -errno; | |
84 | } | |
85 | ||
86 | setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (void *)&val, sizeof(val)); | |
87 | ||
88 | memset((char *) &sa, 0, sizeof(sa)); | |
89 | sa.sin_family = AF_INET; | |
90 | sa.sin_port = htons(port); | |
91 | sa.sin_addr.s_addr = htonl(INADDR_ANY); | |
92 | ||
93 | if(bind (sock, (struct sockaddr *)&sa, sizeof(sa))==-1) | |
94 | { | |
95 | perror("bind"); | |
96 | return -errno; | |
97 | } | |
98 | ||
99 | if(listen(sock, 5)==-1) | |
100 | { | |
101 | perror("listen"); | |
102 | return -errno; | |
103 | } | |
104 | ||
105 | return sock; | |
106 | } | |
107 | ||
108 | ||
109 | static OSStatus SocketWrite(SSLConnectionRef conn, const void *data, size_t *length) | |
110 | { | |
111 | size_t len = *length; | |
112 | uint8_t *ptr = (uint8_t *)data; | |
113 | ||
114 | do { | |
115 | ssize_t ret; | |
116 | do { | |
117 | hexdump(ptr, len); | |
118 | ret = write((int)conn, ptr, len); | |
119 | } while ((ret < 0) && (errno == EAGAIN || errno == EINTR)); | |
120 | if (ret > 0) { | |
121 | len -= ret; | |
122 | ptr += ret; | |
123 | } | |
124 | else | |
125 | return -36; | |
126 | } while (len > 0); | |
127 | ||
128 | *length = *length - len; | |
129 | return errSecSuccess; | |
130 | } | |
131 | ||
132 | static OSStatus SocketRead(SSLConnectionRef conn, void *data, size_t *length) | |
133 | { | |
134 | size_t len = *length; | |
135 | uint8_t *ptr = (uint8_t *)data; | |
136 | ||
137 | do { | |
138 | ssize_t ret; | |
139 | do { | |
140 | ret = read((int)conn, ptr, len); | |
141 | } while ((ret < 0) && (errno == EINPROGRESS || errno == EAGAIN || errno == EINTR)); | |
142 | if (ret > 0) { | |
143 | len -= ret; | |
144 | ptr += ret; | |
145 | } else { | |
146 | printf("read error(%d): ret=%zd, errno=%d\n", (int)conn, ret, errno); | |
147 | return -errno; | |
148 | } | |
149 | } while (len > 0); | |
150 | ||
151 | *length = *length - len; | |
152 | return errSecSuccess; | |
153 | } | |
154 | ||
155 | ||
156 | static SSLContextRef make_ssl_ref(bool server, int sock, CFArrayRef certs) | |
157 | { | |
158 | SSLContextRef ctx = SSLCreateContext(kCFAllocatorDefault, server?kSSLServerSide:kSSLClientSide, kSSLStreamType); | |
159 | require(ctx, out); | |
160 | ||
161 | require_noerr(SSLSetIOFuncs(ctx, (SSLReadFunc)SocketRead, (SSLWriteFunc)SocketWrite), out); | |
162 | require_noerr(SSLSetConnection(ctx, (SSLConnectionRef)(intptr_t)sock), out); | |
163 | require_noerr(SSLSetCertificate(ctx, certs), out); | |
164 | ||
165 | return ctx; | |
166 | out: | |
167 | if (ctx) | |
168 | CFRelease(ctx); | |
169 | return NULL; | |
170 | } | |
171 | ||
172 | ||
173 | static ssl_test_handle * | |
174 | ssl_test_handle_create(int comm, CFArrayRef certs) | |
175 | { | |
176 | ssl_test_handle *handle = calloc(1, sizeof(ssl_test_handle)); | |
177 | if (handle) { | |
178 | handle->comm = comm; | |
179 | handle->certs = certs; | |
180 | handle->st = make_ssl_ref(true, comm, certs); | |
181 | } | |
182 | return handle; | |
183 | } | |
184 | ||
185 | static void *securetransport_ssl_thread(void *arg) | |
186 | { | |
187 | OSStatus ortn; | |
d64be36e | 188 | int sock = *((int*)arg); |
d8f41ccd A |
189 | |
190 | int socket = accept(sock, NULL, NULL); | |
191 | ||
192 | CFArrayRef server_certs = server_chain(); | |
193 | ssl_test_handle * ssl = ssl_test_handle_create(socket, server_certs); | |
194 | SSLContextRef ctx = ssl->st; | |
195 | ||
196 | pthread_setname_np("server thread"); | |
197 | ||
198 | //uint64_t start = mach_absolute_time(); | |
199 | do { | |
200 | ortn = SSLHandshake(ctx); | |
201 | } while (ortn == errSSLWouldBlock); | |
202 | ||
203 | require_noerr_action_quiet(ortn, out, | |
204 | fprintf(stderr, "Fell out of SSLHandshake with error: %d\n", (int)ortn)); | |
205 | ||
206 | //uint64_t elapsed = mach_absolute_time() - start; | |
207 | //fprintf(stderr, "setr elapsed: %lld\n", elapsed); | |
208 | ||
209 | /* | |
210 | SSLProtocol proto = kSSLProtocolUnknown; | |
211 | require_noerr_quiet(SSLGetNegotiatedProtocolVersion(ctx, &proto), out); */ | |
212 | ||
213 | SSLCipherSuite cipherSuite; | |
214 | require_noerr_quiet(ortn = SSLGetNegotiatedCipher(ctx, &cipherSuite), out); | |
215 | //fprintf(stderr, "st negotiated %s\n", sslcipher_itoa(cipherSuite)); | |
216 | ||
217 | ||
218 | out: | |
219 | CFRelease(server_certs); | |
220 | ||
221 | SSLClose(ctx); | |
222 | CFRelease(ctx); | |
223 | if(ssl) { | |
224 | close(ssl->comm); | |
225 | free(ssl); | |
226 | } | |
227 | pthread_exit((void *)(intptr_t)ortn); | |
228 | return NULL; | |
229 | } | |
230 | ||
231 | ||
232 | ||
233 | static void | |
234 | tests(void) | |
235 | { | |
236 | pthread_t server_thread; | |
237 | int socket; | |
238 | ||
239 | socket = SocketListen(4443); | |
240 | ||
241 | ok(socket>=0, "SocketListen failed"); | |
242 | if(socket<0) { | |
243 | return; | |
244 | } | |
245 | //fprintf(stderr, "session_id: %d\n", session_id); | |
246 | ||
d64be36e | 247 | pthread_create(&server_thread, NULL, securetransport_ssl_thread, (void*)&socket); |
d8f41ccd A |
248 | |
249 | system("/usr/bin/openssl s_client -msg -debug -connect localhost:4443"); | |
250 | ||
251 | int server_err; | |
252 | pthread_join(server_thread, (void*)&server_err); | |
253 | ||
254 | ok(!server_err, "Server thread failed err=%d", server_err); | |
255 | } | |
256 | ||
257 | int ssl_50_server(int argc, char *const *argv) | |
258 | { | |
259 | ||
260 | plan_tests(1 + 1 /*cert*/); | |
261 | ||
262 | ||
263 | tests(); | |
264 | ||
265 | return 0; | |
266 | } |