我使用 libmesode(fork libstrophe)开发了一个 xmpp 客户端。我想通过认证来确保身份验证。服务器端有一个证书 server.pem 客户端有它的证书 client.pem
在 lidmesode 中用于检查证书的函数:
tls_t *tls_new(xmpp_ctx_t *ctx, sock_t sock, xmpp_certfail_handler certfail_handler, char *tls_cert_path)
{
_xmppctx = ctx;
_certfail_handler = certfail_handler;
_cert_handled = 0;
_last_cb_res = 0;
tls_t *tls = xmpp_alloc(ctx, sizeof(*tls));
if (tls) {
int ret;
memset(tls, 0, sizeof(*tls));
tls->ctx = ctx;
tls->sock = sock;
tls->ssl_ctx = SSL_CTX_new(SSLv23_client_method());
if (tls->ssl_ctx == NULL)
goto err;
SSL_CTX_set_client_cert_cb(tls->ssl_ctx, NULL);
SSL_CTX_set_mode(tls->ssl_ctx, SSL_MODE_ENABLE_PARTIAL_WRITE);
SSL_CTX_set_verify(tls->ssl_ctx, SSL_VERIFY_PEER, verify_callback);
if (tls_cert_path) {
SSL_CTX_load_verify_locations(tls->ssl_ctx, NULL, tls_cert_path);
//SSL_CTX_use_certificate_file(tls->ssl_ctx, certif, SSL_FILETYPE_PEM);
}
tls->ssl = SSL_new(tls->ssl_ctx);
if (tls->ssl == NULL)
goto err_free_ctx;
ret = SSL_set_fd(tls->ssl, sock);
if (ret <= 0)
goto err_free_ssl;
}
return tls;
err_free_ssl:
SSL_free(tls->ssl);
err_free_ctx:
SSL_CTX_free(tls->ssl_ctx);
err:
xmpp_free(ctx, tls);
_tls_log_error(ctx);
return NULL;
}
static int
verify_callback(int preverify_ok, X509_STORE_CTX *x509_ctx)
{
const STACK_OF(X509) *sk = X509_STORE_CTX_get1_chain(x509_ctx);
int slen = sk_X509_num(sk);
unsigned i;
X509 *certsk;
xmpp_debug(_xmppctx, "TLS", "STACK");
for(i=0; i<slen; i++) {
certsk = sk_X509_value(sk, i);
_print_certificate(certsk);
}
xmpp_debug(_xmppctx, "TLS", "ENDSTACK");
if (preverify_ok) {
sk_X509_pop_free(sk, X509_free);
printf("=========> 1\n");
return 1;
} else if (_cert_handled) {
if (_last_cb_res == 0) {
X509_STORE_CTX_set_error(x509_ctx, X509_V_ERR_APPLICATION_VERIFICATION);
}
sk_X509_pop_free(sk, X509_free);
return _last_cb_res;
} else {
int err = X509_STORE_CTX_get_error(x509_ctx);
const char *errstr = X509_verify_cert_error_string(err);
xmpp_debug(_xmppctx, "TLS", "ERROR: %s", errstr);
X509 *user_cert = sk_X509_value(sk, 0);
struct _tlscert_t *tlscert = _x509_to_tlscert(_xmppctx, user_cert);
int cb_res = 0;
if (_certfail_handler) {
cb_res = _certfail_handler(tlscert, errstr);
}
xmpp_conn_free_tlscert(_xmppctx, tlscert);
_cert_handled = 1;
_last_cb_res = cb_res;
if (cb_res == 0) {
X509_STORE_CTX_set_error(x509_ctx, X509_V_ERR_APPLICATION_VERIFICATION);
}
sk_X509_pop_free(sk, X509_free);
return cb_res;
}
}
当 xmpp 客户端使用 TLS 连接到 ejabbed xmpp 服务器时,openssl 检查自签名但继续连接的服务器证书!!。第二件事是:openssl 不使用客户端证书检查服务器证书以检查服务器证书是否受信任。
openssl 做这些检查吗?
1)如果自签名证书断开连接
2)检查证书是否可信。
以下捕获显示服务器发送证书,然后客户端发送密钥。
就是这个key应该取自客户端认证!