=== User Auth ===
c USER <username>\n
s 100 SALT <string>\n or 100 User Set\n (If no salt used)
-c PASS <hash>\n (Hex-Encoded SHA-512 Hash of <username><salt><password>)
+c PASS <hash>\n (Hex-Encoded SHA-1 Hash of <username><salt><password>)
s 200 Auth OK\n or 401 Auth Failure\n
User is now authenticated
--- Alternate Method (Implicit Trust Authentication) ---
CFLAGS := -Wall -Werror -g
-LDFLAGS := -g -lncurses
+LDFLAGS := -g -lncurses -lssl
BIN := ../../dispense
OBJ := main.o
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
+#include <openssl/sha.h> // SHA1
// === TYPES ===
typedef struct sItem {
int giDispensePort = 11020;
tItem *gaItems;
int giNumItems;
-regex_t gArrayRegex;
-regex_t gItemRegex;
+regex_t gArrayRegex, gItemRegex, gSaltRegex;
// === CODE ===
int main(int argc, char *argv[])
CompileRegex(&gArrayRegex, "^([0-9]{3})\\s+([A-Za-z]+)\\s+([0-9]+)", REG_EXTENDED); //
// > Code Type Ident Price Desc
CompileRegex(&gItemRegex, "^([0-9]{3})\\s+(.+?)\\s+(.+?)\\s+([0-9]+)\\s+(.+)$", REG_EXTENDED);
+ // > Code 'SALT' salt
+ CompileRegex(&gSaltRegex, "^([0-9]{3})\\s+(.+)\\s+(.+)$", REG_EXTENDED);
// Connect to server
sock = OpenConnection(gsDispenseServer, giDispensePort);
printf("%3i %s\n", gaItems[i].Price, gaItems[i].Desc);
}
- Authenticate(sock);
-
// and choose what to dispense
// TODO: ncurses interface (with separation between item classes)
// - Hmm... that would require standardising the item ID to be <class>:<index>
}
#endif
+ Authenticate(sock);
+
if( i >= 0 )
{
// Dispense!
struct passwd *pwd;
char buf[512];
int responseCode;
+ char salt[32];
+ regmatch_t matches[4];
// Get user name
pwd = getpwuid( getuid() );
case 200: // Authenticated, return :)
return ;
case 401: // Untrusted, attempt password authentication
+ sendf(Socket, "USER %s\n", pwd->pw_name);
+ printf("Using username %s\n", pwd->pw_name);
+
+ recv(Socket, buf, 511, 0);
+ trim(buf);
+ // TODO: Get Salt
+ // Expected format: 100 SALT <something> ...
+ // OR : 100 User Set
+ printf("string = '%s'\n", buf);
+ RunRegex(&gSaltRegex, buf, 4, matches, "Malformed server response");
+ if( atoi(buf) != 100 ) {
+ exit(-1); // ERROR
+ }
+ if( memcmp( buf+matches[2].rm_so, "SALT", matches[2].rm_eo - matches[2].rm_so) == 0) {
+ // Set salt
+ memcpy( salt, buf + matches[3].rm_so, matches[3].rm_eo - matches[3].rm_so );
+ salt[ matches[3].rm_eo - matches[3].rm_so ] = 0;
+ printf("Salt: '%s'\n", salt);
+ }
+
+ fflush(stdout);
+ {
+ int ofs = strlen(pwd->pw_name)+strlen(salt);
+ char tmp[ofs+20];
+ char *pass = getpass("Password: ");
+ uint8_t h[20];
+
+ strcpy(tmp, pwd->pw_name);
+ strcat(tmp, salt);
+ SHA1( (unsigned char*)pass, strlen(pass), h );
+ memcpy(tmp+ofs, h, 20);
+
+ // Hash all that
+ SHA1( (unsigned char*)tmp, ofs+20, h );
+ sprintf(buf, "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x",
+ h[ 0], h[ 1], h[ 2], h[ 3], h[ 4], h[ 5], h[ 6], h[ 7], h[ 8], h[ 9],
+ h[10], h[11], h[12], h[13], h[14], h[15], h[16], h[17], h[18], h[19]
+ );
+ printf("Final hash: '%s'\n", buf);
+ fflush(stdout); // Debug
+ }
+
+ sendf(Socket, "PASS %s\n", buf);
+ recv(Socket, buf, 511, 0);
break;
case 404: // Bad Username
fprintf(stderr, "Bad Username '%s'\n", pwd->pw_name);
#include <stdio.h>
#include <pwd.h>
#include <string.h>
+#include <openssl/sha.h>
#include "common.h"
#define HACK_TPG_NOAUTH 1
return ret;
}
-/**
- * \brief Authenticate a user
- * \return User ID, or -1 if authentication failed
- */
-int GetUserAuth(const char *Username, const char *Password)
-{
- #if HACK_TPG_NOAUTH
- if( strcmp(Username, "tpg") == 0 )
- return GetUserID("tpg");
- #endif
- return -1;
-}
-
OBJ := main.o server.o logging.o
OBJ += dispense.o itemdb.o
-OBJ += handler_coke.o handler_snack.o
+OBJ += handler_coke.o handler_snack.o handler_door.o
BIN := ../../dispsrv
LINKFLAGS := -g ../../cokebank.so
extern int GetBalance(int User);
extern char *GetUserName(int User);
extern int GetUserID(const char *Username);
-extern int GetUserAuth(const char *Username, const char *Password);
#endif
*/
int Door_DoDispense(int User, int Item)
{
- char tmp[32], *status;
- regmatch_t matches[4];
// Sanity please
if( Item != 0 ) return -1;
+ // Check if user is in door
+
// llogin or other
return 0;
char *Server_Cmd_ITEMINFO(tClient *Client, char *Args);
char *Server_Cmd_DISPENSE(tClient *Client, char *Args);
// --- Helpers ---
+ int GetUserAuth(const char *Salt, const char *Username, const uint8_t *Hash);
void HexBin(uint8_t *Dest, char *Src, int BufSize);
// === GLOBALS ===
// TODO: Decrypt password passed
- Client->UID = GetUserAuth(Client->Username, "");
+ Client->UID = GetUserAuth(Client->Salt, Client->Username, clienthash);
if( Client->UID != -1 ) {
Client->bIsAuthed = 1;
}
}
+/**
+ * \brief Authenticate a user
+ * \return User ID, or -1 if authentication failed
+ */
+int GetUserAuth(const char *Salt, const char *Username, const uint8_t *ProvidedHash)
+{
+ #if 0
+ uint8_t h[20];
+ int ofs = strlen(Username) + strlen(Salt);
+ char input[ ofs + 40 + 1];
+ char tmp[4 + strlen(Username) + 1]; // uid=%s
+ #endif
+
+ #if HACK_TPG_NOAUTH
+ if( strcmp(Username, "tpg") == 0 )
+ return GetUserID("tpg");
+ #endif
+
+ #if 0
+ //
+ strcpy(input, Username);
+ strcpy(input, Salt);
+ // TODO: Get user's SHA-1 hash
+ sprintf(tmp, "uid=%s", Username);
+ ldap_search_s(ld, "", LDAP_SCOPE_BASE, tmp, "userPassword", 0, res);
+
+ sprintf(input+ofs, "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x",
+ h[ 0], h[ 1], h[ 2], h[ 3], h[ 4], h[ 5], h[ 6], h[ 7], h[ 8], h[ 9],
+ h[10], h[11], h[12], h[13], h[14], h[15], h[16], h[17], h[18], h[19]
+ );
+ // Then create the hash from the provided salt
+ // Compare that with the provided hash
+ #endif
+
+ return -1;
+}
+
// --- INTERNAL HELPERS ---
// TODO: Move to another file
void HexBin(uint8_t *Dest, char *Src, int BufSize)