Changeset 68709f5
- Timestamp:
- 2012-08-19T15:33:55Z (12 years ago)
- Branches:
- master
- Children:
- 7281ad1
- Parents:
- 6ee51a9
- Files:
-
- 2 deleted
- 3 edited
Legend:
- Unmodified
- Added
- Removed
-
configure
r6ee51a9 r68709f5 454 454 fi; 455 455 456 if [ "$msn" = "1" -a "$ssl" != "openssl" -a "$ssl" != "gnutls" ]; then457 # Needed for MSN only. OpenSSL exports nice cipher functions already,458 # in case of GnuTLS we should be able to use gcrypt. Otherwise, use459 # built-in stuff. (Since right now those are the only two supported460 # SSL modules anyway, this is mostly unnecessary.)461 echo 'DES=des.o' >> Makefile.settings462 fi463 464 456 echo 'SSL_CLIENT=ssl_'$ssl'.o' >> Makefile.settings 465 457 -
lib/Makefile
r6ee51a9 r68709f5 13 13 14 14 # [SH] Program variables 15 objects = arc.o base64.o $( DES) $(EVENT_HANDLER) ftutil.o http_client.o ini.o md5.o misc.o oauth.o oauth2.o proxy.o sha1.o $(SSL_CLIENT) url.o xmltree.o15 objects = arc.o base64.o $(EVENT_HANDLER) ftutil.o http_client.o ini.o md5.o misc.o oauth.o oauth2.o proxy.o sha1.o $(SSL_CLIENT) url.o xmltree.o 16 16 17 17 LFLAGS += -r -
lib/ssl_nss.c
r6ee51a9 r68709f5 40 40 #include <secerr.h> 41 41 #include <sslerr.h> 42 #include <assert.h> 43 #include <unistd.h> 42 44 43 45 int ssl_errno = 0; … … 45 47 static gboolean initialized = FALSE; 46 48 47 struct scd 48 { 49 #define SSLDEBUG 0 50 51 struct scd { 49 52 ssl_input_function func; 50 53 gpointer data; 51 54 int fd; 55 char *hostname; 52 56 PRFileDesc *prfd; 53 57 gboolean established; … … 55 59 }; 56 60 57 static gboolean ssl_connected( gpointer data, gint source, b_input_condition cond ); 58 static gboolean ssl_starttls_real( gpointer data, gint source, b_input_condition cond ); 59 60 61 static SECStatus nss_auth_cert (void *arg, PRFileDesc *socket, PRBool checksig, PRBool isserver) 61 static gboolean ssl_connected(gpointer data, gint source, 62 b_input_condition cond); 63 static gboolean ssl_starttls_real(gpointer data, gint source, 64 b_input_condition cond); 65 66 static SECStatus nss_auth_cert(void *arg, PRFileDesc * socket, PRBool checksig, 67 PRBool isserver) 62 68 { 63 69 return SECSuccess; 64 70 } 65 71 66 static SECStatus nss_bad_cert (void *arg, PRFileDesc *socket)72 static SECStatus nss_bad_cert(void *arg, PRFileDesc * socket) 67 73 { 68 74 PRErrorCode err; 69 75 70 if(!arg) return SECFailure; 71 72 *(PRErrorCode *)arg = err = PORT_GetError(); 73 74 switch(err) { 76 if (!arg) 77 return SECFailure; 78 79 *(PRErrorCode *) arg = err = PORT_GetError(); 80 81 switch (err) { 75 82 case SEC_ERROR_INVALID_AVA: 76 83 case SEC_ERROR_INVALID_TIME: … … 94 101 } 95 102 96 97 void ssl_init( void ) 98 { 99 PR_Init( PR_SYSTEM_THREAD, PR_PRIORITY_NORMAL, 1); 103 void ssl_init(void) 104 { 105 PR_Init(PR_SYSTEM_THREAD, PR_PRIORITY_NORMAL, 1); 106 // https://www.mozilla.org/projects/security/pki/nss/ref/ssl/sslfnc.html#1234224 107 // This NSS function is not intended for use with SSL, which 108 // requires that the certificate and key database files be 109 // opened. Relates to whole non-verification of servers for now. 100 110 NSS_NoDB_Init(NULL); 101 111 NSS_SetDomesticPolicy(); … … 103 113 } 104 114 105 void *ssl_connect( char *host, int port, gboolean verify, ssl_input_function func, gpointer data ) 106 { 107 struct scd *conn = g_new0( struct scd, 1 ); 108 109 conn->fd = proxy_connect( host, port, ssl_connected, conn ); 115 void *ssl_connect(char *host, int port, gboolean verify, 116 ssl_input_function func, gpointer data) 117 { 118 struct scd *conn = g_new0(struct scd, 1); 119 120 conn->fd = proxy_connect(host, port, ssl_connected, conn); 110 121 conn->func = func; 111 122 conn->data = data; 112 113 if( conn->fd < 0 ) 114 {115 g_free( conn);116 return( NULL);117 }118 119 if( !initialized ) 120 {123 conn->hostname = g_strdup(host); 124 125 if (conn->fd < 0) { 126 g_free(conn->hostname); 127 g_free(conn); 128 return (NULL); 129 } 130 131 if (!initialized) { 121 132 ssl_init(); 122 133 } 123 134 124 125 return( conn ); 126 } 127 128 static gboolean ssl_starttls_real( gpointer data, gint source, b_input_condition cond)135 return (conn); 136 } 137 138 static gboolean ssl_starttls_real(gpointer data, gint source, 139 b_input_condition cond) 129 140 { 130 141 struct scd *conn = data; 131 142 132 return ssl_connected( conn, conn->fd, B_EV_IO_WRITE ); 133 } 134 135 void *ssl_starttls( int fd, char *hostname, gboolean verify, ssl_input_function func, gpointer data ) 136 { 137 struct scd *conn = g_new0( struct scd, 1 ); 143 return ssl_connected(conn, conn->fd, B_EV_IO_WRITE); 144 } 145 146 void *ssl_starttls(int fd, char *hostname, gboolean verify, 147 ssl_input_function func, gpointer data) 148 { 149 struct scd *conn = g_new0(struct scd, 1); 138 150 139 151 conn->fd = fd; 140 152 conn->func = func; 141 153 conn->data = data; 154 conn->hostname = hostname; 155 156 /* For now, SSL verification is globally enabled by setting the cafile 157 setting in bitlbee.conf. Commented out by default because probably 158 not everyone has this file in the same place and plenty of folks 159 may not have the cert of their private Jabber server in it. */ 142 160 conn->verify = verify && global.conf->cafile; 143 161 … … 151 169 simpler. */ 152 170 153 b_timeout_add( 1, ssl_starttls_real, conn);171 b_timeout_add(1, ssl_starttls_real, conn); 154 172 155 173 return conn; 156 174 } 157 175 158 static gboolean ssl_connected( gpointer data, gint source, b_input_condition cond ) 176 static gboolean ssl_connected(gpointer data, gint source, 177 b_input_condition cond) 159 178 { 160 179 struct scd *conn = data; 161 180 162 181 /* Right now we don't have any verification functionality for NSS. */ 163 182 164 if( conn->verify ) 165 { 166 conn->func( conn->data, 1, NULL, cond ); 167 if( source >= 0 ) closesocket( source ); 168 g_free( conn ); 183 if (conn->verify) { 184 conn->func(conn->data, 1, NULL, cond); 185 if (source >= 0) 186 closesocket(source); 187 g_free(conn->hostname); 188 g_free(conn); 169 189 170 190 return FALSE; 171 191 } 172 173 if ( source == -1)192 193 if (source == -1) 174 194 goto ssl_connected_failure; 175 195 176 196 /* Until we find out how to handle non-blocking I/O with NSS... */ 177 sock_make_blocking( conn->fd);178 197 sock_make_blocking(conn->fd); 198 179 199 conn->prfd = SSL_ImportFD(NULL, PR_ImportTCPSocket(source)); 200 if (!conn->prfd) 201 goto ssl_connected_failure; 180 202 SSL_OptionSet(conn->prfd, SSL_SECURITY, PR_TRUE); 181 203 SSL_OptionSet(conn->prfd, SSL_HANDSHAKE_AS_CLIENT, PR_TRUE); 182 SSL_BadCertHook(conn->prfd, (SSLBadCertHandler)nss_bad_cert, NULL); 183 SSL_AuthCertificateHook(conn->prfd, (SSLAuthCertificate)nss_auth_cert, (void *)CERT_GetDefaultCertDB()); 204 SSL_BadCertHook(conn->prfd, (SSLBadCertHandler) nss_bad_cert, NULL); 205 SSL_AuthCertificateHook(conn->prfd, (SSLAuthCertificate) nss_auth_cert, 206 (void *)CERT_GetDefaultCertDB()); 207 SSL_SetURL(conn->prfd, conn->hostname); 184 208 SSL_ResetHandshake(conn->prfd, PR_FALSE); 185 209 … … 187 211 goto ssl_connected_failure; 188 212 } 189 190 213 191 214 conn->established = TRUE; 192 conn->func( conn->data, 0, conn, cond);215 conn->func(conn->data, 0, conn, cond); 193 216 return FALSE; 194 195 ssl_connected_failure: 196 197 conn->func( conn->data, 0, NULL, cond ); 198 199 PR_Close( conn -> prfd ); 200 if( source >= 0 ) closesocket( source ); 201 g_free( conn ); 202 217 218 ssl_connected_failure: 219 220 conn->func(conn->data, 0, NULL, cond); 221 222 if (conn->prfd) 223 PR_Close(conn->prfd); 224 if (source >= 0) 225 closesocket(source); 226 g_free(conn->hostname); 227 g_free(conn); 228 203 229 return FALSE; 204 230 } 205 231 206 int ssl_read( void *conn, char *buf, int len ) 207 { 208 if( !((struct scd*)conn)->established ) 209 return( 0 ); 210 211 return( PR_Read( ((struct scd*)conn)->prfd, buf, len ) ); 212 } 213 214 int ssl_write( void *conn, const char *buf, int len ) 215 { 216 if( !((struct scd*)conn)->established ) 217 return( 0 ); 218 219 return( PR_Write ( ((struct scd*)conn)->prfd, buf, len ) ); 220 } 221 222 int ssl_pending( void *conn ) 223 { 224 struct scd *c = (struct scd *) conn; 225 226 if( c == NULL ) { 232 int ssl_read(void *conn, char *buf, int len) 233 { 234 int st; 235 PRErrorCode PR_err; 236 237 if (!((struct scd *)conn)->established) { 238 ssl_errno = SSL_NOHANDSHAKE; 239 return -1; 240 } 241 242 st = PR_Read(((struct scd *)conn)->prfd, buf, len); 243 PR_err = PR_GetError(); 244 245 ssl_errno = SSL_OK; 246 if (PR_err == PR_WOULD_BLOCK_ERROR) 247 ssl_errno = SSL_AGAIN; 248 249 if (SSLDEBUG && getenv("BITLBEE_DEBUG") && st > 0) 250 len = write(STDERR_FILENO, buf, st); 251 252 return st; 253 } 254 255 int ssl_write(void *conn, const char *buf, int len) 256 { 257 int st; 258 PRErrorCode PR_err; 259 260 if (!((struct scd *)conn)->established) { 261 ssl_errno = SSL_NOHANDSHAKE; 262 return -1; 263 } 264 st = PR_Write(((struct scd *)conn)->prfd, buf, len); 265 PR_err = PR_GetError(); 266 267 ssl_errno = SSL_OK; 268 if (PR_err == PR_WOULD_BLOCK_ERROR) 269 ssl_errno = SSL_AGAIN; 270 271 if (SSLDEBUG && getenv("BITLBEE_DEBUG") && st > 0) 272 len = write(2, buf, st); 273 274 return st; 275 } 276 277 int ssl_pending(void *conn) 278 { 279 struct scd *c = (struct scd *)conn; 280 281 if (c == NULL) { 227 282 return 0; 228 283 } 229 284 230 return ( c->established && SSL_DataPending( c->prfd ) > 0);231 } 232 233 void ssl_disconnect( void *conn_)285 return (c->established && SSL_DataPending(c->prfd) > 0); 286 } 287 288 void ssl_disconnect(void *conn_) 234 289 { 235 290 struct scd *conn = conn_; 236 237 PR_Close( conn->prfd ); 238 closesocket( conn->fd ); 239 240 g_free( conn ); 241 } 242 243 int ssl_getfd( void *conn ) 244 { 245 return( ((struct scd*)conn)->fd ); 246 } 247 248 b_input_condition ssl_getdirection( void *conn ) 291 292 // When we swich to NSS_Init, we should have here 293 // NSS_Shutdown(); 294 295 if (conn->prfd) 296 PR_Close(conn->prfd); 297 298 g_free(conn->hostname); 299 g_free(conn); 300 } 301 302 int ssl_getfd(void *conn) 303 { 304 return (((struct scd *)conn)->fd); 305 } 306 307 b_input_condition ssl_getdirection(void *conn) 249 308 { 250 309 /* Just in case someone calls us, let's return the most likely case: */ … … 252 311 } 253 312 254 char *ssl_verify_strerror( int code ) 255 { 256 return g_strdup( "SSL certificate verification not supported by BitlBee NSS code." ); 257 } 313 char *ssl_verify_strerror(int code) 314 { 315 return 316 g_strdup 317 ("SSL certificate verification not supported by BitlBee NSS code."); 318 } 319 320 size_t ssl_des3_encrypt(const unsigned char *key, size_t key_len, 321 const unsigned char *input, size_t input_len, 322 const unsigned char *iv, unsigned char **res) 323 { 324 #define CIPHER_MECH CKM_DES3_CBC 325 #define MAX_OUTPUT_LEN 72 326 327 int len1; 328 unsigned int len2; 329 330 PK11Context *ctx = NULL; 331 PK11SlotInfo *slot = NULL; 332 SECItem keyItem; 333 SECItem ivItem; 334 SECItem *secParam = NULL; 335 PK11SymKey *symKey = NULL; 336 337 size_t rc; 338 SECStatus rv; 339 340 if (!initialized) { 341 ssl_init(); 342 } 343 344 keyItem.data = (unsigned char *)key; 345 keyItem.len = key_len; 346 347 slot = PK11_GetBestSlot(CIPHER_MECH, NULL); 348 if (slot == NULL) { 349 fprintf(stderr, "PK11_GetBestSlot failed (err %d)\n", 350 PR_GetError()); 351 rc = 0; 352 goto out; 353 } 354 355 symKey = 356 PK11_ImportSymKey(slot, CIPHER_MECH, PK11_OriginUnwrap, CKA_ENCRYPT, 357 &keyItem, NULL); 358 if (symKey == NULL) { 359 fprintf(stderr, "PK11_ImportSymKey failed (err %d)\n", 360 PR_GetError()); 361 rc = 0; 362 goto out; 363 } 364 365 ivItem.data = (unsigned char *)iv; 366 /* See msn_soap_passport_sso_handle_response in protocols/msn/soap.c */ 367 ivItem.len = 8; 368 369 secParam = PK11_ParamFromIV(CIPHER_MECH, &ivItem); 370 if (secParam == NULL) { 371 fprintf(stderr, "PK11_ParamFromIV failed (err %d)\n", 372 PR_GetError()); 373 rc = 0; 374 goto out; 375 } 376 377 ctx = 378 PK11_CreateContextBySymKey(CIPHER_MECH, CKA_ENCRYPT, symKey, 379 secParam); 380 if (ctx == NULL) { 381 fprintf(stderr, "PK11_CreateContextBySymKey failed (err %d)\n", 382 PR_GetError()); 383 rc = 0; 384 goto out; 385 } 386 387 *res = g_new0(unsigned char, MAX_OUTPUT_LEN); 388 389 rv = PK11_CipherOp(ctx, *res, &len1, MAX_OUTPUT_LEN, 390 (unsigned char *)input, input_len); 391 if (rv != SECSuccess) { 392 fprintf(stderr, "PK11_CipherOp failed (err %d)\n", 393 PR_GetError()); 394 rc = 0; 395 goto out; 396 } 397 398 assert(len1 <= MAX_OUTPUT_LEN); 399 400 rv = PK11_DigestFinal(ctx, *res + len1, &len2, 401 (unsigned int)MAX_OUTPUT_LEN - len1); 402 if (rv != SECSuccess) { 403 fprintf(stderr, "PK11_DigestFinal failed (err %d)\n", 404 PR_GetError()); 405 rc = 0; 406 goto out; 407 } 408 409 rc = len1 + len2; 410 411 out: 412 if (ctx) 413 PK11_DestroyContext(ctx, PR_TRUE); 414 if (symKey) 415 PK11_FreeSymKey(symKey); 416 if (secParam) 417 SECITEM_FreeItem(secParam, PR_TRUE); 418 if (slot) 419 PK11_FreeSlot(slot); 420 421 return rc; 422 }
Note: See TracChangeset
for help on using the changeset viewer.