security.c 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169
  1. /* RxRPC security handling
  2. *
  3. * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
  4. * Written by David Howells (dhowells@redhat.com)
  5. *
  6. * This program is free software; you can redistribute it and/or
  7. * modify it under the terms of the GNU General Public License
  8. * as published by the Free Software Foundation; either version
  9. * 2 of the License, or (at your option) any later version.
  10. */
  11. #include <linux/module.h>
  12. #include <linux/net.h>
  13. #include <linux/skbuff.h>
  14. #include <linux/udp.h>
  15. #include <linux/crypto.h>
  16. #include <net/sock.h>
  17. #include <net/af_rxrpc.h>
  18. #include <keys/rxrpc-type.h>
  19. #include "ar-internal.h"
  20. static LIST_HEAD(rxrpc_security_methods);
  21. static DECLARE_RWSEM(rxrpc_security_sem);
  22. static const struct rxrpc_security *rxrpc_security_types[] = {
  23. [RXRPC_SECURITY_NONE] = &rxrpc_no_security,
  24. #ifdef CONFIG_RXKAD
  25. [RXRPC_SECURITY_RXKAD] = &rxkad,
  26. #endif
  27. };
  28. int __init rxrpc_init_security(void)
  29. {
  30. int i, ret;
  31. for (i = 0; i < ARRAY_SIZE(rxrpc_security_types); i++) {
  32. if (rxrpc_security_types[i]) {
  33. ret = rxrpc_security_types[i]->init();
  34. if (ret < 0)
  35. goto failed;
  36. }
  37. }
  38. return 0;
  39. failed:
  40. for (i--; i >= 0; i--)
  41. if (rxrpc_security_types[i])
  42. rxrpc_security_types[i]->exit();
  43. return ret;
  44. }
  45. void rxrpc_exit_security(void)
  46. {
  47. int i;
  48. for (i = 0; i < ARRAY_SIZE(rxrpc_security_types); i++)
  49. if (rxrpc_security_types[i])
  50. rxrpc_security_types[i]->exit();
  51. }
  52. /*
  53. * look up an rxrpc security module
  54. */
  55. static const struct rxrpc_security *rxrpc_security_lookup(u8 security_index)
  56. {
  57. if (security_index >= ARRAY_SIZE(rxrpc_security_types))
  58. return NULL;
  59. return rxrpc_security_types[security_index];
  60. }
  61. /*
  62. * initialise the security on a client connection
  63. */
  64. int rxrpc_init_client_conn_security(struct rxrpc_connection *conn)
  65. {
  66. const struct rxrpc_security *sec;
  67. struct rxrpc_key_token *token;
  68. struct key *key = conn->params.key;
  69. int ret;
  70. _enter("{%d},{%x}", conn->debug_id, key_serial(key));
  71. if (!key)
  72. return 0;
  73. ret = key_validate(key);
  74. if (ret < 0)
  75. return ret;
  76. token = key->payload.data[0];
  77. if (!token)
  78. return -EKEYREJECTED;
  79. sec = rxrpc_security_lookup(token->security_index);
  80. if (!sec)
  81. return -EKEYREJECTED;
  82. conn->security = sec;
  83. ret = conn->security->init_connection_security(conn);
  84. if (ret < 0) {
  85. conn->security = &rxrpc_no_security;
  86. return ret;
  87. }
  88. _leave(" = 0");
  89. return 0;
  90. }
  91. /*
  92. * initialise the security on a server connection
  93. */
  94. int rxrpc_init_server_conn_security(struct rxrpc_connection *conn)
  95. {
  96. const struct rxrpc_security *sec;
  97. struct rxrpc_local *local = conn->params.local;
  98. struct rxrpc_sock *rx;
  99. struct key *key;
  100. key_ref_t kref;
  101. char kdesc[5 + 1 + 3 + 1];
  102. _enter("");
  103. sprintf(kdesc, "%u:%u", conn->params.service_id, conn->security_ix);
  104. sec = rxrpc_security_lookup(conn->security_ix);
  105. if (!sec) {
  106. _leave(" = -ENOKEY [lookup]");
  107. return -ENOKEY;
  108. }
  109. /* find the service */
  110. read_lock(&local->services_lock);
  111. rx = rcu_dereference_protected(local->service,
  112. lockdep_is_held(&local->services_lock));
  113. if (rx && rx->srx.srx_service == conn->params.service_id)
  114. goto found_service;
  115. /* the service appears to have died */
  116. read_unlock(&local->services_lock);
  117. _leave(" = -ENOENT");
  118. return -ENOENT;
  119. found_service:
  120. if (!rx->securities) {
  121. read_unlock(&local->services_lock);
  122. _leave(" = -ENOKEY");
  123. return -ENOKEY;
  124. }
  125. /* look through the service's keyring */
  126. kref = keyring_search(make_key_ref(rx->securities, 1UL),
  127. &key_type_rxrpc_s, kdesc);
  128. if (IS_ERR(kref)) {
  129. read_unlock(&local->services_lock);
  130. _leave(" = %ld [search]", PTR_ERR(kref));
  131. return PTR_ERR(kref);
  132. }
  133. key = key_ref_to_ptr(kref);
  134. read_unlock(&local->services_lock);
  135. conn->server_key = key;
  136. conn->security = sec;
  137. _leave(" = 0");
  138. return 0;
  139. }