Loading sld/Makefile.am +8 −7 Original line number Diff line number Diff line bin_PROGRAMS= sld sld_SOURCES= sld.hh \ sld.cc \ daemon.cc \ error.hh \ error.cc sld_SOURCES= src/sld.hh \ src/sld.cc \ src/daemon.hh \ src/daemon.cc \ src/error.hh \ src/error.cc CLEANFILES= *~ '\#*' CLEANFILES= *~ '\#*' .*.swp .*~ .PHONY: tar re Loading sld/configure.ac +2 −2 Original line number Diff line number Diff line Loading @@ -63,8 +63,8 @@ AC_ARG_WITH([efence], [AS_HELP_STRING([--with-efence], [link with lib efence])], [dnl action-if-given LDFLAGS="$LDFLAGS -lefence" test -r "/usr/include/efence.h" && CXXFLAGS="$CXXFLAGS -include stdlib.h -include efence.h" #test -r "/usr/include/efencepp.h" && #CXXFLAGS="$CXXFLAGS -include efencepp.h" ], [dnl action-if-not-given true Loading sld/daemon.cc→sld/src/daemon.cc +155 −160 Original line number Diff line number Diff line Loading @@ -43,7 +43,7 @@ void SLDaemon::usage(const char *argv0) const { << " -d scriptdir : Scripts directory." << std::endl << " -h : Print this usage." << std::endl << " -v : Verbose mode." << std::endl << " -l name : Set login to name." << std::endl << " -l host : Set login to host." << std::endl << " -p secret : Set pass to secret." << std::endl << " -H name : Set server host to name." << std::endl << " -P number : Set server port to number." << std::endl Loading Loading @@ -158,8 +158,8 @@ void SLDaemon::check_options() const { if (options_.scriptdir == "") throw Error(ERR_BADPARAM, "No scripts directory specified."); // Empty scripts dir // TODO // TODO: Check dir exist // TODO: Empty scripts dir } void SLDaemon::run() { char *line; Loading @@ -169,13 +169,10 @@ void SLDaemon::run() { auth(); while (1) { line = recvln(); warn(line, RCV_DATA); // call right handler try { if (!strcmp(line, "EXIT\n")) cmd_exit(); else if (!strcmp(line, "RELOAD\n")) cmd_reload(); else if (!strcmp(line, "VERSION\n")) cmd_version(); else if (!strcmp(line, "STATUS\n")) Loading @@ -186,21 +183,20 @@ void SLDaemon::run() { cmd_killall(); else if (!strcmp(line, "KILL\n")) cmd_kill(line); else if (!strncmp(line, "JOB ", 4)) cmd_job(line); else if (!strncmp(line, "EXEC ", 4)) cmd_exec(line); else if (!strncmp(line, "FILE ", 5)) cmd_file(line); else if (!strcmp(line, "UPDATE")) else if (!strcmp(line, "UPDATE\n")) cmd_update(); else proto_violation(); sendln("sld: Invalid command."); } catch (const Error &e) { e.print(); send("!! "); send(e.message()); sendln(e.message()); std::cerr << "!! " << e.message() << std::endl; } delete line; delete[] line; } } Loading Loading @@ -265,11 +261,18 @@ void SLDaemon::send(const char *data, size_t len, bool buf) { throw Error(ERR_NET, strerror(errno)); } void SLDaemon::sendln(const string &s) { if (!fprintf(socket_fs_, "%s\n", s.c_str())) throw Error(ERR_NET, strerror(errno)); if (verbose()) std::cout << SND_DATA << s << std::endl; } char *SLDaemon::recv(size_t size) { char *data = new char[size]; if (fread(data, 1, size, socket_fs_) != size) { delete data; delete[] data; throw Error(ERR_NET, strerror(errno)); } return data; Loading @@ -279,20 +282,23 @@ void SLDaemon::recv(size_t size, const string &filename) { char *data = recv(size); FILE *fs = fopen(filename.c_str(), "w"); if (fs == 0) throw Error(ERR_FILE, (string) "recv: " + strerror(errno)); throw Error(ERR_FILE, (string) "recv: fopen: " + strerror(errno)); if (fwrite(data, 1, size, fs) != size) throw Error(ERR_FILE, (string) "recv: " + strerror(errno)); throw Error(ERR_FILE, (string) "recv: fwrite: " + strerror(errno)); if (fclose(fs)) throw Error(ERR_FILE, (string) "recv: " + strerror(errno)); throw Error(ERR_FILE, (string) "recv: fclose: " + strerror(errno)); } char *SLDaemon::recvln() { char *line = new char[MAX_LINE_SIZE]; if (fgets(line, MAX_LINE_SIZE, socket_fs_) == 0) { delete line; delete[] line; throw Error(ERR_FILE, (string) "recvln: " + strerror(errno)); } if (verbose()) std::cout << SND_DATA << line; return line; } Loading @@ -307,6 +313,8 @@ void SLDaemon::flush() { void SLDaemon::auth() { unsigned char md[SHA_DIGEST_LENGTH]; char buf[MAX_LINE_SIZE]; char *buf2 = ""; BIO *bmem, *b64; BUF_MEM *bptr; Loading @@ -319,99 +327,84 @@ void SLDaemon::auth() { BIO_flush(b64); BIO_get_mem_ptr(b64, &bptr); char *buff = new char[bptr->length]; memcpy(buff, bptr->data, bptr->length-1); buff[bptr->length-1] = 0; BIO_free_all(b64); send("HOST "); send(options_.login); send("\n"); send("PASS "); send(buff); send("\n"); flush(); delete buff; return; if (bptr->length > 0) { buf2 = new char[bptr->length]; memcpy(buf2, bptr->data, bptr->length-1); buf2[bptr->length-1] = 0; } void SLDaemon::answer(const string &msg, bool prefix) { if (verbose()) std::cout << (prefix ? SND_DATA : "") << msg; send(msg); } snprintf(buf, MAX_LINE_SIZE, "HOST %s", options_.login.c_str()); sendln(buf); void SLDaemon::answer(long int i, bool prefix) { if (verbose()) std::cout << (prefix ? SND_DATA : "") << i; send(i); } snprintf(buf, MAX_LINE_SIZE, "PASS %s", buf2); sendln(buf); void SLDaemon::warn(const string &msg, const string &prefix) { if (verbose()) std::cout << prefix << msg; } if (bptr->length > 0) delete[] buf2; void SLDaemon::warn(long int i, const string &prefix) { if (verbose()) std::cout << prefix << i; } BIO_free_all(b64); void SLDaemon::proto_violation() { answer("sld: Protocol violation.\n"); return; } //****************************************************************************** // command functions //****************************************************************************** void SLDaemon::cmd_exit() { answer("BYE\n"); sendln("Bye."); disconnect(); exit(ERR_OK); } void SLDaemon::cmd_version() { answer(VERSION + "\n"); sendln(VERSION); } void SLDaemon::cmd_job(const char *line) { void SLDaemon::cmd_exec(const char *line) { assert(line); // build path char buf[MAX_LINE_SIZE]; sscanf(line, "EXEC %512s\n", buf); //FIXME: Bad static magic number if (sscanf(line, "EXEC %512s\n", buf) != 1) { //FIXME: Bad static magic number sendln("EXEC: Syntax error."); return; } string path = options_.scriptdir + "/" + buf; // Check transversal path attack if (strchr(buf, '/')) { sendln("EXEC: Invalid character in job name."); return; } // Check if file exist struct stat st; int ret = lstat(path.c_str(), &st); if (ret == ENOENT || errno == EACCES) { answer((string) "JOB: " + strerror(errno) + ".\n"); if (ret) { char msg[MAX_LINE_SIZE]; snprintf(msg, MAX_LINE_SIZE, "EXEC: %s: %s.", buf, strerror(errno)); sendln(msg); return; } // check for exec flag if (st.st_mode & S_IXUSR != S_IXUSR) { answer("JOB: no exec flag.\n"); sendln("EXEC: no exec flag."); return; } // check file owner if (st.st_uid != getuid()) { answer("JOB: Bad file owner.\n"); sendln("EXEC: Bad file owner."); return; } // Create new process // flush before fork flush(); //Create new process pid_t pid = fork(); if (pid == -1) { answer((string) "JOB: Unable to fork: " + strerror(errno) + ".\n"); sendln((string) "EXEC: Unable to fork: " + strerror(errno) + "."); return; } Loading @@ -423,12 +416,26 @@ void SLDaemon::cmd_job(const char *line) { // send job info snprintf(buf, MAX_LINE_SIZE, "JOB: %s, pid: %d, start at: %ld.\n", "EXEC: %s, pid: %d, start at: %ld.", j.name.c_str(), j.pid, j.start_time); answer(buf); sendln(buf); // allow sun to start if (kill(pid, SIGCONT)) { perror("sld: cmd_exec"); jobs_.erase(j); } } // Son job else if (pid == 0) { // Wait father registration stuff before doing something else // so we suspend execution if (kill(getpid(), SIGSTOP)) { perror("sld: cmd_exec"); return; } // try to run job if (dup2(socket_fd_, STDOUT_FILENO) == -1) { perror(">> dup2"); exit(ERR_UNKNOWN); Loading @@ -452,30 +459,35 @@ void SLDaemon::cmd_file(const char *line) { // get filename char filename[MAX_LINE_SIZE]; if (sscanf(line, "FILE %512s\n", filename) != 1) { //FIXME: bad magic size proto_violation(); sendln("FILE: Syntax error."); return; } // Check transversal path attack if (strchr(filename, '/')) { sendln("FILE: Invalid character in filename."); return; } string target = options_.scriptdir + "/" + filename; //get size int size; buf = recvln(); warn(buf); ret = sscanf(buf, "SIZE %i\n", &size); delete buf; delete[] buf; if (ret != 1) { answer("FILE: Invalid size parameter.\n"); sendln("FILE: Invalid size parameter."); return; } //get md5 char md5[MAX_LINE_SIZE]; buf = recvln(); warn(buf); ret = sscanf(buf, "MD5 %512s\n", md5); //FIXME: bad magic size delete buf; delete[] buf; if (ret != 1) { answer("FILE: Invalid md5 parameter.\n"); sendln("FILE: Invalid md5 parameter."); return; } Loading @@ -485,7 +497,7 @@ void SLDaemon::cmd_file(const char *line) { } catch (const Error &err) { if (err.code() == ERR_FILE) { answer("FILE: Data transfer error.\n"); sendln("FILE: Data transfer error."); return; } throw; Loading @@ -493,26 +505,26 @@ void SLDaemon::cmd_file(const char *line) { // check MD5 if (SLDaemon::md5(target) != string(md5)) { answer("FILE: file " + target + ": Invalid MD5.\n"); sendln("FILE: file " + target + ": Invalid MD5."); unlink(target.c_str()); return; } // proceed chown if (chown(target.c_str(), getuid(), getgid())) { answer("FILE: chown of " + target + ": Unable to chown.\n"); sendln("FILE: chown of " + target + ": Unable to chown."); unlink(target.c_str()); return; } // proceed chmod if (chmod(target.c_str(), S_IRUSR | S_IWUSR | S_IXUSR)) { answer("FILE: chmod of " + target + ": Unable to chmod.\n"); sendln("FILE: chmod of " + target + ": Unable to chmod."); unlink(target.c_str()); return; } answer("FILE: Transfer of " + target + ": OK.\n"); sendln("FILE: Transfer of " + target + ": OK."); } void SLDaemon::cmd_update() { Loading @@ -520,70 +532,92 @@ void SLDaemon::cmd_update() { int ret; // get filename const string &target = binpath; const string &target = getbinpath(); //get size int size; buf = recvln(); warn(buf); ret = sscanf(buf, "SIZE %i\n", &size); delete buf; delete[] buf; if (ret != 1) { answer("UPDATE: Invalid size parameter.\n"); sendln("UPDATE: Syntax error."); return; } //get md5 char md5[MAX_LINE_SIZE]; buf = recvln(); warn(buf); ret = sscanf(buf, "MD5 %512s\n", md5); //FIXME: bad magic size delete buf; delete[] buf; if (ret != 1) { answer("UPDATE: Invalid md5 parameter.\n"); sendln("UPDATE: Invalid md5 parameter."); return; } // find tempory filename char tempsld[PATH_MAX] = "/tmp/sldXXXXXX"; int tempsld_fd = mkstemp(tempsld); if (tempsld_fd == 0) { sendln((string) "UPDATE: mkstemp: " + strerror(errno) + "."); return; } close(tempsld_fd); //get data try { recv(size, target); recv(size, tempsld); } catch (const Error &err) { if (err.code() == ERR_FILE) { answer("UPDATE: Data transfer error.\n"); sendln("UPDATE: " + err.message() + "."); unlink(tempsld); return; } throw; } // check MD5 if (SLDaemon::md5(target) != string(md5)) { answer("UPDATE: file " + target + ": Invalid MD5.\n"); if (SLDaemon::md5(tempsld) != string(md5)) { sendln("UPDATE: file " + tempsld + ": Invalid MD5."); unlink(tempsld); return; } // copy file to its right destination unlink(target.c_str()); cp(tempsld, target.c_str()); // check MD5 if (SLDaemon::md5(target.c_str()) != string(md5)) { sendln("UPDATE: file " + target + ": Invalid MD5."); unlink(tempsld); return; } // proceed chown if (chown(target.c_str(), getuid(), getgid())) { answer("FILE: chown of " + target + ": Unable to chown.\n"); sendln("FILE: chown of " + target + ": Unable to chown."); unlink(target.c_str()); return; } // proceed chmod if (chmod(target.c_str(), S_IRUSR | S_IWUSR | S_IXUSR)) { answer("FILE: chmod of " + target + ": Unable to chmod.\n"); sendln("FILE: chmod of " + target + ": Unable to chmod."); unlink(target.c_str()); return; } answer("UPDATE: Transfer of " + target + ": OK.\n"); sendln("UPDATE: Transfer of " + target + ": OK."); } void SLDaemon::cmd_list() { FILE *fls = popen(string("ls -1A " + options_.scriptdir).c_str(), "r"); if (fls == 0) { answer("LIST: Unable to list " + options_.scriptdir + ".\n"); sendln("LIST: Unable to list " + options_.scriptdir + "."); return; } Loading @@ -592,8 +626,7 @@ void SLDaemon::cmd_list() { try { while ((len = fread(buf, 1, 255, fls)) > 0) send(buf, len); flush(); warn("LIST: data send.\n"); sendln("LIST: data send."); } catch (...) { pclose(fls); Loading @@ -606,14 +639,16 @@ void SLDaemon::cmd_status() { time_t t = time(0); char buf[MAX_LINE_SIZE]; answer("STATUS of \n"); if (jobs_.size() == 0) return; sendln("STATUS of"); for (i = jobs_.begin(); i != jobs_.end(); ++i) { snprintf(buf, MAX_LINE_SIZE, " job: %s, pid: %d, start at: %ld, since: %ld seconds.\n", " job: %s, pid: %d, start at: %ld, since: %ld seconds.", i->name.c_str(), i->pid, i->start_time,t - i->start_time); answer(buf); sendln(buf); } flush(); } void SLDaemon::cmd_kill(const char *line) { Loading @@ -623,18 +658,17 @@ void SLDaemon::cmd_kill(const char *line) { // retrieve pid int pid; if (sscanf(line, "KILL %i\n", &pid) != 1) { proto_violation(); sendln("KILL: Syntax error."); return; } for (i = jobs_.begin(); i != jobs_.end(); ++i) if (pid == i->pid) { int ret = kill(i->pid, SIGKILL); snprintf(buf, MAX_LINE_SIZE, "KILL: kill -SIGKILL %d (%s), return %d (%s).\n", snprintf(buf, MAX_LINE_SIZE, "KILL: kill -SIGKILL %d (%s), return %d (%s).", i->pid, i->name.c_str(), ret, ((ret == -1) ? strerror(errno) : "OK" )); answer(buf); sendln(buf); } flush(); } void SLDaemon::cmd_killall() { Loading @@ -643,48 +677,9 @@ void SLDaemon::cmd_killall() { for (i = jobs_.begin(); i != jobs_.end(); ++i) { int ret = kill(i->pid, SIGKILL); snprintf(buf, MAX_LINE_SIZE, "KILL: kill -SIGKILL %d (%s), return %d (%s).\n", snprintf(buf, MAX_LINE_SIZE, "KILL: kill -SIGKILL %d (%s), return %d (%s).", i->pid, i->name.c_str(), ret, ((ret == -1) ? strerror(errno) : "OK" )); answer(buf); } flush(); } void SLDaemon::cmd_reload() { const string &path = binpath; if (path == "") { answer("RELOAD: Unable to locate sld binary.\n"); return; } // Get bin info struct stat st; if (lstat(path.c_str(), &st)) { answer((string)"RELOAD: lstat: " + strerror(errno) + ".\n"); return; } // FIXME: check re run right (exec + file owner) answer((string) "RELOAD: Trying to reload `" + path.c_str() + "'.\n"); int pid = fork(); if (pid == -1) { answer((string)"RELOAD: fork: " + strerror(errno) + ".\n"); return; } // father process if (pid) { disconnect(); exit(0); } // son process else { execl(path.c_str(), path.c_str()); answer((string) "RELOAD: execl: " + strerror(errno) + ".\n"); flush(); exit(ERR_UNKNOWN); sendln(buf); } } Loading sld/sld.hh→sld/src/daemon.hh +4 −49 Original line number Diff line number Diff line #ifndef SLD_HH # define SLD_HH # include <cassert> # include <ios> # include <iostream> # include <fstream> # include <sstream> # include <map> # include <time.h> # include <set> # include "error.hh" #ifndef DAEMON_HH # define DAEMON_HH typedef std::string string; typedef std::stringstream sstream; typedef std::ostream ostream; typedef std::ifstream ifstream; enum { ERR_OK = 0, ERR_USAGE = 1, ERR_BADPARAM = 2, ERR_FILE = 3, ERR_NET = 4, ERR_PROTO = 5, ERR_AUTH = 6, ERR_NOMEM = 41, ERR_UNKNOWN = 42 }; // ----------------------------------------------------------------------------- // Gonstant // ----------------------------------------------------------------------------- static const string VERSION = "1"; static const int MAX_LINE_SIZE = 512; static const string RCV_DATA = "<< "; static const string SND_DATA = ">> "; extern string binpath; string getbinpath(const char *argv0); void sigchild(int); // ----------------------------------------------------------------------------- // SLDAEMON CLASS // ----------------------------------------------------------------------------- Loading Loading @@ -109,6 +71,7 @@ protected: void send(const char *data, size_t len, bool buf = true); void send(const string str, bool buf = true); void send(long int i); void sendln(const string &s); char *recv(size_t size); void recv(size_t size, const string &filename); char *recvln(); Loading @@ -116,21 +79,15 @@ protected: // protocol functions void auth(); void answer(const string &, bool = true); void answer(long int, bool = true); void warn(const string &, const string & = ""); void warn(long int, const string & = ""); void proto_violation(); // commmand functions void cmd_exit(); void cmd_version(); void cmd_list(); void cmd_reload(); void cmd_status(); void cmd_killall(); void cmd_kill(const char *line); void cmd_job(const char *line); void cmd_exec(const char *line); void cmd_update(); void cmd_file(const char *line); Loading @@ -146,6 +103,4 @@ private: SLDaemon &operator=(const SLDaemon &) { assert(true); return *instance_; } }; #endif sld/error.cc→sld/src/error.cc +0 −0 File moved. View file Loading
sld/Makefile.am +8 −7 Original line number Diff line number Diff line bin_PROGRAMS= sld sld_SOURCES= sld.hh \ sld.cc \ daemon.cc \ error.hh \ error.cc sld_SOURCES= src/sld.hh \ src/sld.cc \ src/daemon.hh \ src/daemon.cc \ src/error.hh \ src/error.cc CLEANFILES= *~ '\#*' CLEANFILES= *~ '\#*' .*.swp .*~ .PHONY: tar re Loading
sld/configure.ac +2 −2 Original line number Diff line number Diff line Loading @@ -63,8 +63,8 @@ AC_ARG_WITH([efence], [AS_HELP_STRING([--with-efence], [link with lib efence])], [dnl action-if-given LDFLAGS="$LDFLAGS -lefence" test -r "/usr/include/efence.h" && CXXFLAGS="$CXXFLAGS -include stdlib.h -include efence.h" #test -r "/usr/include/efencepp.h" && #CXXFLAGS="$CXXFLAGS -include efencepp.h" ], [dnl action-if-not-given true Loading
sld/daemon.cc→sld/src/daemon.cc +155 −160 Original line number Diff line number Diff line Loading @@ -43,7 +43,7 @@ void SLDaemon::usage(const char *argv0) const { << " -d scriptdir : Scripts directory." << std::endl << " -h : Print this usage." << std::endl << " -v : Verbose mode." << std::endl << " -l name : Set login to name." << std::endl << " -l host : Set login to host." << std::endl << " -p secret : Set pass to secret." << std::endl << " -H name : Set server host to name." << std::endl << " -P number : Set server port to number." << std::endl Loading Loading @@ -158,8 +158,8 @@ void SLDaemon::check_options() const { if (options_.scriptdir == "") throw Error(ERR_BADPARAM, "No scripts directory specified."); // Empty scripts dir // TODO // TODO: Check dir exist // TODO: Empty scripts dir } void SLDaemon::run() { char *line; Loading @@ -169,13 +169,10 @@ void SLDaemon::run() { auth(); while (1) { line = recvln(); warn(line, RCV_DATA); // call right handler try { if (!strcmp(line, "EXIT\n")) cmd_exit(); else if (!strcmp(line, "RELOAD\n")) cmd_reload(); else if (!strcmp(line, "VERSION\n")) cmd_version(); else if (!strcmp(line, "STATUS\n")) Loading @@ -186,21 +183,20 @@ void SLDaemon::run() { cmd_killall(); else if (!strcmp(line, "KILL\n")) cmd_kill(line); else if (!strncmp(line, "JOB ", 4)) cmd_job(line); else if (!strncmp(line, "EXEC ", 4)) cmd_exec(line); else if (!strncmp(line, "FILE ", 5)) cmd_file(line); else if (!strcmp(line, "UPDATE")) else if (!strcmp(line, "UPDATE\n")) cmd_update(); else proto_violation(); sendln("sld: Invalid command."); } catch (const Error &e) { e.print(); send("!! "); send(e.message()); sendln(e.message()); std::cerr << "!! " << e.message() << std::endl; } delete line; delete[] line; } } Loading Loading @@ -265,11 +261,18 @@ void SLDaemon::send(const char *data, size_t len, bool buf) { throw Error(ERR_NET, strerror(errno)); } void SLDaemon::sendln(const string &s) { if (!fprintf(socket_fs_, "%s\n", s.c_str())) throw Error(ERR_NET, strerror(errno)); if (verbose()) std::cout << SND_DATA << s << std::endl; } char *SLDaemon::recv(size_t size) { char *data = new char[size]; if (fread(data, 1, size, socket_fs_) != size) { delete data; delete[] data; throw Error(ERR_NET, strerror(errno)); } return data; Loading @@ -279,20 +282,23 @@ void SLDaemon::recv(size_t size, const string &filename) { char *data = recv(size); FILE *fs = fopen(filename.c_str(), "w"); if (fs == 0) throw Error(ERR_FILE, (string) "recv: " + strerror(errno)); throw Error(ERR_FILE, (string) "recv: fopen: " + strerror(errno)); if (fwrite(data, 1, size, fs) != size) throw Error(ERR_FILE, (string) "recv: " + strerror(errno)); throw Error(ERR_FILE, (string) "recv: fwrite: " + strerror(errno)); if (fclose(fs)) throw Error(ERR_FILE, (string) "recv: " + strerror(errno)); throw Error(ERR_FILE, (string) "recv: fclose: " + strerror(errno)); } char *SLDaemon::recvln() { char *line = new char[MAX_LINE_SIZE]; if (fgets(line, MAX_LINE_SIZE, socket_fs_) == 0) { delete line; delete[] line; throw Error(ERR_FILE, (string) "recvln: " + strerror(errno)); } if (verbose()) std::cout << SND_DATA << line; return line; } Loading @@ -307,6 +313,8 @@ void SLDaemon::flush() { void SLDaemon::auth() { unsigned char md[SHA_DIGEST_LENGTH]; char buf[MAX_LINE_SIZE]; char *buf2 = ""; BIO *bmem, *b64; BUF_MEM *bptr; Loading @@ -319,99 +327,84 @@ void SLDaemon::auth() { BIO_flush(b64); BIO_get_mem_ptr(b64, &bptr); char *buff = new char[bptr->length]; memcpy(buff, bptr->data, bptr->length-1); buff[bptr->length-1] = 0; BIO_free_all(b64); send("HOST "); send(options_.login); send("\n"); send("PASS "); send(buff); send("\n"); flush(); delete buff; return; if (bptr->length > 0) { buf2 = new char[bptr->length]; memcpy(buf2, bptr->data, bptr->length-1); buf2[bptr->length-1] = 0; } void SLDaemon::answer(const string &msg, bool prefix) { if (verbose()) std::cout << (prefix ? SND_DATA : "") << msg; send(msg); } snprintf(buf, MAX_LINE_SIZE, "HOST %s", options_.login.c_str()); sendln(buf); void SLDaemon::answer(long int i, bool prefix) { if (verbose()) std::cout << (prefix ? SND_DATA : "") << i; send(i); } snprintf(buf, MAX_LINE_SIZE, "PASS %s", buf2); sendln(buf); void SLDaemon::warn(const string &msg, const string &prefix) { if (verbose()) std::cout << prefix << msg; } if (bptr->length > 0) delete[] buf2; void SLDaemon::warn(long int i, const string &prefix) { if (verbose()) std::cout << prefix << i; } BIO_free_all(b64); void SLDaemon::proto_violation() { answer("sld: Protocol violation.\n"); return; } //****************************************************************************** // command functions //****************************************************************************** void SLDaemon::cmd_exit() { answer("BYE\n"); sendln("Bye."); disconnect(); exit(ERR_OK); } void SLDaemon::cmd_version() { answer(VERSION + "\n"); sendln(VERSION); } void SLDaemon::cmd_job(const char *line) { void SLDaemon::cmd_exec(const char *line) { assert(line); // build path char buf[MAX_LINE_SIZE]; sscanf(line, "EXEC %512s\n", buf); //FIXME: Bad static magic number if (sscanf(line, "EXEC %512s\n", buf) != 1) { //FIXME: Bad static magic number sendln("EXEC: Syntax error."); return; } string path = options_.scriptdir + "/" + buf; // Check transversal path attack if (strchr(buf, '/')) { sendln("EXEC: Invalid character in job name."); return; } // Check if file exist struct stat st; int ret = lstat(path.c_str(), &st); if (ret == ENOENT || errno == EACCES) { answer((string) "JOB: " + strerror(errno) + ".\n"); if (ret) { char msg[MAX_LINE_SIZE]; snprintf(msg, MAX_LINE_SIZE, "EXEC: %s: %s.", buf, strerror(errno)); sendln(msg); return; } // check for exec flag if (st.st_mode & S_IXUSR != S_IXUSR) { answer("JOB: no exec flag.\n"); sendln("EXEC: no exec flag."); return; } // check file owner if (st.st_uid != getuid()) { answer("JOB: Bad file owner.\n"); sendln("EXEC: Bad file owner."); return; } // Create new process // flush before fork flush(); //Create new process pid_t pid = fork(); if (pid == -1) { answer((string) "JOB: Unable to fork: " + strerror(errno) + ".\n"); sendln((string) "EXEC: Unable to fork: " + strerror(errno) + "."); return; } Loading @@ -423,12 +416,26 @@ void SLDaemon::cmd_job(const char *line) { // send job info snprintf(buf, MAX_LINE_SIZE, "JOB: %s, pid: %d, start at: %ld.\n", "EXEC: %s, pid: %d, start at: %ld.", j.name.c_str(), j.pid, j.start_time); answer(buf); sendln(buf); // allow sun to start if (kill(pid, SIGCONT)) { perror("sld: cmd_exec"); jobs_.erase(j); } } // Son job else if (pid == 0) { // Wait father registration stuff before doing something else // so we suspend execution if (kill(getpid(), SIGSTOP)) { perror("sld: cmd_exec"); return; } // try to run job if (dup2(socket_fd_, STDOUT_FILENO) == -1) { perror(">> dup2"); exit(ERR_UNKNOWN); Loading @@ -452,30 +459,35 @@ void SLDaemon::cmd_file(const char *line) { // get filename char filename[MAX_LINE_SIZE]; if (sscanf(line, "FILE %512s\n", filename) != 1) { //FIXME: bad magic size proto_violation(); sendln("FILE: Syntax error."); return; } // Check transversal path attack if (strchr(filename, '/')) { sendln("FILE: Invalid character in filename."); return; } string target = options_.scriptdir + "/" + filename; //get size int size; buf = recvln(); warn(buf); ret = sscanf(buf, "SIZE %i\n", &size); delete buf; delete[] buf; if (ret != 1) { answer("FILE: Invalid size parameter.\n"); sendln("FILE: Invalid size parameter."); return; } //get md5 char md5[MAX_LINE_SIZE]; buf = recvln(); warn(buf); ret = sscanf(buf, "MD5 %512s\n", md5); //FIXME: bad magic size delete buf; delete[] buf; if (ret != 1) { answer("FILE: Invalid md5 parameter.\n"); sendln("FILE: Invalid md5 parameter."); return; } Loading @@ -485,7 +497,7 @@ void SLDaemon::cmd_file(const char *line) { } catch (const Error &err) { if (err.code() == ERR_FILE) { answer("FILE: Data transfer error.\n"); sendln("FILE: Data transfer error."); return; } throw; Loading @@ -493,26 +505,26 @@ void SLDaemon::cmd_file(const char *line) { // check MD5 if (SLDaemon::md5(target) != string(md5)) { answer("FILE: file " + target + ": Invalid MD5.\n"); sendln("FILE: file " + target + ": Invalid MD5."); unlink(target.c_str()); return; } // proceed chown if (chown(target.c_str(), getuid(), getgid())) { answer("FILE: chown of " + target + ": Unable to chown.\n"); sendln("FILE: chown of " + target + ": Unable to chown."); unlink(target.c_str()); return; } // proceed chmod if (chmod(target.c_str(), S_IRUSR | S_IWUSR | S_IXUSR)) { answer("FILE: chmod of " + target + ": Unable to chmod.\n"); sendln("FILE: chmod of " + target + ": Unable to chmod."); unlink(target.c_str()); return; } answer("FILE: Transfer of " + target + ": OK.\n"); sendln("FILE: Transfer of " + target + ": OK."); } void SLDaemon::cmd_update() { Loading @@ -520,70 +532,92 @@ void SLDaemon::cmd_update() { int ret; // get filename const string &target = binpath; const string &target = getbinpath(); //get size int size; buf = recvln(); warn(buf); ret = sscanf(buf, "SIZE %i\n", &size); delete buf; delete[] buf; if (ret != 1) { answer("UPDATE: Invalid size parameter.\n"); sendln("UPDATE: Syntax error."); return; } //get md5 char md5[MAX_LINE_SIZE]; buf = recvln(); warn(buf); ret = sscanf(buf, "MD5 %512s\n", md5); //FIXME: bad magic size delete buf; delete[] buf; if (ret != 1) { answer("UPDATE: Invalid md5 parameter.\n"); sendln("UPDATE: Invalid md5 parameter."); return; } // find tempory filename char tempsld[PATH_MAX] = "/tmp/sldXXXXXX"; int tempsld_fd = mkstemp(tempsld); if (tempsld_fd == 0) { sendln((string) "UPDATE: mkstemp: " + strerror(errno) + "."); return; } close(tempsld_fd); //get data try { recv(size, target); recv(size, tempsld); } catch (const Error &err) { if (err.code() == ERR_FILE) { answer("UPDATE: Data transfer error.\n"); sendln("UPDATE: " + err.message() + "."); unlink(tempsld); return; } throw; } // check MD5 if (SLDaemon::md5(target) != string(md5)) { answer("UPDATE: file " + target + ": Invalid MD5.\n"); if (SLDaemon::md5(tempsld) != string(md5)) { sendln("UPDATE: file " + tempsld + ": Invalid MD5."); unlink(tempsld); return; } // copy file to its right destination unlink(target.c_str()); cp(tempsld, target.c_str()); // check MD5 if (SLDaemon::md5(target.c_str()) != string(md5)) { sendln("UPDATE: file " + target + ": Invalid MD5."); unlink(tempsld); return; } // proceed chown if (chown(target.c_str(), getuid(), getgid())) { answer("FILE: chown of " + target + ": Unable to chown.\n"); sendln("FILE: chown of " + target + ": Unable to chown."); unlink(target.c_str()); return; } // proceed chmod if (chmod(target.c_str(), S_IRUSR | S_IWUSR | S_IXUSR)) { answer("FILE: chmod of " + target + ": Unable to chmod.\n"); sendln("FILE: chmod of " + target + ": Unable to chmod."); unlink(target.c_str()); return; } answer("UPDATE: Transfer of " + target + ": OK.\n"); sendln("UPDATE: Transfer of " + target + ": OK."); } void SLDaemon::cmd_list() { FILE *fls = popen(string("ls -1A " + options_.scriptdir).c_str(), "r"); if (fls == 0) { answer("LIST: Unable to list " + options_.scriptdir + ".\n"); sendln("LIST: Unable to list " + options_.scriptdir + "."); return; } Loading @@ -592,8 +626,7 @@ void SLDaemon::cmd_list() { try { while ((len = fread(buf, 1, 255, fls)) > 0) send(buf, len); flush(); warn("LIST: data send.\n"); sendln("LIST: data send."); } catch (...) { pclose(fls); Loading @@ -606,14 +639,16 @@ void SLDaemon::cmd_status() { time_t t = time(0); char buf[MAX_LINE_SIZE]; answer("STATUS of \n"); if (jobs_.size() == 0) return; sendln("STATUS of"); for (i = jobs_.begin(); i != jobs_.end(); ++i) { snprintf(buf, MAX_LINE_SIZE, " job: %s, pid: %d, start at: %ld, since: %ld seconds.\n", " job: %s, pid: %d, start at: %ld, since: %ld seconds.", i->name.c_str(), i->pid, i->start_time,t - i->start_time); answer(buf); sendln(buf); } flush(); } void SLDaemon::cmd_kill(const char *line) { Loading @@ -623,18 +658,17 @@ void SLDaemon::cmd_kill(const char *line) { // retrieve pid int pid; if (sscanf(line, "KILL %i\n", &pid) != 1) { proto_violation(); sendln("KILL: Syntax error."); return; } for (i = jobs_.begin(); i != jobs_.end(); ++i) if (pid == i->pid) { int ret = kill(i->pid, SIGKILL); snprintf(buf, MAX_LINE_SIZE, "KILL: kill -SIGKILL %d (%s), return %d (%s).\n", snprintf(buf, MAX_LINE_SIZE, "KILL: kill -SIGKILL %d (%s), return %d (%s).", i->pid, i->name.c_str(), ret, ((ret == -1) ? strerror(errno) : "OK" )); answer(buf); sendln(buf); } flush(); } void SLDaemon::cmd_killall() { Loading @@ -643,48 +677,9 @@ void SLDaemon::cmd_killall() { for (i = jobs_.begin(); i != jobs_.end(); ++i) { int ret = kill(i->pid, SIGKILL); snprintf(buf, MAX_LINE_SIZE, "KILL: kill -SIGKILL %d (%s), return %d (%s).\n", snprintf(buf, MAX_LINE_SIZE, "KILL: kill -SIGKILL %d (%s), return %d (%s).", i->pid, i->name.c_str(), ret, ((ret == -1) ? strerror(errno) : "OK" )); answer(buf); } flush(); } void SLDaemon::cmd_reload() { const string &path = binpath; if (path == "") { answer("RELOAD: Unable to locate sld binary.\n"); return; } // Get bin info struct stat st; if (lstat(path.c_str(), &st)) { answer((string)"RELOAD: lstat: " + strerror(errno) + ".\n"); return; } // FIXME: check re run right (exec + file owner) answer((string) "RELOAD: Trying to reload `" + path.c_str() + "'.\n"); int pid = fork(); if (pid == -1) { answer((string)"RELOAD: fork: " + strerror(errno) + ".\n"); return; } // father process if (pid) { disconnect(); exit(0); } // son process else { execl(path.c_str(), path.c_str()); answer((string) "RELOAD: execl: " + strerror(errno) + ".\n"); flush(); exit(ERR_UNKNOWN); sendln(buf); } } Loading
sld/sld.hh→sld/src/daemon.hh +4 −49 Original line number Diff line number Diff line #ifndef SLD_HH # define SLD_HH # include <cassert> # include <ios> # include <iostream> # include <fstream> # include <sstream> # include <map> # include <time.h> # include <set> # include "error.hh" #ifndef DAEMON_HH # define DAEMON_HH typedef std::string string; typedef std::stringstream sstream; typedef std::ostream ostream; typedef std::ifstream ifstream; enum { ERR_OK = 0, ERR_USAGE = 1, ERR_BADPARAM = 2, ERR_FILE = 3, ERR_NET = 4, ERR_PROTO = 5, ERR_AUTH = 6, ERR_NOMEM = 41, ERR_UNKNOWN = 42 }; // ----------------------------------------------------------------------------- // Gonstant // ----------------------------------------------------------------------------- static const string VERSION = "1"; static const int MAX_LINE_SIZE = 512; static const string RCV_DATA = "<< "; static const string SND_DATA = ">> "; extern string binpath; string getbinpath(const char *argv0); void sigchild(int); // ----------------------------------------------------------------------------- // SLDAEMON CLASS // ----------------------------------------------------------------------------- Loading Loading @@ -109,6 +71,7 @@ protected: void send(const char *data, size_t len, bool buf = true); void send(const string str, bool buf = true); void send(long int i); void sendln(const string &s); char *recv(size_t size); void recv(size_t size, const string &filename); char *recvln(); Loading @@ -116,21 +79,15 @@ protected: // protocol functions void auth(); void answer(const string &, bool = true); void answer(long int, bool = true); void warn(const string &, const string & = ""); void warn(long int, const string & = ""); void proto_violation(); // commmand functions void cmd_exit(); void cmd_version(); void cmd_list(); void cmd_reload(); void cmd_status(); void cmd_killall(); void cmd_kill(const char *line); void cmd_job(const char *line); void cmd_exec(const char *line); void cmd_update(); void cmd_file(const char *line); Loading @@ -146,6 +103,4 @@ private: SLDaemon &operator=(const SLDaemon &) { assert(true); return *instance_; } }; #endif