00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026 #include <vos/corelibs/vos/vos.hh>
00027 #include <vos/metaobjects/property/property.hh>
00028 #include "login.hh"
00029 #include "md5.hh"
00030
00031 class MD5;
00032
00033
00034
00035 LocalLogin::LocalLogin(MetaObject* s) : MetaObject(s) {
00036 addMessageHandler<LocalLogin>("misc:request-login", this, &LocalLogin::handleRequestLogin);
00037 addMessageHandler<LocalLogin>("misc:login-challenge-reply", this, &LocalLogin::handleLoginChallengeReply);
00038 }
00039
00040 LocalLogin::~LocalLogin() {
00041 }
00042
00043 RemoteLogin::RemoteLogin(MetaObject* s) : MetaObject(s) {
00044 addUpdateHandler<RemoteLogin>("misc:request-login-challenge", this, &RemoteLogin::handleRequestLoginChallenge);
00045 addUpdateHandler<RemoteLogin>("misc:login-result", this, &RemoteLogin::handleLoginResult);
00046 }
00047
00048 RemoteLogin::~RemoteLogin() {
00049 }
00050
00051 const string LocalLogin::getType() {
00052 return string("misc:login");
00053 }
00054
00055 const string RemoteLogin::getType() {
00056 return string("misc:login");
00057 }
00058
00059
00060
00061 void RemoteLogin::registerExtenders() {
00062 static bool done = false;
00063 if(! done) {
00064 RemoteSite::addRemoteObjectExtension(typeid(RemoteLogin).name(), &RemoteLogin::new_RemoteLogin);
00065 RemoteSite::addRemoteObjectExtension("misc:login", &RemoteLogin::new_RemoteLogin);
00066 done = true;
00067 }
00068 }
00069
00070
00071
00072
00073
00074
00075
00076
00077 void LocalLogin::handleRequestLogin(Message* m) {
00078
00079
00080
00081
00082
00083
00084
00085 try {
00086 pREF(Message*, reply, new Message(),
00087 LocalVobject::initReply(this, reply, m, "misc:request-login-challenge");
00088 rREF(Vobject&, from, Vobject::findObjectFromRoot(m->getFrom()),
00089
00090 char s[64];
00091 snprintf(s, sizeof(s), "%li", rand());
00092 nonceMap[m->getSourceSite()].username = m->getField("username").value;
00093 nonceMap[m->getSourceSite()].timestamp = time(0);
00094 nonceMap[m->getSourceSite()].nonce = s;
00095 reply->insertField(-1, "nonce", s);
00096
00097 from.sendMessage(reply);
00098 );
00099 );
00100 } catch(Message::NoSuchFieldError e) {
00101
00102 }
00103
00104 }
00105
00106
00107
00108 void LocalLogin::handleLoginChallengeReply(Message* m) {
00109
00110
00111
00112
00113
00114
00115
00116
00117 try {
00118 pREF(Message*, reply, new Message(),
00119 LocalVobject::initReply(this, reply, m, "misc:login-result");
00120 rREF(Vobject&, from, Vobject::findObjectFromRoot(m->getFrom()),
00121
00122 if(time(0) - nonceMap[m->getSourceSite()].timestamp > 60) {
00123 reply->insertField(-1, "result", "Stale nonce (waited too long to reply). Try again.");
00124 } else {
00125 string app = nonceMap[m->getSourceSite()].nonce;
00126 try {
00127 app += getPassword(nonceMap[m->getSourceSite()].username);
00128 _MD5 md5;
00129 md5.update((unsigned char*)app.c_str(), app.size());
00130 md5.finalize();
00131 if(m->getField("hash").value == md5.hex_digest()) {
00132 reply->insertField(-1, "result", "success");
00133 } else {
00134 reply->insertField(-1, "result", "Bad username or password ");
00135 }
00136 } catch(BadUsernameError x) {
00137 reply->insertField(-1, "result", string("Bad username or password ") + x.what());
00138 }
00139 }
00140
00141 string username = nonceMap[m->getSourceSite()].username;
00142 nonceMap.erase(m->getSourceSite());
00143
00144 from.sendMessage(reply);
00145
00146 if(reply->getField("result").value == "success")
00147 notifyAuthenticated(username, m->getSourceSite());
00148 );
00149 );
00150 } catch(Message::NoSuchFieldError e) {
00151
00152 }
00153
00154 }
00155
00156
00157
00158
00159
00160 bool RemoteLogin::doRequestLogin(const string& username, const string& passwd) {
00161 success = false;
00162 password = passwd;
00163
00164 pREF(Message*, m, new Message(),
00165 rREF(LocalSite&, ls, RemoteVobject::initFields(this, m, "misc:request-login", true),
00166
00167 m->insertField(-1, "username", username);
00168
00169 sendMessage(m);
00170 rREF(RemoteSite&, site, dynamic_cast<RemoteSite&>(getSite()),
00171 pREF(Message*, n, ls.waitFor(m->getNonce(), &site), );
00172 );
00173 );
00174 );
00175 return success;
00176 }
00177
00178
00179
00180 MetaObject* RemoteLogin::new_RemoteLogin(MetaObject* s, const string& type) {
00181 return new RemoteLogin(s);
00182 }
00183
00184
00185
00186 void RemoteLogin::handleRequestLoginChallenge(Message* m) {
00187 try {
00188 pREF(Message*, p, new Message(),
00189 rREF(LocalSite&, ls, RemoteVobject::initFields(this, p, "misc:login-challenge-reply", true),
00190
00191 string nonce = m->getField("nonce").value;
00192 nonce += password;
00193 _MD5 md5;
00194 md5.update((unsigned char*)nonce.c_str(), nonce.size());
00195 md5.finalize();
00196 p->insertField(-1, "hash", md5.hex_digest());
00197
00198 sendMessage(p);
00199 rREF(RemoteSite&, site, dynamic_cast<RemoteSite&>(getSite()),
00200 pREF(Message*, x, ls.waitFor(p->getNonce(), &site), );
00201 );
00202 );
00203 );
00204 } catch(Message::NoSuchFieldError) {}
00205 }
00206
00207 void RemoteLogin::handleLoginResult(Message* m) {
00208 if(m->getField("result").value == "success") success=true;
00209 }