X-Git-Url: https://git.ucc.asn.au/?a=blobdiff_plain;f=src%2Fserver%2Fserver.c;h=af9dc3428ebd3ed618c488434e41b1f7415939dd;hb=5df82cb2854e4f7c693c8a31e0c2d56682a93855;hp=c9ab63e7e786a8d804c9054185bba36067969c79;hpb=a189b749e46348379d2271eb7c51ca1f7334cbda;p=tpg%2Fopendispense2.git diff --git a/src/server/server.c b/src/server/server.c index c9ab63e..af9dc34 100644 --- a/src/server/server.c +++ b/src/server/server.c @@ -16,11 +16,16 @@ #include #include +// HACKS +#define HACK_TPG_NOAUTH 1 +#define HACK_ROOT_NOAUTH 1 + +// Statistics #define MAX_CONNECTION_QUEUE 5 #define INPUT_BUFFER_SIZE 256 -#define HASH_TYPE SHA512 -#define HASH_LENGTH 64 +#define HASH_TYPE SHA1 +#define HASH_LENGTH 20 #define MSG_STR_TOO_LONG "499 Command too long (limit "EXPSTR(INPUT_BUFFER_SIZE)")\n" @@ -40,6 +45,7 @@ typedef struct sClient // === PROTOTYPES === void Server_Start(void); +void Server_Cleanup(void); void Server_HandleClient(int Socket, int bTrusted); char *Server_ParseClientCommand(tClient *Client, char *CommandString); // --- Commands --- @@ -48,7 +54,12 @@ char *Server_Cmd_PASS(tClient *Client, char *Args); char *Server_Cmd_AUTOAUTH(tClient *Client, char *Args); char *Server_Cmd_ENUMITEMS(tClient *Client, char *Args); char *Server_Cmd_ITEMINFO(tClient *Client, char *Args); +char *Server_Cmd_DISPENSE(tClient *Client, char *Args); +char *Server_Cmd_GIVE(tClient *Client, char *Args); +char *Server_Cmd_ADD(tClient *Client, char *Args); +char *Server_Cmd_USERINFO(tClient *Client, char *Args); // --- Helpers --- + int GetUserAuth(const char *Salt, const char *Username, const uint8_t *Hash); void HexBin(uint8_t *Dest, char *Src, int BufSize); // === GLOBALS === @@ -63,9 +74,14 @@ struct sClientCommand { {"PASS", Server_Cmd_PASS}, {"AUTOAUTH", Server_Cmd_AUTOAUTH}, {"ENUM_ITEMS", Server_Cmd_ENUMITEMS}, - {"ITEM_INFO", Server_Cmd_ITEMINFO} + {"ITEM_INFO", Server_Cmd_ITEMINFO}, + {"DISPENSE", Server_Cmd_DISPENSE}, + {"GIVE", Server_Cmd_GIVE}, + {"ADD", Server_Cmd_ADD}, + {"USER_INFO", Server_Cmd_USERINFO} }; #define NUM_COMMANDS (sizeof(gaServer_Commands)/sizeof(gaServer_Commands[0])) + int giServer_Socket; // === CODE === /** @@ -73,12 +89,14 @@ struct sClientCommand { */ void Server_Start(void) { - int server_socket, client_socket; + int client_socket; struct sockaddr_in server_addr, client_addr; + atexit(Server_Cleanup); + // Create Server - server_socket = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP); - if( server_socket < 0 ) { + giServer_Socket = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP); + if( giServer_Socket < 0 ) { fprintf(stderr, "ERROR: Unable to create server socket\n"); return ; } @@ -90,14 +108,16 @@ void Server_Start(void) server_addr.sin_port = htons(giServer_Port); // Port // Bind - if( bind(server_socket, (struct sockaddr *) &server_addr, sizeof(server_addr)) < 0 ) { + if( bind(giServer_Socket, (struct sockaddr *) &server_addr, sizeof(server_addr)) < 0 ) { fprintf(stderr, "ERROR: Unable to bind to 0.0.0.0:%i\n", giServer_Port); + perror("Binding"); return ; } // Listen - if( listen(server_socket, MAX_CONNECTION_QUEUE) < 0 ) { + if( listen(giServer_Socket, MAX_CONNECTION_QUEUE) < 0 ) { fprintf(stderr, "ERROR: Unable to listen to socket\n"); + perror("Listen"); return ; } @@ -108,7 +128,7 @@ void Server_Start(void) uint len = sizeof(client_addr); int bTrusted = 0; - client_socket = accept(server_socket, (struct sockaddr *) &client_addr, &len); + client_socket = accept(giServer_Socket, (struct sockaddr *) &client_addr, &len); if(client_socket < 0) { fprintf(stderr, "ERROR: Unable to accept client connection\n"); return ; @@ -145,6 +165,12 @@ void Server_Start(void) } } +void Server_Cleanup(void) +{ + printf("Close(%i)\n", giServer_Socket); + close(giServer_Socket); +} + /** * \brief Reads from a client socket and parses the command strings * \param Socket Client socket number/handle @@ -182,6 +208,7 @@ void Server_HandleClient(int Socket, int bTrusted) char *ret; *eol = '\0'; ret = Server_ParseClientCommand(&clientInfo, start); + printf("ret = %s", ret); // `ret` is a string on the heap send(Socket, ret, strlen(ret), 0); free(ret); @@ -281,9 +308,8 @@ char *Server_Cmd_USER(tClient *Client, char *Args) Client->Salt[6] = 0x21 + (rand()&0x3F); Client->Salt[7] = 0x21 + (rand()&0x3F); - // "100 Salt xxxxXXXX\n" - ret = strdup("100 SALT xxxxXXXX\n"); - sprintf(ret, "100 SALT %s\n", Client->Salt); + // TODO: Also send hash type to use, (SHA1 or crypt according to [DAA]) + ret = mkstr("100 SALT %s\n", Client->Salt); #else ret = strdup("100 User Set\n"); #endif @@ -302,6 +328,15 @@ char *Server_Cmd_PASS(tClient *Client, char *Args) // Read user's hash HexBin(clienthash, Args, HASH_LENGTH); + // TODO: Decrypt password passed + + Client->UID = GetUserAuth(Client->Salt, Client->Username, clienthash); + + if( Client->UID != -1 ) { + Client->bIsAuthed = 1; + return strdup("200 Auth OK\n"); + } + if( giDebugLevel ) { int i; printf("Client %i: Password hash ", Client->ID); @@ -349,7 +384,6 @@ char *Server_Cmd_AUTOAUTH(tClient *Client, char *Args) */ char *Server_Cmd_ENUMITEMS(tClient *Client, char *Args) { -// int nItems = giNumItems; int retLen; int i; char *ret; @@ -374,21 +408,15 @@ char *Server_Cmd_ENUMITEMS(tClient *Client, char *Args) return ret; } -/** - * \brief Fetch information on a specific item - */ -char *Server_Cmd_ITEMINFO(tClient *Client, char *Args) +tItem *_GetItemFromString(char *String) { - int retLen = 0; - char *ret; - tItem *item; tHandler *handler; - char *type = Args; - char *colon = strchr(Args, ':'); + char *type = String; + char *colon = strchr(String, ':'); int num, i; if( !colon ) { - return strdup("406 Bad Item ID\n"); + return NULL; } num = atoi(colon+1); @@ -404,7 +432,7 @@ char *Server_Cmd_ITEMINFO(tClient *Client, char *Args) } } if( !handler ) { - return strdup("406 Bad Item ID\n"); + return NULL; } // Find item @@ -412,23 +440,192 @@ char *Server_Cmd_ITEMINFO(tClient *Client, char *Args) { if( gaItems[i].Handler != handler ) continue; if( gaItems[i].ID != num ) continue; - item = &gaItems[i]; - break; + return &gaItems[i]; } + return NULL; +} + +/** + * \brief Fetch information on a specific item + */ +char *Server_Cmd_ITEMINFO(tClient *Client, char *Args) +{ + int retLen = 0; + char *ret; + tItem *item = _GetItemFromString(Args); + if( !item ) { return strdup("406 Bad Item ID\n"); } // Create return retLen = snprintf(NULL, 0, "202 Item %s:%i %i %s\n", - handler->Name, item->ID, item->Price, item->Name); + item->Handler->Name, item->ID, item->Price, item->Name); ret = malloc(retLen+1); sprintf(ret, "202 Item %s:%i %i %s\n", - handler->Name, item->ID, item->Price, item->Name); + item->Handler->Name, item->ID, item->Price, item->Name); return ret; } +char *Server_Cmd_DISPENSE(tClient *Client, char *Args) +{ + tItem *item; + int ret; + if( !Client->bIsAuthed ) return strdup("401 Not Authenticated\n"); + + item = _GetItemFromString(Args); + if( !item ) { + return strdup("406 Bad Item ID\n"); + } + + switch( ret = DispenseItem( Client->UID, item ) ) + { + case 0: return strdup("200 Dispense OK\n"); + case 1: return strdup("501 Unable to dispense\n"); + case 2: return strdup("402 Poor You\n"); + default: + return strdup("500 Dispense Error\n"); + } +} + +char *Server_Cmd_GIVE(tClient *Client, char *Args) +{ + char *recipient, *ammount, *reason; + int uid, iAmmount; + + if( !Client->bIsAuthed ) return strdup("401 Not Authenticated\n"); + + recipient = Args; + + ammount = strchr(Args, ' '); + if( !ammount ) return strdup("407 Invalid Argument, expected 3 parameters, 1 encountered\n"); + *ammount = '\0'; + ammount ++; + + reason = strchr(ammount, ' '); + if( !reason ) return strdup("407 Invalid Argument, expected 3 parameters, 2 encountered\n"); + *reason = '\0'; + reason ++; + + // Get recipient + uid = GetUserID(recipient); + if( uid == -1 ) return strdup("404 Invalid target user"); + + // Parse ammount + iAmmount = atoi(ammount); + if( iAmmount <= 0 ) return strdup("407 Invalid Argument, ammount must be > zero\n"); + + // Do give + switch( DispenseGive(Client->UID, uid, iAmmount, reason) ) + { + case 0: + return strdup("200 Give OK\n"); + case 2: + return strdup("402 Poor You\n"); + default: + return strdup("500 Unknown error\n"); + } +} + +char *Server_Cmd_ADD(tClient *Client, char *Args) +{ + char *user, *ammount, *reason; + int uid, iAmmount; + + if( !Client->bIsAuthed ) return strdup("401 Not Authenticated\n"); + + user = Args; + + ammount = strchr(Args, ' '); + if( !ammount ) return strdup("407 Invalid Argument, expected 3 parameters, 1 encountered\n"); + *ammount = '\0'; + ammount ++; + + reason = strchr(ammount, ' '); + if( !reason ) return strdup("407 Invalid Argument, expected 3 parameters, 2 encountered\n"); + *reason = '\0'; + reason ++; + + // TODO: Check if the current user is in coke/higher + + // Get recipient + uid = GetUserID(user); + if( uid == -1 ) return strdup("404 Invalid user"); + + // Parse ammount + iAmmount = atoi(ammount); + if( iAmmount == 0 && ammount[0] != '0' ) return strdup("407 Invalid Argument, ammount must be > zero\n"); + + // Do give + switch( DispenseAdd(uid, Client->UID, iAmmount, reason) ) + { + case 0: + return strdup("200 Add OK\n"); + case 2: + return strdup("402 Poor Guy\n"); + default: + return strdup("500 Unknown error\n"); + } +} + +char *Server_Cmd_USERINFO(tClient *Client, char *Args) +{ + int uid; + char *user = Args; + char *space; + + space = strchr(user, ' '); + if(space) *space = '\0'; + + // Get recipient + uid = GetUserID(user); + if( uid == -1 ) return strdup("404 Invalid user"); + + return mkstr("202 User %s %i user\n", user, GetBalance(uid)); +} + +/** + * \brief Authenticate a user + * \return User ID, or -1 if authentication failed + */ +int GetUserAuth(const char *Salt, const char *Username, const uint8_t *ProvidedHash) +{ + #if 0 + uint8_t h[20]; + int ofs = strlen(Username) + strlen(Salt); + char input[ ofs + 40 + 1]; + char tmp[4 + strlen(Username) + 1]; // uid=%s + #endif + + #if HACK_TPG_NOAUTH + if( strcmp(Username, "tpg") == 0 ) + return GetUserID("tpg"); + #endif + #if HACK_ROOT_NOAUTH + if( strcmp(Username, "root") == 0 ) + return GetUserID("root"); + #endif + + #if 0 + // + strcpy(input, Username); + strcpy(input, Salt); + // TODO: Get user's SHA-1 hash + sprintf(tmp, "uid=%s", Username); + ldap_search_s(ld, "", LDAP_SCOPE_BASE, tmp, "userPassword", 0, res); + + sprintf(input+ofs, "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x", + h[ 0], h[ 1], h[ 2], h[ 3], h[ 4], h[ 5], h[ 6], h[ 7], h[ 8], h[ 9], + h[10], h[11], h[12], h[13], h[14], h[15], h[16], h[17], h[18], h[19] + ); + // Then create the hash from the provided salt + // Compare that with the provided hash + #endif + + return -1; +} + // --- INTERNAL HELPERS --- // TODO: Move to another file void HexBin(uint8_t *Dest, char *Src, int BufSize)