Merge ~paelzer/ubuntu/+source/apache2:eoan-bug-1830728-keys-from-pkcs into ubuntu/+source/apache2:ubuntu/eoan-devel

Proposed by Christian Ehrhardt 
Status: Work in progress
Proposed branch: ~paelzer/ubuntu/+source/apache2:eoan-bug-1830728-keys-from-pkcs
Merge into: ubuntu/+source/apache2:ubuntu/eoan-devel
Diff against target: 764 lines (+730/-0)
5 files modified
debian/changelog (+7/-0)
debian/patches/series (+3/-0)
debian/patches/ubuntu/lp-1830728-Hook-up-PKCS-11-PIN-entry-through-configured-passphr.patch (+328/-0)
debian/patches/ubuntu/lp-1830728-mod_ssl-Add-support-for-loading-TLS-certificates-thr.patch (+207/-0)
debian/patches/ubuntu/lp-1830728-mod_ssl-Add-support-for-loading-private-keys-from-EN.patch (+185/-0)
Reviewer Review Type Date Requested Status
Canonical Server Pending
Canonical Server packageset reviewers Pending
git-ubuntu developers Pending
Review via email: mp+370701@code.launchpad.net
To post a comment you must log in.
Revision history for this message
Christian Ehrhardt  (paelzer) wrote :

This is WIP for now as we still need to find how to carry the doc changes properly into 2.4.x
Upstream changes XML files which are no more bundled (or not exiting in 2.4) in our tarball.
The HTML files in the tarball are the usual "do not edit this is generated" style so I'll need to check where to correctly add the doc changes.

But for now the PPA is enough for IBM to evaluate if this is even what they want (before spending more on the docs).

Revision history for this message
Dimitri John Ledkov (xnox) wrote :

What's the status of said evaluation?

Unmerged commits

0db4573... by Christian Ehrhardt 

changelog: support loading private keys via PKCS#11 token (LP: #1830728)

Signed-off-by: Christian Ehrhardt <email address hidden>

e93ffde... by Christian Ehrhardt 

d/p/ubuntu/lp-1830728-*: support loading private keys via PKCS#11 token (LP: #1830728)

Signed-off-by: Christian Ehrhardt <email address hidden>

5a4aa4d... by Dimitri John Ledkov

Import patches-unapplied version 2.4.38-3ubuntu2 to ubuntu/eoan-proposed

Imported using git-ubuntu import.

Changelog parent: e936130b355fd0cbf58c47c7cd36cf3a0d49a6fb

New changelog entries:
  * Cherrypick upstream test suite fix for buffer.

e936130... by Dimitri John Ledkov

Import patches-unapplied version 2.4.38-3ubuntu1 to ubuntu/eoan-proposed

Imported using git-ubuntu import.

Changelog parent: 6f896d33242900b08c8788338c9e90e23713055c

New changelog entries:
  * Merge from Debian unstable. Remaining changes:
    - Cherrypick upstream testsuite fix:
      + r1850941 Skip tests for TLSv1.3 (where there is no "renegotiation"
      as such).
    - Similarly use TLSv1.2 for pr12355 and pr43738.
    - debian/{control, apache2.install, apache2-utils.ufw.profile,
      apache2.dirs}: Add ufw profiles.
    - debian/apache2.py, debian/apache2-bin.install: Add apport hook.
    - debian/patches/086_svn_cross_compiles: Backport several cross
      fixes from upstream
      [Removed configure chunk, not needed since configure.in is being
       patched.]
    - d/index.html, d/icons/ubuntu-logo.png, d/apache2.postrm: replace
      Debian with Ubuntu on default page.
      + d/source/include-binaries: add Ubuntu icon file
    - d/t/control, d/t/check-http2: add basic test for http2 support

6f896d3... by Stefan Fritsch

Import patches-unapplied version 2.4.38-3 to debian/sid

Imported using git-ubuntu import.

Changelog parent: 847b2dd6c945b42d4b49bbc8fbb24a7dd4fc4897

New changelog entries:
  [ Marc Deslauriers ]
  * SECURITY UPDATE: read-after-free on a string compare in mod_http2
    - debian/patches/CVE-2019-0196.patch: disentangelment of stream and
      request method in modules/http2/h2_request.c.
    - CVE-2019-0196
  * SECURITY UPDATE: privilege escalation from modules' scripts
    - debian/patches/CVE-2019-0211.patch: bind the bucket number of each
      child to its slot number in include/scoreboard.h,
      server/mpm/event/event.c, server/mpm/prefork/prefork.c,
      server/mpm/worker/worker.c.
    - CVE-2019-0211
  * SECURITY UPDATE: mod_ssl access control bypass
    - debian/patches/CVE-2019-0215.patch: restore SSL verify state after
      PHA failure in TLSv1.3 in modules/ssl/ssl_engine_kernel.c.
    - CVE-2019-0215
  * SECURITY UPDATE: mod_auth_digest access control bypass
    - debian/patches/CVE-2019-0217.patch: fix a race condition in
      modules/aaa/mod_auth_digest.c.
    - CVE-2019-0217
  * SECURITY UPDATE: URL normalization inconsistincy
    - debian/patches/CVE-2019-0220-1.patch: merge consecutive slashes in
      the path in include/http_core.h, include/httpd.h, server/core.c,
      server/request.c, server/util.c.
    - debian/patches/CVE-2019-0220-2.patch: fix r->parsed_uri.path safety
      in server/request.c, server/util.c.
    - debian/patches/CVE-2019-0220-3.patch: maintainer mode fix in
      server/util.c.
    - CVE-2019-0220
  [ Stefan Fritsch ]
  * Pull security fixes from 2.4.39 via Ubuntu
  * CVE-2019-0197: mod_http2: Fix possible crash on late upgrade

847b2dd... by Xavier Guimard <email address hidden>

Import patches-unapplied version 2.4.38-2 to debian/sid

Imported using git-ubuntu import.

Changelog parent: 9da9dfa1e43b5d69d2783d1a3e1a5b6dcde606c1

New changelog entries:
  * Disable "reset" test in allowmethods.t (Closes: #921024)

9da9dfa... by Xavier Guimard <email address hidden>

Import patches-unapplied version 2.4.38-1 to debian/sid

Imported using git-ubuntu import.

Changelog parent: 7387d718ca26d92498f9ed1584fea8cbcb4f704e

New changelog entries:
  [ Jelmer Vernooij ]
  * Reverted for now: Transition to automatic debug package (from: apache2-dbg)
  * Trim trailing whitespace
  * Use secure copyright file specification URI
  [ Niels Thykier ]
  * Add Rules-Requires-Root: binary-targets
  [ Xavier Guimard ]
  * Convert signing-key.pgp into signing-key.asc
  * Add http2.conf (Closes: #880993)
  * Remove unnecessary greater-than versioned dependency to dpkg-dev,
    libbrotli-dev and libapache2-mod-md
  * Declare compliance with policy 4.2.1
  * Add spelling errors patch (reported)
  * Fix some spelling errors in debian files
  * Add myself to uploaders
  * Refresh patches
  * Bump debhelper compatibility level to 10
  * debian/rules:
    - Remove unnecessary dh argument --parallel
    - use /usr/share/dpkg/pkg-info.mk instead of dpkg-parsechangelog
  * Add upstream/metadata
  * Replace MIT by Expat in debian/copyright
  * debian/watch: use https url
  * Add documentation links in systemd service files
  * Team upload
  [ Cyrille Bollu ]
  * Put HTTP2 configuration within <IfModule !mpm_prefork></IfModule> tags as
    it gets automatically de-activated upon apache 'startup when using
    mpm_prefork.
  * Updated http2.conf to inform user that they may want to change their
    LogFormat directives.
  [ Xavier Guimard ]
  * New upstream version 2.4.38 (Closes: #920220, #920302, #920303)
  * Refresh patches
  * Remove setenvifexpr.diff patch now included in upstream
  * Replace libapache2-mod-proxy-uwsgi.{post*,prerm} by a maintscript
  * Add a "sleep" in debian/tests/htcacheclean and skip result if "stop" failed
  * Declare compliance with policy 4.3.0
  * Fix homepage to https
  * Update debian/copyright

7387d71... by Stefan Fritsch

Import patches-unapplied version 2.4.37-1 to debian/sid

Imported using git-ubuntu import.

Changelog parent: bf7f8f045ccf34c2c08f02ecdd0f46ef7a97ee46

New changelog entries:
  * New upstream version
    - mod_ssl: Add support for TLSv1.3
  * Add docs symlink for libapache2-mod-proxy-uwsgi. Closes: #910218
  * Update test-framework to r1845652
  * Fix test suite to actually run by creating a test user. It turns out
    the test suite refuses to run as root but returns true even in that
    case. It seems this has been broken since 2.4.27-4, where the test suite
    had been updated and the debci test duration dropped from 15min to
    3min. Also, don't rely on the exit status anymore but parse the test
    output.
  * Backport a fix from trunk for SetEnvIfExpr. This fixes a test failure.

bf7f8f0... by Stefan Fritsch

Import patches-unapplied version 2.4.35-1 to debian/sid

Imported using git-ubuntu import.

Changelog parent: ef5d2450201d96722e86ff11a816bf14e3b9cfca

New changelog entries:
  * New upstream version 2.4.35
    Security fix:
    - CVE-2018-11763: DoS for HTTP/2 connections by continuous SETTINGS
      Closes: #909591
  * Fix lintian warning: Don't force xz in builddeb override.

ef5d245... by Stefan Fritsch

Import patches-unapplied version 2.4.34-1 to debian/sid

Imported using git-ubuntu import.

Changelog parent: f9135dfca55cef91c3af3074fc3ba3826d3f95d8

New changelog entries:
  [ Ondřej Surý ]
  * New upstream version 2.4.34
    Security fixes:
    - CVE-2018-1333: Denial of service in mod_http2. Closes: #904106
    - CVE-2018-8011: Denial of service in mod_md. Closes: #904107
  * Refresh patches for Apache2 2.4.34 release
  * Update the suexec-custom.patch for 2.4.34 release
  [ Stefan Fritsch ]
  * Remove load order dependency introduced in mod_lbmethod_* in 2.4.34
  * Remove debian/gbp.conf. Closes: #904641
  * Fix typo in apache2_switch_mpm() in apache2-maintscript-helper.
    Closes: #904150

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1diff --git a/debian/changelog b/debian/changelog
2index 24b7788..9c74c1b 100644
3--- a/debian/changelog
4+++ b/debian/changelog
5@@ -1,3 +1,10 @@
6+apache2 (2.4.38-3ubuntu3) eoan; urgency=medium
7+
8+ * d/p/ubuntu/lp-1830728-*: support loading private keys via PKCS#11
9+ token (LP: #1830728)
10+
11+ -- Christian Ehrhardt <christian.ehrhardt@canonical.com> Mon, 29 Jul 2019 08:52:19 +0200
12+
13 apache2 (2.4.38-3ubuntu2) eoan; urgency=medium
14
15 * Cherrypick upstream test suite fix for buffer.
16diff --git a/debian/patches/series b/debian/patches/series
17index b570181..f11f226 100644
18--- a/debian/patches/series
19+++ b/debian/patches/series
20@@ -20,3 +20,6 @@ CVE-2019-0197.patch
21
22 # Patches added by Ubuntu
23 086_svn_cross_compiles
24+ubuntu/lp-1830728-mod_ssl-Add-support-for-loading-private-keys-from-EN.patch
25+ubuntu/lp-1830728-mod_ssl-Add-support-for-loading-TLS-certificates-thr.patch
26+ubuntu/lp-1830728-Hook-up-PKCS-11-PIN-entry-through-configured-passphr.patch
27diff --git a/debian/patches/ubuntu/lp-1830728-Hook-up-PKCS-11-PIN-entry-through-configured-passphr.patch b/debian/patches/ubuntu/lp-1830728-Hook-up-PKCS-11-PIN-entry-through-configured-passphr.patch
28new file mode 100644
29index 0000000..6d2117b
30--- /dev/null
31+++ b/debian/patches/ubuntu/lp-1830728-Hook-up-PKCS-11-PIN-entry-through-configured-passphr.patch
32@@ -0,0 +1,328 @@
33+From ae480ad7738038e26063b67b545a8e1b85df5451 Mon Sep 17 00:00:00 2001
34+From: Joe Orton <jorton@apache.org>
35+Date: Fri, 6 Jul 2018 12:01:29 +0000
36+Subject: [PATCH] Hook up PKCS#11 PIN entry through configured passphrase entry
37+ method.
38+MIME-Version: 1.0
39+Content-Type: text/plain; charset=UTF-8
40+Content-Transfer-Encoding: 8bit
41+
42+* modules/ssl/ssl_engine_pphrase.c: Add wrappers for OpenSSL UI * API
43+ around passphrase entry.
44+ (modssl_load_engine_keypair): Take vhost ID and use above rather than
45+ default OpenSSL UI.
46+
47+* modules/ssl/ssl_engine_init.c (ssl_init_server_certs): Pass vhost ID.
48+
49+Submitted by: Anderson Sasaki<ansaski redhat.com>, jorton
50+
51+
52+git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@1835240 13f79535-47bb-0310-9956-ffa450edef68
53+
54+Origin: upstream, https://github.com/apache/httpd/commit/ae480ad7738038e26063b67b545a8e1b85df5451
55+Bug-Ubuntu: https://bugs.launchpad.net/bugs/1830728
56+Last-Update: 2019-07-29
57+
58+---
59+ modules/ssl/ssl_engine_init.c | 5 +-
60+ modules/ssl/ssl_engine_pphrase.c | 235 ++++++++++++++++++++++++++++++-
61+ modules/ssl/ssl_private.h | 1 +
62+ 3 files changed, 232 insertions(+), 9 deletions(-)
63+
64+diff --git a/modules/ssl/ssl_engine_init.c b/modules/ssl/ssl_engine_init.c
65+index c8a3365e0c..be4184ff86 100644
66+--- a/modules/ssl/ssl_engine_init.c
67++++ b/modules/ssl/ssl_engine_init.c
68+@@ -1293,8 +1293,9 @@ static apr_status_t ssl_init_server_certs(server_rec *s,
69+
70+ cert = NULL;
71+
72+- if ((rv = modssl_load_engine_keypair(s, ptemp, engine_certfile,
73+- keyfile, &cert, &pkey))) {
74++ if ((rv = modssl_load_engine_keypair(s, ptemp, vhost_id,
75++ engine_certfile, keyfile,
76++ &cert, &pkey))) {
77+ return rv;
78+ }
79+
80+diff --git a/modules/ssl/ssl_engine_pphrase.c b/modules/ssl/ssl_engine_pphrase.c
81+index 85982c80c1..7688b2425c 100644
82+--- a/modules/ssl/ssl_engine_pphrase.c
83++++ b/modules/ssl/ssl_engine_pphrase.c
84+@@ -588,13 +588,239 @@ int ssl_pphrase_Handle_CB(char *buf, int bufsize, int verify, void *srv)
85+ }
86+
87+ #if defined(HAVE_OPENSSL_ENGINE_H) && defined(HAVE_ENGINE_INIT)
88++
89++/* OpenSSL UI implementation for passphrase entry; largely duplicated
90++ * from ssl_pphrase_Handle_CB but adjusted for UI API. TODO: Might be
91++ * worth trying to shift pphrase handling over to the UI API
92++ * completely. */
93++static int passphrase_ui_open(UI *ui)
94++{
95++ pphrase_cb_arg_t *ppcb = UI_get0_user_data(ui);
96++ SSLSrvConfigRec *sc = mySrvConfig(ppcb->s);
97++
98++ ppcb->nPassPhraseDialog++;
99++ ppcb->nPassPhraseDialogCur++;
100++
101++ /*
102++ * Builtin or Pipe dialog
103++ */
104++ if (sc->server->pphrase_dialog_type == SSL_PPTYPE_BUILTIN
105++ || sc->server->pphrase_dialog_type == SSL_PPTYPE_PIPE) {
106++ if (sc->server->pphrase_dialog_type == SSL_PPTYPE_PIPE) {
107++ if (!readtty) {
108++ ap_log_error(APLOG_MARK, APLOG_INFO, 0, ppcb->s,
109++ APLOGNO()
110++ "Init: Creating pass phrase dialog pipe child "
111++ "'%s'", sc->server->pphrase_dialog_path);
112++ if (ssl_pipe_child_create(ppcb->p,
113++ sc->server->pphrase_dialog_path)
114++ != APR_SUCCESS) {
115++ ap_log_error(APLOG_MARK, APLOG_ERR, 0, ppcb->s,
116++ APLOGNO()
117++ "Init: Failed to create pass phrase pipe '%s'",
118++ sc->server->pphrase_dialog_path);
119++ return 0;
120++ }
121++ }
122++ ap_log_error(APLOG_MARK, APLOG_INFO, 0, ppcb->s, APLOGNO()
123++ "Init: Requesting pass phrase via piped dialog");
124++ }
125++ else { /* sc->server->pphrase_dialog_type == SSL_PPTYPE_BUILTIN */
126++#ifdef WIN32
127++ ap_log_error(APLOG_MARK, APLOG_ERR, 0, ppcb->s, APLOGNO()
128++ "Init: Failed to create pass phrase pipe '%s'",
129++ sc->server->pphrase_dialog_path);
130++ return 0;
131++#else
132++ /*
133++ * stderr has already been redirected to the error_log.
134++ * rather than attempting to temporarily rehook it to the terminal,
135++ * we print the prompt to stdout before EVP_read_pw_string turns
136++ * off tty echo
137++ */
138++ apr_file_open_stdout(&writetty, ppcb->p);
139++
140++ ap_log_error(APLOG_MARK, APLOG_INFO, 0, ppcb->s, APLOGNO()
141++ "Init: Requesting pass phrase via builtin terminal "
142++ "dialog");
143++#endif
144++ }
145++
146++ /*
147++ * The first time display a header to inform the user about what
148++ * program he actually speaks to, which module is responsible for
149++ * this terminal dialog and why to the hell he has to enter
150++ * something...
151++ */
152++ if (ppcb->nPassPhraseDialog == 1) {
153++ apr_file_printf(writetty, "%s mod_ssl (Pass Phrase Dialog)\n",
154++ AP_SERVER_BASEVERSION);
155++ apr_file_printf(writetty,
156++ "A pass phrase is required to access the private key.\n");
157++ }
158++ if (ppcb->bPassPhraseDialogOnce) {
159++ ppcb->bPassPhraseDialogOnce = FALSE;
160++ apr_file_printf(writetty, "\n");
161++ apr_file_printf(writetty, "Private key %s (%s)\n",
162++ ppcb->key_id, ppcb->pkey_file);
163++ }
164++ }
165++
166++ return 1;
167++}
168++
169++static int passphrase_ui_read(UI *ui, UI_STRING *uis)
170++{
171++ pphrase_cb_arg_t *ppcb = UI_get0_user_data(ui);
172++ SSLSrvConfigRec *sc = mySrvConfig(ppcb->s);
173++ const char *prompt;
174++ int i;
175++ int bufsize;
176++ int len;
177++ char *buf;
178++
179++ prompt = UI_get0_output_string(uis);
180++ if (prompt == NULL) {
181++ prompt = "Enter pass phrase:";
182++ }
183++
184++ /*
185++ * Get the maximum expected size and allocate the buffer
186++ */
187++ bufsize = UI_get_result_maxsize(uis);
188++ buf = apr_pcalloc(ppcb->p, bufsize);
189++
190++ if (sc->server->pphrase_dialog_type == SSL_PPTYPE_BUILTIN
191++ || sc->server->pphrase_dialog_type == SSL_PPTYPE_PIPE) {
192++ /*
193++ * Get the pass phrase through a callback.
194++ * Empty input is not accepted.
195++ */
196++ for (;;) {
197++ if (sc->server->pphrase_dialog_type == SSL_PPTYPE_PIPE) {
198++ i = pipe_get_passwd_cb(buf, bufsize, "", FALSE);
199++ }
200++ else { /* sc->server->pphrase_dialog_type == SSL_PPTYPE_BUILTIN */
201++ i = EVP_read_pw_string(buf, bufsize, "", FALSE);
202++ }
203++ if (i != 0) {
204++ OPENSSL_cleanse(buf, bufsize);
205++ return 0;
206++ }
207++ len = strlen(buf);
208++ if (len < 1){
209++ apr_file_printf(writetty, "Apache:mod_ssl:Error: Pass phrase"
210++ "empty (needs to be at least 1 character).\n");
211++ apr_file_puts(prompt, writetty);
212++ }
213++ else {
214++ break;
215++ }
216++ }
217++ }
218++ /*
219++ * Filter program
220++ */
221++ else if (sc->server->pphrase_dialog_type == SSL_PPTYPE_FILTER) {
222++ const char *cmd = sc->server->pphrase_dialog_path;
223++ const char **argv = apr_palloc(ppcb->p, sizeof(char *) * 3);
224++ char *result;
225++
226++ ap_log_error(APLOG_MARK, APLOG_INFO, 0, ppcb->s, APLOGNO()
227++ "Init: Requesting pass phrase from dialog filter "
228++ "program (%s)", cmd);
229++
230++ argv[0] = cmd;
231++ argv[1] = ppcb->key_id;
232++ argv[2] = NULL;
233++
234++ result = ssl_util_readfilter(ppcb->s, ppcb->p, cmd, argv);
235++ apr_cpystrn(buf, result, bufsize);
236++ len = strlen(buf);
237++ }
238++
239++ /*
240++ * Ok, we now have the pass phrase, so give it back
241++ */
242++ ppcb->cpPassPhraseCur = apr_pstrdup(ppcb->p, buf);
243++ UI_set_result(ui, uis, buf);
244++
245++ /* Clear sensitive data. */
246++ OPENSSL_cleanse(buf, bufsize);
247++ return 1;
248++}
249++
250++static int passphrase_ui_write(UI *ui, UI_STRING *uis)
251++{
252++ pphrase_cb_arg_t *ppcb = UI_get0_user_data(ui);
253++ SSLSrvConfigRec *sc;
254++ const char *prompt;
255++
256++ sc = mySrvConfig(ppcb->s);
257++
258++ if (sc->server->pphrase_dialog_type == SSL_PPTYPE_BUILTIN
259++ || sc->server->pphrase_dialog_type == SSL_PPTYPE_PIPE) {
260++ prompt = UI_get0_output_string(uis);
261++ apr_file_puts(prompt, writetty);
262++ }
263++
264++ return 1;
265++}
266++
267++static int passphrase_ui_close(UI *ui)
268++{
269++ /*
270++ * Close the pipes if they were opened
271++ */
272++ if (readtty) {
273++ apr_file_close(readtty);
274++ apr_file_close(writetty);
275++ readtty = writetty = NULL;
276++ }
277++ return 1;
278++}
279++
280++static apr_status_t pp_ui_method_cleanup(void *uip)
281++{
282++ UI_METHOD *uim = uip;
283++
284++ UI_destroy_method(uim);
285++
286++ return APR_SUCCESS;
287++}
288++
289++static UI_METHOD *get_passphrase_ui(apr_pool_t *p)
290++{
291++ UI_METHOD *ui_method = UI_create_method("Passphrase UI");
292++
293++ UI_method_set_opener(ui_method, passphrase_ui_open);
294++ UI_method_set_reader(ui_method, passphrase_ui_read);
295++ UI_method_set_writer(ui_method, passphrase_ui_write);
296++ UI_method_set_closer(ui_method, passphrase_ui_close);
297++
298++ apr_pool_cleanup_register(p, ui_method, pp_ui_method_cleanup,
299++ pp_ui_method_cleanup);
300++
301++ return ui_method;
302++}
303++
304++
305+ apr_status_t modssl_load_engine_keypair(server_rec *s, apr_pool_t *p,
306++ const char *vhostid,
307+ const char *certid, const char *keyid,
308+ X509 **pubkey, EVP_PKEY **privkey)
309+ {
310+ SSLModConfigRec *mc = myModConfig(s);
311+ ENGINE *e;
312+- UI_METHOD *ui_method;
313++ UI_METHOD *ui_method = get_passphrase_ui(p);
314++ pphrase_cb_arg_t ppcb;
315++
316++ memset(&ppcb, 0, sizeof ppcb);
317++ ppcb.s = s;
318++ ppcb.p = p;
319++ ppcb.bPassPhraseDialogOnce = TRUE;
320++ ppcb.key_id = vhostid;
321++ ppcb.pkey_file = keyid;
322+
323+ if (!mc->szCryptoDevice) {
324+ ap_log_error(APLOG_MARK, APLOG_EMERG, 0, s, APLOGNO(10131)
325+@@ -603,11 +829,6 @@ apr_status_t modssl_load_engine_keypair(server_rec *s, apr_pool_t *p,
326+ return ssl_die(s);
327+ }
328+
329+- /*
330+- * Using the builtin OpenSSL UI only, for now...
331+- */
332+- ui_method = UI_OpenSSL();
333+-
334+ if (!(e = ENGINE_by_id(mc->szCryptoDevice))) {
335+ ap_log_error(APLOG_MARK, APLOG_EMERG, 0, s, APLOGNO(10132)
336+ "Init: Failed to load Crypto Device API `%s'",
337+@@ -636,7 +857,7 @@ apr_status_t modssl_load_engine_keypair(server_rec *s, apr_pool_t *p,
338+ *pubkey = params.cert;
339+ }
340+
341+- *privkey = ENGINE_load_private_key(e, keyid, ui_method, NULL);
342++ *privkey = ENGINE_load_private_key(e, keyid, ui_method, &ppcb);
343+ if (*privkey == NULL) {
344+ ap_log_error(APLOG_MARK, APLOG_EMERG, 0, s, APLOGNO(10133)
345+ "Init: Unable to get the private key");
346+diff --git a/modules/ssl/ssl_private.h b/modules/ssl/ssl_private.h
347+index 1f629a46e3..8524c515ba 100644
348+--- a/modules/ssl/ssl_private.h
349++++ b/modules/ssl/ssl_private.h
350+@@ -994,6 +994,7 @@ apr_status_t ssl_load_encrypted_pkey(server_rec *, apr_pool_t *, int,
351+ * key returned as *pkey. certid can be NULL, in which case *pubkey
352+ * is not altered. Errors logged on failure. */
353+ apr_status_t modssl_load_engine_keypair(server_rec *s, apr_pool_t *p,
354++ const char *vhostid,
355+ const char *certid, const char *keyid,
356+ X509 **pubkey, EVP_PKEY **privkey);
357+
358+--
359+2.22.0
360+
361diff --git a/debian/patches/ubuntu/lp-1830728-mod_ssl-Add-support-for-loading-TLS-certificates-thr.patch b/debian/patches/ubuntu/lp-1830728-mod_ssl-Add-support-for-loading-TLS-certificates-thr.patch
362new file mode 100644
363index 0000000..a07d8b9
364--- /dev/null
365+++ b/debian/patches/ubuntu/lp-1830728-mod_ssl-Add-support-for-loading-TLS-certificates-thr.patch
366@@ -0,0 +1,207 @@
367+From 9007b62ecc0ad59edb37ec5f267a08868064699c Mon Sep 17 00:00:00 2001
368+From: Joe Orton <jorton@apache.org>
369+Date: Tue, 8 May 2018 12:39:22 +0000
370+Subject: [PATCH] mod_ssl: Add support for loading TLS certificates through the
371+ PKCS#11 engine.
372+
373+* modules/ssl/ssl_util.c (modssl_is_engine_id): Renamed
374+ from modssl_is_engine_key.
375+
376+* modules/ssl/ssl_engine_config.c (ssl_cmd_SSLCertificateKeyFile):
377+ Adjust accordingly.
378+ (ssl_cmd_SSLCertificateFile): Also allow ENGINE cert ids.
379+
380+* modules/ssl/ssl_engine_pphrase.c (modssl_load_engine_keypair):
381+ Rename from modssl_load_engine_key; load certificate if
382+ cert id is passed.
383+
384+* modules/ssl/ssl_engine_init.c (ssl_init_server_certs): Optionally
385+ load the certificate from the engine as well.
386+
387+* docs/manual/: Update manual.
388+
389+
390+git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@1831168 13f79535-47bb-0310-9956-ffa450edef68
391+
392+Origin: backport, https://github.com/apache/httpd/commit/9007b62ecc0ad59edb37ec5f267a08868064699c
393+Bug-Ubuntu: https://bugs.launchpad.net/bugs/1830728
394+Last-Update: 2019-07-29
395+
396+---
397+ modules/ssl/ssl_engine_config.c | 6 ++++--
398+ modules/ssl/ssl_engine_init.c | 26 +++++++++++++++++++++++---
399+ modules/ssl/ssl_engine_pphrase.c | 30 ++++++++++++++++++++++--------
400+ modules/ssl/ssl_private.h | 15 +++++++++------
401+ modules/ssl/ssl_util.c | 2 +-
402+ 8 files changed, 85 insertions(+), 27 deletions(-)
403+
404+--- a/modules/ssl/ssl_engine_config.c
405++++ b/modules/ssl/ssl_engine_config.c
406+@@ -1008,7 +1008,9 @@ const char *ssl_cmd_SSLCACertificateFile
407+ SSLSrvConfigRec *sc = mySrvConfig(cmd->server);
408+ const char *err;
409+
410+- if ((err = ssl_cmd_check_file(cmd, &arg))) {
411++ /* Only check for non-ENGINE based certs. */
412++ if (!modssl_is_engine_id(arg)
413++ && (err = ssl_cmd_check_file(cmd, &arg))) {
414+ return err;
415+ }
416+
417+@@ -1044,7 +1046,7 @@ const char *ssl_cmd_SSLCADNRequestFile(c
418+ const char *err;
419+
420+ /* Check keyfile exists for non-ENGINE keys. */
421+- if (!modssl_is_engine_key(arg)
422++ if (!modssl_is_engine_id(arg)
423+ && (err = ssl_cmd_check_file(cmd, &arg))) {
424+ return err;
425+ }
426+--- a/modules/ssl/ssl_engine_init.c
427++++ b/modules/ssl/ssl_engine_init.c
428+@@ -1229,13 +1229,17 @@ static apr_status_t ssl_init_server_cert
429+ const char *));
430+ i++) {
431+ EVP_PKEY *pkey;
432++ const char *engine_certfile = NULL;
433+
434+ key_id = apr_psprintf(ptemp, "%s:%d", vhost_id, i);
435+
436+ ERR_clear_error();
437+
438+ /* first the certificate (public key) */
439+- if (mctx->cert_chain) {
440++ if (modssl_is_engine_id(certfile)) {
441++ engine_certfile = certfile;
442++ }
443++ else if (mctx->cert_chain) {
444+ if ((SSL_CTX_use_certificate_file(mctx->ssl_ctx, certfile,
445+ SSL_FILETYPE_PEM) < 1)) {
446+ ap_log_error(APLOG_MARK, APLOG_EMERG, 0, s, APLOGNO(02561)
447+@@ -1264,12 +1268,28 @@ static apr_status_t ssl_init_server_cert
448+
449+ ERR_clear_error();
450+
451+- if (modssl_is_engine_key(keyfile)) {
452++ if (modssl_is_engine_id(keyfile)) {
453+ apr_status_t rv;
454+
455+- if ((rv = modssl_load_engine_pkey(s, ptemp, keyfile, &pkey))) {
456++ cert = NULL;
457++
458++ if ((rv = modssl_load_engine_keypair(s, ptemp, engine_certfile,
459++ keyfile, &cert, &pkey))) {
460+ return rv;
461+ }
462++
463++ if (cert) {
464++ if (SSL_CTX_use_certificate(mctx->ssl_ctx, cert) < 1) {
465++ ap_log_error(APLOG_MARK, APLOG_EMERG, 0, s, APLOGNO()
466++ "Failed to configure engine certificate %s, check %s",
467++ key_id, certfile);
468++ ssl_log_ssl_error(SSLLOG_MARK, APLOG_EMERG, s);
469++ return APR_EGENERAL;
470++ }
471++
472++ /* SSL_CTX now owns the cert. */
473++ X509_free(cert);
474++ }
475+
476+ if (SSL_CTX_use_PrivateKey(mctx->ssl_ctx, pkey) < 1) {
477+ ap_log_error(APLOG_MARK, APLOG_EMERG, 0, s, APLOGNO(10130)
478+--- a/modules/ssl/ssl_engine_pphrase.c
479++++ b/modules/ssl/ssl_engine_pphrase.c
480+@@ -616,11 +616,11 @@ int ssl_pphrase_Handle_CB(char *buf, int
481+ }
482+
483+ #if defined(HAVE_OPENSSL_ENGINE_H) && defined(HAVE_ENGINE_INIT)
484+-apr_status_t modssl_load_engine_pkey(server_rec *s, apr_pool_t *p,
485+- const char *keyid, EVP_PKEY **ppkey)
486++apr_status_t modssl_load_engine_keypair(server_rec *s, apr_pool_t *p,
487++ const char *certid, const char *keyid,
488++ X509 **pubkey, EVP_PKEY **privkey)
489+ {
490+ SSLModConfigRec *mc = myModConfig(s);
491+- EVP_PKEY *pPrivateKey = NULL;
492+ ENGINE *e;
493+ UI_METHOD *ui_method;
494+
495+@@ -647,17 +647,31 @@ apr_status_t modssl_load_engine_pkey(ser
496+ if (APLOGdebug(s)) {
497+ ENGINE_ctrl_cmd_string(e, "VERBOSE", NULL, 0);
498+ }
499+-
500+- pPrivateKey = ENGINE_load_private_key(e, keyid, ui_method, NULL);
501+- if (pPrivateKey == NULL) {
502++
503++ if (certid) {
504++ struct {
505++ const char *cert_id;
506++ X509 *cert;
507++ } params = { certid, NULL };
508++
509++ if (!ENGINE_ctrl_cmd(e, "LOAD_CERT_CTRL", 0, &params, NULL, 1)) {
510++ ap_log_error(APLOG_MARK, APLOG_EMERG, 0, s, APLOGNO(10136)
511++ "Init: Unable to get the certificate");
512++ ssl_log_ssl_error(SSLLOG_MARK, APLOG_EMERG, s);
513++ return ssl_die(s);
514++ }
515++
516++ *pubkey = params.cert;
517++ }
518++
519++ *privkey = ENGINE_load_private_key(e, keyid, ui_method, NULL);
520++ if (*privkey == NULL) {
521+ ap_log_error(APLOG_MARK, APLOG_EMERG, 0, s, APLOGNO(10133)
522+ "Init: Unable to get the private key");
523+ ssl_log_ssl_error(SSLLOG_MARK, APLOG_EMERG, s);
524+ return ssl_die(s);
525+ }
526+
527+- *ppkey = pPrivateKey;
528+-
529+ ENGINE_free(e);
530+
531+ return APR_SUCCESS;
532+--- a/modules/ssl/ssl_private.h
533++++ b/modules/ssl/ssl_private.h
534+@@ -1001,10 +1001,13 @@ BOOL ssl_util_vhost_matches(cons
535+ /** Pass Phrase Support */
536+ apr_status_t ssl_load_encrypted_pkey(server_rec *, apr_pool_t *, int,
537+ const char *, apr_array_header_t **);
538+-/* Load private key from the configured ENGINE, returned as **pkey.
539+- * Errors logged on failure. */
540+-apr_status_t modssl_load_engine_pkey(server_rec *s, apr_pool_t *p,
541+- const char *keyid, EVP_PKEY **ppkey);
542++
543++/* Load public and/or private key from the configured ENGINE. Private
544++ * key returned as *pkey. certid can be NULL, in which case *pubkey
545++ * is not altered. Errors logged on failure. */
546++apr_status_t modssl_load_engine_keypair(server_rec *s, apr_pool_t *p,
547++ const char *certid, const char *keyid,
548++ X509 **pubkey, EVP_PKEY **privkey);
549+
550+ /** Diffie-Hellman Parameter Support */
551+ DH *ssl_dh_GetParamFromFile(const char *);
552+@@ -1111,8 +1114,8 @@ DH *modssl_get_dh_params(unsigned keylen
553+ int modssl_request_is_tls(const request_rec *r, SSLConnRec **sslconn);
554+
555+ /* Returns non-zero if the cert/key filename should be handled through
556+- * the configure ENGINE. */
557+-int modssl_is_engine_key(const char *name);
558++ * the configured ENGINE. */
559++int modssl_is_engine_id(const char *name);
560+
561+ int ssl_is_challenge(conn_rec *c, const char *servername,
562+ X509 **pcert, EVP_PKEY **pkey);
563+--- a/modules/ssl/ssl_util.c
564++++ b/modules/ssl/ssl_util.c
565+@@ -481,7 +481,7 @@ void ssl_util_thread_id_setup(apr_pool_t
566+
567+ #endif /* #if APR_HAS_THREADS && MODSSL_USE_OPENSSL_PRE_1_1_API */
568+
569+-int modssl_is_engine_key(const char *name)
570++int modssl_is_engine_id(const char *name)
571+ {
572+ #if defined(HAVE_OPENSSL_ENGINE_H) && defined(HAVE_ENGINE_INIT)
573+ /* ### Can handle any other special ENGINE key names here? */
574diff --git a/debian/patches/ubuntu/lp-1830728-mod_ssl-Add-support-for-loading-private-keys-from-EN.patch b/debian/patches/ubuntu/lp-1830728-mod_ssl-Add-support-for-loading-private-keys-from-EN.patch
575new file mode 100644
576index 0000000..8fbf151
577--- /dev/null
578+++ b/debian/patches/ubuntu/lp-1830728-mod_ssl-Add-support-for-loading-private-keys-from-EN.patch
579@@ -0,0 +1,185 @@
580+From e71764a49d1276b8051b83e6ad346482f3e7bc06 Mon Sep 17 00:00:00 2001
581+From: Joe Orton <jorton@apache.org>
582+Date: Thu, 3 May 2018 13:06:46 +0000
583+Subject: [PATCH] mod_ssl: Add support for loading private keys from ENGINEs.
584+ Support for PKCS#11 URIs only, and PIN entry is not threaded through
585+ SSLPassPhraseDialog config yet.
586+
587+* modules/ssl/ssl_util.c (modssl_is_engine_key): New function.
588+
589+* modules/ssl/ssl_engine_config.c (ssl_cmd_SSLCertificateKeyFile):
590+ Use it, skip check for file existence for engine keys.
591+
592+* modules/ssl/ssl_engine_pphrase.c (modssl_load_engine_pkey):
593+ New function.
594+
595+* modules/ssl/ssl_engine_init.c (ssl_init_server_certs):
596+ For engine keys, load via modssl_load_engine_pkey.
597+
598+Submitted by: Anderson Sasaki <ansasaki redhat.com>, jorton
599+
600+
601+git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@1830819 13f79535-47bb-0310-9956-ffa450edef68
602+
603+Origin: backport, https://github.com/apache/httpd/commit/e71764a49d1276b8051b83e6ad346482f3e7bc06
604+Last-Update: 2019-07-29
605+
606+---
607+ modules/ssl/ssl_engine_config.c | 4 ++-
608+ modules/ssl/ssl_engine_init.c | 26 ++++++++++++----
609+ modules/ssl/ssl_engine_pphrase.c | 49 +++++++++++++++++++++++++++++++
610+ modules/ssl/ssl_private.h | 8 +++++
611+ modules/ssl/ssl_util.c | 10 +++++++
612+ 8 files changed, 112 insertions(+), 10 deletions(-)
613+
614+--- a/modules/ssl/ssl_engine_config.c
615++++ b/modules/ssl/ssl_engine_config.c
616+@@ -1043,7 +1043,9 @@ const char *ssl_cmd_SSLCADNRequestFile(c
617+ SSLSrvConfigRec *sc = mySrvConfig(cmd->server);
618+ const char *err;
619+
620+- if ((err = ssl_cmd_check_file(cmd, &arg))) {
621++ /* Check keyfile exists for non-ENGINE keys. */
622++ if (!modssl_is_engine_key(arg)
623++ && (err = ssl_cmd_check_file(cmd, &arg))) {
624+ return err;
625+ }
626+
627+--- a/modules/ssl/ssl_engine_init.c
628++++ b/modules/ssl/ssl_engine_init.c
629+@@ -1228,6 +1228,8 @@ static apr_status_t ssl_init_server_cert
630+ (certfile = APR_ARRAY_IDX(mctx->pks->cert_files, i,
631+ const char *));
632+ i++) {
633++ EVP_PKEY *pkey;
634++
635+ key_id = apr_psprintf(ptemp, "%s:%d", vhost_id, i);
636+
637+ ERR_clear_error();
638+@@ -1262,12 +1264,26 @@ static apr_status_t ssl_init_server_cert
639+
640+ ERR_clear_error();
641+
642+- if ((SSL_CTX_use_PrivateKey_file(mctx->ssl_ctx, keyfile,
643+- SSL_FILETYPE_PEM) < 1) &&
644+- (ERR_GET_FUNC(ERR_peek_last_error())
645+- != X509_F_X509_CHECK_PRIVATE_KEY)) {
646++ if (modssl_is_engine_key(keyfile)) {
647++ apr_status_t rv;
648++
649++ if ((rv = modssl_load_engine_pkey(s, ptemp, keyfile, &pkey))) {
650++ return rv;
651++ }
652++
653++ if (SSL_CTX_use_PrivateKey(mctx->ssl_ctx, pkey) < 1) {
654++ ap_log_error(APLOG_MARK, APLOG_EMERG, 0, s, APLOGNO(10130)
655++ "Failed to configure private key %s from engine",
656++ keyfile);
657++ ssl_log_ssl_error(SSLLOG_MARK, APLOG_EMERG, s);
658++ return APR_EGENERAL;
659++ }
660++ }
661++ else if ((SSL_CTX_use_PrivateKey_file(mctx->ssl_ctx, keyfile,
662++ SSL_FILETYPE_PEM) < 1)
663++ && (ERR_GET_FUNC(ERR_peek_last_error())
664++ != X509_F_X509_CHECK_PRIVATE_KEY)) {
665+ ssl_asn1_t *asn1;
666+- EVP_PKEY *pkey;
667+ const unsigned char *ptr;
668+
669+ ERR_clear_error();
670+--- a/modules/ssl/ssl_engine_pphrase.c
671++++ b/modules/ssl/ssl_engine_pphrase.c
672+@@ -614,3 +614,52 @@ int ssl_pphrase_Handle_CB(char *buf, int
673+ */
674+ return (len);
675+ }
676++
677++#if defined(HAVE_OPENSSL_ENGINE_H) && defined(HAVE_ENGINE_INIT)
678++apr_status_t modssl_load_engine_pkey(server_rec *s, apr_pool_t *p,
679++ const char *keyid, EVP_PKEY **ppkey)
680++{
681++ SSLModConfigRec *mc = myModConfig(s);
682++ EVP_PKEY *pPrivateKey = NULL;
683++ ENGINE *e;
684++ UI_METHOD *ui_method;
685++
686++ if (!mc->szCryptoDevice) {
687++ ap_log_error(APLOG_MARK, APLOG_EMERG, 0, s, APLOGNO(10131)
688++ "Init: Cannot load private key `%s' without engine",
689++ keyid);
690++ return ssl_die(s);
691++ }
692++
693++ /*
694++ * Using the builtin OpenSSL UI only, for now...
695++ */
696++ ui_method = UI_OpenSSL();
697++
698++ if (!(e = ENGINE_by_id(mc->szCryptoDevice))) {
699++ ap_log_error(APLOG_MARK, APLOG_EMERG, 0, s, APLOGNO(10132)
700++ "Init: Failed to load Crypto Device API `%s'",
701++ mc->szCryptoDevice);
702++ ssl_log_ssl_error(SSLLOG_MARK, APLOG_EMERG, s);
703++ return ssl_die(s);
704++ }
705++
706++ if (APLOGdebug(s)) {
707++ ENGINE_ctrl_cmd_string(e, "VERBOSE", NULL, 0);
708++ }
709++
710++ pPrivateKey = ENGINE_load_private_key(e, keyid, ui_method, NULL);
711++ if (pPrivateKey == NULL) {
712++ ap_log_error(APLOG_MARK, APLOG_EMERG, 0, s, APLOGNO(10133)
713++ "Init: Unable to get the private key");
714++ ssl_log_ssl_error(SSLLOG_MARK, APLOG_EMERG, s);
715++ return ssl_die(s);
716++ }
717++
718++ *ppkey = pPrivateKey;
719++
720++ ENGINE_free(e);
721++
722++ return APR_SUCCESS;
723++}
724++#endif
725+--- a/modules/ssl/ssl_private.h
726++++ b/modules/ssl/ssl_private.h
727+@@ -1001,6 +1001,10 @@ BOOL ssl_util_vhost_matches(cons
728+ /** Pass Phrase Support */
729+ apr_status_t ssl_load_encrypted_pkey(server_rec *, apr_pool_t *, int,
730+ const char *, apr_array_header_t **);
731++/* Load private key from the configured ENGINE, returned as **pkey.
732++ * Errors logged on failure. */
733++apr_status_t modssl_load_engine_pkey(server_rec *s, apr_pool_t *p,
734++ const char *keyid, EVP_PKEY **ppkey);
735+
736+ /** Diffie-Hellman Parameter Support */
737+ DH *ssl_dh_GetParamFromFile(const char *);
738+@@ -1106,6 +1110,10 @@ DH *modssl_get_dh_params(unsigned keylen
739+ * corresponding SSLConnRec structure for the connection. */
740+ int modssl_request_is_tls(const request_rec *r, SSLConnRec **sslconn);
741+
742++/* Returns non-zero if the cert/key filename should be handled through
743++ * the configure ENGINE. */
744++int modssl_is_engine_key(const char *name);
745++
746+ int ssl_is_challenge(conn_rec *c, const char *servername,
747+ X509 **pcert, EVP_PKEY **pkey);
748+
749+--- a/modules/ssl/ssl_util.c
750++++ b/modules/ssl/ssl_util.c
751+@@ -480,3 +480,13 @@ void ssl_util_thread_id_setup(apr_pool_t
752+ }
753+
754+ #endif /* #if APR_HAS_THREADS && MODSSL_USE_OPENSSL_PRE_1_1_API */
755++
756++int modssl_is_engine_key(const char *name)
757++{
758++#if defined(HAVE_OPENSSL_ENGINE_H) && defined(HAVE_ENGINE_INIT)
759++ /* ### Can handle any other special ENGINE key names here? */
760++ return strncmp(name, "pkcs11:", 7) == 0;
761++#else
762++ return 0;
763++#endif
764++}

Subscribers

People subscribed via source and target branches