0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
0012
0013 #include <crypto/skcipher.h>
0014 #include <linux/module.h>
0015 #include <linux/net.h>
0016 #include <linux/skbuff.h>
0017 #include <linux/key-type.h>
0018 #include <linux/ctype.h>
0019 #include <linux/slab.h>
0020 #include <net/sock.h>
0021 #include <net/af_rxrpc.h>
0022 #include <keys/rxrpc-type.h>
0023 #include <keys/user-type.h>
0024 #include "ar-internal.h"
0025
0026 static int rxrpc_preparse(struct key_preparsed_payload *);
0027 static void rxrpc_free_preparse(struct key_preparsed_payload *);
0028 static void rxrpc_destroy(struct key *);
0029 static void rxrpc_describe(const struct key *, struct seq_file *);
0030 static long rxrpc_read(const struct key *, char *, size_t);
0031
0032
0033
0034
0035
0036 struct key_type key_type_rxrpc = {
0037 .name = "rxrpc",
0038 .flags = KEY_TYPE_NET_DOMAIN,
0039 .preparse = rxrpc_preparse,
0040 .free_preparse = rxrpc_free_preparse,
0041 .instantiate = generic_key_instantiate,
0042 .destroy = rxrpc_destroy,
0043 .describe = rxrpc_describe,
0044 .read = rxrpc_read,
0045 };
0046 EXPORT_SYMBOL(key_type_rxrpc);
0047
0048
0049
0050
0051
0052 static int rxrpc_preparse_xdr_rxkad(struct key_preparsed_payload *prep,
0053 size_t datalen,
0054 const __be32 *xdr, unsigned int toklen)
0055 {
0056 struct rxrpc_key_token *token, **pptoken;
0057 time64_t expiry;
0058 size_t plen;
0059 u32 tktlen;
0060
0061 _enter(",{%x,%x,%x,%x},%u",
0062 ntohl(xdr[0]), ntohl(xdr[1]), ntohl(xdr[2]), ntohl(xdr[3]),
0063 toklen);
0064
0065 if (toklen <= 8 * 4)
0066 return -EKEYREJECTED;
0067 tktlen = ntohl(xdr[7]);
0068 _debug("tktlen: %x", tktlen);
0069 if (tktlen > AFSTOKEN_RK_TIX_MAX)
0070 return -EKEYREJECTED;
0071 if (toklen < 8 * 4 + tktlen)
0072 return -EKEYREJECTED;
0073
0074 plen = sizeof(*token) + sizeof(*token->kad) + tktlen;
0075 prep->quotalen = datalen + plen;
0076
0077 plen -= sizeof(*token);
0078 token = kzalloc(sizeof(*token), GFP_KERNEL);
0079 if (!token)
0080 return -ENOMEM;
0081
0082 token->kad = kzalloc(plen, GFP_KERNEL);
0083 if (!token->kad) {
0084 kfree(token);
0085 return -ENOMEM;
0086 }
0087
0088 token->security_index = RXRPC_SECURITY_RXKAD;
0089 token->kad->ticket_len = tktlen;
0090 token->kad->vice_id = ntohl(xdr[0]);
0091 token->kad->kvno = ntohl(xdr[1]);
0092 token->kad->start = ntohl(xdr[4]);
0093 token->kad->expiry = ntohl(xdr[5]);
0094 token->kad->primary_flag = ntohl(xdr[6]);
0095 memcpy(&token->kad->session_key, &xdr[2], 8);
0096 memcpy(&token->kad->ticket, &xdr[8], tktlen);
0097
0098 _debug("SCIX: %u", token->security_index);
0099 _debug("TLEN: %u", token->kad->ticket_len);
0100 _debug("EXPY: %x", token->kad->expiry);
0101 _debug("KVNO: %u", token->kad->kvno);
0102 _debug("PRIM: %u", token->kad->primary_flag);
0103 _debug("SKEY: %02x%02x%02x%02x%02x%02x%02x%02x",
0104 token->kad->session_key[0], token->kad->session_key[1],
0105 token->kad->session_key[2], token->kad->session_key[3],
0106 token->kad->session_key[4], token->kad->session_key[5],
0107 token->kad->session_key[6], token->kad->session_key[7]);
0108 if (token->kad->ticket_len >= 8)
0109 _debug("TCKT: %02x%02x%02x%02x%02x%02x%02x%02x",
0110 token->kad->ticket[0], token->kad->ticket[1],
0111 token->kad->ticket[2], token->kad->ticket[3],
0112 token->kad->ticket[4], token->kad->ticket[5],
0113 token->kad->ticket[6], token->kad->ticket[7]);
0114
0115
0116 prep->payload.data[1] = (void *)((unsigned long)prep->payload.data[1] + 1);
0117
0118
0119 for (pptoken = (struct rxrpc_key_token **)&prep->payload.data[0];
0120 *pptoken;
0121 pptoken = &(*pptoken)->next)
0122 continue;
0123 *pptoken = token;
0124 expiry = rxrpc_u32_to_time64(token->kad->expiry);
0125 if (expiry < prep->expiry)
0126 prep->expiry = expiry;
0127
0128 _leave(" = 0");
0129 return 0;
0130 }
0131
0132
0133
0134
0135
0136 static int rxrpc_preparse_xdr(struct key_preparsed_payload *prep)
0137 {
0138 const __be32 *xdr = prep->data, *token, *p;
0139 const char *cp;
0140 unsigned int len, paddedlen, loop, ntoken, toklen, sec_ix;
0141 size_t datalen = prep->datalen;
0142 int ret, ret2;
0143
0144 _enter(",{%x,%x,%x,%x},%zu",
0145 ntohl(xdr[0]), ntohl(xdr[1]), ntohl(xdr[2]), ntohl(xdr[3]),
0146 prep->datalen);
0147
0148 if (datalen > AFSTOKEN_LENGTH_MAX)
0149 goto not_xdr;
0150
0151
0152 if (datalen & 3)
0153 goto not_xdr;
0154
0155
0156
0157 if (ntohl(*xdr++) != 0)
0158 goto not_xdr;
0159 datalen -= 4;
0160
0161
0162 len = ntohl(*xdr++);
0163 if (len < 1 || len > AFSTOKEN_CELL_MAX)
0164 goto not_xdr;
0165 datalen -= 4;
0166 paddedlen = (len + 3) & ~3;
0167 if (paddedlen > datalen)
0168 goto not_xdr;
0169
0170 cp = (const char *) xdr;
0171 for (loop = 0; loop < len; loop++)
0172 if (!isprint(cp[loop]))
0173 goto not_xdr;
0174 for (; loop < paddedlen; loop++)
0175 if (cp[loop])
0176 goto not_xdr;
0177 _debug("cellname: [%u/%u] '%*.*s'",
0178 len, paddedlen, len, len, (const char *) xdr);
0179 datalen -= paddedlen;
0180 xdr += paddedlen >> 2;
0181
0182
0183 if (datalen < 12)
0184 goto not_xdr;
0185 ntoken = ntohl(*xdr++);
0186 datalen -= 4;
0187 _debug("ntoken: %x", ntoken);
0188 if (ntoken < 1 || ntoken > AFSTOKEN_MAX)
0189 goto not_xdr;
0190
0191
0192 p = xdr;
0193 loop = ntoken;
0194 do {
0195 if (datalen < 8)
0196 goto not_xdr;
0197 toklen = ntohl(*p++);
0198 sec_ix = ntohl(*p);
0199 datalen -= 4;
0200 _debug("token: [%x/%zx] %x", toklen, datalen, sec_ix);
0201 paddedlen = (toklen + 3) & ~3;
0202 if (toklen < 20 || toklen > datalen || paddedlen > datalen)
0203 goto not_xdr;
0204 datalen -= paddedlen;
0205 p += paddedlen >> 2;
0206
0207 } while (--loop > 0);
0208
0209 _debug("remainder: %zu", datalen);
0210 if (datalen != 0)
0211 goto not_xdr;
0212
0213
0214
0215
0216 ret = -EPROTONOSUPPORT;
0217 do {
0218 toklen = ntohl(*xdr++);
0219 token = xdr;
0220 xdr += (toklen + 3) / 4;
0221
0222 sec_ix = ntohl(*token++);
0223 toklen -= 4;
0224
0225 _debug("TOKEN type=%x len=%x", sec_ix, toklen);
0226
0227 switch (sec_ix) {
0228 case RXRPC_SECURITY_RXKAD:
0229 ret2 = rxrpc_preparse_xdr_rxkad(prep, datalen, token, toklen);
0230 break;
0231 default:
0232 ret2 = -EPROTONOSUPPORT;
0233 break;
0234 }
0235
0236 switch (ret2) {
0237 case 0:
0238 ret = 0;
0239 break;
0240 case -EPROTONOSUPPORT:
0241 break;
0242 case -ENOPKG:
0243 if (ret != 0)
0244 ret = -ENOPKG;
0245 break;
0246 default:
0247 ret = ret2;
0248 goto error;
0249 }
0250
0251 } while (--ntoken > 0);
0252
0253 error:
0254 _leave(" = %d", ret);
0255 return ret;
0256
0257 not_xdr:
0258 _leave(" = -EPROTO");
0259 return -EPROTO;
0260 }
0261
0262
0263
0264
0265
0266
0267
0268
0269
0270
0271
0272
0273
0274
0275
0276
0277 static int rxrpc_preparse(struct key_preparsed_payload *prep)
0278 {
0279 const struct rxrpc_key_data_v1 *v1;
0280 struct rxrpc_key_token *token, **pp;
0281 time64_t expiry;
0282 size_t plen;
0283 u32 kver;
0284 int ret;
0285
0286 _enter("%zu", prep->datalen);
0287
0288
0289 if (!prep->data && prep->datalen == 0)
0290 return 0;
0291
0292
0293 if (prep->datalen > 7 * 4) {
0294 ret = rxrpc_preparse_xdr(prep);
0295 if (ret != -EPROTO)
0296 return ret;
0297 }
0298
0299
0300 ret = -EINVAL;
0301 if (prep->datalen <= 4 || !prep->data)
0302 goto error;
0303 memcpy(&kver, prep->data, sizeof(kver));
0304 prep->data += sizeof(kver);
0305 prep->datalen -= sizeof(kver);
0306
0307 _debug("KEY I/F VERSION: %u", kver);
0308
0309 ret = -EKEYREJECTED;
0310 if (kver != 1)
0311 goto error;
0312
0313
0314 ret = -EINVAL;
0315 if (prep->datalen < sizeof(*v1))
0316 goto error;
0317
0318 v1 = prep->data;
0319 if (prep->datalen != sizeof(*v1) + v1->ticket_length)
0320 goto error;
0321
0322 _debug("SCIX: %u", v1->security_index);
0323 _debug("TLEN: %u", v1->ticket_length);
0324 _debug("EXPY: %x", v1->expiry);
0325 _debug("KVNO: %u", v1->kvno);
0326 _debug("SKEY: %02x%02x%02x%02x%02x%02x%02x%02x",
0327 v1->session_key[0], v1->session_key[1],
0328 v1->session_key[2], v1->session_key[3],
0329 v1->session_key[4], v1->session_key[5],
0330 v1->session_key[6], v1->session_key[7]);
0331 if (v1->ticket_length >= 8)
0332 _debug("TCKT: %02x%02x%02x%02x%02x%02x%02x%02x",
0333 v1->ticket[0], v1->ticket[1],
0334 v1->ticket[2], v1->ticket[3],
0335 v1->ticket[4], v1->ticket[5],
0336 v1->ticket[6], v1->ticket[7]);
0337
0338 ret = -EPROTONOSUPPORT;
0339 if (v1->security_index != RXRPC_SECURITY_RXKAD)
0340 goto error;
0341
0342 plen = sizeof(*token->kad) + v1->ticket_length;
0343 prep->quotalen = plen + sizeof(*token);
0344
0345 ret = -ENOMEM;
0346 token = kzalloc(sizeof(*token), GFP_KERNEL);
0347 if (!token)
0348 goto error;
0349 token->kad = kzalloc(plen, GFP_KERNEL);
0350 if (!token->kad)
0351 goto error_free;
0352
0353 token->security_index = RXRPC_SECURITY_RXKAD;
0354 token->kad->ticket_len = v1->ticket_length;
0355 token->kad->expiry = v1->expiry;
0356 token->kad->kvno = v1->kvno;
0357 memcpy(&token->kad->session_key, &v1->session_key, 8);
0358 memcpy(&token->kad->ticket, v1->ticket, v1->ticket_length);
0359
0360
0361 prep->payload.data[1] = (void *)((unsigned long)prep->payload.data[1] + 1);
0362
0363
0364 pp = (struct rxrpc_key_token **)&prep->payload.data[0];
0365 while (*pp)
0366 pp = &(*pp)->next;
0367 *pp = token;
0368 expiry = rxrpc_u32_to_time64(token->kad->expiry);
0369 if (expiry < prep->expiry)
0370 prep->expiry = expiry;
0371 token = NULL;
0372 ret = 0;
0373
0374 error_free:
0375 kfree(token);
0376 error:
0377 return ret;
0378 }
0379
0380
0381
0382
0383 static void rxrpc_free_token_list(struct rxrpc_key_token *token)
0384 {
0385 struct rxrpc_key_token *next;
0386
0387 for (; token; token = next) {
0388 next = token->next;
0389 switch (token->security_index) {
0390 case RXRPC_SECURITY_RXKAD:
0391 kfree(token->kad);
0392 break;
0393 default:
0394 pr_err("Unknown token type %x on rxrpc key\n",
0395 token->security_index);
0396 BUG();
0397 }
0398
0399 kfree(token);
0400 }
0401 }
0402
0403
0404
0405
0406 static void rxrpc_free_preparse(struct key_preparsed_payload *prep)
0407 {
0408 rxrpc_free_token_list(prep->payload.data[0]);
0409 }
0410
0411
0412
0413
0414 static void rxrpc_destroy(struct key *key)
0415 {
0416 rxrpc_free_token_list(key->payload.data[0]);
0417 }
0418
0419
0420
0421
0422 static void rxrpc_describe(const struct key *key, struct seq_file *m)
0423 {
0424 const struct rxrpc_key_token *token;
0425 const char *sep = ": ";
0426
0427 seq_puts(m, key->description);
0428
0429 for (token = key->payload.data[0]; token; token = token->next) {
0430 seq_puts(m, sep);
0431
0432 switch (token->security_index) {
0433 case RXRPC_SECURITY_RXKAD:
0434 seq_puts(m, "ka");
0435 break;
0436 default:
0437 seq_printf(m, "%u", token->security_index);
0438 break;
0439 }
0440
0441 sep = " ";
0442 }
0443 }
0444
0445
0446
0447
0448 int rxrpc_request_key(struct rxrpc_sock *rx, sockptr_t optval, int optlen)
0449 {
0450 struct key *key;
0451 char *description;
0452
0453 _enter("");
0454
0455 if (optlen <= 0 || optlen > PAGE_SIZE - 1 || rx->securities)
0456 return -EINVAL;
0457
0458 description = memdup_sockptr_nul(optval, optlen);
0459 if (IS_ERR(description))
0460 return PTR_ERR(description);
0461
0462 key = request_key_net(&key_type_rxrpc, description, sock_net(&rx->sk), NULL);
0463 if (IS_ERR(key)) {
0464 kfree(description);
0465 _leave(" = %ld", PTR_ERR(key));
0466 return PTR_ERR(key);
0467 }
0468
0469 rx->key = key;
0470 kfree(description);
0471 _leave(" = 0 [key %x]", key->serial);
0472 return 0;
0473 }
0474
0475
0476
0477
0478 int rxrpc_get_server_data_key(struct rxrpc_connection *conn,
0479 const void *session_key,
0480 time64_t expiry,
0481 u32 kvno)
0482 {
0483 const struct cred *cred = current_cred();
0484 struct key *key;
0485 int ret;
0486
0487 struct {
0488 u32 kver;
0489 struct rxrpc_key_data_v1 v1;
0490 } data;
0491
0492 _enter("");
0493
0494 key = key_alloc(&key_type_rxrpc, "x",
0495 GLOBAL_ROOT_UID, GLOBAL_ROOT_GID, cred, 0,
0496 KEY_ALLOC_NOT_IN_QUOTA, NULL);
0497 if (IS_ERR(key)) {
0498 _leave(" = -ENOMEM [alloc %ld]", PTR_ERR(key));
0499 return -ENOMEM;
0500 }
0501
0502 _debug("key %d", key_serial(key));
0503
0504 data.kver = 1;
0505 data.v1.security_index = RXRPC_SECURITY_RXKAD;
0506 data.v1.ticket_length = 0;
0507 data.v1.expiry = rxrpc_time64_to_u32(expiry);
0508 data.v1.kvno = 0;
0509
0510 memcpy(&data.v1.session_key, session_key, sizeof(data.v1.session_key));
0511
0512 ret = key_instantiate_and_link(key, &data, sizeof(data), NULL, NULL);
0513 if (ret < 0)
0514 goto error;
0515
0516 conn->params.key = key;
0517 _leave(" = 0 [%d]", key_serial(key));
0518 return 0;
0519
0520 error:
0521 key_revoke(key);
0522 key_put(key);
0523 _leave(" = -ENOMEM [ins %d]", ret);
0524 return -ENOMEM;
0525 }
0526 EXPORT_SYMBOL(rxrpc_get_server_data_key);
0527
0528
0529
0530
0531
0532
0533
0534
0535 struct key *rxrpc_get_null_key(const char *keyname)
0536 {
0537 const struct cred *cred = current_cred();
0538 struct key *key;
0539 int ret;
0540
0541 key = key_alloc(&key_type_rxrpc, keyname,
0542 GLOBAL_ROOT_UID, GLOBAL_ROOT_GID, cred,
0543 KEY_POS_SEARCH, KEY_ALLOC_NOT_IN_QUOTA, NULL);
0544 if (IS_ERR(key))
0545 return key;
0546
0547 ret = key_instantiate_and_link(key, NULL, 0, NULL, NULL);
0548 if (ret < 0) {
0549 key_revoke(key);
0550 key_put(key);
0551 return ERR_PTR(ret);
0552 }
0553
0554 return key;
0555 }
0556 EXPORT_SYMBOL(rxrpc_get_null_key);
0557
0558
0559
0560
0561
0562 static long rxrpc_read(const struct key *key,
0563 char *buffer, size_t buflen)
0564 {
0565 const struct rxrpc_key_token *token;
0566 size_t size;
0567 __be32 *xdr, *oldxdr;
0568 u32 cnlen, toksize, ntoks, tok, zero;
0569 u16 toksizes[AFSTOKEN_MAX];
0570
0571 _enter("");
0572
0573
0574 if (memcmp(key->description, "afs@", 4) != 0)
0575 return -EOPNOTSUPP;
0576 cnlen = strlen(key->description + 4);
0577
0578 #define RND(X) (((X) + 3) & ~3)
0579
0580
0581
0582 size = 2 * 4;
0583 size += RND(cnlen);
0584 size += 1 * 4;
0585
0586 ntoks = 0;
0587 for (token = key->payload.data[0]; token; token = token->next) {
0588 toksize = 4;
0589
0590 switch (token->security_index) {
0591 case RXRPC_SECURITY_RXKAD:
0592 toksize += 8 * 4;
0593
0594 if (!token->no_leak_key)
0595 toksize += RND(token->kad->ticket_len);
0596 break;
0597
0598 default:
0599 pr_err("Unsupported key token type (%u)\n",
0600 token->security_index);
0601 return -ENOPKG;
0602 }
0603
0604 _debug("token[%u]: toksize=%u", ntoks, toksize);
0605 ASSERTCMP(toksize, <=, AFSTOKEN_LENGTH_MAX);
0606
0607 toksizes[ntoks++] = toksize;
0608 size += toksize + 4;
0609 }
0610
0611 #undef RND
0612
0613 if (!buffer || buflen < size)
0614 return size;
0615
0616 xdr = (__be32 *)buffer;
0617 zero = 0;
0618 #define ENCODE(x) \
0619 do { \
0620 *xdr++ = htonl(x); \
0621 } while(0)
0622 #define ENCODE_DATA(l, s) \
0623 do { \
0624 u32 _l = (l); \
0625 ENCODE(l); \
0626 memcpy(xdr, (s), _l); \
0627 if (_l & 3) \
0628 memcpy((u8 *)xdr + _l, &zero, 4 - (_l & 3)); \
0629 xdr += (_l + 3) >> 2; \
0630 } while(0)
0631 #define ENCODE_BYTES(l, s) \
0632 do { \
0633 u32 _l = (l); \
0634 memcpy(xdr, (s), _l); \
0635 if (_l & 3) \
0636 memcpy((u8 *)xdr + _l, &zero, 4 - (_l & 3)); \
0637 xdr += (_l + 3) >> 2; \
0638 } while(0)
0639 #define ENCODE64(x) \
0640 do { \
0641 __be64 y = cpu_to_be64(x); \
0642 memcpy(xdr, &y, 8); \
0643 xdr += 8 >> 2; \
0644 } while(0)
0645 #define ENCODE_STR(s) \
0646 do { \
0647 const char *_s = (s); \
0648 ENCODE_DATA(strlen(_s), _s); \
0649 } while(0)
0650
0651 ENCODE(0);
0652 ENCODE_DATA(cnlen, key->description + 4);
0653 ENCODE(ntoks);
0654
0655 tok = 0;
0656 for (token = key->payload.data[0]; token; token = token->next) {
0657 toksize = toksizes[tok++];
0658 ENCODE(toksize);
0659 oldxdr = xdr;
0660 ENCODE(token->security_index);
0661
0662 switch (token->security_index) {
0663 case RXRPC_SECURITY_RXKAD:
0664 ENCODE(token->kad->vice_id);
0665 ENCODE(token->kad->kvno);
0666 ENCODE_BYTES(8, token->kad->session_key);
0667 ENCODE(token->kad->start);
0668 ENCODE(token->kad->expiry);
0669 ENCODE(token->kad->primary_flag);
0670 if (token->no_leak_key)
0671 ENCODE(0);
0672 else
0673 ENCODE_DATA(token->kad->ticket_len, token->kad->ticket);
0674 break;
0675
0676 default:
0677 pr_err("Unsupported key token type (%u)\n",
0678 token->security_index);
0679 return -ENOPKG;
0680 }
0681
0682 ASSERTCMP((unsigned long)xdr - (unsigned long)oldxdr, ==,
0683 toksize);
0684 }
0685
0686 #undef ENCODE_STR
0687 #undef ENCODE_DATA
0688 #undef ENCODE64
0689 #undef ENCODE
0690
0691 ASSERTCMP(tok, ==, ntoks);
0692 ASSERTCMP((char __user *) xdr - buffer, ==, size);
0693 _leave(" = %zu", size);
0694 return size;
0695 }