diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..5e6591f --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "external/tart"] + path = external/tart + url = ssh://git@www.gitea.preacherdhm.com:222/PreacherDHM/Tart.git diff --git a/external/CMakeLists.txt b/external/CMakeLists.txt index f517f42..fea1b84 100644 --- a/external/CMakeLists.txt +++ b/external/CMakeLists.txt @@ -1,3 +1,3 @@ # ADD Externals HERE -# add_subdirectory(external) +add_subdirectory(tart) diff --git a/external/tart b/external/tart new file mode 160000 index 0000000..ee10de8 --- /dev/null +++ b/external/tart @@ -0,0 +1 @@ +Subproject commit ee10de863ddaaf94a4246c71f991d946bc0df1cc diff --git a/source/CMakeLists.txt b/source/CMakeLists.txt index d0f1726..a767eab 100644 --- a/source/CMakeLists.txt +++ b/source/CMakeLists.txt @@ -1,12 +1,21 @@ # ADD SOURCES HERE set(SOURCE_FILES main.c + ssh_server_client.c ) add_executable(${PROJECT_NAME} ${SOURCE_FILES}) +find_package(mongoc 2.1.2 REQUIRED) + target_link_libraries( ${PROJECT_NAME} ssh tart + mongoc::static ) + +add_subdirectory(game_source) +add_subdirectory(client_source) +add_subdirectory(Userdb) +add_subdirectory(server_source) diff --git a/source/Userdb/CMakeLists.txt b/source/Userdb/CMakeLists.txt new file mode 100644 index 0000000..e69de29 diff --git a/source/Userdb/user_data.cpp b/source/Userdb/user_data.cpp new file mode 100644 index 0000000..62f5084 --- /dev/null +++ b/source/Userdb/user_data.cpp @@ -0,0 +1,11 @@ +#include "user_data.h" +#include +#include +#include + +int Hash_Password(const char *password, unsigned char *out) { + const unsigned char salt[] = "alskdjaslkjdjasdjiw3i"; + int size =PKCS5_PBKDF2_HMAC(password, strlen(password), salt, sizeof(salt), + 1000, EVP_sha256(), 32, out); + return size; +} diff --git a/source/Userdb/user_data.h b/source/Userdb/user_data.h new file mode 100644 index 0000000..1debbde --- /dev/null +++ b/source/Userdb/user_data.h @@ -0,0 +1,18 @@ +#ifndef USER_DATA_H +#define USER_DATA_H + +/* + * Hash_Password + * + * password: this is the password in plane text + * out: this is the ouput hash of the function. + * + * NOTE: *This uses sha256 hashing.* + * + * this will return a unsigned char* that contains the hash. + * returns if zero or less then the hashing has failed other wise it is the len + * of the password hash. + * */ +int Hash_Password(const char* password,unsigned char* out); + +#endif diff --git a/source/Userdb/userdb.cpp b/source/Userdb/userdb.cpp new file mode 100644 index 0000000..040a346 --- /dev/null +++ b/source/Userdb/userdb.cpp @@ -0,0 +1,307 @@ +#include "userdb.h" + +#include +#include +#include +#include +#include +#include + +static mongoc_client_t* client = NULL; +static mongoc_database_t* db = NULL; +static mongoc_collection_t* collection = NULL; + +// Initialize MongoDB client +int userdb_init(const char* host, int port) { + + const char* target = "mongodb://mongoadmin:secret@127.0.0.1:27017"; + mongoc_uri_t* uri = mongoc_uri_new(target); + bson_error_t error; + + // Initialize the C Driver + mongoc_init(); + + // Create a new client and connect to the server + mongoc_client_t *client = mongoc_client_new_from_uri(uri); + if (!client) { + fprintf(stderr, "Failed to create MongoDB client\n"); + return -1; + } + db = mongoc_client_get_database(client, "userdb"); + if (!db) { + fprintf(stderr, "Failed to get database\n"); + mongoc_client_destroy(client); + return -1; + } + + bson_t *ping = BCON_NEW("ping", BCON_INT32(1)); + bson_t reply = BSON_INITIALIZER; + bson_t* options; + + collection = mongoc_database_create_collection(db, "users", NULL, &error); + if(!collection) { + + if(error.code == 43) { // if collection exists + collection = mongoc_database_get_collection(db, "users"); + if (!collection) { + fprintf(stderr, "Failed to get collection\n"); + mongoc_client_destroy(client); + return -1; + } + } else { + printf("bad thing has happed %d, %s\n", error.code, error.message); + } + + } + return 0; +} + +// Create user +//int userdb_create_user(const char* username, const char* email, const char* password_hash, const char** user_tags, int size_of_user_tags) { +int userdb_create_user(UserCreate user) { + bson_t* doc = NULL; + bson_error_t error; + int ret = 0; + bson_t* array = bson_new(); + + if(!array) { + printf("Failed to create BSON document\n"); + ret = -2; + goto cleanup; + } + + for(int i = 0; i < user.size_of_user_tags; i++) { + char id[32] = {0}; + snprintf(id,32,"%d", i); + bson_append_utf8(array, id, -1, user.user_tags[i], -1); + } + + + doc = bson_new(); + + + if (!doc) { + printf("Failed to create BSON document\n"); + ret = -1; + goto cleanup; + } + + // This is the old way of doing things --V + //doc = BCON_NEW( + // "username", BCON_UTF8(username), + // "email", BCON_UTF8(email), + // "password_hash", BCON_UTF8(password_hash), + // "session_id", BCON_UTF8(""), + // "active", BCON_INT32(1) + //); + // + + + + bson_append_utf8(doc, "username", -1, user.username, -1); + bson_append_utf8(doc, "email", -1, user.email, -1); + bson_append_utf8(doc, "password_hash", -1, user.password_hash, -1); + bson_append_utf8(doc, "session_id", -1, user.session_id, strlen(user.session_id)); + bson_append_utf8(doc, "last_page", -1, "/", -1); + + bson_append_array(doc,"tags", -1, array); + + if (!mongoc_collection_insert_one(collection, doc, NULL, NULL, &error)) { + fprintf(stderr, "Insert failed: %s\n", error.message); + ret = -1; + goto cleanup; + } + +cleanup: + if (doc) { + bson_destroy(doc); + } + if(array) { + bson_destroy(array); + } + return ret; +} + +// Find user by username +Userdb* userdb_find_user_by_username(const char* username) { + Userdb* user = (Userdb*)malloc(sizeof(Userdb)); + if (!user) { + return NULL; + } + + bson_t* query = BCON_NEW("username", BCON_UTF8(username)); + bson_error_t error; + mongoc_cursor_t* cursor = mongoc_collection_find_with_opts(collection, query, NULL, NULL); + if (!cursor) { + fprintf(stderr, "Find failed\n"); + free(user); + return NULL; + } + + bson_iter_t iter; + const bson_t* doc; + + if(mongoc_cursor_next(cursor, &doc)) { + bson_iter_init(&iter, doc); + + + + strncpy(user->username, username, USERDB_USERNAME_MAX_SIZE); + + if(bson_iter_find(&iter, "email")) { + const char* email = bson_iter_utf8(&iter, NULL); + if(email && strlen(email) < USERDB_EMAIL_MAX_SIZE) { + strcpy(user->email, email); + } + user->email[USERDB_EMAIL_MAX_SIZE - 1] = '\0'; + } + if(bson_iter_find(&iter, "password_hash")) { + const char* password_hash = bson_iter_utf8(&iter, NULL); + if(password_hash && strlen(password_hash) < USERDB_PASSWORD_HASH_MAX_SIZE) { + strcpy(user->password_hash, password_hash); + } + user->password_hash[USERDB_PASSWORD_HASH_MAX_SIZE - 1] = '\0'; + } + if(bson_iter_find(&iter, "user_group")) { + const char* user_group = bson_iter_utf8(&iter, NULL); + if(user_group && strlen(user_group) < USERDB_USER_GROUP_MAX_SIZE) { + strcpy(user->user_group, user_group); + } + user->user_group[USERDB_USER_GROUP_MAX_SIZE - 1] = '\0'; + } + if(bson_iter_find(&iter, "user_freads")) { + const char* password_hash = bson_iter_utf8(&iter, NULL); + if(password_hash && strlen(password_hash) < USERDB_PASSWORD_HASH_MAX_SIZE) { + strcpy(user->password_hash, password_hash); + } + user->password_hash[USERDB_PASSWORD_HASH_MAX_SIZE - 1] = '\0'; + } + if(bson_iter_find(&iter, "user_freads")) { + const char* password_hash = bson_iter_utf8(&iter, NULL); + if(password_hash && strlen(password_hash) < USERDB_PASSWORD_HASH_MAX_SIZE) { + strcpy(user->password_hash, password_hash); + } + user->password_hash[USERDB_PASSWORD_HASH_MAX_SIZE - 1] = '\0'; + } + + if(bson_iter_find(&iter, "level")) { + user->level = bson_iter_int32(&iter); + } + if(bson_iter_find(&iter, "current_xp")) { + user->current_xp = bson_iter_int32(&iter); + } + if(bson_iter_find(&iter, "credits")) { + user->credits = bson_iter_int32(&iter); + } + if(bson_iter_find(&iter, "runs")) { + user->runs = bson_iter_int32(&iter); + } + if(bson_iter_find(&iter, "active")) { + user->active = bson_iter_int32(&iter); + } + } + + bson_destroy(query); + return user; +} + +// Find user by username +User* userdb_find_user_by_username(const char* username) { + User* user = (User*)malloc(sizeof(User)); + if (!user) { + return NULL; + } + + bson_t* query = BCON_NEW("username", BCON_UTF8(username)); + bson_error_t error; + mongoc_cursor_t* cursor = mongoc_collection_find_with_opts(collection, query, NULL, NULL); + + if (!cursor) { + fprintf(stderr, "Find failed\n"); + bson_destroy(query); + free(user); + return NULL; + } + + bson_iter_t iter; + const bson_t* doc; + + if(mongoc_cursor_next(cursor, &doc)) { + if(bson_iter_init(&iter, doc)) { + + char* res = bson_as_canonical_extended_json(doc, NULL); + printf("resolt :%s\n", res); + bson_free(res); + + if(bson_iter_find(&iter, "email")) { + const char* email = bson_iter_utf8(&iter, NULL); + if(email && strlen(email) < USERDB_EMAIL_MAX_SIZE) { + strcpy(user->email, email); + } + user->email[USERDB_EMAIL_MAX_SIZE - 1] = '\0'; + } + + if(bson_iter_find(&iter, "password_hash")) { + const char* password_hash = bson_iter_utf8(&iter, NULL); + if(password_hash && strlen(password_hash) < USERDB_PASSWORD_HASH_MAX_SIZE) { + strcpy(user->password_hash, password_hash); + } + user->password_hash[USERDB_PASSWORD_HASH_MAX_SIZE - 1] = '\0'; + } + + if(bson_iter_find(&iter, "session_id")) { + const char* username = bson_iter_utf8(&iter, NULL); + if(username && strlen(username) < USERDB_USERNAME_MAX_SIZE) { + strcpy(user->username, username); + } + user->username[USERDB_USERNAME_MAX_SIZE - 1] = '\0'; + + } + } + } + + bson_destroy(query); + mongoc_cursor_destroy(cursor); + return user; +} + +// Update user status +int userdb_update_user_status(const char* username, int active) { + const bson_t* filter = BCON_NEW("username", BCON_UTF8(username)); + const bson_t* update = BCON_NEW("$set", BCON_DOCUMENT(BCON_NEW("active", BCON_INT32(active)))); + bson_error_t error; + + if (mongoc_collection_insert_one(collection, filter, update, NULL, &error) == 0) { + fprintf(stderr, "Update failed: %s\n", error.message); + return -1; + } + + return 0; +} + +// Delete user +int userdb_delete_user(const char* username) { + const bson_t* filter = BCON_NEW("username", BCON_UTF8(username)); + bson_error_t error; + + if (mongoc_collection_delete_one(collection, filter,NULL, NULL, &error) == 0) { + fprintf(stderr, "Delete failed: %s\n", error.message); + return -1; + } + + return 0; +} + +// Cleanup +void userdb_cleanup() { + if (collection) { + mongoc_collection_destroy(collection); + } + if (db) { + mongoc_database_destroy(db); + } + if (client) { + mongoc_client_destroy(client); + } + mongoc_cleanup(); +} diff --git a/source/Userdb/userdb.h b/source/Userdb/userdb.h new file mode 100644 index 0000000..be136ed --- /dev/null +++ b/source/Userdb/userdb.h @@ -0,0 +1,61 @@ +#ifndef USER_DB_H +#define USER_DB_H + +#define USERDB_USERNAME_MAX_SIZE 32 +#define USERDB_EMAIL_MAX_SIZE 64 +#define USERDB_PASSWORD_HASH_MAX_SIZE 128 +#define USERDB_COOKIE_MAX_SIZE 128 +#define USERDB_USER_GROUP_MAX_SIZE 30 +#define USERDB_FIREND_MAX_SIZE 30 +#define USERDB_MAX_ITEM_COUNT 50 + +#include + +typedef struct { + char username[USERDB_USERNAME_MAX_SIZE]; + char email[USERDB_EMAIL_MAX_SIZE]; + char password_hash[USERDB_PASSWORD_HASH_MAX_SIZE]; + char user_group[USERDB_USER_GROUP_MAX_SIZE]; + int user_freads[USERDB_FIREND_MAX_SIZE]; + int user_items[USERDB_MAX_ITEM_COUNT]; + int level; + int current_xp; + int credits; + int runs; + int active; +} Userdb; + +typedef struct { + + const char username[USERDB_USERNAME_MAX_SIZE]; + const char email[USERDB_EMAIL_MAX_SIZE]; + const char password_hash[USERDB_PASSWORD_HASH_MAX_SIZE]; + const char user_group[USERDB_USER_GROUP_MAX_SIZE]; + +} UserCreate; + +// Initialize MongoDB client +int userdb_init(const char* host, int port); + +// Connect to collection (e.g., "users") +int userdb_connect(const char* db_name, const char* collection_name); + +// Create a new user +int userdb_create_user(UserCreate user); + +// Retrieve user by username +Userdb* userdb_find_user_by_username(const char* username); +// Get the user by session_id +Userdb* userdb_find_user_by_session_id(const char* session_id); + +// Update user status +int userdb_update_user_status(const char* username, int active); + +// Delete user +int userdb_delete_user(const char* username); + +// Cleanup +void userdb_cleanup(); + + +#endif // !USER_DB_H diff --git a/source/client_source/CMakeLists.txt b/source/client_source/CMakeLists.txt new file mode 100644 index 0000000..e69de29 diff --git a/source/client_source/client.h b/source/client_source/client.h new file mode 100644 index 0000000..80e029f --- /dev/null +++ b/source/client_source/client.h @@ -0,0 +1,6 @@ +#ifndef CLIENT_H +#define CLIENT_H + + + +#endif diff --git a/source/game_source/CMakeLists.txt b/source/game_source/CMakeLists.txt new file mode 100644 index 0000000..e69de29 diff --git a/source/game_source/color.h b/source/game_source/color.h new file mode 100644 index 0000000..5bce3fe --- /dev/null +++ b/source/game_source/color.h @@ -0,0 +1,8 @@ +#ifndef COLOR_H +#define COLOR_H +typedef struct { + unsigned char r; + unsigned char g; + unsigned char b; +} color; +#endif // !COLOR_H diff --git a/source/game_source/engine.c b/source/game_source/engine.c new file mode 100644 index 0000000..f66fee3 --- /dev/null +++ b/source/game_source/engine.c @@ -0,0 +1,25 @@ +#include "engine.h" + +int GameInit(AuthUser *auth, User *user){ + // init tart + return 0; +} + + +void GameRun(User* user) { + // game logic + // display render +} + +void GameEnd() { + // free objects +} + +int GetInput(char* buffer){ + return 0; +} + +int Render(char* outbuffer) { + return 0; +} + diff --git a/source/game_source/engine.h b/source/game_source/engine.h new file mode 100644 index 0000000..7a043a6 --- /dev/null +++ b/source/game_source/engine.h @@ -0,0 +1,25 @@ +#ifndef ENGIN_H +#define ENGIN_H + + +typedef struct { + const char* username; + int userId; + int runs; + int hours; + int currentServerId; +} User; + +typedef struct { + char username[256]; + char password[256]; +} AuthUser; + +int GameInit(AuthUser* auth, User* user); +void GameRun(User* user); +void GameEnd(); +void SetInput(char* buffer); +int GetInput(char* buffer); +int Render(char* outbuffer); + +#endif // !ENGIN_H diff --git a/source/game_source/entities/Centery.c b/source/game_source/entities/Centery.c new file mode 100644 index 0000000..a0a59d0 --- /dev/null +++ b/source/game_source/entities/Centery.c @@ -0,0 +1,26 @@ +#include "Centery.h" +#include "entity_utils.h" + +int CreateCentery(int tear, int classification) { + return 0; +} + +int ServerUpdate(void * ent) { + entity* e = (entity*)ent; + centery* cen = (centery*)e->userdata; + + if( + + return 0; +} +int ClientUpdate(int action, void * centery) { + return 0; +} + +int Init(void * ent){ + return 0; +} + +int Free(void* ent) { + return 0; +} diff --git a/source/game_source/entities/Centery.h b/source/game_source/entities/Centery.h new file mode 100644 index 0000000..21a7138 --- /dev/null +++ b/source/game_source/entities/Centery.h @@ -0,0 +1,27 @@ +#ifndef CENTERY_H +#define CENTERY_H +#include "../entity.h" + +typedef struct { + entity* target; + int weapon; + int classification; + int tear; + int alert; + int mode; + + int health; + int ac; + int str; + int wis; + int dex; +} centery; + +int CreateCentery(int tear, int classification); + +int ServerUpdate(void*); +int ClientUpdate(int, void*); +int Init(void*); +int Free(void*); + +#endif // !CENTERY_H diff --git a/source/game_source/entities/Cypher.c b/source/game_source/entities/Cypher.c new file mode 100644 index 0000000..e69de29 diff --git a/source/game_source/entities/Cypher.h b/source/game_source/entities/Cypher.h new file mode 100644 index 0000000..6100fd8 --- /dev/null +++ b/source/game_source/entities/Cypher.h @@ -0,0 +1,6 @@ +#ifndef CYPHER_H +#define CYPHER_H +#include "../entity.h" + +#endif + diff --git a/source/game_source/entities/RAT.c b/source/game_source/entities/RAT.c new file mode 100644 index 0000000..e69de29 diff --git a/source/game_source/entities/RAT.h b/source/game_source/entities/RAT.h new file mode 100644 index 0000000..e69de29 diff --git a/source/game_source/entities/Rebuilder.c b/source/game_source/entities/Rebuilder.c new file mode 100644 index 0000000..e69de29 diff --git a/source/game_source/entities/Rebuilder.h b/source/game_source/entities/Rebuilder.h new file mode 100644 index 0000000..e69de29 diff --git a/source/game_source/entities/Reclamed.c b/source/game_source/entities/Reclamed.c new file mode 100644 index 0000000..e69de29 diff --git a/source/game_source/entities/Reclamed.h b/source/game_source/entities/Reclamed.h new file mode 100644 index 0000000..e69de29 diff --git a/source/game_source/entities/Reclamer.c b/source/game_source/entities/Reclamer.c new file mode 100644 index 0000000..e69de29 diff --git a/source/game_source/entities/Reclamer.h b/source/game_source/entities/Reclamer.h new file mode 100644 index 0000000..e69de29 diff --git a/source/game_source/entities/Servitor.c b/source/game_source/entities/Servitor.c new file mode 100644 index 0000000..e69de29 diff --git a/source/game_source/entities/Servitor.h b/source/game_source/entities/Servitor.h new file mode 100644 index 0000000..e69de29 diff --git a/source/game_source/entities/Walker.c b/source/game_source/entities/Walker.c new file mode 100644 index 0000000..e69de29 diff --git a/source/game_source/entities/Walker.h b/source/game_source/entities/Walker.h new file mode 100644 index 0000000..e69de29 diff --git a/source/game_source/entity.c b/source/game_source/entity.c new file mode 100644 index 0000000..e69de29 diff --git a/source/game_source/entity.h b/source/game_source/entity.h new file mode 100644 index 0000000..515bde1 --- /dev/null +++ b/source/game_source/entity.h @@ -0,0 +1,52 @@ +#ifndef ENTITY_H +#define ENTITY_H +#include "vector.h" +#include "tile.h" + +typedef int(*entity_func)(void*); +typedef int(*entity_update_func)(int, void*); + +// Entity network transaction. +typedef struct { + int id; + int action; + int userdataSize; + void* userdata; +} entity_transaction; + +// Entity Callbacks +typedef struct { + entity_func init; + entity_update_func update; + entity_func free; +} entity_callbacks; + +// Entity Struct +typedef struct { + int id; + const char* name; + const char* description; + tile tile; + vec2 position; + void* userdata; + entity_callbacks callback; + entity_transaction ta; +} entity; + +entity* CreateEntity(const char* name, const char* description); +int EntityAddCallbacks(entity* e, entity_callbacks cb); +int EntitySetUserdat(entity* e, void* userdata); + +// Gets +const char* GetEntityDescription(entity* e); +const char* GetEntityName(entity* e); + +// Entity minipulation +int EntityInit(entity* e); +int EntityUpdate(entity* e, int action, void* userdata); +int EntityFree(entity* e); + +// Network +int EntityTransaction(entity* e); + +#endif diff --git a/source/game_source/entity_handler.c b/source/game_source/entity_handler.c new file mode 100644 index 0000000..e69de29 diff --git a/source/game_source/entity_handler.h b/source/game_source/entity_handler.h new file mode 100644 index 0000000..630a62b --- /dev/null +++ b/source/game_source/entity_handler.h @@ -0,0 +1,29 @@ +#ifndef ENTITY_HEADER_H +#define ENTITY_HEADER_H + +#define ENTITY_LIST_ACTION_ADD +#define ENTITY_LIST_ACTION_REMOVE +#include "entity.h" + +typedef struct { + int count; + entity* entities[256]; +} entity_list; + +typedef struct { + int action; + int sizeOfData; + void* data; +}entity_list_transaction; + +void EntityListInit(entity_list* list); +int EntityListAddEntity(entity* ent); +int EntityListRemoveEntity(entity* ent); + +int EntityListTransactionSet(entity_list_transaction* ta, int action, void* data); +int EntityListTransactionSend(entity_list* list, entity_list_transaction* ta); + +int EntityListUpdate(); + + +#endif diff --git a/source/game_source/entity_utils.c b/source/game_source/entity_utils.c new file mode 100644 index 0000000..e69de29 diff --git a/source/game_source/entity_utils.h b/source/game_source/entity_utils.h new file mode 100644 index 0000000..9abad24 --- /dev/null +++ b/source/game_source/entity_utils.h @@ -0,0 +1,10 @@ +#ifndef ENTITY_UTILS_H +#define ENTITY_UTILS_H +#include "entity_handler.h" +#include "vector.h" + + +int* GetEntitiesAroundPoint(entity_list* list, vec2 position, int radious); +int* GetClosestEntity(entity_list* list, vec2 position); + +#endif // !ENTITY_UTILS_H diff --git a/source/game_source/level.c b/source/game_source/level.c new file mode 100644 index 0000000..e69de29 diff --git a/source/game_source/level.h b/source/game_source/level.h new file mode 100644 index 0000000..e69de29 diff --git a/source/game_source/tile.h b/source/game_source/tile.h new file mode 100644 index 0000000..445cd0e --- /dev/null +++ b/source/game_source/tile.h @@ -0,0 +1,9 @@ +#ifndef TILE_H +#define TILE_H +#include "color.h" +typedef struct { + char simble; + color forground; + color background; +} tile; +#endif diff --git a/source/game_source/transaction.h b/source/game_source/transaction.h new file mode 100644 index 0000000..05451b4 --- /dev/null +++ b/source/game_source/transaction.h @@ -0,0 +1,5 @@ +#ifndef TRANSACTION_H +#define TRANSACTION_H + + +#endif // !TRANSACTION_H diff --git a/source/game_source/vector.h b/source/game_source/vector.h new file mode 100644 index 0000000..7897621 --- /dev/null +++ b/source/game_source/vector.h @@ -0,0 +1,12 @@ +#ifndef VECTOR_H +#define VECTOR_H +typedef struct { + int x; + int y; +} vec2; + +vec2 vec2_add(vec2 a, vec2 b); +vec2 vec2_sub(vec2 a, vec2 b); +vec2 vec2_mul(vec2 a, vec2 b); +vec2 vec2_dev(vec2 a, vec2 b); +#endif diff --git a/source/main.c b/source/main.c index a90089c..fb63fe5 100644 --- a/source/main.c +++ b/source/main.c @@ -7,397 +7,22 @@ * ############################################################################# */ /* This is a sample implementation of a libssh based SSH server */ -/* -Copyright 2003-2009 Aris Adamantiadis +#include "ssh_server_client.h" -This file is part of the SSH Library - -You are free to copy this file, modify it in any way, consider it being public -domain. This does not apply to the rest of the library though, but it is -allowed to cut-and-paste working code from this file to any license of -program. -The goal is to show the API in action. It's not a reference on how terminal -clients must be made or how a client should react. -*/ +int test(void*); +int testrun(void*, void*); -#include -#include -#include -#include -#include -#include -#include - -#ifdef HAVE_ARGP_H -#include -#endif -#include -#include -#include - - -#ifndef BUF_SIZE -#define BUF_SIZE 2049 -#endif - -#ifndef KEYS_FOLDER -#ifdef _WIN32 -#define KEYS_FOLDER -#else -#define KEYS_FOLDER "/etc/ssh/" -#endif -#endif - -#define USER "myuser" -#define PASSWORD "mypassword" - - - -static int authenticated=0; -static int tries = 0; -static int error = 0; -static ssh_channel chan[30] ={NULL}; - -typedef struct { - ssh_session session; - int id; -} ud; - -static int auth_none(ssh_session session, - const char *user, - void *userdata) -{ - ssh_string banner = NULL; - - (void)user; /* unused */ - (void)userdata; /* unused */ - - //ssh_set_auth_methods(session, - // SSH_AUTH_METHOD_PASSWORD | SSH_AUTH_METHOD_GSSAPI_MIC); - - banner = ssh_string_from_char("Loggin To your skelvetty acount!\n"); - if (banner != NULL) { - ssh_send_issue_banner(session, banner); - } - ssh_string_free(banner); - - authenticated ++; - return SSH_AUTH_SUCCESS; -} - -static int auth_password(ssh_session session, const char *user, - const char *password, void *userdata){ - (void)userdata; - printf("Authenticating user %s pwd %s\n",user, password); - if(strcmp(user,USER) == 0 && strcmp(password, PASSWORD) == 0){ - authenticated = 1; - printf("Authenticated\n"); - return SSH_AUTH_SUCCESS; - } - if (tries >= 3){ - printf("Too many authentication tries\n"); - ssh_disconnect(session); - error = 1; - return SSH_AUTH_DENIED; - } - tries++; - return SSH_AUTH_DENIED; -} - -#ifdef WITH_GSSAPI -static int auth_gssapi_mic(ssh_session session, const char *user, const char *principal, void *userdata){ - ssh_gssapi_creds creds = ssh_gssapi_get_creds(session); - (void)userdata; - printf("Authenticating user %s with gssapi principal %s\n",user, principal); - if (creds != NULL) - printf("Received some gssapi credentials\n"); - else - printf("Not received any forwardable creds\n"); - printf("authenticated\n"); - authenticated = 1; - return SSH_AUTH_SUCCESS; -} -#endif - -static int pty_request(ssh_session session, ssh_channel channel, const char *term, - int x,int y, int px, int py, void *userdata){ - (void) session; - (void) channel; - (void) term; - (void) x; - (void) y; - (void) px; - (void) py; - (void) userdata; - printf("Allocated terminal\n"); - return 0; -} - -static int shell_request(ssh_session session, ssh_channel channel, void *userdata){ - (void)session; - (void)channel; - (void)userdata; - printf("Allocated shell\n"); - return 0; -} -struct ssh_channel_callbacks_struct channel_cb = { - .channel_pty_request_function = pty_request, - .channel_shell_request_function = shell_request -}; - -static ssh_channel new_session_channel(ssh_session session, void *userdata){ - (void) session; - (void) userdata; - printf("Allocated session channel for id %d\n", *(int*)userdata); - *(ssh_channel*)userdata = ssh_channel_new(session); - ssh_callbacks_init(&channel_cb); - ssh_set_channel_callbacks(*(ssh_channel*)userdata, &channel_cb); - return *(ssh_channel*)userdata; -} - - -#ifdef HAVE_ARGP_H -const char *argp_program_version = "libssh server example " -SSH_STRINGIFY(LIBSSH_VERSION); -const char *argp_program_bug_address = ""; - -/* Program documentation. */ -static char doc[] = "libssh -- a Secure Shell protocol implementation"; - -/* A description of the arguments we accept. */ -static char args_doc[] = "BINDADDR"; - -/* The options we understand. */ -static struct argp_option options[] = { - { - .name = "port", - .key = 'p', - .arg = "PORT", - .flags = 0, - .doc = "Set the port to bind.", - .group = 0 - }, - { - .name = "hostkey", - .key = 'k', - .arg = "FILE", - .flags = 0, - .doc = "Set the host key.", - .group = 0 - }, - { - .name = "rsakey", - .key = 'r', - .arg = "FILE", - .flags = 0, - .doc = "Set the rsa key (deprecated alias for 'k').", - .group = 0 - }, - { - .name = "verbose", - .key = 'v', - .arg = NULL, - .flags = 0, - .doc = "Get verbose output.", - .group = 0 - }, - { - .name = "config", - .key = 'f', - .arg = "FILE", - .flags = 0, - .doc = "Configuration file to use.", - .group = 0 - }, - {NULL, 0, NULL, 0, NULL, 0} -}; - -/* Parse a single option. */ -static error_t parse_opt (int key, char *arg, struct argp_state *state) { - /* Get the input argument from argp_parse, which we - * know is a pointer to our arguments structure. - */ - ssh_bind sshbind = state->input; - - switch (key) { - case 'p': - ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_BINDPORT_STR, arg); - break; - case 'r': - case 'k': - ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_HOSTKEY, arg); - break; - case 'v': - ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_LOG_VERBOSITY_STR, "3"); - break; - case 'f': - ssh_bind_options_parse_config(sshbind, arg); - break; - case ARGP_KEY_ARG: - if (state->arg_num >= 1) { - /* Too many arguments. */ - argp_usage (state); - } - ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_BINDADDR, arg); - break; - case ARGP_KEY_END: - if (state->arg_num < 1) { - /* Not enough arguments. */ - argp_usage (state); - } - break; - default: - return ARGP_ERR_UNKNOWN; - } - - return 0; -} - -/* Our argp parser. */ -static struct argp argp = {options, parse_opt, args_doc, doc, NULL, NULL, NULL}; -#endif /* HAVE_ARGP_H */ - -void* Handel_Client(void* d) { - ud data = *(ud*)d; - char buf[BUF_SIZE]; - int r; - int i; - ssh_event mainloop; - ssh_session session = data.session; - ssh_channel c; - - struct ssh_server_callbacks_struct cb = { - .userdata = (void*)&c, - .auth_none_function = auth_none, - .auth_password_function = auth_password, - .channel_open_request_session_function = new_session_channel, +int main() { + ServerConfig conf = { + .id = 123, + .port = 2222, + .cbs = (ServerLoopCallbacks){ + .ssh_init = test, + .ssh_stop = test, + .ssh_run = testrun, + } }; - - ssh_callbacks_init(&cb); - ssh_set_server_callbacks(session, &cb); - - if (ssh_handle_key_exchange(session)) { - printf("ssh_handle_key_exchange: %s\n", ssh_get_error(session)); - return NULL; - } - - ssh_set_auth_methods(session, SSH_AUTH_METHOD_NONE); - - mainloop = ssh_event_new(); - ssh_event_add_session(mainloop, session); - - while (!(authenticated && c != NULL)){ - if(error) - break; - r = ssh_event_dopoll(mainloop, -1); - if (r == SSH_ERROR){ - printf("Error : %s\n",ssh_get_error(session)); - ssh_disconnect(session); - return NULL; - } - } - - char sendBuf[1024] = {0}; - int counter = 0; - if(error){ - printf("Error, exiting loop\n"); - } else - printf("Authenticated and got a channel\n"); - // GameInit() - do{ - i = 1; - snprintf(sendBuf, 1024, "Counter: %d, id: %d\r", counter, data.id); - char kittyBuffer[30] = {0}; - sprintf(kittyBuffer, "\e[>%d", 0b1000); - if (ssh_channel_write(c, kittyBuffer, 30) == SSH_ERROR) { - printf("error writing to channel\n"); - return NULL; - } - i = ssh_channel_read_nonblocking(c, buf, sizeof(buf)-1, 0); - counter++; - // code go here - // GameUpdate() - // code go here - if (ssh_channel_write(c, sendBuf, 1024) == SSH_ERROR) { - printf("error writing to channel\n"); - return NULL; - } - if(i>0) { - - buf[i] = '\0'; - printf("%s", buf); - fflush(stdout); - if(buf[0] == '\x03') { - ssh_disconnect(data.session); - ssh_free(data.session); - authenticated--; - //ssh_channel_close(c); - //ssh_channel_free(c); - return 0; - } - - //if (buf[0] == '\x0d') { - // if (ssh_channel_write(chan, "\n", 1) == SSH_ERROR) { - // printf("error writing to channel\n"); - // return 1; - // } - - // printf("\n"); - //} - } - } while (true); - + ssh_start(&conf); return 0; } -int main(int argc, char **argv){ - ssh_session session; - ssh_bind sshbind; - - int port = 2222; - int r =0; - - sshbind=ssh_bind_new(); - - ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_HOSTKEY, "./rsa.key"); - ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_BINDPORT, &port); - //ssh_bind_set_blocking(sshbind, 0); - -#ifdef HAVE_ARGP_H - /* - * Parse our arguments; every option seen by parse_opt will - * be reflected in arguments. - */ - argp_parse (&argp, argc, argv, 0, 0, sshbind); -#else - (void) argc; - (void) argv; -#endif - - while(sshbind) { - - if(ssh_bind_listen(sshbind)<0){ - printf("Error listening to socket: %s\n",ssh_get_error(sshbind)); - return 1; - } - session=ssh_new(); - r=ssh_bind_accept(sshbind,session); - if(r==SSH_ERROR){ - printf("error accepting a connection : %s\n",ssh_get_error(sshbind)); - return 1; - } - ud d = {session, authenticated}; - - pthread_t thread_id; - if(pthread_create(&thread_id, NULL, Handel_Client, (void*)&d) < 0) { - ssh_disconnect(session); - } - } - // GameEnd() - //ssh_disconnect(session); - //ssh_bind_free(sshbind); - //ssh_finalize(); - return 0; -} - - diff --git a/source/server_source/CMakeLists.txt b/source/server_source/CMakeLists.txt new file mode 100644 index 0000000..e69de29 diff --git a/source/server_source/server.c b/source/server_source/server.c new file mode 100644 index 0000000..e69de29 diff --git a/source/server_source/server.h b/source/server_source/server.h new file mode 100644 index 0000000..e495ee6 --- /dev/null +++ b/source/server_source/server.h @@ -0,0 +1,11 @@ +#ifndef SERVER_H +#define SERVER_H + +typedef struct { + int port; + int id; +} server_info; + +server_info start_server(); + +#endif // !SERVER_H diff --git a/source/server_source/transactions.c b/source/server_source/transactions.c new file mode 100644 index 0000000..e69de29 diff --git a/source/server_source/transactions.h b/source/server_source/transactions.h new file mode 100644 index 0000000..e69de29 diff --git a/source/ssh_server_client.c b/source/ssh_server_client.c new file mode 100644 index 0000000..923a569 --- /dev/null +++ b/source/ssh_server_client.c @@ -0,0 +1,280 @@ + +/* ############################################################################# + * # sshGameServer + * This is a test + * + * AUTHER: PreacherDHM + * DATE: 07/03/26 + * ############################################################################# + */ + +/* This is a sample implementation of a libssh based SSH server */ + + +#include "ssh_server_client.h" +#include +#include +#include +#include +#include +#include +#include + +#ifdef HAVE_ARGP_H +#include +#endif +#include +#include +#include + + +#ifndef BUF_SIZE +#define BUF_SIZE 2049 +#endif + +#ifndef KEYS_FOLDER +#ifdef _WIN32 +#define KEYS_FOLDER +#else +#define KEYS_FOLDER "/etc/ssh/" +#endif +#endif + + + + +static int authenticated=0; +static int tries = 0; +static int error = 0; +static ssh_channel chan[30] ={NULL}; + +typedef struct { + ssh_session session; + ServerConfig* config; +} ud; + +static int auth_none(ssh_session session, + const char *user, + void *userdata) +{ + ssh_string banner = NULL; + + (void)user; /* unused */ + (void)userdata; /* unused */ + + //ssh_set_auth_methods(session, + // SSH_AUTH_METHOD_PASSWORD | SSH_AUTH_METHOD_GSSAPI_MIC); + + banner = ssh_string_from_char("Loggin To your skelvetty acount!\n"); + if (banner != NULL) { + ssh_send_issue_banner(session, banner); + } + ssh_string_free(banner); + + authenticated ++; + return SSH_AUTH_SUCCESS; +} + +static int auth_password(ssh_session session, const char *user, + const char *password, void *userdata){ + //(void)userdata; + //printf("Authenticating user %s pwd %s\n",user, password); + //if(strcmp(user,USER) == 0 && strcmp(password, PASSWORD) == 0){ + // authenticated = 1; + // printf("Authenticated\n"); + return SSH_AUTH_SUCCESS; + //} + //if (tries >= 3){ + // printf("Too many authentication tries\n"); + // ssh_disconnect(session); + // error = 1; + // return SSH_AUTH_DENIED; + //} + //tries++; + //return SSH_AUTH_DENIED; +} + +#ifdef WITH_GSSAPI +static int auth_gssapi_mic(ssh_session session, const char *user, const char *principal, void *userdata){ + ssh_gssapi_creds creds = ssh_gssapi_get_creds(session); + (void)userdata; + printf("Authenticating user %s with gssapi principal %s\n",user, principal); + if (creds != NULL) + printf("Received some gssapi credentials\n"); + else + printf("Not received any forwardable creds\n"); + printf("authenticated\n"); + authenticated = 1; + return SSH_AUTH_SUCCESS; +} +#endif + +static int pty_request(ssh_session session, ssh_channel channel, const char *term, + int x,int y, int px, int py, void *userdata){ + (void) session; + (void) channel; + (void) term; + (void) x; + (void) y; + (void) px; + (void) py; + (void) userdata; + printf("Allocated terminal\n"); + return 0; +} + +static int shell_request(ssh_session session, ssh_channel channel, void *userdata){ + (void)session; + (void)channel; + (void)userdata; + printf("Allocated shell\n"); + return 0; +} +struct ssh_channel_callbacks_struct channel_cb = { + .channel_pty_request_function = pty_request, + .channel_shell_request_function = shell_request +}; + +static ssh_channel new_session_channel(ssh_session session, void *userdata){ + (void) session; + (void) userdata; + printf("Allocated session channel for id %d\n", *(int*)userdata); + *(ssh_channel*)userdata = ssh_channel_new(session); + ssh_callbacks_init(&channel_cb); + ssh_set_channel_callbacks(*(ssh_channel*)userdata, &channel_cb); + return *(ssh_channel*)userdata; +} + + + +void* Handel_Client(void* d) { + ud data = *(ud*)d; + char buf[BUF_SIZE]; + int r; + int i; + ssh_event mainloop; + ssh_session session = data.session; + ssh_channel c; + + struct ssh_server_callbacks_struct cb = { + .userdata = (void*)&c, + .auth_none_function = auth_none, + .auth_password_function = auth_password, + .channel_open_request_session_function = new_session_channel, + }; + + ssh_callbacks_init(&cb); + ssh_set_server_callbacks(session, &cb); + + if (ssh_handle_key_exchange(session)) { + printf("ssh_handle_key_exchange: %s\n", ssh_get_error(session)); + return NULL; + } + + ssh_set_auth_methods(session, SSH_AUTH_METHOD_NONE); + + mainloop = ssh_event_new(); + ssh_event_add_session(mainloop, session); + + while (!(authenticated && c != NULL)){ + if(error) + break; + r = ssh_event_dopoll(mainloop, -1); + if (r == SSH_ERROR){ + printf("Error : %s\n",ssh_get_error(session)); + ssh_disconnect(session); + return NULL; + } + } + + char sendBuf[1024] = {0}; + int sendBuffSize = 1024; + int counter = 0; + if(error){ + printf("Error, exiting loop\n"); + } else + printf("Authenticated and got a channel\n"); + data.config->cbs.ssh_init(data.config->cbs.init_var); + do{ + i = 1; + snprintf(sendBuf, 1024, "Counter: %d, id: %d\r", counter, data.config->id); + char kittyBuffer[30] = {0}; + sprintf(kittyBuffer, "\e[>%d", 0b1000); + if (ssh_channel_write(c, kittyBuffer, 30) == SSH_ERROR) { + printf("error writing to channel\n"); + return NULL; + } + i = ssh_channel_read_nonblocking(c, buf, sizeof(buf)-1, 0); + counter++; + // code go here + ssh_terminal_data db = { + .inputBuffer = buf, + .outputBuffer = sendBuf, + .inputSize = 1024, + .outputSize = &sendBuffSize, + }; + data.config->cbs.ssh_run(&db,data.config->cbs.run_var); + // code go here + if (ssh_channel_write(c, sendBuf, 1024) == SSH_ERROR) { + printf("error writing to channel\n"); + return NULL; + } + if(i>0) { + + buf[i] = '\0'; + printf("%s", buf); + fflush(stdout); + if(buf[0] == '\x03') { + ssh_disconnect(data.session); + ssh_free(data.session); + authenticated--; + //ssh_channel_close(c); + //ssh_channel_free(c); + return 0; + } + } + } while (true); + + data.config->cbs.ssh_stop(data.config->cbs.stop_var); + + return 0; +} + +int ssh_start(ServerConfig* conf){ + ssh_session session; + ssh_bind sshbind; + + int port = conf->port; + int r =0; + + sshbind=ssh_bind_new(); + + ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_HOSTKEY, "./rsa.key"); + ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_BINDPORT, &port); + + while(sshbind) { + + if(ssh_bind_listen(sshbind)<0){ + printf("Error listening to socket: %s\n",ssh_get_error(sshbind)); + return 1; + } + session=ssh_new(); + r=ssh_bind_accept(sshbind,session); + if(r==SSH_ERROR){ + printf("error accepting a connection : %s\n",ssh_get_error(sshbind)); + return 1; + } + ud d = {session, conf}; + + pthread_t thread_id; + if(pthread_create(&thread_id, NULL, Handel_Client, (void*)&d) < 0) { + ssh_disconnect(session); + } + } + //ssh_disconnect(session); + //ssh_bind_free(sshbind); + //ssh_finalize(); + return 0; +} + + diff --git a/source/ssh_server_client.h b/source/ssh_server_client.h new file mode 100644 index 0000000..985f259 --- /dev/null +++ b/source/ssh_server_client.h @@ -0,0 +1,33 @@ +#ifndef SSH_SERVER_CLIENT_H +#define SSH_SERVER_CLIENT_H + +typedef struct { + int inputSize; + int* outputSize; + char* inputBuffer; + char* outputBuffer; + +}ssh_terminal_data; + +typedef int(*ssh_server_callback)(void* userdata); +typedef int(*ssh_server_run_callback)(void* ssh_terminal_data, void* userdata); + +typedef struct { + void* init_var; + void* run_var; + void* stop_var; + ssh_server_callback ssh_init; + ssh_server_run_callback ssh_run; + ssh_server_callback ssh_stop; +}ServerLoopCallbacks; + +typedef struct { + int port; + int id; + ServerLoopCallbacks cbs; +}ServerConfig; + + +int ssh_start(ServerConfig* conf); + +#endif