/*! * @file remote.c * @brief Definitions of functions and types that interact with a remote endpoint. */ #include "common.h" /*! * @brief Instantiate a remote context from a file descriptor. * @details This function takes a file descriptor and wraps it in \c Remote * context which makes it easier to interact with the endpoint. * @returns Pointer to the created \c Remote instance. * @retval NULL Indicates a memory allocation failure or a lock creation failure. * @retval Non-NULL Successful creation of the context. */ Remote* remote_allocate() { Remote* remote = (Remote*)malloc(sizeof(Remote)); LOCK* lock = lock_create(); do { if (remote == NULL || lock == NULL) { break; } memset(remote, 0, sizeof(Remote)); remote->lock = lock; dprintf("[REMOTE] remote created %p", remote); return remote; } while (0); if (lock) { lock_destroy(lock); } if (remote) { free(remote); } vdprintf("[REMOTE] here 3"); return NULL; } /*! * @brief Deallocate a remote context. * @param remote Pointer to the \c Remote instance to deallocate. */ VOID remote_deallocate(Remote * remote) { if (remote->lock) { lock_destroy(remote->lock); } // Wipe our structure from memory memset(remote, 0, sizeof(Remote)); free(remote); } /*! * @brief Initializes a given cipher as instructed by the remote endpoint. * @param remote Pointer to the \c Remote instance. * @param cipher Name of the cipher to use. * @param initializer Pointer to the received \c Packet instance. * @returns Indication of success or failure. * @retval ERROR_SUCCESS The cipher was set correctly. * @retval ERROR_NOT_ENOUGH_MEMORY Memory allocation failed. * @retval ERROR_NOT_FOUND An invalid value was specified for \c cipher. */ DWORD remote_set_cipher(Remote *remote, LPCSTR cipher, Packet *initializer) { DWORD res = ERROR_SUCCESS; if (remote->crypto) free(remote->crypto); do { // Allocate storage for the crypto context if (!(remote->crypto = (CryptoContext *)malloc(sizeof(CryptoContext)))) { res = ERROR_NOT_ENOUGH_MEMORY; break; } memset(remote->crypto, 0, sizeof(CryptoContext)); // Set the remote pointer on the crypto context remote->crypto->remote = remote; // Populate handlers according to what cipher was selected if (!strcmp(cipher, "xor")) { res = xor_populate_handlers(remote->crypto); } else { res = ERROR_NOT_FOUND; } // If we got a context and it wants to process the request, do it. if ((res == ERROR_SUCCESS) && (remote->crypto->handlers.process_negotiate_request)) { res = remote->crypto->handlers.process_negotiate_request( remote->crypto, initializer); } } while (0); // If we fail, destroy the crypto context should it have been allocated. if (res != ERROR_SUCCESS) { if (remote->crypto) { free(remote->crypto); } remote->crypto = NULL; } return res; } /*! * @brief Gets a pointer to the remote endpoint's crypto context. * @param remote The \c Remote instance to get the crypto context from. * @returns A pointer to the crypto context. */ CryptoContext *remote_get_cipher(Remote *remote) { return remote->crypto; }