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 48typedef 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 59static 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 */ 75static 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 109static 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 132static 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 156static 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; 166out: 167 if (ctx) 168 CFRelease(ctx); 169 return NULL; 170} 171 172 173static ssl_test_handle * 174ssl_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 185static void *securetransport_ssl_thread(void *arg) 186{ 187 OSStatus ortn; 188 int sock = (int)arg; 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 218out: 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 233static void 234tests(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 247 pthread_create(&server_thread, NULL, securetransport_ssl_thread, socket); 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 257int 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} 267