security.c 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158
  1. // SPDX-License-Identifier: GPL-2.0-or-later
  2. /* RxRPC security handling
  3. *
  4. * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
  5. * Written by David Howells (dhowells@redhat.com)
  6. */
  7. #include <linux/module.h>
  8. #include <linux/net.h>
  9. #include <linux/skbuff.h>
  10. #include <linux/udp.h>
  11. #include <linux/crypto.h>
  12. #include <net/sock.h>
  13. #include <net/af_rxrpc.h>
  14. #include <keys/rxrpc-type.h>
  15. #include "ar-internal.h"
  16. static const struct rxrpc_security *rxrpc_security_types[] = {
  17. [RXRPC_SECURITY_NONE] = &rxrpc_no_security,
  18. #ifdef CONFIG_RXKAD
  19. [RXRPC_SECURITY_RXKAD] = &rxkad,
  20. #endif
  21. };
  22. int __init rxrpc_init_security(void)
  23. {
  24. int i, ret;
  25. for (i = 0; i < ARRAY_SIZE(rxrpc_security_types); i++) {
  26. if (rxrpc_security_types[i]) {
  27. ret = rxrpc_security_types[i]->init();
  28. if (ret < 0)
  29. goto failed;
  30. }
  31. }
  32. return 0;
  33. failed:
  34. for (i--; i >= 0; i--)
  35. if (rxrpc_security_types[i])
  36. rxrpc_security_types[i]->exit();
  37. return ret;
  38. }
  39. void rxrpc_exit_security(void)
  40. {
  41. int i;
  42. for (i = 0; i < ARRAY_SIZE(rxrpc_security_types); i++)
  43. if (rxrpc_security_types[i])
  44. rxrpc_security_types[i]->exit();
  45. }
  46. /*
  47. * look up an rxrpc security module
  48. */
  49. static const struct rxrpc_security *rxrpc_security_lookup(u8 security_index)
  50. {
  51. if (security_index >= ARRAY_SIZE(rxrpc_security_types))
  52. return NULL;
  53. return rxrpc_security_types[security_index];
  54. }
  55. /*
  56. * initialise the security on a client connection
  57. */
  58. int rxrpc_init_client_conn_security(struct rxrpc_connection *conn)
  59. {
  60. const struct rxrpc_security *sec;
  61. struct rxrpc_key_token *token;
  62. struct key *key = conn->params.key;
  63. int ret;
  64. _enter("{%d},{%x}", conn->debug_id, key_serial(key));
  65. if (!key)
  66. return 0;
  67. ret = key_validate(key);
  68. if (ret < 0)
  69. return ret;
  70. token = key->payload.data[0];
  71. if (!token)
  72. return -EKEYREJECTED;
  73. sec = rxrpc_security_lookup(token->security_index);
  74. if (!sec)
  75. return -EKEYREJECTED;
  76. conn->security = sec;
  77. ret = conn->security->init_connection_security(conn);
  78. if (ret < 0) {
  79. conn->security = &rxrpc_no_security;
  80. return ret;
  81. }
  82. _leave(" = 0");
  83. return 0;
  84. }
  85. /*
  86. * Find the security key for a server connection.
  87. */
  88. bool rxrpc_look_up_server_security(struct rxrpc_local *local, struct rxrpc_sock *rx,
  89. const struct rxrpc_security **_sec,
  90. struct key **_key,
  91. struct sk_buff *skb)
  92. {
  93. const struct rxrpc_security *sec;
  94. struct rxrpc_skb_priv *sp = rxrpc_skb(skb);
  95. key_ref_t kref = NULL;
  96. char kdesc[5 + 1 + 3 + 1];
  97. _enter("");
  98. sprintf(kdesc, "%u:%u", sp->hdr.serviceId, sp->hdr.securityIndex);
  99. sec = rxrpc_security_lookup(sp->hdr.securityIndex);
  100. if (!sec) {
  101. trace_rxrpc_abort(0, "SVS",
  102. sp->hdr.cid, sp->hdr.callNumber, sp->hdr.seq,
  103. RX_INVALID_OPERATION, EKEYREJECTED);
  104. skb->mark = RXRPC_SKB_MARK_REJECT_ABORT;
  105. skb->priority = RX_INVALID_OPERATION;
  106. return false;
  107. }
  108. if (sp->hdr.securityIndex == RXRPC_SECURITY_NONE)
  109. goto out;
  110. if (!rx->securities) {
  111. trace_rxrpc_abort(0, "SVR",
  112. sp->hdr.cid, sp->hdr.callNumber, sp->hdr.seq,
  113. RX_INVALID_OPERATION, EKEYREJECTED);
  114. skb->mark = RXRPC_SKB_MARK_REJECT_ABORT;
  115. skb->priority = RX_INVALID_OPERATION;
  116. return false;
  117. }
  118. /* look through the service's keyring */
  119. kref = keyring_search(make_key_ref(rx->securities, 1UL),
  120. &key_type_rxrpc_s, kdesc, true);
  121. if (IS_ERR(kref)) {
  122. trace_rxrpc_abort(0, "SVK",
  123. sp->hdr.cid, sp->hdr.callNumber, sp->hdr.seq,
  124. sec->no_key_abort, EKEYREJECTED);
  125. skb->mark = RXRPC_SKB_MARK_REJECT_ABORT;
  126. skb->priority = sec->no_key_abort;
  127. return false;
  128. }
  129. out:
  130. *_sec = sec;
  131. *_key = key_ref_to_ptr(kref);
  132. return true;
  133. }