^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-or-later
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /* RxRPC key management
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Written by David Howells (dhowells@redhat.com)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * RxRPC keys should have a description of describing their purpose:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) * "afs@CAMBRIDGE.REDHAT.COM>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <crypto/skcipher.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <linux/net.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <linux/skbuff.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include <linux/key-type.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include <linux/ctype.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #include <net/sock.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #include <net/af_rxrpc.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #include <keys/rxrpc-type.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #include <keys/user-type.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) #include "ar-internal.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) static int rxrpc_vet_description_s(const char *);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) static int rxrpc_preparse(struct key_preparsed_payload *);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) static int rxrpc_preparse_s(struct key_preparsed_payload *);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) static void rxrpc_free_preparse(struct key_preparsed_payload *);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) static void rxrpc_free_preparse_s(struct key_preparsed_payload *);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) static void rxrpc_destroy(struct key *);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) static void rxrpc_destroy_s(struct key *);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) static void rxrpc_describe(const struct key *, struct seq_file *);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) static long rxrpc_read(const struct key *, char *, size_t);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) * rxrpc defined keys take an arbitrary string as the description and an
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) * arbitrary blob of data as the payload
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) struct key_type key_type_rxrpc = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) .name = "rxrpc",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) .flags = KEY_TYPE_NET_DOMAIN,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) .preparse = rxrpc_preparse,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) .free_preparse = rxrpc_free_preparse,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) .instantiate = generic_key_instantiate,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) .destroy = rxrpc_destroy,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) .describe = rxrpc_describe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) .read = rxrpc_read,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) EXPORT_SYMBOL(key_type_rxrpc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) * rxrpc server defined keys take "<serviceId>:<securityIndex>" as the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) * description and an 8-byte decryption key as the payload
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) struct key_type key_type_rxrpc_s = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) .name = "rxrpc_s",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) .flags = KEY_TYPE_NET_DOMAIN,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) .vet_description = rxrpc_vet_description_s,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) .preparse = rxrpc_preparse_s,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) .free_preparse = rxrpc_free_preparse_s,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) .instantiate = generic_key_instantiate,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) .destroy = rxrpc_destroy_s,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) .describe = rxrpc_describe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) * Vet the description for an RxRPC server key
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) static int rxrpc_vet_description_s(const char *desc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) unsigned long num;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) char *p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) num = simple_strtoul(desc, &p, 10);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) if (*p != ':' || num > 65535)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) num = simple_strtoul(p + 1, &p, 10);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) if (*p || num < 1 || num > 255)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) * parse an RxKAD type XDR format token
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) * - the caller guarantees we have at least 4 words
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) static int rxrpc_preparse_xdr_rxkad(struct key_preparsed_payload *prep,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) size_t datalen,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) const __be32 *xdr, unsigned int toklen)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) struct rxrpc_key_token *token, **pptoken;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) time64_t expiry;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) size_t plen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) u32 tktlen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) _enter(",{%x,%x,%x,%x},%u",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) ntohl(xdr[0]), ntohl(xdr[1]), ntohl(xdr[2]), ntohl(xdr[3]),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) toklen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) if (toklen <= 8 * 4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) return -EKEYREJECTED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) tktlen = ntohl(xdr[7]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) _debug("tktlen: %x", tktlen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) if (tktlen > AFSTOKEN_RK_TIX_MAX)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) return -EKEYREJECTED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) if (toklen < 8 * 4 + tktlen)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) return -EKEYREJECTED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) plen = sizeof(*token) + sizeof(*token->kad) + tktlen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) prep->quotalen = datalen + plen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) plen -= sizeof(*token);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) token = kzalloc(sizeof(*token), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) if (!token)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) token->kad = kzalloc(plen, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) if (!token->kad) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) kfree(token);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) token->security_index = RXRPC_SECURITY_RXKAD;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) token->kad->ticket_len = tktlen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) token->kad->vice_id = ntohl(xdr[0]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) token->kad->kvno = ntohl(xdr[1]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) token->kad->start = ntohl(xdr[4]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) token->kad->expiry = ntohl(xdr[5]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) token->kad->primary_flag = ntohl(xdr[6]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) memcpy(&token->kad->session_key, &xdr[2], 8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) memcpy(&token->kad->ticket, &xdr[8], tktlen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) _debug("SCIX: %u", token->security_index);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) _debug("TLEN: %u", token->kad->ticket_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) _debug("EXPY: %x", token->kad->expiry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) _debug("KVNO: %u", token->kad->kvno);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) _debug("PRIM: %u", token->kad->primary_flag);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) _debug("SKEY: %02x%02x%02x%02x%02x%02x%02x%02x",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) token->kad->session_key[0], token->kad->session_key[1],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) token->kad->session_key[2], token->kad->session_key[3],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) token->kad->session_key[4], token->kad->session_key[5],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) token->kad->session_key[6], token->kad->session_key[7]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) if (token->kad->ticket_len >= 8)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) _debug("TCKT: %02x%02x%02x%02x%02x%02x%02x%02x",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) token->kad->ticket[0], token->kad->ticket[1],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) token->kad->ticket[2], token->kad->ticket[3],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) token->kad->ticket[4], token->kad->ticket[5],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) token->kad->ticket[6], token->kad->ticket[7]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) /* count the number of tokens attached */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) prep->payload.data[1] = (void *)((unsigned long)prep->payload.data[1] + 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) /* attach the data */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) for (pptoken = (struct rxrpc_key_token **)&prep->payload.data[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) *pptoken;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) pptoken = &(*pptoken)->next)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) *pptoken = token;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) expiry = rxrpc_u32_to_time64(token->kad->expiry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) if (expiry < prep->expiry)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) prep->expiry = expiry;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) _leave(" = 0");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) static void rxrpc_free_krb5_principal(struct krb5_principal *princ)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) int loop;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) if (princ->name_parts) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) for (loop = princ->n_name_parts - 1; loop >= 0; loop--)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) kfree(princ->name_parts[loop]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) kfree(princ->name_parts);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) kfree(princ->realm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) static void rxrpc_free_krb5_tagged(struct krb5_tagged_data *td)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) kfree(td->data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) * free up an RxK5 token
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) static void rxrpc_rxk5_free(struct rxk5_key *rxk5)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) int loop;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) rxrpc_free_krb5_principal(&rxk5->client);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) rxrpc_free_krb5_principal(&rxk5->server);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) rxrpc_free_krb5_tagged(&rxk5->session);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) if (rxk5->addresses) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) for (loop = rxk5->n_addresses - 1; loop >= 0; loop--)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) rxrpc_free_krb5_tagged(&rxk5->addresses[loop]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) kfree(rxk5->addresses);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) if (rxk5->authdata) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) for (loop = rxk5->n_authdata - 1; loop >= 0; loop--)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) rxrpc_free_krb5_tagged(&rxk5->authdata[loop]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) kfree(rxk5->authdata);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) kfree(rxk5->ticket);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) kfree(rxk5->ticket2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) kfree(rxk5);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) * extract a krb5 principal
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) static int rxrpc_krb5_decode_principal(struct krb5_principal *princ,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) const __be32 **_xdr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) unsigned int *_toklen)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) const __be32 *xdr = *_xdr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) unsigned int toklen = *_toklen, n_parts, loop, tmp, paddedlen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) /* there must be at least one name, and at least #names+1 length
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) * words */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) if (toklen <= 12)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) _enter(",{%x,%x,%x},%u",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) ntohl(xdr[0]), ntohl(xdr[1]), ntohl(xdr[2]), toklen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) n_parts = ntohl(*xdr++);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) toklen -= 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) if (n_parts <= 0 || n_parts > AFSTOKEN_K5_COMPONENTS_MAX)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) princ->n_name_parts = n_parts;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) if (toklen <= (n_parts + 1) * 4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) princ->name_parts = kcalloc(n_parts, sizeof(char *), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) if (!princ->name_parts)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) for (loop = 0; loop < n_parts; loop++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) if (toklen < 4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) tmp = ntohl(*xdr++);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) toklen -= 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) if (tmp <= 0 || tmp > AFSTOKEN_STRING_MAX)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) paddedlen = (tmp + 3) & ~3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) if (paddedlen > toklen)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) princ->name_parts[loop] = kmalloc(tmp + 1, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) if (!princ->name_parts[loop])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) memcpy(princ->name_parts[loop], xdr, tmp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) princ->name_parts[loop][tmp] = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) toklen -= paddedlen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) xdr += paddedlen >> 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) if (toklen < 4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) tmp = ntohl(*xdr++);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) toklen -= 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) if (tmp <= 0 || tmp > AFSTOKEN_K5_REALM_MAX)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) paddedlen = (tmp + 3) & ~3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) if (paddedlen > toklen)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) princ->realm = kmalloc(tmp + 1, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) if (!princ->realm)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) memcpy(princ->realm, xdr, tmp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) princ->realm[tmp] = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) toklen -= paddedlen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) xdr += paddedlen >> 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) _debug("%s/...@%s", princ->name_parts[0], princ->realm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) *_xdr = xdr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) *_toklen = toklen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) _leave(" = 0 [toklen=%u]", toklen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) * extract a piece of krb5 tagged data
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) static int rxrpc_krb5_decode_tagged_data(struct krb5_tagged_data *td,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) size_t max_data_size,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) const __be32 **_xdr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) unsigned int *_toklen)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) const __be32 *xdr = *_xdr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) unsigned int toklen = *_toklen, len, paddedlen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) /* there must be at least one tag and one length word */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) if (toklen <= 8)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) _enter(",%zu,{%x,%x},%u",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) max_data_size, ntohl(xdr[0]), ntohl(xdr[1]), toklen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) td->tag = ntohl(*xdr++);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) len = ntohl(*xdr++);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) toklen -= 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) if (len > max_data_size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) paddedlen = (len + 3) & ~3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) if (paddedlen > toklen)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) td->data_len = len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) if (len > 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) td->data = kmemdup(xdr, len, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) if (!td->data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) toklen -= paddedlen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) xdr += paddedlen >> 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) _debug("tag %x len %x", td->tag, td->data_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) *_xdr = xdr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) *_toklen = toklen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) _leave(" = 0 [toklen=%u]", toklen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) * extract an array of tagged data
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) static int rxrpc_krb5_decode_tagged_array(struct krb5_tagged_data **_td,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) u8 *_n_elem,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) u8 max_n_elem,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) size_t max_elem_size,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) const __be32 **_xdr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) unsigned int *_toklen)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) struct krb5_tagged_data *td;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) const __be32 *xdr = *_xdr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) unsigned int toklen = *_toklen, n_elem, loop;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) /* there must be at least one count */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) if (toklen < 4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) _enter(",,%u,%zu,{%x},%u",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) max_n_elem, max_elem_size, ntohl(xdr[0]), toklen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) n_elem = ntohl(*xdr++);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) toklen -= 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) if (n_elem > max_n_elem)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) *_n_elem = n_elem;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) if (n_elem > 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) if (toklen <= (n_elem + 1) * 4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) _debug("n_elem %d", n_elem);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) td = kcalloc(n_elem, sizeof(struct krb5_tagged_data),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) if (!td)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) *_td = td;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) for (loop = 0; loop < n_elem; loop++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) ret = rxrpc_krb5_decode_tagged_data(&td[loop],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) max_elem_size,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) &xdr, &toklen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) *_xdr = xdr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) *_toklen = toklen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) _leave(" = 0 [toklen=%u]", toklen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) * extract a krb5 ticket
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) static int rxrpc_krb5_decode_ticket(u8 **_ticket, u16 *_tktlen,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) const __be32 **_xdr, unsigned int *_toklen)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) const __be32 *xdr = *_xdr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) unsigned int toklen = *_toklen, len, paddedlen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) /* there must be at least one length word */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) if (toklen <= 4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) _enter(",{%x},%u", ntohl(xdr[0]), toklen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) len = ntohl(*xdr++);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) toklen -= 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) if (len > AFSTOKEN_K5_TIX_MAX)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) paddedlen = (len + 3) & ~3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) if (paddedlen > toklen)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) *_tktlen = len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) _debug("ticket len %u", len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) if (len > 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) *_ticket = kmemdup(xdr, len, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) if (!*_ticket)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) toklen -= paddedlen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) xdr += paddedlen >> 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) *_xdr = xdr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) *_toklen = toklen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) _leave(" = 0 [toklen=%u]", toklen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) * parse an RxK5 type XDR format token
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) * - the caller guarantees we have at least 4 words
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) static int rxrpc_preparse_xdr_rxk5(struct key_preparsed_payload *prep,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) size_t datalen,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) const __be32 *xdr, unsigned int toklen)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) struct rxrpc_key_token *token, **pptoken;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) struct rxk5_key *rxk5;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) const __be32 *end_xdr = xdr + (toklen >> 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) time64_t expiry;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) _enter(",{%x,%x,%x,%x},%u",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) ntohl(xdr[0]), ntohl(xdr[1]), ntohl(xdr[2]), ntohl(xdr[3]),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) toklen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) /* reserve some payload space for this subkey - the length of the token
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) * is a reasonable approximation */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) prep->quotalen = datalen + toklen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) token = kzalloc(sizeof(*token), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) if (!token)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) rxk5 = kzalloc(sizeof(*rxk5), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) if (!rxk5) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) kfree(token);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) token->security_index = RXRPC_SECURITY_RXK5;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) token->k5 = rxk5;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) /* extract the principals */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) ret = rxrpc_krb5_decode_principal(&rxk5->client, &xdr, &toklen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) ret = rxrpc_krb5_decode_principal(&rxk5->server, &xdr, &toklen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) /* extract the session key and the encoding type (the tag field ->
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) * ENCTYPE_xxx) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) ret = rxrpc_krb5_decode_tagged_data(&rxk5->session, AFSTOKEN_DATA_MAX,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) &xdr, &toklen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) if (toklen < 4 * 8 + 2 * 4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) goto inval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) rxk5->authtime = be64_to_cpup((const __be64 *) xdr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) xdr += 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) rxk5->starttime = be64_to_cpup((const __be64 *) xdr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) xdr += 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) rxk5->endtime = be64_to_cpup((const __be64 *) xdr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) xdr += 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) rxk5->renew_till = be64_to_cpup((const __be64 *) xdr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) xdr += 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) rxk5->is_skey = ntohl(*xdr++);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) rxk5->flags = ntohl(*xdr++);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) toklen -= 4 * 8 + 2 * 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) _debug("times: a=%llx s=%llx e=%llx rt=%llx",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) rxk5->authtime, rxk5->starttime, rxk5->endtime,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) rxk5->renew_till);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) _debug("is_skey=%x flags=%x", rxk5->is_skey, rxk5->flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) /* extract the permitted client addresses */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) ret = rxrpc_krb5_decode_tagged_array(&rxk5->addresses,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) &rxk5->n_addresses,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) AFSTOKEN_K5_ADDRESSES_MAX,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) AFSTOKEN_DATA_MAX,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) &xdr, &toklen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) ASSERTCMP((end_xdr - xdr) << 2, ==, toklen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) /* extract the tickets */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) ret = rxrpc_krb5_decode_ticket(&rxk5->ticket, &rxk5->ticket_len,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) &xdr, &toklen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) ret = rxrpc_krb5_decode_ticket(&rxk5->ticket2, &rxk5->ticket2_len,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) &xdr, &toklen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) ASSERTCMP((end_xdr - xdr) << 2, ==, toklen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) /* extract the typed auth data */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) ret = rxrpc_krb5_decode_tagged_array(&rxk5->authdata,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) &rxk5->n_authdata,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) AFSTOKEN_K5_AUTHDATA_MAX,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) AFSTOKEN_BDATALN_MAX,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) &xdr, &toklen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) ASSERTCMP((end_xdr - xdr) << 2, ==, toklen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) if (toklen != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) goto inval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) /* attach the payload */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) for (pptoken = (struct rxrpc_key_token **)&prep->payload.data[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) *pptoken;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) pptoken = &(*pptoken)->next)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) *pptoken = token;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) expiry = rxrpc_u32_to_time64(token->k5->endtime);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) if (expiry < prep->expiry)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) prep->expiry = expiry;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) _leave(" = 0");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) inval:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) ret = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) error:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) rxrpc_rxk5_free(rxk5);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) kfree(token);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) _leave(" = %d", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) * attempt to parse the data as the XDR format
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) * - the caller guarantees we have more than 7 words
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) static int rxrpc_preparse_xdr(struct key_preparsed_payload *prep)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) const __be32 *xdr = prep->data, *token;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) const char *cp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) unsigned int len, paddedlen, loop, ntoken, toklen, sec_ix;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) size_t datalen = prep->datalen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) _enter(",{%x,%x,%x,%x},%zu",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) ntohl(xdr[0]), ntohl(xdr[1]), ntohl(xdr[2]), ntohl(xdr[3]),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) prep->datalen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) if (datalen > AFSTOKEN_LENGTH_MAX)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) goto not_xdr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) /* XDR is an array of __be32's */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) if (datalen & 3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) goto not_xdr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) /* the flags should be 0 (the setpag bit must be handled by
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) * userspace) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) if (ntohl(*xdr++) != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) goto not_xdr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) datalen -= 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) /* check the cell name */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) len = ntohl(*xdr++);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) if (len < 1 || len > AFSTOKEN_CELL_MAX)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) goto not_xdr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) datalen -= 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) paddedlen = (len + 3) & ~3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) if (paddedlen > datalen)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) goto not_xdr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) cp = (const char *) xdr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) for (loop = 0; loop < len; loop++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) if (!isprint(cp[loop]))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) goto not_xdr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) for (; loop < paddedlen; loop++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) if (cp[loop])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) goto not_xdr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) _debug("cellname: [%u/%u] '%*.*s'",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) len, paddedlen, len, len, (const char *) xdr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) datalen -= paddedlen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) xdr += paddedlen >> 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) /* get the token count */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) if (datalen < 12)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) goto not_xdr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) ntoken = ntohl(*xdr++);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) datalen -= 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) _debug("ntoken: %x", ntoken);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) if (ntoken < 1 || ntoken > AFSTOKEN_MAX)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) goto not_xdr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) /* check each token wrapper */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) token = xdr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) loop = ntoken;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) do {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) if (datalen < 8)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) goto not_xdr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) toklen = ntohl(*xdr++);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) sec_ix = ntohl(*xdr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) datalen -= 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) _debug("token: [%x/%zx] %x", toklen, datalen, sec_ix);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) paddedlen = (toklen + 3) & ~3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) if (toklen < 20 || toklen > datalen || paddedlen > datalen)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) goto not_xdr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) datalen -= paddedlen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) xdr += paddedlen >> 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) } while (--loop > 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) _debug("remainder: %zu", datalen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) if (datalen != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) goto not_xdr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) /* okay: we're going to assume it's valid XDR format
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) * - we ignore the cellname, relying on the key to be correctly named
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) do {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638) xdr = token;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) toklen = ntohl(*xdr++);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) token = xdr + ((toklen + 3) >> 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) sec_ix = ntohl(*xdr++);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642) toklen -= 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) _debug("TOKEN type=%u [%p-%p]", sec_ix, xdr, token);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) switch (sec_ix) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647) case RXRPC_SECURITY_RXKAD:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) ret = rxrpc_preparse_xdr_rxkad(prep, datalen, xdr, toklen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) if (ret != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) case RXRPC_SECURITY_RXK5:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) ret = rxrpc_preparse_xdr_rxk5(prep, datalen, xdr, toklen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655) if (ret != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656) goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660) ret = -EPROTONOSUPPORT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664) } while (--ntoken > 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666) _leave(" = 0");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) not_xdr:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) _leave(" = -EPROTO");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671) return -EPROTO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672) error:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673) _leave(" = %d", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678) * Preparse an rxrpc defined key.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680) * Data should be of the form:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681) * OFFSET LEN CONTENT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682) * 0 4 key interface version number
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683) * 4 2 security index (type)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684) * 6 2 ticket length
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685) * 8 4 key expiry time (time_t)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686) * 12 4 kvno
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687) * 16 8 session key
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688) * 24 [len] ticket
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690) * if no data is provided, then a no-security key is made
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692) static int rxrpc_preparse(struct key_preparsed_payload *prep)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694) const struct rxrpc_key_data_v1 *v1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695) struct rxrpc_key_token *token, **pp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696) time64_t expiry;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697) size_t plen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698) u32 kver;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701) _enter("%zu", prep->datalen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703) /* handle a no-security key */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704) if (!prep->data && prep->datalen == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707) /* determine if the XDR payload format is being used */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708) if (prep->datalen > 7 * 4) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709) ret = rxrpc_preparse_xdr(prep);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710) if (ret != -EPROTO)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714) /* get the key interface version number */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715) ret = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716) if (prep->datalen <= 4 || !prep->data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717) goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718) memcpy(&kver, prep->data, sizeof(kver));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719) prep->data += sizeof(kver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720) prep->datalen -= sizeof(kver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722) _debug("KEY I/F VERSION: %u", kver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724) ret = -EKEYREJECTED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725) if (kver != 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726) goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728) /* deal with a version 1 key */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729) ret = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730) if (prep->datalen < sizeof(*v1))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731) goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733) v1 = prep->data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734) if (prep->datalen != sizeof(*v1) + v1->ticket_length)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735) goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737) _debug("SCIX: %u", v1->security_index);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738) _debug("TLEN: %u", v1->ticket_length);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739) _debug("EXPY: %x", v1->expiry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740) _debug("KVNO: %u", v1->kvno);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741) _debug("SKEY: %02x%02x%02x%02x%02x%02x%02x%02x",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742) v1->session_key[0], v1->session_key[1],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743) v1->session_key[2], v1->session_key[3],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744) v1->session_key[4], v1->session_key[5],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745) v1->session_key[6], v1->session_key[7]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746) if (v1->ticket_length >= 8)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747) _debug("TCKT: %02x%02x%02x%02x%02x%02x%02x%02x",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748) v1->ticket[0], v1->ticket[1],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749) v1->ticket[2], v1->ticket[3],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750) v1->ticket[4], v1->ticket[5],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751) v1->ticket[6], v1->ticket[7]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753) ret = -EPROTONOSUPPORT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754) if (v1->security_index != RXRPC_SECURITY_RXKAD)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755) goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757) plen = sizeof(*token->kad) + v1->ticket_length;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758) prep->quotalen = plen + sizeof(*token);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760) ret = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761) token = kzalloc(sizeof(*token), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762) if (!token)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763) goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764) token->kad = kzalloc(plen, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765) if (!token->kad)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766) goto error_free;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768) token->security_index = RXRPC_SECURITY_RXKAD;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769) token->kad->ticket_len = v1->ticket_length;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770) token->kad->expiry = v1->expiry;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771) token->kad->kvno = v1->kvno;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772) memcpy(&token->kad->session_key, &v1->session_key, 8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773) memcpy(&token->kad->ticket, v1->ticket, v1->ticket_length);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 775) /* count the number of tokens attached */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 776) prep->payload.data[1] = (void *)((unsigned long)prep->payload.data[1] + 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 777)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 778) /* attach the data */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 779) pp = (struct rxrpc_key_token **)&prep->payload.data[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 780) while (*pp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 781) pp = &(*pp)->next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 782) *pp = token;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 783) expiry = rxrpc_u32_to_time64(token->kad->expiry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 784) if (expiry < prep->expiry)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 785) prep->expiry = expiry;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 786) token = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 787) ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 788)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 789) error_free:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 790) kfree(token);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 791) error:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 792) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 793) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 794)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 795) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 796) * Free token list.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 797) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 798) static void rxrpc_free_token_list(struct rxrpc_key_token *token)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 799) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 800) struct rxrpc_key_token *next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 801)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 802) for (; token; token = next) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 803) next = token->next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 804) switch (token->security_index) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 805) case RXRPC_SECURITY_RXKAD:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 806) kfree(token->kad);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 807) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 808) case RXRPC_SECURITY_RXK5:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 809) if (token->k5)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 810) rxrpc_rxk5_free(token->k5);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 811) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 812) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 813) pr_err("Unknown token type %x on rxrpc key\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 814) token->security_index);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 815) BUG();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 816) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 817)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 818) kfree(token);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 819) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 820) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 821)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 822) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 823) * Clean up preparse data.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 824) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 825) static void rxrpc_free_preparse(struct key_preparsed_payload *prep)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 826) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 827) rxrpc_free_token_list(prep->payload.data[0]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 828) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 829)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 830) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 831) * Preparse a server secret key.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 832) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 833) * The data should be the 8-byte secret key.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 834) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 835) static int rxrpc_preparse_s(struct key_preparsed_payload *prep)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 836) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 837) struct crypto_skcipher *ci;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 838)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 839) _enter("%zu", prep->datalen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 840)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 841) if (prep->datalen != 8)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 842) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 843)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 844) memcpy(&prep->payload.data[2], prep->data, 8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 845)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 846) ci = crypto_alloc_skcipher("pcbc(des)", 0, CRYPTO_ALG_ASYNC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 847) if (IS_ERR(ci)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 848) _leave(" = %ld", PTR_ERR(ci));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 849) return PTR_ERR(ci);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 850) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 851)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 852) if (crypto_skcipher_setkey(ci, prep->data, 8) < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 853) BUG();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 854)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 855) prep->payload.data[0] = ci;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 856) _leave(" = 0");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 857) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 858) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 859)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 860) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 861) * Clean up preparse data.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 862) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 863) static void rxrpc_free_preparse_s(struct key_preparsed_payload *prep)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 864) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 865) if (prep->payload.data[0])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 866) crypto_free_skcipher(prep->payload.data[0]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 867) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 868)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 869) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 870) * dispose of the data dangling from the corpse of a rxrpc key
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 871) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 872) static void rxrpc_destroy(struct key *key)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 873) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 874) rxrpc_free_token_list(key->payload.data[0]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 875) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 876)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 877) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 878) * dispose of the data dangling from the corpse of a rxrpc key
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 879) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 880) static void rxrpc_destroy_s(struct key *key)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 881) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 882) if (key->payload.data[0]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 883) crypto_free_skcipher(key->payload.data[0]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 884) key->payload.data[0] = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 885) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 886) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 887)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 888) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 889) * describe the rxrpc key
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 890) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 891) static void rxrpc_describe(const struct key *key, struct seq_file *m)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 892) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 893) seq_puts(m, key->description);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 894) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 895)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 896) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 897) * grab the security key for a socket
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 898) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 899) int rxrpc_request_key(struct rxrpc_sock *rx, sockptr_t optval, int optlen)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 900) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 901) struct key *key;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 902) char *description;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 903)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 904) _enter("");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 905)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 906) if (optlen <= 0 || optlen > PAGE_SIZE - 1 || rx->securities)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 907) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 908)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 909) description = memdup_sockptr_nul(optval, optlen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 910) if (IS_ERR(description))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 911) return PTR_ERR(description);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 912)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 913) key = request_key_net(&key_type_rxrpc, description, sock_net(&rx->sk), NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 914) if (IS_ERR(key)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 915) kfree(description);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 916) _leave(" = %ld", PTR_ERR(key));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 917) return PTR_ERR(key);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 918) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 919)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 920) rx->key = key;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 921) kfree(description);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 922) _leave(" = 0 [key %x]", key->serial);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 923) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 924) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 925)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 926) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 927) * grab the security keyring for a server socket
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 928) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 929) int rxrpc_server_keyring(struct rxrpc_sock *rx, sockptr_t optval, int optlen)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 930) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 931) struct key *key;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 932) char *description;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 933)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 934) _enter("");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 935)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 936) if (optlen <= 0 || optlen > PAGE_SIZE - 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 937) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 938)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 939) description = memdup_sockptr_nul(optval, optlen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 940) if (IS_ERR(description))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 941) return PTR_ERR(description);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 942)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 943) key = request_key(&key_type_keyring, description, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 944) if (IS_ERR(key)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 945) kfree(description);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 946) _leave(" = %ld", PTR_ERR(key));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 947) return PTR_ERR(key);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 948) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 949)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 950) rx->securities = key;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 951) kfree(description);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 952) _leave(" = 0 [key %x]", key->serial);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 953) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 954) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 955)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 956) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 957) * generate a server data key
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 958) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 959) int rxrpc_get_server_data_key(struct rxrpc_connection *conn,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 960) const void *session_key,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 961) time64_t expiry,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 962) u32 kvno)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 963) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 964) const struct cred *cred = current_cred();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 965) struct key *key;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 966) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 967)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 968) struct {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 969) u32 kver;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 970) struct rxrpc_key_data_v1 v1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 971) } data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 972)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 973) _enter("");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 974)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 975) key = key_alloc(&key_type_rxrpc, "x",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 976) GLOBAL_ROOT_UID, GLOBAL_ROOT_GID, cred, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 977) KEY_ALLOC_NOT_IN_QUOTA, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 978) if (IS_ERR(key)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 979) _leave(" = -ENOMEM [alloc %ld]", PTR_ERR(key));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 980) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 981) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 982)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 983) _debug("key %d", key_serial(key));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 984)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 985) data.kver = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 986) data.v1.security_index = RXRPC_SECURITY_RXKAD;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 987) data.v1.ticket_length = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 988) data.v1.expiry = rxrpc_time64_to_u32(expiry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 989) data.v1.kvno = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 990)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 991) memcpy(&data.v1.session_key, session_key, sizeof(data.v1.session_key));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 992)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 993) ret = key_instantiate_and_link(key, &data, sizeof(data), NULL, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 994) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 995) goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 996)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 997) conn->params.key = key;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 998) _leave(" = 0 [%d]", key_serial(key));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 999) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1000)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1001) error:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1002) key_revoke(key);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1003) key_put(key);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1004) _leave(" = -ENOMEM [ins %d]", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1005) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1006) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1007) EXPORT_SYMBOL(rxrpc_get_server_data_key);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1008)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1009) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1010) * rxrpc_get_null_key - Generate a null RxRPC key
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1011) * @keyname: The name to give the key.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1012) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1013) * Generate a null RxRPC key that can be used to indicate anonymous security is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1014) * required for a particular domain.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1015) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1016) struct key *rxrpc_get_null_key(const char *keyname)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1017) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1018) const struct cred *cred = current_cred();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1019) struct key *key;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1020) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1021)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1022) key = key_alloc(&key_type_rxrpc, keyname,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1023) GLOBAL_ROOT_UID, GLOBAL_ROOT_GID, cred,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1024) KEY_POS_SEARCH, KEY_ALLOC_NOT_IN_QUOTA, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1025) if (IS_ERR(key))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1026) return key;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1027)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1028) ret = key_instantiate_and_link(key, NULL, 0, NULL, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1029) if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1030) key_revoke(key);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1031) key_put(key);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1032) return ERR_PTR(ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1033) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1034)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1035) return key;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1036) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1037) EXPORT_SYMBOL(rxrpc_get_null_key);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1038)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1039) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1040) * read the contents of an rxrpc key
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1041) * - this returns the result in XDR form
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1042) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1043) static long rxrpc_read(const struct key *key,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1044) char *buffer, size_t buflen)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1045) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1046) const struct rxrpc_key_token *token;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1047) const struct krb5_principal *princ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1048) size_t size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1049) __be32 *xdr, *oldxdr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1050) u32 cnlen, toksize, ntoks, tok, zero;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1051) u16 toksizes[AFSTOKEN_MAX];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1052) int loop;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1053)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1054) _enter("");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1055)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1056) /* we don't know what form we should return non-AFS keys in */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1057) if (memcmp(key->description, "afs@", 4) != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1058) return -EOPNOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1059) cnlen = strlen(key->description + 4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1060)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1061) #define RND(X) (((X) + 3) & ~3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1062)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1063) /* AFS keys we return in XDR form, so we need to work out the size of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1064) * the XDR */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1065) size = 2 * 4; /* flags, cellname len */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1066) size += RND(cnlen); /* cellname */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1067) size += 1 * 4; /* token count */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1068)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1069) ntoks = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1070) for (token = key->payload.data[0]; token; token = token->next) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1071) toksize = 4; /* sec index */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1072)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1073) switch (token->security_index) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1074) case RXRPC_SECURITY_RXKAD:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1075) toksize += 8 * 4; /* viceid, kvno, key*2, begin,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1076) * end, primary, tktlen */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1077) toksize += RND(token->kad->ticket_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1078) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1079)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1080) case RXRPC_SECURITY_RXK5:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1081) princ = &token->k5->client;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1082) toksize += 4 + princ->n_name_parts * 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1083) for (loop = 0; loop < princ->n_name_parts; loop++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1084) toksize += RND(strlen(princ->name_parts[loop]));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1085) toksize += 4 + RND(strlen(princ->realm));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1086)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1087) princ = &token->k5->server;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1088) toksize += 4 + princ->n_name_parts * 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1089) for (loop = 0; loop < princ->n_name_parts; loop++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1090) toksize += RND(strlen(princ->name_parts[loop]));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1091) toksize += 4 + RND(strlen(princ->realm));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1092)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1093) toksize += 8 + RND(token->k5->session.data_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1094)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1095) toksize += 4 * 8 + 2 * 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1096)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1097) toksize += 4 + token->k5->n_addresses * 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1098) for (loop = 0; loop < token->k5->n_addresses; loop++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1099) toksize += RND(token->k5->addresses[loop].data_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1100)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1101) toksize += 4 + RND(token->k5->ticket_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1102) toksize += 4 + RND(token->k5->ticket2_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1103)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1104) toksize += 4 + token->k5->n_authdata * 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1105) for (loop = 0; loop < token->k5->n_authdata; loop++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1106) toksize += RND(token->k5->authdata[loop].data_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1107) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1108)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1109) default: /* we have a ticket we can't encode */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1110) pr_err("Unsupported key token type (%u)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1111) token->security_index);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1112) return -ENOPKG;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1113) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1114)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1115) _debug("token[%u]: toksize=%u", ntoks, toksize);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1116) ASSERTCMP(toksize, <=, AFSTOKEN_LENGTH_MAX);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1117)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1118) toksizes[ntoks++] = toksize;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1119) size += toksize + 4; /* each token has a length word */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1120) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1121)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1122) #undef RND
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1123)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1124) if (!buffer || buflen < size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1125) return size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1126)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1127) xdr = (__be32 *)buffer;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1128) zero = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1129) #define ENCODE(x) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1130) do { \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1131) *xdr++ = htonl(x); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1132) } while(0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1133) #define ENCODE_DATA(l, s) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1134) do { \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1135) u32 _l = (l); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1136) ENCODE(l); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1137) memcpy(xdr, (s), _l); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1138) if (_l & 3) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1139) memcpy((u8 *)xdr + _l, &zero, 4 - (_l & 3)); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1140) xdr += (_l + 3) >> 2; \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1141) } while(0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1142) #define ENCODE_BYTES(l, s) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1143) do { \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1144) u32 _l = (l); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1145) memcpy(xdr, (s), _l); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1146) if (_l & 3) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1147) memcpy((u8 *)xdr + _l, &zero, 4 - (_l & 3)); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1148) xdr += (_l + 3) >> 2; \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1149) } while(0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1150) #define ENCODE64(x) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1151) do { \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1152) __be64 y = cpu_to_be64(x); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1153) memcpy(xdr, &y, 8); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1154) xdr += 8 >> 2; \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1155) } while(0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1156) #define ENCODE_STR(s) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1157) do { \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1158) const char *_s = (s); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1159) ENCODE_DATA(strlen(_s), _s); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1160) } while(0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1161)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1162) ENCODE(0); /* flags */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1163) ENCODE_DATA(cnlen, key->description + 4); /* cellname */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1164) ENCODE(ntoks);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1165)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1166) tok = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1167) for (token = key->payload.data[0]; token; token = token->next) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1168) toksize = toksizes[tok++];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1169) ENCODE(toksize);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1170) oldxdr = xdr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1171) ENCODE(token->security_index);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1172)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1173) switch (token->security_index) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1174) case RXRPC_SECURITY_RXKAD:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1175) ENCODE(token->kad->vice_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1176) ENCODE(token->kad->kvno);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1177) ENCODE_BYTES(8, token->kad->session_key);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1178) ENCODE(token->kad->start);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1179) ENCODE(token->kad->expiry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1180) ENCODE(token->kad->primary_flag);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1181) ENCODE_DATA(token->kad->ticket_len, token->kad->ticket);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1182) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1183)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1184) case RXRPC_SECURITY_RXK5:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1185) princ = &token->k5->client;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1186) ENCODE(princ->n_name_parts);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1187) for (loop = 0; loop < princ->n_name_parts; loop++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1188) ENCODE_STR(princ->name_parts[loop]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1189) ENCODE_STR(princ->realm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1190)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1191) princ = &token->k5->server;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1192) ENCODE(princ->n_name_parts);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1193) for (loop = 0; loop < princ->n_name_parts; loop++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1194) ENCODE_STR(princ->name_parts[loop]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1195) ENCODE_STR(princ->realm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1196)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1197) ENCODE(token->k5->session.tag);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1198) ENCODE_DATA(token->k5->session.data_len,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1199) token->k5->session.data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1200)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1201) ENCODE64(token->k5->authtime);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1202) ENCODE64(token->k5->starttime);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1203) ENCODE64(token->k5->endtime);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1204) ENCODE64(token->k5->renew_till);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1205) ENCODE(token->k5->is_skey);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1206) ENCODE(token->k5->flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1207)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1208) ENCODE(token->k5->n_addresses);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1209) for (loop = 0; loop < token->k5->n_addresses; loop++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1210) ENCODE(token->k5->addresses[loop].tag);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1211) ENCODE_DATA(token->k5->addresses[loop].data_len,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1212) token->k5->addresses[loop].data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1213) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1214)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1215) ENCODE_DATA(token->k5->ticket_len, token->k5->ticket);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1216) ENCODE_DATA(token->k5->ticket2_len, token->k5->ticket2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1217)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1218) ENCODE(token->k5->n_authdata);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1219) for (loop = 0; loop < token->k5->n_authdata; loop++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1220) ENCODE(token->k5->authdata[loop].tag);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1221) ENCODE_DATA(token->k5->authdata[loop].data_len,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1222) token->k5->authdata[loop].data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1223) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1224) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1225)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1226) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1227) pr_err("Unsupported key token type (%u)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1228) token->security_index);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1229) return -ENOPKG;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1230) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1231)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1232) ASSERTCMP((unsigned long)xdr - (unsigned long)oldxdr, ==,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1233) toksize);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1234) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1235)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1236) #undef ENCODE_STR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1237) #undef ENCODE_DATA
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1238) #undef ENCODE64
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1239) #undef ENCODE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1240)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1241) ASSERTCMP(tok, ==, ntoks);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1242) ASSERTCMP((char __user *) xdr - buffer, ==, size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1243) _leave(" = %zu", size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1244) return size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1245) }