Changeset 486ddb5
- Timestamp:
- 2011-12-19T14:50:58Z (13 years ago)
- Branches:
- master
- Children:
- 78b8401
- Parents:
- 5a48afd
- Files:
-
- 12 edited
Legend:
- Unmodified
- Added
- Removed
-
conf.c
r5a48afd r486ddb5 67 67 conf->ft_listen = NULL; 68 68 conf->protocols = NULL; 69 conf->cafile = NULL; 69 70 proxytype = 0; 70 71 … … 340 341 conf->protocols = g_strsplit_set( ini->value, " \t,;", -1 ); 341 342 } 343 else if( g_strcasecmp( ini->key, "cafile" ) == 0 ) 344 { 345 g_free( conf->cafile ); 346 conf->cafile = g_strdup( ini->value ); 347 } 342 348 else 343 349 { -
conf.h
r5a48afd r486ddb5 54 54 char *ft_listen; 55 55 char **protocols; 56 char *cafile; 56 57 } conf_t; 57 58 -
lib/http_client.c
r5a48afd r486ddb5 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 ); … … 170 170 } 171 171 172 static gboolean http_ssl_connected( gpointer data, void *source, b_input_condition cond ) 173 { 172 static gboolean http_ssl_connected( gpointer data, int returncode, void *source, b_input_condition cond ) 173 { 174 //The returncode is not used at the moment. 174 175 struct http_request *req = data; 175 176 -
lib/ssl_bogus.c
r5a48afd r486ddb5 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; -
lib/ssl_client.h
r5a48afd r486ddb5 37 37 /* Some generic error codes. Especially SSL_AGAIN is important if you 38 38 want to do asynchronous I/O. */ 39 #define NSS_VERIFY_ERROR -2 40 #define OPENSSL_VERIFY_ERROR -1 39 41 #define SSL_OK 0 40 42 #define SSL_NOHANDSHAKE 1 41 43 #define SSL_AGAIN 2 44 #define VERIFY_CERT_ERROR 2 45 #define VERIFY_CERT_INVALID 4 46 #define VERIFY_CERT_REVOKED 8 47 #define VERIFY_CERT_SIGNER_NOT_FOUND 16 48 #define VERIFY_CERT_SIGNER_NOT_CA 32 49 #define VERIFY_CERT_INSECURE_ALGORITHM 64 50 #define VERIFY_CERT_NOT_ACTIVATED 128 51 #define VERIFY_CERT_EXPIRED 256 52 #define VERIFY_CERT_WRONG_HOSTNAME 512 42 53 43 54 extern int ssl_errno; 44 55 45 56 /* This is what your callback function should look like. */ 46 typedef gboolean (*ssl_input_function)(gpointer, void*, b_input_condition);57 typedef gboolean (*ssl_input_function)(gpointer, int, void*, b_input_condition); 47 58 48 59 … … 57 68 /* Start an SSL session on an existing fd. Useful for STARTTLS functionality, 58 69 for example in Jabber. */ 59 G_MODULE_EXPORT void *ssl_starttls( int fd, ssl_input_function func, gpointer data );70 G_MODULE_EXPORT void *ssl_starttls( int fd, char *hostname, gboolean verify, ssl_input_function func, gpointer data ); 60 71 61 72 /* Obviously you need special read/write functions to read data. */ -
lib/ssl_gnutls.c
r5a48afd r486ddb5 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; … … 92 96 } 93 97 94 void *ssl_starttls( int fd, ssl_input_function func, gpointer data )98 void *ssl_starttls( int fd, char *hostname, gboolean verify, ssl_input_function func, gpointer data ) 95 99 { 96 100 struct scd *conn = g_new0( struct scd, 1 ); … … 100 104 conn->data = data; 101 105 conn->inpa = -1; 106 conn->hostname = hostname; 107 108 /* For now, SSL verification is globally enabled by setting the cafile 109 setting in bitlbee.conf. Commented out by default because probably 110 not everyone has this file in the same place and plenty of folks 111 may not have the cert of their private Jabber server in it. */ 112 conn->verify = verify && global.conf->cafile; 102 113 103 114 /* This function should be called via a (short) timeout instead of … … 122 133 } 123 134 135 static int verify_certificate_callback( gnutls_session_t session ) 136 { 137 unsigned int status; 138 const gnutls_datum_t *cert_list; 139 unsigned int cert_list_size; 140 int gnutlsret; 141 int verifyret = 0; 142 gnutls_x509_crt_t cert; 143 const char *hostname; 144 145 hostname = gnutls_session_get_ptr(session ); 146 147 gnutlsret = gnutls_certificate_verify_peers2( session, &status ); 148 if( gnutlsret < 0 ) 149 return VERIFY_CERT_ERROR; 150 151 if( status & GNUTLS_CERT_INVALID ) 152 verifyret |= VERIFY_CERT_INVALID; 153 154 if( status & GNUTLS_CERT_REVOKED ) 155 verifyret |= VERIFY_CERT_REVOKED; 156 157 if( status & GNUTLS_CERT_SIGNER_NOT_FOUND ) 158 verifyret |= VERIFY_CERT_SIGNER_NOT_FOUND; 159 160 if( status & GNUTLS_CERT_SIGNER_NOT_CA ) 161 verifyret |= VERIFY_CERT_SIGNER_NOT_CA; 162 163 if( status & GNUTLS_CERT_INSECURE_ALGORITHM ) 164 verifyret |= VERIFY_CERT_INSECURE_ALGORITHM; 165 166 if( status & GNUTLS_CERT_NOT_ACTIVATED ) 167 verifyret |= VERIFY_CERT_NOT_ACTIVATED; 168 169 if( status & GNUTLS_CERT_EXPIRED ) 170 verifyret |= VERIFY_CERT_EXPIRED; 171 172 /* The following check is already performed inside 173 * gnutls_certificate_verify_peers2, so we don't need it. 174 175 * if( gnutls_certificate_type_get( session ) != GNUTLS_CRT_X509 ) 176 * return GNUTLS_E_CERTIFICATE_ERROR; 177 */ 178 179 if( gnutls_x509_crt_init( &cert ) < 0 ) 180 return VERIFY_CERT_ERROR; 181 182 cert_list = gnutls_certificate_get_peers( session, &cert_list_size ); 183 if( cert_list == NULL || gnutls_x509_crt_import( cert, &cert_list[0], GNUTLS_X509_FMT_DER ) < 0 ) 184 return VERIFY_CERT_ERROR; 185 186 if( !gnutls_x509_crt_check_hostname( cert, hostname ) ) 187 { 188 verifyret |= VERIFY_CERT_INVALID; 189 verifyret |= VERIFY_CERT_WRONG_HOSTNAME; 190 } 191 192 gnutls_x509_crt_deinit( cert ); 193 194 return verifyret; 195 } 196 124 197 static gboolean ssl_connected( gpointer data, gint source, b_input_condition cond ) 125 198 { … … 128 201 if( source == -1 ) 129 202 { 130 conn->func( conn->data, NULL, cond );203 conn->func( conn->data, 0, NULL, cond ); 131 204 g_free( conn ); 132 205 return FALSE; … … 136 209 137 210 gnutls_certificate_allocate_credentials( &conn->xcred ); 211 if( conn->verify && global.conf->cafile ) 212 { 213 gnutls_certificate_set_x509_trust_file( conn->xcred, global.conf->cafile, GNUTLS_X509_FMT_PEM ); 214 gnutls_certificate_set_verify_flags( conn->xcred, GNUTLS_VERIFY_ALLOW_X509_V1_CA_CRT ); 215 } 216 138 217 gnutls_init( &conn->session, GNUTLS_CLIENT ); 218 if( conn->verify ) 219 gnutls_session_set_ptr( conn->session, (void *) conn->hostname ); 139 220 #if GNUTLS_VERSION_NUMBER < 0x020c00 140 221 gnutls_transport_set_lowat( conn->session, 0 ); … … 152 233 { 153 234 struct scd *conn = data; 154 int st ;235 int st, stver; 155 236 156 237 if( ( st = gnutls_handshake( conn->session ) ) < 0 ) … … 163 244 else 164 245 { 165 conn->func( conn->data, NULL, cond );246 conn->func( conn->data, 0, NULL, cond ); 166 247 167 248 gnutls_deinit( conn->session ); … … 174 255 else 175 256 { 176 /* For now we can't handle non-blocking perfectly everywhere... */ 177 sock_make_blocking( conn->fd ); 257 if( conn->verify && ( stver = verify_certificate_callback( conn->session ) ) != 0 ) 258 { 259 conn->func( conn->data, stver, NULL, cond ); 260 261 gnutls_deinit( conn->session ); 262 gnutls_certificate_free_credentials( conn->xcred ); 263 closesocket( conn->fd ); 264 265 g_free( conn ); 266 } 267 else 268 { 269 /* For now we can't handle non-blocking perfectly everywhere... */ 270 sock_make_blocking( conn->fd ); 178 271 179 conn->established = TRUE; 180 conn->func( conn->data, conn, cond ); 272 conn->established = TRUE; 273 conn->func( conn->data, 0, conn, cond ); 274 } 181 275 } 182 276 -
lib/ssl_nss.c
r5a48afd r486ddb5 52 52 PRFileDesc *prfd; 53 53 gboolean established; 54 gboolean verify; 54 55 }; 55 56 … … 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; 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 so we 163 fail in case verification has been requested by the user. */ 164 165 if( conn->verify ) 166 { 167 conn->func( conn->data, NSS_VERIFY_ERROR, NULL, cond ); 168 if( source >= 0 ) closesocket( source ); 169 g_free( conn ); 170 171 return FALSE; 172 } 159 173 160 174 if( source == -1 ) … … 177 191 178 192 conn->established = TRUE; 179 conn->func( conn->data, conn, cond );193 conn->func( conn->data, 0, conn, cond ); 180 194 return FALSE; 181 195 182 196 ssl_connected_failure: 183 197 184 conn->func( conn->data, NULL, cond );198 conn->func( conn->data, 0, NULL, cond ); 185 199 186 200 PR_Close( conn -> prfd ); -
lib/ssl_openssl.c
r5a48afd r486ddb5 45 45 int fd; 46 46 gboolean established; 47 gboolean verify; 47 48 48 49 int inpa; … … 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; 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 so we 122 fail in case verification has been requested by the user. */ 123 124 if( conn->verify ) 125 { 126 conn->func( conn->data, OPENSSL_VERIFY_ERROR, NULL, cond ); 127 if( source >= 0 ) closesocket( source ); 128 g_free( conn ); 129 130 return FALSE; 131 } 132 119 133 if( source == -1 ) 120 134 goto ssl_connected_failure; … … 141 155 142 156 ssl_connected_failure: 143 conn->func( conn->data, NULL, cond );157 conn->func( conn->data, 0, NULL, cond ); 144 158 145 159 if( conn->ssl ) … … 169 183 if( conn->lasterr != SSL_ERROR_WANT_READ && conn->lasterr != SSL_ERROR_WANT_WRITE ) 170 184 { 171 conn->func( conn->data, NULL, cond );185 conn->func( conn->data, 0, NULL, cond ); 172 186 173 187 SSL_shutdown( conn->ssl ); … … 187 201 conn->established = TRUE; 188 202 sock_make_blocking( conn->fd ); /* For now... */ 189 conn->func( conn->data, conn, cond );203 conn->func( conn->data, 0, conn, cond ); 190 204 return FALSE; 191 205 } -
protocols/jabber/io.c
r5a48afd r486ddb5 276 276 } 277 277 278 gboolean jabber_connected_ssl( gpointer data, void *source, b_input_condition cond )278 gboolean jabber_connected_ssl( gpointer data, int returncode, void *source, b_input_condition cond ) 279 279 { 280 280 struct im_connection *ic = data; … … 293 293 294 294 imcb_error( ic, "Could not connect to server" ); 295 if (returncode == OPENSSL_VERIFY_ERROR ) 296 { 297 imcb_error( ic, "This BitlBee server is built agains the OpenSSL library." ); 298 imcb_error( ic, "Unfortunately certificate verification is only supported when built against GnuTLS for now." ); 299 imc_logout( ic, FALSE ); 300 } 301 else if (returncode == NSS_VERIFY_ERROR ) 302 { 303 imcb_error( ic, "This BitlBee server is built agains the NSS library." ); 304 imcb_error( ic, "Unfortunately certificate verification is only supported when built against GnuTLS for now." ); 305 imc_logout( ic, FALSE ); 306 } 307 else if (returncode == VERIFY_CERT_ERROR ) 308 { 309 imcb_error( ic, "An error occured during the certificate verification." ); 310 imc_logout( ic, FALSE ); 311 } 312 else if (returncode & VERIFY_CERT_INVALID) 313 { 314 imcb_error( ic, "Unable to verify peer's certificate." ); 315 if (returncode & VERIFY_CERT_REVOKED) 316 imcb_error( ic, "The certificate has been revoked." ); 317 if (returncode & VERIFY_CERT_SIGNER_NOT_FOUND) 318 imcb_error( ic, "The certificate hasn't got a known issuer." ); 319 if (returncode & VERIFY_CERT_SIGNER_NOT_CA) 320 imcb_error( ic, "The certificate's issuer is not a CA." ); 321 if (returncode & VERIFY_CERT_INSECURE_ALGORITHM) 322 imcb_error( ic, "The certificate uses an insecure algorithm." ); 323 if (returncode & VERIFY_CERT_NOT_ACTIVATED) 324 imcb_error( ic, "The certificate has not been activated." ); 325 if (returncode & VERIFY_CERT_EXPIRED) 326 imcb_error( ic, "The certificate has expired." ); 327 if (returncode & VERIFY_CERT_WRONG_HOSTNAME) 328 imcb_error( ic, "The hostname specified in the certificate doesn't match the server name." ); 329 imc_logout( ic, FALSE ); 330 } 331 else 295 332 imc_logout( ic, TRUE ); 296 333 return FALSE; … … 397 434 struct im_connection *ic = data; 398 435 struct jabber_data *jd = ic->proto_data; 399 char *xmlns ;436 char *xmlns, *tlsname; 400 437 401 438 xmlns = xt_find_attr( node, "xmlns" ); … … 423 460 424 461 jd->flags |= JFLAG_STARTTLS_DONE; 425 jd->ssl = ssl_starttls( jd->fd, jabber_connected_ssl, ic ); 462 463 /* If the user specified a server for the account, use this server as the 464 * hostname in the certificate verification. Else we use the domain from 465 * the username. */ 466 if( ic->acc->server && *ic->acc->server ) 467 tlsname = ic->acc->server; 468 else 469 tlsname = jd->server; 470 471 jd->ssl = ssl_starttls( jd->fd, tlsname, set_getbool( &ic->acc->set, "tls_verify" ), 472 jabber_connected_ssl, ic ); 426 473 427 474 return XT_HANDLED; -
protocols/jabber/jabber.c
r5a48afd r486ddb5 80 80 81 81 s = set_add( &acc->set, "tls", "try", set_eval_tls, acc ); 82 s->flags |= ACC_SET_OFFLINE_ONLY; 83 84 s = set_add( &acc->set, "tls_verify", "true", set_eval_bool, acc ); 82 85 s->flags |= ACC_SET_OFFLINE_ONLY; 83 86 -
protocols/jabber/jabber.h
r5a48afd r486ddb5 307 307 int jabber_write( struct im_connection *ic, char *buf, int len ); 308 308 gboolean jabber_connected_plain( gpointer data, gint source, b_input_condition cond ); 309 gboolean jabber_connected_ssl( gpointer data, void *source, b_input_condition cond );309 gboolean jabber_connected_ssl( gpointer data, int returncode, void *source, b_input_condition cond ); 310 310 gboolean jabber_start_stream( struct im_connection *ic ); 311 311 void jabber_end_stream( struct im_connection *ic ); -
protocols/skype/skype.c
r5a48afd r486ddb5 1157 1157 } 1158 1158 1159 gboolean skype_connected(gpointer data, void *source, b_input_condition cond)1159 gboolean skype_connected(gpointer data, int returncode, void *source, b_input_condition cond) 1160 1160 { 1161 1161 struct im_connection *ic = data;
Note: See TracChangeset
for help on using the changeset viewer.