int Bank_SetFlags(int AcctID, int Mask, int Value);
int Bank_GetBalance(int AcctID);
char *Bank_GetAcctName(int AcctID);
+ int Bank_IsPinValid(int AcctID, int Pin);
+void Bank_SetPin(int AcctID, int Pin);
sqlite3_stmt *Bank_int_MakeStatemnt(sqlite3 *Database, const char *Query);
int Bank_int_QueryNone(sqlite3 *Database, const char *Query, char **ErrorMessage);
sqlite3_stmt *Bank_int_QuerySingle(sqlite3 *Database, const char *Query);
return sqlite3_last_insert_rowid(gBank_Database);
}
+int Bank_IsPinValid(int AcctID, int Pin)
+{
+ char *query = mkstr("SELECT acct_id FROM accounts WHERE acct_id=%i AND acct_pin=%i LIMIT 1", AcctID, Pin);
+ sqlite3_stmt *statement = Bank_int_QuerySingle(gBank_Database, query);
+ free(query);
+
+ if( statement ) {
+ sqlite3_finalize(statement);
+ }
+
+ return (statement != NULL);
+}
+
+void Bank_SetPin(int AcctID, int Pin)
+{
+ char *errmsg;
+ char *query = mkstr("UPDATE accounts SET acct_pin=%i WHERE acct_id=%i", Pin, AcctID);
+ int rv = Bank_int_QueryNone(gBank_Database, query, &errmsg);
+ if( rv != SQLITE_OK )
+ {
+ fprintf(stderr, "Bank_CreateAcct - SQLite Error: '%s'\n", errmsg);
+ fprintf(stderr, "Query = '%s'\n", query);
+ sqlite3_free(errmsg);
+ free(query);
+ return ;
+ }
+ free(query);
+}
/*
* Create an iterator for user accounts
*/
#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
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, ...);
{"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])))
}
}
+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 ;
+ }
+
+ // Check user permissions
+ if( !(Bank_GetFlags(Client->UID) & (USER_FLAG_COKE|USER_FLAG_ADMIN)) ) {
+ sendf(Client->Socket, "403 Not in coke\n");
+ return ;
+ }
+
+ // Get user
+ int uid = Bank_GetAcctByName(username, 0);
+ if( uid == -1 ) {
+ sendf(Client->Socket, "404 User '%s' not found\n", username);
+ 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, "403 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, ...)
{
return 0;
}
+