// SPDX-License-Identifier: GPL-2.0-or-later /* RxRPC key management * * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved. * Written by David Howells (dhowells@redhat.com) * * RxRPC keys should have a description of describing their purpose: * "afs@example.com"
*/
/* * rxrpc defined keys take an arbitrary string as the description and an * arbitrary blob of data as the payload
*/ struct key_type key_type_rxrpc = {
.name = "rxrpc",
.flags = KEY_TYPE_NET_DOMAIN,
.preparse = rxrpc_preparse,
.free_preparse = rxrpc_free_preparse,
.instantiate = generic_key_instantiate,
.destroy = rxrpc_destroy,
.describe = rxrpc_describe,
.read = rxrpc_read,
};
EXPORT_SYMBOL(key_type_rxrpc);
/* * parse an RxKAD type XDR format token * - the caller guarantees we have at least 4 words
*/ staticint rxrpc_preparse_xdr_rxkad(struct key_preparsed_payload *prep,
size_t datalen, const __be32 *xdr, unsignedint toklen)
{ struct rxrpc_key_token *token, **pptoken;
time64_t expiry;
size_t plen;
u32 tktlen;
/* Pad the ticket so that we can use it directly in XDR */
token->rxgk->ticket.data = kzalloc(round_up(token->rxgk->ticket.len, 4),
GFP_KERNEL); if (!token->rxgk->ticket.data) goto nomem_yrxgk;
memcpy(token->rxgk->ticket.data, ticket, token->rxgk->ticket.len);
/* * attempt to parse the data as the XDR format * - the caller guarantees we have more than 7 words
*/ staticint rxrpc_preparse_xdr(struct key_preparsed_payload *prep)
{ const __be32 *xdr = prep->data, *token, *p; constchar *cp; unsignedint len, paddedlen, loop, ntoken, toklen, sec_ix;
size_t datalen = prep->datalen; int ret, ret2;
_debug("remainder: %zu", datalen); if (datalen != 0) goto not_xdr;
/* okay: we're going to assume it's valid XDR format * - we ignore the cellname, relying on the key to be correctly named
*/
ret = -EPROTONOSUPPORT; do {
toklen = ntohl(*xdr++);
token = xdr;
xdr += (toklen + 3) / 4;
switch (ret2) { case 0:
ret = 0; break; case -EPROTONOSUPPORT: break; case -ENOPKG: if (ret != 0)
ret = -ENOPKG; break; default:
ret = ret2; goto error;
}
} while (--ntoken > 0);
error:
_leave(" = %d", ret); return ret;
not_xdr:
_leave(" = -EPROTO"); return -EPROTO;
}
/* * Preparse an rxrpc defined key. * * Data should be of the form: * OFFSET LEN CONTENT * 0 4 key interface version number * 4 2 security index (type) * 6 2 ticket length * 8 4 key expiry time (time_t) * 12 4 kvno * 16 8 session key * 24 [len] ticket * * if no data is provided, then a no-security key is made
*/ staticint rxrpc_preparse(struct key_preparsed_payload *prep)
{ conststruct rxrpc_key_data_v1 *v1; struct rxrpc_key_token *token, **pp;
time64_t expiry;
size_t plen;
u32 kver; int ret;
_enter("%zu", prep->datalen);
/* handle a no-security key */ if (!prep->data && prep->datalen == 0) return 0;
/* determine if the XDR payload format is being used */ if (prep->datalen > 7 * 4) {
ret = rxrpc_preparse_xdr(prep); if (ret != -EPROTO) return ret;
}
/* get the key interface version number */
ret = -EINVAL; if (prep->datalen <= 4 || !prep->data) goto error;
memcpy(&kver, prep->data, sizeof(kver));
prep->data += sizeof(kver);
prep->datalen -= sizeof(kver);
_debug("KEY I/F VERSION: %u", kver);
ret = -EKEYREJECTED; if (kver != 1) goto error;
/* deal with a version 1 key */
ret = -EINVAL; if (prep->datalen < sizeof(*v1)) goto error;
/* * dispose of the data dangling from the corpse of a rxrpc key
*/ staticvoid rxrpc_destroy(struct key *key)
{
rxrpc_free_token_list(key->payload.data[0]);
}
switch (token->security_index) { case RXRPC_SECURITY_RXKAD:
seq_puts(m, "ka"); break; case RXRPC_SECURITY_YFS_RXGK:
seq_puts(m, "ygk"); break; default: /* we have a ticket we can't encode */
seq_printf(m, "%u", token->security_index); break;
}
sep = " ";
}
}
/* * grab the security key for a socket
*/ int rxrpc_request_key(struct rxrpc_sock *rx, sockptr_t optval, int optlen)
{ struct key *key; char *description;
/** * rxrpc_get_null_key - Generate a null RxRPC key * @keyname: The name to give the key. * * Generate a null RxRPC key that can be used to indicate anonymous security is * required for a particular domain. * * Return: The new key or a negative error code.
*/ struct key *rxrpc_get_null_key(constchar *keyname)
{ conststruct cred *cred = current_cred(); struct key *key; int ret;
ret = key_instantiate_and_link(key, NULL, 0, NULL, NULL); if (ret < 0) {
key_revoke(key);
key_put(key); return ERR_PTR(ret);
}
return key;
}
EXPORT_SYMBOL(rxrpc_get_null_key);
/* * read the contents of an rxrpc key * - this returns the result in XDR form
*/ staticlong rxrpc_read(conststruct key *key, char *buffer, size_t buflen)
{ conststruct rxrpc_key_token *token;
size_t size;
__be32 *xdr, *oldxdr;
u32 cnlen, toksize, ntoks, tok, zero;
u16 toksizes[AFSTOKEN_MAX];
_enter("");
/* we don't know what form we should return non-AFS keys in */ if (memcmp(key->description, "afs@", 4) != 0) return -EOPNOTSUPP;
cnlen = strlen(key->description + 4);
#define RND(X) (((X) + 3) & ~3)
/* AFS keys we return in XDR form, so we need to work out the size of
* the XDR */
size = 2 * 4; /* flags, cellname len */
size += RND(cnlen); /* cellname */
size += 1 * 4; /* token count */
ntoks = 0; for (token = key->payload.data[0]; token; token = token->next) {
toksize = 4; /* sec index */
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.