Implimented pin checks fully
authorJohn Hodge <[email protected]>
Sat, 12 Jan 2013 13:55:24 +0000 (21:55 +0800)
committerJohn Hodge <[email protected]>
Sat, 12 Jan 2013 13:55:24 +0000 (21:55 +0800)
src/client/common.h
src/client/main.c
src/client/protocol.c
src/server/server.c

index 4c592ff..2ac604f 100644 (file)
@@ -87,6 +87,8 @@ extern void   _PrintUserLine(const char *Line);
 extern int     Dispense_AddUser(int Socket, const char *Username);
 extern int     Dispense_SetUserType(int Socket, const char *Username, const char *TypeString, const char *Reason);
 extern int     Dispense_SetItem(int Socket, const char *Type, int ID, int NewPrice, const char *NewName);
+extern int     DispenseCheckPin(int Socket, const char *Username, const char *Pin);
+extern int     DispenseSetPin(int Socket, const char *Pin);
 
 #endif
 
index 444ab34..da301be 100644 (file)
@@ -12,7 +12,8 @@
 #include <stdio.h>
 #include <string.h>
 #include <ctype.h>     // isspace
-#include <unistd.h>    // close
+#include <pwd.h>       // getpwuids
+#include <unistd.h>    // close/getuid
 #include <limits.h>    // INT_MIN/INT_MAX
 #include "common.h"
 
@@ -637,6 +638,54 @@ int main(int argc, char *argv[])
                close(sock);
                return ret;
        }
+       // Check a user's pin
+       else if(strcmp(gsTextArgs[0], "pincheck") == 0)
+       {
+               if( giTextArgc < 2 || giTextArgc > 3 ) {
+                       fprintf(stderr, "Error: `dispense pincheck` takes one/two arguments\n");
+                       ShowUsage();
+                       return RV_ARGUMENTS;
+               }
+               struct passwd   *pwd = getpwuid( getuid() );
+               gsUserName = strdup(pwd->pw_name);
+               
+               const char *pin = gsTextArgs[1];
+               const char *user = gsUserName;
+               if( giTextArgc == 3 )
+                       user = gsTextArgs[2];
+
+               
+               sock = OpenConnection(gsDispenseServer, giDispensePort);
+               if( sock < 0 )  return RV_SOCKET_ERROR;
+               ret = Authenticate(sock);
+               if(ret) return ret;
+               
+               ret = DispenseCheckPin(sock, user, pin);
+               
+               close(sock);
+               return ret;
+       }
+       // Update 'your' pin
+       else if(strcmp(gsTextArgs[0], "pinset") == 0)
+       {
+               if( giTextArgc != 2 ) {
+                       fprintf(stderr, "Error: `dispense pinset` takes one argument\n");
+                       ShowUsage();
+                       return RV_ARGUMENTS;
+               }
+               
+               const char *pin = gsTextArgs[1];
+               
+               sock = OpenConnection(gsDispenseServer, giDispensePort);
+               if( sock < 0 )  return RV_SOCKET_ERROR;
+               ret = Authenticate(sock);
+               if(ret) return ret;
+
+               ret = DispenseSetPin(sock, pin);
+               
+               close(sock);
+               return ret;
+       }
        // Item name / pattern
        else
        {
index ad8a6bf..dae51cb 100644 (file)
@@ -21,6 +21,7 @@
 #include <unistd.h>    // close/getuid
 #include <limits.h>    // INT_MIN/INT_MAX
 #include <stdarg.h>
+#include <ctype.h>     // isdigit
 #include "common.h"
 
 // === PROTOTYPES ===
@@ -520,14 +521,14 @@ int DispenseCheckPin(int Socket, const char *Username, const char *Pin)
                return RV_ARGUMENTS;
        }
                
-       for( int i = 0; i < 4; i ++ )
+       for( int i = 0; i < 4; i ++ ) {
                if( !isdigit(Pin[i]) ) {
                        fprintf(stderr, "Pin format incorrect (character %i not a digit)\n", i);
                        return RV_ARGUMENTS;
                }
        }
        
-       sendf(Socket, "CHECK_PIN %s %s\n", Username, Pin);
+       sendf(Socket, "PIN_CHECK %s %s\n", Username, Pin);
        buf = ReadLine(Socket);
        
        responseCode = atoi(buf);
@@ -566,6 +567,49 @@ int DispenseCheckPin(int Socket, const char *Username, const char *Pin)
        return ret;
 }
 
+int DispenseSetPin(int Socket, const char *Pin)
+{
+        int    ret, responseCode;
+       char    *buf;
+       
+       if( strlen(Pin) != 4 ) {
+               fprintf(stderr, "Pin format incorrect (not 4 characters long)\n");
+               return RV_ARGUMENTS;
+       }
+               
+       for( int i = 0; i < 4; i ++ ) {
+               if( !isdigit(Pin[i]) ) {
+                       fprintf(stderr, "Pin format incorrect (character %i not a digit)\n", i);
+                       return RV_ARGUMENTS;
+               }
+       }
+       
+       sendf(Socket, "PIN_SET %s\n", Pin);
+       buf = ReadLine(Socket);
+       
+       responseCode = atoi(buf);
+       switch(responseCode)
+       {
+       case 200:
+               printf("Pin Updated\n");
+               ret = 0;
+               break;
+       case 401:
+               printf("Not authenticated\n");
+               ret = RV_PERMISSIONS;
+               break;
+       case 407:
+               printf("Client/server disagreement on pin format\n");
+               ret = RV_SERVER_ERROR;
+               break;
+       default:
+               printf("Unknown response code %i ('%s')\n", responseCode, buf);
+               ret = RV_UNKNOWN_ERROR;
+               break;
+       }
+       return ret;
+}
+
 /**
  * \brief Dispense an item
  * \return Boolean Failure
index 2afd1a7..a48b69a 100644 (file)
@@ -28,6 +28,9 @@
 
 #define PIDFILE        "/var/run/dispsrv.pid"
 
+#define Debug_Notice(msg, v...)        printf("%08llun: "msg"\n", (unsigned long long)time(NULL) ,##v)
+#define Debug_Debug(msg, v...) printf("%08llud: "msg"\n", (unsigned long long)time(NULL) ,##v)
+
 // Statistics
 #define MAX_CONNECTION_QUEUE   5
 #define INPUT_BUFFER_SIZE      256
@@ -155,7 +158,6 @@ void Server_Start(void)
                }
        }
 
-       atexit(Server_Cleanup);
        // Ignore SIGPIPE (stops crashes when the client exits early)
        signal(SIGPIPE, SIG_IGN);
 
@@ -176,6 +178,7 @@ void Server_Start(void)
        if( bind(giServer_Socket, (struct sockaddr *) &server_addr, sizeof(server_addr)) < 0 ) {
                fprintf(stderr, "ERROR: Unable to bind to 0.0.0.0:%i\n", giServer_Port);
                perror("Binding");
+               close(giServer_Socket);
                return ;
        }
 
@@ -190,7 +193,7 @@ void Server_Start(void)
                }
                if( pid != 0 ) {
                        // Parent, quit
-                       printf("Forked child %i\n", pid);
+                       Debug_Notice("Forked child server as PID %i\n", pid);
                        exit(0);
                }
                // In child
@@ -207,6 +210,7 @@ void Server_Start(void)
                fprintf(stderr, "OpenDispense 2 Server Started at %lld\n", (long long)time(NULL));
                #endif
        }
+       atexit(Server_Cleanup);
 
        // Start the helper thread
        StartPeriodicThread();
@@ -218,7 +222,7 @@ void Server_Start(void)
                return ;
        }
        
-       printf("Listening on 0.0.0.0:%i\n", giServer_Port);
+       Debug_Notice("Listening on 0.0.0.0:%i", giServer_Port);
        
        // write pidfile
        {
@@ -258,7 +262,7 @@ void Server_Start(void)
                if(giDebugLevel >= 2) {
                        char    ipstr[INET_ADDRSTRLEN];
                        inet_ntop(AF_INET, &client_addr.sin_addr, ipstr, INET_ADDRSTRLEN);
-                       printf("Client connection from %s:%i\n",
+                       Debug_Debug("Client connection from %s:%i",
                                ipstr, ntohs(client_addr.sin_port));
                }
                
@@ -312,7 +316,7 @@ void Server_Start(void)
 
 void Server_Cleanup(void)
 {
-       printf("\nClose(%i)\n", giServer_Socket);
+       Debug_Debug("Close(%i)", giServer_Socket);
        close(giServer_Socket);
        unlink(PIDFILE);
 }
@@ -1560,7 +1564,7 @@ void Server_Cmd_PINCHECK(tClient *Client, char *Args)
        }
        pin = atoi(pinstr);
 
-       // Not strictly needed, but ensures that randoms don't do brute forcing
+       // Not authenticated? go away!
        if( !Client->bIsAuthed ) {
                sendf(Client->Socket, "401 Not Authenticated\n");
                return ;
@@ -1591,6 +1595,13 @@ void Server_Cmd_PINCHECK(tClient *Client, char *Args)
        if( !Bank_IsPinValid(uid, pin) )
        {
                sendf(Client->Socket, "201 Pin incorrect\n");
+               struct sockaddr_storage addr;
+               socklen_t len = sizeof(addr);
+               char ipstr[INET6_ADDRSTRLEN];
+               getpeername(Client->Socket, (void*)&addr, &len);
+               struct sockaddr_in *s = (struct sockaddr_in *)&addr;
+               inet_ntop(addr.ss_family, &s->sin_addr, ipstr, sizeof(ipstr));
+               Debug_Notice("Bad pin from %s for %s by %i", ipstr, username, Client->UID);
                if( backoff < 5)
                        backoff ++;
                return ;
@@ -1608,7 +1619,7 @@ void Server_Cmd_PINSET(tClient *Client, char *Args)
        
 
        if( Server_int_ParseArgs(0, Args, &pinstr, NULL) ) {
-               sendf(Client->Socket, "407 PIN_SET takes 2 arguments\n");
+               sendf(Client->Socket, "407 PIN_SET takes 1 argument\n");
                return ;
        }
        
@@ -1618,7 +1629,6 @@ void Server_Cmd_PINSET(tClient *Client, char *Args)
        }
        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 ;

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