1 
2 module mars.protoauth;
3 
4 import std.algorithm;
5 import std.ascii;
6 import std.random;
7 import std.range;
8 import std.digest.sha;
9 import std..string;
10 import std.experimental.logger;
11 import vibe.core.log;
12 
13 import mars.msg;
14 import mars.client;
15 import mars.server;
16 
17 void protoAuth(S)(MarsClient* client, S socket)
18 {
19     import msgpack : unpack, pack;
20 
21 
22     auto authenticationRequest = socket.binaryAs!AuthenticationRequest;
23     string username = authenticationRequest.username;
24 
25     // reject multiple authentication request ...
26     if( client.authorised ){
27         socket.sendReply(authenticationRequest, AuthenticationReply(AuthenticationReply.alreadyAuthorised));
28         return;
29     }
30 
31     // empty username, not allowed ...
32     if( username == "" ){
33         socket.sendReply(authenticationRequest, AuthenticationReply(AuthenticationReply.invalidUsername));
34         return;
35     }
36 
37 
38     auto seed = letters.length
39         .iota
40         .randomSample(10)
41         .map!( i => letters[i] )
42         .array;
43     socket.sendReply(authenticationRequest, AuthenticationReply(AuthenticationReply.seedProvided, seed));
44     auto authenticateRequest = socket.receiveMsg!AuthenticateRequest;
45     logInfo("S <-- %s | authenticate request, hash:%s", client.id, authenticateRequest.hash);
46 
47     // ... right now, we can't pass the hash to postgres, so ...
48     string hash256, password = "password";
49     if     ( username == "dev"    ){ password = "password"; }
50     else if( username == "pinver" ){ password = "arathorn"; }
51     else if( username == "elisa"  ){ password = "seta"; }
52     else if( username == "chiara" ){ password = "velluto"; }
53     else if( username == "a.liu"  ){ password = "2tuxeSeseswa"; }
54 
55     bool authorised = authenticateRequest.hash.toUpper() == sha256Of(seed ~ sha256Of(password).toHexString()).toHexString();
56     if(authorised){
57         AuthoriseError dbAuthorised = client.authoriseUser(username, password) ;
58 
59         auto reply = AuthenticateReply(cast(int)dbAuthorised, "", []);
60 
61         if( dbAuthorised == AuthoriseError.authorised ){
62             reply.sqlCreateDatabase = marsServer.configuration.alasqlCreateDatabase;
63             reply.sqlStatements = marsServer.configuration.alasqlStatements;
64             reply.jsStatements = marsServer.configuration.jsStatements;
65 
66             // ... now that the client is authorised, expose the data to it
67             marsServer.createClientSideTablesFor(client);
68         }
69 
70         logInfo("S --> %s | authenticate reply, authorised:%s", client.id, dbAuthorised);
71         socket.sendReply(authenticateRequest, reply);
72     }
73     else {
74         logInfo("S --> %s | authenticate reply, authorised:%s (web password hash failed)", client.id, false);
75         auto reply = AuthenticateReply(cast(int)AuthoriseError.wrongUsernameOrPassword, "", []);
76         socket.sendReply(authenticateRequest, reply);
77     }
78 
79     // ... try the push from the server, a new client has connected ...
80     //if(dbAuthorised == AuthoriseError.authorised) marsServer.broadcast(WelcomeBroadcast(username));
81 }
82 
83 void protoDeauth(S)(MarsClient* client, S socket)
84 {
85     marsServer.wipeClientSideTablesFor(client);
86     auto request = socket.binaryAs!DiscardAuthenticationRequest;
87     client.discardAuthorisation();
88     auto reply = DiscardAuthenticationReply();
89     socket.sendReply(request, reply);
90 
91     //marsServer.broadcast(GoodbyBroadcast("theusename"));
92 }
93 
94 struct WelcomeBroadcast { static immutable type = MsgType.welcomeBroadcast; string username; }
95 struct GoodbyBroadcast { static immutable type = MsgType.goodbyBroadcast; string username; }