+/**
+ * \brief Authenticate as a user using the IDENT protocol
+ *
+ * Usage: AUTHIDENT
+ */
+void Server_Cmd_AUTHIDENT(tClient *Client, char *Args)
+{
+ char *username;
+ const int IDENT_TIMEOUT = 5;
+
+ if( Args != NULL && strlen(Args) ) {
+ sendf(Client->Socket, "407 AUTHIDENT takes no arguments\n");
+ return ;
+ }
+
+ // Check if trusted
+ if( !Client->bTrustedHost ) {
+ if(giDebugLevel)
+ Debug(Client, "Untrusted client attempting to AUTHIDENT");
+ sendf(Client->Socket, "401 Untrusted\n");
+ return ;
+ }
+
+ // Get username via IDENT
+ 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 ;
+ }
+
+ 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 ;
+ }
+ if( ! authenticate(Client, uid, username) )
+ {
+ free(username);
+ return ;
+ }
+ 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 ;
+ }
+
+ // 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 ;
+ }
+
+ 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, username=%s\n", Client->Username);
+}
+
+/**
+ * \brief Set effective user
+ */
+void Server_Cmd_SETEUSER(tClient *Client, char *Args)
+{
+ char *username;
+ int eUserFlags, userFlags;
+
+ if( Server_int_ParseArgs(0, Args, &username, NULL) )
+ {
+ sendf(Client->Socket, "407 SETEUSER takes 1 argument\n");
+ return ;
+ }
+
+ if( !strlen(Args) ) {
+ sendf(Client->Socket, "407 SETEUSER expects an argument\n");
+ return ;
+ }
+
+ // Check authentication
+ if( !Client->bIsAuthed ) {
+ sendf(Client->Socket, "401 Not Authenticated\n");
+ return ;
+ }
+
+ // Check user permissions
+ userFlags = Bank_GetFlags(Client->UID);
+ if( !(userFlags & (USER_FLAG_COKE|USER_FLAG_ADMIN)) ) {
+ sendf(Client->Socket, "403 Not in coke\n");
+ return ;
+ }
+
+ // Set id
+ Client->EffectiveUID = Bank_GetAcctByName(username, 0);
+ if( Client->EffectiveUID == -1 ) {
+ sendf(Client->Socket, "404 User not found\n");
+ return ;
+ }
+ // You can't be an internal account (unless you're an admin)
+ if( !(userFlags & USER_FLAG_ADMIN) )
+ {
+ eUserFlags = Bank_GetFlags(Client->EffectiveUID);
+ if( eUserFlags & USER_FLAG_INTERNAL ) {
+ Client->EffectiveUID = -1;
+ sendf(Client->Socket, "404 User not found\n");
+ return ;
+ }
+ }
+
+ // Disabled accounts
+ // - 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, "200 User set\n");
+}
+
+/**
+ * \brief Send an item status to the client
+ * \param Client Who to?
+ * \param Item Item to send
+ */
+void Server_int_SendItem(tClient *Client, tItem *Item)
+{
+ char *status = "avail";
+
+ if( Item->Handler->CanDispense )
+ {
+ switch(Item->Handler->CanDispense(Client->UID, Item->ID))
+ {
+ case 0: status = "avail"; break;
+ case 1: status = "sold"; break;
+ default:
+ case -1: status = "error"; break;
+ }
+ }
+
+ if( !gbNoCostMode && Item->Price == 0 )
+ status = "error";
+ // KNOWN HACK: Naming a slot 'dead' disables it
+ if( strcmp(Item->Name, "dead") == 0 )
+ status = "sold"; // Another status?
+
+ sendf(Client->Socket,
+ "202 Item %s:%i %s %i %s\n",
+ Item->Handler->Name, Item->ID, status, Item->Price, Item->Name
+ );
+}
+