| 137 } |
137 } |
| 138 |
138 |
| 139 return ret; |
139 return ret; |
| 140 } |
140 } |
| 141 |
141 |
| |
142 static void ssl_nss_log_ciphers(void) { |
| |
143 const PRUint16 *cipher; |
| |
144 for (cipher = SSL_GetImplementedCiphers(); *cipher != 0; ++cipher) { |
| |
145 const PRUint16 suite = *cipher; |
| |
146 SECStatus rv; |
| |
147 PRBool enabled; |
| |
148 PRErrorCode err; |
| |
149 SSLCipherSuiteInfo info; |
| |
150 |
| |
151 rv = SSL_CipherPrefGetDefault(suite, &enabled); |
| |
152 if (rv != SECSuccess) { |
| |
153 err = PR_GetError(); |
| |
154 purple_debug_warning("nss", |
| |
155 "SSL_CipherPrefGetDefault didn't like value 0x%04x: %s\n", |
| |
156 suite, PORT_ErrorToString(err)); |
| |
157 continue; |
| |
158 } |
| |
159 rv = SSL_GetCipherSuiteInfo(suite, &info, (int)(sizeof info)); |
| |
160 if (rv != SECSuccess) { |
| |
161 err = PR_GetError(); |
| |
162 purple_debug_warning("nss", |
| |
163 "SSL_GetCipherSuiteInfo didn't like value 0x%04x: %s\n", |
| |
164 suite, PORT_ErrorToString(err)); |
| |
165 continue; |
| |
166 } |
| |
167 purple_debug_info("nss", "Cipher - %s: %s\n", |
| |
168 info.cipherSuiteName, |
| |
169 enabled ? "Enabled" : "Disabled"); |
| |
170 } |
| |
171 } |
| |
172 |
| 142 static void |
173 static void |
| 143 ssl_nss_init_nss(void) |
174 ssl_nss_init_nss(void) |
| 144 { |
175 { |
| 145 #if NSS_VMAJOR > 3 || ( NSS_VMAJOR == 3 && NSS_VMINOR >= 14 ) |
176 #if NSS_VMAJOR > 3 || ( NSS_VMAJOR == 3 && NSS_VMINOR >= 14 ) |
| 146 SSLVersionRange supported, enabled; |
177 SSLVersionRange supported, enabled; |
| 147 #endif /* NSS >= 3.14 */ |
178 #endif /* NSS >= 3.14 */ |
| 148 |
179 |
| 149 PR_Init(PR_SYSTEM_THREAD, PR_PRIORITY_NORMAL, 1); |
180 PR_Init(PR_SYSTEM_THREAD, PR_PRIORITY_NORMAL, 1); |
| 150 NSS_NoDB_Init("."); |
181 NSS_NoDB_Init("."); |
| |
182 #if (NSS_VMAJOR == 3 && (NSS_VMINOR < 15 || (NSS_VMINOR == 15 && NSS_VMICRO < 2))) |
| 151 NSS_SetDomesticPolicy(); |
183 NSS_SetDomesticPolicy(); |
| |
184 #endif /* NSS < 3.15.2 */ |
| 152 |
185 |
| 153 SSL_CipherPrefSetDefault(TLS_DHE_RSA_WITH_AES_256_CBC_SHA, 1); |
186 SSL_CipherPrefSetDefault(TLS_DHE_RSA_WITH_AES_256_CBC_SHA, 1); |
| 154 SSL_CipherPrefSetDefault(TLS_DHE_DSS_WITH_AES_256_CBC_SHA, 1); |
187 SSL_CipherPrefSetDefault(TLS_DHE_DSS_WITH_AES_256_CBC_SHA, 1); |
| 155 SSL_CipherPrefSetDefault(TLS_RSA_WITH_AES_256_CBC_SHA, 1); |
188 SSL_CipherPrefSetDefault(TLS_RSA_WITH_AES_256_CBC_SHA, 1); |
| 156 SSL_CipherPrefSetDefault(TLS_DHE_DSS_WITH_RC4_128_SHA, 1); |
189 SSL_CipherPrefSetDefault(TLS_DHE_DSS_WITH_RC4_128_SHA, 1); |
| 193 /** Disable OCSP Checking until we can make that use our HTTP & Proxy stuff */ |
226 /** Disable OCSP Checking until we can make that use our HTTP & Proxy stuff */ |
| 194 CERT_EnableOCSPChecking(PR_FALSE); |
227 CERT_EnableOCSPChecking(PR_FALSE); |
| 195 |
228 |
| 196 _identity = PR_GetUniqueIdentity("Purple"); |
229 _identity = PR_GetUniqueIdentity("Purple"); |
| 197 _nss_methods = PR_GetDefaultIOMethods(); |
230 _nss_methods = PR_GetDefaultIOMethods(); |
| |
231 |
| |
232 ssl_nss_log_ciphers(); |
| 198 } |
233 } |
| 199 |
234 |
| 200 static SECStatus |
235 static SECStatus |
| 201 ssl_auth_cert(void *arg, PRFileDesc *socket, PRBool checksig, PRBool is_server) |
236 ssl_auth_cert(void *arg, PRFileDesc *socket, PRBool checksig, PRBool is_server) |
| 202 { |
237 { |
| 1032 static void x509_verify_cert(PurpleCertificateVerificationRequest *vrq, PurpleCertificateVerificationStatus *flags) |
1067 static void x509_verify_cert(PurpleCertificateVerificationRequest *vrq, PurpleCertificateVerificationStatus *flags) |
| 1033 { |
1068 { |
| 1034 CERTCertDBHandle *certdb = CERT_GetDefaultCertDB(); |
1069 CERTCertDBHandle *certdb = CERT_GetDefaultCertDB(); |
| 1035 CERTCertificate *crt_dat; |
1070 CERTCertificate *crt_dat; |
| 1036 PRTime now = PR_Now(); |
1071 PRTime now = PR_Now(); |
| 1037 SECStatus rv; |
1072 SECStatus rv; |
| 1038 PurpleCertificate *first_cert = vrq->cert_chain->data; |
1073 PurpleCertificate *first_cert = vrq->cert_chain->data; |
| 1039 CERTVerifyLog log; |
1074 CERTVerifyLog log; |
| |
1075 gboolean self_signed = FALSE; |
| 1040 |
1076 |
| 1041 crt_dat = X509_NSS_DATA(first_cert); |
1077 crt_dat = X509_NSS_DATA(first_cert); |
| 1042 |
1078 |
| 1043 log.arena = PORT_NewArena(512); |
1079 log.arena = PORT_NewArena(512); |
| 1044 log.head = log.tail = NULL; |
1080 log.head = log.tail = NULL; |
| 1047 |
1083 |
| 1048 if (rv != SECSuccess || log.count > 0) { |
1084 if (rv != SECSuccess || log.count > 0) { |
| 1049 CERTVerifyLogNode *node = NULL; |
1085 CERTVerifyLogNode *node = NULL; |
| 1050 unsigned int depth = (unsigned int)-1; |
1086 unsigned int depth = (unsigned int)-1; |
| 1051 |
1087 |
| |
1088 if (crt_dat->isRoot) { |
| |
1089 self_signed = TRUE; |
| |
1090 *flags |= PURPLE_CERTIFICATE_SELF_SIGNED; |
| |
1091 } |
| |
1092 |
| |
1093 /* Handling of untrusted, etc. modeled after |
| |
1094 * source/security/manager/ssl/src/TransportSecurityInfo.cpp in Firefox |
| |
1095 */ |
| 1052 for (node = log.head; node; node = node->next) { |
1096 for (node = log.head; node; node = node->next) { |
| 1053 if (depth != node->depth) { |
1097 if (depth != node->depth) { |
| 1054 depth = node->depth; |
1098 depth = node->depth; |
| 1055 purple_debug_error("nss", "CERT %d. %s %s:\n", depth, |
1099 purple_debug_error("nss", "CERT %d. %s %s:\n", depth, |
| 1056 node->cert->subjectName, |
1100 node->cert->subjectName, |
| 1063 *flags |= PURPLE_CERTIFICATE_EXPIRED; |
1107 *flags |= PURPLE_CERTIFICATE_EXPIRED; |
| 1064 break; |
1108 break; |
| 1065 case SEC_ERROR_REVOKED_CERTIFICATE: |
1109 case SEC_ERROR_REVOKED_CERTIFICATE: |
| 1066 *flags |= PURPLE_CERTIFICATE_REVOKED; |
1110 *flags |= PURPLE_CERTIFICATE_REVOKED; |
| 1067 break; |
1111 break; |
| |
1112 case SEC_ERROR_UNKNOWN_ISSUER: |
| 1068 case SEC_ERROR_UNTRUSTED_ISSUER: |
1113 case SEC_ERROR_UNTRUSTED_ISSUER: |
| 1069 if (crt_dat->isRoot) { |
1114 if (!self_signed) { |
| 1070 *flags |= PURPLE_CERTIFICATE_SELF_SIGNED; |
|
| 1071 } else { |
|
| 1072 *flags |= PURPLE_CERTIFICATE_CA_UNKNOWN; |
1115 *flags |= PURPLE_CERTIFICATE_CA_UNKNOWN; |
| 1073 } |
1116 } |
| 1074 break; |
1117 break; |
| |
1118 case SEC_ERROR_CA_CERT_INVALID: |
| |
1119 case SEC_ERROR_EXPIRED_ISSUER_CERTIFICATE: |
| |
1120 case SEC_ERROR_UNTRUSTED_CERT: |
| 1075 case SEC_ERROR_CERT_SIGNATURE_ALGORITHM_DISABLED: |
1121 case SEC_ERROR_CERT_SIGNATURE_ALGORITHM_DISABLED: |
| |
1122 if (!self_signed) { |
| |
1123 *flags |= PURPLE_CERTIFICATE_INVALID_CHAIN; |
| |
1124 } |
| |
1125 break; |
| 1076 case SEC_ERROR_BAD_SIGNATURE: |
1126 case SEC_ERROR_BAD_SIGNATURE: |
| 1077 default: |
1127 default: |
| 1078 *flags |= PURPLE_CERTIFICATE_INVALID_CHAIN; |
1128 *flags |= PURPLE_CERTIFICATE_INVALID_CHAIN; |
| 1079 } |
1129 } |
| 1080 if (node->cert) |
1130 if (node->cert) |
| 1081 CERT_DestroyCertificate(node->cert); |
1131 CERT_DestroyCertificate(node->cert); |
| 1082 } |
1132 } |
| 1083 } else { |
1133 } |
| 1084 rv = CERT_VerifyCertName(crt_dat, vrq->subject_name); |
1134 |
| 1085 if (rv != SECSuccess) { |
1135 rv = CERT_VerifyCertName(crt_dat, vrq->subject_name); |
| 1086 purple_debug_error("nss", "Cert chain valid, but name not verified\n"); |
1136 if (rv != SECSuccess) { |
| 1087 *flags |= PURPLE_CERTIFICATE_NAME_MISMATCH; |
1137 purple_debug_error("nss", "subject name not verified\n"); |
| 1088 } |
1138 *flags |= PURPLE_CERTIFICATE_NAME_MISMATCH; |
| 1089 } |
1139 } |
| 1090 |
1140 |
| 1091 PORT_FreeArena(log.arena, PR_FALSE); |
1141 PORT_FreeArena(log.arena, PR_FALSE); |
| 1092 } |
1142 } |
| 1093 |
1143 |