summaryrefslogtreecommitdiff
path: root/src/pki
diff options
context:
space:
mode:
Diffstat (limited to 'src/pki')
-rw-r--r--src/pki/Makefile.in6
-rw-r--r--src/pki/command.c2
-rw-r--r--src/pki/commands/acert.c5
-rw-r--r--src/pki/commands/gen.c2
-rw-r--r--src/pki/commands/issue.c5
-rw-r--r--src/pki/commands/keyid.c1
-rw-r--r--src/pki/commands/pkcs7.c1
-rw-r--r--src/pki/commands/print.c1
-rw-r--r--src/pki/commands/pub.c2
-rw-r--r--src/pki/commands/req.c5
-rw-r--r--src/pki/commands/self.c5
-rw-r--r--src/pki/commands/signcrl.c4
-rw-r--r--src/pki/commands/verify.c135
-rw-r--r--src/pki/man/Makefile.in6
-rw-r--r--src/pki/man/pki---verify.1.in16
-rw-r--r--src/pki/pki.c106
-rw-r--r--src/pki/pki.h5
17 files changed, 229 insertions, 78 deletions
diff --git a/src/pki/Makefile.in b/src/pki/Makefile.in
index 2dd91e801..8349a77f8 100644
--- a/src/pki/Makefile.in
+++ b/src/pki/Makefile.in
@@ -1,4 +1,4 @@
-# Makefile.in generated by automake 1.13.3 from Makefile.am.
+# Makefile.in generated by automake 1.14.1 from Makefile.am.
# @configure_input@
# Copyright (C) 1994-2013 Free Software Foundation, Inc.
@@ -280,6 +280,7 @@ NM = @NM@
NMEDIT = @NMEDIT@
OBJDUMP = @OBJDUMP@
OBJEXT = @OBJEXT@
+OPENSSL_LIB = @OPENSSL_LIB@
OTOOL = @OTOOL@
OTOOL64 = @OTOOL64@
PACKAGE = @PACKAGE@
@@ -298,6 +299,7 @@ PERL = @PERL@
PKG_CONFIG = @PKG_CONFIG@
PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
+PLUGIN_CFLAGS = @PLUGIN_CFLAGS@
PTHREADLIB = @PTHREADLIB@
PYTHON = @PYTHON@
PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
@@ -325,6 +327,7 @@ abs_top_srcdir = @abs_top_srcdir@
ac_ct_AR = @ac_ct_AR@
ac_ct_CC = @ac_ct_CC@
ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+aikgen_plugins = @aikgen_plugins@
am__include = @am__include@
am__leading_dot = @am__leading_dot@
am__quote = @am__quote@
@@ -416,6 +419,7 @@ srcdir = @srcdir@
starter_plugins = @starter_plugins@
strongswan_conf = @strongswan_conf@
strongswan_options = @strongswan_options@
+swanctldir = @swanctldir@
sysconfdir = @sysconfdir@
systemdsystemunitdir = @systemdsystemunitdir@
t_plugins = @t_plugins@
diff --git a/src/pki/command.c b/src/pki/command.c
index 075a2279a..13e81404c 100644
--- a/src/pki/command.c
+++ b/src/pki/command.c
@@ -73,7 +73,7 @@ static void build_opts()
memset(command_optstring, 0, sizeof(command_optstring));
if (active == help_idx)
{
- for (i = 0; cmds[i].cmd; i++)
+ for (i = 0; i < MAX_COMMANDS && cmds[i].cmd; i++)
{
command_opts[i].name = cmds[i].cmd;
command_opts[i].val = cmds[i].op;
diff --git a/src/pki/commands/acert.c b/src/pki/commands/acert.c
index d49365db5..185aa40b4 100644
--- a/src/pki/commands/acert.c
+++ b/src/pki/commands/acert.c
@@ -53,8 +53,7 @@ static int acert()
case 'h':
goto usage;
case 'g':
- digest = enum_from_name(hash_algorithm_short_names, arg);
- if (digest == -1)
+ if (!enum_from_name(hash_algorithm_short_names, arg, &digest))
{
error = "invalid --digest type";
goto usage;
@@ -197,6 +196,7 @@ static int acert()
}
else
{
+ set_file_mode(stdin, CERT_ASN1_DER);
if (!chunk_from_fd(0, &encoding))
{
fprintf(stderr, "%s: ", strerror(errno));
@@ -233,6 +233,7 @@ static int acert()
error = "encoding attribute certificate failed";
goto end;
}
+ set_file_mode(stdout, form);
if (fwrite(encoding.ptr, encoding.len, 1, stdout) != 1)
{
error = "writing attribute certificate key failed";
diff --git a/src/pki/commands/gen.c b/src/pki/commands/gen.c
index b74be7d98..ce28a0971 100644
--- a/src/pki/commands/gen.c
+++ b/src/pki/commands/gen.c
@@ -133,6 +133,7 @@ static int gen()
return 1;
}
key->destroy(key);
+ set_file_mode(stdout, form);
if (fwrite(encoding.ptr, encoding.len, 1, stdout) != 1)
{
fprintf(stderr, "writing private key failed\n");
@@ -163,4 +164,3 @@ static void __attribute__ ((constructor))reg()
}
});
}
-
diff --git a/src/pki/commands/issue.c b/src/pki/commands/issue.c
index d03326e3d..aaa2c2ff7 100644
--- a/src/pki/commands/issue.c
+++ b/src/pki/commands/issue.c
@@ -106,8 +106,7 @@ static int issue()
}
continue;
case 'g':
- digest = enum_from_name(hash_algorithm_short_names, arg);
- if (digest == -1)
+ if (!enum_from_name(hash_algorithm_short_names, arg, &digest))
{
error = "invalid --digest type";
goto usage;
@@ -403,6 +402,7 @@ static int issue()
{
chunk_t chunk;
+ set_file_mode(stdin, CERT_ASN1_DER);
if (!chunk_from_fd(0, &chunk))
{
fprintf(stderr, "%s: ", strerror(errno));
@@ -501,6 +501,7 @@ static int issue()
error = "encoding certificate failed";
goto end;
}
+ set_file_mode(stdout, form);
if (fwrite(encoding.ptr, encoding.len, 1, stdout) != 1)
{
error = "writing certificate key failed";
diff --git a/src/pki/commands/keyid.c b/src/pki/commands/keyid.c
index 64bb3cc2c..c3ac0c288 100644
--- a/src/pki/commands/keyid.c
+++ b/src/pki/commands/keyid.c
@@ -91,6 +91,7 @@ static int keyid()
{
chunk_t chunk;
+ set_file_mode(stdin, CERT_ASN1_DER);
if (!chunk_from_fd(0, &chunk))
{
fprintf(stderr, "reading input failed: %s\n", strerror(errno));
diff --git a/src/pki/commands/pkcs7.c b/src/pki/commands/pkcs7.c
index 6c75693ab..28bcd1397 100644
--- a/src/pki/commands/pkcs7.c
+++ b/src/pki/commands/pkcs7.c
@@ -58,6 +58,7 @@ static bool write_to_stream(FILE *stream, chunk_t data)
{
size_t len, total = 0;
+ set_file_mode(stream, CERT_ASN1_DER);
while (total < data.len)
{
len = fwrite(data.ptr + total, 1, data.len - total, stream);
diff --git a/src/pki/commands/print.c b/src/pki/commands/print.c
index 15ace035d..fb07169bf 100644
--- a/src/pki/commands/print.c
+++ b/src/pki/commands/print.c
@@ -604,6 +604,7 @@ static int print()
{
chunk_t chunk;
+ set_file_mode(stdin, CERT_ASN1_DER);
if (!chunk_from_fd(0, &chunk))
{
fprintf(stderr, "reading input failed: %s\n", strerror(errno));
diff --git a/src/pki/commands/pub.c b/src/pki/commands/pub.c
index 260044c4e..b8d2f701d 100644
--- a/src/pki/commands/pub.c
+++ b/src/pki/commands/pub.c
@@ -110,6 +110,7 @@ static int pub()
{
chunk_t chunk;
+ set_file_mode(stdin, CERT_ASN1_DER);
if (!chunk_from_fd(0, &chunk))
{
fprintf(stderr, "reading input failed: %s\n", strerror(errno));
@@ -163,6 +164,7 @@ static int pub()
return 1;
}
public->destroy(public);
+ set_file_mode(stdout, form);
if (fwrite(encoding.ptr, encoding.len, 1, stdout) != 1)
{
fprintf(stderr, "writing public key failed\n");
diff --git a/src/pki/commands/req.c b/src/pki/commands/req.c
index 5b2c128b7..023683569 100644
--- a/src/pki/commands/req.c
+++ b/src/pki/commands/req.c
@@ -64,8 +64,7 @@ static int req()
}
continue;
case 'g':
- digest = enum_from_name(hash_algorithm_short_names, arg);
- if (digest == -1)
+ if (!enum_from_name(hash_algorithm_short_names, arg, &digest))
{
error = "invalid --digest type";
goto usage;
@@ -119,6 +118,7 @@ static int req()
{
chunk_t chunk;
+ set_file_mode(stdin, CERT_ASN1_DER);
if (!chunk_from_fd(0, &chunk))
{
fprintf(stderr, "reading private key failed: %s\n", strerror(errno));
@@ -151,6 +151,7 @@ static int req()
error = "encoding certificate request failed";
goto end;
}
+ set_file_mode(stdout, form);
if (fwrite(encoding.ptr, encoding.len, 1, stdout) != 1)
{
error = "writing certificate request failed";
diff --git a/src/pki/commands/self.c b/src/pki/commands/self.c
index a35a42b89..daefcdc10 100644
--- a/src/pki/commands/self.c
+++ b/src/pki/commands/self.c
@@ -95,8 +95,7 @@ static int self()
}
continue;
case 'g':
- digest = enum_from_name(hash_algorithm_short_names, arg);
- if (digest == -1)
+ if (!enum_from_name(hash_algorithm_short_names, arg, &digest))
{
error = "invalid --digest type";
goto usage;
@@ -293,6 +292,7 @@ static int self()
{
chunk_t chunk;
+ set_file_mode(stdin, CERT_ASN1_DER);
if (!chunk_from_fd(0, &chunk))
{
fprintf(stderr, "%s: ", strerror(errno));
@@ -361,6 +361,7 @@ static int self()
error = "encoding certificate failed";
goto end;
}
+ set_file_mode(stdout, form);
if (fwrite(encoding.ptr, encoding.len, 1, stdout) != 1)
{
error = "writing certificate key failed";
diff --git a/src/pki/commands/signcrl.c b/src/pki/commands/signcrl.c
index c9eebbf59..e5f49efe2 100644
--- a/src/pki/commands/signcrl.c
+++ b/src/pki/commands/signcrl.c
@@ -142,8 +142,7 @@ static int sign_crl()
case 'h':
goto usage;
case 'g':
- digest = enum_from_name(hash_algorithm_short_names, arg);
- if (digest == -1)
+ if (!enum_from_name(hash_algorithm_short_names, arg, &digest))
{
error = "invalid --digest type";
goto usage;
@@ -406,6 +405,7 @@ static int sign_crl()
error = "encoding CRL failed";
goto error;
}
+ set_file_mode(stdout, form);
if (fwrite(encoding.ptr, encoding.len, 1, stdout) != 1)
{
error = "writing CRL failed";
diff --git a/src/pki/commands/verify.c b/src/pki/commands/verify.c
index f30dda94d..8cc633a95 100644
--- a/src/pki/commands/verify.c
+++ b/src/pki/commands/verify.c
@@ -19,32 +19,53 @@
#include <credentials/certificates/certificate.h>
#include <credentials/certificates/x509.h>
+#include <credentials/sets/mem_cred.h>
/**
* Verify a certificate signature
*/
static int verify()
{
- certificate_t *cert, *ca;
- char *file = NULL, *cafile = NULL;
- bool good = FALSE;
- char *arg;
+ bool trusted = FALSE, valid = FALSE, revoked = FALSE;
+ bool has_ca = FALSE, online = FALSE;
+ certificate_t *cert;
+ enumerator_t *enumerator;
+ auth_cfg_t *auth;
+ mem_cred_t *creds;
+ char *arg, *file = NULL;
+
+ creds = mem_cred_create();
+ lib->credmgr->add_set(lib->credmgr, &creds->set);
while (TRUE)
{
switch (command_getopt(&arg))
{
case 'h':
+ creds->destroy(creds);
return command_usage(NULL);
case 'i':
file = arg;
continue;
case 'c':
- cafile = arg;
+ cert = lib->creds->create(lib->creds,
+ CRED_CERTIFICATE, CERT_X509,
+ BUILD_FROM_FILE, arg, BUILD_END);
+ if (!cert)
+ {
+ fprintf(stderr, "parsing CA certificate failed\n");
+ goto end;
+ }
+ has_ca = TRUE;
+ creds->add_cert(creds, TRUE, cert);
+ continue;
+ case 'o':
+ online = TRUE;
continue;
case EOF:
break;
default:
+ creds->destroy(creds);
return command_usage("invalid --verify option");
}
break;
@@ -59,10 +80,11 @@ static int verify()
{
chunk_t chunk;
+ set_file_mode(stdin, CERT_ASN1_DER);
if (!chunk_from_fd(0, &chunk))
{
fprintf(stderr, "reading certificate failed: %s\n", strerror(errno));
- return 1;
+ goto end;
}
cert = lib->creds->create(lib->creds, CRED_CERTIFICATE, CERT_X509,
BUILD_BLOB, chunk, BUILD_END);
@@ -71,60 +93,76 @@ static int verify()
if (!cert)
{
fprintf(stderr, "parsing certificate failed\n");
- return 1;
- }
- if (cafile)
- {
- ca = lib->creds->create(lib->creds, CRED_CERTIFICATE, CERT_X509,
- BUILD_FROM_FILE, cafile, BUILD_END);
- if (!ca)
- {
- fprintf(stderr, "parsing CA certificate failed\n");
- return 1;
- }
+ goto end;
}
- else
- {
- ca = cert;
- }
- if (cert->issued_by(cert, ca, NULL))
+ creds->add_cert(creds, !has_ca, cert);
+
+ enumerator = lib->credmgr->create_trusted_enumerator(lib->credmgr,
+ KEY_ANY, cert->get_subject(cert), online);
+ if (enumerator->enumerate(enumerator, &cert, &auth))
{
+ trusted = TRUE;
if (cert->get_validity(cert, NULL, NULL, NULL))
{
- if (cafile)
- {
- if (ca->get_validity(ca, NULL, NULL, NULL))
- {
- printf("signature good, certificates valid\n");
- good = TRUE;
- }
- else
- {
- printf("signature good, CA certificates not valid now\n");
- }
- }
- else
- {
- printf("signature good, certificate valid\n");
- good = TRUE;
- }
+ printf("certificate trusted, lifetimes valid");
+ valid = TRUE;
}
else
{
- printf("certificate not valid now\n");
+ printf("certificate trusted, but no valid lifetime");
}
+ if (online)
+ {
+ switch ((uintptr_t)auth->get(auth, AUTH_RULE_CRL_VALIDATION))
+ {
+ case VALIDATION_GOOD:
+ printf(", certificate not revoked");
+ break;
+ case VALIDATION_SKIPPED:
+ printf(", no revocation information");
+ break;
+ case VALIDATION_STALE:
+ printf(", revocation information stale");
+ break;
+ case VALIDATION_FAILED:
+ printf(", revocation checking failed");
+ break;
+ case VALIDATION_ON_HOLD:
+ printf(", certificate revocation on hold");
+ revoked = TRUE;
+ break;
+ case VALIDATION_REVOKED:
+ printf(", certificate revoked");
+ revoked = TRUE;
+ break;
+ }
+ }
+ printf("\n");
}
- else
+ enumerator->destroy(enumerator);
+
+ if (!trusted)
{
- printf("signature invalid\n");
+ printf("certificate untrusted\n");
}
- if (cafile)
+
+end:
+ lib->credmgr->remove_set(lib->credmgr, &creds->set);
+ creds->destroy(creds);
+
+ if (!trusted)
{
- ca->destroy(ca);
+ return 1;
}
- cert->destroy(cert);
-
- return good ? 0 : 2;
+ if (!valid)
+ {
+ return 2;
+ }
+ if (revoked)
+ {
+ return 3;
+ }
+ return 0;
}
/**
@@ -139,7 +177,8 @@ static void __attribute__ ((constructor))reg()
{
{"help", 'h', 0, "show usage information"},
{"in", 'i', 1, "X.509 certificate to verify, default: stdin"},
- {"cacert", 'c', 1, "CA certificate, default: verify self signed"},
+ {"cacert", 'c', 1, "CA certificate for trustchain verification"},
+ {"online", 'o', 0, "enable online CRL/OCSP revocation checking"},
}
});
}
diff --git a/src/pki/man/Makefile.in b/src/pki/man/Makefile.in
index 5d901a87e..4c0efd5a7 100644
--- a/src/pki/man/Makefile.in
+++ b/src/pki/man/Makefile.in
@@ -1,4 +1,4 @@
-# Makefile.in generated by automake 1.13.3 from Makefile.am.
+# Makefile.in generated by automake 1.14.1 from Makefile.am.
# @configure_input@
# Copyright (C) 1994-2013 Free Software Foundation, Inc.
@@ -218,6 +218,7 @@ NM = @NM@
NMEDIT = @NMEDIT@
OBJDUMP = @OBJDUMP@
OBJEXT = @OBJEXT@
+OPENSSL_LIB = @OPENSSL_LIB@
OTOOL = @OTOOL@
OTOOL64 = @OTOOL64@
PACKAGE = @PACKAGE@
@@ -236,6 +237,7 @@ PERL = @PERL@
PKG_CONFIG = @PKG_CONFIG@
PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
+PLUGIN_CFLAGS = @PLUGIN_CFLAGS@
PTHREADLIB = @PTHREADLIB@
PYTHON = @PYTHON@
PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
@@ -263,6 +265,7 @@ abs_top_srcdir = @abs_top_srcdir@
ac_ct_AR = @ac_ct_AR@
ac_ct_CC = @ac_ct_CC@
ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+aikgen_plugins = @aikgen_plugins@
am__include = @am__include@
am__leading_dot = @am__leading_dot@
am__quote = @am__quote@
@@ -354,6 +357,7 @@ srcdir = @srcdir@
starter_plugins = @starter_plugins@
strongswan_conf = @strongswan_conf@
strongswan_options = @strongswan_options@
+swanctldir = @swanctldir@
sysconfdir = @sysconfdir@
systemdsystemunitdir = @systemdsystemunitdir@
t_plugins = @t_plugins@
diff --git a/src/pki/man/pki---verify.1.in b/src/pki/man/pki---verify.1.in
index de34acad4..dd0c0e928 100644
--- a/src/pki/man/pki---verify.1.in
+++ b/src/pki/man/pki---verify.1.in
@@ -10,6 +10,7 @@ pki \-\-verify \- Verify a certificate using a CA certificate
.OP \-\-in file
.OP \-\-cacert file
.OP \-\-debug level
+.OP \-\-online
.YS
.
.SY pki\ \-\-verify
@@ -44,13 +45,18 @@ Read command line options from \fIfile\fR.
X.509 certificate to verify. If not given it is read from \fISTDIN\fR.
.TP
.BI "\-c, \-\-cacert " file
-CA certificate to use. If not given the certificate is assumed to be
-self-signed.
+CA certificate to use for trustchain verification. If not given the certificate
+is assumed to be self\-signed.
+.TP
+.BI "\-o, \-\-online
+Enable online CRL/OCSP revocation checking.
.
.SH "EXIT STATUS"
-The exit status is 0 if the certificate was verified successfully, and 2 if
-the verification failed.
+The exit status is 0 if the certificate was verified successfully, 1 if the
+certificate is untrusted, 2 if the certificate's lifetimes are invalid, and 3
+if the certificate was verified successfully but the online revocation check
+indicated that it has been revoked.
.
.SH "SEE ALSO"
.
-.BR pki (1) \ No newline at end of file
+.BR pki (1)
diff --git a/src/pki/pki.c b/src/pki/pki.c
index ae4ef1cb0..434287de6 100644
--- a/src/pki/pki.c
+++ b/src/pki/pki.c
@@ -19,6 +19,7 @@
#include <time.h>
#include <unistd.h>
+#include <fcntl.h>
#include <utils/debug.h>
#include <credentials/sets/callback_cred.h>
@@ -104,13 +105,12 @@ bool get_form(char *form, cred_encoding_type_t *enc, credential_type_t type)
}
/**
- * See header
+ * Convert a time string to struct tm using strptime format
*/
-bool calculate_lifetime(char *format, char *nbstr, char *nastr, time_t span,
- time_t *nb, time_t *na)
+static bool convert_time(char *str, char *format, struct tm *tm)
{
- struct tm tm;
- time_t now;
+#ifdef HAVE_STRPTIME
+
char *end;
if (!format)
@@ -118,29 +118,84 @@ bool calculate_lifetime(char *format, char *nbstr, char *nastr, time_t span,
format = "%d.%m.%y %T";
}
+ end = strptime(str, format, tm);
+ if (end == NULL || *end != '\0')
+ {
+ return FALSE;
+ }
+ return TRUE;
+
+#else /* !HAVE_STRPTIME */
+
+ if (format)
+ {
+ fprintf(stderr, "custom datetime string format not supported\n");
+ return FALSE;
+ }
+
+ if (sscanf(str, "%d.%d.%d %d:%d:%d",
+ &tm->tm_mday, &tm->tm_mon, &tm->tm_year,
+ &tm->tm_hour, &tm->tm_min, &tm->tm_sec) != 6)
+ {
+ return FALSE;
+ }
+ /* strptime() interprets two-digit years > 68 as 19xx, do the same here.
+ * mktime() expects years based on 1900 */
+ if (tm->tm_year <= 68)
+ {
+ tm->tm_year += 100;
+ }
+ else if (tm->tm_year >= 1900)
+ { /* looks like four digits? */
+ tm->tm_year -= 1900;
+ }
+ /* month is specified from 0-11 */
+ tm->tm_mon--;
+ /* automatically detect daylight saving time */
+ tm->tm_isdst = -1;
+ return TRUE;
+
+#endif /* !HAVE_STRPTIME */
+}
+
+/**
+ * See header
+ */
+bool calculate_lifetime(char *format, char *nbstr, char *nastr, time_t span,
+ time_t *nb, time_t *na)
+{
+ struct tm tm;
+ time_t now;
+
now = time(NULL);
localtime_r(&now, &tm);
if (nbstr)
{
- end = strptime(nbstr, format, &tm);
- if (end == NULL || *end != '\0')
+ if (!convert_time(nbstr, format, &tm))
{
return FALSE;
}
}
*nb = mktime(&tm);
+ if (*nb == -1)
+ {
+ return FALSE;
+ }
localtime_r(&now, &tm);
if (nastr)
{
- end = strptime(nastr, format, &tm);
- if (end == NULL || *end != '\0')
+ if (!convert_time(nastr, format, &tm))
{
return FALSE;
}
}
*na = mktime(&tm);
+ if (*na == -1)
+ {
+ return FALSE;
+ }
if (!nbstr && nastr)
{
@@ -154,6 +209,33 @@ bool calculate_lifetime(char *format, char *nbstr, char *nastr, time_t span,
}
/**
+ * Set output file mode appropriate for credential encoding form on Windows
+ */
+void set_file_mode(FILE *stream, cred_encoding_type_t enc)
+{
+#ifdef WIN32
+ int fd;
+
+ switch (enc)
+ {
+ case CERT_PEM:
+ case PRIVKEY_PEM:
+ case PUBKEY_PEM:
+ /* keep default text mode */
+ return;
+ default:
+ /* switch to binary mode */
+ break;
+ }
+ fd = fileno(stream);
+ if (fd != -1)
+ {
+ _setmode(fd, _O_BINARY);
+ }
+#endif
+}
+
+/**
* Callback credential set pki uses
*/
static callback_cred_t *cb_set;
@@ -165,7 +247,7 @@ static shared_key_t* cb(void *data, shared_key_type_t type,
identification_t *me, identification_t *other,
id_match_t *match_me, id_match_t *match_other)
{
- char buf[64], *label, *secret;
+ char buf[64], *label, *secret = NULL;
switch (type)
{
@@ -179,8 +261,10 @@ static shared_key_t* cb(void *data, shared_key_type_t type,
return NULL;
}
snprintf(buf, sizeof(buf), "%s: ", label);
+#ifdef HAVE_GETPASS
secret = getpass(buf);
- if (secret)
+#endif
+ if (secret && strlen(secret))
{
if (match_me)
{
diff --git a/src/pki/pki.h b/src/pki/pki.h
index 616fac44a..1f0827733 100644
--- a/src/pki/pki.h
+++ b/src/pki/pki.h
@@ -50,4 +50,9 @@ bool get_form(char *form, cred_encoding_type_t *enc, credential_type_t type);
bool calculate_lifetime(char *format, char *nbstr, char *nastr, time_t span,
time_t *nb, time_t *na);
+/**
+ * Set output file mode appropriate for credential encoding form on Windows
+ */
+void set_file_mode(FILE *stream, cred_encoding_type_t enc);
+
#endif /** PKI_H_ @}*/