1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/security/nss/lib/ssl/sslauth.c Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,294 @@ 1.4 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.5 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.6 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.7 +#include "cert.h" 1.8 +#include "secitem.h" 1.9 +#include "ssl.h" 1.10 +#include "sslimpl.h" 1.11 +#include "sslproto.h" 1.12 +#include "pk11func.h" 1.13 +#include "ocsp.h" 1.14 + 1.15 +/* NEED LOCKS IN HERE. */ 1.16 +CERTCertificate * 1.17 +SSL_PeerCertificate(PRFileDesc *fd) 1.18 +{ 1.19 + sslSocket *ss; 1.20 + 1.21 + ss = ssl_FindSocket(fd); 1.22 + if (!ss) { 1.23 + SSL_DBG(("%d: SSL[%d]: bad socket in PeerCertificate", 1.24 + SSL_GETPID(), fd)); 1.25 + return 0; 1.26 + } 1.27 + if (ss->opt.useSecurity && ss->sec.peerCert) { 1.28 + return CERT_DupCertificate(ss->sec.peerCert); 1.29 + } 1.30 + return 0; 1.31 +} 1.32 + 1.33 +/* NEED LOCKS IN HERE. */ 1.34 +CERTCertList * 1.35 +SSL_PeerCertificateChain(PRFileDesc *fd) 1.36 +{ 1.37 + sslSocket *ss; 1.38 + CERTCertList *chain = NULL; 1.39 + CERTCertificate *cert; 1.40 + ssl3CertNode *cur; 1.41 + 1.42 + ss = ssl_FindSocket(fd); 1.43 + if (!ss) { 1.44 + SSL_DBG(("%d: SSL[%d]: bad socket in PeerCertificateChain", 1.45 + SSL_GETPID(), fd)); 1.46 + return NULL; 1.47 + } 1.48 + if (!ss->opt.useSecurity || !ss->sec.peerCert) { 1.49 + PORT_SetError(SSL_ERROR_NO_CERTIFICATE); 1.50 + return NULL; 1.51 + } 1.52 + chain = CERT_NewCertList(); 1.53 + if (!chain) { 1.54 + return NULL; 1.55 + } 1.56 + cert = CERT_DupCertificate(ss->sec.peerCert); 1.57 + if (CERT_AddCertToListTail(chain, cert) != SECSuccess) { 1.58 + goto loser; 1.59 + } 1.60 + for (cur = ss->ssl3.peerCertChain; cur; cur = cur->next) { 1.61 + cert = CERT_DupCertificate(cur->cert); 1.62 + if (CERT_AddCertToListTail(chain, cert) != SECSuccess) { 1.63 + goto loser; 1.64 + } 1.65 + } 1.66 + return chain; 1.67 + 1.68 +loser: 1.69 + CERT_DestroyCertList(chain); 1.70 + return NULL; 1.71 +} 1.72 + 1.73 +/* NEED LOCKS IN HERE. */ 1.74 +CERTCertificate * 1.75 +SSL_LocalCertificate(PRFileDesc *fd) 1.76 +{ 1.77 + sslSocket *ss; 1.78 + 1.79 + ss = ssl_FindSocket(fd); 1.80 + if (!ss) { 1.81 + SSL_DBG(("%d: SSL[%d]: bad socket in PeerCertificate", 1.82 + SSL_GETPID(), fd)); 1.83 + return NULL; 1.84 + } 1.85 + if (ss->opt.useSecurity) { 1.86 + if (ss->sec.localCert) { 1.87 + return CERT_DupCertificate(ss->sec.localCert); 1.88 + } 1.89 + if (ss->sec.ci.sid && ss->sec.ci.sid->localCert) { 1.90 + return CERT_DupCertificate(ss->sec.ci.sid->localCert); 1.91 + } 1.92 + } 1.93 + return NULL; 1.94 +} 1.95 + 1.96 + 1.97 + 1.98 +/* NEED LOCKS IN HERE. */ 1.99 +SECStatus 1.100 +SSL_SecurityStatus(PRFileDesc *fd, int *op, char **cp, int *kp0, int *kp1, 1.101 + char **ip, char **sp) 1.102 +{ 1.103 + sslSocket *ss; 1.104 + const char *cipherName; 1.105 + PRBool isDes = PR_FALSE; 1.106 + 1.107 + ss = ssl_FindSocket(fd); 1.108 + if (!ss) { 1.109 + SSL_DBG(("%d: SSL[%d]: bad socket in SecurityStatus", 1.110 + SSL_GETPID(), fd)); 1.111 + return SECFailure; 1.112 + } 1.113 + 1.114 + if (cp) *cp = 0; 1.115 + if (kp0) *kp0 = 0; 1.116 + if (kp1) *kp1 = 0; 1.117 + if (ip) *ip = 0; 1.118 + if (sp) *sp = 0; 1.119 + if (op) { 1.120 + *op = SSL_SECURITY_STATUS_OFF; 1.121 + } 1.122 + 1.123 + if (ss->opt.useSecurity && ss->enoughFirstHsDone) { 1.124 + if (ss->version < SSL_LIBRARY_VERSION_3_0) { 1.125 + cipherName = ssl_cipherName[ss->sec.cipherType]; 1.126 + } else { 1.127 + cipherName = ssl3_cipherName[ss->sec.cipherType]; 1.128 + } 1.129 + PORT_Assert(cipherName); 1.130 + if (cipherName) { 1.131 + if (PORT_Strstr(cipherName, "DES")) isDes = PR_TRUE; 1.132 + 1.133 + if (cp) { 1.134 + *cp = PORT_Strdup(cipherName); 1.135 + } 1.136 + } 1.137 + 1.138 + if (kp0) { 1.139 + *kp0 = ss->sec.keyBits; 1.140 + if (isDes) *kp0 = (*kp0 * 7) / 8; 1.141 + } 1.142 + if (kp1) { 1.143 + *kp1 = ss->sec.secretKeyBits; 1.144 + if (isDes) *kp1 = (*kp1 * 7) / 8; 1.145 + } 1.146 + if (op) { 1.147 + if (ss->sec.keyBits == 0) { 1.148 + *op = SSL_SECURITY_STATUS_OFF; 1.149 + } else if (ss->sec.secretKeyBits < 90) { 1.150 + *op = SSL_SECURITY_STATUS_ON_LOW; 1.151 + 1.152 + } else { 1.153 + *op = SSL_SECURITY_STATUS_ON_HIGH; 1.154 + } 1.155 + } 1.156 + 1.157 + if (ip || sp) { 1.158 + CERTCertificate *cert; 1.159 + 1.160 + cert = ss->sec.peerCert; 1.161 + if (cert) { 1.162 + if (ip) { 1.163 + *ip = CERT_NameToAscii(&cert->issuer); 1.164 + } 1.165 + if (sp) { 1.166 + *sp = CERT_NameToAscii(&cert->subject); 1.167 + } 1.168 + } else { 1.169 + if (ip) { 1.170 + *ip = PORT_Strdup("no certificate"); 1.171 + } 1.172 + if (sp) { 1.173 + *sp = PORT_Strdup("no certificate"); 1.174 + } 1.175 + } 1.176 + } 1.177 + } 1.178 + 1.179 + return SECSuccess; 1.180 +} 1.181 + 1.182 +/************************************************************************/ 1.183 + 1.184 +/* NEED LOCKS IN HERE. */ 1.185 +SECStatus 1.186 +SSL_AuthCertificateHook(PRFileDesc *s, SSLAuthCertificate func, void *arg) 1.187 +{ 1.188 + sslSocket *ss; 1.189 + 1.190 + ss = ssl_FindSocket(s); 1.191 + if (!ss) { 1.192 + SSL_DBG(("%d: SSL[%d]: bad socket in AuthCertificateHook", 1.193 + SSL_GETPID(), s)); 1.194 + return SECFailure; 1.195 + } 1.196 + 1.197 + ss->authCertificate = func; 1.198 + ss->authCertificateArg = arg; 1.199 + 1.200 + return SECSuccess; 1.201 +} 1.202 + 1.203 +/* NEED LOCKS IN HERE. */ 1.204 +SECStatus 1.205 +SSL_GetClientAuthDataHook(PRFileDesc *s, SSLGetClientAuthData func, 1.206 + void *arg) 1.207 +{ 1.208 + sslSocket *ss; 1.209 + 1.210 + ss = ssl_FindSocket(s); 1.211 + if (!ss) { 1.212 + SSL_DBG(("%d: SSL[%d]: bad socket in GetClientAuthDataHook", 1.213 + SSL_GETPID(), s)); 1.214 + return SECFailure; 1.215 + } 1.216 + 1.217 + ss->getClientAuthData = func; 1.218 + ss->getClientAuthDataArg = arg; 1.219 + return SECSuccess; 1.220 +} 1.221 + 1.222 +/* NEED LOCKS IN HERE. */ 1.223 +SECStatus 1.224 +SSL_SetPKCS11PinArg(PRFileDesc *s, void *arg) 1.225 +{ 1.226 + sslSocket *ss; 1.227 + 1.228 + ss = ssl_FindSocket(s); 1.229 + if (!ss) { 1.230 + SSL_DBG(("%d: SSL[%d]: bad socket in GetClientAuthDataHook", 1.231 + SSL_GETPID(), s)); 1.232 + return SECFailure; 1.233 + } 1.234 + 1.235 + ss->pkcs11PinArg = arg; 1.236 + return SECSuccess; 1.237 +} 1.238 + 1.239 + 1.240 +/* This is the "default" authCert callback function. It is called when a 1.241 + * certificate message is received from the peer and the local application 1.242 + * has not registered an authCert callback function. 1.243 + */ 1.244 +SECStatus 1.245 +SSL_AuthCertificate(void *arg, PRFileDesc *fd, PRBool checkSig, PRBool isServer) 1.246 +{ 1.247 + SECStatus rv; 1.248 + CERTCertDBHandle * handle; 1.249 + sslSocket * ss; 1.250 + SECCertUsage certUsage; 1.251 + const char * hostname = NULL; 1.252 + PRTime now = PR_Now(); 1.253 + SECItemArray * certStatusArray; 1.254 + 1.255 + ss = ssl_FindSocket(fd); 1.256 + PORT_Assert(ss != NULL); 1.257 + if (!ss) { 1.258 + return SECFailure; 1.259 + } 1.260 + 1.261 + handle = (CERTCertDBHandle *)arg; 1.262 + certStatusArray = &ss->sec.ci.sid->peerCertStatus; 1.263 + 1.264 + if (certStatusArray->len) { 1.265 + PORT_SetError(0); 1.266 + if (CERT_CacheOCSPResponseFromSideChannel(handle, ss->sec.peerCert, now, 1.267 + &certStatusArray->items[0], 1.268 + ss->pkcs11PinArg) 1.269 + != SECSuccess) { 1.270 + PRErrorCode error = PR_GetError(); 1.271 + PORT_Assert(error != 0); 1.272 + } 1.273 + } 1.274 + 1.275 + /* this may seem backwards, but isn't. */ 1.276 + certUsage = isServer ? certUsageSSLClient : certUsageSSLServer; 1.277 + 1.278 + rv = CERT_VerifyCert(handle, ss->sec.peerCert, checkSig, certUsage, 1.279 + now, ss->pkcs11PinArg, NULL); 1.280 + 1.281 + if ( rv != SECSuccess || isServer ) 1.282 + return rv; 1.283 + 1.284 + /* cert is OK. This is the client side of an SSL connection. 1.285 + * Now check the name field in the cert against the desired hostname. 1.286 + * NB: This is our only defense against Man-In-The-Middle (MITM) attacks! 1.287 + */ 1.288 + hostname = ss->url; 1.289 + if (hostname && hostname[0]) 1.290 + rv = CERT_VerifyCertName(ss->sec.peerCert, hostname); 1.291 + else 1.292 + rv = SECFailure; 1.293 + if (rv != SECSuccess) 1.294 + PORT_SetError(SSL_ERROR_BAD_CERT_DOMAIN); 1.295 + 1.296 + return rv; 1.297 +}