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 $ */
12 /* NEED LOCKS IN HERE. */
14 SSL_PeerCertificate(PRFileDesc
*fd
)
18 ss
= ssl_FindSocket(fd
);
20 SSL_DBG(("%d: SSL[%d]: bad socket in PeerCertificate",
24 if (ss
->opt
.useSecurity
&& ss
->sec
.peerCert
) {
25 return CERT_DupCertificate(ss
->sec
.peerCert
);
30 /* NEED LOCKS IN HERE. */
32 SSL_PeerCertificateChain(PRFileDesc
*fd
, CERTCertificate
**certs
,
33 unsigned int *numCerts
, unsigned int maxNumCerts
)
38 ss
= ssl_FindSocket(fd
);
40 SSL_DBG(("%d: SSL[%d]: bad socket in PeerCertificateChain",
44 if (!ss
->opt
.useSecurity
)
47 if (ss
->sec
.peerCert
== NULL
) {
52 *numCerts
= 1; /* for the leaf certificate */
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
);
65 /* NEED LOCKS IN HERE. */
67 SSL_LocalCertificate(PRFileDesc
*fd
)
71 ss
= ssl_FindSocket(fd
);
73 SSL_DBG(("%d: SSL[%d]: bad socket in PeerCertificate",
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
);
90 /* NEED LOCKS IN HERE. */
92 SSL_SecurityStatus(PRFileDesc
*fd
, int *op
, char **cp
, int *kp0
, int *kp1
,
96 const char *cipherName
;
97 PRBool isDes
= PR_FALSE
;
98 PRBool enoughFirstHsDone
= PR_FALSE
;
100 ss
= ssl_FindSocket(fd
);
102 SSL_DBG(("%d: SSL[%d]: bad socket in SecurityStatus",
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
];
127 cipherName
= ssl3_cipherName
[ss
->sec
.cipherType
];
129 PORT_Assert(cipherName
);
131 if (PORT_Strstr(cipherName
, "DES")) isDes
= PR_TRUE
;
134 *cp
= PORT_Strdup(cipherName
);
139 *kp0
= ss
->sec
.keyBits
;
140 if (isDes
) *kp0
= (*kp0
* 7) / 8;
143 *kp1
= ss
->sec
.secretKeyBits
;
144 if (isDes
) *kp1
= (*kp1
* 7) / 8;
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
;
153 *op
= SSL_SECURITY_STATUS_ON_HIGH
;
158 CERTCertificate
*cert
;
160 cert
= ss
->sec
.peerCert
;
163 *ip
= CERT_NameToAscii(&cert
->issuer
);
166 *sp
= CERT_NameToAscii(&cert
->subject
);
170 *ip
= PORT_Strdup("no certificate");
173 *sp
= PORT_Strdup("no certificate");
182 /************************************************************************/
184 /* NEED LOCKS IN HERE. */
186 SSL_AuthCertificateHook(PRFileDesc
*s
, SSLAuthCertificate func
, void *arg
)
190 ss
= ssl_FindSocket(s
);
192 SSL_DBG(("%d: SSL[%d]: bad socket in AuthCertificateHook",
197 ss
->authCertificate
= func
;
198 ss
->authCertificateArg
= arg
;
203 /* NEED LOCKS IN HERE. */
205 SSL_GetClientAuthDataHook(PRFileDesc
*s
, SSLGetClientAuthData func
,
210 ss
= ssl_FindSocket(s
);
212 SSL_DBG(("%d: SSL[%d]: bad socket in GetClientAuthDataHook",
217 ss
->getClientAuthData
= func
;
218 ss
->getClientAuthDataArg
= arg
;
223 SSL_SetClientChannelIDCallback(PRFileDesc
*fd
,
224 SSLClientChannelIDCallback callback
,
226 sslSocket
*ss
= ssl_FindSocket(fd
);
229 SSL_DBG(("%d: SSL[%d]: bad socket in SSL_SetClientChannelIDCallback",
234 ss
->getChannelID
= callback
;
235 ss
->getChannelIDArg
= arg
;
240 #ifdef NSS_PLATFORM_CLIENT_AUTH
241 /* NEED LOCKS IN HERE. */
243 SSL_GetPlatformClientAuthDataHook(PRFileDesc
*s
,
244 SSLGetPlatformClientAuthData func
,
249 ss
= ssl_FindSocket(s
);
251 SSL_DBG(("%d: SSL[%d]: bad socket in GetPlatformClientAuthDataHook",
256 ss
->getPlatformClientAuthData
= func
;
257 ss
->getPlatformClientAuthDataArg
= arg
;
260 #endif /* NSS_PLATFORM_CLIENT_AUTH */
262 /* NEED LOCKS IN HERE. */
264 SSL_SetPKCS11PinArg(PRFileDesc
*s
, void *arg
)
268 ss
= ssl_FindSocket(s
);
270 SSL_DBG(("%d: SSL[%d]: bad socket in GetClientAuthDataHook",
275 ss
->pkcs11PinArg
= arg
;
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.
285 SSL_AuthCertificate(void *arg
, PRFileDesc
*fd
, PRBool checkSig
, PRBool isServer
)
288 CERTCertDBHandle
* handle
;
290 SECCertUsage certUsage
;
291 const char * hostname
= NULL
;
293 ss
= ssl_FindSocket(fd
);
294 PORT_Assert(ss
!= NULL
);
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
,
307 if ( rv
!= SECSuccess
|| isServer
)
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!
315 if (hostname
&& hostname
[0])
316 rv
= CERT_VerifyCertName(ss
->sec
.peerCert
, hostname
);
319 if (rv
!= SECSuccess
)
320 PORT_SetError(SSL_ERROR_BAD_CERT_DOMAIN
);