mirror of
https://github.com/ultimatepp/ultimatepp.git
synced 2026-05-17 06:06:00 -06:00
Bazaar/Protect : more features and bugfixes
git-svn-id: svn://ultimatepp.org/upp/trunk@2777 f0d560ea-af0d-0410-9eb7-867de7ffcac7
This commit is contained in:
parent
b7133c97bc
commit
ae32efdfbb
8 changed files with 264 additions and 44 deletions
|
|
@ -2,9 +2,9 @@ description "Software copy protection module\377";
|
|||
|
||||
uses
|
||||
Core,
|
||||
ScgiServer,
|
||||
Cypher,
|
||||
MySql;
|
||||
MySql,
|
||||
Web;
|
||||
|
||||
file
|
||||
ProtectStatus.h,
|
||||
|
|
|
|||
|
|
@ -91,13 +91,14 @@ bool ProtectClient::Connect(void)
|
|||
{
|
||||
lastError = 0;
|
||||
|
||||
// if already connected, disconnect first
|
||||
// disconnect first, im case we're already connected
|
||||
Disconnect();
|
||||
|
||||
// send a connect packet to server
|
||||
VectorMap<String, Value>v;
|
||||
v.Add("REASON", PROTECT_CONNECT);
|
||||
v.Add("EMAIL", userEMail);
|
||||
v.Add("CLIENTID", (int)clientID);
|
||||
VectorMap<String, Value> res = SendMap(v);
|
||||
|
||||
// check for errors
|
||||
|
|
@ -204,9 +205,8 @@ bool ProtectClient::GetLicenseInfo(void)
|
|||
lastError = res.Get("ERROR");
|
||||
return false;
|
||||
}
|
||||
|
||||
if(res.Find("EMAIL") >= 0) userEMail = res.Get("EMAIL");
|
||||
if(res.Find("USERNAME") >= 0) userName = res.Get("NAME");
|
||||
if(res.Find("NAME") >= 0) userName = res.Get("NAME");
|
||||
if(res.Find("ADDRESS") >= 0) userAddress = res.Get("ADDRESS");
|
||||
if(res.Find("COUNTRY") >= 0) userCountry = res.Get("COUNTRY");
|
||||
if(res.Find("ZIP") >= 0) userZIP = res.Get("ZIP");
|
||||
|
|
@ -219,6 +219,34 @@ bool ProtectClient::GetLicenseInfo(void)
|
|||
return true;
|
||||
}
|
||||
|
||||
// updates user data on server
|
||||
bool ProtectClient::UpdateUserData(void)
|
||||
{
|
||||
lastError = 0;
|
||||
|
||||
// sends a register packet to server
|
||||
VectorMap<String, Value>v;
|
||||
v.Add("REASON", PROTECT_UPDATEUSERDATA);
|
||||
v.Add("CLIENTID", (int)clientID);
|
||||
v.Add("EMAIL", userEMail);
|
||||
v.Add("NAME", userName);
|
||||
v.Add("ADDRESS", userAddress);
|
||||
v.Add("COUNTRY", userCountry);
|
||||
v.Add("ZIP", userZIP);
|
||||
v.Add("PHONE", userPhone);
|
||||
v.Add("FAX", userFax);
|
||||
v.Add("CELL", userCell);
|
||||
VectorMap<String, Value> res = SendMap(v);
|
||||
|
||||
// check for errors
|
||||
if(res.Find("ERROR") >= 0)
|
||||
{
|
||||
lastError = res.Get("ERROR");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// register app
|
||||
bool ProtectClient::Register(void)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -87,6 +87,9 @@ class ProtectClient
|
|||
// gets license info
|
||||
bool GetLicenseInfo(void);
|
||||
|
||||
// updates user data on server
|
||||
bool UpdateUserData(void);
|
||||
|
||||
// register app
|
||||
bool Register(void);
|
||||
|
||||
|
|
@ -100,6 +103,15 @@ class ProtectClient
|
|||
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; }
|
||||
|
||||
String GetUserEMail(void) { return userEMail; }
|
||||
String GetUserName(void) { return userName; }
|
||||
String GetUserAddress(void) { return userAddress; }
|
||||
String GetUserCountry(void) { return userCountry; }
|
||||
String GetUserZip(void) { return userZIP; }
|
||||
String GetUserPhone(void) { return userPhone; }
|
||||
String GetUserFax(void) { return userFax; }
|
||||
String GetUserCell(void) { return userCell; }
|
||||
};
|
||||
|
||||
END_UPP_NAMESPACE
|
||||
|
|
|
|||
|
|
@ -109,7 +109,7 @@ dword ProtectServer::ConnectClient(String const &eMail)
|
|||
{
|
||||
id = Random();
|
||||
}
|
||||
while(clientLinks.Find(id) >= 0);
|
||||
while(id == 0 || id == -1 || clientLinks.Find(id) >= 0);
|
||||
|
||||
// adds to clientLinks and to registered emails count
|
||||
clientLinks.Add(id, TimeMail(GetSysTime() + clientTimeout, eMail));
|
||||
|
|
@ -151,34 +151,50 @@ void ProtectServer::OnRequest()
|
|||
int err = 0;
|
||||
VectorMap<String, Value> data;
|
||||
VectorMap<String, Value> results;
|
||||
String IV;
|
||||
|
||||
clientSock.Write("Content-Type: text/plain\r\n\r\n");
|
||||
|
||||
// ignore requests without post data
|
||||
if(!HasPostData())
|
||||
err = PROTECT_BAD_REQUEST;
|
||||
// post data should contain at least an IV field and a DATA field
|
||||
else if(post.Find("IV") < 0 || post.Find("DATA") < 0)
|
||||
err = PROTECT_MISSING_IV;
|
||||
else
|
||||
// POST rwquest ?
|
||||
if(HasPostData())
|
||||
{
|
||||
// gets IV and setup the cypher to decrypt DATA field
|
||||
String IV = ScanHexString(post.GetString("IV"));
|
||||
cypher->SetKey(key, IV);
|
||||
|
||||
// decrypts DATA field and build its vectormap
|
||||
String decoded;
|
||||
try
|
||||
// all requests besides PROTECT_ACTIVATE go through post
|
||||
if(post.Find("IV") < 0)
|
||||
err = PROTECT_MISSING_IV;
|
||||
else
|
||||
{
|
||||
decoded = (*cypher)(ScanHexString(post.GetString("DATA")));
|
||||
LoadFromXML(data, decoded);
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
err = PROTECT_BAD_DATA;
|
||||
IV = ScanHexString(post.GetString("IV"));
|
||||
if(post.Find("DATA") < 0)
|
||||
err = PROTECT_MISSING_DATA;
|
||||
else
|
||||
{
|
||||
cypher->SetKey(key, IV);
|
||||
String decoded = (*cypher)(ScanHexString(post.GetString("DATA")));
|
||||
LoadFromXML(data, decoded);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// GET rwquest ?
|
||||
else if(query.GetCount())
|
||||
{
|
||||
// here should come just PROTECT_ACTIVATE requests
|
||||
if(query.Find("IV") < 0)
|
||||
err = PROTECT_MISSING_IV;
|
||||
else
|
||||
{
|
||||
IV = ScanHexString(query.GetString("IV"));
|
||||
if(query.Find("DATA") < 0)
|
||||
err = PROTECT_MISSING_DATA;
|
||||
else
|
||||
{
|
||||
cypher->SetKey(key, IV);
|
||||
String decoded = (*cypher)(ScanHexString(query.GetString("DATA")));
|
||||
LoadFromXML(data, decoded);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
err = PROTECT_BAD_REQUEST;
|
||||
|
||||
|
||||
// Get request reason and process it
|
||||
// supports following reasons :
|
||||
// CONNECT establish connection to server
|
||||
|
|
@ -201,11 +217,28 @@ void ProtectServer::OnRequest()
|
|||
else if(results.Find("ERROR") >= 0)
|
||||
results.Add("ERRORMSG", ProtectMessage(results.Get("ERROR")));
|
||||
|
||||
// encodes results and send back to client
|
||||
cypher->SetKey(key);
|
||||
clientSock.Write("IV=" + HexString(cypher->GetNonce()) + "\r\n");
|
||||
String encoded = HexString((*cypher)(StoreAsXML(results, "ProtectServer")));
|
||||
clientSock.Write("DATA=" + encoded + "\r\n");
|
||||
// if not ACTIVATION REQUEST encodes results and send back to client
|
||||
if(data.Get("REASON") != PROTECT_ACTIVATE)
|
||||
{
|
||||
clientSock.Write("Content-Type: text/plain\r\n\r\n");
|
||||
cypher->SetKey(key);
|
||||
clientSock.Write("IV=" + HexString(cypher->GetNonce()) + "\r\n");
|
||||
String encoded = HexString((*cypher)(StoreAsXML(results, "ProtectServer")));
|
||||
clientSock.Write("DATA=" + encoded + "\r\n");
|
||||
}
|
||||
// otherwise send a fancy welcome html -- replacing %NAME% with user name
|
||||
else
|
||||
{
|
||||
String w;
|
||||
clientSock.Write("Content-Type: text/html\r\n\r\n");
|
||||
if(results.Find("ERROR") >= 0)
|
||||
w = welcome;
|
||||
else
|
||||
w = activationFailed;
|
||||
data = db.Get(data.Get("EMAIL"));
|
||||
w.Replace("%USER%", data.Get("NAME"));
|
||||
clientSock.Write(w);
|
||||
}
|
||||
}
|
||||
|
||||
void ProtectServer::OnClosed()
|
||||
|
|
@ -222,6 +255,7 @@ VectorMap<String, Value> ProtectServer::ProcessRequest(int reason, VectorMap<Str
|
|||
dword clientID;
|
||||
VectorMap<String, Value> userRec;
|
||||
String eMail;
|
||||
String activationKey;
|
||||
int numConnections;
|
||||
|
||||
switch(reason)
|
||||
|
|
@ -258,6 +292,7 @@ VectorMap<String, Value> ProtectServer::ProcessRequest(int reason, VectorMap<Str
|
|||
{
|
||||
// new registration
|
||||
db.Set(vs);
|
||||
userRec = db.Get(eMail);
|
||||
if(SendActivationMail(userRec))
|
||||
res.Add("STATUS", "ACTIVATION RESENT");
|
||||
else
|
||||
|
|
@ -286,6 +321,39 @@ VectorMap<String, Value> ProtectServer::ProcessRequest(int reason, VectorMap<Str
|
|||
}
|
||||
}
|
||||
break;
|
||||
case PROTECT_ACTIVATE:
|
||||
// we need email to activate
|
||||
if(v.Find("EMAIL") < 0)
|
||||
{
|
||||
res.Add("ERROR", PROTECT_MISSING_EMAIL);
|
||||
return res;
|
||||
}
|
||||
eMail = v.Get("EMAIL");
|
||||
|
||||
// we need ACTIVATIONKEY too
|
||||
if(v.Find("ACTIVATIONKEY") < 0)
|
||||
{
|
||||
res.Add("ERROR", PROTECT_MISSING_ACTIVATIONKEY);
|
||||
return res;
|
||||
}
|
||||
activationKey = v.Get("ACTIVATIONKEY");
|
||||
|
||||
// get user record by email
|
||||
userRec = db.Get(eMail);
|
||||
|
||||
// if no mail data, product is unregistered
|
||||
if(!userRec.GetCount())
|
||||
{
|
||||
res.Add("ERROR", PROTECT_UNREGISTERED);
|
||||
return res;
|
||||
}
|
||||
|
||||
// sets registered flag and update record
|
||||
userRec.Get("ACTIVATED") = true;
|
||||
db.Set(userRec);
|
||||
|
||||
res.Add("STATUS", "ACTIVATION SUCCESSFUL");
|
||||
break;
|
||||
case PROTECT_CONNECT:
|
||||
// we need email to connect
|
||||
if(v.Find("EMAIL") < 0)
|
||||
|
|
@ -349,6 +417,21 @@ VectorMap<String, Value> ProtectServer::ProcessRequest(int reason, VectorMap<Str
|
|||
DisconnectClient(clientID);
|
||||
break;
|
||||
|
||||
case PROTECT_REFRESH :
|
||||
// we need the conneciton ID
|
||||
if(v.Find("CLIENTID") < 0)
|
||||
{
|
||||
res.Add("ERROR", PROTECT_MISSING_CLIENTID);
|
||||
return res;
|
||||
}
|
||||
clientID = (int)v.Get("CLIENTID");
|
||||
if(!IsClientConnected(clientID))
|
||||
{
|
||||
res.Add("ERROR", PROTECT_NOT_CONNECTED);
|
||||
return res;
|
||||
}
|
||||
break;
|
||||
|
||||
case PROTECT_GETKEY:
|
||||
// we need the conneciton ID
|
||||
if(v.Find("CLIENTID") < 0)
|
||||
|
|
@ -367,7 +450,73 @@ VectorMap<String, Value> ProtectServer::ProcessRequest(int reason, VectorMap<Str
|
|||
res.Add("KEY", appKey);
|
||||
break;
|
||||
|
||||
case PROTECT_GETLICENSEINFO :
|
||||
// we need the conneciton ID
|
||||
if(v.Find("CLIENTID") < 0)
|
||||
{
|
||||
res.Add("ERROR", PROTECT_MISSING_CLIENTID);
|
||||
return res;
|
||||
}
|
||||
// we shall be connected
|
||||
clientID = (int)v.Get("CLIENTID");
|
||||
if(!IsClientConnected(clientID))
|
||||
{
|
||||
res.Add("ERROR", PROTECT_NOT_CONNECTED);
|
||||
return res;
|
||||
}
|
||||
// get user data from database
|
||||
res = db.Get(clientLinks.Get(clientID).eMail);
|
||||
// remove unnecessary data
|
||||
res.RemoveKey("ACTIVATIONKEY");
|
||||
res.RemoveKey("ACTIVATIONSENT");
|
||||
break;
|
||||
|
||||
case PROTECT_UPDATEUSERDATA :
|
||||
{
|
||||
// we need the conneciton ID
|
||||
if(v.Find("CLIENTID") < 0)
|
||||
{
|
||||
res.Add("ERROR", PROTECT_MISSING_CLIENTID);
|
||||
return res;
|
||||
}
|
||||
// we shall be connected
|
||||
clientID = (int)v.Get("CLIENTID");
|
||||
if(!IsClientConnected(clientID))
|
||||
{
|
||||
res.Add("ERROR", PROTECT_NOT_CONNECTED);
|
||||
return res;
|
||||
}
|
||||
// get user data from database
|
||||
userRec = db.Get(clientLinks.Get(clientID).eMail);
|
||||
|
||||
// avoid hacking of source packet stripping
|
||||
// data non-updateable by user
|
||||
VectorMap<String, Value>vs(v, 1);
|
||||
vs.RemoveKey("LICENSES");
|
||||
vs.RemoveKey("EXPIRATION");
|
||||
vs.RemoveKey("ACTIVATIONKEY");
|
||||
vs.RemoveKey("ACTIVATIONSENT");
|
||||
vs.RemoveKey("ACTIVATED");
|
||||
vs.RemoveKey("EMAIL");
|
||||
|
||||
// update user record
|
||||
for(int i = 0; i < vs.GetCount(); i++)
|
||||
{
|
||||
int j = userRec.Find(vs.GetKey(i));
|
||||
if(j >= 0)
|
||||
userRec[j] = vs[i];
|
||||
}
|
||||
db.Set(userRec);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
// disconnect me anyways
|
||||
if(v.Find("CLIENTID") >= 0)
|
||||
{
|
||||
clientID = (int)v.Get("CLIENTID");
|
||||
DisconnectClient(clientID);
|
||||
}
|
||||
res.Add("ERROR", PROTECT_UNKNOWN_REASON);
|
||||
break;
|
||||
}
|
||||
|
|
@ -377,9 +526,25 @@ VectorMap<String, Value> ProtectServer::ProcessRequest(int reason, VectorMap<Str
|
|||
// sends activation mail to user
|
||||
bool ProtectServer::SendActivationMail(VectorMap<String, Value> const &userData)
|
||||
{
|
||||
// build request map
|
||||
VectorMap<String, Value>req;
|
||||
req.Add("REASON", PROTECT_ACTIVATE);
|
||||
req.Add("EMAIL", userData.Get("EMAIL"));
|
||||
req.Add("ACTIVATIONKEY", userData.Get("ACTIVATIONKEY"));
|
||||
|
||||
// builds activation link
|
||||
String link = "http://" + serverVars.Get("SERVER_NAME") + serverVars.Get("REQUEST_URI") + "?";
|
||||
|
||||
// encodes results and send back to client
|
||||
cypher->SetKey(key);
|
||||
link += "IV=" + HexString(cypher->GetNonce()) + "&";
|
||||
String encoded = HexString((*cypher)(StoreAsXML(req, "ProtectServer")));
|
||||
link += "DATA=" + encoded;
|
||||
|
||||
smtp.To(userData.Get("EMAIL"));
|
||||
smtp.Subject("APPLICATION ACTIVATION");
|
||||
smtp.Text("http://www.timberstruct.it?DATA=" + (String)userData.Get("ACTIVATIONKEY"));
|
||||
smtp.From(serverVars.Get("SERVER_NAME"));
|
||||
smtp.Text(link);
|
||||
return smtp.Send();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
#define _ProtectServer_h_
|
||||
|
||||
#include <Core/Core.h>
|
||||
#include <ScgiServer/ScgiServer.h>
|
||||
#include <Web/Web.h>
|
||||
#include <Cypher/Cypher.h>
|
||||
|
||||
#include "ProtectStatus.h"
|
||||
|
|
@ -42,6 +42,10 @@ class ProtectServer : public ScgiServer
|
|||
|
||||
// key used to en/decrypt http data
|
||||
String key;
|
||||
|
||||
// welcome and activation failed messages sent on key activation
|
||||
String welcome;
|
||||
String activationFailed;
|
||||
|
||||
void OnAccepted();
|
||||
void OnRequest();
|
||||
|
|
@ -83,6 +87,10 @@ public:
|
|||
// sets encryption key
|
||||
ProtectServer &SetKey(String const &_key) { key = _key; return *this; }
|
||||
|
||||
// sets welcome and activation failed (HTML) messages
|
||||
ProtectServer &SetWelcome(String const &w) { welcome = w; return *this; }
|
||||
ProtectServer &SetActivationFailed(String const &a) { activationFailed = a; return *this; }
|
||||
|
||||
// gets database
|
||||
ProtectDB &GetDB(void) { return db; }
|
||||
|
||||
|
|
|
|||
|
|
@ -9,11 +9,13 @@ const char *__ProtectMessages[] =
|
|||
tt_("HTTP SERVER ERROR"),
|
||||
tt_("BAD REQUEST"),
|
||||
tt_("MISSING INITIALIZATION VECTOR ON DATA"),
|
||||
tt_("MISSING DATA FIELD"),
|
||||
tt_("MISSING EMAIL ON DATA"),
|
||||
tt_("ILL-FORMED EMAIL ADDRESS"),
|
||||
tt_("MISSING CONNECTION REASON ON DATA"),
|
||||
tt_("UNKNOWN CONNECTION REASON"),
|
||||
tt_("MISSING CLIENT ID ON DATA"),
|
||||
tt_("MISSING ACTIVATION KEY ON DATA"),
|
||||
tt_("BAD REQUEST DATA"),
|
||||
tt_("NOT CONNECTED TO SERVER"),
|
||||
tt_("SERVER CONNECTION EXPIRED"),
|
||||
|
|
@ -43,6 +45,7 @@ const char *__ProtectReasons[] =
|
|||
"REFRESH", // refreshes server connection (to restart timeout)
|
||||
"GETKEY", // gets application key
|
||||
"REGISTER", // registers app for timed demo
|
||||
"ACTIVATE", // activate registration by click on email link
|
||||
"GETLICENSEINFO" // gets info about license (name, expiration date, app version....)
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -11,11 +11,13 @@ typedef enum {
|
|||
PROTECT_HTTP_ERROR, // error on HTTP communication with server
|
||||
PROTECT_BAD_REQUEST, // missing POST data on request
|
||||
PROTECT_MISSING_IV, // missing Initialization Vector on POST data
|
||||
PROTECT_MISSING_DATA, // missing DATA field on POST data
|
||||
PROTECT_MISSING_EMAIL, // missing mandatory EMAIL field in POST DATA
|
||||
PROTECT_INVALID_EMAIL, // ill-formed email address
|
||||
PROTECT_MISSING_REASON, // missing connection's reason
|
||||
PROTECT_UNKNOWN_REASON, // unknown connection's reason
|
||||
PROTECT_MISSING_CLIENTID, // missing client connection ID in POST DATA
|
||||
PROTECT_MISSING_ACTIVATIONKEY, // missing activation key on activation request
|
||||
PROTECT_BAD_DATA, // missing mandatory fields in POST DATA
|
||||
PROTECT_NOT_CONNECTED, // not connected to server -- must connect first
|
||||
PROTECT_CONNECTION_EXPIRED, // server connection timeout -- should refresh more often
|
||||
|
|
@ -33,13 +35,15 @@ extern String ProtectMessage(int m);
|
|||
|
||||
// server request reasons
|
||||
typedef enum {
|
||||
PROTECT_BAD_REASON, // internal error
|
||||
PROTECT_CONNECT, // establish connection to server
|
||||
PROTECT_DISCONNECT, // frees server connection
|
||||
PROTECT_REFRESH, // refreshes server connection (to restart timeout)
|
||||
PROTECT_GETKEY, // gets application key
|
||||
PROTECT_REGISTER, // registers app for timed demo
|
||||
PROTECT_GETLICENSEINFO // gets info about license (name, expiration date, app version....)
|
||||
PROTECT_BAD_REASON, // internal error
|
||||
PROTECT_CONNECT, // establish connection to server
|
||||
PROTECT_DISCONNECT, // frees server connection
|
||||
PROTECT_REFRESH, // refreshes server connection (to restart timeout)
|
||||
PROTECT_GETKEY, // gets application key
|
||||
PROTECT_REGISTER, // registers app for timed demo
|
||||
PROTECT_ACTIVATE, // activate registration by click on email link
|
||||
PROTECT_GETLICENSEINFO, // gets info about license (name, expiration date, app version....)
|
||||
PROTECT_UPDATEUSERDATA // update user-modifiable user data (name, address....)
|
||||
} ProtectReasons;
|
||||
|
||||
// get reason in string format
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
#ifndef _Protect_icpp_init_stub
|
||||
#define _Protect_icpp_init_stub
|
||||
#include "Core/init"
|
||||
#include "ScgiServer/init"
|
||||
#include "Cypher/init"
|
||||
#include "MySql/init"
|
||||
#include "Web/init"
|
||||
#endif
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue