X-Git-Url: https://git.ucc.asn.au/?a=blobdiff_plain;f=src%2Fserver%2Fserver.c;h=97800588ea3daf783f5474ee11bcab563f614d6f;hb=0b5755205d388b5704c040c21285c0b7ab58825e;hp=66d10627290d1a9d3a82b1b46a3f6d0fa7fffe59;hpb=0da15449ea2ea9f32612cb249b4709ee54df4761;p=tpg%2Fopendispense2.git diff --git a/src/server/server.c b/src/server/server.c index 66d1062..9780058 100644 --- a/src/server/server.c +++ b/src/server/server.c @@ -25,6 +25,8 @@ #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 @@ -44,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]; @@ -57,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); @@ -118,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 @@ -132,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); @@ -199,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); @@ -210,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); @@ -241,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 ) ) @@ -264,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); } @@ -276,7 +309,7 @@ void Server_Cleanup(void) { printf("\nClose(%i)\n", giServer_Socket); close(giServer_Socket); - unlink("/var/run/dispsrv.pid"); + unlink(PIDFILE); } /** @@ -284,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; @@ -297,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 @@ -492,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"); @@ -548,38 +582,24 @@ 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) == -1 ) { - Debug(Client, "500 getpeername() failed\n"); - perror("Getting AUTHIDENT peer name"); - sendf(Client->Socket, "500 getpeername() failed\n"); + // Check if trusted + if( !Client->bTrustedHost ) { + if(giDebugLevel) + Debug(Client, "Untrusted client attempting to AUTHIDENT"); + sendf(Client->Socket, "401 Untrusted\n"); return ; } - client_ip = client_addr.sin_addr.s_addr; - if(giDebugLevel >= 2) { - Debug(Client, "client_ip = %x, ntohl(client_ip) = %x", client_ip, ntohl(client_ip)); - } - 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 ; - } - // Get username via IDENT username = ident_id(Client->Socket, ident_timeout); if( !username ) { + perror("AUTHIDENT - IDENT timed out"); sendf(Client->Socket, "403 Authentication failure: IDENT auth timed out\n"); return ; } @@ -665,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); @@ -685,7 +704,7 @@ void Server_Cmd_SETEUSER(tClient *Client, char *Args) // Disabled accounts if( userFlags & USER_FLAG_DISABLED ) { - Client->UID = -1; + Client->EffectiveUID = -1; sendf(Client->Socket, "403 Account disabled\n"); return ; } @@ -713,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? @@ -791,6 +812,8 @@ tItem *_GetItemFromString(char *String) /** * \brief Fetch information on a specific item + * + * Usage: ITEMINFO */ void Server_Cmd_ITEMINFO(tClient *Client, char *Args) { @@ -811,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; @@ -852,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; @@ -900,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;