X-Git-Url: https://git.ucc.asn.au/?a=blobdiff_plain;f=src%2Fserver%2Fserver.c;h=1faa6fe914e2ddb26653479209c27411d61d6e57;hb=0e15ed888a4d398530a74a6b713414e649767358;hp=6286f43a3b2217ad4283447a09328d88f2df3338;hpb=5cf5f1c0479d0052d53ea735895a550a0e455287;p=tpg%2Fopendispense2.git diff --git a/src/server/server.c b/src/server/server.c index 6286f43..1faa6fe 100644 --- a/src/server/server.c +++ b/src/server/server.c @@ -18,7 +18,9 @@ #include #include #include -#include +#include // Signal handling +#include // AUTHIDENT +#include // time(2) #define DEBUG_TRACE_CLIENT 0 #define HACK_NO_REFUNDS 1 @@ -33,6 +35,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 +63,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 +94,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}, @@ -160,6 +167,7 @@ void Server_Start(void) } if( pid != 0 ) { // Parent, quit + printf("Forked child %i\n", pid); exit(0); } // In child @@ -172,6 +180,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 } @@ -528,6 +538,95 @@ 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) == -1 ) { + Debug(Client, "500 getpeername() failed\n"); + perror("Getting AUTHIDENT peer name"); + sendf(Client->Socket, "500 getpeername() failed\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 ) { + sendf(Client->Socket, "403 Authentication failure: IDENT auth timed out\n"); + return ; + } + + // 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 */