35 #include <sys/types.h>
44 static int gDebug = 0;
45 static FILE *gLogger = 0;
47 #define kMAXPATHLEN 4096
49 int assertdir(
const std::string &path, uid_t u, gid_t g,
unsigned int mode);
50 int changeown(
const std::string &path, uid_t u, gid_t g);
51 int exportsock(rpdunix *conn);
52 int loginuser(
const std::string &home,
const std::string &user, uid_t u, gid_t g);
53 int mvfile(
const std::string &from,
const std::string &to, uid_t u, gid_t g,
unsigned int mode);
54 int completercfile(
const std::string &rcfile,
const std::string &sessdir,
55 const std::string &stag,
const std::string &adminpath);
56 int setownerships(
int euid,
const std::string &us,
const std::string &gr,
57 const std::string &creds,
const std::string &dsrcs,
58 const std::string &ddir,
const std::string &ddiro,
59 const std::string &ord,
const std::string &stag);
60 int setproofservenv(
const std::string &envfile,
61 const std::string &logfile,
const std::string &rcfile);
62 int redirectoutput(
const std::string &logfile);
64 void start_ps(
int argc,
char **argv);
69 void Info(
const char *va_(fmt), ...)
71 char buf[kMAXPATHLEN];
74 va_start(ap,va_(fmt));
75 vsnprintf(buf,
sizeof(buf), fmt, ap);
79 fprintf(gLogger,
"proofexecv: %s\n", buf);
81 fprintf(stderr,
"proofexecv: %s\n", buf);
89 int main(
int argc,
char **argv)
94 Info(
"argc=%d: at least 2 additional argument (the process type and debug level) are required - exit",
98 if ((gType = atoi(argv[1])) < 0) {
99 Info(
"ERROR: invalid process type %d (must be > 0) - exit", gType);
102 gDebug = atoi(argv[2]);
106 start_ps(argc, argv);
108 }
else if (gType == 20) {
110 Info(
"ERROR: 'rootd' has been removed from ROOT");
113 Info(
"ERROR: process type %d not yet implemented", gType);
124 void start_ps(
int argc,
char **argv)
127 Info(
"argc=%d: at least 5 additional arguments required - exit", argc);
145 std::string errlog(argv[6]);
146 if (!(gLogger = fopen(errlog.c_str(),
"a"))) {
147 Info(
"FATAL: could not open '%s' for error logging - errno: %d",
148 errlog.c_str(), (int) errno);
154 snprintf(spid, 20,
"%d", (
int)getpid());
157 std::string user = argv[3];
158 struct passwd *pw = getpwnam(user.c_str());
160 Info(
"ERROR: could noy get identity info for '%s' - errno: %d", user.c_str(), (int) errno);
163 uid_t uid = pw->pw_uid;
164 uid_t gid = pw->pw_gid;
166 std::string::size_type loc = 0;
170 std::string sessdir(argv[4]), logfile(argv[4]), tenvfile, trcfile;
173 if ((loc = sessdir.rfind(
'/')) != std::string::npos) sessdir.erase(loc, std::string::npos);
178 if ((loc = sessdir.rfind(
'/')) != std::string::npos) sessdir.erase(loc, std::string::npos);
180 if ((loc = tenvfile.rfind(
"<pid>")) != std::string::npos) tenvfile.erase(loc, std::string::npos);
183 trcfile +=
".rootrc";
186 if ((loc = sessdir.find(
"<pid>")) != std::string::npos) sessdir.replace(loc, 5, spid);
187 if (assertdir(sessdir, uid, gid, 0755) != 0) {
188 Info(
"ERROR: could not assert dir '%s'", sessdir.c_str());
191 Info(
"session dir: %s", sessdir.c_str());
194 while ((loc = logfile.find(
"<pid>")) != std::string::npos) { logfile.replace(loc, 5, spid); }
195 std::string stag(logfile), envfile(logfile), userdir(logfile), rcfile(logfile);
201 if (assertdir(userdir, uid, gid, 0755) != 0) {
202 Info(
"ERROR: could not assert dir '%s'", userdir.c_str());
207 if ((loc = stag.rfind(
'/')) != std::string::npos) stag.erase(0, loc);
208 if ((loc = stag.find(
'-')) != std::string::npos) loc = stag.find(
'-', loc+1);
209 if (loc != std::string::npos) stag.erase(0, loc+1);
210 Info(
"session tag: %s", stag.c_str());
213 std::string sockpath = argv[5];
214 rpdunix *uconn =
new rpdunix(sockpath.c_str());
215 if (!uconn || (uconn && !uconn->isvalid(0))) {
216 Info(
"ERROR: failure calling back parent on '%s'", sockpath.c_str());
217 if (uconn)
delete uconn;
223 if ((rcc = uconn->send((
int) getpid())) != 0) {
224 Info(
"ERROR: failure sending pid to parent (errno: %d)", -rcc);
231 if ((rcc = uconn->recv(msg)) != 0) {
232 Info(
"ERROR: failure receiving admin path and executable from parent (errno: %d)", -rcc);
237 std::string srvadmin, adminpath, pspath;
238 msg >> srvadmin >> adminpath >> pspath >> ppid;
239 Info(
"srv admin path: %s", srvadmin.c_str());
240 Info(
"partial admin path: %s", adminpath.c_str());
241 Info(
"executable: %s", pspath.c_str());
242 Info(
"parent pid: %d", ppid);
246 if ((rcc = uconn->recv(msg)) != 0) {
247 Info(
"ERROR: failure receiving information about dataset and data dir(s) from parent (errno: %d)", -rcc);
252 std::string group, creds, ord, datadir, ddiropts, datasetsrcs;
253 msg >> euid >> group >> creds >> ord >> datadir >> ddiropts >> datasetsrcs;
254 Info(
"euid at startup: %d", euid);
255 Info(
"group, ord: %s, %s", group.c_str(), ord.c_str());
256 Info(
"datadir: %s", datadir.c_str());
257 Info(
"datasetsrcs: %s", datasetsrcs.c_str());
260 if (setownerships(euid, user, group, creds, datasetsrcs, datadir, ddiropts,
262 Info(
"ERROR: problems setting relevant user ownerships");
268 if (mvfile(tenvfile, envfile, uid, gid, 0644) != 0) {
269 Info(
"ERROR: problems renaming '%s' to '%s' (errno: %d)",
270 tenvfile.c_str(), envfile.c_str(), errno);
275 if (mvfile(trcfile, rcfile, uid, gid, 0644) != 0) {
276 Info(
"ERROR: problems renaming '%s' to '%s' (errno: %d)",
277 trcfile.c_str(), rcfile.c_str(), errno);
283 if (completercfile(rcfile, userdir, stag, adminpath) != 0) {
284 Info(
"ERROR: problems completing '%s'", rcfile.c_str());
289 if (setproofservenv(envfile, logfile, rcfile) != 0) {
290 Info(
"ERROR: problems setting environment from '%s'", envfile.c_str());
296 if (exportsock(uconn) != 0) {
297 Info(
"ERROR: problems exporting file descriptor");
304 if (loginuser(userdir, user, uid, gid) != 0) {
305 Info(
"ERROR: problems login user '%s' in", user.c_str());
311 if (redirectoutput(logfile) != 0) {
312 Info(
"ERROR: problems redirecting logs to '%s'", logfile.c_str());
318 char *argvv[6] = {0};
321 if (adminpath.length() > 0) {
323 int len = srvadmin.length() + strlen(
"xpdpath:") + 1;
324 sxpd =
new char[len];
325 snprintf(sxpd, len,
"xpdpath:%s", adminpath.c_str());
329 snprintf(sxpd, 10,
"%d", ppid);
334 snprintf(slog, 10,
"%d", gDebug);
337 argvv[0] = (
char *) pspath.c_str();
338 argvv[1] = (
char *)((gType == 0) ?
"proofslave" :
"proofserv");
339 argvv[2] = (
char *)
"xpd";
340 argvv[3] = (
char *)sxpd;
341 argvv[4] = (
char *)slog;
347 sigaddset(&myset, SIGUSR1);
348 sigaddset(&myset, SIGUSR2);
349 pthread_sigmask(SIG_UNBLOCK, &myset, 0);
351 Info(
"%d: uid: %d, euid: %d", (
int)getpid(), getuid(), geteuid());
352 Info(
"argvv: '%s' '%s' '%s' '%s' '%s'", argvv[0], argvv[1], argvv[2], argvv[3], argvv[4]);
355 execv(pspath.c_str(), argvv);
358 Info(
"ERROR: returned from execv: bad, bad sign !!!");
365 int loginuser(
const std::string &home,
const std::string &user, uid_t uid, gid_t gid)
367 if (chdir(home.c_str()) != 0) {
368 Info(
"loginuser: ERROR: can't change directory to %s, euid: %d, uid: %d; errno: %d",
369 home.c_str(), geteuid(), getuid(), errno);
374 size_t len = home.length() + 8;
375 char *h =
new char[len];
376 snprintf(h, len,
"HOME=%s", home.c_str());
378 if (gDebug > 0) Info(
"loginuser: set '%s'", h);
381 char *u =
new char[len];
382 snprintf(u, len,
"USER=%s", user.c_str());
384 if (gDebug > 0) Info(
"loginuser: set '%s'", u);
388 if (geteuid() != uid) {
389 rpdprivguard pguard((uid_t)0, (gid_t)0);
390 if (rpdbadpguard(pguard, uid)) {
391 Info(
"loginuser: ERROR: could not get required privileges");
394 initgroups(user.c_str(), gid);
399 Info(
"loginuser: acquiring target user identity (%d,%d)", uid, gid);
400 if (rpdpriv::changeperm(uid, gid) != 0) {
401 Info(
"loginuser: ERROR: can't acquire '%s' identity", user.c_str());
414 int assertdir(
const std::string &path, uid_t u, gid_t g,
unsigned int mode)
416 if (path.length() <= 0)
return -1;
418 rpdprivguard pguard((uid_t)0, (gid_t)0);
419 if (rpdbadpguard(pguard, u)) {
420 Info(
"assertdir: ERROR: could not get privileges (errno: %d)", errno);
425 if (mkdir(path.c_str(), mode) != 0 && (errno != EEXIST)) {
426 Info(
"assertdir: ERROR: unable to create path: %s (errno: %d)", path.c_str(), errno);
430 if (chown(path.c_str(), u, g) == -1) {
431 Info(
"assertdir: ERROR: unable to set ownership on path: %s (errno: %d)", path.c_str(), errno);
444 int mvfile(
const std::string &from,
const std::string &to, uid_t u, gid_t g,
unsigned int mode)
446 if (from.length() <= 0 || to.length() <= 0)
return -1;
448 rpdprivguard pguard((uid_t)0, (gid_t)0);
449 if (rpdbadpguard(pguard, u)) {
450 Info(
"mvfile: ERROR: could not get privileges (errno: %d)", errno);
455 if (rename(from.c_str(), to.c_str()) != 0) {
456 Info(
"mvfile: ERROR: unable to rename '%s' to '%s' (errno: %d)", from.c_str(), to.c_str(), errno);
461 if (chmod(to.c_str(), mode) == -1) {
462 Info(
"mvfile: ERROR: unable to set mode %o on path: %s (errno: %d)", mode, to.c_str(), errno);
467 if (chown(to.c_str(), u, g) == -1) {
468 Info(
"mvfile: ERROR: unable to set ownership on path: %s (errno: %d)", to.c_str(), errno);
479 int completercfile(
const std::string &rcfile,
const std::string &sessdir,
480 const std::string &stag,
const std::string &adminpath)
482 FILE *frc = fopen(rcfile.c_str(),
"a");
484 Info(
"completercfile: ERROR: unable to open rc file: '%s' (errno: %d)", rcfile.c_str(), errno);
488 fprintf(frc,
"# The session working dir\n");
489 fprintf(frc,
"ProofServ.SessionDir: %s\n", sessdir.c_str());
491 fprintf(frc,
"# Session tag\n");
492 fprintf(frc,
"ProofServ.SessionTag: %s\n", stag.c_str());
494 fprintf(frc,
"# Admin path\n");
495 fprintf(frc,
"ProofServ.AdminPath: %s%d.status\n", adminpath.c_str(), (int)getpid());
506 int setproofservenv(
const std::string &envfile,
507 const std::string &logfile,
const std::string &rcfile)
509 if (envfile.length() <= 0)
return -1;
514 len = logfile.length() + strlen(
"ROOTPROOFLOGFILE") + 4;
515 h =
new char[len + 1];
516 snprintf(h, len + 1,
"ROOTPROOFLOGFILE=%s", logfile.c_str());
519 Info(
"setproofservenv: set '%s'", h);
521 len = rcfile.length() + strlen(
"ROOTRCFILE") + 4;
522 h =
new char[len + 1];
523 snprintf(h, len + 1,
"ROOTRCFILE=%s", rcfile.c_str());
526 Info(
"setproofservenv: set '%s'", h);
528 std::fstream fin(envfile.c_str(), std::ios::in);
530 Info(
"setproofservenv: ERROR: unable to open env file: %s (errno: %d)", envfile.c_str(), errno);
536 std::getline(fin, line);
537 if (line[line.length()-1] ==
'\n') line.erase(line.length()-1);
538 if (line.length() > 0) {
539 h =
new char[line.length() + 1];
540 snprintf(h, line.length()+1,
"%s", line.c_str());
543 Info(
"setproofservenv: set '%s'", h);
557 int exportsock(rpdunix *conn)
560 if (!conn || (conn && !conn->isvalid(0))) {
561 Info(
"exportsock: ERROR: connection is %s", (conn ?
"invalid" :
"undefined"));
566 int d = conn->exportfd();
569 if (d == 0 || d == 1 || d == 2) {
572 while (natt > 0 && (fd = dup(d)) <= 2) {
573 if (fd >= 0 && fd != d) close(fd);
577 if (natt <= 0 && fd <= 2) {
578 Info(
"exportsock: ERROR: no free filedescriptor!");
590 char *rootopensock =
new char[33];
591 snprintf(rootopensock, 33,
"ROOTOPENSOCK=%d", d);
592 putenv(rootopensock);
602 int redirectoutput(
const std::string &logfile)
605 Info(
"redirectoutput: enter: %s", logfile.c_str());
607 if (logfile.length() <= 0) {
608 Info(
"redirectoutput: ERROR: logfile path undefined");
613 Info(
"redirectoutput: reopen %s", logfile.c_str());
614 FILE *flog = freopen(logfile.c_str(),
"a", stdout);
616 Info(
"redirectoutput: ERROR: could not freopen stdout (errno: %d)", errno);
621 Info(
"redirectoutput: dup2 ...");
622 if ((dup2(fileno(stdout), fileno(stderr))) < 0) {
623 Info(
"redirectoutput: ERROR: could not redirect stderr (errno: %d)", errno);
628 if (gLogger != stderr) fclose(gLogger);
632 int len = strlen(
"ROOTPROOFDONOTREDIR=2");
633 char *notredir =
new char[len + 1];
634 snprintf(notredir, len+1,
"ROOTPROOFDONOTREDIR=2");
638 Info(
"redirectoutput: done!");
647 int setownerships(
int euid,
const std::string &us,
const std::string &gr,
648 const std::string &creds,
const std::string &dsrcs,
649 const std::string &ddir,
const std::string &ddiro,
650 const std::string &ord,
const std::string &stag)
653 struct passwd *pwad, *pwus;
654 if (!(pwad = getpwuid(euid))) {
655 Info(
"setownerships: ERROR: problems getting 'struct passwd' for"
656 " uid: %d (errno: %d)", euid, (
int)errno);
659 if (!(pwus = getpwnam(us.c_str()))) {
660 Info(
"setownerships: ERROR: problems getting 'struct passwd' for"
661 " user: '%s' (errno: %d)", us.c_str(), (int)errno);
667 if (dsrcs.length() > 0) {
668 std::string dsrc(dsrcs);
669 std::string::size_type loc = dsrcs.find(
',', 0);
671 if (loc != std::string::npos) dsrc.erase(loc, std::string::npos);
672 if (dsrc.length() > 0) {
676 if (assertdir(d, pwad->pw_uid, pwad->pw_gid, 0777) == 0) {
678 if (assertdir(d, pwus->pw_uid, pwus->pw_gid, 0755) != 0) {
679 Info(
"setownerships: ERROR: problems asserting '%s' in mode 0755"
680 " (errno: %d)", d.c_str(), (int)errno);
683 Info(
"setownerships: ERROR: problems asserting '%s' in mode 0777"
684 " (errno: %d)", d.c_str(), (int)errno);
687 dsrc.assign(dsrcs, loc + 1, dsrcs.length() - loc);
689 }
while ((loc = dsrcs.find(
',', loc)) != std::string::npos);
694 if (ddir.length() > 0 && ord.length() > 0 && stag.length() > 0) {
695 std::string dgr(ddir);
696 dgr +=
"/"; dgr += gr;
697 if (assertdir(dgr, pwad->pw_uid, pwad->pw_gid, 0777) == 0) {
699 unsigned int mode = 0755;
700 if (ddiro.find(
'g') != std::string::npos) mode = 0775;
701 if (ddiro.find(
'a') != std::string::npos ||
702 ddiro.find(
'o') != std::string::npos) mode = 0777;
703 std::string dus(dgr);
704 dus +=
"/"; dus += us;
705 if (assertdir(dus, pwus->pw_uid, pwus->pw_gid, mode) == 0) {
706 dus +=
"/"; dus += ord;
707 if (assertdir(dus, pwus->pw_uid, pwus->pw_gid, mode) == 0) {
708 dus +=
"/"; dus += stag;
709 if (assertdir(dus, pwus->pw_uid, pwus->pw_gid, mode) == 0) drc = 0;
713 Info(
"setownerships: ERROR: problems asserting '%s' in mode %o"
714 " (errno: %d)", dus.c_str(), mode, (int)errno);
716 Info(
"setownerships: ERROR: problems asserting '%s' in mode 0777"
717 " (errno: %d)", dgr.c_str(), (int)errno);
722 if (creds.length() > 0) {
723 if (changeown(creds, pwus->pw_uid, pwus->pw_gid) != 0) {
724 Info(
"setownerships: ERROR: problems changing owenership of '%s'", creds.c_str());
738 int changeown(
const std::string &path, uid_t u, gid_t g)
740 if (path.length() <= 0)
return -1;
743 DIR *dir = opendir(path.c_str());
746 std::string proot(path);
747 if (!(proot.rfind(
'/') != proot.length() - 1)) proot +=
"/";
749 struct dirent *ent = 0;
750 while ((ent = readdir(dir))) {
751 if (ent->d_name[0] ==
'.' || !strcmp(ent->d_name,
".."))
continue;
752 std::string fn(proot);
756 if (changeown(fn.c_str(), u, g) != 0) {
757 Info(
"changeown: ERROR: problems changing recursively ownership of '%s'",
768 if (errno != 0 && (errno != ENOTDIR)) {
769 Info(
"changeown: ERROR: problems opening '%s' (errno: %d)",
770 path.c_str(), (int)errno);
774 rpdprivguard pguard((uid_t)0, (gid_t)0);
775 if (rpdbadpguard(pguard, u)) {
776 Info(
"changeown: ERROR: could not get privileges (errno: %d)", errno);
780 if (chown(path.c_str(), u, g) == -1) {
781 Info(
"changeown: ERROR: cannot set user ownership on path '%s' (errno: %d)",
782 path.c_str(), errno);