Pin checks and disabled account behavior
[tpg/opendispense2.git] / src / server / server.c
index 63b4aa7..2afd1a7 100644 (file)
 #include <signal.h>    // Signal handling
 #include <ident.h>     // AUTHIDENT
 #include <time.h>      // time(2)
 #include <signal.h>    // Signal handling
 #include <ident.h>     // AUTHIDENT
 #include <time.h>      // time(2)
+#include <ctype.h>
 
 #define        DEBUG_TRACE_CLIENT      0
 #define HACK_NO_REFUNDS        1
 
 
 #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
 // Statistics
 #define MAX_CONNECTION_QUEUE   5
 #define INPUT_BUFFER_SIZE      256
@@ -80,6 +83,8 @@ void  _SendUserInfo(tClient *Client, int UserID);
 void   Server_Cmd_USERADD(tClient *Client, char *Args);
 void   Server_Cmd_USERFLAGS(tClient *Client, char *Args);
 void   Server_Cmd_UPDATEITEM(tClient *Client, char *Args);
 void   Server_Cmd_USERADD(tClient *Client, char *Args);
 void   Server_Cmd_USERFLAGS(tClient *Client, char *Args);
 void   Server_Cmd_UPDATEITEM(tClient *Client, char *Args);
+void   Server_Cmd_PINCHECK(tClient *Client, char *Args);
+void   Server_Cmd_PINSET(tClient *Client, char *Args);
 // --- Helpers ---
 void   Debug(tClient *Client, const char *Format, ...);
  int   sendf(int Socket, const char *Format, ...);
 // --- Helpers ---
 void   Debug(tClient *Client, const char *Format, ...);
  int   sendf(int Socket, const char *Format, ...);
@@ -109,7 +114,9 @@ const struct sClientCommand {
        {"USER_INFO", Server_Cmd_USERINFO},
        {"USER_ADD", Server_Cmd_USERADD},
        {"USER_FLAGS", Server_Cmd_USERFLAGS},
        {"USER_INFO", Server_Cmd_USERINFO},
        {"USER_ADD", Server_Cmd_USERADD},
        {"USER_FLAGS", Server_Cmd_USERFLAGS},
-       {"UPDATE_ITEM", Server_Cmd_UPDATEITEM}
+       {"UPDATE_ITEM", Server_Cmd_UPDATEITEM},
+       {"PIN_CHECK", Server_Cmd_PINCHECK},
+       {"PIN_SET", Server_Cmd_PINSET}
 };
 #define NUM_COMMANDS   ((int)(sizeof(gaServer_Commands)/sizeof(gaServer_Commands[0])))
 
 };
 #define NUM_COMMANDS   ((int)(sizeof(gaServer_Commands)/sizeof(gaServer_Commands[0])))
 
@@ -215,7 +222,7 @@ void Server_Start(void)
        
        // write pidfile
        {
        
        // write pidfile
        {
-               FILE *fp = fopen("/var/run/dispsrv.pid", "w");
+               FILE *fp = fopen(PIDFILE, "w");
                if( fp ) {
                        fprintf(fp, "%i", getpid());
                        fclose(fp);
                if( fp ) {
                        fprintf(fp, "%i", getpid());
                        fclose(fp);
@@ -307,7 +314,7 @@ void Server_Cleanup(void)
 {
        printf("\nClose(%i)\n", giServer_Socket);
        close(giServer_Socket);
 {
        printf("\nClose(%i)\n", giServer_Socket);
        close(giServer_Socket);
-       unlink("/var/run/dispsrv.pid");
+       unlink(PIDFILE);
 }
 
 /**
 }
 
 /**
@@ -683,8 +690,7 @@ void Server_Cmd_SETEUSER(tClient *Client, char *Args)
                sendf(Client->Socket, "404 User not found\n");
                return ;
        }
                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);
        if( !(userFlags & USER_FLAG_ADMIN) )
        {
                eUserFlags = Bank_GetFlags(Client->EffectiveUID);
@@ -693,17 +699,13 @@ void Server_Cmd_SETEUSER(tClient *Client, char *Args)
                        sendf(Client->Socket, "404 User not found\n");
                        return ;
                }
                        sendf(Client->Socket, "404 User not found\n");
                        return ;
                }
-               // Disabled only avaliable to admins
-               if( eUserFlags & USER_FLAG_DISABLED ) {
-                       Client->EffectiveUID = -1;
-                       sendf(Client->Socket, "403 Account disabled\n");
-                       return ;
-               }
        }
 
        // Disabled accounts
        }
 
        // Disabled accounts
-       if( userFlags & USER_FLAG_DISABLED ) {
-               Client->UID = -1;
+       // - If disabled and the actual user is not an admin (and not root)
+       //   return 403
+       if( (eUserFlags & USER_FLAG_DISABLED) && (Client->UID == 0 || !(userFlags & USER_FLAG_ADMIN)) ) {
+               Client->EffectiveUID = -1;
                sendf(Client->Socket, "403 Account disabled\n");
                return ;
        }
                sendf(Client->Socket, "403 Account disabled\n");
                return ;
        }
@@ -868,6 +870,9 @@ void Server_Cmd_DISPENSE(tClient *Client, char *Args)
                uid = Client->UID;
        }
 
                uid = Client->UID;
        }
 
+//     if( Bank_GetFlags(Client->UID) & USER_FLAG_DISABLED  ) {
+//     }
+
        switch( ret = DispenseItem( Client->UID, uid, item ) )
        {
        case 0: sendf(Client->Socket, "200 Dispense OK\n");     return ;
        switch( ret = DispenseItem( Client->UID, uid, item ) )
        {
        case 0: sendf(Client->Socket, "200 Dispense OK\n");     return ;
@@ -1539,6 +1544,95 @@ void Server_Cmd_UPDATEITEM(tClient *Client, char *Args)
        }
 }
 
        }
 }
 
+void Server_Cmd_PINCHECK(tClient *Client, char *Args)
+{
+       char    *username, *pinstr;
+        int    pin;
+
+       if( Server_int_ParseArgs(0, Args, &username, &pinstr, NULL) ) {
+               sendf(Client->Socket, "407 PIN_CHECK takes 2 arguments\n");
+               return ;
+       }
+       
+       if( !isdigit(pinstr[0]) || !isdigit(pinstr[1]) || !isdigit(pinstr[2]) || !isdigit(pinstr[3]) || pinstr[4] != '\0' ) {
+               sendf(Client->Socket, "407 PIN should be four digits\n");
+               return ;
+       }
+       pin = atoi(pinstr);
+
+       // Not strictly needed, but ensures that randoms don't do brute forcing
+       if( !Client->bIsAuthed ) {
+               sendf(Client->Socket, "401 Not Authenticated\n");
+               return ;
+       }
+       
+       // Get user
+       int uid = Bank_GetAcctByName(username, 0);
+       if( uid == -1 ) {
+               sendf(Client->Socket, "404 User '%s' not found\n", username);
+               return ;
+       }
+       
+       // Check user permissions
+       if( uid != Client->UID && !(Bank_GetFlags(Client->UID) & (USER_FLAG_COKE|USER_FLAG_ADMIN))  ) {
+               sendf(Client->Socket, "403 Not in coke\n");
+               return ;
+       }
+       
+       // Get the pin
+       static time_t   last_wrong_pin_time;
+       static int      backoff = 1;
+       if( time(NULL) - last_wrong_pin_time < backoff ) {
+               sendf(Client->Socket, "407 Rate limited (%i seconds remaining)\n",
+                       backoff - (time(NULL) - last_wrong_pin_time));
+               return ;
+       }       
+       last_wrong_pin_time = time(NULL);
+       if( !Bank_IsPinValid(uid, pin) )
+       {
+               sendf(Client->Socket, "201 Pin incorrect\n");
+               if( backoff < 5)
+                       backoff ++;
+               return ;
+       }
+
+       last_wrong_pin_time = 0;
+       backoff = 1;
+       sendf(Client->Socket, "200 Pin correct\n");
+       return ;
+}
+void Server_Cmd_PINSET(tClient *Client, char *Args)
+{
+       char    *pinstr;
+        int    pin;
+       
+
+       if( Server_int_ParseArgs(0, Args, &pinstr, NULL) ) {
+               sendf(Client->Socket, "407 PIN_SET takes 2 arguments\n");
+               return ;
+       }
+       
+       if( !isdigit(pinstr[0]) || !isdigit(pinstr[1]) || !isdigit(pinstr[2]) || !isdigit(pinstr[3]) || pinstr[4] != '\0' ) {
+               sendf(Client->Socket, "407 PIN should be four digits\n");
+               return ;
+       }
+       pin = atoi(pinstr);
+
+       // Not strictly needed, but ensures that randoms don't do brute forcing
+       if( !Client->bIsAuthed ) {
+               sendf(Client->Socket, "401 Not Authenticated\n");
+               return ;
+       }
+       
+       int uid = Client->EffectiveUID;
+       if(uid == -1)
+               uid = Client->UID;
+       // Can only pinset yourself (well, the effective user)
+       Bank_SetPin(uid, pin);
+       sendf(Client->Socket, "200 Pin updated\n");
+       return ;
+}
+
 // --- INTERNAL HELPERS ---
 void Debug(tClient *Client, const char *Format, ...)
 {
 // --- INTERNAL HELPERS ---
 void Debug(tClient *Client, const char *Format, ...)
 {
@@ -1715,3 +1809,4 @@ int Server_int_ParseFlags(tClient *Client, const char *Str, int *Mask, int *Valu
        
        return 0;
 }
        
        return 0;
 }
+

UCC git Repository :: git.ucc.asn.au