- Timestamp:
- 2011-12-24T18:02:39Z (13 years ago)
- Branches:
- master
- Children:
- 34ded90
- Parents:
- e306fbf (diff), 96f954d (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the(diff)
links above to see all the changes relative to each parent. - Location:
- lib
- Files:
-
- 7 edited
Legend:
- Unmodified
- Added
- Removed
-
lib/events_glib.c
re306fbf r164352e 75 75 b_input_condition gaim_cond = 0; 76 76 gboolean st; 77 78 if (condition & G_IO_NVAL) 79 return FALSE; 77 80 78 81 if (condition & GAIM_READ_COND) -
lib/http_client.c
re306fbf r164352e 33 33 34 34 static gboolean http_connected( gpointer data, int source, b_input_condition cond ); 35 static gboolean http_ssl_connected( gpointer data, void *source, b_input_condition cond );35 static gboolean http_ssl_connected( gpointer data, int returncode, void *source, b_input_condition cond ); 36 36 static gboolean http_incoming_data( gpointer data, int source, b_input_condition cond ); 37 37 static void http_free( struct http_request *req ); … … 47 47 if( ssl ) 48 48 { 49 req->ssl = ssl_connect( host, port, http_ssl_connected, req );49 req->ssl = ssl_connect( host, port, TRUE, http_ssl_connected, req ); 50 50 if( req->ssl == NULL ) 51 51 error = 1; … … 163 163 164 164 error: 165 req->status_string = g_strdup( "Error while writing HTTP request" ); 165 if( req->status_string == NULL ) 166 req->status_string = g_strdup( "Error while writing HTTP request" ); 166 167 167 168 req->func( req ); … … 170 171 } 171 172 172 static gboolean http_ssl_connected( gpointer data, void *source, b_input_condition cond )173 static gboolean http_ssl_connected( gpointer data, int returncode, void *source, b_input_condition cond ) 173 174 { 174 175 struct http_request *req = data; 175 176 176 177 if( source == NULL ) 178 { 179 if( returncode != 0 ) 180 { 181 char *err = ssl_verify_strerror( returncode ); 182 req->status_string = g_strdup_printf( 183 "Certificate verification problem 0x%x: %s", 184 returncode, err ? err : "Unknown" ); 185 g_free( err ); 186 } 177 187 return http_connected( data, -1, cond ); 188 } 178 189 179 190 req->fd = ssl_getfd( source ); … … 439 450 if( new_proto == PROTO_HTTPS ) 440 451 { 441 req->ssl = ssl_connect( new_host, new_port, http_ssl_connected, req );452 req->ssl = ssl_connect( new_host, new_port, TRUE, http_ssl_connected, req ); 442 453 if( req->ssl == NULL ) 443 454 error = 1; -
lib/ssl_bogus.c
re306fbf r164352e 32 32 } 33 33 34 void *ssl_connect( char *host, int port, ssl_input_function func, gpointer data )34 void *ssl_connect( char *host, int port, gboolean verify, ssl_input_function func, gpointer data ) 35 35 { 36 36 return( NULL ); … … 56 56 } 57 57 58 void *ssl_starttls( int fd, ssl_input_function func, gpointer data )58 void *ssl_starttls( int fd, char *hostname, gboolean verify, ssl_input_function func, gpointer data ) 59 59 { 60 60 return NULL; … … 70 70 return 0; 71 71 } 72 73 char *ssl_verify_strerror( int code ) 74 { 75 return NULL; 76 } -
lib/ssl_client.h
re306fbf r164352e 40 40 #define SSL_NOHANDSHAKE 1 41 41 #define SSL_AGAIN 2 42 #define VERIFY_CERT_ERROR 2 43 #define VERIFY_CERT_INVALID 4 44 #define VERIFY_CERT_REVOKED 8 45 #define VERIFY_CERT_SIGNER_NOT_FOUND 16 46 #define VERIFY_CERT_SIGNER_NOT_CA 32 47 #define VERIFY_CERT_INSECURE_ALGORITHM 64 48 #define VERIFY_CERT_NOT_ACTIVATED 128 49 #define VERIFY_CERT_EXPIRED 256 50 #define VERIFY_CERT_WRONG_HOSTNAME 512 42 51 43 52 extern int ssl_errno; 44 53 45 54 /* This is what your callback function should look like. */ 46 typedef gboolean (*ssl_input_function)(gpointer, void*, b_input_condition);55 typedef gboolean (*ssl_input_function)(gpointer, int, void*, b_input_condition); 47 56 48 57 … … 53 62 ready to be used for SSL traffic. This is all done asynchronously, no 54 63 blocking I/O! (Except for the DNS lookups, for now...) */ 55 G_MODULE_EXPORT void *ssl_connect( char *host, int port, ssl_input_function func, gpointer data );64 G_MODULE_EXPORT void *ssl_connect( char *host, int port, gboolean verify, ssl_input_function func, gpointer data ); 56 65 57 66 /* Start an SSL session on an existing fd. Useful for STARTTLS functionality, 58 67 for example in Jabber. */ 59 G_MODULE_EXPORT void *ssl_starttls( int fd, ssl_input_function func, gpointer data );68 G_MODULE_EXPORT void *ssl_starttls( int fd, char *hostname, gboolean verify, ssl_input_function func, gpointer data ); 60 69 61 70 /* Obviously you need special read/write functions to read data. */ … … 90 99 G_MODULE_EXPORT b_input_condition ssl_getdirection( void *conn ); 91 100 101 /* Converts a verification bitfield passed to ssl_input_function into 102 a more useful string. Or NULL if it had no useful bits set. */ 103 G_MODULE_EXPORT char *ssl_verify_strerror( int code ); 104 92 105 G_MODULE_EXPORT size_t ssl_des3_encrypt(const unsigned char *key, size_t key_len, const unsigned char *input, size_t input_len, const unsigned char *iv, unsigned char **res); -
lib/ssl_gnutls.c
re306fbf r164352e 25 25 26 26 #include <gnutls/gnutls.h> 27 #include <gnutls/x509.h> 27 28 #include <gcrypt.h> 28 29 #include <fcntl.h> … … 32 33 #include "sock.h" 33 34 #include "stdlib.h" 35 #include "bitlbee.h" 34 36 35 37 int ssl_errno = 0; … … 54 56 gboolean established; 55 57 int inpa; 58 char *hostname; 59 gboolean verify; 56 60 57 61 gnutls_session session; … … 74 78 } 75 79 76 void *ssl_connect( char *host, int port, ssl_input_function func, gpointer data )80 void *ssl_connect( char *host, int port, gboolean verify, ssl_input_function func, gpointer data ) 77 81 { 78 82 struct scd *conn = g_new0( struct scd, 1 ); … … 82 86 conn->data = data; 83 87 conn->inpa = -1; 88 conn->hostname = g_strdup( host ); 89 conn->verify = verify && global.conf->cafile; 84 90 85 91 if( conn->fd < 0 ) … … 92 98 } 93 99 94 void *ssl_starttls( int fd, ssl_input_function func, gpointer data )100 void *ssl_starttls( int fd, char *hostname, gboolean verify, ssl_input_function func, gpointer data ) 95 101 { 96 102 struct scd *conn = g_new0( struct scd, 1 ); … … 100 106 conn->data = data; 101 107 conn->inpa = -1; 108 conn->hostname = hostname; 109 110 /* For now, SSL verification is globally enabled by setting the cafile 111 setting in bitlbee.conf. Commented out by default because probably 112 not everyone has this file in the same place and plenty of folks 113 may not have the cert of their private Jabber server in it. */ 114 conn->verify = verify && global.conf->cafile; 102 115 103 116 /* This function should be called via a (short) timeout instead of … … 122 135 } 123 136 137 static int verify_certificate_callback( gnutls_session_t session ) 138 { 139 unsigned int status; 140 const gnutls_datum_t *cert_list; 141 unsigned int cert_list_size; 142 int gnutlsret; 143 int verifyret = 0; 144 gnutls_x509_crt_t cert; 145 const char *hostname; 146 147 hostname = gnutls_session_get_ptr(session ); 148 149 gnutlsret = gnutls_certificate_verify_peers2( session, &status ); 150 if( gnutlsret < 0 ) 151 return VERIFY_CERT_ERROR; 152 153 if( status & GNUTLS_CERT_INVALID ) 154 verifyret |= VERIFY_CERT_INVALID; 155 156 if( status & GNUTLS_CERT_REVOKED ) 157 verifyret |= VERIFY_CERT_REVOKED; 158 159 if( status & GNUTLS_CERT_SIGNER_NOT_FOUND ) 160 verifyret |= VERIFY_CERT_SIGNER_NOT_FOUND; 161 162 if( status & GNUTLS_CERT_SIGNER_NOT_CA ) 163 verifyret |= VERIFY_CERT_SIGNER_NOT_CA; 164 165 if( status & GNUTLS_CERT_INSECURE_ALGORITHM ) 166 verifyret |= VERIFY_CERT_INSECURE_ALGORITHM; 167 168 #ifdef GNUTLS_CERT_NOT_ACTIVATED 169 /* Amusingly, the GnuTLS function used above didn't check for expiry 170 until GnuTLS 2.8 or so. (See CVE-2009-1417) */ 171 if( status & GNUTLS_CERT_NOT_ACTIVATED ) 172 verifyret |= VERIFY_CERT_NOT_ACTIVATED; 173 174 if( status & GNUTLS_CERT_EXPIRED ) 175 verifyret |= VERIFY_CERT_EXPIRED; 176 #endif 177 178 /* The following check is already performed inside 179 * gnutls_certificate_verify_peers2, so we don't need it. 180 181 * if( gnutls_certificate_type_get( session ) != GNUTLS_CRT_X509 ) 182 * return GNUTLS_E_CERTIFICATE_ERROR; 183 */ 184 185 if( gnutls_x509_crt_init( &cert ) < 0 ) 186 return VERIFY_CERT_ERROR; 187 188 cert_list = gnutls_certificate_get_peers( session, &cert_list_size ); 189 if( cert_list == NULL || gnutls_x509_crt_import( cert, &cert_list[0], GNUTLS_X509_FMT_DER ) < 0 ) 190 return VERIFY_CERT_ERROR; 191 192 if( !gnutls_x509_crt_check_hostname( cert, hostname ) ) 193 { 194 verifyret |= VERIFY_CERT_INVALID; 195 verifyret |= VERIFY_CERT_WRONG_HOSTNAME; 196 } 197 198 gnutls_x509_crt_deinit( cert ); 199 200 return verifyret; 201 } 202 203 char *ssl_verify_strerror( int code ) 204 { 205 GString *ret = g_string_new( "" ); 206 207 if( code & VERIFY_CERT_REVOKED ) 208 g_string_append( ret, "certificate has been revoked, " ); 209 if( code & VERIFY_CERT_SIGNER_NOT_FOUND ) 210 g_string_append( ret, "certificate hasn't got a known issuer, " ); 211 if( code & VERIFY_CERT_SIGNER_NOT_CA ) 212 g_string_append( ret, "certificate's issuer is not a CA, " ); 213 if( code & VERIFY_CERT_INSECURE_ALGORITHM ) 214 g_string_append( ret, "certificate uses an insecure algorithm, " ); 215 if( code & VERIFY_CERT_NOT_ACTIVATED ) 216 g_string_append( ret, "certificate has not been activated, " ); 217 if( code & VERIFY_CERT_EXPIRED ) 218 g_string_append( ret, "certificate has expired, " ); 219 if( code & VERIFY_CERT_WRONG_HOSTNAME ) 220 g_string_append( ret, "certificate hostname mismatch, " ); 221 222 if( ret->len == 0 ) 223 { 224 g_string_free( ret, TRUE ); 225 return NULL; 226 } 227 else 228 { 229 g_string_truncate( ret, ret->len - 2 ); 230 return g_string_free( ret, FALSE ); 231 } 232 } 233 124 234 static gboolean ssl_connected( gpointer data, gint source, b_input_condition cond ) 125 235 { … … 128 238 if( source == -1 ) 129 239 { 130 conn->func( conn->data, NULL, cond );240 conn->func( conn->data, 0, NULL, cond ); 131 241 g_free( conn ); 132 242 return FALSE; … … 136 246 137 247 gnutls_certificate_allocate_credentials( &conn->xcred ); 248 if( conn->verify && global.conf->cafile ) 249 { 250 gnutls_certificate_set_x509_trust_file( conn->xcred, global.conf->cafile, GNUTLS_X509_FMT_PEM ); 251 gnutls_certificate_set_verify_flags( conn->xcred, GNUTLS_VERIFY_ALLOW_X509_V1_CA_CRT ); 252 } 253 138 254 gnutls_init( &conn->session, GNUTLS_CLIENT ); 255 if( conn->verify ) 256 gnutls_session_set_ptr( conn->session, (void *) conn->hostname ); 139 257 #if GNUTLS_VERSION_NUMBER < 0x020c00 140 258 gnutls_transport_set_lowat( conn->session, 0 ); … … 152 270 { 153 271 struct scd *conn = data; 154 int st ;272 int st, stver; 155 273 156 274 if( ( st = gnutls_handshake( conn->session ) ) < 0 ) … … 163 281 else 164 282 { 165 conn->func( conn->data, NULL, cond );283 conn->func( conn->data, 0, NULL, cond ); 166 284 167 285 gnutls_deinit( conn->session ); … … 174 292 else 175 293 { 176 /* For now we can't handle non-blocking perfectly everywhere... */ 177 sock_make_blocking( conn->fd ); 294 if( conn->verify && ( stver = verify_certificate_callback( conn->session ) ) != 0 ) 295 { 296 conn->func( conn->data, stver, NULL, cond ); 297 298 gnutls_deinit( conn->session ); 299 gnutls_certificate_free_credentials( conn->xcred ); 300 closesocket( conn->fd ); 301 302 g_free( conn ); 303 } 304 else 305 { 306 /* For now we can't handle non-blocking perfectly everywhere... */ 307 sock_make_blocking( conn->fd ); 178 308 179 conn->established = TRUE; 180 conn->func( conn->data, conn, cond ); 309 conn->established = TRUE; 310 conn->func( conn->data, 0, conn, cond ); 311 } 181 312 } 182 313 -
lib/ssl_nss.c
re306fbf r164352e 52 52 PRFileDesc *prfd; 53 53 gboolean established; 54 gboolean verify; 54 55 }; 55 56 … … 102 103 } 103 104 104 void *ssl_connect( char *host, int port, ssl_input_function func, gpointer data )105 void *ssl_connect( char *host, int port, gboolean verify, ssl_input_function func, gpointer data ) 105 106 { 106 107 struct scd *conn = g_new0( struct scd, 1 ); … … 132 133 } 133 134 134 void *ssl_starttls( int fd, ssl_input_function func, gpointer data )135 void *ssl_starttls( int fd, char *hostname, gboolean verify, ssl_input_function func, gpointer data ) 135 136 { 136 137 struct scd *conn = g_new0( struct scd, 1 ); … … 139 140 conn->func = func; 140 141 conn->data = data; 142 conn->verify = verify && global.conf->cafile; 141 143 142 144 /* This function should be called via a (short) timeout instead of … … 157 159 { 158 160 struct scd *conn = data; 161 162 /* Right now we don't have any verification functionality for NSS. */ 163 164 if( conn->verify ) 165 { 166 conn->func( conn->data, 1, NULL, cond ); 167 if( source >= 0 ) closesocket( source ); 168 g_free( conn ); 169 170 return FALSE; 171 } 159 172 160 173 if( source == -1 ) … … 177 190 178 191 conn->established = TRUE; 179 conn->func( conn->data, conn, cond );192 conn->func( conn->data, 0, conn, cond ); 180 193 return FALSE; 181 194 182 195 ssl_connected_failure: 183 196 184 conn->func( conn->data, NULL, cond );197 conn->func( conn->data, 0, NULL, cond ); 185 198 186 199 PR_Close( conn -> prfd ); … … 238 251 return B_EV_IO_READ; 239 252 } 253 254 char *ssl_verify_strerror( int code ) 255 { 256 return g_strdup( "SSL certificate verification not supported by BitlBee NSS code." ); 257 } -
lib/ssl_openssl.c
re306fbf r164352e 45 45 int fd; 46 46 gboolean established; 47 gboolean verify; 47 48 48 49 int inpa; … … 64 65 } 65 66 66 void *ssl_connect( char *host, int port, ssl_input_function func, gpointer data )67 void *ssl_connect( char *host, int port, gboolean verify, ssl_input_function func, gpointer data ) 67 68 { 68 69 struct scd *conn = g_new0( struct scd, 1 ); … … 82 83 } 83 84 84 void *ssl_starttls( int fd, ssl_input_function func, gpointer data )85 void *ssl_starttls( int fd, char *hostname, gboolean verify, ssl_input_function func, gpointer data ) 85 86 { 86 87 struct scd *conn = g_new0( struct scd, 1 ); … … 90 91 conn->data = data; 91 92 conn->inpa = -1; 93 conn->verify = verify && global.conf->cafile; 92 94 93 95 /* This function should be called via a (short) timeout instead of … … 117 119 SSL_METHOD *meth; 118 120 121 /* Right now we don't have any verification functionality for OpenSSL. */ 122 123 if( conn->verify ) 124 { 125 conn->func( conn->data, 1, NULL, cond ); 126 if( source >= 0 ) closesocket( source ); 127 g_free( conn ); 128 129 return FALSE; 130 } 131 119 132 if( source == -1 ) 120 133 goto ssl_connected_failure; … … 141 154 142 155 ssl_connected_failure: 143 conn->func( conn->data, NULL, cond );156 conn->func( conn->data, 0, NULL, cond ); 144 157 145 158 if( conn->ssl ) … … 169 182 if( conn->lasterr != SSL_ERROR_WANT_READ && conn->lasterr != SSL_ERROR_WANT_WRITE ) 170 183 { 171 conn->func( conn->data, NULL, cond );184 conn->func( conn->data, 0, NULL, cond ); 172 185 173 186 SSL_shutdown( conn->ssl ); … … 187 200 conn->established = TRUE; 188 201 sock_make_blocking( conn->fd ); /* For now... */ 189 conn->func( conn->data, conn, cond );202 conn->func( conn->data, 0, conn, cond ); 190 203 return FALSE; 191 204 } … … 272 285 { 273 286 return( ((struct scd*)conn)->lasterr == SSL_ERROR_WANT_WRITE ? B_EV_IO_WRITE : B_EV_IO_READ ); 287 } 288 289 char *ssl_verify_strerror( int code ) 290 { 291 return g_strdup( "SSL certificate verification not supported by BitlBee OpenSSL code." ); 274 292 } 275 293
Note: See TracChangeset
for help on using the changeset viewer.