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_AUTHCARD(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);
void Server_Cmd_UPDATEITEM(tClient *Client, char *Args);
void Server_Cmd_PINCHECK(tClient *Client, char *Args);
void Server_Cmd_PINSET(tClient *Client, char *Args);
+void Server_Cmd_CARDADD(tClient *Client, char *Args);
// --- Helpers ---
void Debug(tClient *Client, const char *Format, ...);
int sendf(int Socket, const char *Format, ...);
int Server_int_ParseArgs(int bUseLongArg, char *ArgStr, ...);
int Server_int_ParseFlags(tClient *Client, const char *Str, int *Mask, int *Value);
+#define CLIENT_DEBUG_LOW(Client, ...) do { if(giDebugLevel>1) Debug(Client, __VA_ARGS__); } while(0)
+#define CLIENT_DEBUG(Client, ...) do { if(giDebugLevel) Debug(Client, __VA_ARGS__); } while(0)
+
// === CONSTANTS ===
// - Commands
const struct sClientCommand {
{"PASS", Server_Cmd_PASS},
{"AUTOAUTH", Server_Cmd_AUTOAUTH},
{"AUTHIDENT", Server_Cmd_AUTHIDENT},
+ {"AUTHCARD", Server_Cmd_AUTHCARD},
{"SETEUSER", Server_Cmd_SETEUSER},
{"ENUM_ITEMS", Server_Cmd_ENUMITEMS},
{"ITEM_INFO", Server_Cmd_ITEMINFO},
{"USER_FLAGS", Server_Cmd_USERFLAGS},
{"UPDATE_ITEM", Server_Cmd_UPDATEITEM},
{"PIN_CHECK", Server_Cmd_PINCHECK},
- {"PIN_SET", Server_Cmd_PINSET}
+ {"PIN_SET", Server_Cmd_PINSET},
+ {"CARD_ADD", Server_Cmd_CARDADD},
};
#define NUM_COMMANDS ((int)(sizeof(gaServer_Commands)/sizeof(gaServer_Commands[0])))
gaServer_TrustedHosts = malloc(giServer_NumTrustedHosts * sizeof(*gaServer_TrustedHosts));
for( int i = 0; i < giServer_NumTrustedHosts; i ++ )
{
- const char *addr = Config_GetValue("trusted_host", i);
+ const char *addr = Config_GetValue_Idx("trusted_host", i);
if( inet_aton(addr, &gaServer_TrustedHosts[i]) == 0 ) {
fprintf(stderr, "Invalid IP address '%s'\n", addr);
#endif
}
+/// UID: User ID (must be valid)
+/// username: Optional username
+bool authenticate(tClient* Client, int UID, const char* username)
+{
+ Client->UID = UID;
+
+ int flags = Bank_GetFlags(Client->UID);
+ if( flags & USER_FLAG_DISABLED ) {
+ Client->UID = -1;
+ sendf(Client->Socket, "403 Authentication failure: account disabled\n");
+ return false;
+ }
+ // You can't be an internal account
+ if( flags & 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");
+ return false;
+ }
+
+ // Save username
+ if(Client->Username != username)
+ {
+ if(Client->Username)
+ {
+ free(Client->Username);
+ }
+
+ // Fetch username (if not provided)
+ if( username )
+ {
+ Client->Username = strdup(username);
+ }
+ else
+ {
+ Client->Username = Bank_GetAcctName(UID);
+ }
+ }
+
+ Client->bIsAuthed = 1;
+
+ if(giDebugLevel)
+ Debug(Client, "Auto authenticated as '%s' (%i)", Client->Username, Client->UID);
+ return true;
+}
+bool require_auth(tClient* Client)
+{
+ // Check authentication
+ if( !Client->bIsAuthed ) {
+ sendf(Client->Socket, "401 Not Authenticated\n");
+ return false;
+ }
+ return true;
+}
+
/**
* \brief Authenticate as a user
*
void Server_Cmd_PASS(tClient *Client, char *Args)
{
char *passhash;
- int flags;
if( Server_int_ParseArgs(0, Args, &passhash, NULL) )
{
}
// Pass on to cokebank
- Client->UID = Bank_GetUserAuth(Client->Salt, Client->Username, passhash);
-
- if( Client->UID == -1 ) {
- sendf(Client->Socket, "401 Auth Failure\n");
- return ;
- }
-
- flags = Bank_GetFlags(Client->UID);
- if( flags & USER_FLAG_DISABLED ) {
- Client->UID = -1;
- sendf(Client->Socket, "403 Account Disabled\n");
+ int uid = Bank_GetUserAuth(Client->Salt, Client->Username, passhash);
+ if( uid < 0 ) {
+ if(giDebugLevel)
+ Debug(Client, "Unknown user '%s'", Client->Username);
+ sendf(Client->Socket, "403 Authentication failure: unknown account\n");
return ;
}
- if( flags & USER_FLAG_INTERNAL ) {
- Client->UID = -1;
- sendf(Client->Socket, "403 Internal account\n");
- return ;
+ if( ! authenticate(Client, uid, Client->Username) )
+ {
+ return;
}
-
- Client->bIsAuthed = 1;
sendf(Client->Socket, "200 Auth OK\n");
}
void Server_Cmd_AUTOAUTH(tClient *Client, char *Args)
{
char *username;
- int userflags;
if( Server_int_ParseArgs(0, Args, &username, NULL) )
{
}
// Get UID
- Client->UID = Bank_GetAcctByName( username, 0 );
- if( Client->UID < 0 ) {
+ int uid = Bank_GetAcctByName( username, /*bCreate=*/0 );
+ if( uid < 0 ) {
if(giDebugLevel)
Debug(Client, "Unknown user '%s'", username);
- sendf(Client->Socket, "403 Auth Failure\n");
- return ;
- }
-
- userflags = Bank_GetFlags(Client->UID);
- // You can't be an internal account
- if( userflags & USER_FLAG_INTERNAL ) {
- if(giDebugLevel)
- Debug(Client, "Autoauth as '%s', not allowed", username);
- Client->UID = -1;
- sendf(Client->Socket, "403 Account is internal\n");
+ sendf(Client->Socket, "403 Authentication failure: unknown account\n");
return ;
}
-
- // Disabled accounts
- if( userflags & USER_FLAG_DISABLED ) {
- Client->UID = -1;
- sendf(Client->Socket, "403 Account disabled\n");
- return ;
+ if( ! authenticate(Client, uid, username) )
+ {
+ return;
}
-
- // Save username
- if(Client->Username)
- free(Client->Username);
- Client->Username = strdup(username);
-
- Client->bIsAuthed = 1;
-
- if(giDebugLevel)
- Debug(Client, "Auto authenticated as '%s' (%i)", username, Client->UID);
sendf(Client->Socket, "200 Auth OK\n");
}
void Server_Cmd_AUTHIDENT(tClient *Client, char *Args)
{
char *username;
- int userflags;
- const int ident_timeout = 5;
+ const int IDENT_TIMEOUT = 5;
if( Args != NULL && strlen(Args) ) {
sendf(Client->Socket, "407 AUTHIDENT takes no arguments\n");
}
// Get username via IDENT
- username = ident_id(Client->Socket, ident_timeout);
+ username = ident_id(Client->Socket, IDENT_TIMEOUT);
if( !username ) {
perror("AUTHIDENT - IDENT timed out");
sendf(Client->Socket, "403 Authentication failure: IDENT auth timed out\n");
return ;
}
- // Get UID
- Client->UID = Bank_GetAcctByName( username, 0 );
- if( Client->UID < 0 ) {
+ int uid = Bank_GetAcctByName(username, /*bCreate=*/0);
+ if( 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");
+ if( ! authenticate(Client, uid, username) )
+ {
free(username);
return ;
}
+ free(username);
- // Disabled accounts
- if( userflags & USER_FLAG_DISABLED ) {
- Client->UID = -1;
- sendf(Client->Socket, "403 Authentication failure: account disabled\n");
- free(username);
+ sendf(Client->Socket, "200 Auth OK\n");
+}
+
+void Server_Cmd_AUTHCARD(tClient* Client, char *Args)
+{
+ char* card_id;
+ if( Server_int_ParseArgs(0, Args, &card_id, NULL) )
+ {
+ sendf(Client->Socket, "407 AUTHCARD takes 1 argument\n");
return ;
}
- // Save username
- if(Client->Username)
- free(Client->Username);
- Client->Username = strdup(username);
-
- Client->bIsAuthed = 1;
+ // Check if trusted (has to be root)
+ if( Client->UID != 1 )
+ {
+ if(giDebugLevel)
+ Debug(Client, "Attempting to use AUTHCARD as non-root");
+ sendf(Client->Socket, "401 Untrusted\n");
+ return ;
+ }
- if(giDebugLevel)
- Debug(Client, "IDENT authenticated as '%s' (%i)", username, Client->UID);
- free(username);
+ CLIENT_DEBUG(Client, "MIFARE auth with '%s'", card_id);
+ int uid = Bank_GetAcctByCard(card_id);
+ if( uid < 0 )
+ {
+ if(giDebugLevel)
+ Debug(Client, "Unknown MIFARE '%s'", card_id);
+ sendf(Client->Socket, "403 Authentication failure: unknown MIFARE ID\n");
+ return ;
+ }
+ if( ! authenticate(Client, uid, NULL) )
+ {
+ return ;
+ }
- sendf(Client->Socket, "200 Auth OK\n");
+ sendf(Client->Socket, "200 Auth Ok, username=%s\n", Client->Username);
}
/**
}
// Check authentication
- if( !Client->bIsAuthed ) {
- sendf(Client->Socket, "401 Not Authenticated\n");
- return ;
- }
+ if(!require_auth(Client)) return;
// Check permissions
if( !(Bank_GetFlags(Client->UID) & USER_FLAG_ADMIN) ) {
sendf(Client->Socket, "407 UPDATE_ITEM takes 3 arguments\n");
return ;
}
-
- if( !Client->bIsAuthed ) {
- sendf(Client->Socket, "401 Not Authenticated\n");
- return ;
- }
+
+ if(!require_auth(Client)) return;
// Check user permissions
if( !(Bank_GetFlags(Client->UID) & (USER_FLAG_COKE|USER_FLAG_ADMIN)) ) {
}
pin = atoi(pinstr);
- // Not authenticated? go away!
- if( !Client->bIsAuthed ) {
- sendf(Client->Socket, "401 Not Authenticated\n");
- return ;
- }
+ if(!require_auth(Client)) return;
// Get user
int uid = Bank_GetAcctByName(username, 0);
last_wrong_pin_time = time(NULL);
if( !Bank_IsPinValid(uid, pin) )
{
- sendf(Client->Socket, "201 Pin incorrect\n");
+ sendf(Client->Socket, "401 Pin incorrect\n");
struct sockaddr_storage addr;
socklen_t len = sizeof(addr);
char ipstr[INET6_ADDRSTRLEN];
}
pin = atoi(pinstr);
- if( !Client->bIsAuthed ) {
- sendf(Client->Socket, "401 Not Authenticated\n");
- return ;
- }
+ if(!require_auth(Client)) return;
- int uid = Client->EffectiveUID;
- if(uid == -1)
- uid = Client->UID;
+ int uid = Client->EffectiveUID > 0 ? Client->EffectiveUID : Client->UID;
+ CLIENT_DEBUG(Client, "Setting PIN for UID %i", uid);
// Can only pinset yourself (well, the effective user)
Bank_SetPin(uid, pin);
sendf(Client->Socket, "200 Pin updated\n");
return ;
}
+void Server_Cmd_CARDADD(tClient* Client, char* Args)
+{
+ char* card_id;
+ if( Server_int_ParseArgs(0, Args, &card_id, NULL) ) {
+ sendf(Client->Socket, "407 CARD_ADD takes 1 argument\n");
+ return ;
+ }
+
+ if(!require_auth(Client)) return;
+
+ int uid = Client->EffectiveUID > 0 ? Client->EffectiveUID : Client->UID;
+ CLIENT_DEBUG(Client, "Add card '%s' to UID %i", card_id, uid);
+ if( Bank_AddAcctCard(uid, card_id) )
+ {
+ sendf(Client->Socket, "408 Card already exists\n");
+ return ;
+ }
+ sendf(Client->Socket, "200 Card added\n");
+}
// --- INTERNAL HELPERS ---
void Debug(tClient *Client, const char *Format, ...)