Package: openvpn Version: 2.4.5-1 Severity: important Tags: patch Dear Maintainer,
users of yubikey or other PKCS11 based authetication are not able to use this feature with the current package. Upstream reference: https://community.openvpn.net/openvpn/ticket/538 I was able to fix this problem by building the current debian package with the patch provided upstream: https://community.openvpn.net/openvpn/attachment/ticket/538/openvpn-2.4.5_bug-538.patch Please consider including this patch in your package. Regards, Robert Haist -- System Information: Debian Release: buster/sid APT prefers testing APT policy: (650, 'testing') Architecture: amd64 (x86_64) Kernel: Linux 4.16.0-1-amd64 (SMP w/8 CPU cores) Locale: LANG=en_US.UTF-8, LC_CTYPE=en_US.UTF-8 (charmap=UTF-8), LANGUAGE=en_US:en (charmap=UTF-8) Shell: /bin/sh linked to /bin/dash Init: systemd (via /run/systemd/system) LSM: AppArmor: enabled Versions of packages openvpn depends on: ii debconf [debconf-2.0] 1.5.66 ii iproute2 4.16.0-4 ii libc6 2.27-3 ii liblz4-1 1.8.2-1 ii liblzo2-2 2.10-0.1 ii libpam0g 1.1.8-3.7 ii libpkcs11-helper1 1.22-4 ii libssl1.1 1.1.0h-4 ii libsystemd0 238-5 ii lsb-base 9.20170808 Versions of packages openvpn recommends: ii easy-rsa 3.0.4-1 Versions of packages openvpn suggests: ii openssl 1.1.0h-4 pn resolvconf <none> -- debconf information excluded
diff -Naur openvpn-2.4.5/src/openvpn/console.h openvpn-2.4.5_bug-538/src/openvpn/console.h --- openvpn-2.4.5/src/openvpn/console.h 2018-03-01 08:22:17.000000000 +0100 +++ openvpn-2.4.5_bug-538/src/openvpn/console.h 2018-03-09 15:01:36.825094859 +0100 @@ -116,4 +116,22 @@ return query_user_exec(); } +/** + * A plain "make Gert happy" wrapper over built-in user querying method. + * Same arguments as @query_user_add + * + * Allows to use built-in method for PKCS11 PIN prompt regardless of + * the systemd support status and presence, + * see https://community.openvpn.net/openvpn/ticket/538 for details. +*/ +static inline bool +query_user_builtin_SINGLE(char *prompt, size_t prompt_len, + char *resp, size_t resp_len, + bool echo) +{ + query_user_clear(); + query_user_add(prompt, prompt_len, resp, resp_len, echo); + return query_user_exec_builtin(); +} + #endif /* ifndef CONSOLE_H */ diff -Naur openvpn-2.4.5/src/openvpn/misc.c openvpn-2.4.5_bug-538/src/openvpn/misc.c --- openvpn-2.4.5/src/openvpn/misc.c 2018-03-01 08:22:19.000000000 +0100 +++ openvpn-2.4.5_bug-538/src/openvpn/misc.c 2018-03-09 15:02:11.056279505 +0100 @@ -930,10 +930,19 @@ struct buffer user_prompt = alloc_buf_gc(128, &gc); buf_printf(&user_prompt, "NEED-OK|%s|%s:", prefix, up->username); - if (!query_user_SINGLE(BSTR(&user_prompt), BLEN(&user_prompt), - up->password, USER_PASS_LEN, false)) - { - msg(M_FATAL, "ERROR: could not read %s ok-confirmation from stdin", prefix); + if (flags & GET_USER_PASS_FORCE_BUILTIN) { + if (!query_user_builtin_SINGLE(BSTR(&user_prompt), BLEN(&user_prompt), + up->password, USER_PASS_LEN, false)) + { + msg(M_FATAL, "ERROR: could not read %s ok-confirmation from stdin", prefix); + } + } + else { + if (!query_user_SINGLE(BSTR(&user_prompt), BLEN(&user_prompt), + up->password, USER_PASS_LEN, false)) + { + msg(M_FATAL, "ERROR: could not read %s ok-confirmation from stdin", prefix); + } } if (!strlen(up->password)) @@ -941,7 +950,7 @@ strcpy(up->password, "ok"); } } - else if (flags & GET_USER_PASS_INLINE_CREDS) + else if (flags & GET_USER_PASS_NEED_OK) { struct buffer buf; buf_set_read(&buf, (uint8_t *) auth_file, strlen(auth_file) + 1); @@ -1030,10 +1039,19 @@ buf_printf(&challenge, "CHALLENGE: %s", ac->challenge_text); buf_set_write(&packed_resp, (uint8_t *)up->password, USER_PASS_LEN); - if (!query_user_SINGLE(BSTR(&challenge), BLEN(&challenge), - response, USER_PASS_LEN, BOOL_CAST(ac->flags&CR_ECHO))) - { - msg(M_FATAL, "ERROR: could not read challenge response from stdin"); + if (flags & GET_USER_PASS_FORCE_BUILTIN) { + if (!query_user_builtin_SINGLE(BSTR(&challenge), BLEN(&challenge), + response, USER_PASS_LEN, BOOL_CAST(ac->flags&CR_ECHO))) + { + msg(M_FATAL, "ERROR: could not read challenge response from stdin"); + } + } + else { + if (!query_user_SINGLE(BSTR(&challenge), BLEN(&challenge), + response, USER_PASS_LEN, BOOL_CAST(ac->flags&CR_ECHO))) + { + msg(M_FATAL, "ERROR: could not read challenge response from stdin"); + } } strncpynt(up->username, ac->user, USER_PASS_LEN); buf_printf(&packed_resp, "CRV1::%s::%s", ac->state_id, response); @@ -1065,9 +1083,17 @@ up->password, USER_PASS_LEN, false); } - if (!query_user_exec() ) - { - msg(M_FATAL, "ERROR: Failed retrieving username or password"); + if (flags & GET_USER_PASS_FORCE_BUILTIN) { + if (!query_user_exec_builtin() ) + { + msg(M_FATAL, "ERROR: Failed retrieving username or password"); + } + } + else { + if (!query_user_exec() ) + { + msg(M_FATAL, "ERROR: Failed retrieving username or password"); + } } if (!(flags & GET_USER_PASS_PASSWORD_ONLY)) @@ -1088,11 +1114,21 @@ challenge = alloc_buf_gc(14+strlen(auth_challenge), &gc); buf_printf(&challenge, "CHALLENGE: %s", auth_challenge); - if (!query_user_SINGLE(BSTR(&challenge), BLEN(&challenge), - response, USER_PASS_LEN, - BOOL_CAST(flags & GET_USER_PASS_STATIC_CHALLENGE_ECHO))) - { - msg(M_FATAL, "ERROR: could not retrieve static challenge response"); + if (flags & GET_USER_PASS_FORCE_BUILTIN) { + if (!query_user_builtin_SINGLE(BSTR(&challenge), BLEN(&challenge), + response, USER_PASS_LEN, + BOOL_CAST(flags & GET_USER_PASS_STATIC_CHALLENGE_ECHO))) + { + msg(M_FATAL, "ERROR: could not retrieve static challenge response"); + } + } + else { + if (!query_user_SINGLE(BSTR(&challenge), BLEN(&challenge), + response, USER_PASS_LEN, + BOOL_CAST(flags & GET_USER_PASS_STATIC_CHALLENGE_ECHO))) + { + msg(M_FATAL, "ERROR: could not retrieve static challenge response"); + } } if (openvpn_base64_encode(up->password, strlen(up->password), &pw64) == -1 || openvpn_base64_encode(response, strlen(response), &resp64) == -1) diff -Naur openvpn-2.4.5/src/openvpn/misc.h openvpn-2.4.5_bug-538/src/openvpn/misc.h --- openvpn-2.4.5/src/openvpn/misc.h 2018-03-01 08:22:19.000000000 +0100 +++ openvpn-2.4.5_bug-538/src/openvpn/misc.h 2018-03-09 15:02:07.946262729 +0100 @@ -232,7 +232,9 @@ #define GET_USER_PASS_STATIC_CHALLENGE (1<<8) /* SCRV1 protocol -- static challenge */ #define GET_USER_PASS_STATIC_CHALLENGE_ECHO (1<<9) /* SCRV1 protocol -- echo response */ -#define GET_USER_PASS_INLINE_CREDS (1<<10) /* indicates that auth_file is actually inline creds */ +#define GET_USER_PASS_INLINE_CREDS (1<<10) + +#define GET_USER_PASS_FORCE_BUILTIN (1<<11) /* force builtin prompt to work around 538 */ bool get_user_pass_cr(struct user_pass *up, const char *auth_file, diff -Naur openvpn-2.4.5/src/openvpn/pkcs11.c openvpn-2.4.5_bug-538/src/openvpn/pkcs11.c --- openvpn-2.4.5/src/openvpn/pkcs11.c 2018-03-01 08:22:17.000000000 +0100 +++ openvpn-2.4.5_bug-538/src/openvpn/pkcs11.c 2018-03-09 15:02:01.982230559 +0100 @@ -257,7 +257,7 @@ &token_pass, NULL, prompt, - GET_USER_PASS_MANAGEMENT|GET_USER_PASS_PASSWORD_ONLY|GET_USER_PASS_NOFATAL + GET_USER_PASS_MANAGEMENT|GET_USER_PASS_PASSWORD_ONLY|GET_USER_PASS_NOFATAL|GET_USER_PASS_FORCE_BUILTIN ) ) { @@ -813,7 +813,7 @@ ASSERT(token!=NULL); buf_printf(&pass_prompt, "Please enter '%s' token PIN or 'cancel': ", token->display); - if (!query_user_SINGLE(BSTR(&pass_prompt), BLEN(&pass_prompt), + if (!query_user_builtin_SINGLE(BSTR(&pass_prompt), BLEN(&pass_prompt), pin, pin_max, false)) { msg(M_FATAL, "Could not retrieve the PIN");
diff -Naur openvpn-2.4.5/src/openvpn/console.h openvpn-2.4.5_bug-538/src/openvpn/console.h --- openvpn-2.4.5/src/openvpn/console.h 2018-03-01 08:22:17.000000000 +0100 +++ openvpn-2.4.5_bug-538/src/openvpn/console.h 2018-03-09 15:01:36.825094859 +0100 @@ -116,4 +116,22 @@ return query_user_exec(); } +/** + * A plain "make Gert happy" wrapper over built-in user querying method. + * Same arguments as @query_user_add + * + * Allows to use built-in method for PKCS11 PIN prompt regardless of + * the systemd support status and presence, + * see https://community.openvpn.net/openvpn/ticket/538 for details. +*/ +static inline bool +query_user_builtin_SINGLE(char *prompt, size_t prompt_len, + char *resp, size_t resp_len, + bool echo) +{ + query_user_clear(); + query_user_add(prompt, prompt_len, resp, resp_len, echo); + return query_user_exec_builtin(); +} + #endif /* ifndef CONSOLE_H */ diff -Naur openvpn-2.4.5/src/openvpn/misc.c openvpn-2.4.5_bug-538/src/openvpn/misc.c --- openvpn-2.4.5/src/openvpn/misc.c 2018-03-01 08:22:19.000000000 +0100 +++ openvpn-2.4.5_bug-538/src/openvpn/misc.c 2018-03-09 15:02:11.056279505 +0100 @@ -930,10 +930,19 @@ struct buffer user_prompt = alloc_buf_gc(128, &gc); buf_printf(&user_prompt, "NEED-OK|%s|%s:", prefix, up->username); - if (!query_user_SINGLE(BSTR(&user_prompt), BLEN(&user_prompt), - up->password, USER_PASS_LEN, false)) - { - msg(M_FATAL, "ERROR: could not read %s ok-confirmation from stdin", prefix); + if (flags & GET_USER_PASS_FORCE_BUILTIN) { + if (!query_user_builtin_SINGLE(BSTR(&user_prompt), BLEN(&user_prompt), + up->password, USER_PASS_LEN, false)) + { + msg(M_FATAL, "ERROR: could not read %s ok-confirmation from stdin", prefix); + } + } + else { + if (!query_user_SINGLE(BSTR(&user_prompt), BLEN(&user_prompt), + up->password, USER_PASS_LEN, false)) + { + msg(M_FATAL, "ERROR: could not read %s ok-confirmation from stdin", prefix); + } } if (!strlen(up->password)) @@ -941,7 +950,7 @@ strcpy(up->password, "ok"); } } - else if (flags & GET_USER_PASS_INLINE_CREDS) + else if (flags & GET_USER_PASS_NEED_OK) { struct buffer buf; buf_set_read(&buf, (uint8_t *) auth_file, strlen(auth_file) + 1); @@ -1030,10 +1039,19 @@ buf_printf(&challenge, "CHALLENGE: %s", ac->challenge_text); buf_set_write(&packed_resp, (uint8_t *)up->password, USER_PASS_LEN); - if (!query_user_SINGLE(BSTR(&challenge), BLEN(&challenge), - response, USER_PASS_LEN, BOOL_CAST(ac->flags&CR_ECHO))) - { - msg(M_FATAL, "ERROR: could not read challenge response from stdin"); + if (flags & GET_USER_PASS_FORCE_BUILTIN) { + if (!query_user_builtin_SINGLE(BSTR(&challenge), BLEN(&challenge), + response, USER_PASS_LEN, BOOL_CAST(ac->flags&CR_ECHO))) + { + msg(M_FATAL, "ERROR: could not read challenge response from stdin"); + } + } + else { + if (!query_user_SINGLE(BSTR(&challenge), BLEN(&challenge), + response, USER_PASS_LEN, BOOL_CAST(ac->flags&CR_ECHO))) + { + msg(M_FATAL, "ERROR: could not read challenge response from stdin"); + } } strncpynt(up->username, ac->user, USER_PASS_LEN); buf_printf(&packed_resp, "CRV1::%s::%s", ac->state_id, response); @@ -1065,9 +1083,17 @@ up->password, USER_PASS_LEN, false); } - if (!query_user_exec() ) - { - msg(M_FATAL, "ERROR: Failed retrieving username or password"); + if (flags & GET_USER_PASS_FORCE_BUILTIN) { + if (!query_user_exec_builtin() ) + { + msg(M_FATAL, "ERROR: Failed retrieving username or password"); + } + } + else { + if (!query_user_exec() ) + { + msg(M_FATAL, "ERROR: Failed retrieving username or password"); + } } if (!(flags & GET_USER_PASS_PASSWORD_ONLY)) @@ -1088,11 +1114,21 @@ challenge = alloc_buf_gc(14+strlen(auth_challenge), &gc); buf_printf(&challenge, "CHALLENGE: %s", auth_challenge); - if (!query_user_SINGLE(BSTR(&challenge), BLEN(&challenge), - response, USER_PASS_LEN, - BOOL_CAST(flags & GET_USER_PASS_STATIC_CHALLENGE_ECHO))) - { - msg(M_FATAL, "ERROR: could not retrieve static challenge response"); + if (flags & GET_USER_PASS_FORCE_BUILTIN) { + if (!query_user_builtin_SINGLE(BSTR(&challenge), BLEN(&challenge), + response, USER_PASS_LEN, + BOOL_CAST(flags & GET_USER_PASS_STATIC_CHALLENGE_ECHO))) + { + msg(M_FATAL, "ERROR: could not retrieve static challenge response"); + } + } + else { + if (!query_user_SINGLE(BSTR(&challenge), BLEN(&challenge), + response, USER_PASS_LEN, + BOOL_CAST(flags & GET_USER_PASS_STATIC_CHALLENGE_ECHO))) + { + msg(M_FATAL, "ERROR: could not retrieve static challenge response"); + } } if (openvpn_base64_encode(up->password, strlen(up->password), &pw64) == -1 || openvpn_base64_encode(response, strlen(response), &resp64) == -1) diff -Naur openvpn-2.4.5/src/openvpn/misc.h openvpn-2.4.5_bug-538/src/openvpn/misc.h --- openvpn-2.4.5/src/openvpn/misc.h 2018-03-01 08:22:19.000000000 +0100 +++ openvpn-2.4.5_bug-538/src/openvpn/misc.h 2018-03-09 15:02:07.946262729 +0100 @@ -232,7 +232,9 @@ #define GET_USER_PASS_STATIC_CHALLENGE (1<<8) /* SCRV1 protocol -- static challenge */ #define GET_USER_PASS_STATIC_CHALLENGE_ECHO (1<<9) /* SCRV1 protocol -- echo response */ -#define GET_USER_PASS_INLINE_CREDS (1<<10) /* indicates that auth_file is actually inline creds */ +#define GET_USER_PASS_INLINE_CREDS (1<<10) + +#define GET_USER_PASS_FORCE_BUILTIN (1<<11) /* force builtin prompt to work around 538 */ bool get_user_pass_cr(struct user_pass *up, const char *auth_file, diff -Naur openvpn-2.4.5/src/openvpn/pkcs11.c openvpn-2.4.5_bug-538/src/openvpn/pkcs11.c --- openvpn-2.4.5/src/openvpn/pkcs11.c 2018-03-01 08:22:17.000000000 +0100 +++ openvpn-2.4.5_bug-538/src/openvpn/pkcs11.c 2018-03-09 15:02:01.982230559 +0100 @@ -257,7 +257,7 @@ &token_pass, NULL, prompt, - GET_USER_PASS_MANAGEMENT|GET_USER_PASS_PASSWORD_ONLY|GET_USER_PASS_NOFATAL + GET_USER_PASS_MANAGEMENT|GET_USER_PASS_PASSWORD_ONLY|GET_USER_PASS_NOFATAL|GET_USER_PASS_FORCE_BUILTIN ) ) { @@ -813,7 +813,7 @@ ASSERT(token!=NULL); buf_printf(&pass_prompt, "Please enter '%s' token PIN or 'cancel': ", token->display); - if (!query_user_SINGLE(BSTR(&pass_prompt), BLEN(&pass_prompt), + if (!query_user_builtin_SINGLE(BSTR(&pass_prompt), BLEN(&pass_prompt), pin, pin_max, false)) { msg(M_FATAL, "Could not retrieve the PIN");