Revert "Merged all Chromoting Host code into remoting_core.dll (Windows)."
[chromium-blink-merge.git] / net / third_party / nss / ssl / sslauth.c
blob229d890b2447be78d270128565f3c510736fea8f
1 /* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this
3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
4 /* $Id: sslauth.c,v 1.18 2012/04/25 14:50:12 gerv%gerv.net Exp $ */
5 #include "cert.h"
6 #include "secitem.h"
7 #include "ssl.h"
8 #include "sslimpl.h"
9 #include "sslproto.h"
10 #include "pk11func.h"
12 /* NEED LOCKS IN HERE. */
13 CERTCertificate *
14 SSL_PeerCertificate(PRFileDesc *fd)
16 sslSocket *ss;
18 ss = ssl_FindSocket(fd);
19 if (!ss) {
20 SSL_DBG(("%d: SSL[%d]: bad socket in PeerCertificate",
21 SSL_GETPID(), fd));
22 return 0;
24 if (ss->opt.useSecurity && ss->sec.peerCert) {
25 return CERT_DupCertificate(ss->sec.peerCert);
27 return 0;
30 /* NEED LOCKS IN HERE. */
31 SECStatus
32 SSL_PeerCertificateChain(PRFileDesc *fd, CERTCertificate **certs,
33 unsigned int *numCerts, unsigned int maxNumCerts)
35 sslSocket *ss;
36 ssl3CertNode* cur;
38 ss = ssl_FindSocket(fd);
39 if (!ss) {
40 SSL_DBG(("%d: SSL[%d]: bad socket in PeerCertificateChain",
41 SSL_GETPID(), fd));
42 return SECFailure;
44 if (!ss->opt.useSecurity)
45 return SECFailure;
47 if (ss->sec.peerCert == NULL) {
48 *numCerts = 0;
49 return SECSuccess;
52 *numCerts = 1; /* for the leaf certificate */
53 if (maxNumCerts > 0)
54 certs[0] = CERT_DupCertificate(ss->sec.peerCert);
56 for (cur = ss->ssl3.peerCertChain; cur; cur = cur->next) {
57 if (*numCerts < maxNumCerts)
58 certs[*numCerts] = CERT_DupCertificate(cur->cert);
59 (*numCerts)++;
62 return SECSuccess;
65 /* NEED LOCKS IN HERE. */
66 CERTCertificate *
67 SSL_LocalCertificate(PRFileDesc *fd)
69 sslSocket *ss;
71 ss = ssl_FindSocket(fd);
72 if (!ss) {
73 SSL_DBG(("%d: SSL[%d]: bad socket in PeerCertificate",
74 SSL_GETPID(), fd));
75 return NULL;
77 if (ss->opt.useSecurity) {
78 if (ss->sec.localCert) {
79 return CERT_DupCertificate(ss->sec.localCert);
81 if (ss->sec.ci.sid && ss->sec.ci.sid->localCert) {
82 return CERT_DupCertificate(ss->sec.ci.sid->localCert);
85 return NULL;
90 /* NEED LOCKS IN HERE. */
91 SECStatus
92 SSL_SecurityStatus(PRFileDesc *fd, int *op, char **cp, int *kp0, int *kp1,
93 char **ip, char **sp)
95 sslSocket *ss;
96 const char *cipherName;
97 PRBool isDes = PR_FALSE;
98 PRBool enoughFirstHsDone = PR_FALSE;
100 ss = ssl_FindSocket(fd);
101 if (!ss) {
102 SSL_DBG(("%d: SSL[%d]: bad socket in SecurityStatus",
103 SSL_GETPID(), fd));
104 return SECFailure;
107 if (cp) *cp = 0;
108 if (kp0) *kp0 = 0;
109 if (kp1) *kp1 = 0;
110 if (ip) *ip = 0;
111 if (sp) *sp = 0;
112 if (op) {
113 *op = SSL_SECURITY_STATUS_OFF;
116 if (ss->firstHsDone) {
117 enoughFirstHsDone = PR_TRUE;
118 } else if (ss->version >= SSL_LIBRARY_VERSION_3_0 &&
119 ssl3_CanFalseStart(ss)) {
120 enoughFirstHsDone = PR_TRUE;
123 if (ss->opt.useSecurity && enoughFirstHsDone) {
124 if (ss->version < SSL_LIBRARY_VERSION_3_0) {
125 cipherName = ssl_cipherName[ss->sec.cipherType];
126 } else {
127 cipherName = ssl3_cipherName[ss->sec.cipherType];
129 PORT_Assert(cipherName);
130 if (cipherName) {
131 if (PORT_Strstr(cipherName, "DES")) isDes = PR_TRUE;
133 if (cp) {
134 *cp = PORT_Strdup(cipherName);
138 if (kp0) {
139 *kp0 = ss->sec.keyBits;
140 if (isDes) *kp0 = (*kp0 * 7) / 8;
142 if (kp1) {
143 *kp1 = ss->sec.secretKeyBits;
144 if (isDes) *kp1 = (*kp1 * 7) / 8;
146 if (op) {
147 if (ss->sec.keyBits == 0) {
148 *op = SSL_SECURITY_STATUS_OFF;
149 } else if (ss->sec.secretKeyBits < 90) {
150 *op = SSL_SECURITY_STATUS_ON_LOW;
152 } else {
153 *op = SSL_SECURITY_STATUS_ON_HIGH;
157 if (ip || sp) {
158 CERTCertificate *cert;
160 cert = ss->sec.peerCert;
161 if (cert) {
162 if (ip) {
163 *ip = CERT_NameToAscii(&cert->issuer);
165 if (sp) {
166 *sp = CERT_NameToAscii(&cert->subject);
168 } else {
169 if (ip) {
170 *ip = PORT_Strdup("no certificate");
172 if (sp) {
173 *sp = PORT_Strdup("no certificate");
179 return SECSuccess;
182 /************************************************************************/
184 /* NEED LOCKS IN HERE. */
185 SECStatus
186 SSL_AuthCertificateHook(PRFileDesc *s, SSLAuthCertificate func, void *arg)
188 sslSocket *ss;
190 ss = ssl_FindSocket(s);
191 if (!ss) {
192 SSL_DBG(("%d: SSL[%d]: bad socket in AuthCertificateHook",
193 SSL_GETPID(), s));
194 return SECFailure;
197 ss->authCertificate = func;
198 ss->authCertificateArg = arg;
200 return SECSuccess;
203 /* NEED LOCKS IN HERE. */
204 SECStatus
205 SSL_GetClientAuthDataHook(PRFileDesc *s, SSLGetClientAuthData func,
206 void *arg)
208 sslSocket *ss;
210 ss = ssl_FindSocket(s);
211 if (!ss) {
212 SSL_DBG(("%d: SSL[%d]: bad socket in GetClientAuthDataHook",
213 SSL_GETPID(), s));
214 return SECFailure;
217 ss->getClientAuthData = func;
218 ss->getClientAuthDataArg = arg;
219 return SECSuccess;
222 SECStatus
223 SSL_SetClientChannelIDCallback(PRFileDesc *fd,
224 SSLClientChannelIDCallback callback,
225 void *arg) {
226 sslSocket *ss = ssl_FindSocket(fd);
228 if (!ss) {
229 SSL_DBG(("%d: SSL[%d]: bad socket in SSL_SetClientChannelIDCallback",
230 SSL_GETPID(), fd));
231 return SECFailure;
234 ss->getChannelID = callback;
235 ss->getChannelIDArg = arg;
237 return SECSuccess;
240 #ifdef NSS_PLATFORM_CLIENT_AUTH
241 /* NEED LOCKS IN HERE. */
242 SECStatus
243 SSL_GetPlatformClientAuthDataHook(PRFileDesc *s,
244 SSLGetPlatformClientAuthData func,
245 void *arg)
247 sslSocket *ss;
249 ss = ssl_FindSocket(s);
250 if (!ss) {
251 SSL_DBG(("%d: SSL[%d]: bad socket in GetPlatformClientAuthDataHook",
252 SSL_GETPID(), s));
253 return SECFailure;
256 ss->getPlatformClientAuthData = func;
257 ss->getPlatformClientAuthDataArg = arg;
258 return SECSuccess;
260 #endif /* NSS_PLATFORM_CLIENT_AUTH */
262 /* NEED LOCKS IN HERE. */
263 SECStatus
264 SSL_SetPKCS11PinArg(PRFileDesc *s, void *arg)
266 sslSocket *ss;
268 ss = ssl_FindSocket(s);
269 if (!ss) {
270 SSL_DBG(("%d: SSL[%d]: bad socket in GetClientAuthDataHook",
271 SSL_GETPID(), s));
272 return SECFailure;
275 ss->pkcs11PinArg = arg;
276 return SECSuccess;
280 /* This is the "default" authCert callback function. It is called when a
281 * certificate message is received from the peer and the local application
282 * has not registered an authCert callback function.
284 SECStatus
285 SSL_AuthCertificate(void *arg, PRFileDesc *fd, PRBool checkSig, PRBool isServer)
287 SECStatus rv;
288 CERTCertDBHandle * handle;
289 sslSocket * ss;
290 SECCertUsage certUsage;
291 const char * hostname = NULL;
293 ss = ssl_FindSocket(fd);
294 PORT_Assert(ss != NULL);
295 if (!ss) {
296 return SECFailure;
299 handle = (CERTCertDBHandle *)arg;
301 /* this may seem backwards, but isn't. */
302 certUsage = isServer ? certUsageSSLClient : certUsageSSLServer;
304 rv = CERT_VerifyCertNow(handle, ss->sec.peerCert, checkSig, certUsage,
305 ss->pkcs11PinArg);
307 if ( rv != SECSuccess || isServer )
308 return rv;
310 /* cert is OK. This is the client side of an SSL connection.
311 * Now check the name field in the cert against the desired hostname.
312 * NB: This is our only defense against Man-In-The-Middle (MITM) attacks!
314 hostname = ss->url;
315 if (hostname && hostname[0])
316 rv = CERT_VerifyCertName(ss->sec.peerCert, hostname);
317 else
318 rv = SECFailure;
319 if (rv != SECSuccess)
320 PORT_SetError(SSL_ERROR_BAD_CERT_DOMAIN);
322 return rv;