From: John Hodge Date: Sat, 12 Jan 2013 13:55:24 +0000 (+0800) Subject: Implimented pin checks fully X-Git-Url: https://git.ucc.asn.au/?a=commitdiff_plain;h=ee724c0360fac7840d032812b5ab677aa0d15074;p=tpg%2Fopendispense2.git Implimented pin checks fully --- diff --git a/src/client/common.h b/src/client/common.h index 4c592ff..2ac604f 100644 --- a/src/client/common.h +++ b/src/client/common.h @@ -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 diff --git a/src/client/main.c b/src/client/main.c index 444ab34..da301be 100644 --- a/src/client/main.c +++ b/src/client/main.c @@ -12,7 +12,8 @@ #include #include #include // isspace -#include // close +#include // getpwuids +#include // close/getuid #include // 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 { diff --git a/src/client/protocol.c b/src/client/protocol.c index ad8a6bf..dae51cb 100644 --- a/src/client/protocol.c +++ b/src/client/protocol.c @@ -21,6 +21,7 @@ #include // close/getuid #include // INT_MIN/INT_MAX #include +#include // 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 diff --git a/src/server/server.c b/src/server/server.c index 2afd1a7..a48b69a 100644 --- a/src/server/server.c +++ b/src/server/server.c @@ -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 ;