35 #include <sys/types.h> 44 namespace std { using ::string; }
51 #define kMAXPATHLEN 4096 53 int assertdir(
const std::string &path, uid_t u, gid_t g,
unsigned int mode);
54 int changeown(
const std::string &path, uid_t u, gid_t g);
56 int loginuser(
const std::string &home,
const std::string &user, uid_t u, gid_t g);
57 int mvfile(
const std::string &from,
const std::string &to, uid_t u, gid_t g,
unsigned int mode);
58 int completercfile(
const std::string &rcfile,
const std::string &sessdir,
59 const std::string &stag,
const std::string &adminpath);
60 int setownerships(
int euid,
const std::string &us,
const std::string &
gr,
61 const std::string &creds,
const std::string &dsrcs,
62 const std::string &ddir,
const std::string &ddiro,
63 const std::string &ord,
const std::string &stag);
65 const std::string &logfile,
const std::string &rcfile);
68 void start_ps(
int argc,
char **argv);
79 va_start(ap,
va_(fmt));
80 vsnprintf(buf,
sizeof(buf), fmt, ap);
84 fprintf(
gLogger,
"proofexecv: %s\n", buf);
86 fprintf(stderr,
"proofexecv: %s\n", buf);
94 int main(
int argc,
char **argv)
99 Info(
"argc=%d: at least 2 additional argument (the process type and debug level) are required - exit",
103 if ((
gType = atoi(argv[1])) < 0) {
104 Info(
"ERROR: invalid process type %d (must be > 0) - exit",
gType);
113 }
else if (
gType == 20) {
118 Info(
"ERROR: process type %d not yet implemented",
gType);
132 Info(
"argc=%d: at least 5 additional arguments required - exit", argc);
144 std::string sockpath = argv[3];
145 rpdunix *uconn =
new rpdunix(sockpath.c_str());
146 if (!uconn || (uconn && !uconn->isvalid(0))) {
147 Info(
"ERROR: failure calling back parent on '%s'", sockpath.c_str());
154 if ((rcc = uconn->recvdesc(fd)) != 0) {
155 Info(
"ERROR: failure receiving open descriptor from parent (errno: %d)", -rcc);
164 if (dup2(fd, STDIN_FILENO) != 0)
165 Info(
"WARNING: failure duplicating STDIN (errno: %d)", errno);
166 if (dup2(fd, STDOUT_FILENO) != 0)
167 Info(
"WARNING: failure duplicating STDOUT (errno: %d)", errno);
171 char **argvv =
new char *[na + 1];
177 argvv[ka] = argv[ia];
183 execv(argv[4], argvv);
186 Info(
"ERROR: returned from execv: bad, bad sign !!!");
197 Info(
"argc=%d: at least 5 additional arguments required - exit", argc);
215 std::string errlog(argv[6]);
216 if (!(
gLogger = fopen(errlog.c_str(),
"a"))) {
217 Info(
"FATAL: could not open '%s' for error logging - errno: %d",
218 errlog.c_str(), (int) errno);
224 snprintf(spid, 20,
"%d", (
int)getpid());
227 std::string user = argv[3];
228 struct passwd *pw = getpwnam(user.c_str());
230 Info(
"ERROR: could noy get identity info for '%s' - errno: %d", user.c_str(), (int) errno);
236 std::string::size_type loc = 0;
240 std::string sessdir(argv[4]), logfile(argv[4]), tenvfile, trcfile;
243 if ((loc = sessdir.rfind(
'/')) != std::string::npos) sessdir.erase(loc, std::string::npos);
248 if ((loc = sessdir.rfind(
'/')) != std::string::npos) sessdir.erase(loc, std::string::npos);
250 if ((loc = tenvfile.rfind(
"<pid>")) != std::string::npos) tenvfile.erase(loc, std::string::npos);
253 trcfile +=
".rootrc";
256 if ((loc = sessdir.find(
"<pid>")) != std::string::npos) sessdir.replace(loc, 5, spid);
257 if (
assertdir(sessdir, uid, gid, 0755) != 0) {
258 Info(
"ERROR: could not assert dir '%s'", sessdir.c_str());
261 Info(
"session dir: %s", sessdir.c_str());
264 while ((loc = logfile.find(
"<pid>")) != std::string::npos) { logfile.replace(loc, 5, spid); }
265 std::string stag(logfile), envfile(logfile), userdir(logfile), rcfile(logfile);
271 if (
assertdir(userdir, uid, gid, 0755) != 0) {
272 Info(
"ERROR: could not assert dir '%s'", userdir.c_str());
277 if ((loc = stag.rfind(
'/')) != std::string::npos) stag.erase(0, loc);
278 if ((loc = stag.find(
'-')) != std::string::npos) loc = stag.find(
'-', loc+1);
279 if (loc != std::string::npos) stag.erase(0, loc+1);
280 Info(
"session tag: %s", stag.c_str());
283 std::string sockpath = argv[5];
284 rpdunix *uconn =
new rpdunix(sockpath.c_str());
285 if (!uconn || (uconn && !uconn->isvalid(0))) {
286 Info(
"ERROR: failure calling back parent on '%s'", sockpath.c_str());
287 if (uconn)
delete uconn;
293 if ((rcc = uconn->send((
int) getpid())) != 0) {
294 Info(
"ERROR: failure sending pid to parent (errno: %d)", -rcc);
301 if ((rcc = uconn->recv(msg)) != 0) {
302 Info(
"ERROR: failure receiving admin path and executable from parent (errno: %d)", -rcc);
307 std::string srvadmin, adminpath, pspath;
308 msg >> srvadmin >> adminpath >> pspath >> ppid;
309 Info(
"srv admin path: %s", srvadmin.c_str());
310 Info(
"partial admin path: %s", adminpath.c_str());
311 Info(
"executable: %s", pspath.c_str());
312 Info(
"parent pid: %d", ppid);
316 if ((rcc = uconn->recv(msg)) != 0) {
317 Info(
"ERROR: failure receiving information about dataset and data dir(s) from parent (errno: %d)", -rcc);
322 std::string
group, creds, ord, datadir, ddiropts, datasetsrcs;
323 msg >> euid >> group >> creds >> ord >> datadir >> ddiropts >> datasetsrcs;
324 Info(
"euid at startup: %d", euid);
325 Info(
"group, ord: %s, %s", group.c_str(), ord.c_str());
326 Info(
"datadir: %s", datadir.c_str());
327 Info(
"datasetsrcs: %s", datasetsrcs.c_str());
330 if (
setownerships(euid, user, group, creds, datasetsrcs, datadir, ddiropts,
332 Info(
"ERROR: problems setting relevant user ownerships");
338 if (
mvfile(tenvfile, envfile, uid, gid, 0644) != 0) {
339 Info(
"ERROR: problems renaming '%s' to '%s' (errno: %d)",
340 tenvfile.c_str(), envfile.c_str(), errno);
345 if (
mvfile(trcfile, rcfile, uid, gid, 0644) != 0) {
346 Info(
"ERROR: problems renaming '%s' to '%s' (errno: %d)",
347 trcfile.c_str(), rcfile.c_str(), errno);
354 Info(
"ERROR: problems completing '%s'", rcfile.c_str());
360 Info(
"ERROR: problems setting environment from '%s'", envfile.c_str());
367 Info(
"ERROR: problems exporting file descriptor");
374 if (
loginuser(userdir, user, uid, gid) != 0) {
375 Info(
"ERROR: problems login user '%s' in", user.c_str());
382 Info(
"ERROR: problems redirecting logs to '%s'", logfile.c_str());
388 char *argvv[6] = {0};
391 if (adminpath.length() > 0) {
393 int len = srvadmin.length() + strlen(
"xpdpath:") + 1;
394 sxpd =
new char[len];
395 snprintf(sxpd, len,
"xpdpath:%s", adminpath.c_str());
407 argvv[0] = (
char *) pspath.c_str();
408 argvv[1] = (
char *)((
gType == 0) ?
"proofslave" :
"proofserv");
409 argvv[2] = (
char *)
"xpd";
410 argvv[3] = (
char *)sxpd;
411 argvv[4] = (
char *)slog;
417 sigaddset(&myset, SIGUSR1);
418 sigaddset(&myset, SIGUSR2);
419 pthread_sigmask(SIG_UNBLOCK, &myset, 0);
421 Info(
"%d: uid: %d, euid: %d", (
int)getpid(), getuid(), geteuid());
422 Info(
"argvv: '%s' '%s' '%s' '%s' '%s'", argvv[0], argvv[1], argvv[2], argvv[3], argvv[4]);
425 execv(pspath.c_str(), argvv);
428 Info(
"ERROR: returned from execv: bad, bad sign !!!");
435 int loginuser(
const std::string &home,
const std::string &user, uid_t uid, gid_t gid)
437 if (chdir(home.c_str()) != 0) {
438 Info(
"loginuser: ERROR: can't change directory to %s, euid: %d, uid: %d; errno: %d",
439 home.c_str(), geteuid(), getuid(), errno);
444 size_t len = home.length() + 8;
445 char *
h =
new char[len];
446 snprintf(h, len,
"HOME=%s", home.c_str());
448 if (
gDebug > 0)
Info(
"loginuser: set '%s'", h);
451 char *u =
new char[len];
452 snprintf(u, len,
"USER=%s", user.c_str());
454 if (
gDebug > 0)
Info(
"loginuser: set '%s'", u);
458 if (geteuid() != uid) {
459 rpdprivguard pguard((uid_t)0, (gid_t)0);
460 if (rpdbadpguard(pguard, uid)) {
461 Info(
"loginuser: ERROR: could not get required privileges");
464 initgroups(user.c_str(), gid);
469 Info(
"loginuser: acquiring target user identity (%d,%d)", uid, gid);
470 if (rpdpriv::changeperm(uid, gid) != 0) {
471 Info(
"loginuser: ERROR: can't acquire '%s' identity", user.c_str());
484 int assertdir(
const std::string &path, uid_t u, gid_t g,
unsigned int mode)
486 if (path.length() <= 0)
return -1;
488 rpdprivguard pguard((uid_t)0, (gid_t)0);
489 if (rpdbadpguard(pguard, u)) {
490 Info(
"assertdir: ERROR: could not get privileges (errno: %d)", errno);
495 if (mkdir(path.c_str(), mode) != 0 && (errno != EEXIST)) {
496 Info(
"assertdir: ERROR: unable to create path: %s (errno: %d)", path.c_str(), errno);
500 if (chown(path.c_str(), u, g) == -1) {
501 Info(
"assertdir: ERROR: unable to set ownership on path: %s (errno: %d)", path.c_str(), errno);
514 int mvfile(
const std::string &from,
const std::string &to, uid_t u, gid_t g,
unsigned int mode)
516 if (from.length() <= 0 || to.length() <= 0)
return -1;
518 rpdprivguard pguard((uid_t)0, (gid_t)0);
519 if (rpdbadpguard(pguard, u)) {
520 Info(
"mvfile: ERROR: could not get privileges (errno: %d)", errno);
525 if (rename(from.c_str(), to.c_str()) != 0) {
526 Info(
"mvfile: ERROR: unable to rename '%s' to '%s' (errno: %d)", from.c_str(), to.c_str(), errno);
531 if (chmod(to.c_str(), mode) == -1) {
532 Info(
"mvfile: ERROR: unable to set mode %o on path: %s (errno: %d)", mode, to.c_str(), errno);
537 if (chown(to.c_str(), u, g) == -1) {
538 Info(
"mvfile: ERROR: unable to set ownership on path: %s (errno: %d)", to.c_str(), errno);
550 const std::string &stag,
const std::string &adminpath)
552 FILE *frc = fopen(rcfile.c_str(),
"a");
554 Info(
"completercfile: ERROR: unable to open rc file: '%s' (errno: %d)", rcfile.c_str(), errno);
558 fprintf(frc,
"# The session working dir\n");
559 fprintf(frc,
"ProofServ.SessionDir: %s\n", sessdir.c_str());
561 fprintf(frc,
"# Session tag\n");
562 fprintf(frc,
"ProofServ.SessionTag: %s\n", stag.c_str());
564 fprintf(frc,
"# Admin path\n");
565 fprintf(frc,
"ProofServ.AdminPath: %s%d.status\n", adminpath.c_str(), (int)getpid());
577 const std::string &logfile,
const std::string &rcfile)
579 if (envfile.length() <= 0)
return -1;
584 len = logfile.length() + strlen(
"ROOTPROOFLOGFILE") + 4;
585 h =
new char[len + 1];
586 snprintf(h, len + 1,
"ROOTPROOFLOGFILE=%s", logfile.c_str());
589 Info(
"setproofservenv: set '%s'", h);
591 len = rcfile.length() + strlen(
"ROOTRCFILE") + 4;
592 h =
new char[len + 1];
593 snprintf(h, len + 1,
"ROOTRCFILE=%s", rcfile.c_str());
596 Info(
"setproofservenv: set '%s'", h);
598 std::fstream fin(envfile.c_str(), std::ios::in);
600 Info(
"setproofservenv: ERROR: unable to open env file: %s (errno: %d)", envfile.c_str(), errno);
606 std::getline(fin, line);
607 if (line[line.length()-1] ==
'\n') line.erase(line.length()-1);
608 if (line.length() > 0) {
609 h =
new char[line.length() + 1];
610 snprintf(h, line.length()+1,
"%s", line.c_str());
613 Info(
"setproofservenv: set '%s'", h);
630 if (!conn || (conn && !conn->isvalid(0))) {
631 Info(
"exportsock: ERROR: connection is %s", (conn ?
"invalid" :
"undefined"));
636 int d = conn->exportfd();
639 if (d == 0 || d == 1 || d == 2) {
642 while (natt > 0 && (fd = dup(d)) <= 2) {
643 if (fd != d)
close(fd);
647 if (natt <= 0 && fd <= 2) {
648 Info(
"exportsock: ERROR: no free filedescriptor!");
660 char *rootopensock =
new char[33];
661 snprintf(rootopensock, 33,
"ROOTOPENSOCK=%d", d);
662 putenv(rootopensock);
675 Info(
"redirectoutput: enter: %s", logfile.c_str());
677 if (logfile.length() <= 0) {
678 Info(
"redirectoutput: ERROR: logfile path undefined");
683 Info(
"redirectoutput: reopen %s", logfile.c_str());
684 FILE *
flog = freopen(logfile.c_str(),
"a", stdout);
686 Info(
"redirectoutput: ERROR: could not freopen stdout (errno: %d)", errno);
691 Info(
"redirectoutput: dup2 ...");
692 if ((dup2(fileno(stdout), fileno(stderr))) < 0) {
693 Info(
"redirectoutput: ERROR: could not redirect stderr (errno: %d)", errno);
702 int len = strlen(
"ROOTPROOFDONOTREDIR=2");
703 char *notredir =
new char[len + 1];
704 snprintf(notredir, len+1,
"ROOTPROOFDONOTREDIR=2");
708 Info(
"redirectoutput: done!");
718 const std::string &creds,
const std::string &dsrcs,
719 const std::string &ddir,
const std::string &ddiro,
720 const std::string &ord,
const std::string &stag)
723 struct passwd *pwad, *pwus;
724 if (!(pwad = getpwuid(euid))) {
725 Info(
"setownerships: ERROR: problems getting 'struct passwd' for" 726 " uid: %d (errno: %d)", euid, (
int)errno);
729 if (!(pwus = getpwnam(us.c_str()))) {
730 Info(
"setownerships: ERROR: problems getting 'struct passwd' for" 731 " user: '%s' (errno: %d)", us.c_str(), (int)errno);
737 if (dsrcs.length() > 0) {
738 std::string dsrc(dsrcs);
739 std::string::size_type loc = dsrcs.find(
',', 0);
741 if (loc != std::string::npos) dsrc.erase(loc, std::string::npos);
742 if (dsrc.length() > 0) {
749 Info(
"setownerships: ERROR: problems asserting '%s' in mode 0755" 750 " (errno: %d)", d.c_str(), (int)errno);
753 Info(
"setownerships: ERROR: problems asserting '%s' in mode 0777" 754 " (errno: %d)", d.c_str(), (int)errno);
757 dsrc.assign(dsrcs, loc + 1, dsrcs.length() - loc);
759 }
while ((loc = dsrcs.find(
',', loc)) != std::string::npos);
764 if (ddir.length() > 0 && ord.length() > 0 && stag.length() > 0) {
765 std::string dgr(ddir);
766 dgr +=
"/"; dgr +=
gr;
769 unsigned int mode = 0755;
770 if (ddiro.find(
'g') != std::string::npos) mode = 0775;
771 if (ddiro.find(
'a') != std::string::npos ||
772 ddiro.find(
'o') != std::string::npos) mode = 0777;
773 std::string dus(dgr);
774 dus +=
"/"; dus += us;
776 dus +=
"/"; dus += ord;
778 dus +=
"/"; dus += stag;
783 Info(
"setownerships: ERROR: problems asserting '%s' in mode %o" 784 " (errno: %d)", dus.c_str(), mode, (int)errno);
786 Info(
"setownerships: ERROR: problems asserting '%s' in mode 0777" 787 " (errno: %d)", dgr.c_str(), (int)errno);
792 if (creds.length() > 0) {
794 Info(
"setownerships: ERROR: problems changing owenership of '%s'", creds.c_str());
808 int changeown(
const std::string &path, uid_t u, gid_t g)
810 if (path.length() <= 0)
return -1;
813 DIR *dir = opendir(path.c_str());
816 std::string proot(path);
817 if (!(proot.rfind(
'/') != proot.length() - 1)) proot +=
"/";
819 struct dirent *ent = 0;
820 while ((ent = readdir(dir))) {
821 if (ent->d_name[0] ==
'.' || !strcmp(ent->d_name,
".."))
continue;
822 std::string fn(proot);
827 Info(
"changeown: ERROR: problems changing recursively ownership of '%s'",
838 if (errno != 0 && (errno != ENOTDIR)) {
839 Info(
"changeown: ERROR: problems opening '%s' (errno: %d)",
840 path.c_str(), (int)errno);
844 rpdprivguard pguard((uid_t)0, (gid_t)0);
845 if (rpdbadpguard(pguard, u)) {
846 Info(
"changeown: ERROR: could not get privileges (errno: %d)", errno);
850 if (chown(path.c_str(), u, g) == -1) {
851 Info(
"changeown: ERROR: cannot set user ownership on path '%s' (errno: %d)",
852 path.c_str(), errno);
void start_rootd(int argc, char **argv)
Process a request to start a rootd server.
void Info(const char *va_(fmt),...)
Write info message to syslog.
void start_ps(int argc, char **argv)
Process a request to start a proofserv process.
int setownerships(int euid, const std::string &us, const std::string &gr, const std::string &creds, const std::string &dsrcs, const std::string &ddir, const std::string &ddiro, const std::string &ord, const std::string &stag)
Set user ownerships on some critical files or directories.
int redirectoutput(const std::string &logfile)
Redirect stdout to 'logfile' On success return 0.
int setproofservenv(const std::string &envfile, const std::string &logfile, const std::string &rcfile)
Initialize the environment following the content of 'envfile'.
int loginuser(const std::string &home, const std::string &user, uid_t u, gid_t g)
Login the user in its space.
int exportsock(rpdunix *conn)
Export the descriptor of 'conn' so that it can used in the execv application.
int mvfile(const std::string &from, const std::string &to, uid_t u, gid_t g, unsigned int mode)
Move file form 'from' to 'to', making sure that it is owned by the entity described by {u...
int assertdir(const std::string &path, uid_t u, gid_t g, unsigned int mode)
Make sure that 'path' exists, it is owned by the entity described by {u,g} and its mode is 'mode'...
int changeown(const std::string &path, uid_t u, gid_t g)
Change the ownership of 'path' to the entity described by {u,g}.
int completercfile(const std::string &rcfile, const std::string &sessdir, const std::string &stag, const std::string &adminpath)
Finalize the rc file with the missing pieces.
int main(int argc, char **argv)
Program executed via system starting proofserv instances.