00001
00002
00003
00004
00005
00006
00007
00008
00009
00010 const char *XrdSysPrivCVSID = "$Id: XrdSysPriv.cc 30949 2009-11-02 16:37:58Z ganis $";
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include "XrdSys/XrdSysPriv.hh"
00025
00026 #if !defined(WINDOWS)
00027 #include <stdio.h>
00028 #include "XrdSys/XrdSysHeaders.hh"
00029 #include <unistd.h>
00030 #include <pwd.h>
00031 #include <errno.h>
00032
00033 #define NOUC ((uid_t)(-1))
00034 #define NOGC ((gid_t)(-1))
00035 #define XSPERR(x) ((x == 0) ? -1 : -x)
00036
00037
00038 #if defined(__sgi) && !defined(__GNUG__) && (SGI_REL<62)
00039 extern "C" {
00040 int seteuid(int euid);
00041 int setegid(int egid);
00042 int geteuid();
00043 int getegid();
00044 }
00045 #endif
00046
00047 #if defined(_AIX)
00048 extern "C" {
00049 int seteuid(uid_t euid);
00050 int setegid(gid_t egid);
00051 uid_t geteuid();
00052 gid_t getegid();
00053 }
00054 #endif
00055
00056 #if !defined(HAVE_SETRESUID)
00057 static int setresgid(gid_t r, gid_t e, gid_t)
00058 {
00059 if (r != NOGC && setgid(r) == -1)
00060 return XSPERR(errno);
00061 return ((e != NOGC) ? setegid(e) : 0);
00062 }
00063
00064 static int setresuid(uid_t r, uid_t e, uid_t)
00065 {
00066 if (r != NOUC && setuid(r) == -1)
00067 return XSPERR(errno);
00068 return ((e != NOUC) ? seteuid(e) : 0);
00069 }
00070
00071 static int getresgid(gid_t *r, gid_t *e, gid_t *)
00072 {
00073 *r = getgid();
00074 *e = getegid();
00075 return 0;
00076 }
00077
00078 static int getresuid(uid_t *r, uid_t *e, uid_t *)
00079 {
00080 *r = getuid();
00081 *e = geteuid();
00082 return 0;
00083 }
00084
00085 #else
00086 #if (defined(__linux__) || \
00087 (defined(__CYGWIN__) && defined(__GNUC__))) && !defined(linux)
00088 # define linux
00089 #endif
00090 #if defined(linux) && !defined(HAVE_SETRESUID)
00091 extern "C" {
00092 int setresgid(gid_t r, gid_t e, gid_t s);
00093 int setresuid(uid_t r, uid_t e, uid_t s);
00094 int getresgid(gid_t *r, gid_t *e, gid_t *s);
00095 int getresuid(uid_t *r, uid_t *e, uid_t *s);
00096 }
00097 #endif
00098 #endif
00099 #endif // not WINDOWS
00100
00101 bool XrdSysPriv::fDebug = 0;
00102
00103
00104 XrdSysRecMutex XrdSysPriv::fgMutex;
00105
00106
00107 int XrdSysPriv::Restore(bool saved)
00108 {
00109
00110
00111
00112 #if !defined(WINDOWS)
00113
00114 uid_t ruid = 0, euid = 0, suid = 0;
00115 if (getresuid(&ruid, &euid, &suid) != 0)
00116 return XSPERR(errno);
00117
00118
00119 uid_t uid = saved ? suid : ruid;
00120
00121
00122 if (euid != uid) {
00123
00124
00125 if (setresuid(NOUC, uid, NOUC) != 0)
00126 return XSPERR(errno);
00127
00128
00129 if (geteuid() != uid)
00130 return XSPERR(errno);
00131 }
00132
00133
00134 uid_t rgid = 0, egid = 0, sgid = 0;
00135 if (getresgid(&rgid, &egid, &sgid) != 0)
00136 return XSPERR(errno);
00137
00138
00139 gid_t gid = saved ? sgid : rgid;
00140
00141
00142 if (egid != gid) {
00143
00144
00145 if (setresgid(NOGC, gid, NOGC) != 0)
00146 return XSPERR(errno);
00147
00148
00149 if (getegid() != gid)
00150 return XSPERR(errno);
00151 }
00152
00153 #endif
00154
00155 return 0;
00156 }
00157
00158
00159 int XrdSysPriv::ChangeTo(uid_t newuid, gid_t newgid)
00160 {
00161
00162
00163
00164
00165
00166 #if !defined(WINDOWS)
00167
00168 uid_t oeuid = geteuid();
00169 gid_t oegid = getegid();
00170
00171
00172 if (oeuid && XrdSysPriv::Restore(0) != 0)
00173 return XSPERR(errno);
00174
00175
00176 if (newgid != oegid) {
00177
00178
00179 if (setresgid(NOGC, newgid, oegid) != 0)
00180 return XSPERR(errno);
00181
00182
00183 uid_t rgid = 0, egid = 0, sgid = 0;
00184 if (getresgid(&rgid, &egid, &sgid) != 0)
00185 return XSPERR(errno);
00186
00187
00188 if (egid != newgid)
00189 return XSPERR(errno);
00190 }
00191
00192
00193 if (newuid != oeuid) {
00194
00195
00196 if (setresuid(NOUC, newuid, oeuid) != 0)
00197 return XSPERR(errno);
00198
00199
00200 uid_t ruid = 0, euid = 0, suid = 0;
00201 if (getresuid(&ruid, &euid, &suid) != 0)
00202 return XSPERR(errno);
00203
00204
00205 if (euid != newuid)
00206 return XSPERR(errno);
00207 }
00208
00209 #endif
00210
00211 return 0;
00212 }
00213
00214
00215 int XrdSysPriv::ChangePerm(uid_t newuid, gid_t newgid)
00216 {
00217
00218
00219
00220
00221
00222 XrdSysPriv::fgMutex.Lock();
00223 #if !defined(WINDOWS)
00224
00225 uid_t cruid = 0, ceuid = 0, csuid = 0;
00226 if (getresuid(&cruid, &ceuid, &csuid) != 0) {
00227 XrdSysPriv::fgMutex.UnLock();
00228 return XSPERR(errno);
00229 }
00230
00231
00232 uid_t crgid = 0, cegid = 0, csgid = 0;
00233 if (getresgid(&crgid, &cegid, &csgid) != 0) {
00234 XrdSysPriv::fgMutex.UnLock();
00235 return XSPERR(errno);
00236 }
00237
00238 if (ceuid && XrdSysPriv::Restore(0) != 0) {
00239 XrdSysPriv::fgMutex.UnLock();
00240 return XSPERR(errno);
00241 }
00242
00243 if (newgid != cegid || newgid != crgid) {
00244
00245
00246 if (setresgid(newgid, newgid, newgid) != 0) {
00247 XrdSysPriv::fgMutex.UnLock();
00248 return XSPERR(errno);
00249 }
00250
00251 uid_t rgid = 0, egid = 0, sgid = 0;
00252 if (getresgid(&rgid, &egid, &sgid) != 0) {
00253 XrdSysPriv::fgMutex.UnLock();
00254 return XSPERR(errno);
00255 }
00256
00257 if (rgid != newgid || egid != newgid) {
00258 XrdSysPriv::fgMutex.UnLock();
00259 return XSPERR(errno);
00260 }
00261 }
00262
00263
00264 if (newuid != ceuid || newuid != cruid) {
00265
00266
00267 if (setresuid(newuid, newuid, newuid) != 0) {
00268 XrdSysPriv::fgMutex.UnLock();
00269 return XSPERR(errno);
00270 }
00271
00272 uid_t ruid = 0, euid = 0, suid = 0;
00273 if (getresuid(&ruid, &euid, &suid) != 0) {
00274 XrdSysPriv::fgMutex.UnLock();
00275 return XSPERR(errno);
00276 }
00277
00278 if (ruid != newuid || euid != newuid) {
00279 XrdSysPriv::fgMutex.UnLock();
00280 return XSPERR(errno);
00281 }
00282 }
00283 #endif
00284
00285 XrdSysPriv::fgMutex.UnLock();
00286
00287
00288 return 0;
00289 }
00290
00291
00292 void XrdSysPriv::DumpUGID(const char *msg)
00293 {
00294
00295
00296 #if !defined(WINDOWS)
00297 XrdSysPriv::fgMutex.Lock();
00298
00299 uid_t ruid = 0, euid = 0, suid = 0;
00300 if (getresuid(&ruid, &euid, &suid) != 0)
00301 return;
00302
00303
00304 uid_t rgid = 0, egid = 0, sgid = 0;
00305 if (getresgid(&rgid, &egid, &sgid) != 0)
00306 return;
00307
00308 cout << "XrdSysPriv: " << endl;
00309 cout << "XrdSysPriv: dump values: " << (msg ? msg : "") << endl;
00310 cout << "XrdSysPriv: " << endl;
00311 cout << "XrdSysPriv: real = (" << ruid <<","<< rgid <<")" << endl;
00312 cout << "XrdSysPriv: effective = (" << euid <<","<< egid <<")" << endl;
00313 cout << "XrdSysPriv: saved = (" << suid <<","<< sgid <<")" << endl;
00314 cout << "XrdSysPriv: " << endl;
00315 XrdSysPriv::fgMutex.UnLock();
00316 #endif
00317 }
00318
00319
00320
00321
00322 XrdSysPrivGuard::XrdSysPrivGuard(uid_t uid, gid_t gid)
00323 {
00324
00325
00326
00327 dum = 1;
00328 valid = 0;
00329
00330 Init(uid, gid);
00331 }
00332
00333
00334 XrdSysPrivGuard::XrdSysPrivGuard(const char *usr)
00335 {
00336
00337
00338
00339 dum = 1;
00340 valid = 0;
00341
00342 #if !defined(WINDOWS)
00343 if (usr && strlen(usr) > 0) {
00344 struct passwd *pw = getpwnam(usr);
00345 if (pw)
00346 Init(pw->pw_uid, pw->pw_gid);
00347 }
00348 #else
00349 if (usr) { }
00350 #endif
00351 }
00352
00353
00354 XrdSysPrivGuard::~XrdSysPrivGuard()
00355 {
00356
00357
00358 if (!dum) {
00359 XrdSysPriv::Restore();
00360 XrdSysPriv::fgMutex.UnLock();
00361 }
00362 }
00363
00364
00365 void XrdSysPrivGuard::Init(uid_t uid, gid_t gid)
00366 {
00367
00368
00369
00370 dum = 1;
00371 valid = 1;
00372
00373
00374 if (XrdSysPriv::fDebug)
00375 XrdSysPriv::DumpUGID("before Init()");
00376
00377 #if !defined(WINDOWS)
00378 XrdSysPriv::fgMutex.Lock();
00379 uid_t ruid = 0, euid = 0, suid = 0;
00380 gid_t rgid = 0, egid = 0, sgid = 0;
00381 if (getresuid(&ruid, &euid, &suid) == 0 &&
00382 getresgid(&rgid, &egid, &sgid) == 0) {
00383 if ((euid != uid) || (egid != gid)) {
00384 if (!ruid) {
00385
00386 if (XrdSysPriv::ChangeTo(uid, gid) != 0)
00387 valid = 0;
00388 dum = 0;
00389 } else {
00390
00391 valid = 0;
00392 }
00393 }
00394 } else {
00395
00396 valid = 0;
00397 }
00398
00399 if (dum)
00400 XrdSysPriv::fgMutex.UnLock();
00401 #endif
00402
00403 if (XrdSysPriv::fDebug)
00404 XrdSysPriv::DumpUGID("after Init()");
00405 }