|
|
665228 |
From e7266b788278f019ad15d2d2fe518401e98c5645 Mon Sep 17 00:00:00 2001
|
|
|
665228 |
From: Robbie Harwood <rharwood@redhat.com>
|
|
|
665228 |
Date: Tue, 31 Jul 2018 13:47:26 -0400
|
|
|
665228 |
Subject: [PATCH] In FIPS mode, add plaintext fallback for RC4 usages and taint
|
|
|
665228 |
|
|
|
665228 |
---
|
|
|
665228 |
src/lib/krad/attr.c | 38 ++++++++++++++++++++++++++++----------
|
|
|
665228 |
src/lib/krad/attrset.c | 5 +++--
|
|
|
665228 |
src/lib/krad/internal.h | 13 +++++++++++--
|
|
|
665228 |
src/lib/krad/packet.c | 18 +++++++++---------
|
|
|
665228 |
src/lib/krad/remote.c | 10 ++++++++--
|
|
|
665228 |
src/lib/krad/t_attr.c | 3 ++-
|
|
|
665228 |
src/lib/krad/t_attrset.c | 4 +++-
|
|
|
665228 |
7 files changed, 64 insertions(+), 27 deletions(-)
|
|
|
665228 |
|
|
|
665228 |
diff --git a/src/lib/krad/attr.c b/src/lib/krad/attr.c
|
|
|
665228 |
index 9c13d9d75..f96153e2e 100644
|
|
|
665228 |
--- a/src/lib/krad/attr.c
|
|
|
665228 |
+++ b/src/lib/krad/attr.c
|
|
|
665228 |
@@ -38,7 +38,8 @@
|
|
|
665228 |
typedef krb5_error_code
|
|
|
665228 |
(*attribute_transform_fn)(krb5_context ctx, const char *secret,
|
|
|
665228 |
const unsigned char *auth, const krb5_data *in,
|
|
|
665228 |
- unsigned char outbuf[MAX_ATTRSIZE], size_t *outlen);
|
|
|
665228 |
+ unsigned char outbuf[MAX_ATTRSIZE], size_t *outlen,
|
|
|
665228 |
+ krb5_boolean *is_fips);
|
|
|
665228 |
|
|
|
665228 |
typedef struct {
|
|
|
665228 |
const char *name;
|
|
|
665228 |
@@ -51,12 +52,14 @@ typedef struct {
|
|
|
665228 |
static krb5_error_code
|
|
|
665228 |
user_password_encode(krb5_context ctx, const char *secret,
|
|
|
665228 |
const unsigned char *auth, const krb5_data *in,
|
|
|
665228 |
- unsigned char outbuf[MAX_ATTRSIZE], size_t *outlen);
|
|
|
665228 |
+ unsigned char outbuf[MAX_ATTRSIZE], size_t *outlen,
|
|
|
665228 |
+ krb5_boolean *is_fips);
|
|
|
665228 |
|
|
|
665228 |
static krb5_error_code
|
|
|
665228 |
user_password_decode(krb5_context ctx, const char *secret,
|
|
|
665228 |
const unsigned char *auth, const krb5_data *in,
|
|
|
665228 |
- unsigned char outbuf[MAX_ATTRSIZE], size_t *outlen);
|
|
|
665228 |
+ unsigned char outbuf[MAX_ATTRSIZE], size_t *outlen,
|
|
|
665228 |
+ krb5_boolean *ignored);
|
|
|
665228 |
|
|
|
665228 |
static const attribute_record attributes[UCHAR_MAX] = {
|
|
|
665228 |
{"User-Name", 1, MAX_ATTRSIZE, NULL, NULL},
|
|
|
665228 |
@@ -128,7 +131,8 @@ static const attribute_record attributes[UCHAR_MAX] = {
|
|
|
665228 |
static krb5_error_code
|
|
|
665228 |
user_password_encode(krb5_context ctx, const char *secret,
|
|
|
665228 |
const unsigned char *auth, const krb5_data *in,
|
|
|
665228 |
- unsigned char outbuf[MAX_ATTRSIZE], size_t *outlen)
|
|
|
665228 |
+ unsigned char outbuf[MAX_ATTRSIZE], size_t *outlen,
|
|
|
665228 |
+ krb5_boolean *is_fips)
|
|
|
665228 |
{
|
|
|
665228 |
const unsigned char *indx;
|
|
|
665228 |
krb5_error_code retval;
|
|
|
665228 |
@@ -156,7 +160,12 @@ user_password_encode(krb5_context ctx, const char *secret,
|
|
|
665228 |
|
|
|
665228 |
retval = krb5_c_make_checksum(ctx, CKSUMTYPE_RSA_MD5, NULL, 0, &tmp,
|
|
|
665228 |
&sum);
|
|
|
665228 |
- if (retval != 0) {
|
|
|
665228 |
+ if (retval == ENOMEM) {
|
|
|
665228 |
+ /* I'm Linux, so we know this is a FIPS failure. RSA_MD5 doesn't
|
|
|
665228 |
+ * provide security so let's move on. */
|
|
|
665228 |
+ *is_fips = TRUE;
|
|
|
665228 |
+ sum.contents = calloc(1, BLOCKSIZE);
|
|
|
665228 |
+ } else if (retval != 0) {
|
|
|
665228 |
zap(tmp.data, tmp.length);
|
|
|
665228 |
zap(outbuf, len);
|
|
|
665228 |
krb5_free_data_contents(ctx, &tmp);
|
|
|
665228 |
@@ -180,7 +189,8 @@ user_password_encode(krb5_context ctx, const char *secret,
|
|
|
665228 |
static krb5_error_code
|
|
|
665228 |
user_password_decode(krb5_context ctx, const char *secret,
|
|
|
665228 |
const unsigned char *auth, const krb5_data *in,
|
|
|
665228 |
- unsigned char outbuf[MAX_ATTRSIZE], size_t *outlen)
|
|
|
665228 |
+ unsigned char outbuf[MAX_ATTRSIZE], size_t *outlen,
|
|
|
665228 |
+ krb5_boolean *is_fips)
|
|
|
665228 |
{
|
|
|
665228 |
const unsigned char *indx;
|
|
|
665228 |
krb5_error_code retval;
|
|
|
665228 |
@@ -206,7 +216,12 @@ user_password_decode(krb5_context ctx, const char *secret,
|
|
|
665228 |
|
|
|
665228 |
retval = krb5_c_make_checksum(ctx, CKSUMTYPE_RSA_MD5, NULL, 0,
|
|
|
665228 |
&tmp, &sum);
|
|
|
665228 |
- if (retval != 0) {
|
|
|
665228 |
+ if (retval == ENOMEM) {
|
|
|
665228 |
+ /* I'm Linux, so we know this is a FIPS failure. Assume the
|
|
|
665228 |
+ * other side is running locally and move on. */
|
|
|
665228 |
+ *is_fips = TRUE;
|
|
|
665228 |
+ sum.contents = calloc(1, BLOCKSIZE);
|
|
|
665228 |
+ } else if (retval != 0) {
|
|
|
665228 |
zap(tmp.data, tmp.length);
|
|
|
665228 |
zap(outbuf, in->length);
|
|
|
665228 |
krb5_free_data_contents(ctx, &tmp);
|
|
|
665228 |
@@ -248,7 +263,7 @@ krb5_error_code
|
|
|
665228 |
kr_attr_encode(krb5_context ctx, const char *secret,
|
|
|
665228 |
const unsigned char *auth, krad_attr type,
|
|
|
665228 |
const krb5_data *in, unsigned char outbuf[MAX_ATTRSIZE],
|
|
|
665228 |
- size_t *outlen)
|
|
|
665228 |
+ size_t *outlen, krb5_boolean *is_fips)
|
|
|
665228 |
{
|
|
|
665228 |
krb5_error_code retval;
|
|
|
665228 |
|
|
|
665228 |
@@ -265,7 +280,8 @@ kr_attr_encode(krb5_context ctx, const char *secret,
|
|
|
665228 |
return 0;
|
|
|
665228 |
}
|
|
|
665228 |
|
|
|
665228 |
- return attributes[type - 1].encode(ctx, secret, auth, in, outbuf, outlen);
|
|
|
665228 |
+ return attributes[type - 1].encode(ctx, secret, auth, in, outbuf, outlen,
|
|
|
665228 |
+ is_fips);
|
|
|
665228 |
}
|
|
|
665228 |
|
|
|
665228 |
krb5_error_code
|
|
|
665228 |
@@ -274,6 +290,7 @@ kr_attr_decode(krb5_context ctx, const char *secret, const unsigned char *auth,
|
|
|
665228 |
unsigned char outbuf[MAX_ATTRSIZE], size_t *outlen)
|
|
|
665228 |
{
|
|
|
665228 |
krb5_error_code retval;
|
|
|
665228 |
+ krb5_boolean ignored;
|
|
|
665228 |
|
|
|
665228 |
retval = kr_attr_valid(type, in);
|
|
|
665228 |
if (retval != 0)
|
|
|
665228 |
@@ -288,7 +305,8 @@ kr_attr_decode(krb5_context ctx, const char *secret, const unsigned char *auth,
|
|
|
665228 |
return 0;
|
|
|
665228 |
}
|
|
|
665228 |
|
|
|
665228 |
- return attributes[type - 1].decode(ctx, secret, auth, in, outbuf, outlen);
|
|
|
665228 |
+ return attributes[type - 1].decode(ctx, secret, auth, in, outbuf, outlen,
|
|
|
665228 |
+ &ignored);
|
|
|
665228 |
}
|
|
|
665228 |
|
|
|
665228 |
krad_attr
|
|
|
665228 |
diff --git a/src/lib/krad/attrset.c b/src/lib/krad/attrset.c
|
|
|
665228 |
index 03c613716..d89982a13 100644
|
|
|
665228 |
--- a/src/lib/krad/attrset.c
|
|
|
665228 |
+++ b/src/lib/krad/attrset.c
|
|
|
665228 |
@@ -167,7 +167,8 @@ krad_attrset_copy(const krad_attrset *set, krad_attrset **copy)
|
|
|
665228 |
krb5_error_code
|
|
|
665228 |
kr_attrset_encode(const krad_attrset *set, const char *secret,
|
|
|
665228 |
const unsigned char *auth,
|
|
|
665228 |
- unsigned char outbuf[MAX_ATTRSETSIZE], size_t *outlen)
|
|
|
665228 |
+ unsigned char outbuf[MAX_ATTRSETSIZE], size_t *outlen,
|
|
|
665228 |
+ krb5_boolean *is_fips)
|
|
|
665228 |
{
|
|
|
665228 |
unsigned char buffer[MAX_ATTRSIZE];
|
|
|
665228 |
krb5_error_code retval;
|
|
|
665228 |
@@ -181,7 +182,7 @@ kr_attrset_encode(const krad_attrset *set, const char *secret,
|
|
|
665228 |
|
|
|
665228 |
K5_TAILQ_FOREACH(a, &set->list, list) {
|
|
|
665228 |
retval = kr_attr_encode(set->ctx, secret, auth, a->type, &a->attr,
|
|
|
665228 |
- buffer, &attrlen);
|
|
|
665228 |
+ buffer, &attrlen, is_fips);
|
|
|
665228 |
if (retval != 0)
|
|
|
665228 |
return retval;
|
|
|
665228 |
|
|
|
665228 |
diff --git a/src/lib/krad/internal.h b/src/lib/krad/internal.h
|
|
|
665228 |
index 996a89372..a53ce31ce 100644
|
|
|
665228 |
--- a/src/lib/krad/internal.h
|
|
|
665228 |
+++ b/src/lib/krad/internal.h
|
|
|
665228 |
@@ -49,6 +49,13 @@
|
|
|
665228 |
|
|
|
665228 |
typedef struct krad_remote_st krad_remote;
|
|
|
665228 |
|
|
|
665228 |
+struct krad_packet_st {
|
|
|
665228 |
+ char buffer[KRAD_PACKET_SIZE_MAX];
|
|
|
665228 |
+ krad_attrset *attrset;
|
|
|
665228 |
+ krb5_data pkt;
|
|
|
665228 |
+ krb5_boolean is_fips;
|
|
|
665228 |
+};
|
|
|
665228 |
+
|
|
|
665228 |
/* Validate constraints of an attribute. */
|
|
|
665228 |
krb5_error_code
|
|
|
665228 |
kr_attr_valid(krad_attr type, const krb5_data *data);
|
|
|
665228 |
@@ -57,7 +64,8 @@ kr_attr_valid(krad_attr type, const krb5_data *data);
|
|
|
665228 |
krb5_error_code
|
|
|
665228 |
kr_attr_encode(krb5_context ctx, const char *secret, const unsigned char *auth,
|
|
|
665228 |
krad_attr type, const krb5_data *in,
|
|
|
665228 |
- unsigned char outbuf[MAX_ATTRSIZE], size_t *outlen);
|
|
|
665228 |
+ unsigned char outbuf[MAX_ATTRSIZE], size_t *outlen,
|
|
|
665228 |
+ krb5_boolean *is_fips);
|
|
|
665228 |
|
|
|
665228 |
/* Decode an attribute. */
|
|
|
665228 |
krb5_error_code
|
|
|
665228 |
@@ -69,7 +77,8 @@ kr_attr_decode(krb5_context ctx, const char *secret, const unsigned char *auth,
|
|
|
665228 |
krb5_error_code
|
|
|
665228 |
kr_attrset_encode(const krad_attrset *set, const char *secret,
|
|
|
665228 |
const unsigned char *auth,
|
|
|
665228 |
- unsigned char outbuf[MAX_ATTRSETSIZE], size_t *outlen);
|
|
|
665228 |
+ unsigned char outbuf[MAX_ATTRSETSIZE], size_t *outlen,
|
|
|
665228 |
+ krb5_boolean *is_fips);
|
|
|
665228 |
|
|
|
665228 |
/* Decode attributes from a buffer. */
|
|
|
665228 |
krb5_error_code
|
|
|
665228 |
diff --git a/src/lib/krad/packet.c b/src/lib/krad/packet.c
|
|
|
665228 |
index c597174b6..2fbf0ee1e 100644
|
|
|
665228 |
--- a/src/lib/krad/packet.c
|
|
|
665228 |
+++ b/src/lib/krad/packet.c
|
|
|
665228 |
@@ -53,12 +53,6 @@ typedef unsigned char uchar;
|
|
|
665228 |
#define pkt_auth(p) ((uchar *)offset(&(p)->pkt, OFFSET_AUTH))
|
|
|
665228 |
#define pkt_attr(p) ((unsigned char *)offset(&(p)->pkt, OFFSET_ATTR))
|
|
|
665228 |
|
|
|
665228 |
-struct krad_packet_st {
|
|
|
665228 |
- char buffer[KRAD_PACKET_SIZE_MAX];
|
|
|
665228 |
- krad_attrset *attrset;
|
|
|
665228 |
- krb5_data pkt;
|
|
|
665228 |
-};
|
|
|
665228 |
-
|
|
|
665228 |
typedef struct {
|
|
|
665228 |
uchar x[(UCHAR_MAX + 1) / 8];
|
|
|
665228 |
} idmap;
|
|
|
665228 |
@@ -190,7 +184,11 @@ auth_generate_response(krb5_context ctx, const char *secret,
|
|
|
665228 |
retval = krb5_c_make_checksum(ctx, CKSUMTYPE_RSA_MD5, NULL, 0, &data,
|
|
|
665228 |
&hash);
|
|
|
665228 |
free(data.data);
|
|
|
665228 |
- if (retval != 0)
|
|
|
665228 |
+ if (retval == ENOMEM) {
|
|
|
665228 |
+ /* We're on Linux, so this is a FIPS failure, and this checksum
|
|
|
665228 |
+ * does very little security-wise anyway, so don't taint. */
|
|
|
665228 |
+ hash.contents = calloc(1, AUTH_FIELD_SIZE);
|
|
|
665228 |
+ } else if (retval != 0)
|
|
|
665228 |
return retval;
|
|
|
665228 |
|
|
|
665228 |
memcpy(rauth, hash.contents, AUTH_FIELD_SIZE);
|
|
|
665228 |
@@ -276,7 +274,7 @@ krad_packet_new_request(krb5_context ctx, const char *secret, krad_code code,
|
|
|
665228 |
|
|
|
665228 |
/* Encode the attributes. */
|
|
|
665228 |
retval = kr_attrset_encode(set, secret, pkt_auth(pkt), pkt_attr(pkt),
|
|
|
665228 |
- &attrset_len);
|
|
|
665228 |
+ &attrset_len, &pkt->is_fips);
|
|
|
665228 |
if (retval != 0)
|
|
|
665228 |
goto error;
|
|
|
665228 |
|
|
|
665228 |
@@ -314,7 +312,7 @@ krad_packet_new_response(krb5_context ctx, const char *secret, krad_code code,
|
|
|
665228 |
|
|
|
665228 |
/* Encode the attributes. */
|
|
|
665228 |
retval = kr_attrset_encode(set, secret, pkt_auth(request), pkt_attr(pkt),
|
|
|
665228 |
- &attrset_len);
|
|
|
665228 |
+ &attrset_len, &pkt->is_fips);
|
|
|
665228 |
if (retval != 0)
|
|
|
665228 |
goto error;
|
|
|
665228 |
|
|
|
665228 |
@@ -451,6 +449,8 @@ krad_packet_decode_response(krb5_context ctx, const char *secret,
|
|
|
665228 |
const krb5_data *
|
|
|
665228 |
krad_packet_encode(const krad_packet *pkt)
|
|
|
665228 |
{
|
|
|
665228 |
+ if (pkt->is_fips)
|
|
|
665228 |
+ return NULL;
|
|
|
665228 |
return &pkt->pkt;
|
|
|
665228 |
}
|
|
|
665228 |
|
|
|
665228 |
diff --git a/src/lib/krad/remote.c b/src/lib/krad/remote.c
|
|
|
665228 |
index 437f7e91a..0f90443ce 100644
|
|
|
665228 |
--- a/src/lib/krad/remote.c
|
|
|
665228 |
+++ b/src/lib/krad/remote.c
|
|
|
665228 |
@@ -263,7 +263,7 @@ on_io_write(krad_remote *rr)
|
|
|
665228 |
request *r;
|
|
|
665228 |
|
|
|
665228 |
K5_TAILQ_FOREACH(r, &rr->list, list) {
|
|
|
665228 |
- tmp = krad_packet_encode(r->request);
|
|
|
665228 |
+ tmp = &r->request->pkt;
|
|
|
665228 |
|
|
|
665228 |
/* If the packet has already been sent, do nothing. */
|
|
|
665228 |
if (r->sent == tmp->length)
|
|
|
665228 |
@@ -359,7 +359,7 @@ on_io_read(krad_remote *rr)
|
|
|
665228 |
if (req != NULL) {
|
|
|
665228 |
K5_TAILQ_FOREACH(r, &rr->list, list) {
|
|
|
665228 |
if (r->request == req &&
|
|
|
665228 |
- r->sent == krad_packet_encode(req)->length) {
|
|
|
665228 |
+ r->sent == req->pkt.length) {
|
|
|
665228 |
request_finish(r, 0, rsp);
|
|
|
665228 |
break;
|
|
|
665228 |
}
|
|
|
665228 |
@@ -455,6 +455,12 @@ kr_remote_send(krad_remote *rr, krad_code code, krad_attrset *attrs,
|
|
|
665228 |
(krad_packet_iter_cb)iterator, &r, &tmp);
|
|
|
665228 |
if (retval != 0)
|
|
|
665228 |
goto error;
|
|
|
665228 |
+ else if (tmp->is_fips && rr->info->ai_family != AF_LOCAL &&
|
|
|
665228 |
+ rr->info->ai_family != AF_UNIX) {
|
|
|
665228 |
+ /* This would expose cleartext passwords, so abort. */
|
|
|
665228 |
+ retval = ESOCKTNOSUPPORT;
|
|
|
665228 |
+ goto error;
|
|
|
665228 |
+ }
|
|
|
665228 |
|
|
|
665228 |
K5_TAILQ_FOREACH(r, &rr->list, list) {
|
|
|
665228 |
if (r->request == tmp) {
|
|
|
665228 |
diff --git a/src/lib/krad/t_attr.c b/src/lib/krad/t_attr.c
|
|
|
665228 |
index eb2a780c8..4d285ad9d 100644
|
|
|
665228 |
--- a/src/lib/krad/t_attr.c
|
|
|
665228 |
+++ b/src/lib/krad/t_attr.c
|
|
|
665228 |
@@ -50,6 +50,7 @@ main()
|
|
|
665228 |
const char *tmp;
|
|
|
665228 |
krb5_data in;
|
|
|
665228 |
size_t len;
|
|
|
665228 |
+ krb5_boolean is_fips = FALSE;
|
|
|
665228 |
|
|
|
665228 |
noerror(krb5_init_context(&ctx));
|
|
|
665228 |
|
|
|
665228 |
@@ -73,7 +74,7 @@ main()
|
|
|
665228 |
in = string2data((char *)decoded);
|
|
|
665228 |
retval = kr_attr_encode(ctx, secret, auth,
|
|
|
665228 |
krad_attr_name2num("User-Password"),
|
|
|
665228 |
- &in, outbuf, &len;;
|
|
|
665228 |
+ &in, outbuf, &len, &is_fips);
|
|
|
665228 |
insist(retval == 0);
|
|
|
665228 |
insist(len == sizeof(encoded));
|
|
|
665228 |
insist(memcmp(outbuf, encoded, len) == 0);
|
|
|
665228 |
diff --git a/src/lib/krad/t_attrset.c b/src/lib/krad/t_attrset.c
|
|
|
665228 |
index 7928335ca..0f9576253 100644
|
|
|
665228 |
--- a/src/lib/krad/t_attrset.c
|
|
|
665228 |
+++ b/src/lib/krad/t_attrset.c
|
|
|
665228 |
@@ -49,6 +49,7 @@ main()
|
|
|
665228 |
krb5_context ctx;
|
|
|
665228 |
size_t len = 0, encode_len;
|
|
|
665228 |
krb5_data tmp;
|
|
|
665228 |
+ krb5_boolean is_fips = FALSE;
|
|
|
665228 |
|
|
|
665228 |
noerror(krb5_init_context(&ctx));
|
|
|
665228 |
noerror(krad_attrset_new(ctx, &set);;
|
|
|
665228 |
@@ -62,7 +63,8 @@ main()
|
|
|
665228 |
noerror(krad_attrset_add(set, krad_attr_name2num("User-Password"), &tmp));
|
|
|
665228 |
|
|
|
665228 |
/* Encode attrset. */
|
|
|
665228 |
- noerror(kr_attrset_encode(set, "foo", auth, buffer, &encode_len));
|
|
|
665228 |
+ noerror(kr_attrset_encode(set, "foo", auth, buffer, &encode_len,
|
|
|
665228 |
+ &is_fips));
|
|
|
665228 |
krad_attrset_free(set);
|
|
|
665228 |
|
|
|
665228 |
/* Manually encode User-Name. */
|