mirror of
https://github.com/ultimatepp/ultimatepp.git
synced 2026-08-12 06:12:46 -06:00
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:
parent
58bfefff23
commit
86b495890e
4 changed files with 214 additions and 49 deletions
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue