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 "Aria.h"
00027 #include "ArExport.h"
00028 #include "ArServerUserInfo.h"
00029 #include "md5.h"
00030
00031 AREXPORT ArServerUserInfo::ArServerUserInfo(const char *baseDirectory) :
00032 myV1HeaderCB(this, &ArServerUserInfo::v1HeaderCallback),
00033 myV1UserCB(this, &ArServerUserInfo::v1UserCallback),
00034 myV1DoNotUseCB(this, &ArServerUserInfo::v1DoNotUseCallback)
00035 {
00036 myParser.setBaseDirectory(baseDirectory);
00037 myGotHeader = false;
00038 myDoNotUse = false;
00039 }
00040
00041 AREXPORT ArServerUserInfo::~ArServerUserInfo()
00042 {
00043
00044 }
00045
00046 AREXPORT void ArServerUserInfo::setBaseDirectory(const char *baseDirectory)
00047 {
00048 myDataMutex.lock();
00049 myParser.setBaseDirectory(baseDirectory);
00050 myDataMutex.unlock();
00051 }
00052
00053
00054 bool ArServerUserInfo::v1HeaderCallback(ArArgumentBuilder * arg)
00055 {
00056 removeHandlers();
00057 if (myParser.addHandler("user", &myV1UserCB) &&
00058 myParser.addHandler("doNotUse", &myV1DoNotUseCB))
00059 {
00060 myGotHeader = true;
00061 myDoNotUse = false;
00062 return true;
00063 }
00064 else
00065 {
00066 ArLog::log(ArLog::Terse, "ArServerUserInfo::Could not add user info callback");
00067 return false;
00068 }
00069 }
00070
00071 bool ArServerUserInfo::v1UserCallback(ArArgumentBuilder * arg)
00072 {
00073 if (arg->getArgc() < 2)
00074 {
00075 ArLog::log(ArLog::Normal, "ArServerUserInfo: Not enough arguments to user info 'user <user> <password> <reapingOptional:group>");
00076 return false;
00077 }
00078
00079 const char *user;
00080 const char *password;
00081 user = arg->getArg(0);
00082 if (!ArUtil::isOnlyAlphaNumeric(user))
00083 {
00084 ArLog::log(ArLog::Normal, "ArServerUserInfo: user has non-alpha-numeric characters in it");
00085 return false;
00086 }
00087 password = arg->getArg(1);
00088 if (!ArUtil::isOnlyAlphaNumeric(password))
00089 {
00090 ArLog::log(ArLog::Normal, "ArServerUserInfo: password has non-alpha-numeric characters in it");
00091 return false;
00092 }
00093
00094 if (myPasswords.find(user) != myPasswords.end())
00095 {
00096 ArLog::log(ArLog::Terse, "ArServerUserInfo: Already a user with name %s", user);
00097 return false;
00098 }
00099
00100 myPasswords[user] = password;
00101
00102 std::set<std::string, ArStrCaseCmpOp> *groups;
00103 groups = new std::set<std::string, ArStrCaseCmpOp>;
00104 myGroups[user] = groups;
00105
00106 unsigned int i;
00107 for (i = 2; i < arg->getArgc(); i++)
00108 {
00109 groups->insert(arg->getArg(i));
00110 }
00111 return true;
00112 }
00113
00114 bool ArServerUserInfo::v1DoNotUseCallback(ArArgumentBuilder * arg)
00115 {
00116 myDoNotUse = true;
00117 return true;
00118 }
00119
00120 void ArServerUserInfo::removeHandlers(void)
00121 {
00122 myParser.remHandler(&myV1HeaderCB);
00123 myParser.remHandler(&myV1UserCB);
00124 }
00125
00126 AREXPORT bool ArServerUserInfo::readFile(const char *fileName)
00127 {
00128 myDataMutex.lock();
00129 removeHandlers();
00130 myPasswords.clear();
00131 ArUtil::deleteSetPairs(myGroups.begin(), myGroups.end());
00132 myGroups.clear();
00133 myParser.addHandler("UserInfoVersion1", &myV1HeaderCB);
00134 myGotHeader = false;
00135 if (!myParser.parseFile(fileName, false))
00136 {
00137 myDataMutex.unlock();
00138 ArLog::log(ArLog::Terse, "Problem loading server user info");
00139 return false;
00140 }
00141 removeHandlers();
00142 if (myGotHeader)
00143 {
00144 myDataMutex.unlock();
00145 ArLog::log(ArLog::Verbose, "Loaded server user info");
00146 return true;
00147 }
00148 else
00149 {
00150 myDataMutex.unlock();
00151 ArLog::log(ArLog::Normal, "Problem loading server user info: no header");
00152 return false;
00153 }
00154 }
00155
00156 AREXPORT bool ArServerUserInfo::matchUserPassword(
00157 const char *user, unsigned char password[16], const char *passwordKey,
00158 const char *serverKey) const
00159 {
00160 std::map<std::string, std::string, ArStrCaseCmpOp>::const_iterator it;
00161 if (!ArUtil::isOnlyAlphaNumeric(user))
00162 {
00163 ArLog::log(ArLog::Normal,
00164 "ArServerUserInfo: login denied: user '%s' has non alpha-numeric characters",
00165 user);
00166 return false;
00167 }
00168 it = myPasswords.find(user);
00169 if (it == myPasswords.end())
00170 {
00171 ArLog::log(ArLog::Normal, "ArServerUserInfo: login denied: No user %s",
00172 user);
00173 return false;
00174 }
00175
00176
00177
00178
00179
00180
00181
00182
00183 md5_state_t md5State;
00184 unsigned char md5Digest[16];
00185
00186 md5_init(&md5State);
00187 md5_append(&md5State, (unsigned char *)serverKey, strlen(serverKey));
00188 md5_append(&md5State, (unsigned char *)passwordKey, strlen(passwordKey));
00189 md5_append(&md5State, (unsigned char *)(*it).second.c_str(),
00190 (*it).second.size());
00191 md5_finish(&md5State, md5Digest);
00192
00193 if (memcmp(md5Digest, password, 16) != 0)
00194 {
00195 ArLog::log(ArLog::Normal,
00196 "ArServerUserInfo: login denied: Wrong password for user %s",
00197 user);
00198 return false;
00199 }
00200 return true;
00201 }
00202
00203 AREXPORT std::set<std::string, ArStrCaseCmpOp>
00204 ArServerUserInfo::getUsersGroups(const char *user) const
00205 {
00206 std::map<std::string, std::set<std::string, ArStrCaseCmpOp> *, ArStrCaseCmpOp>::const_iterator sit;
00207 std::set<std::string, ArStrCaseCmpOp> ret;
00208
00209 if ((sit = myGroups.find(user)) == myGroups.end())
00210 {
00211 ArLog::log(ArLog::Terse, "No user %s", user);
00212 return ret;
00213 }
00214
00215 ret = *((*sit).second);
00216 return ret;
00217 }
00218
00219 AREXPORT void ArServerUserInfo::logUsers(void) const
00220 {
00221 std::map<std::string, std::string, ArStrCaseCmpOp>::const_iterator it;
00222 std::set<std::string, ArStrCaseCmpOp> groups;
00223 std::set<std::string, ArStrCaseCmpOp>::const_iterator git;
00224 std::string line;
00225 if (myDoNotUse)
00226 ArLog::log(ArLog::Terse, "The user info should not be used");
00227 else
00228 ArLog::log(ArLog::Terse, "The user info should be used");
00229 for (it = myPasswords.begin(); it != myPasswords.end(); it++)
00230 {
00231 line = "User ";
00232 line += (*it).first;
00233 line += " has groups:";
00234
00235 groups = getUsersGroups((*it).first.c_str());
00236
00237
00238
00239
00240
00241
00242
00243
00244 for (git = groups.begin(); git != groups.end(); git++)
00245 {
00246 line += " ";
00247 line += (*git);
00248 }
00249 ArLog::log(ArLog::Terse, line.c_str());
00250 }
00251 }
00252
00253 AREXPORT bool ArServerUserInfo::doNotUse(void) const
00254 {
00255 return myDoNotUse;
00256 }
00257
00258
00259
00260
00261