X-Git-Url: https://git.ucc.asn.au/?a=blobdiff_plain;f=src%2Fserver%2Fserver.c;h=21740fd87d126bf4f0af028d76758ea903444071;hb=dd8536ef3eddac19e517e99479f7ec7c4c1faf1c;hp=483806ab41f7d8d032fd50cdfad2282f28a98429;hpb=8a516dd60ab15cf514481c74dd087a294915565d;p=tpg%2Fopendispense2.git diff --git a/src/server/server.c b/src/server/server.c index 483806a..21740fd 100644 --- a/src/server/server.c +++ b/src/server/server.c @@ -19,6 +19,7 @@ #include #include #include +#include #define DEBUG_TRACE_CLIENT 0 #define HACK_NO_REFUNDS 1 @@ -33,6 +34,9 @@ #define MSG_STR_TOO_LONG "499 Command too long (limit "EXPSTR(INPUT_BUFFER_SIZE)")\n" +#define IDENT_TRUSTED_NETWORK 0x825F0D00 +#define IDENT_TRUSTED_NETMASK 0xFFFFFFC0 + // === TYPES === typedef struct sClient { @@ -58,6 +62,7 @@ void Server_ParseClientCommand(tClient *Client, char *CommandString); void Server_Cmd_USER(tClient *Client, char *Args); void Server_Cmd_PASS(tClient *Client, char *Args); void Server_Cmd_AUTOAUTH(tClient *Client, char *Args); +void Server_Cmd_AUTHIDENT(tClient *Client, char *Args); void Server_Cmd_SETEUSER(tClient *Client, char *Args); void Server_Cmd_ENUMITEMS(tClient *Client, char *Args); void Server_Cmd_ITEMINFO(tClient *Client, char *Args); @@ -88,6 +93,7 @@ const struct sClientCommand { {"USER", Server_Cmd_USER}, {"PASS", Server_Cmd_PASS}, {"AUTOAUTH", Server_Cmd_AUTOAUTH}, + {"AUTHIDENT", Server_Cmd_AUTHIDENT}, {"SETEUSER", Server_Cmd_SETEUSER}, {"ENUM_ITEMS", Server_Cmd_ENUMITEMS}, {"ITEM_INFO", Server_Cmd_ITEMINFO}, @@ -164,9 +170,15 @@ void Server_Start(void) } // In child // - Sort out stdin/stdout + #if 0 dup2( open("/dev/null", O_RDONLY, 0644), STDIN_FILENO ); dup2( open(gsServer_LogFile, O_CREAT|O_APPEND, 0644), STDOUT_FILENO ); dup2( open(gsServer_ErrorLog, O_CREAT|O_APPEND, 0644), STDERR_FILENO ); + #else + freopen("/dev/null", "r", stdin); + freopen(gsServer_LogFile, "a", stdout); + freopen(gsServer_ErrorLog, "a", stderr); + #endif } // Start the helper thread @@ -235,13 +247,13 @@ void Server_Start(void) case 0x7F000001: // 127.0.0.1 localhost // case 0x825F0D00: // 130.95.13.0 case 0x825F0D04: // 130.95.13.4 merlo - case 0x825F0D05: // 130.95.13.5 heathred (MR) + // case 0x825F0D05: // 130.95.13.5 heathred (MR) case 0x825F0D07: // 130.95.13.7 motsugo case 0x825F0D11: // 130.95.13.17 mermaid case 0x825F0D12: // 130.95.13.18 mussel case 0x825F0D17: // 130.95.13.23 martello case 0x825F0D2A: // 130.95.13.42 meersau - case 0x825F0D42: // 130.95.13.66 heathred (Clubroom) + // case 0x825F0D42: // 130.95.13.66 heathred (Clubroom) bTrusted = 1; break; default: @@ -509,6 +521,11 @@ void Server_Cmd_AUTOAUTH(tClient *Client, char *Args) return ; } + // Save username + if(Client->Username) + free(Client->Username); + Client->Username = strdup(username); + Client->bIsAuthed = 1; if(giDebugLevel) @@ -517,6 +534,88 @@ void Server_Cmd_AUTOAUTH(tClient *Client, char *Args) sendf(Client->Socket, "200 Auth OK\n"); } +/** + * \brief Authenticate as a user using the IDENT protocol + * + * Usage: AUTHIDENT + */ +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 ; + } + + // Get username via IDENT + username = ident_id(Client->Socket, ident_timeout); + if (!username) { + sendf(Client->Socket, "403 Authentication failure: IDENT auth timed out\n"); + } + + // Get UID + Client->UID = Bank_GetAcctByName( username, 0 ); + if( Client->UID < 0 ) { + if(giDebugLevel) + Debug(Client, "Unknown user '%s'", username); + sendf(Client->Socket, "403 Authentication failure: unknown account\n"); + free(username); + return ; + } + + userflags = Bank_GetFlags(Client->UID); + // You can't be an internal account + if( userflags & USER_FLAG_INTERNAL ) { + if(giDebugLevel) + Debug(Client, "IDENT auth as '%s', not allowed", username); + Client->UID = -1; + sendf(Client->Socket, "403 Authentication failure: that account is internal\n"); + free(username); + return ; + } + + // Disabled accounts + if( userflags & USER_FLAG_DISABLED ) { + Client->UID = -1; + sendf(Client->Socket, "403 Authentication failure: account disabled\n"); + free(username); + return ; + } + + // Save username + if(Client->Username) + free(Client->Username); + Client->Username = strdup(username); + + Client->bIsAuthed = 1; + + if(giDebugLevel) + Debug(Client, "IDENT authenticated as '%s' (%i)", username, Client->UID); + free(username); + + sendf(Client->Socket, "200 Auth OK\n"); +} + /** * \brief Set effective user */ @@ -912,6 +1011,16 @@ void Server_Cmd_ADD(tClient *Client, char *Args) return ; } + #if !ROOT_CAN_ADD + if( strcmp( Client->Username, "root" ) == 0 ) { + // Allow adding for new users + if( strcmp(reason, "treasurer: new user") != 0 ) { + sendf(Client->Socket, "403 Root may not add\n"); + return ; + } + } + #endif + #if HACK_NO_REFUNDS if( strstr(reason, "refund") != NULL || strstr(reason, "misdispense") != NULL ) { @@ -1323,8 +1432,8 @@ void Server_Cmd_USERFLAGS(tClient *Client, char *Args) Bank_SetFlags(uid, mask, value); // Log the change - Log_Info("Updated '%s' with flag set '%s' - Reason: %s", - username, flags, reason); + Log_Info("Updated '%s' with flag set '%s' by '%s' - Reason: %s", + username, flags, Client->Username, reason); // Return OK sendf(Client->Socket, "200 User Updated\n");