#include <obd.h>
#include <obd_class.h>
#include <obd_support.h>
-#include <lustre/lustre_idl.h>
#include <lustre_net.h>
#include <lustre_import.h>
#include <lustre_sec.h>
[ENCTYPE_DES3_CBC_RAW] = { /* des3-hmac-sha1 */
.ke_dispname = "des3-hmac-sha1",
.ke_enc_name = "cbc(des3_ede)",
- .ke_hash_name = "hmac(sha1)",
+ .ke_hash_name = "sha1",
.ke_hash_size = 20,
.ke_conf_size = 8,
.ke_hash_hmac = 1,
[ENCTYPE_AES128_CTS_HMAC_SHA1_96] = { /* aes128-cts */
.ke_dispname = "aes128-cts-hmac-sha1-96",
.ke_enc_name = "cbc(aes)",
- .ke_hash_name = "hmac(sha1)",
+ .ke_hash_name = "sha1",
.ke_hash_size = 12,
.ke_conf_size = 16,
.ke_hash_hmac = 1,
[ENCTYPE_AES256_CTS_HMAC_SHA1_96] = { /* aes256-cts */
.ke_dispname = "aes256-cts-hmac-sha1-96",
.ke_enc_name = "cbc(aes)",
- .ke_hash_name = "hmac(sha1)",
+ .ke_hash_name = "sha1",
.ke_hash_size = 12,
.ke_conf_size = 16,
.ke_hash_hmac = 1,
[ENCTYPE_ARCFOUR_HMAC] = { /* arcfour-hmac-md5 */
.ke_dispname = "arcfour-hmac-md5",
.ke_enc_name = "ecb(arc4)",
- .ke_hash_name = "hmac(md5)",
+ .ke_hash_name = "md5",
.ke_hash_size = 16,
.ke_conf_size = 8,
.ke_hash_hmac = 1,
}
};
-#define MAX_ENCTYPES sizeof(enctypes)/sizeof(struct krb5_enctype)
-
static const char * enctype2str(__u32 enctype)
{
- if (enctype < MAX_ENCTYPES && enctypes[enctype].ke_dispname)
- return enctypes[enctype].ke_dispname;
+ if (enctype < ARRAY_SIZE(enctypes) && enctypes[enctype].ke_dispname)
+ return enctypes[enctype].ke_dispname;
- return "unknown";
+ return "unknown";
}
static
int krb5_init_keys(struct krb5_ctx *kctx)
{
- struct krb5_enctype *ke;
+ struct krb5_enctype *ke;
- if (kctx->kc_enctype >= MAX_ENCTYPES ||
- enctypes[kctx->kc_enctype].ke_hash_size == 0) {
- CERROR("unsupported enctype %x\n", kctx->kc_enctype);
- return -1;
- }
+ if (kctx->kc_enctype >= ARRAY_SIZE(enctypes) ||
+ enctypes[kctx->kc_enctype].ke_hash_size == 0) {
+ CERROR("unsupported enctype %x\n", kctx->kc_enctype);
+ return -1;
+ }
ke = &enctypes[kctx->kc_enctype];
gss_get_bytes(&p, end, &tmp_uint, sizeof(tmp_uint)))
goto out_err;
- /* end time */
- if (gss_get_bytes(&p, end, &kctx->kc_endtime, sizeof(kctx->kc_endtime)))
+ /* end time. While kc_endtime might be 64 bit the krb5 API
+ * still uses 32 bits. To delay the 2038 bug see the incoming
+ * value as a u32 which give us until 2106. See the link for details:
+ *
+ * http://web.mit.edu/kerberos/www/krb5-current/doc/appdev/y2038.html
+ */
+ if (gss_get_bytes(&p, end, &kctx->kc_endtime, sizeof(u32)))
goto out_err;
/* seq send */
{
unsigned int tmp_uint, keysize;
- /* end time */
- if (gss_get_bytes(&p, end, &kctx->kc_endtime, sizeof(kctx->kc_endtime)))
+ /* end time. While kc_endtime might be 64 bit the krb5 API
+ * still uses 32 bits. To delay the 2038 bug see the incoming
+ * value as a u32 which give us until 2106. See the link for details:
+ *
+ * http://web.mit.edu/kerberos/www/krb5-current/doc/appdev/y2038.html
+ */
+ if (gss_get_bytes(&p, end, &kctx->kc_endtime, sizeof(u32)))
goto out_err;
/* flags */
static
__u32 gss_inquire_context_kerberos(struct gss_ctx *gctx,
- unsigned long *endtime)
+ time64_t *endtime)
{
struct krb5_ctx *kctx = gctx->internal_ctx_id;
- *endtime = (unsigned long)((__u32) kctx->kc_endtime);
+ *endtime = kctx->kc_endtime;
return GSS_S_COMPLETE;
}
int iovcnt, lnet_kiov_t *iovs,
rawobj_t *cksum)
{
- struct krb5_enctype *ke = &enctypes[enctype];
- struct crypto_hash *tfm;
- rawobj_t hdr;
- __u32 code = GSS_S_FAILURE;
- int rc;
-
- if (!(tfm = crypto_alloc_hash(ke->ke_hash_name, 0, 0))) {
- CERROR("failed to alloc TFM: %s\n", ke->ke_hash_name);
- return GSS_S_FAILURE;
- }
+ struct krb5_enctype *ke = &enctypes[enctype];
+ struct cfs_crypto_hash_desc *desc = NULL;
+ enum cfs_crypto_hash_alg hash_algo;
+ rawobj_t hdr;
+ int rc;
+
+ hash_algo = cfs_crypto_hash_alg(ke->ke_hash_name);
+
+ /* For the cbc(des) case we want md5 instead of hmac(md5) */
+ if (strcmp(ke->ke_enc_name, "cbc(des)"))
+ desc = cfs_crypto_hash_init(hash_algo, kb->kb_key.data,
+ kb->kb_key.len);
+ else
+ desc = cfs_crypto_hash_init(hash_algo, NULL, 0);
+ if (IS_ERR(desc)) {
+ rc = PTR_ERR(desc);
+ CERROR("failed to alloc hash %s : rc = %d\n",
+ ke->ke_hash_name, rc);
+ goto out_no_hash;
+ }
- cksum->len = crypto_hash_digestsize(tfm);
- OBD_ALLOC_LARGE(cksum->data, cksum->len);
- if (!cksum->data) {
- cksum->len = 0;
- goto out_tfm;
- }
+ cksum->len = cfs_crypto_hash_digestsize(hash_algo);
+ OBD_ALLOC_LARGE(cksum->data, cksum->len);
+ if (!cksum->data) {
+ cksum->len = 0;
+ rc = -ENOMEM;
+ goto out_free_hash;
+ }
hdr.data = (__u8 *)khdr;
hdr.len = sizeof(*khdr);
- if (ke->ke_hash_hmac)
- rc = gss_digest_hmac(tfm, &kb->kb_key,
- &hdr, msgcnt, msgs, iovcnt, iovs, cksum);
- else
- rc = gss_digest_norm(tfm, kb,
- &hdr, msgcnt, msgs, iovcnt, iovs, cksum);
+ rc = gss_digest_hash(desc, &hdr, msgcnt, msgs,
+ iovcnt, iovs, cksum);
+ if (rc)
+ goto out_free_hash;
- if (rc == 0)
- code = GSS_S_COMPLETE;
-out_tfm:
- crypto_free_hash(tfm);
- return code;
+ if (!ke->ke_hash_hmac) {
+ LASSERT(kb->kb_tfm);
+
+ cfs_crypto_hash_final(desc, cksum->data, &cksum->len);
+ rc = gss_crypt_generic(kb->kb_tfm, 0, NULL,
+ cksum->data, cksum->data,
+ cksum->len);
+ goto out_no_hash;
+ }
+
+out_free_hash:
+ if (desc)
+ cfs_crypto_hash_final(desc, cksum->data, &cksum->len);
+out_no_hash:
+ return rc ? GSS_S_FAILURE : GSS_S_COMPLETE;
}
static void fill_krb5_header(struct krb5_ctx *kctx,
struct krb5_ctx *kctx = gctx->internal_ctx_id;
struct krb5_enctype *ke = &enctypes[kctx->kc_enctype];
struct krb5_header *khdr;
- rawobj_t cksum = RAWOBJ_EMPTY;
+ rawobj_t cksum = RAWOBJ_EMPTY;
+ u32 major;
/* fill krb5 header */
LASSERT(token->len >= sizeof(*khdr));
fill_krb5_header(kctx, khdr, 0);
/* checksum */
- if (krb5_make_checksum(kctx->kc_enctype, &kctx->kc_keyc,
- khdr, msgcnt, msgs, iovcnt, iovs, &cksum))
- return GSS_S_FAILURE;
+ if (krb5_make_checksum(kctx->kc_enctype, &kctx->kc_keyc, khdr,
+ msgcnt, msgs, iovcnt, iovs, &cksum))
+ GOTO(out_free_cksum, major = GSS_S_FAILURE);
LASSERT(cksum.len >= ke->ke_hash_size);
LASSERT(token->len >= sizeof(*khdr) + ke->ke_hash_size);
memcpy(khdr + 1, cksum.data + cksum.len - ke->ke_hash_size,
ke->ke_hash_size);
- token->len = sizeof(*khdr) + ke->ke_hash_size;
- rawobj_free(&cksum);
- return GSS_S_COMPLETE;
+ token->len = sizeof(*khdr) + ke->ke_hash_size;
+ major = GSS_S_COMPLETE;
+out_free_cksum:
+ rawobj_free(&cksum);
+ return major;
}
static
lnet_kiov_t *iovs,
rawobj_t *token)
{
- struct krb5_ctx *kctx = gctx->internal_ctx_id;
- struct krb5_enctype *ke = &enctypes[kctx->kc_enctype];
- struct krb5_header *khdr;
- rawobj_t cksum = RAWOBJ_EMPTY;
- __u32 major;
+ struct krb5_ctx *kctx = gctx->internal_ctx_id;
+ struct krb5_enctype *ke = &enctypes[kctx->kc_enctype];
+ struct krb5_header *khdr;
+ rawobj_t cksum = RAWOBJ_EMPTY;
+ u32 major;
if (token->len < sizeof(*khdr)) {
CERROR("short signature: %u\n", token->len);
major = verify_krb5_header(kctx, khdr, 0);
if (major != GSS_S_COMPLETE) {
CERROR("bad krb5 header\n");
- return major;
+ goto out;
}
if (token->len < sizeof(*khdr) + ke->ke_hash_size) {
CERROR("short signature: %u, require %d\n",
token->len, (int) sizeof(*khdr) + ke->ke_hash_size);
- return GSS_S_FAILURE;
+ GOTO(out, major = GSS_S_FAILURE);
}
if (krb5_make_checksum(kctx->kc_enctype, &kctx->kc_keyc,
khdr, msgcnt, msgs, iovcnt, iovs, &cksum)) {
CERROR("failed to make checksum\n");
- return GSS_S_FAILURE;
+ GOTO(out_free_cksum, major = GSS_S_FAILURE);
}
LASSERT(cksum.len >= ke->ke_hash_size);
if (memcmp(khdr + 1, cksum.data + cksum.len - ke->ke_hash_size,
ke->ke_hash_size)) {
CERROR("checksum mismatch\n");
- rawobj_free(&cksum);
- return GSS_S_BAD_SIG;
- }
-
- rawobj_free(&cksum);
- return GSS_S_COMPLETE;
+ GOTO(out_free_cksum, major = GSS_S_BAD_SIG);
+ }
+ major = GSS_S_COMPLETE;
+out_free_cksum:
+ rawobj_free(&cksum);
+out:
+ return major;
}
/*
rawobj_t data_desc[3], cipher;
__u8 conf[GSS_MAX_CIPHER_BLOCK];
__u8 local_iv[16] = {0};
+ u32 major;
int rc = 0;
LASSERT(ke);
/* compute checksum */
if (krb5_make_checksum(kctx->kc_enctype, &kctx->kc_keyi,
khdr, 3, data_desc, 0, NULL, &cksum))
- return GSS_S_FAILURE;
+ GOTO(out_free_cksum, major = GSS_S_FAILURE);
LASSERT(cksum.len >= ke->ke_hash_size);
/*
LASSERT(cipher.len >= ke->ke_conf_size + msg->len + sizeof(*khdr));
if (kctx->kc_enctype == ENCTYPE_ARCFOUR_HMAC) {
- rawobj_t arc4_keye;
+ rawobj_t arc4_keye = RAWOBJ_EMPTY;
struct crypto_blkcipher *arc4_tfm;
if (krb5_make_checksum(ENCTYPE_ARCFOUR_HMAC, &kctx->kc_keyi,
NULL, 1, &cksum, 0, NULL, &arc4_keye)) {
CERROR("failed to obtain arc4 enc key\n");
- GOTO(arc4_out, rc = -EACCES);
+ GOTO(arc4_out_key, rc = -EACCES);
}
arc4_tfm = crypto_alloc_blkcipher("ecb(arc4)", 0, 0);
arc4_out_tfm:
crypto_free_blkcipher(arc4_tfm);
arc4_out_key:
- rawobj_free(&arc4_keye);
-arc4_out:
- do {} while(0); /* just to avoid compile warning */
+ rawobj_free(&arc4_keye);
} else {
rc = gss_crypt_rawobjs(kctx->kc_keye.kb_tfm, local_iv, 3,
data_desc, &cipher, 1);
}
- if (rc != 0) {
- rawobj_free(&cksum);
- return GSS_S_FAILURE;
- }
+ if (rc)
+ GOTO(out_free_cksum, major = GSS_S_FAILURE);
/* fill in checksum */
LASSERT(token->len >= sizeof(*khdr) + cipher.len + ke->ke_hash_size);
memcpy((char *)(khdr + 1) + cipher.len,
cksum.data + cksum.len - ke->ke_hash_size,
ke->ke_hash_size);
- rawobj_free(&cksum);
- /* final token length */
- token->len = sizeof(*khdr) + cipher.len + ke->ke_hash_size;
- return GSS_S_COMPLETE;
+ /* final token length */
+ token->len = sizeof(*khdr) + cipher.len + ke->ke_hash_size;
+ major = GSS_S_COMPLETE;
+out_free_cksum:
+ rawobj_free(&cksum);
+ return major;
}
static
rawobj_t cksum = RAWOBJ_EMPTY;
rawobj_t data_desc[1], cipher;
__u8 conf[GSS_MAX_CIPHER_BLOCK];
- int rc = 0;
+ int rc = 0;
+ u32 major;
LASSERT(ptlrpc_is_bulk_desc_kiov(desc->bd_type));
LASSERT(ke);
khdr, 1, data_desc,
desc->bd_iov_count, GET_KIOV(desc),
&cksum))
- return GSS_S_FAILURE;
+ GOTO(out_free_cksum, major = GSS_S_FAILURE);
LASSERT(cksum.len >= ke->ke_hash_size);
/*
rc = krb5_encrypt_bulk(kctx->kc_keye.kb_tfm, khdr,
conf, desc, &cipher, adj_nob);
}
-
- if (rc != 0) {
- rawobj_free(&cksum);
- return GSS_S_FAILURE;
- }
+ if (rc)
+ GOTO(out_free_cksum, major = GSS_S_FAILURE);
/* fill in checksum */
LASSERT(token->len >= sizeof(*khdr) + cipher.len + ke->ke_hash_size);
memcpy((char *)(khdr + 1) + cipher.len,
cksum.data + cksum.len - ke->ke_hash_size,
ke->ke_hash_size);
- rawobj_free(&cksum);
- /* final token length */
- token->len = sizeof(*khdr) + cipher.len + ke->ke_hash_size;
- return GSS_S_COMPLETE;
+ /* final token length */
+ token->len = sizeof(*khdr) + cipher.len + ke->ke_hash_size;
+ major = GSS_S_COMPLETE;
+out_free_cksum:
+ rawobj_free(&cksum);
+ return major;
}
static