Package: release.debian.org
Severity: normal
Tags: buster
User: release.debian....@packages.debian.org
Usertags: pu

Hi,

I would like to update erlang-p1-pkix in Buster to fix a regression in
ejabberd, prohibiting the use of GnuTLS certificates.

The patch is directly from upstream [1] and will also be part of the next
upload to unstable. To keep changes minimal I stripped the tests and
example certificates added with that commit.

The resulting package has been successfully tested in real life.

The full diff is attached.

[1] 
https://github.com/processone/pkix/commit/2d7a3b80bf6fc0794720aca852e487a5064d8b86
diff --git a/debian/changelog b/debian/changelog
index 772931a..f7f2286 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,3 +1,9 @@
+erlang-p1-pkix (1.0.0-3+deb10u1) buster; urgency=medium
+
+  * Added upstream patch to fix handling of GnuTLS certificates
+
+ -- Philipp Huebner <debala...@debian.org>  Thu, 01 Aug 2019 11:34:25 +0200
+
 erlang-p1-pkix (1.0.0-3) unstable; urgency=medium
 
   * Updated debian/copyright
diff --git a/debian/patches/2d7a3b80bf6fc0794720aca852e487a5064d8b86.patch 
b/debian/patches/2d7a3b80bf6fc0794720aca852e487a5064d8b86.patch
new file mode 100644
index 0000000..fe1ef43
--- /dev/null
+++ b/debian/patches/2d7a3b80bf6fc0794720aca852e487a5064d8b86.patch
@@ -0,0 +1,109 @@
+From 2d7a3b80bf6fc0794720aca852e487a5064d8b86 Mon Sep 17 00:00:00 2001
+From: Evgeny Khramtsov <ekhramt...@process-one.net>
+Date: Thu, 1 Aug 2019 12:23:48 +0300
+Subject: [PATCH] Use original DER during certification path validation
+
+Index: erlang-p1-pkix/src/pkix.erl
+===================================================================
+--- erlang-p1-pkix.orig/src/pkix.erl
++++ erlang-p1-pkix/src/pkix.erl
+@@ -35,7 +35,8 @@
+ -define(CERTFILE_TAB, pkix_certfiles).
+
+ -record(pem, {file :: filename(),
+-            line :: pos_integer()}).
++            line :: pos_integer(),
++            der  :: binary()}).
+
+ -record(state, {files = #{}      :: map(),
+               certs = #{}      :: map(),
+@@ -437,9 +438,9 @@ pem_decode(Fd, Line, Begin, Buf) ->
+ -spec pem_decode_entries([{pos_integer(), binary()}], filename(),
+                        map(), map()) -> {ok, map(), map()} | {error, 
bad_cert_error()}.
+ pem_decode_entries([{Begin, Data}|PEMs], File, Certs, PrivKeys) ->
+-    P = #pem{file = File, line = Begin},
+     try public_key:pem_decode(Data) of
+-      [PemEntry] ->
++      [{_, DER, _} = PemEntry] ->
++          P = #pem{file = File, der = DER, line = Begin},
+           try der_decode(PemEntry) of
+               undefined ->
+                   pem_decode_entries(PEMs, File, Certs, PrivKeys);
+@@ -510,7 +511,7 @@ der_decode({_, _, _}) ->
+            {error, filename() | dirname(), io_error()}.
+ commit(State, Dir, CAFile, ValidateHow) ->
+     {Chains, BadCertsWithReason, UnusedKeysWithReason} = build_chains(State),
+-    {CAError, InvalidCertsWithReason} = validate(Chains, CAFile, ValidateHow),
++    {CAError, InvalidCertsWithReason} = validate(State, Chains, CAFile, 
ValidateHow),
+     InvalidCerts = [C || {C, _} <- InvalidCertsWithReason],
+     SortedChains = case ValidateHow of
+                      hard when CAError == undefined ->
+@@ -730,8 +731,7 @@ store_chain(Chain, Dir, State) ->
+ pem_encode({Certs, Key}, State) ->
+     PEM1 = lists:map(
+            fun(Cert) ->
+-                   Type = element(1, Cert),
+-                   DER = public_key:pkix_encode(Type, Cert, otp),
++                   DER = get_der(Cert, State#state.certs),
+                    PemEntry = {'Certificate', DER, not_encrypted},
+                    Source = lists:map(
+                               fun(#pem{file = File, line = Line}) ->
+@@ -742,11 +742,14 @@ pem_encode({Certs, Key}, State) ->
+     PEM2 = [[io_lib:format("From ~s:~B~n", [File, Line])
+            || #pem{file = File, line = Line} <- maps:get(Key, 
State#state.keys)],
+           public_key:pem_encode(
+-            [{element(1, Key),
+-              public_key:der_encode(element(1, Key), Key),
+-              not_encrypted}])],
++            [{element(1, Key), get_der(Key, State#state.keys), 
not_encrypted}])],
+     iolist_to_binary([PEM1, PEM2]).
+
++-spec get_der(cert() | priv_key(), map()) -> binary().
++get_der(Key, Map) ->
++    [#pem{der = DER}|_] = maps:get(Key, Map),
++    DER.
++
+ %%%===================================================================
+ %%% Domains extraction
+ %%%===================================================================
+@@ -850,12 +853,12 @@ get_cert_path(G, [Root|_] = Acc) ->
+ %%%===================================================================
+ %%% Certificates chain validation
+ %%%===================================================================
+--spec validate([cert_chain()], filename(), false | soft | hard) ->
++-spec validate(state(), [cert_chain()], filename(), false | soft | hard) ->
+              {undefined | {filename(), bad_cert_error() | io_error()},
+               [{cert(), invalid_cert_reason()}]}.
+-validate(_Chains, _CAFile, false) ->
++validate(_State, _Chains, _CAFile, false) ->
+     {undefined, []};
+-validate(Chains, CAFile, _) ->
++validate(State, Chains, CAFile, _) ->
+     {CAError, IssuerCerts} = case pem_decode_file(CAFile) of
+                                {error, Why} ->
+                                    {{CAFile, Why}, []};
+@@ -866,7 +869,7 @@ validate(Chains, CAFile, _) ->
+      lists:filtermap(
+        fun({Certs, _PrivKey}) ->
+              RevCerts = lists:reverse(Certs),
+-             case validate_path(RevCerts, IssuerCerts) of
++             case validate_path(State, RevCerts, IssuerCerts) of
+                  ok ->
+                      false;
+                  {error, Reason} ->
+@@ -874,11 +877,12 @@ validate(Chains, CAFile, _) ->
+              end
+        end, Chains)}.
+
+--spec validate_path([cert()], [cert()]) -> ok | {error, 
invalid_cert_reason()}.
+-validate_path([Cert|_] = Certs, IssuerCerts) ->
++-spec validate_path(state(), [cert()], [cert()]) -> ok | {error, 
invalid_cert_reason()}.
++validate_path(State, [Cert|_] = Certs, IssuerCerts) ->
+     case find_issuer_cert(Cert, IssuerCerts) of
+       {ok, IssuerCert} ->
+-          case public_key:pkix_path_validation(IssuerCert, Certs, []) of
++          DERs = [get_der(C, State#state.certs) || C <- Certs],
++          case public_key:pkix_path_validation(IssuerCert, DERs, []) of
+               {ok, _} ->
+                   ok;
+               {error, {bad_cert, Reason}} ->
diff --git a/debian/patches/series b/debian/patches/series
new file mode 100644
index 0000000..568471b
--- /dev/null
+++ b/debian/patches/series
@@ -0,0 +1 @@
+2d7a3b80bf6fc0794720aca852e487a5064d8b86.patch

Reply via email to