Main Page | Class Hierarchy | Class List | Directories | File List | Class Members | File Members | Related Pages | Examples

ArServerUserInfo.cpp

Go to the documentation of this file.
00001 /*
00002 MobileRobots Advanced Robotics Interface for Applications (ARIA)
00003 Copyright (C) 2004, 2005 ActivMedia Robotics LLC
00004 Copyright (C) 2006, 2007 MobileRobots Inc.
00005 
00006      This program is free software; you can redistribute it and/or modify
00007      it under the terms of the GNU General Public License as published by
00008      the Free Software Foundation; either version 2 of the License, or
00009      (at your option) any later version.
00010 
00011      This program is distributed in the hope that it will be useful,
00012      but WITHOUT ANY WARRANTY; without even the implied warranty of
00013      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014      GNU General Public License for more details.
00015 
00016      You should have received a copy of the GNU General Public License
00017      along with this program; if not, write to the Free Software
00018      Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00019 
00020 If you wish to redistribute ARIA under different terms, contact 
00021 MobileRobots for information about a commercial version of ARIA at 
00022 robots@mobilerobots.com or 
00023 MobileRobots Inc, 19 Columbia Drive, Amherst, NH 03031; 800-639-9481
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   //printf("Adding user %s with password %s and groups\n", user, password);
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   /*  thd old simple clear text way
00176   if (ArUtil::strcmp((*it).second, password) != 0)
00177   {
00178     ArLog::log(ArLog::Normal, 
00179                "ArServerUserInfo: login denied: Wrong password for user %s", 
00180                user);
00181     return false;
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     if ((sit = myGroups.find((*it).first)) == myGroups.end())
00238     {
00239       ArLog::log(ArLog::Terse, "ArServerUserInfo::logUsersAndGroups: Hideous error with the groups of user '%s'", (*it).first.c_str());
00240       continue;
00241     } 
00242     groups = (*sit).second;
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 

Generated on Tue Feb 20 10:51:50 2007 for ArNetworking by  doxygen 1.4.0