upstream: allow key revocation by SHA256 hash and allow ssh-keygen
to create KRLs using SHA256/base64 key fingerprints; ok markus@ OpenBSD-Commit-ID: a0590fd34e7f1141f2873ab3acc57442560e6a94
This commit is contained in:
parent
50e2687ee0
commit
9405c6214f
16
PROTOCOL.krl
16
PROTOCOL.krl
|
@ -36,6 +36,7 @@ The available section types are:
|
||||||
#define KRL_SECTION_EXPLICIT_KEY 2
|
#define KRL_SECTION_EXPLICIT_KEY 2
|
||||||
#define KRL_SECTION_FINGERPRINT_SHA1 3
|
#define KRL_SECTION_FINGERPRINT_SHA1 3
|
||||||
#define KRL_SECTION_SIGNATURE 4
|
#define KRL_SECTION_SIGNATURE 4
|
||||||
|
#define KRL_SECTION_FINGERPRINT_SHA256 5
|
||||||
|
|
||||||
2. Certificate section
|
2. Certificate section
|
||||||
|
|
||||||
|
@ -127,18 +128,19 @@ must be a raw key (i.e. not a certificate).
|
||||||
|
|
||||||
This section may appear multiple times.
|
This section may appear multiple times.
|
||||||
|
|
||||||
4. SHA1 fingerprint sections
|
4. SHA1/SHA256 fingerprint sections
|
||||||
|
|
||||||
These sections, identified as KRL_SECTION_FINGERPRINT_SHA1, revoke
|
These sections, identified as KRL_SECTION_FINGERPRINT_SHA1 and
|
||||||
plain keys (i.e. not certificates) by listing their SHA1 hashes:
|
KRL_SECTION_FINGERPRINT_SHA256, revoke plain keys (i.e. not
|
||||||
|
certificates) by listing their hashes:
|
||||||
|
|
||||||
string public_key_hash[0]
|
string public_key_hash[0]
|
||||||
....
|
....
|
||||||
|
|
||||||
This section must contain at least one "public_key_hash". The hash blob
|
This section must contain at least one "public_key_hash". The hash blob
|
||||||
is obtained by taking the SHA1 hash of the public key blob. Hashes in
|
is obtained by taking the SHA1 or SHA256 hash of the public key blob.
|
||||||
this section must appear in numeric order, treating each hash as a big-
|
Hashes in this section must appear in numeric order, treating each hash
|
||||||
endian integer.
|
as a big-endian integer.
|
||||||
|
|
||||||
This section may appear multiple times.
|
This section may appear multiple times.
|
||||||
|
|
||||||
|
@ -166,4 +168,4 @@ Implementations that retrieve KRLs over untrusted channels must verify
|
||||||
signatures. Signature sections are optional for KRLs distributed by
|
signatures. Signature sections are optional for KRLs distributed by
|
||||||
trusted means.
|
trusted means.
|
||||||
|
|
||||||
$OpenBSD: PROTOCOL.krl,v 1.4 2018/04/10 00:10:49 djm Exp $
|
$OpenBSD: PROTOCOL.krl,v 1.5 2018/09/12 01:21:34 djm Exp $
|
||||||
|
|
126
krl.c
126
krl.c
|
@ -14,7 +14,7 @@
|
||||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* $OpenBSD: krl.c,v 1.41 2017/12/18 02:25:15 djm Exp $ */
|
/* $OpenBSD: krl.c,v 1.42 2018/09/12 01:21:34 djm Exp $ */
|
||||||
|
|
||||||
#include "includes.h"
|
#include "includes.h"
|
||||||
|
|
||||||
|
@ -96,6 +96,7 @@ struct ssh_krl {
|
||||||
char *comment;
|
char *comment;
|
||||||
struct revoked_blob_tree revoked_keys;
|
struct revoked_blob_tree revoked_keys;
|
||||||
struct revoked_blob_tree revoked_sha1s;
|
struct revoked_blob_tree revoked_sha1s;
|
||||||
|
struct revoked_blob_tree revoked_sha256s;
|
||||||
struct revoked_certs_list revoked_certs;
|
struct revoked_certs_list revoked_certs;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -136,6 +137,7 @@ ssh_krl_init(void)
|
||||||
return NULL;
|
return NULL;
|
||||||
RB_INIT(&krl->revoked_keys);
|
RB_INIT(&krl->revoked_keys);
|
||||||
RB_INIT(&krl->revoked_sha1s);
|
RB_INIT(&krl->revoked_sha1s);
|
||||||
|
RB_INIT(&krl->revoked_sha256s);
|
||||||
TAILQ_INIT(&krl->revoked_certs);
|
TAILQ_INIT(&krl->revoked_certs);
|
||||||
return krl;
|
return krl;
|
||||||
}
|
}
|
||||||
|
@ -178,6 +180,11 @@ ssh_krl_free(struct ssh_krl *krl)
|
||||||
free(rb->blob);
|
free(rb->blob);
|
||||||
free(rb);
|
free(rb);
|
||||||
}
|
}
|
||||||
|
RB_FOREACH_SAFE(rb, revoked_blob_tree, &krl->revoked_sha256s, trb) {
|
||||||
|
RB_REMOVE(revoked_blob_tree, &krl->revoked_sha256s, rb);
|
||||||
|
free(rb->blob);
|
||||||
|
free(rb);
|
||||||
|
}
|
||||||
TAILQ_FOREACH_SAFE(rc, &krl->revoked_certs, entry, trc) {
|
TAILQ_FOREACH_SAFE(rc, &krl->revoked_certs, entry, trc) {
|
||||||
TAILQ_REMOVE(&krl->revoked_certs, rc, entry);
|
TAILQ_REMOVE(&krl->revoked_certs, rc, entry);
|
||||||
revoked_certs_free(rc);
|
revoked_certs_free(rc);
|
||||||
|
@ -408,25 +415,47 @@ ssh_krl_revoke_key_explicit(struct ssh_krl *krl, const struct sshkey *key)
|
||||||
return revoke_blob(&krl->revoked_keys, blob, len);
|
return revoke_blob(&krl->revoked_keys, blob, len);
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
static int
|
||||||
ssh_krl_revoke_key_sha1(struct ssh_krl *krl, const struct sshkey *key)
|
revoke_by_hash(struct revoked_blob_tree *target, const u_char *p, size_t len)
|
||||||
{
|
{
|
||||||
u_char *blob;
|
u_char *blob;
|
||||||
size_t len;
|
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
debug3("%s: revoke type %s by sha1", __func__, sshkey_type(key));
|
/* need to copy hash, as revoke_blob steals ownership */
|
||||||
if ((r = sshkey_fingerprint_raw(key, SSH_DIGEST_SHA1,
|
if ((blob = malloc(len)) == NULL)
|
||||||
&blob, &len)) != 0)
|
return SSH_ERR_SYSTEM_ERROR;
|
||||||
|
memcpy(blob, p, len);
|
||||||
|
if ((r = revoke_blob(target, blob, len)) != 0) {
|
||||||
|
free(blob);
|
||||||
return r;
|
return r;
|
||||||
return revoke_blob(&krl->revoked_sha1s, blob, len);
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
ssh_krl_revoke_key_sha1(struct ssh_krl *krl, const u_char *p, size_t len)
|
||||||
|
{
|
||||||
|
debug3("%s: revoke by sha1", __func__);
|
||||||
|
if (len != 20)
|
||||||
|
return SSH_ERR_INVALID_FORMAT;
|
||||||
|
return revoke_by_hash(&krl->revoked_sha1s, p, len);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
ssh_krl_revoke_key_sha256(struct ssh_krl *krl, const u_char *p, size_t len)
|
||||||
|
{
|
||||||
|
debug3("%s: revoke by sha256", __func__);
|
||||||
|
if (len != 32)
|
||||||
|
return SSH_ERR_INVALID_FORMAT;
|
||||||
|
return revoke_by_hash(&krl->revoked_sha256s, p, len);
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
ssh_krl_revoke_key(struct ssh_krl *krl, const struct sshkey *key)
|
ssh_krl_revoke_key(struct ssh_krl *krl, const struct sshkey *key)
|
||||||
{
|
{
|
||||||
|
/* XXX replace with SHA256? */
|
||||||
if (!sshkey_is_cert(key))
|
if (!sshkey_is_cert(key))
|
||||||
return ssh_krl_revoke_key_sha1(krl, key);
|
return ssh_krl_revoke_key_explicit(krl, key);
|
||||||
|
|
||||||
if (key->cert->serial == 0) {
|
if (key->cert->serial == 0) {
|
||||||
return ssh_krl_revoke_cert_by_key_id(krl,
|
return ssh_krl_revoke_cert_by_key_id(krl,
|
||||||
|
@ -762,6 +791,18 @@ ssh_krl_to_blob(struct ssh_krl *krl, struct sshbuf *buf,
|
||||||
(r = sshbuf_put_stringb(buf, sect)) != 0)
|
(r = sshbuf_put_stringb(buf, sect)) != 0)
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
sshbuf_reset(sect);
|
||||||
|
RB_FOREACH(rb, revoked_blob_tree, &krl->revoked_sha256s) {
|
||||||
|
KRL_DBG(("%s: hash len %zu ", __func__, rb->len));
|
||||||
|
if ((r = sshbuf_put_string(sect, rb->blob, rb->len)) != 0)
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
if (sshbuf_len(sect) != 0) {
|
||||||
|
if ((r = sshbuf_put_u8(buf,
|
||||||
|
KRL_SECTION_FINGERPRINT_SHA256)) != 0 ||
|
||||||
|
(r = sshbuf_put_stringb(buf, sect)) != 0)
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
for (i = 0; i < nsign_keys; i++) {
|
for (i = 0; i < nsign_keys; i++) {
|
||||||
KRL_DBG(("%s: signature key %s", __func__,
|
KRL_DBG(("%s: signature key %s", __func__,
|
||||||
|
@ -914,6 +955,29 @@ parse_revoked_certs(struct sshbuf *buf, struct ssh_krl *krl)
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
blob_section(struct sshbuf *sect, struct revoked_blob_tree *target_tree,
|
||||||
|
size_t expected_len)
|
||||||
|
{
|
||||||
|
u_char *rdata = NULL;
|
||||||
|
size_t rlen = 0;
|
||||||
|
int r;
|
||||||
|
|
||||||
|
while (sshbuf_len(sect) > 0) {
|
||||||
|
if ((r = sshbuf_get_string(sect, &rdata, &rlen)) != 0)
|
||||||
|
return r;
|
||||||
|
if (expected_len != 0 && rlen != expected_len) {
|
||||||
|
error("%s: bad length", __func__);
|
||||||
|
free(rdata);
|
||||||
|
return SSH_ERR_INVALID_FORMAT;
|
||||||
|
}
|
||||||
|
if ((r = revoke_blob(target_tree, rdata, rlen)) != 0) {
|
||||||
|
free(rdata);
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/* Attempt to parse a KRL, checking its signature (if any) with sign_ca_keys. */
|
/* Attempt to parse a KRL, checking its signature (if any) with sign_ca_keys. */
|
||||||
int
|
int
|
||||||
|
@ -925,9 +989,9 @@ ssh_krl_from_blob(struct sshbuf *buf, struct ssh_krl **krlp,
|
||||||
char timestamp[64];
|
char timestamp[64];
|
||||||
int r = SSH_ERR_INTERNAL_ERROR, sig_seen;
|
int r = SSH_ERR_INTERNAL_ERROR, sig_seen;
|
||||||
struct sshkey *key = NULL, **ca_used = NULL, **tmp_ca_used;
|
struct sshkey *key = NULL, **ca_used = NULL, **tmp_ca_used;
|
||||||
u_char type, *rdata = NULL;
|
u_char type;
|
||||||
const u_char *blob;
|
const u_char *blob;
|
||||||
size_t i, j, sig_off, sects_off, rlen, blen, nca_used;
|
size_t i, j, sig_off, sects_off, blen, nca_used;
|
||||||
u_int format_version;
|
u_int format_version;
|
||||||
|
|
||||||
nca_used = 0;
|
nca_used = 0;
|
||||||
|
@ -1068,24 +1132,19 @@ ssh_krl_from_blob(struct sshbuf *buf, struct ssh_krl **krlp,
|
||||||
goto out;
|
goto out;
|
||||||
break;
|
break;
|
||||||
case KRL_SECTION_EXPLICIT_KEY:
|
case KRL_SECTION_EXPLICIT_KEY:
|
||||||
|
if ((r = blob_section(sect,
|
||||||
|
&krl->revoked_keys, 0)) != 0)
|
||||||
|
goto out;
|
||||||
|
break;
|
||||||
case KRL_SECTION_FINGERPRINT_SHA1:
|
case KRL_SECTION_FINGERPRINT_SHA1:
|
||||||
while (sshbuf_len(sect) > 0) {
|
if ((r = blob_section(sect,
|
||||||
if ((r = sshbuf_get_string(sect,
|
&krl->revoked_sha1s, 20)) != 0)
|
||||||
&rdata, &rlen)) != 0)
|
goto out;
|
||||||
goto out;
|
break;
|
||||||
if (type == KRL_SECTION_FINGERPRINT_SHA1 &&
|
case KRL_SECTION_FINGERPRINT_SHA256:
|
||||||
rlen != 20) {
|
if ((r = blob_section(sect,
|
||||||
error("%s: bad SHA1 length", __func__);
|
&krl->revoked_sha256s, 32)) != 0)
|
||||||
r = SSH_ERR_INVALID_FORMAT;
|
goto out;
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
if ((r = revoke_blob(
|
|
||||||
type == KRL_SECTION_EXPLICIT_KEY ?
|
|
||||||
&krl->revoked_keys : &krl->revoked_sha1s,
|
|
||||||
rdata, rlen)) != 0)
|
|
||||||
goto out;
|
|
||||||
rdata = NULL; /* revoke_blob frees rdata */
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
case KRL_SECTION_SIGNATURE:
|
case KRL_SECTION_SIGNATURE:
|
||||||
/* Handled above, but still need to stay in synch */
|
/* Handled above, but still need to stay in synch */
|
||||||
|
@ -1150,7 +1209,6 @@ ssh_krl_from_blob(struct sshbuf *buf, struct ssh_krl **krlp,
|
||||||
for (i = 0; i < nca_used; i++)
|
for (i = 0; i < nca_used; i++)
|
||||||
sshkey_free(ca_used[i]);
|
sshkey_free(ca_used[i]);
|
||||||
free(ca_used);
|
free(ca_used);
|
||||||
free(rdata);
|
|
||||||
sshkey_free(key);
|
sshkey_free(key);
|
||||||
sshbuf_free(copy);
|
sshbuf_free(copy);
|
||||||
sshbuf_free(sect);
|
sshbuf_free(sect);
|
||||||
|
@ -1210,6 +1268,16 @@ is_key_revoked(struct ssh_krl *krl, const struct sshkey *key)
|
||||||
KRL_DBG(("%s: revoked by key SHA1", __func__));
|
KRL_DBG(("%s: revoked by key SHA1", __func__));
|
||||||
return SSH_ERR_KEY_REVOKED;
|
return SSH_ERR_KEY_REVOKED;
|
||||||
}
|
}
|
||||||
|
memset(&rb, 0, sizeof(rb));
|
||||||
|
if ((r = sshkey_fingerprint_raw(key, SSH_DIGEST_SHA256,
|
||||||
|
&rb.blob, &rb.len)) != 0)
|
||||||
|
return r;
|
||||||
|
erb = RB_FIND(revoked_blob_tree, &krl->revoked_sha256s, &rb);
|
||||||
|
free(rb.blob);
|
||||||
|
if (erb != NULL) {
|
||||||
|
KRL_DBG(("%s: revoked by key SHA256", __func__));
|
||||||
|
return SSH_ERR_KEY_REVOKED;
|
||||||
|
}
|
||||||
|
|
||||||
/* Next, explicit keys */
|
/* Next, explicit keys */
|
||||||
memset(&rb, 0, sizeof(rb));
|
memset(&rb, 0, sizeof(rb));
|
||||||
|
|
6
krl.h
6
krl.h
|
@ -14,7 +14,7 @@
|
||||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* $OpenBSD: krl.h,v 1.5 2015/12/30 23:46:14 djm Exp $ */
|
/* $OpenBSD: krl.h,v 1.6 2018/09/12 01:21:34 djm Exp $ */
|
||||||
|
|
||||||
#ifndef _KRL_H
|
#ifndef _KRL_H
|
||||||
#define _KRL_H
|
#define _KRL_H
|
||||||
|
@ -29,6 +29,7 @@
|
||||||
#define KRL_SECTION_EXPLICIT_KEY 2
|
#define KRL_SECTION_EXPLICIT_KEY 2
|
||||||
#define KRL_SECTION_FINGERPRINT_SHA1 3
|
#define KRL_SECTION_FINGERPRINT_SHA1 3
|
||||||
#define KRL_SECTION_SIGNATURE 4
|
#define KRL_SECTION_SIGNATURE 4
|
||||||
|
#define KRL_SECTION_FINGERPRINT_SHA256 5
|
||||||
|
|
||||||
/* KRL_SECTION_CERTIFICATES subsection types */
|
/* KRL_SECTION_CERTIFICATES subsection types */
|
||||||
#define KRL_SECTION_CERT_SERIAL_LIST 0x20
|
#define KRL_SECTION_CERT_SERIAL_LIST 0x20
|
||||||
|
@ -51,7 +52,8 @@ int ssh_krl_revoke_cert_by_serial_range(struct ssh_krl *krl,
|
||||||
int ssh_krl_revoke_cert_by_key_id(struct ssh_krl *krl,
|
int ssh_krl_revoke_cert_by_key_id(struct ssh_krl *krl,
|
||||||
const struct sshkey *ca_key, const char *key_id);
|
const struct sshkey *ca_key, const char *key_id);
|
||||||
int ssh_krl_revoke_key_explicit(struct ssh_krl *krl, const struct sshkey *key);
|
int ssh_krl_revoke_key_explicit(struct ssh_krl *krl, const struct sshkey *key);
|
||||||
int ssh_krl_revoke_key_sha1(struct ssh_krl *krl, const struct sshkey *key);
|
int ssh_krl_revoke_key_sha1(struct ssh_krl *krl, const u_char *p, size_t len);
|
||||||
|
int ssh_krl_revoke_key_sha256(struct ssh_krl *krl, const u_char *p, size_t len);
|
||||||
int ssh_krl_revoke_key(struct ssh_krl *krl, const struct sshkey *key);
|
int ssh_krl_revoke_key(struct ssh_krl *krl, const struct sshkey *key);
|
||||||
int ssh_krl_to_blob(struct ssh_krl *krl, struct sshbuf *buf,
|
int ssh_krl_to_blob(struct ssh_krl *krl, struct sshbuf *buf,
|
||||||
const struct sshkey **sign_keys, u_int nsign_keys);
|
const struct sshkey **sign_keys, u_int nsign_keys);
|
||||||
|
|
19
ssh-keygen.1
19
ssh-keygen.1
|
@ -1,4 +1,4 @@
|
||||||
.\" $OpenBSD: ssh-keygen.1,v 1.148 2018/08/08 01:16:01 djm Exp $
|
.\" $OpenBSD: ssh-keygen.1,v 1.149 2018/09/12 01:21:34 djm Exp $
|
||||||
.\"
|
.\"
|
||||||
.\" Author: Tatu Ylonen <ylo@cs.hut.fi>
|
.\" Author: Tatu Ylonen <ylo@cs.hut.fi>
|
||||||
.\" Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
|
.\" Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
|
||||||
|
@ -35,7 +35,7 @@
|
||||||
.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||||
.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
.\"
|
.\"
|
||||||
.Dd $Mdocdate: August 8 2018 $
|
.Dd $Mdocdate: September 12 2018 $
|
||||||
.Dt SSH-KEYGEN 1
|
.Dt SSH-KEYGEN 1
|
||||||
.Os
|
.Os
|
||||||
.Sh NAME
|
.Sh NAME
|
||||||
|
@ -814,7 +814,20 @@ option.
|
||||||
Revokes the specified key.
|
Revokes the specified key.
|
||||||
If a certificate is listed, then it is revoked as a plain public key.
|
If a certificate is listed, then it is revoked as a plain public key.
|
||||||
.It Cm sha1 : Ar public_key
|
.It Cm sha1 : Ar public_key
|
||||||
Revokes the specified key by its SHA1 hash.
|
Revokes the specified key by including its SHA1 hash in the KRL.
|
||||||
|
.It Cm sha256 : Ar public_key
|
||||||
|
Revokes the specified key by including its SHA256 hash in the KRL.
|
||||||
|
KRLs that revoke keys by SHA256 hash are not supported by OpenSSH versions
|
||||||
|
prior to 7.9.
|
||||||
|
.It Cm hash : Ar fingerprint
|
||||||
|
Revokes a key using by fingerprint hash, as obtained from a
|
||||||
|
.Xr sshd 8
|
||||||
|
authentication log message or the
|
||||||
|
.Nm
|
||||||
|
.Fl l
|
||||||
|
flag.
|
||||||
|
Only SHA256 fingerprints are supported here and resultant KRLs are
|
||||||
|
not supported by OpenSSH versions prior to 7.9.
|
||||||
.El
|
.El
|
||||||
.Pp
|
.Pp
|
||||||
KRLs may be updated using the
|
KRLs may be updated using the
|
||||||
|
|
75
ssh-keygen.c
75
ssh-keygen.c
|
@ -1,4 +1,4 @@
|
||||||
/* $OpenBSD: ssh-keygen.c,v 1.319 2018/08/08 01:16:01 djm Exp $ */
|
/* $OpenBSD: ssh-keygen.c,v 1.320 2018/09/12 01:21:34 djm Exp $ */
|
||||||
/*
|
/*
|
||||||
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
||||||
* Copyright (c) 1994 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
|
* Copyright (c) 1994 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
|
||||||
|
@ -2079,6 +2079,41 @@ load_krl(const char *path, struct ssh_krl **krlp)
|
||||||
sshbuf_free(krlbuf);
|
sshbuf_free(krlbuf);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
hash_to_blob(const char *cp, u_char **blobp, size_t *lenp,
|
||||||
|
const char *file, u_long lnum)
|
||||||
|
{
|
||||||
|
char *tmp;
|
||||||
|
size_t tlen;
|
||||||
|
struct sshbuf *b;
|
||||||
|
int r;
|
||||||
|
|
||||||
|
if (strncmp(cp, "SHA256:", 7) != 0)
|
||||||
|
fatal("%s:%lu: unsupported hash algorithm", file, lnum);
|
||||||
|
cp += 7;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* OpenSSH base64 hashes omit trailing '='
|
||||||
|
* characters; put them back for decode.
|
||||||
|
*/
|
||||||
|
tlen = strlen(cp);
|
||||||
|
tmp = xmalloc(tlen + 4 + 1);
|
||||||
|
strlcpy(tmp, cp, tlen + 1);
|
||||||
|
while ((tlen % 4) != 0) {
|
||||||
|
tmp[tlen++] = '=';
|
||||||
|
tmp[tlen] = '\0';
|
||||||
|
}
|
||||||
|
if ((b = sshbuf_new()) == NULL)
|
||||||
|
fatal("%s: sshbuf_new failed", __func__);
|
||||||
|
if ((r = sshbuf_b64tod(b, tmp)) != 0)
|
||||||
|
fatal("%s:%lu: decode hash failed: %s", file, lnum, ssh_err(r));
|
||||||
|
free(tmp);
|
||||||
|
*lenp = sshbuf_len(b);
|
||||||
|
*blobp = xmalloc(*lenp);
|
||||||
|
memcpy(*blobp, sshbuf_ptr(b), *lenp);
|
||||||
|
sshbuf_free(b);
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
update_krl_from_file(struct passwd *pw, const char *file, int wild_ca,
|
update_krl_from_file(struct passwd *pw, const char *file, int wild_ca,
|
||||||
const struct sshkey *ca, struct ssh_krl *krl)
|
const struct sshkey *ca, struct ssh_krl *krl)
|
||||||
|
@ -2086,9 +2121,10 @@ update_krl_from_file(struct passwd *pw, const char *file, int wild_ca,
|
||||||
struct sshkey *key = NULL;
|
struct sshkey *key = NULL;
|
||||||
u_long lnum = 0;
|
u_long lnum = 0;
|
||||||
char *path, *cp, *ep, *line = NULL;
|
char *path, *cp, *ep, *line = NULL;
|
||||||
size_t linesize = 0;
|
u_char *blob = NULL;
|
||||||
|
size_t blen = 0, linesize = 0;
|
||||||
unsigned long long serial, serial2;
|
unsigned long long serial, serial2;
|
||||||
int i, was_explicit_key, was_sha1, r;
|
int i, was_explicit_key, was_sha1, was_sha256, was_hash, r;
|
||||||
FILE *krl_spec;
|
FILE *krl_spec;
|
||||||
|
|
||||||
path = tilde_expand_filename(file, pw->pw_uid);
|
path = tilde_expand_filename(file, pw->pw_uid);
|
||||||
|
@ -2103,7 +2139,7 @@ update_krl_from_file(struct passwd *pw, const char *file, int wild_ca,
|
||||||
printf("Revoking from %s\n", path);
|
printf("Revoking from %s\n", path);
|
||||||
while (getline(&line, &linesize, krl_spec) != -1) {
|
while (getline(&line, &linesize, krl_spec) != -1) {
|
||||||
lnum++;
|
lnum++;
|
||||||
was_explicit_key = was_sha1 = 0;
|
was_explicit_key = was_sha1 = was_sha256 = was_hash = 0;
|
||||||
cp = line + strspn(line, " \t");
|
cp = line + strspn(line, " \t");
|
||||||
/* Trim trailing space, comments and strip \n */
|
/* Trim trailing space, comments and strip \n */
|
||||||
for (i = 0, r = -1; cp[i] != '\0'; i++) {
|
for (i = 0, r = -1; cp[i] != '\0'; i++) {
|
||||||
|
@ -2168,6 +2204,11 @@ update_krl_from_file(struct passwd *pw, const char *file, int wild_ca,
|
||||||
cp = cp + strspn(cp, " \t");
|
cp = cp + strspn(cp, " \t");
|
||||||
if (ssh_krl_revoke_cert_by_key_id(krl, ca, cp) != 0)
|
if (ssh_krl_revoke_cert_by_key_id(krl, ca, cp) != 0)
|
||||||
fatal("%s: revoke key ID failed", __func__);
|
fatal("%s: revoke key ID failed", __func__);
|
||||||
|
} else if (strncasecmp(cp, "hash:", 5) == 0) {
|
||||||
|
cp += 5;
|
||||||
|
cp = cp + strspn(cp, " \t");
|
||||||
|
hash_to_blob(cp, &blob, &blen, file, lnum);
|
||||||
|
r = ssh_krl_revoke_key_sha256(krl, blob, blen);
|
||||||
} else {
|
} else {
|
||||||
if (strncasecmp(cp, "key:", 4) == 0) {
|
if (strncasecmp(cp, "key:", 4) == 0) {
|
||||||
cp += 4;
|
cp += 4;
|
||||||
|
@ -2177,7 +2218,10 @@ update_krl_from_file(struct passwd *pw, const char *file, int wild_ca,
|
||||||
cp += 5;
|
cp += 5;
|
||||||
cp = cp + strspn(cp, " \t");
|
cp = cp + strspn(cp, " \t");
|
||||||
was_sha1 = 1;
|
was_sha1 = 1;
|
||||||
} else {
|
} else if (strncasecmp(cp, "sha256:", 7) == 0) {
|
||||||
|
cp += 7;
|
||||||
|
cp = cp + strspn(cp, " \t");
|
||||||
|
was_sha256 = 1;
|
||||||
/*
|
/*
|
||||||
* Just try to process the line as a key.
|
* Just try to process the line as a key.
|
||||||
* Parsing will fail if it isn't.
|
* Parsing will fail if it isn't.
|
||||||
|
@ -2190,13 +2234,28 @@ update_krl_from_file(struct passwd *pw, const char *file, int wild_ca,
|
||||||
path, lnum, ssh_err(r));
|
path, lnum, ssh_err(r));
|
||||||
if (was_explicit_key)
|
if (was_explicit_key)
|
||||||
r = ssh_krl_revoke_key_explicit(krl, key);
|
r = ssh_krl_revoke_key_explicit(krl, key);
|
||||||
else if (was_sha1)
|
else if (was_sha1) {
|
||||||
r = ssh_krl_revoke_key_sha1(krl, key);
|
if (sshkey_fingerprint_raw(key,
|
||||||
else
|
SSH_DIGEST_SHA1, &blob, &blen) != 0) {
|
||||||
|
fatal("%s:%lu: fingerprint failed",
|
||||||
|
file, lnum);
|
||||||
|
}
|
||||||
|
r = ssh_krl_revoke_key_sha1(krl, blob, blen);
|
||||||
|
} else if (was_sha256) {
|
||||||
|
if (sshkey_fingerprint_raw(key,
|
||||||
|
SSH_DIGEST_SHA256, &blob, &blen) != 0) {
|
||||||
|
fatal("%s:%lu: fingerprint failed",
|
||||||
|
file, lnum);
|
||||||
|
}
|
||||||
|
r = ssh_krl_revoke_key_sha256(krl, blob, blen);
|
||||||
|
} else
|
||||||
r = ssh_krl_revoke_key(krl, key);
|
r = ssh_krl_revoke_key(krl, key);
|
||||||
if (r != 0)
|
if (r != 0)
|
||||||
fatal("%s: revoke key failed: %s",
|
fatal("%s: revoke key failed: %s",
|
||||||
__func__, ssh_err(r));
|
__func__, ssh_err(r));
|
||||||
|
freezero(blob, blen);
|
||||||
|
blob = NULL;
|
||||||
|
blen = 0;
|
||||||
sshkey_free(key);
|
sshkey_free(key);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue