Back to index

nordugrid-arc-nox  1.1.0~rc6
User.cpp
Go to the documentation of this file.
00001 // -*- indent-tabs-mode: nil -*-
00002 
00003 #ifdef HAVE_CONFIG_H
00004 #include <config.h>
00005 #endif
00006 
00007 #include <string>
00008 #ifndef WIN32
00009 #include <pwd.h>
00010 #include <grp.h>
00011 #include <sys/stat.h>
00012 #include <unistd.h>
00013 #include <sys/types.h>
00014 #include <fcntl.h>
00015 
00016 #else // WIN32
00017 #include <arc/win32.h>
00018 #include <glibmm/miscutils.h>
00019 #endif
00020 
00021 #include <arc/StringConv.h>
00022 #include <arc/Utils.h>
00023 #include "User.h"
00024 
00025 namespace Arc {
00026 
00027 static Glib::Mutex suid_lock;
00028 
00029 #ifndef WIN32
00030   static uid_t get_user_id(void) {
00031     uid_t user_id = getuid();
00032     if (user_id != 0)
00033       return user_id;
00034     std::string user_s = GetEnv("USER_ID");
00035     if (user_s.empty())
00036       return 0;
00037     user_id = stringtoui(user_s);
00038     return user_id;
00039   }
00040 
00041   static uid_t get_group_id(void) {
00042     return getgid();
00043   }
00044 
00045   void User::set(const struct passwd *pwd_p) {
00046     if (pwd_p == NULL)
00047       return;
00048     home = GetEnv("HOME");
00049     name = pwd_p->pw_name;
00050     if (home.empty())
00051       home = pwd_p->pw_dir;
00052     uid = pwd_p->pw_uid;
00053     gid = pwd_p->pw_gid;
00054   }
00055 
00056   User::User(void) {
00057     uid = get_user_id();
00058     gid = get_group_id();
00059     struct passwd pwd;
00060     char pwdbuf[2048];
00061     struct passwd *pwd_p;
00062     getpwuid_r(uid, &pwd, pwdbuf, sizeof(pwdbuf), &pwd_p);
00063     set(pwd_p);
00064   }
00065 
00066   // Unix implementation
00067   User::User(std::string name) {
00068     this->name = name;
00069     struct passwd pwd;
00070     char pwdbuf[2048];
00071     struct passwd *pwd_p;
00072     getpwnam_r(name.c_str(), &pwd, pwdbuf, sizeof(pwdbuf), &pwd_p);
00073     set(pwd_p);
00074   }
00075 
00076   User::User(int uid) {
00077     this->uid = uid;
00078     this->gid = -1;
00079     struct passwd pwd;
00080     char pwdbuf[2048];
00081     struct passwd *pwd_p;
00082     getpwuid_r(uid, &pwd, pwdbuf, sizeof(pwdbuf), &pwd_p);
00083     set(pwd_p);
00084   }
00085 
00086   bool User::RunAs(std::string) {
00087     // XXX NOP
00088     return false;
00089   }
00090 
00091   int User::check_file_access(const std::string& path, int flags) {
00092     int h;
00093     struct stat st;
00094     mode_t m;
00095     char **grmem;
00096 
00097     flags &= O_RDWR | O_RDONLY | O_WRONLY;
00098     if ((flags != O_RDWR) && (flags != O_RDONLY) && (flags != O_WRONLY))
00099       return -1;
00100     if (getuid() != 0) { /* not root - just try to open */
00101       if ((h = open(path.c_str(), flags)) == -1)
00102         return -1;
00103       close(h);
00104       return 0;
00105     }
00106     if (uid == 0)
00107       return 0;
00108     /* check for file */
00109     if (stat(path.c_str(), &st) != 0)
00110       return -1;
00111     if (!S_ISREG(st.st_mode))
00112       return -1;
00113     m = 0;
00114     if (st.st_uid == uid)
00115       m |= st.st_mode & (S_IRUSR | S_IWUSR);
00116     if (st.st_gid == gid)
00117       m |= st.st_mode & (S_IRGRP | S_IWGRP);
00118     else {
00119       char grbuf[2048];
00120       struct group grp;
00121       struct group *grp_p = NULL;
00122       char pwdbuf[2048];
00123       struct passwd pwd;
00124       struct passwd *pwd_p = NULL;
00125       getpwuid_r(uid, &pwd, pwdbuf, sizeof(pwdbuf), &pwd_p);
00126       getgrgid_r(st.st_gid, &grp, grbuf, sizeof(grbuf), &grp_p);
00127       if ((grp_p != NULL) && (pwd_p != NULL))
00128         for (grmem = grp_p->gr_mem; (*grmem) != NULL; grmem++)
00129           if (strcmp(*grmem, pwd_p->pw_name) == 0) {
00130             m |= st.st_mode & (S_IRGRP | S_IWGRP);
00131             break;
00132           }
00133     }
00134     m |= st.st_mode & (S_IROTH | S_IWOTH);
00135     if (flags == O_RDWR) {
00136       if (((m & (S_IRUSR | S_IRGRP | S_IROTH)) == 0) ||
00137           ((m & (S_IWUSR | S_IWGRP | S_IWOTH)) == 0))
00138         return 1;
00139     }
00140     else if (flags == O_RDONLY) {
00141       if ((m & (S_IRUSR | S_IRGRP | S_IROTH)) == 0)
00142         return 1;
00143     }
00144     else if (flags == O_WRONLY) {
00145       if ((m & (S_IWUSR | S_IWGRP | S_IWOTH)) == 0)
00146         return 1;
00147     }
00148     else
00149       return -1; /* check if all directories allow to read - not implemented yet */
00150 
00151     return 0;
00152   }
00153 
00154 
00155 #else
00156   // Win32 implementation
00157 
00158   static uid_t get_user_id(void) {
00159     return 0; // TODO: The user id is not used on windows for file permissions etc.
00160   }
00161 
00162   static uid_t get_group_id(void) {
00163     return 0; // TODO: The user id is not used on windows for file permissions etc.
00164   }
00165 
00166   void User::set(const struct passwd *pwd_p) {
00167     if (pwd_p == NULL)
00168       return;
00169     name = pwd_p->pw_name;
00170     home = pwd_p->pw_dir;
00171     uid = pwd_p->pw_uid;
00172     gid = pwd_p->pw_gid;
00173   }
00174 
00175   User::User(void) {
00176     int uid = get_user_id();
00177     int gid = get_group_id();
00178     bool found;
00179 
00180     struct passwd pwd_p;
00181 
00182     std::string name = Glib::getenv("USERNAME", found);
00183     if (!found)
00184       name = "";
00185     std::string home = g_get_user_config_dir();
00186 
00187     pwd_p.pw_name = const_cast<char*>(name.c_str());
00188     pwd_p.pw_uid = uid;
00189     pwd_p.pw_gid = gid;
00190     pwd_p.pw_dir = const_cast<char*>(home.c_str());
00191 
00192     set(&pwd_p);
00193   }
00194 
00195   User::User(std::string name) {
00196     this->name = name;
00197     int uid = get_user_id();
00198     int gid = get_group_id();
00199     bool found;
00200 
00201     struct passwd pwd_p;
00202 
00203     std::string home = g_get_user_config_dir();
00204 
00205     pwd_p.pw_name = const_cast<char*>(name.c_str());
00206     pwd_p.pw_uid = uid;
00207     pwd_p.pw_gid = gid;
00208     pwd_p.pw_dir = const_cast<char*>(home.c_str());
00209 
00210     set(&pwd_p);
00211   }
00212 
00213   User::User(int uid) {
00214     this->uid = uid;
00215     this->gid = 0;
00216 
00217     bool found;
00218 
00219     struct passwd pwd_p;
00220 
00221     std::string name = Glib::getenv("USERNAME", found);
00222     if (!found)
00223       name = "";
00224     std::string home = g_get_user_config_dir();
00225 
00226     pwd_p.pw_name = const_cast<char*>(name.c_str());
00227     pwd_p.pw_uid = uid;
00228     pwd_p.pw_gid = gid;
00229     pwd_p.pw_dir = const_cast<char*>(home.c_str());
00230 
00231     set(&pwd_p);
00232   }
00233   bool User::RunAs(std::string cmd) {
00234     // XXX NOP
00235     return false;
00236   }
00237 
00238   int User::check_file_access(const std::string& path, int flags) {
00239     // XXX NOP
00240     return 0;
00241   }
00242 #endif
00243 
00244 #ifndef WIN32
00245   UserSwitch::UserSwitch(int uid,int gid):valid(false) {
00246     suid_lock.lock();
00247     old_gid = getegid();
00248     old_uid = geteuid();
00249     if(gid) {
00250       if(old_gid != gid) {
00251         if(setegid(gid) == -1) {
00252           suid_lock.unlock();
00253           return;
00254         };
00255       };
00256     };
00257     if(uid) {
00258       if(old_uid != uid) {
00259         if(seteuid(uid) == -1) {
00260           if(old_gid != gid) setegid(old_gid);
00261           suid_lock.unlock();
00262           return;
00263         };
00264       };
00265     };
00266     valid=true;
00267   }
00268 
00269   UserSwitch::~UserSwitch(void) {
00270     if(valid) {
00271       if(old_uid != geteuid()) seteuid(old_uid);
00272       if(old_gid != getegid()) setegid(old_gid);
00273       suid_lock.unlock();
00274     };
00275   }
00276 #else
00277   UserSwitch::UserSwitch(int uid,int gid):valid(false) {
00278   }
00279 
00280   UserSwitch::~UserSwitch(void) {
00281   }
00282 #endif
00283 
00284 } // namespace Arc