OLD | NEW |
1 /* This Source Code Form is subject to the terms of the Mozilla Public | 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 | 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/. */ | 3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
4 #include "cert.h" | 4 #include "cert.h" |
5 #include "secitem.h" | 5 #include "secitem.h" |
6 #include "ssl.h" | 6 #include "ssl.h" |
7 #include "sslimpl.h" | 7 #include "sslimpl.h" |
8 #include "sslproto.h" | 8 #include "sslproto.h" |
9 #include "pk11func.h" | 9 #include "pk11func.h" |
10 #include "ocsp.h" | 10 #include "ocsp.h" |
11 | 11 |
12 /* NEED LOCKS IN HERE. */ | 12 /* NEED LOCKS IN HERE. */ |
13 CERTCertificate * | 13 CERTCertificate * |
14 SSL_PeerCertificate(PRFileDesc *fd) | 14 SSL_PeerCertificate(PRFileDesc *fd) |
15 { | 15 { |
16 sslSocket *ss; | 16 sslSocket *ss; |
17 | 17 |
18 ss = ssl_FindSocket(fd); | 18 ss = ssl_FindSocket(fd); |
19 if (!ss) { | 19 if (!ss) { |
20 » SSL_DBG(("%d: SSL[%d]: bad socket in PeerCertificate", | 20 SSL_DBG(("%d: SSL[%d]: bad socket in PeerCertificate", |
21 » » SSL_GETPID(), fd)); | 21 SSL_GETPID(), fd)); |
22 » return 0; | 22 return 0; |
23 } | 23 } |
24 if (ss->opt.useSecurity && ss->sec.peerCert) { | 24 if (ss->opt.useSecurity && ss->sec.peerCert) { |
25 » return CERT_DupCertificate(ss->sec.peerCert); | 25 return CERT_DupCertificate(ss->sec.peerCert); |
26 } | 26 } |
27 return 0; | 27 return 0; |
28 } | 28 } |
29 | 29 |
30 /* NEED LOCKS IN HERE. */ | 30 /* NEED LOCKS IN HERE. */ |
31 CERTCertList * | 31 CERTCertList * |
32 SSL_PeerCertificateChain(PRFileDesc *fd) | 32 SSL_PeerCertificateChain(PRFileDesc *fd) |
33 { | 33 { |
34 sslSocket *ss; | 34 sslSocket *ss; |
35 CERTCertList *chain = NULL; | 35 CERTCertList *chain = NULL; |
36 CERTCertificate *cert; | 36 CERTCertificate *cert; |
37 ssl3CertNode *cur; | 37 ssl3CertNode *cur; |
38 | 38 |
39 ss = ssl_FindSocket(fd); | 39 ss = ssl_FindSocket(fd); |
40 if (!ss) { | 40 if (!ss) { |
41 » SSL_DBG(("%d: SSL[%d]: bad socket in PeerCertificateChain", | 41 SSL_DBG(("%d: SSL[%d]: bad socket in PeerCertificateChain", |
42 » » SSL_GETPID(), fd)); | 42 SSL_GETPID(), fd)); |
43 » return NULL; | 43 return NULL; |
44 } | 44 } |
45 if (!ss->opt.useSecurity || !ss->sec.peerCert) { | 45 if (!ss->opt.useSecurity || !ss->sec.peerCert) { |
46 » PORT_SetError(SSL_ERROR_NO_CERTIFICATE); | 46 PORT_SetError(SSL_ERROR_NO_CERTIFICATE); |
47 » return NULL; | 47 return NULL; |
48 } | 48 } |
49 chain = CERT_NewCertList(); | 49 chain = CERT_NewCertList(); |
50 if (!chain) { | 50 if (!chain) { |
51 » return NULL; | 51 return NULL; |
52 } | 52 } |
53 cert = CERT_DupCertificate(ss->sec.peerCert); | 53 cert = CERT_DupCertificate(ss->sec.peerCert); |
54 if (CERT_AddCertToListTail(chain, cert) != SECSuccess) { | 54 if (CERT_AddCertToListTail(chain, cert) != SECSuccess) { |
55 » goto loser; | 55 goto loser; |
56 } | 56 } |
57 for (cur = ss->ssl3.peerCertChain; cur; cur = cur->next) { | 57 for (cur = ss->ssl3.peerCertChain; cur; cur = cur->next) { |
58 » cert = CERT_DupCertificate(cur->cert); | 58 cert = CERT_DupCertificate(cur->cert); |
59 » if (CERT_AddCertToListTail(chain, cert) != SECSuccess) { | 59 if (CERT_AddCertToListTail(chain, cert) != SECSuccess) { |
60 » goto loser; | 60 goto loser; |
61 » } | 61 } |
62 } | 62 } |
63 return chain; | 63 return chain; |
64 | 64 |
65 loser: | 65 loser: |
66 CERT_DestroyCertList(chain); | 66 CERT_DestroyCertList(chain); |
67 return NULL; | 67 return NULL; |
68 } | 68 } |
69 | 69 |
70 /* NEED LOCKS IN HERE. */ | 70 /* NEED LOCKS IN HERE. */ |
71 CERTCertificate * | 71 CERTCertificate * |
72 SSL_LocalCertificate(PRFileDesc *fd) | 72 SSL_LocalCertificate(PRFileDesc *fd) |
73 { | 73 { |
74 sslSocket *ss; | 74 sslSocket *ss; |
75 | 75 |
76 ss = ssl_FindSocket(fd); | 76 ss = ssl_FindSocket(fd); |
77 if (!ss) { | 77 if (!ss) { |
78 » SSL_DBG(("%d: SSL[%d]: bad socket in PeerCertificate", | 78 SSL_DBG(("%d: SSL[%d]: bad socket in PeerCertificate", |
79 » » SSL_GETPID(), fd)); | 79 SSL_GETPID(), fd)); |
80 » return NULL; | 80 return NULL; |
81 } | 81 } |
82 if (ss->opt.useSecurity) { | 82 if (ss->opt.useSecurity) { |
83 » if (ss->sec.localCert) { | 83 if (ss->sec.localCert) { |
84 » return CERT_DupCertificate(ss->sec.localCert); | 84 return CERT_DupCertificate(ss->sec.localCert); |
85 » } | 85 } |
86 » if (ss->sec.ci.sid && ss->sec.ci.sid->localCert) { | 86 if (ss->sec.ci.sid && ss->sec.ci.sid->localCert) { |
87 » return CERT_DupCertificate(ss->sec.ci.sid->localCert); | 87 return CERT_DupCertificate(ss->sec.ci.sid->localCert); |
88 » } | 88 } |
89 } | 89 } |
90 return NULL; | 90 return NULL; |
91 } | 91 } |
92 | 92 |
93 | |
94 | |
95 /* NEED LOCKS IN HERE. */ | 93 /* NEED LOCKS IN HERE. */ |
96 SECStatus | 94 SECStatus |
97 SSL_SecurityStatus(PRFileDesc *fd, int *op, char **cp, int *kp0, int *kp1, | 95 SSL_SecurityStatus(PRFileDesc *fd, int *op, char **cp, int *kp0, int *kp1, |
98 » » char **ip, char **sp) | 96 char **ip, char **sp) |
99 { | 97 { |
100 sslSocket *ss; | 98 sslSocket *ss; |
101 const char *cipherName; | 99 const char *cipherName; |
102 PRBool isDes = PR_FALSE; | 100 PRBool isDes = PR_FALSE; |
103 | 101 |
104 ss = ssl_FindSocket(fd); | 102 ss = ssl_FindSocket(fd); |
105 if (!ss) { | 103 if (!ss) { |
106 » SSL_DBG(("%d: SSL[%d]: bad socket in SecurityStatus", | 104 SSL_DBG(("%d: SSL[%d]: bad socket in SecurityStatus", |
107 » » SSL_GETPID(), fd)); | 105 SSL_GETPID(), fd)); |
108 » return SECFailure; | 106 return SECFailure; |
109 } | 107 } |
110 | 108 |
111 if (cp) *cp = 0; | 109 if (cp) |
112 if (kp0) *kp0 = 0; | 110 *cp = 0; |
113 if (kp1) *kp1 = 0; | 111 if (kp0) |
114 if (ip) *ip = 0; | 112 *kp0 = 0; |
115 if (sp) *sp = 0; | 113 if (kp1) |
| 114 *kp1 = 0; |
| 115 if (ip) |
| 116 *ip = 0; |
| 117 if (sp) |
| 118 *sp = 0; |
116 if (op) { | 119 if (op) { |
117 » *op = SSL_SECURITY_STATUS_OFF; | 120 *op = SSL_SECURITY_STATUS_OFF; |
118 } | 121 } |
119 | 122 |
120 if (ss->opt.useSecurity && ss->enoughFirstHsDone) { | 123 if (ss->opt.useSecurity && ss->enoughFirstHsDone) { |
121 » if (ss->version < SSL_LIBRARY_VERSION_3_0) { | 124 if (ss->version < SSL_LIBRARY_VERSION_3_0) { |
122 » cipherName = ssl_cipherName[ss->sec.cipherType]; | 125 cipherName = ssl_cipherName[ss->sec.cipherType]; |
123 » } else { | 126 } else { |
124 » cipherName = ssl3_cipherName[ss->sec.cipherType]; | 127 cipherName = ssl3_cipherName[ss->sec.cipherType]; |
125 » } | 128 } |
126 » PORT_Assert(cipherName); | 129 PORT_Assert(cipherName); |
127 » if (cipherName) { | 130 if (cipherName) { |
128 if (PORT_Strstr(cipherName, "DES")) isDes = PR_TRUE; | 131 if (PORT_Strstr(cipherName, "DES")) |
| 132 isDes = PR_TRUE; |
129 | 133 |
130 if (cp) { | 134 if (cp) { |
131 *cp = PORT_Strdup(cipherName); | 135 *cp = PORT_Strdup(cipherName); |
132 } | 136 } |
133 } | 137 } |
134 | 138 |
135 » if (kp0) { | 139 if (kp0) { |
136 » *kp0 = ss->sec.keyBits; | 140 *kp0 = ss->sec.keyBits; |
137 » if (isDes) *kp0 = (*kp0 * 7) / 8; | 141 if (isDes) |
138 » } | 142 *kp0 = (*kp0 * 7) / 8; |
139 » if (kp1) { | 143 } |
140 » *kp1 = ss->sec.secretKeyBits; | 144 if (kp1) { |
141 » if (isDes) *kp1 = (*kp1 * 7) / 8; | 145 *kp1 = ss->sec.secretKeyBits; |
142 » } | 146 if (isDes) |
143 » if (op) { | 147 *kp1 = (*kp1 * 7) / 8; |
144 » if (ss->sec.keyBits == 0) { | 148 } |
145 » » *op = SSL_SECURITY_STATUS_OFF; | 149 if (op) { |
146 » } else if (ss->sec.secretKeyBits < 90) { | 150 if (ss->sec.keyBits == 0) { |
147 » » *op = SSL_SECURITY_STATUS_ON_LOW; | 151 *op = SSL_SECURITY_STATUS_OFF; |
| 152 } else if (ss->sec.secretKeyBits < 90) { |
| 153 *op = SSL_SECURITY_STATUS_ON_LOW; |
| 154 } else { |
| 155 *op = SSL_SECURITY_STATUS_ON_HIGH; |
| 156 } |
| 157 } |
148 | 158 |
149 » } else { | 159 if (ip || sp) { |
150 » » *op = SSL_SECURITY_STATUS_ON_HIGH; | 160 CERTCertificate *cert; |
151 » } | |
152 » } | |
153 | 161 |
154 » if (ip || sp) { | 162 cert = ss->sec.peerCert; |
155 » CERTCertificate *cert; | 163 if (cert) { |
156 | 164 if (ip) { |
157 » cert = ss->sec.peerCert; | 165 *ip = CERT_NameToAscii(&cert->issuer); |
158 » if (cert) { | 166 } |
159 » » if (ip) { | 167 if (sp) { |
160 » » *ip = CERT_NameToAscii(&cert->issuer); | 168 *sp = CERT_NameToAscii(&cert->subject); |
161 » » } | 169 } |
162 » » if (sp) { | 170 } else { |
163 » » *sp = CERT_NameToAscii(&cert->subject); | 171 if (ip) { |
164 » » } | 172 *ip = PORT_Strdup("no certificate"); |
165 » } else { | 173 } |
166 » » if (ip) { | 174 if (sp) { |
167 » » *ip = PORT_Strdup("no certificate"); | 175 *sp = PORT_Strdup("no certificate"); |
168 » » } | 176 } |
169 » » if (sp) { | 177 } |
170 » » *sp = PORT_Strdup("no certificate"); | 178 } |
171 » » } | |
172 » } | |
173 » } | |
174 } | 179 } |
175 | 180 |
176 return SECSuccess; | 181 return SECSuccess; |
177 } | 182 } |
178 | 183 |
179 /************************************************************************/ | 184 /************************************************************************/ |
180 | 185 |
181 /* NEED LOCKS IN HERE. */ | 186 /* NEED LOCKS IN HERE. */ |
182 SECStatus | 187 SECStatus |
183 SSL_AuthCertificateHook(PRFileDesc *s, SSLAuthCertificate func, void *arg) | 188 SSL_AuthCertificateHook(PRFileDesc *s, SSLAuthCertificate func, void *arg) |
184 { | 189 { |
185 sslSocket *ss; | 190 sslSocket *ss; |
186 | 191 |
187 ss = ssl_FindSocket(s); | 192 ss = ssl_FindSocket(s); |
188 if (!ss) { | 193 if (!ss) { |
189 » SSL_DBG(("%d: SSL[%d]: bad socket in AuthCertificateHook", | 194 SSL_DBG(("%d: SSL[%d]: bad socket in AuthCertificateHook", |
190 » » SSL_GETPID(), s)); | 195 SSL_GETPID(), s)); |
191 » return SECFailure; | 196 return SECFailure; |
192 } | 197 } |
193 | 198 |
194 ss->authCertificate = func; | 199 ss->authCertificate = func; |
195 ss->authCertificateArg = arg; | 200 ss->authCertificateArg = arg; |
196 | 201 |
197 return SECSuccess; | 202 return SECSuccess; |
198 } | 203 } |
199 | 204 |
200 /* NEED LOCKS IN HERE. */ | 205 /* NEED LOCKS IN HERE. */ |
201 SECStatus | 206 SECStatus |
202 SSL_GetClientAuthDataHook(PRFileDesc *s, SSLGetClientAuthData func, | 207 SSL_GetClientAuthDataHook(PRFileDesc *s, SSLGetClientAuthData func, |
203 » » » void *arg) | 208 void *arg) |
204 { | 209 { |
205 sslSocket *ss; | 210 sslSocket *ss; |
206 | 211 |
207 ss = ssl_FindSocket(s); | 212 ss = ssl_FindSocket(s); |
208 if (!ss) { | 213 if (!ss) { |
209 » SSL_DBG(("%d: SSL[%d]: bad socket in GetClientAuthDataHook", | 214 SSL_DBG(("%d: SSL[%d]: bad socket in GetClientAuthDataHook", |
210 » » SSL_GETPID(), s)); | 215 SSL_GETPID(), s)); |
211 » return SECFailure; | 216 return SECFailure; |
212 } | 217 } |
213 | 218 |
214 ss->getClientAuthData = func; | 219 ss->getClientAuthData = func; |
215 ss->getClientAuthDataArg = arg; | 220 ss->getClientAuthDataArg = arg; |
216 return SECSuccess; | 221 return SECSuccess; |
217 } | 222 } |
218 | 223 |
219 SECStatus | 224 SECStatus |
220 SSL_SetClientChannelIDCallback(PRFileDesc *fd, | 225 SSL_SetClientChannelIDCallback(PRFileDesc *fd, |
221 » » » SSLClientChannelIDCallback callback, | 226 SSLClientChannelIDCallback callback, |
222 » » » void *arg) { | 227 void *arg) |
| 228 { |
223 sslSocket *ss = ssl_FindSocket(fd); | 229 sslSocket *ss = ssl_FindSocket(fd); |
224 | 230 |
225 if (!ss) { | 231 if (!ss) { |
226 » SSL_DBG(("%d: SSL[%d]: bad socket in SSL_SetClientChannelIDCallback", | 232 SSL_DBG(("%d: SSL[%d]: bad socket in SSL_SetClientChannelIDCallback", |
227 » » SSL_GETPID(), fd)); | 233 SSL_GETPID(), fd)); |
228 » return SECFailure; | 234 return SECFailure; |
229 } | 235 } |
230 | 236 |
231 ss->getChannelID = callback; | 237 ss->getChannelID = callback; |
232 ss->getChannelIDArg = arg; | 238 ss->getChannelIDArg = arg; |
233 | 239 |
234 return SECSuccess; | 240 return SECSuccess; |
235 } | 241 } |
236 | 242 |
237 #ifdef NSS_PLATFORM_CLIENT_AUTH | |
238 /* NEED LOCKS IN HERE. */ | 243 /* NEED LOCKS IN HERE. */ |
239 SECStatus | 244 SECStatus |
240 SSL_GetPlatformClientAuthDataHook(PRFileDesc *s, | |
241 SSLGetPlatformClientAuthData func, | |
242 void *arg) | |
243 { | |
244 sslSocket *ss; | |
245 | |
246 ss = ssl_FindSocket(s); | |
247 if (!ss) { | |
248 » SSL_DBG(("%d: SSL[%d]: bad socket in GetPlatformClientAuthDataHook", | |
249 » » SSL_GETPID(), s)); | |
250 » return SECFailure; | |
251 } | |
252 | |
253 ss->getPlatformClientAuthData = func; | |
254 ss->getPlatformClientAuthDataArg = arg; | |
255 return SECSuccess; | |
256 } | |
257 #endif /* NSS_PLATFORM_CLIENT_AUTH */ | |
258 | |
259 /* NEED LOCKS IN HERE. */ | |
260 SECStatus | |
261 SSL_SetPKCS11PinArg(PRFileDesc *s, void *arg) | 245 SSL_SetPKCS11PinArg(PRFileDesc *s, void *arg) |
262 { | 246 { |
263 sslSocket *ss; | 247 sslSocket *ss; |
264 | 248 |
265 ss = ssl_FindSocket(s); | 249 ss = ssl_FindSocket(s); |
266 if (!ss) { | 250 if (!ss) { |
267 » SSL_DBG(("%d: SSL[%d]: bad socket in GetClientAuthDataHook", | 251 SSL_DBG(("%d: SSL[%d]: bad socket in GetClientAuthDataHook", |
268 » » SSL_GETPID(), s)); | 252 SSL_GETPID(), s)); |
269 » return SECFailure; | 253 return SECFailure; |
270 } | 254 } |
271 | 255 |
272 ss->pkcs11PinArg = arg; | 256 ss->pkcs11PinArg = arg; |
273 return SECSuccess; | 257 return SECSuccess; |
274 } | 258 } |
275 | 259 |
276 | 260 /* This is the "default" authCert callback function. It is called when a |
277 /* This is the "default" authCert callback function. It is called when a | |
278 * certificate message is received from the peer and the local application | 261 * certificate message is received from the peer and the local application |
279 * has not registered an authCert callback function. | 262 * has not registered an authCert callback function. |
280 */ | 263 */ |
281 SECStatus | 264 SECStatus |
282 SSL_AuthCertificate(void *arg, PRFileDesc *fd, PRBool checkSig, PRBool isServer) | 265 SSL_AuthCertificate(void *arg, PRFileDesc *fd, PRBool checkSig, PRBool isServer) |
283 { | 266 { |
284 SECStatus rv; | 267 SECStatus rv; |
285 CERTCertDBHandle * handle; | 268 CERTCertDBHandle *handle; |
286 sslSocket * ss; | 269 sslSocket *ss; |
287 SECCertUsage certUsage; | 270 SECCertUsage certUsage; |
288 const char * hostname = NULL; | 271 const char *hostname = NULL; |
289 PRTime now = PR_Now(); | 272 PRTime now = PR_Now(); |
290 SECItemArray * certStatusArray; | 273 SECItemArray *certStatusArray; |
291 | 274 |
292 ss = ssl_FindSocket(fd); | 275 ss = ssl_FindSocket(fd); |
293 PORT_Assert(ss != NULL); | 276 PORT_Assert(ss != NULL); |
294 if (!ss) { | 277 if (!ss) { |
295 » return SECFailure; | 278 return SECFailure; |
296 } | 279 } |
297 | 280 |
298 handle = (CERTCertDBHandle *)arg; | 281 handle = (CERTCertDBHandle *)arg; |
299 certStatusArray = &ss->sec.ci.sid->peerCertStatus; | 282 certStatusArray = &ss->sec.ci.sid->peerCertStatus; |
300 | 283 |
301 if (certStatusArray->len) { | 284 if (certStatusArray->len) { |
302 » PORT_SetError(0); | 285 PORT_SetError(0); |
303 » if (CERT_CacheOCSPResponseFromSideChannel(handle, ss->sec.peerCert, now, | 286 if (CERT_CacheOCSPResponseFromSideChannel(handle, ss->sec.peerCert, now, |
304 » » » » » » &certStatusArray->items[0], | 287 &certStatusArray->items[0], |
305 » » » » » » ss->pkcs11PinArg) | 288 ss->pkcs11PinArg) != |
306 » » != SECSuccess) { | 289 SECSuccess) { |
307 » PORT_Assert(PR_GetError() != 0); | 290 PORT_Assert(PR_GetError() != 0); |
308 » } | 291 } |
309 } | 292 } |
310 | 293 |
311 /* this may seem backwards, but isn't. */ | 294 /* this may seem backwards, but isn't. */ |
312 certUsage = isServer ? certUsageSSLClient : certUsageSSLServer; | 295 certUsage = isServer ? certUsageSSLClient : certUsageSSLServer; |
313 | 296 |
314 rv = CERT_VerifyCert(handle, ss->sec.peerCert, checkSig, certUsage, | 297 rv = CERT_VerifyCert(handle, ss->sec.peerCert, checkSig, certUsage, |
315 » » » now, ss->pkcs11PinArg, NULL); | 298 now, ss->pkcs11PinArg, NULL); |
316 | 299 |
317 if ( rv != SECSuccess || isServer ) | 300 if (rv != SECSuccess || isServer) |
318 » return rv; | 301 return rv; |
319 | 302 |
320 /* cert is OK. This is the client side of an SSL connection. | 303 /* cert is OK. This is the client side of an SSL connection. |
321 * Now check the name field in the cert against the desired hostname. | 304 * Now check the name field in the cert against the desired hostname. |
322 * NB: This is our only defense against Man-In-The-Middle (MITM) attacks! | 305 * NB: This is our only defense against Man-In-The-Middle (MITM) attacks! |
323 */ | 306 */ |
324 hostname = ss->url; | 307 hostname = ss->url; |
325 if (hostname && hostname[0]) | 308 if (hostname && hostname[0]) |
326 » rv = CERT_VerifyCertName(ss->sec.peerCert, hostname); | 309 rv = CERT_VerifyCertName(ss->sec.peerCert, hostname); |
327 else | 310 else |
328 » rv = SECFailure; | 311 rv = SECFailure; |
329 if (rv != SECSuccess) | 312 if (rv != SECSuccess) |
330 » PORT_SetError(SSL_ERROR_BAD_CERT_DOMAIN); | 313 PORT_SetError(SSL_ERROR_BAD_CERT_DOMAIN); |
331 | 314 |
332 return rv; | 315 return rv; |
333 } | 316 } |
OLD | NEW |