TwoWayAuthentication.h 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154
  1. /*
  2. * Copyright (c) 2014, Oculus VR, Inc.
  3. * All rights reserved.
  4. *
  5. * This source code is licensed under the BSD-style license found in the
  6. * LICENSE file in the root directory of this source tree. An additional grant
  7. * of patent rights can be found in the PATENTS file in the same directory.
  8. *
  9. */
  10. /// \file TwoWayAuthentication.h
  11. /// \brief Implements two way authentication
  12. /// \details Given two systems, each of whom known a common password, verify the password without transmitting it
  13. /// This can be used to determine what permissions are should be allowed to the other system
  14. ///
  15. #include "NativeFeatureIncludes.h"
  16. #if _RAKNET_SUPPORT_TwoWayAuthentication==1
  17. #ifndef __TWO_WAY_AUTHENTICATION_H
  18. #define __TWO_WAY_AUTHENTICATION_H
  19. // How often to change the nonce.
  20. #define NONCE_TIMEOUT_MS 10000
  21. // How often to check for ID_TWO_WAY_AUTHENTICATION_OUTGOING_CHALLENGE_TIMEOUT, and the minimum timeout time. Maximum is double this value.
  22. #define CHALLENGE_MINIMUM_TIMEOUT 3000
  23. #if LIBCAT_SECURITY==1
  24. // From CPP FILE:
  25. // static const int HASH_BITS = 256;
  26. // static const int HASH_BYTES = HASH_BITS / 8;
  27. // static const int STRENGTHENING_FACTOR = 1000;
  28. #define TWO_WAY_AUTHENTICATION_NONCE_LENGTH 32
  29. #define HASHED_NONCE_AND_PW_LENGTH 32
  30. #else
  31. #include "DR_SHA1.h"
  32. #define TWO_WAY_AUTHENTICATION_NONCE_LENGTH 20
  33. #define HASHED_NONCE_AND_PW_LENGTH SHA1_LENGTH
  34. #endif
  35. #include "PluginInterface2.h"
  36. #include "RakMemoryOverride.h"
  37. #include "NativeTypes.h"
  38. #include "RakString.h"
  39. #include "DS_Hash.h"
  40. #include "DS_Queue.h"
  41. typedef int64_t FCM2Guid;
  42. namespace RakNet
  43. {
  44. /// Forward declarations
  45. class RakPeerInterface;
  46. /// \brief Implements two way authentication
  47. /// \details Given two systems, each of whom known a common password / identifier pair, verify the password without transmitting it
  48. /// This can be used to determine what permissions are should be allowed to the other system
  49. /// If the other system should not send any data until authentication passes, you can use the MessageFilter plugin for this. Call MessageFilter::SetAllowMessageID() including ID_TWO_WAY_AUTHENTICATION_NEGOTIATION when doing so. Also attach MessageFilter first in the list of plugins
  50. /// \note If other systems challenges us, and fails, you will get ID_TWO_WAY_AUTHENTICATION_INCOMING_CHALLENGE_FAILED.
  51. /// \ingroup PLUGINS_GROUP
  52. class RAK_DLL_EXPORT TwoWayAuthentication : public PluginInterface2
  53. {
  54. public:
  55. // GetInstance() and DestroyInstance(instance*)
  56. STATIC_FACTORY_DECLARATIONS(TwoWayAuthentication)
  57. TwoWayAuthentication();
  58. virtual ~TwoWayAuthentication();
  59. /// \brief Adds a password to the list of passwords the system will accept
  60. /// \details Each password, which is secret and not transmitted, is identified by \a identifier.
  61. /// \a identifier is transmitted in plaintext with the request. It is only needed because the system supports multiple password.
  62. /// It is used to only hash against once password on the remote system, rather than having to hash against every known password.
  63. /// \param[in] identifier A unique identifier representing this password. This is transmitted in plaintext and should be considered insecure
  64. /// \param[in] password The password to add
  65. /// \return True on success, false on identifier==password, either identifier or password is blank, or identifier is already in use
  66. bool AddPassword(RakNet::RakString identifier, RakNet::RakString password);
  67. /// \brief Challenge another system for the specified identifier
  68. /// \details After calling Challenge, you will get back ID_TWO_WAY_AUTHENTICATION_SUCCESS, ID_TWO_WAY_AUTHENTICATION_OUTGOING_CHALLENGE_TIMEOUT, or ID_TWO_WAY_AUTHENTICATION_OUTGOING_CHALLENGE_FAILED
  69. /// ID_TWO_WAY_AUTHENTICATION_SUCCESS will be returned if and only if the other system has called AddPassword() with the same identifier\password pair as this system.
  70. /// \param[in] identifier A unique identifier representing this password. This is transmitted in plaintext and should be considered insecure
  71. /// \return True on success, false on remote system not connected, or identifier not previously added with AddPassword()
  72. bool Challenge(RakNet::RakString identifier, AddressOrGUID remoteSystem);
  73. /// \brief Free all memory
  74. void Clear(void);
  75. /// \internal
  76. virtual void Update(void);
  77. /// \internal
  78. virtual PluginReceiveResult OnReceive(Packet *packet);
  79. /// \internal
  80. virtual void OnRakPeerShutdown(void);
  81. /// \internal
  82. virtual void OnClosedConnection(const SystemAddress &systemAddress, RakNetGUID rakNetGUID, PI2_LostConnectionReason lostConnectionReason );
  83. /// \internal
  84. struct PendingChallenge
  85. {
  86. RakNet::RakString identifier;
  87. AddressOrGUID remoteSystem;
  88. RakNet::Time time;
  89. bool sentHash;
  90. };
  91. DataStructures::Queue<PendingChallenge> outgoingChallenges;
  92. /// \internal
  93. struct NonceAndRemoteSystemRequest
  94. {
  95. char nonce[TWO_WAY_AUTHENTICATION_NONCE_LENGTH];
  96. RakNet::AddressOrGUID remoteSystem;
  97. unsigned short requestId;
  98. RakNet::Time whenGenerated;
  99. };
  100. /// \internal
  101. struct RAK_DLL_EXPORT NonceGenerator
  102. {
  103. NonceGenerator();
  104. ~NonceGenerator();
  105. void GetNonce(char nonce[TWO_WAY_AUTHENTICATION_NONCE_LENGTH], unsigned short *requestId, RakNet::AddressOrGUID remoteSystem);
  106. void GenerateNonce(char nonce[TWO_WAY_AUTHENTICATION_NONCE_LENGTH]);
  107. bool GetNonceById(char nonce[TWO_WAY_AUTHENTICATION_NONCE_LENGTH], unsigned short requestId, RakNet::AddressOrGUID remoteSystem, bool popIfFound);
  108. void Clear(void);
  109. void ClearByAddress(RakNet::AddressOrGUID remoteSystem);
  110. void Update(RakNet::Time curTime);
  111. DataStructures::List<TwoWayAuthentication::NonceAndRemoteSystemRequest*> generatedNonces;
  112. unsigned short nextRequestId;
  113. };
  114. protected:
  115. void PushToUser(MessageID messageId, RakNet::RakString password, RakNet::AddressOrGUID remoteSystem);
  116. // Key is identifier, data is password
  117. DataStructures::Hash<RakNet::RakString, RakNet::RakString, 16, RakNet::RakString::ToInteger > passwords;
  118. RakNet::Time whenLastTimeoutCheck;
  119. NonceGenerator nonceGenerator;
  120. void OnNonceRequest(Packet *packet);
  121. void OnNonceReply(Packet *packet);
  122. PluginReceiveResult OnHashedNonceAndPassword(Packet *packet);
  123. void OnPasswordResult(Packet *packet);
  124. void Hash(char thierNonce[TWO_WAY_AUTHENTICATION_NONCE_LENGTH], RakNet::RakString password, char out[HASHED_NONCE_AND_PW_LENGTH]);
  125. };
  126. } // namespace RakNet
  127. #endif
  128. #endif // _RAKNET_SUPPORT_*
粤ICP备19079148号