]> git.saurik.com Git - apple/security.git/blob - sslViewer/sslClient.cpp
Security-59306.41.2.tar.gz
[apple/security.git] / sslViewer / sslClient.cpp
1 /*
2 * Copyright (c) 2006-2008,2010-2011,2013 Apple Inc. All Rights Reserved.
3 *
4 * sslClient.cpp : perform one SSL client side sesssion
5 */
6
7 #include <Security/SecureTransport.h>
8 #include <Security/Security.h>
9 #include <clAppUtils/sslAppUtils.h>
10 #include <clAppUtils/ioSock.h>
11 #include <clAppUtils/sslThreading.h>
12 #include <utilLib/fileIo.h>
13 #include <utilLib/common.h>
14 #include <security_cdsa_utils/cuPrintCert.h>
15
16 #include <Security/SecBase.h>
17
18 #include <stdio.h>
19 #include <stdlib.h>
20 #include <string.h>
21 #include <time.h>
22 #include <ctype.h>
23 #include <sys/param.h>
24
25 /* when true, keep listening until server disconnects */
26 #define KEEP_CONNECTED 1
27
28 #define CLIENT_GETMSG "GET / HTTP/1.0\r\n\r\n"
29
30 #define READBUF_LEN 256
31
32 /* relies on SSLSetProtocolVersionEnabled */
33 OSStatus sslAppClient(
34 SslAppTestParams *params)
35 {
36 PeerSpec peerId;
37 otSocket sock = 0;
38 OSStatus ortn;
39 SSLContextRef ctx = NULL;
40 SecKeychainRef clientKc = nil;
41 CFArrayRef clientCerts = nil;
42
43 sslThrDebug("Client", "starting");
44 params->negVersion = kSSLProtocolUnknown;
45 params->negCipher = SSL_NULL_WITH_NULL_NULL;
46 params->ortn = noHardwareErr;
47
48 /* first make sure requested server is there */
49 ortn = MakeServerConnection(params->hostName, params->port,
50 params->nonBlocking, &sock, &peerId);
51 if(ortn) {
52 printf("MakeServerConnection returned %d; aborting\n", (int)ortn);
53 return ortn;
54 }
55
56 /*
57 * Set up a SecureTransport session.
58 */
59 ortn = SSLNewContext(false, &ctx);
60 if(ortn) {
61 printSslErrStr("SSLNewContext", ortn);
62 goto cleanup;
63 }
64 ortn = SSLSetIOFuncs(ctx, SocketRead, SocketWrite);
65 if(ortn) {
66 printSslErrStr("SSLSetIOFuncs", ortn);
67 goto cleanup;
68 }
69 ortn = SSLSetConnection(ctx, (SSLConnectionRef)sock);
70 if(ortn) {
71 printSslErrStr("SSLSetConnection", ortn);
72 goto cleanup;
73 }
74 if(!params->skipHostNameCheck) {
75 ortn = SSLSetPeerDomainName(ctx, params->hostName,
76 strlen(params->hostName));
77 if(ortn) {
78 printSslErrStr("SSLSetPeerDomainName", ortn);
79 goto cleanup;
80 }
81 }
82
83 /* remainder of setup is optional */
84 if(params->anchorFile) {
85 ortn = sslAddTrustedRoot(ctx, params->anchorFile, params->replaceAnchors);
86 if(ortn) {
87 goto cleanup;
88 }
89 }
90 ortn = sslSetProtocols(ctx, params->acceptedProts, params->tryVersion);
91 if(ortn) {
92 goto cleanup;
93 }
94 if(params->resumeEnable) {
95 ortn = SSLSetPeerID(ctx, &peerId, sizeof(PeerSpec));
96 if(ortn) {
97 printSslErrStr("SSLSetPeerID", ortn);
98 goto cleanup;
99 }
100 }
101 if(params->disableCertVerify) {
102 ortn = SSLSetEnableCertVerify(ctx, false);
103 if(ortn) {
104 printSslErrStr("SSLSetEnableCertVerify", ortn);
105 goto cleanup;
106 }
107 }
108 if(params->ciphers != NULL) {
109 ortn = sslSetEnabledCiphers(ctx, params->ciphers);
110 if(ortn) {
111 goto cleanup;
112 }
113 }
114 if(params->myCertKcName) {
115 clientCerts = getSslCerts(params->myCertKcName, false, false, NULL, &clientKc);
116 if(clientCerts == nil) {
117 exit(1);
118 }
119 if(params->password) {
120 ortn = SecKeychainUnlock(clientKc, strlen(params->password),
121 (void *)params->password, true);
122 if(ortn) {
123 printf("SecKeychainUnlock returned %d\n", (int)ortn);
124 /* oh well */
125 }
126 }
127 if(params->idIsTrustedRoot) {
128 /* assume this is a root we want to implicitly trust */
129 ortn = addIdentityAsTrustedRoot(ctx, clientCerts);
130 if(ortn) {
131 goto cleanup;
132 }
133 }
134 ortn = SSLSetCertificate(ctx, clientCerts);
135 if(ortn) {
136 printSslErrStr("SSLSetCertificate", ortn);
137 goto cleanup;
138 }
139 }
140 do {
141 ortn = SSLHandshake(ctx);
142 if((ortn == errSSLWouldBlock) && !params->silent) {
143 /* keep UI responsive */
144 sslOutputDot();
145 }
146 } while (ortn == errSSLWouldBlock);
147
148 SSLGetClientCertificateState(ctx, &params->certState);
149 SSLGetNegotiatedCipher(ctx, &params->negCipher);
150 SSLGetNegotiatedProtocolVersion(ctx, &params->negVersion);
151
152 if(ortn != errSecSuccess) {
153 goto cleanup;
154 }
155
156 /* send a GET msg */
157 size_t actLen;
158 ortn = SSLWrite(ctx, CLIENT_GETMSG, strlen(CLIENT_GETMSG), &actLen);
159 if(ortn) {
160 printSslErrStr("SSLWrite", ortn);
161 goto cleanup;
162 }
163
164 #if KEEP_CONNECTED
165
166 /*
167 * Consume any server data and wait for server to disconnect
168 */
169 char readBuf[READBUF_LEN];
170 do {
171 ortn = SSLRead(ctx, readBuf, READBUF_LEN, &actLen);
172 } while (ortn == errSSLWouldBlock);
173
174 /* convert normal "shutdown" into zero err rtn */
175 if(ortn == errSSLClosedGraceful) {
176 ortn = errSecSuccess;
177 }
178 #endif /* KEEP_CONNECTED */
179
180 cleanup:
181 if(ctx) {
182 OSStatus cerr = SSLClose(ctx);
183 if(ortn == errSecSuccess) {
184 ortn = cerr;
185 }
186 }
187 if(sock) {
188 endpointShutdown(sock);
189 }
190 if(ctx) {
191 SSLDisposeContext(ctx);
192 }
193 params->ortn = ortn;
194 sslThrDebug("Client", "done");
195 return ortn;
196 }