Esempio n. 1
0
static void
ssl_nss_verified_cb(PurpleCertificateVerificationStatus st,
		       gpointer userdata)
{
	PurpleSslConnection *gsc = (PurpleSslConnection *) userdata;

	if (st == PURPLE_CERTIFICATE_VALID) {
		/* Certificate valid? Good! Do the connection! */
		gsc->connect_cb(gsc->connect_cb_data, gsc, PURPLE_INPUT_READ);
	} else {
		/* Otherwise, signal an error */
		if(gsc->error_cb != NULL)
			gsc->error_cb(gsc, PURPLE_SSL_CERTIFICATE_INVALID,
				      gsc->connect_cb_data);
		purple_ssl_close(gsc);
	}
}
Esempio n. 2
0
/*
 * ssl_openssl_handshake_cb
 */
static void
ssl_openssl_handshake_cb(gpointer data, gint source, PurpleInputCondition cond)
{
	PurpleSslConnection *gsc = (PurpleSslConnection *)data;
	PurpleSslOpensslData *openssl_data = PURPLE_SSL_OPENSSL_DATA(gsc);
	int ret, ret2;

	purple_debug_info("openssl", "Connecting to %s\n", gsc->host);

	/*
	 * do the negotiation that sets up the SSL connection between
	 * here and there.
	 */
	ret = SSL_connect(openssl_data->ssl);
	if (ret <= 0) {
		ret2 = SSL_get_error(openssl_data->ssl, ret);

		if (ret2 == SSL_ERROR_WANT_READ || ret2 == SSL_ERROR_WANT_WRITE)
			return;

		purple_debug_error("openssl", "SSL_connect failed: %d\n",
		    ret2);

		if (gsc->error_cb != NULL)
			gsc->error_cb(gsc, PURPLE_SSL_HANDSHAKE_FAILED,
				gsc->connect_cb_data);

		purple_ssl_close(gsc);
		return;
	}

	purple_input_remove(openssl_data->handshake_handler);
	openssl_data->handshake_handler = 0;

	purple_debug_info("openssl", "Connected to %s\n", gsc->host);

	/* SSL connected now */
	gsc->connect_cb(gsc->connect_cb_data, gsc, cond);
}
Esempio n. 3
0
/*
 * ssl_cdsa_handshake_cb
 */
static void
ssl_cdsa_handshake_cb(gpointer data, gint source, PurpleInputCondition cond)
{
	PurpleSslConnection *gsc = (PurpleSslConnection *)data;
	PurpleAccount *account = gsc->account;
	PurpleSslCDSAData *cdsa_data = PURPLE_SSL_CDSA_DATA(gsc);
    OSStatus err;
	
	purple_debug_info("cdsa", "Connecting\n");
	
	/*
	 * do the negotiation that sets up the SSL connection between
	 * here and there.
	 */
	err = SSLHandshake(cdsa_data->ssl_ctx);
    if (err == errSSLPeerBadRecordMac
		&& !purple_account_get_bool(account, PURPLE_SSL_CDSA_BUGGY_TLS_WORKAROUND, false)
		&& !strcmp(purple_account_get_protocol_id(account),"prpl-jabber")) {
        /*
         * Set a flag so we know to explicitly disable TLS 1.1 and 1.2 on our next (immediate) connection attempt for this account.
         * Some XMPP servers use buggy TLS stacks that incorrectly report their capabilities, which breaks things with 10.8's new support
         * for TLS 1.1 and 1.2.
         */
        purple_debug_info("cdsa", "SSLHandshake reported that the server rejected our MAC, which most likely means it lied about the TLS versions it supports.");
        purple_debug_info("cdsa", "Setting a flag in this account to only use TLS 1.0 and below on the next connection attempt.");
    
        purple_account_set_bool(account, PURPLE_SSL_CDSA_BUGGY_TLS_WORKAROUND, true);
        if (gsc->error_cb != NULL)
            gsc->error_cb(gsc, PURPLE_SSL_HANDSHAKE_FAILED, gsc->connect_cb_data);
        purple_ssl_close(gsc);
        return;
    } else if (err != noErr) {
		if(err == errSSLWouldBlock)
			return;
		fprintf(stderr,"cdsa: SSLHandshake failed with error %d\n",(int)err);
		purple_debug_error("cdsa", "SSLHandshake failed with error %d\n",(int)err);
		if (gsc->error_cb != NULL)
			gsc->error_cb(gsc, PURPLE_SSL_HANDSHAKE_FAILED,
						  gsc->connect_cb_data);
		
		purple_ssl_close(gsc);
		return;
	}
	
	SSLCipherSuite cipher;
	SSLProtocol protocol;
	
	err = SSLGetNegotiatedCipher(cdsa_data->ssl_ctx, &cipher);
	
	if (err == noErr) {
		err = SSLGetNegotiatedProtocolVersion(cdsa_data->ssl_ctx, &protocol);
		
		purple_debug_info("cdsa", "Your connection is using %s with %s encryption, using %s for message authentication and %s key exchange (%X).\n",
						  SSLVersionToString(protocol),
						  SSLCipherName(cipher),
						  SSLMACName(cipher),
						  SSLKeyExchangeName(cipher),
						  cipher);
	}
	
	purple_input_remove(cdsa_data->handshake_handler);
	cdsa_data->handshake_handler = 0;
	
	purple_debug_info("cdsa", "SSL_connect: verifying certificate\n");
	
	if(certificate_ui_cb) { // does the application want to verify the certificate?
		struct query_cert_userdata *userdata = (struct query_cert_userdata*)malloc(sizeof(struct query_cert_userdata));
		size_t hostnamelen = 0;
		
		SSLGetPeerDomainNameLength(cdsa_data->ssl_ctx, &hostnamelen);
		userdata->hostname = (char*)malloc(hostnamelen+1);
		SSLGetPeerDomainName(cdsa_data->ssl_ctx, userdata->hostname, &hostnamelen);
		userdata->hostname[hostnamelen] = '\0'; // just make sure it's zero-terminated
		userdata->cond = cond;
		userdata->gsc = gsc;
		SSLCopyPeerCertificates(cdsa_data->ssl_ctx, &userdata->certs);
		
		certificate_ui_cb(gsc, userdata->hostname, userdata->certs, query_cert_result, userdata);
	} else {
		purple_debug_info("cdsa", "SSL_connect complete (did not verify certificate)\n");
		
		/* SSL connected now */
		gsc->connect_cb(gsc->connect_cb_data, gsc, cond);
	}
	
	SSLCipherSuite suite;
	SSLGetNegotiatedCipher(cdsa_data->ssl_ctx, &suite);
	
	purple_debug_info("cdsa", "Using cipher %x.\n", suite);
}
Esempio n. 4
0
static void ssl_gnutls_handshake_cb(gpointer data, gint source,
		PurpleInputCondition cond)
{
	PurpleSslConnection *gsc = data;
	PurpleSslGnutlsData *gnutls_data = PURPLE_SSL_GNUTLS_DATA(gsc);
	ssize_t ret;

	/*purple_debug_info("gnutls", "Handshaking with %s\n", gsc->host);*/
	ret = gnutls_handshake(gnutls_data->session);

	if(ret == GNUTLS_E_AGAIN || ret == GNUTLS_E_INTERRUPTED)
		return;

	purple_input_remove(gnutls_data->handshake_handler);
	gnutls_data->handshake_handler = 0;

	if(ret != 0) {
		purple_debug_error("gnutls", "Handshake failed. Error %s\n",
			gnutls_strerror(ret));

		if(gsc->error_cb != NULL)
			gsc->error_cb(gsc, PURPLE_SSL_HANDSHAKE_FAILED,
				gsc->connect_cb_data);

		purple_ssl_close(gsc);
	} else {
		/* Now we are cooking with gas! */
		PurpleSslOps *ops = purple_ssl_get_ops();
		GList * peers = ops->get_peer_certificates(gsc);

		PurpleCertificateScheme *x509 =
			purple_certificate_find_scheme("x509");

		GList * l;

		/* TODO: Remove all this debugging babble */
		purple_debug_info("gnutls", "Handshake complete\n");

		for (l=peers; l; l = l->next) {
			PurpleCertificate *crt = l->data;
			GByteArray *z =
				x509->get_fingerprint_sha1(crt);
			gchar * fpr =
				purple_base16_encode_chunked(z->data,
							     z->len);

			purple_debug_info("gnutls/x509",
					  "Key print: %s\n",
					  fpr);

			/* Kill the cert! */
			x509->destroy_certificate(crt);

			g_free(fpr);
			g_byte_array_free(z, TRUE);
		}
		g_list_free(peers);

		{
			const gnutls_datum_t *cert_list;
			unsigned int cert_list_size = 0;
			gnutls_session_t session=gnutls_data->session;
			guint i;

			cert_list =
				gnutls_certificate_get_peers(session, &cert_list_size);

			purple_debug_info("gnutls",
					    "Peer provided %d certs\n",
					    cert_list_size);
			for (i=0; i<cert_list_size; i++)
			{
				gchar fpr_bin[256];
				gsize fpr_bin_sz = sizeof(fpr_bin);
				gchar * fpr_asc = NULL;
				gchar tbuf[256];
				gsize tsz=sizeof(tbuf);
				gchar * tasc = NULL;
				gnutls_x509_crt_t cert;

				gnutls_x509_crt_init(&cert);
				gnutls_x509_crt_import (cert, &cert_list[i],
						GNUTLS_X509_FMT_DER);

				gnutls_x509_crt_get_fingerprint(cert, GNUTLS_DIG_SHA,
						fpr_bin, &fpr_bin_sz);

				fpr_asc =
						purple_base16_encode_chunked((const guchar *)fpr_bin, fpr_bin_sz);

				purple_debug_info("gnutls",
						"Lvl %d SHA1 fingerprint: %s\n",
						i, fpr_asc);

				tsz=sizeof(tbuf);
				gnutls_x509_crt_get_serial(cert,tbuf,&tsz);
				tasc=purple_base16_encode_chunked((const guchar *)tbuf, tsz);
				purple_debug_info("gnutls",
						"Serial: %s\n",
						tasc);
				g_free(tasc);

				tsz=sizeof(tbuf);
				gnutls_x509_crt_get_dn (cert, tbuf, &tsz);
				purple_debug_info("gnutls",
						"Cert DN: %s\n",
						tbuf);
				tsz=sizeof(tbuf);
				gnutls_x509_crt_get_issuer_dn (cert, tbuf, &tsz);
				purple_debug_info("gnutls",
						"Cert Issuer DN: %s\n",
						tbuf);

				g_free(fpr_asc);
				fpr_asc = NULL;
				gnutls_x509_crt_deinit(cert);
			}
		}

		/* TODO: The following logic should really be in libpurple */
		/* If a Verifier was given, hand control over to it */
		if (gsc->verifier) {
			GList *peers;
			/* First, get the peer cert chain */
			peers = purple_ssl_get_peer_certificates(gsc);

			/* Now kick off the verification process */
			purple_certificate_verify(gsc->verifier,
						  gsc->host,
						  peers,
						  ssl_gnutls_verified_cb,
						  gsc);

			purple_certificate_destroy_list(peers);
		} else {
			/* Otherwise, just call the "connection complete"
			   callback */
			gsc->connect_cb(gsc->connect_cb_data, gsc, cond);
		}
	}

}