/* vim: set expandtab ts=4 sw=4: */ /* * You may redistribute this program and/or modify it under the terms of * the GNU General Public License as published by the Free Software Foundation, * either version 3 of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef CryptoAuth_H #define CryptoAuth_H #include "benc/Object.h" #include "crypto/random/Random.h" #include "interface/Interface.h" #include "memory/Allocator.h" #include "util/Endian.h" #include "util/log/Log.h" #include "util/events/EventBase.h" #include "util/Linker.h" Linker_require("crypto/CryptoAuth.c") #include #include #define CryptoAuth_DEFAULT_RESET_AFTER_INACTIVITY_SECONDS 60 struct CryptoAuth { uint8_t publicKey[32]; /** * After this number of seconds of inactivity, * a connection will be reset to prevent them hanging in a bad state. */ uint32_t resetAfterInactivitySeconds; }; /** The internal interface wrapper struct. */ struct CryptoAuth_Wrapper; /** * Associate a password:authtype pair with a user object. * Calling CryptoAuth_getUser() on any interface which has established a connection with * the same password:authType pair will return the same user object. * * @param password This should be a key derived from the password using a good key derivation * function, using a plaintext password here is NOT recommended. * @param authType The method of authenticating the user, only option currently is 1 for sha256 * based authentication. * @param user The thing to associate with this user, will be returned by CryptoAuth_getUser(). * If this is NULL and requireAuthentication is enabled, authentication will fail. * Duplicate user entires are OK. * @param context The CryptoAuth context. * @return 0 if all goes well, * CryptoAuth_addUser_INVALID_AUTHTYPE if the authentication method is not supported, * CryptoAuth_addUser_OUT_OF_SPACE if there is not enough space to store the entry, * CryptoAuth_addUser_DUPLICATE if the same *password* already exists. */ #define CryptoAuth_addUser_INVALID_AUTHTYPE -1 #define CryptoAuth_addUser_OUT_OF_SPACE -2 #define CryptoAuth_addUser_DUPLICATE -3 int32_t CryptoAuth_addUser(String* password, uint8_t authType, String* user, struct CryptoAuth* context); /** * Remove all users registered with this CryptoAuth. * * @param context the context to remove users for. * @param user the identifier which was passed to addUser(), all users with this id will be removed. * @return the number of users removed. */ int CryptoAuth_removeUsers(struct CryptoAuth* context, String* user); /** * Get a list of all the users added via addUser. * * @param context the context used to call addUser. * @param alloc the Allocator to use to create the usersOut array. * @returns List* containing the user String's */ List* CryptoAuth_getUsers(struct CryptoAuth* context, struct Allocator* alloc); /** * Get the user object associated with the authenticated session or NULL if there is none. * Please make sure to only call this on interfaces which were actually returned by * CryptoAuth_wrapInterface() as strange and interesting bugs will result otherwise. * * @param interface an interface as returned by CryptoAuth_wrapInterface(). * @return the user object added by calling CryptoAuth_addUser() or NULL if this session is not * authenticated. */ String* CryptoAuth_getUser(struct Interface* iface); /** * Create a new crypto authenticator. * * @param allocator the means of aquiring memory. * @param privateKey the private key to use for this CryptoAuth or null if one should be generated. * @param eventBase the libevent context for handling timeouts. * @param logger the mechanism for logging output from the CryptoAuth. * if NULL then no logging will be done. * @param rand random number generator. * @return a new CryptoAuth context. */ struct CryptoAuth* CryptoAuth_new(struct Allocator* allocator, const uint8_t* privateKey, struct EventBase* eventBase, struct Log* logger, struct Random* rand); /** * Wrap an interface with crypto authentication. * * NOTE: Sending empty packets during the handshake is not allowed! * Empty packets are used for signaling during the handshake so they can * only be used while the session is in state ESTABLISHED. * * @param toWarp the interface to wrap * @param herPublicKey the public key of the other party or NULL if unknown. * @param herIp6 the ipv6 address of the other party * @param requireAuth if the remote end of this interface begins the connection, require * them to present valid authentication credentials to connect. * If this end begins the connection, this parameter has no effect. * @param name a name for this CA which will appear in logs. * @param context the CryptoAuth context. */ struct Interface* CryptoAuth_wrapInterface(struct Interface* toWrap, const uint8_t herPublicKey[32], const uint8_t herIp6[16], const bool requireAuth, char* name, struct CryptoAuth* ca); /** * Choose the authentication credentials to use. * WARNING: Even if the remote end begins the connection, these credentials will be presented which * will cause the connection initiation to fail if the remote end does not know of them. * * @param password the password to use for authenticating, this must match the password given to * CryptoAuth_addUser() at the other end of the connection. * @param authType this must match CryptoAuth_addUser() at the other end of the connection. * @param wrappedInterface this MUST be the output from CryptoAuth_wrapInterface(). */ void CryptoAuth_setAuth(const String* password, const uint8_t authType, struct Interface* wrappedInterface); /** @return a pointer to the other party's public key. */ uint8_t* CryptoAuth_getHerPublicKey(struct Interface* iface); /** Reset the session's state to CryptoAuth_NEW, a new connection will be negotiated. */ void CryptoAuth_reset(struct Interface* iface); /** New CryptoAuth session, has not sent or received anything. */ #define CryptoAuth_NEW 0 /** Sent a hello message, waiting for reply. */ #define CryptoAuth_HANDSHAKE1 1 /** Received a hello message, sent a key message, waiting for the session to complete. */ #define CryptoAuth_HANDSHAKE2 2 /** Sent a hello message and received a key message but have not gotten a data message yet. */ #define CryptoAuth_HANDSHAKE3 3 /** The CryptoAuth session has successfully done a handshake and received at least one message. */ #define CryptoAuth_ESTABLISHED 4 static inline char* CryptoAuth_stateString(int state) { switch (state) { case CryptoAuth_NEW: return "CryptoAuth_NEW"; case CryptoAuth_HANDSHAKE1: return "CryptoAuth_HANDSHAKE1"; case CryptoAuth_HANDSHAKE2: return "CryptoAuth_HANDSHAKE2"; case CryptoAuth_HANDSHAKE3: return "CryptoAuth_HANDSHAKE3"; case CryptoAuth_ESTABLISHED: return "CryptoAuth_ESTABLISHED"; default: return "INVALID"; } } /** * Get the state of the CryptoAuth session. * * @param interface a CryptoAuth wrapper. * @return one of CryptoAuth_NEW, * CryptoAuth_HANDSHAKE1, * CryptoAuth_HANDSHAKE2 or * CryptoAuth_ESTABLISHED */ int CryptoAuth_getState(struct Interface* iface); /** * Get the interface on the other side of this CryptoAuth session. * * Given a wrapped interface, get the wrapping interface. * given a wrapping interface, get the one which is wrapped. * * @param iface the wrapped or wrapper iface. * @return the opposite. */ struct Interface* CryptoAuth_getConnectedInterface(struct Interface* iface); /** * Get the structure which is used to protect against packet replay attacks. */ struct ReplayProtector* CryptoAuth_getReplayProtector(struct Interface* iface); #endif