X-Git-Url: https://git.ucc.asn.au/?a=blobdiff_plain;f=src%2Fserver%2Fserver.c;h=97800588ea3daf783f5474ee11bcab563f614d6f;hb=0b5755205d388b5704c040c21285c0b7ab58825e;hp=21740fd87d126bf4f0af028d76758ea903444071;hpb=dd8536ef3eddac19e517e99479f7ec7c4c1faf1c;p=tpg%2Fopendispense2.git diff --git a/src/server/server.c b/src/server/server.c index 21740fd..9780058 100644 --- a/src/server/server.c +++ b/src/server/server.c @@ -18,12 +18,15 @@ #include #include #include -#include -#include +#include // Signal handling +#include // AUTHIDENT +#include // time(2) #define DEBUG_TRACE_CLIENT 0 #define HACK_NO_REFUNDS 1 +#define PIDFILE "/var/run/dispsrv.pid" + // Statistics #define MAX_CONNECTION_QUEUE 5 #define INPUT_BUFFER_SIZE 256 @@ -43,7 +46,8 @@ typedef struct sClient int Socket; // Client socket ID int ID; // Client ID - int bIsTrusted; // Is the connection from a trusted host/port + int bTrustedHost; + int bCanAutoAuth; // Is the connection from a trusted host/port char *Username; char Salt[9]; @@ -56,7 +60,7 @@ typedef struct sClient // === PROTOTYPES === void Server_Start(void); void Server_Cleanup(void); -void Server_HandleClient(int Socket, int bTrusted); +void Server_HandleClient(int Socket, int bTrustedHost, int bRootPort); void Server_ParseClientCommand(tClient *Client, char *CommandString); // --- Commands --- void Server_Cmd_USER(tClient *Client, char *Args); @@ -117,6 +121,8 @@ const struct sClientCommand { int gbServer_RunInBackground = 0; char *gsServer_LogFile = "/var/log/dispsrv.log"; char *gsServer_ErrorLog = "/var/log/dispsrv.err"; + int giServer_NumTrustedHosts; +struct in_addr *gaServer_TrustedHosts; // - State variables int giServer_Socket; // Server socket int giServer_NextClientID = 1; // Debug client ID @@ -131,6 +137,19 @@ void Server_Start(void) int client_socket; struct sockaddr_in server_addr, client_addr; + // Parse trusted hosts list + giServer_NumTrustedHosts = Config_GetValueCount("trusted_host"); + gaServer_TrustedHosts = malloc(giServer_NumTrustedHosts * sizeof(*gaServer_TrustedHosts)); + for( int i = 0; i < giServer_NumTrustedHosts; i ++ ) + { + const char *addr = Config_GetValue("trusted_host", i); + + if( inet_aton(addr, &gaServer_TrustedHosts[i]) == 0 ) { + fprintf(stderr, "Invalid IP address '%s'\n", addr); + continue ; + } + } + atexit(Server_Cleanup); // Ignore SIGPIPE (stops crashes when the client exits early) signal(SIGPIPE, SIG_IGN); @@ -166,6 +185,7 @@ void Server_Start(void) } if( pid != 0 ) { // Parent, quit + printf("Forked child %i\n", pid); exit(0); } // In child @@ -178,6 +198,8 @@ void Server_Start(void) freopen("/dev/null", "r", stdin); freopen(gsServer_LogFile, "a", stdout); freopen(gsServer_ErrorLog, "a", stderr); + fprintf(stdout, "OpenDispense 2 Server Started at %lld\n", (long long)time(NULL)); + fprintf(stderr, "OpenDispense 2 Server Started at %lld\n", (long long)time(NULL)); #endif } @@ -195,7 +217,7 @@ void Server_Start(void) // write pidfile { - FILE *fp = fopen("/var/run/dispsrv.pid", "w"); + FILE *fp = fopen(PIDFILE, "w"); if( fp ) { fprintf(fp, "%i", getpid()); fclose(fp); @@ -206,6 +228,7 @@ void Server_Start(void) { uint len = sizeof(client_addr); int bTrusted = 0; + int bRootPort = 0; // Accept a connection client_socket = accept(giServer_Socket, (struct sockaddr *) &client_addr, &len); @@ -237,9 +260,22 @@ void Server_Start(void) // Doesn't matter what, localhost is trusted if( ntohl( client_addr.sin_addr.s_addr ) == 0x7F000001 ) bTrusted = 1; - - // Trusted Connections + + // Check if the host is on the trusted list + for( int i = 0; i < giServer_NumTrustedHosts; i ++ ) + { + if( memcmp(&client_addr.sin_addr, &gaServer_TrustedHosts[i], sizeof(struct in_addr)) == 0 ) + { + bTrusted = 1; + break; + } + } + + // Root port (can AUTOAUTH if also a trusted machine if( ntohs(client_addr.sin_port) < 1024 ) + bRootPort = 1; + + #if 0 { // TODO: Make this runtime configurable switch( ntohl( client_addr.sin_addr.s_addr ) ) @@ -260,9 +296,10 @@ void Server_Start(void) break; } } + #endif // TODO: Multithread this? - Server_HandleClient(client_socket, bTrusted); + Server_HandleClient(client_socket, bTrusted, bRootPort); close(client_socket); } @@ -272,7 +309,7 @@ void Server_Cleanup(void) { printf("\nClose(%i)\n", giServer_Socket); close(giServer_Socket); - unlink("/var/run/dispsrv.pid"); + unlink(PIDFILE); } /** @@ -280,7 +317,7 @@ void Server_Cleanup(void) * \param Socket Client socket number/handle * \param bTrusted Is the client trusted? */ -void Server_HandleClient(int Socket, int bTrusted) +void Server_HandleClient(int Socket, int bTrusted, int bRootPort) { char inbuf[INPUT_BUFFER_SIZE]; char *buf = inbuf; @@ -293,7 +330,8 @@ void Server_HandleClient(int Socket, int bTrusted) // Initialise Client info clientInfo.Socket = Socket; clientInfo.ID = giServer_NextClientID ++; - clientInfo.bIsTrusted = bTrusted; + clientInfo.bTrustedHost = bTrusted; + clientInfo.bCanAutoAuth = bTrusted && bRootPort; clientInfo.EffectiveUID = -1; // Read from client @@ -488,7 +526,7 @@ void Server_Cmd_AUTOAUTH(tClient *Client, char *Args) } // Check if trusted - if( !Client->bIsTrusted ) { + if( !Client->bCanAutoAuth ) { if(giDebugLevel) Debug(Client, "Untrusted client attempting to AUTOAUTH"); sendf(Client->Socket, "401 Untrusted\n"); @@ -544,33 +582,26 @@ void Server_Cmd_AUTHIDENT(tClient *Client, char *Args) char *username; int userflags; const int ident_timeout = 5; - socklen_t len; - struct sockaddr_in client_addr; - uint32_t client_ip; if( Args != NULL && strlen(Args) ) { sendf(Client->Socket, "407 AUTHIDENT takes no arguments\n"); return ; } - // Check if trusted (only works with INET sockets at present) - len = sizeof(client_addr); - if ( ! getpeername(Client->Socket, (struct sockaddr*)&client_addr, &len) ) { - // throw an error - } - - client_ip = client_addr.sin_addr.s_addr; - if ( ! (ntohl(client_ip) == 0x7F000001 || ( (ntohl(client_ip) & IDENT_TRUSTED_NETMASK) == IDENT_TRUSTED_NETWORK ) )) { - if(giDebugLevel) - Debug(Client, "Untrusted client attempting to AUTHIDENT"); - sendf(Client->Socket, "401 Untrusted\n"); - return ; + // Check if trusted + if( !Client->bTrustedHost ) { + if(giDebugLevel) + Debug(Client, "Untrusted client attempting to AUTHIDENT"); + sendf(Client->Socket, "401 Untrusted\n"); + return ; } // Get username via IDENT username = ident_id(Client->Socket, ident_timeout); - if (!username) { + if( !username ) { + perror("AUTHIDENT - IDENT timed out"); sendf(Client->Socket, "403 Authentication failure: IDENT auth timed out\n"); + return ; } // Get UID @@ -654,8 +685,7 @@ void Server_Cmd_SETEUSER(tClient *Client, char *Args) sendf(Client->Socket, "404 User not found\n"); return ; } - - // You can't be an internal account + // You can't be an internal account (unless you're an admin) if( !(userFlags & USER_FLAG_ADMIN) ) { eUserFlags = Bank_GetFlags(Client->EffectiveUID); @@ -671,6 +701,13 @@ void Server_Cmd_SETEUSER(tClient *Client, char *Args) return ; } } + + // Disabled accounts + if( userFlags & USER_FLAG_DISABLED ) { + Client->EffectiveUID = -1; + sendf(Client->Socket, "403 Account disabled\n"); + return ; + } sendf(Client->Socket, "200 User set\n"); } @@ -695,6 +732,8 @@ void Server_int_SendItem(tClient *Client, tItem *Item) } } + if( !gbNoCostMode && Item->Price == 0 ) + status = "error"; // KNOWN HACK: Naming a slot 'dead' disables it if( strcmp(Item->Name, "dead") == 0 ) status = "sold"; // Another status? @@ -773,6 +812,8 @@ tItem *_GetItemFromString(char *String) /** * \brief Fetch information on a specific item + * + * Usage: ITEMINFO */ void Server_Cmd_ITEMINFO(tClient *Client, char *Args) { @@ -793,6 +834,11 @@ void Server_Cmd_ITEMINFO(tClient *Client, char *Args) Server_int_SendItem( Client, item ); } +/** + * \brief Dispense an item + * + * Usage: DISPENSE + */ void Server_Cmd_DISPENSE(tClient *Client, char *Args) { tItem *item; @@ -834,6 +880,11 @@ void Server_Cmd_DISPENSE(tClient *Client, char *Args) } } +/** + * \brief Refund an item to a user + * + * Usage: REFUND [] + */ void Server_Cmd_REFUND(tClient *Client, char *Args) { tItem *item; @@ -882,6 +933,11 @@ void Server_Cmd_REFUND(tClient *Client, char *Args) } } +/** + * \brief Transfer money to another account + * + * Usage: GIVE + */ void Server_Cmd_GIVE(tClient *Client, char *Args) { char *recipient, *ammount, *reason;