Bazaar/Protect : more work on Client/Server auth

Mostly ready besides database connection / registering

git-svn-id: svn://ultimatepp.org/upp/trunk@2763 f0d560ea-af0d-0410-9eb7-867de7ffcac7
This commit is contained in:
micio 2010-10-10 12:29:45 +00:00
parent 58bfefff23
commit 86b495890e
4 changed files with 214 additions and 49 deletions

View file

@ -38,7 +38,7 @@ VectorMap<String, Value> ProtectClient::SendMap(VectorMap<String, Value> const &
// copy vectormap adding client id and a magic number
VectorMap<String, Value>dataMap(v, 1);
dataMap.Add("APPID", "ProtectClient");
dataMap.Add("CLIENTID=", clientID);
dataMap.Add("CLIENTID", clientID);
// sets cypher key (and create a random IV)
cypher->SetKey(key);
@ -49,44 +49,48 @@ VectorMap<String, Value> ProtectClient::SendMap(VectorMap<String, Value> const &
postData += HexString((*cypher)(StoreAsXML(dataMap, "ProtectClient")));
client.Post(postData);
lastContents = client.ExecuteRedirect();
String contents = client.ExecuteRedirect();
// if contents start with "ERROR", just fetch the error desc
// and put it in result map
VectorMap<String, Value> resMap;
if(lastContents.StartsWith("ERROR="))
if(contents.StartsWith("ERROR="))
{
int i = lastContents.Find("\r");
int i = contents.Find("\r");
String s;
if(i >= 0)
s = lastContents.Mid(6, i - 6);
s = contents.Mid(6, i - 6);
else
s = lastContents.Mid(6);
resMap.Add("ERROR", s);
s = contents.Mid(6);
int errCode = atoi(~s);
resMap.Add("ERROR", errCode);
resMap.Add("ERRORMSG", ProtectMessage(errCode));
return resMap;
}
// otherwise, if lastContents don't start with IV field
// fetch the error from http client
if(!lastContents.StartsWith("IV="))
// signals it
if(!contents.StartsWith("IV="))
{
resMap.Add("ERROR", client.GetStatusLine());
resMap.Add("ERROR", PROTECT_MISSING_IV);
resMap.Add("ERRORMSG", ProtectMessage(PROTECT_MISSING_IV));
return resMap;
}
// well, we've at least the IV, so we can fetch it and DATA field and decrypt
StringStream s(lastContents);
StringStream s(contents);
String line = s.GetLine();
String IV = ScanHexString(line.Mid(3));
line = s.GetLine();
if(!line.StartsWith("DATA="))
{
resMap.Add("ERROR", "Missing DATA field");
resMap.Add("ERROR", PROTECT_BAD_DATA);
resMap.Add("ERRORMSG", ProtectMessage(PROTECT_BAD_DATA));
return resMap;
}
// decodes DATA field and read VectorMap from it
cypher->SetKey(key, IV);
String decoded = (*cypher)(line.Mid(5));
String decoded = (*cypher)(ScanHexString(line.Mid(5)));
try
{
LoadFromXML(resMap, decoded);
@ -94,25 +98,32 @@ VectorMap<String, Value> ProtectClient::SendMap(VectorMap<String, Value> const &
catch(...)
{
resMap.Clear();
resMap.Add("ERROR", "Bad DATA received");
resMap.Add("ERROR", PROTECT_BAD_DATA);
resMap.Add("ERRORMSG", ProtectMessage(PROTECT_BAD_DATA));
}
return resMap;
}
// create a persistent link to server
bool ProtectClient::Connect(int persistTime)
bool ProtectClient::Connect(void)
{
lastError = 0;
// if already connected, disconnect first
Disconnect();
if(!Disconnect())
return false;
// send a connect packet to server
VectorMap<String, Value>v;
v.Add("CONNECT", persistTime);
v.Add("REASON", ProtectReasonStr(PROTECT_CONNECT));
VectorMap<String, Value> res = SendMap(v);
// check for errors
if(res.Find("CONNECTED") < 0)
if(res.Find("ERROR") >= 0)
{
lastError = res.Get("ERROR");
return false;
}
connected = true;
return true;
@ -121,39 +132,124 @@ bool ProtectClient::Connect(int persistTime)
// disconnect from server
bool ProtectClient::Disconnect(void)
{
lastError = 0;
if(!connected)
return true;
// sends a disconnect packet to server
VectorMap<String, Value>v;
v.Add("DISCONNECT", "");
v.Add("REASON", ProtectReasonStr(PROTECT_DISCONNECT));
VectorMap<String, Value> res = SendMap(v);
// check for errors
if(res.Find("DISCONNECTED") < 0)
if(res.Find("ERROR") >= 0)
{
lastError = res.Get("ERROR");
return false;
}
connected = false;
return true;
}
// sends data and get response data
VectorMap<String, Value> ProtectClient::Send(VectorMap<String, Value> const &v)
// refresh server connection
bool ProtectClient::Refresh(void)
{
VectorMap<String, Value> res;
// checks if connection is established
if(!connected)
lastError = 0;
// sends a refresh packet to server
VectorMap<String, Value>v;
v.Add("REASON", ProtectReasonStr(PROTECT_REFRESH));
VectorMap<String, Value> res = SendMap(v);
// check for errors
if(res.Find("ERROR") >= 0)
{
res.Add("ERROR", "NOT CONNECTED TO SERVER");
return res;
lastError = res.Get("ERROR");
return false;
}
// send the map and get results
res = SendMap(v);
return true;
}
// get license key
String ProtectClient::GetKey(void)
{
lastError = 0;
// sends a getkey packet to server
VectorMap<String, Value>v;
v.Add("REASON", ProtectReasonStr(PROTECT_GETKEY));
VectorMap<String, Value> res = SendMap(v);
// check for errors
if(res.Find("ERROR") >= 0)
{
lastError = res.Get("ERROR");
return "";
}
if(res.Find("KEY") < 0)
{
lastError = 999;
return "";
}
return res.Get("KEY");
}
// gets license info
bool ProtectClient::GetLicenseInfo(void)
{
lastError = 0;
// sends a getinfo packet to server
VectorMap<String, Value>v;
v.Add("REASON", ProtectReasonStr(PROTECT_GETLICENSEINFO));
VectorMap<String, Value> res = SendMap(v);
// check for errors
if(res.Find("ERROR") >= 0)
{
lastError = res.Get("ERROR");
return false;
}
// return result map
return res;
if(res.Find("EMAIL") >= 0) userEMail = res.Get("USEREMAIL");
if(res.Find("USERNAME") >= 0) userName = res.Get("USERNAME");
if(res.Find("USERADDRESS") >= 0) userAddress = res.Get("USERADDRESS");
if(res.Find("USERCOUNTRY") >= 0) userCountry = res.Get("USERCOUNTRY");
if(res.Find("USERPHONE") >= 0) userPhone = res.Get("USERPHONE");
if(res.Find("USERFAX") >= 0) userFax = res.Get("USERFAX");
if(res.Find("USERCELL") >= 0) userCell = res.Get("USERCELL");
if(res.Find("EXPIRETIME") >= 0) expireTime = res.Get("EXPIRETIME");
if(res.Find("NUMLICENSES") >= 0) numLicenses = res.Get("NUMLICENSES");
return true;
}
// register app
bool ProtectClient::Register(void)
{
lastError = 0;
// sends a register packet to server
VectorMap<String, Value>v;
v.Add("REASON", ProtectReasonStr(PROTECT_REGISTER));
v.Add("EMAIL", userEMail);
v.Add("USERNAME", userName);
v.Add("USERADDRESS", userAddress);
v.Add("USERCOUNTRY", userCountry);
v.Add("USERPHONE", userPhone);
v.Add("USERFAX", userFax);
v.Add("USERCELL", userCell);
VectorMap<String, Value> res = SendMap(v);
// check for errors
if(res.Find("ERROR") >= 0)
{
lastError = res.Get("ERROR");
return false;
}
}
END_UPP_NAMESPACE

View file

@ -15,8 +15,8 @@ class ProtectClient
// the HTTP client
HttpClient client;
// last HTTP answer
String lastContents;
// last error code for failed operations
int lastError;
// the cypher -- can be changed between available
// in Cypher package
@ -28,6 +28,23 @@ class ProtectClient
// client id -- generated as random dword on creation
String clientID;
// license ID -- got from server upon registration
String licenseID;
// user data
String userEMail;
String userName;
String userAddress;
String userCountry;
String userZIP;
String userPhone;
String userFax;
String userCell;
// license expire time and number of them
Time expireTime;
int numLicenses;
// key and IV for encrypted communication
String key;
qword IV;
@ -57,22 +74,41 @@ class ProtectClient
// sets communication key
ProtectClient &SetKey(String const &_key) { key = _key; return *this; }
// read last HTTP answer got from server
// useful mostly for debugging purposes
String const &GetLastContents(void) { return lastContents; }
String GetLastHeaders(void) { return client.GetHeaders(); }
String GetLastStatus(void) { return client.GetStatusLine(); }
String GetLastError(void) { return client.GetError(); }
int GetLastStatusCode(void) { return client.GetStatusCode(); }
// read last error code and message
int GetLastError(void) { return lastError; }
String GetLastErrorMsg(void) { return ProtectMessage(lastError); }
// checks whether we're connected to server
bool IsConnected(void) { return connected; }
// create a persistent link to server
bool Connect(int persistTime);
bool Connect(void);
// disconnect from server
bool Disconnect(void);
// refresh server connection
bool Refresh(void);
// get license key
String GetKey(void);
// gets license info
bool GetLicenseInfo(void);
// register app
bool Register(void);
// sends data and get response data
VectorMap<String, Value> Send(VectorMap<String, Value> const &v);
// set user data -- for registration
// filled automatically by GETLICENSEINFO request
ProtectClient &SetUserEMail(String const &mail) { userEMail = mail; return *this; }
ProtectClient &SetUserName(String const &name) { userName = name; return *this; }
ProtectClient &SetUserAddress(String const &address) { userAddress = address; return *this; }
ProtectClient &SetUserCountry(String const &country) { userCountry = country; return *this; }
ProtectClient &SetUserZip(String const &zip) { userZIP = zip; return *this; }
ProtectClient &SetUserPhone(String const &phone) { userPhone = phone; return *this; }
ProtectClient &SetUserFax(String const &fax) { userFax = fax; return *this; }
ProtectClient &SetUserCell(String const &cell) { userCell = cell; return *this; }
};
END_UPP_NAMESPACE

View file

@ -103,7 +103,28 @@ void ProtectServer::OnRequest()
// GETKEY gets application key
// REGISTER registers app for timed demo
// GETLICENSEINFO gets info about license (name, expiration date, app version....)
VectorMap<String, Value> results = ProcessRequest(data);
if(data.Find("REASON") < 0 || data.Find("CLIENTID") < 0)
{
SendError(PROTECT_BAD_DATA);
return;
}
String ClientID = data.Get("CLIENTID");
int reason = ProtectReason(data.Get("REASON"));
if(reason < PROTECT_CONNECT || reason > PROTECT_GETLICENSEINFO)
{
SendError(PROTECT_BAD_DATA);
return;
}
if(reason != PROTECT_CONNECT && reason != PROTECT_REGISTER && !IsClientConnected(ClientID))
{
SendError(PROTECT_NOT_CONNECTED);
return;
}
VectorMap<String, Value> results = ProcessRequest(reason, data);
if(reason == PROTECT_CONNECT && results.Find("ERROR") < 0)
ConnectClient(ClientID);
else if(reason == PROTECT_DISCONNECT)
DisconnectClient(ClientID);
// encodes results and send back to client
cypher->SetKey(key);
@ -120,10 +141,22 @@ void ProtectServer::OnClosed()
// process client request
// takes a VectorMap<String, Value> on input from client
// produces a response VectorMap<String, Value> to be returned
VectorMap<String, Value> ProtectServer::ProcessRequest(VectorMap<String, Value> const &v)
VectorMap<String, Value> ProtectServer::ProcessRequest(int reason, VectorMap<String, Value> const &v)
{
// @@@@ TO DO - BY NOW JUST RETURN INPUT DATA
return VectorMap<String, Value>(v, 1);
VectorMap<String, Value> res;
switch(reason)
{
case PROTECT_REGISTER:
break;
case PROTECT_GETKEY:
res.Add("KEY", "THIS IS A DUMMY KEY");
break;
default:
break;
}
return res;
}
END_UPP_NAMESPACE

View file

@ -48,7 +48,7 @@ class ProtectServer : public ScgiServer
// process client request
// takes a VectorMap<String, Value> on input from client
// produces a response VectorMap<String, Value> to be returned
virtual VectorMap<String, Value> ProcessRequest(VectorMap<String, Value> const &v);
virtual VectorMap<String, Value> ProcessRequest(int reason, VectorMap<String, Value> const &v);
public: