libpurple/plugins/ssl/ssl-nss.c

branch
soc.2013.gobjectification.plugins
changeset 36972
dfe5c47d56a9
parent 36896
3865997e388b
parent 35136
f017a2e85832
child 37074
1e7b4b3741a0
equal deleted inserted replaced
36971:602023a35d92 36972:dfe5c47d56a9
153 _identity = PR_GetUniqueIdentity("Purple"); 153 _identity = PR_GetUniqueIdentity("Purple");
154 _nss_methods = PR_GetDefaultIOMethods(); 154 _nss_methods = PR_GetDefaultIOMethods();
155 } 155 }
156 156
157 static SECStatus 157 static SECStatus
158 ssl_auth_cert(void *arg, PRFileDesc *socket, PRBool checksig, 158 ssl_auth_cert(void *arg, PRFileDesc *socket, PRBool checksig, PRBool is_server)
159 PRBool is_server) 159 {
160 { 160 /* We just skip cert verification here, and will verify the whole chain
161 * in ssl_nss_handshake_cb, after the handshake is complete.
162 *
163 * The problem is, purple_certificate_verify is asynchronous and
164 * ssl_auth_cert should return the result synchronously (it may ask the
165 * user, if an unknown certificate should be trusted or not).
166 *
167 * Ideally, SSL_AuthCertificateHook/ssl_auth_cert should decide
168 * immediately, if the certificate chain is already trusted and possibly
169 * SSL_BadCertHook to deal with unknown certificates.
170 *
171 * Current implementation may not be ideal, but is no less secure in
172 * terms of MITM attack.
173 */
161 return SECSuccess; 174 return SECSuccess;
162 175 }
163 #if 0
164 CERTCertificate *cert;
165 void *pinArg;
166 SECStatus status;
167
168 cert = SSL_PeerCertificate(socket);
169 pinArg = SSL_RevealPinArg(socket);
170
171 status = CERT_VerifyCertNow((CERTCertDBHandle *)arg, cert, checksig,
172 certUsageSSLClient, pinArg);
173
174 if (status != SECSuccess) {
175 purple_debug_error("nss", "CERT_VerifyCertNow failed\n");
176 CERT_DestroyCertificate(cert);
177 return status;
178 }
179
180 CERT_DestroyCertificate(cert);
181 return SECSuccess;
182 #endif
183 }
184
185 #if 0
186 static SECStatus
187 ssl_bad_cert(void *arg, PRFileDesc *socket)
188 {
189 SECStatus status = SECFailure;
190 PRErrorCode err;
191
192 if (arg == NULL)
193 return status;
194
195 *(PRErrorCode *)arg = err = PORT_GetError();
196
197 switch (err)
198 {
199 case SEC_ERROR_INVALID_AVA:
200 case SEC_ERROR_INVALID_TIME:
201 case SEC_ERROR_BAD_SIGNATURE:
202 case SEC_ERROR_EXPIRED_CERTIFICATE:
203 case SEC_ERROR_UNKNOWN_ISSUER:
204 case SEC_ERROR_UNTRUSTED_CERT:
205 case SEC_ERROR_CERT_VALID:
206 case SEC_ERROR_EXPIRED_ISSUER_CERTIFICATE:
207 case SEC_ERROR_CRL_EXPIRED:
208 case SEC_ERROR_CRL_BAD_SIGNATURE:
209 case SEC_ERROR_EXTENSION_VALUE_INVALID:
210 case SEC_ERROR_CA_CERT_INVALID:
211 case SEC_ERROR_CERT_USAGES_INVALID:
212 case SEC_ERROR_UNKNOWN_CRITICAL_EXTENSION:
213 status = SECSuccess;
214 break;
215
216 default:
217 status = SECFailure;
218 break;
219 }
220
221 purple_debug_error("nss", "Bad certificate: %d\n", err);
222
223 return status;
224 }
225 #endif
226 176
227 static gboolean 177 static gboolean
228 ssl_nss_init(void) 178 ssl_nss_init(void)
229 { 179 {
230 return TRUE; 180 return TRUE;
360 gsc); 310 gsc);
361 311
362 purple_certificate_destroy_list(peers); 312 purple_certificate_destroy_list(peers);
363 } else { 313 } else {
364 /* Otherwise, just call the "connection complete" 314 /* Otherwise, just call the "connection complete"
365 callback */ 315 * callback. The verification was already done with
316 * SSL_AuthCertificate, the default verifier
317 * (SSL_AuthCertificateHook was not called in ssl_nss_connect).
318 */
366 gsc->connect_cb(gsc->connect_cb_data, gsc, cond); 319 gsc->connect_cb(gsc->connect_cb_data, gsc, cond);
367 } 320 }
368 } 321 }
369 322
370 static gboolean 323 static gboolean
425 } 378 }
426 379
427 SSL_OptionSet(nss_data->in, SSL_SECURITY, PR_TRUE); 380 SSL_OptionSet(nss_data->in, SSL_SECURITY, PR_TRUE);
428 SSL_OptionSet(nss_data->in, SSL_HANDSHAKE_AS_CLIENT, PR_TRUE); 381 SSL_OptionSet(nss_data->in, SSL_HANDSHAKE_AS_CLIENT, PR_TRUE);
429 382
430 SSL_AuthCertificateHook(nss_data->in, 383 /* If we have our internal verifier set up, use it. Otherwise,
431 (SSLAuthCertificate)ssl_auth_cert, 384 * use default. */
432 (void *)CERT_GetDefaultCertDB()); 385 if (gsc->verifier != NULL)
433 #if 0 386 SSL_AuthCertificateHook(nss_data->in, ssl_auth_cert, NULL);
434 /* No point in hooking BadCert, since ssl_auth_cert always succeeds */
435 SSL_BadCertHook(nss_data->in, (SSLBadCertHandler)ssl_bad_cert, NULL);
436 #endif
437 387
438 if(gsc->host) 388 if(gsc->host)
439 SSL_SetURL(nss_data->in, gsc->host); 389 SSL_SetURL(nss_data->in, gsc->host);
440 390
441 #if 0 391 #if 0

mercurial