Skip to content
This repository has been archived by the owner on Nov 7, 2019. It is now read-only.

Commit

Permalink
Fixes in exmpp_tls:get_peer_certificate/1 (thanks to Janusz Dziemidow…
Browse files Browse the repository at this point in the history
…icz)(EXMPP-59)

Fixes:
- compatibility with R14
- fixed case of no certificate
- documentation update
  • Loading branch information
badlop committed Aug 16, 2011
1 parent dc6c7f3 commit ac56aa1
Show file tree
Hide file tree
Showing 2 changed files with 32 additions and 14 deletions.
11 changes: 4 additions & 7 deletions c_src/exmpp_tls_openssl.c
Original file line number Diff line number Diff line change
Expand Up @@ -401,19 +401,16 @@ exmpp_tls_openssl_control(ErlDrvData drv_data, unsigned int command,
case COMMAND_GET_PEER_CERTIFICATE:
/* Get the peer certificate. */
cert = SSL_get_peer_certificate(edd->ssl);
if (cert == NULL) {
if (cert == NULL || (rlen = i2d_X509(cert, NULL)) < 0) {
to_send = exmpp_new_xbuf();
if (to_send == NULL)
return (-1);
ei_x_encode_atom(to_send, "no_certificate");

COPY_AND_FREE_BUF(to_send, size, b, RET_ERROR);
}

/* Calculate the size of the certificate. */
rlen = i2d_X509(cert, NULL);
if (rlen < 0) {
X509_free(cert);
if (cert != NULL) {
X509_free(cert);
}
break;
}

Expand Down
35 changes: 28 additions & 7 deletions src/core/exmpp_tls.erl
Original file line number Diff line number Diff line change
Expand Up @@ -434,20 +434,41 @@ handshake2(server = Mode, Socket_Desc, Port, Recv_Timeout) ->

%% @spec (TLS_Socket) -> Certificate | undefined
%% TLS_Socket = tls_socket()
%% Certificate = binary()
%% Certificate = certificate()
%% Reason = term()
%% @throws {tls, peer_certificate, decode_failed, Reason}
%% @doc Return the peer certificate if he provided one.
%%
%% Note that a client will only send a certificate when requested by a server.
%% This means that in the server case, this function will return anything
%% only when peer verification is enabled.
%%
%% Certificate is returned as a
%% <a href="http://erlang.org/doc/apps/public_key/cert_records.html">
%% public_key certificate record</a>.

get_peer_certificate(#tls_socket{port = Port}) ->
case engine_get_peer_certificate(Port) of
undefined ->
undefined;
Bin_Cert ->
case public_key:pkix_decode_cert(Bin_Cert, plain) of
{ok, Cert} ->
Cert;
{error, Reason} ->
throw({tls, peer_certificate, decode_failed, Reason})
end
try
case public_key:pkix_decode_cert(Bin_Cert, plain) of
{ok, Cert} ->
%% R13 and earlier
Cert;
{error, Reason} ->
%% R13 and earlier
throw({tls, peer_certificate, decode_failed, Reason});
Certificate ->
%% starting from R14, pkix_decode_cert/2 simply returns
%% decoded certificate and uses erlang:error/1 for errors
Certificate
end
catch
_:Exception ->
throw({tls, peer_certificate, decode_failed, Exception})
end
end.

%% @spec (TLS_Socket) -> Result
Expand Down

0 comments on commit ac56aa1

Please sign in to comment.