Просмотр исходного кода

* Moved most of the "shell" functions to shell.c/.h

svn: 662
Bryan Drewery 22 лет назад
Родитель
Сommit
3861e5357b
9 измененных файлов с 857 добавлено и 805 удалено
  1. 1 0
      src/Makefile.in
  2. 1 0
      src/cmds.c
  3. 1 1
      src/debug.c
  4. 2 1
      src/main.c
  5. 3 758
      src/misc.c
  6. 2 45
      src/misc.h
  7. 791 0
      src/shell.c
  8. 54 0
      src/shell.h
  9. 2 0
      src/stat.h

+ 1 - 0
src/Makefile.in

@@ -37,6 +37,7 @@ OBJS = auth.o \
 	net.o \
 	rfc1459.o \
 	settings.o \
+	shell.o \
 	tcl.o \
 	tclhash.o \
 	userent.o \

+ 1 - 0
src/cmds.c

@@ -9,6 +9,7 @@
 #include "cmds.h"
 #include "debug.h"
 #include "dcc.h"
+#include "shell.h"
 #include "misc.h"
 #include "net.h"
 #include "userrec.h"

+ 1 - 1
src/debug.c

@@ -10,7 +10,7 @@
 #include "common.h"
 #include "debug.h"
 #include "net.h"
-#include "misc.h"
+#include "shell.h"
 #include "userrec.h"
 #include "main.h"
 #include "dccutil.h"

+ 2 - 1
src/main.c

@@ -9,11 +9,12 @@
 #include "common.h"
 #include "main.h"
 #include "dcc.h"
+#include "misc.h"
 #include "salt.h"
 #include "misc_file.h"
 #include "net.h"
 #include "users.h"
-#include "misc.h"
+#include "shell.h"
 #include "userrec.h"
 #include "cfg.h"
 #include "dccutil.h"

+ 3 - 758
src/misc.c

@@ -20,31 +20,15 @@
 #include "color.h"
 #include "botmsg.h"
 #include "bg.h"	
-#include <sys/stat.h>
-#include <sys/types.h>
-#include <sys/wait.h>
-#include <ctype.h>
-#include <unistd.h>
-#include <fcntl.h>
 #include "chan.h"
 #include "tandem.h"
 #include "modules.h"
-#include <pwd.h>
-#include <errno.h>
-#include <libgen.h>
 #ifdef HUB
 #include "userrec.h"
 #endif /* HUB */
-#ifdef S_ANTITRACE
-#include <sys/ptrace.h>
-#include <sys/wait.h>
-#endif /* S_ANTITRACE */
-#include <net/if.h>
-#include <sys/ioctl.h>
-#include <sys/socket.h>
-#include <signal.h>
-#include <sys/utsname.h>
 #include "stat.h"
+
+#include <sys/wait.h>
 #include <stdarg.h>
 
 extern struct userrec 	*userlist;
@@ -63,8 +47,7 @@ extern int		 backgrd, term_z, use_stderr, dcc_total, timesync,
 			 strict_host, loading,
                          localhub;
 extern time_t		 now;
-extern struct cfg_entry	CFG_MOTD, CFG_LOGIN, CFG_BADPROCESS, CFG_PROCESSLIST, CFG_PROMISC, 
-			CFG_TRACE, CFG_HIJACK;
+extern struct cfg_entry	CFG_MOTD;
 
 void detected(int, char *);
 
@@ -759,423 +742,6 @@ int dolimit(struct chanset_t *chan)
   return 0;
 }
 
-#ifdef S_LASTCHECK
-char last_buf[128]="";
-#endif /* S_LASTCHECK */
-
-void check_last() {
-#ifdef S_LASTCHECK
-  char user[20];
-  struct passwd *pw;
-
-  if (!strcmp((char *) CFG_LOGIN.ldata ? CFG_LOGIN.ldata : CFG_LOGIN.gdata ? CFG_LOGIN.gdata : "ignore", "ignore"))
-    return;
-
-  pw = getpwuid(geteuid());
-  if (!pw) return;
-
-  strncpyz(user, pw->pw_name ? pw->pw_name : "" , sizeof(user));
-  if (user[0]) {
-    char *out;
-    char buf[50];
-
-    sprintf(buf, STR("last %s"), user);
-    if (shell_exec(buf, NULL, &out, NULL)) {
-      if (out) {
-        char *p;
-
-        p = strchr(out, '\n');
-        if (p)
-          *p = 0;
-        if (strlen(out) > 10) {
-          if (last_buf[0]) {
-            if (strncmp(last_buf, out, sizeof(last_buf))) {
-              char wrk[16384];
-
-              sprintf(wrk, STR("Login: %s"), out);
-              detected(DETECT_LOGIN, wrk);
-            }
-          }
-          strncpyz(last_buf, out, sizeof(last_buf));
-        }
-        free(out);
-      }
-    }
-  }
-#endif /* S_LASTCHECK */
-}
-
-void check_processes()
-{
-#ifdef S_PROCESSCHECK
-  char *proclist,
-   *out,
-   *p,
-   *np,
-   *curp,
-    buf[1024],
-    bin[128];
-
-  if (!strcmp((char *) CFG_BADPROCESS.ldata ? CFG_BADPROCESS.ldata : CFG_BADPROCESS.gdata ? CFG_BADPROCESS.gdata : "ignore", "ignore"))
-    return;
-
-  proclist = (char *) (CFG_PROCESSLIST.ldata && ((char *) CFG_PROCESSLIST.ldata)[0] ?
-                       CFG_PROCESSLIST.ldata : CFG_PROCESSLIST.gdata && ((char *) CFG_PROCESSLIST.gdata)[0] ? CFG_PROCESSLIST.gdata : NULL);
-  if (!proclist)
-    return;
-
-  if (!shell_exec(STR("ps x"), NULL, &out, NULL))
-    return;
-
-  /* Get this binary's filename */
-  strncpyz(buf, binname, sizeof(buf));
-  p = strrchr(buf, '/');
-  if (p) {
-    p++;
-    strncpyz(bin, p, sizeof(bin));
-  } else {
-    bin[0] = 0;
-  }
-  /* Fix up the "permitted processes" list */
-  p = malloc(strlen(proclist) + strlen(bin) + 6);
-  strcpy(p, proclist);
-  strcat(p, " ");
-  strcat(p, bin);
-  strcat(p, " ");
-  proclist = p;
-  curp = out;
-  while (curp) {
-    np = strchr(curp, '\n');
-    if (np)
-      *np++ = 0;
-    if (atoi(curp) > 0) {
-      char *pid,
-       *tty,
-       *stat,
-       *time,
-        cmd[512],
-        line[2048];
-
-      strncpyz(line, curp, sizeof(line));
-      /* it's a process line */
-      /* Assuming format: pid tty stat time cmd */
-      pid = newsplit(&curp);
-      tty = newsplit(&curp);
-      stat = newsplit(&curp);
-      time = newsplit(&curp);
-      strncpyz(cmd, curp, sizeof(cmd));
-      /* skip any <defunct> procs "/bin/sh -c" crontab stuff and binname crontab stuff */
-      if (!strstr(cmd, STR("<defunct>")) && !strncmp(cmd, STR("/bin/sh -c"), 10)
-          && !strncmp(cmd, binname, strlen(binname))) {
-        /* get rid of any args */
-        if ((p = strchr(cmd, ' ')))
-          *p = 0;
-        /* remove [] or () */
-        if (strlen(cmd)) {
-          p = cmd + strlen(cmd) - 1;
-          if (((cmd[0] == '(') && (*p == ')')) || ((cmd[0] == '[') && (*p == ']'))) {
-            *p = 0;
-            strcpy(buf, cmd + 1);
-            strcpy(cmd, buf);
-          }
-        }
-
-        /* remove path */
-        if ((p = strrchr(cmd, '/'))) {
-          p++;
-          strcpy(buf, p);
-          strcpy(cmd, buf);
-        }
-
-        /* skip "ps" */
-        if (strcmp(cmd, "ps")) {
-          /* see if proc's in permitted list */
-          strcat(cmd, " ");
-          if ((p = strstr(proclist, cmd))) {
-            /* Remove from permitted list */
-            while (*p != ' ')
-              *p++ = 1;
-          } else {
-            char wrk[16384];
-
-            sprintf(wrk, STR("Unexpected process: %s"), line);
-            detected(DETECT_PROCESS, wrk);
-          }
-        }
-      }
-    }
-    curp = np;
-  }
-  free(proclist);
-  if (out)
-    free(out);
-#endif /* S_PROCESSCHECK */
-}
-
-void check_promisc()
-{
-#ifdef S_PROMISC
-#ifdef SIOCGIFCONF
-  char buf[8192];
-  struct ifreq ifreq, *ifr;
-  struct ifconf ifcnf;
-  char *cp, *cplim;
-  int sock;
-
-  if (!strcmp((char *) CFG_PROMISC.ldata ? CFG_PROMISC.ldata : CFG_PROMISC.gdata ? CFG_PROMISC.gdata : "ignore", "ignore"))
-    return;
-  sock = socket(AF_INET, SOCK_STREAM, 0);
-  ifcnf.ifc_len = 8191;
-  ifcnf.ifc_buf = buf;
-  if (ioctl(sock, SIOCGIFCONF, (char *) &ifcnf) < 0) {
-    close(sock);
-    return;
-  }
-  ifr = ifcnf.ifc_req;
-  cplim = buf + ifcnf.ifc_len;
-  for (cp = buf; cp < cplim; cp += sizeof(ifr->ifr_name) + sizeof(ifr->ifr_addr)) {
-    ifr = (struct ifreq *) cp;
-    ifreq = *ifr;
-    if (!ioctl(sock, SIOCGIFFLAGS, (char *) &ifreq)) {
-      if (ifreq.ifr_flags & IFF_PROMISC) {
-        close(sock);
-        detected(DETECT_PROMISC, STR("Detected promiscuous mode"));
-        return;
-      }
-    }
-  }
-  close(sock);
-#endif /* SIOCGIFCONF */
-#endif /* S_PROMISC */
-}
-
-#ifdef S_ANTITRACE
-int traced = 0;
-
-void got_trace(int z)
-{
-  traced = 0;
-}
-#endif /* S_ANTITRACE */
-
-void check_trace()
-{
-#ifdef S_ANTITRACE
-  int x, parent, i;
-  struct sigaction sv, *oldsv = NULL;
-
-  if (!strcmp((char *) CFG_TRACE.ldata ? CFG_TRACE.ldata : CFG_TRACE.gdata ? CFG_TRACE.gdata : "ignore", "ignore"))
-    return;
-  parent = getpid();
-#ifdef __linux__
-  egg_bzero(&sv, sizeof(sv));
-  sv.sa_handler = got_trace;
-  sigemptyset(&sv.sa_mask);
-  oldsv = NULL;
-  sigaction(SIGTRAP, &sv, oldsv);
-  traced = 1;
-  asm("INT3");
-  sigaction(SIGTRAP, oldsv, NULL);
-  if (traced)
-    detected(DETECT_TRACE, STR("I'm being traced!"));
-  else {
-    x = fork();
-    if (x == -1)
-      return;
-    else if (x == 0) {
-      i = ptrace(PTRACE_ATTACH, parent, 0, 0);
-      if (i == (-1) && errno == EPERM)
-        detected(DETECT_TRACE, STR("I'm being traced!"));
-      else {
-        waitpid(parent, &i, 0);
-        kill(parent, SIGCHLD);
-        ptrace(PTRACE_DETACH, parent, 0, 0);
-        kill(parent, SIGCHLD);
-      }
-      exit(0);
-    } else
-      wait(&i);
-  }
-#endif /* __linux__ */
-#ifdef __FreeBSD__
-  x = fork();
-  if (x == -1)
-    return;
-  else if (x == 0) {
-    i = ptrace(PT_ATTACH, parent, 0, 0);
-    if (i == (-1) && errno == EBUSY)
-      detected(DETECT_TRACE, STR("I'm being traced"));
-    else {
-      wait(&i);
-      i = ptrace(PT_CONTINUE, parent, (caddr_t) 1, 0);
-      kill(parent, SIGCHLD);
-      wait(&i);
-      i = ptrace(PT_DETACH, parent, (caddr_t) 1, 0);
-      wait(&i);
-    }
-    exit(0);
-  } else
-    waitpid(x, NULL, 0);
-#endif /* __FreeBSD__ */
-#ifdef __OpenBSD__
-  x = fork();
-  if (x == -1)
-    return;
-  else if (x == 0) {
-    i = ptrace(PT_ATTACH, parent, 0, 0);
-    if (i == (-1) && errno == EBUSY)
-      detected(DETECT_TRACE, STR("I'm being traced"));
-    else {
-      wait(&i);
-      i = ptrace(PT_CONTINUE, parent, (caddr_t) 1, 0);
-      kill(parent, SIGCHLD);
-      wait(&i);
-      i = ptrace(PT_DETACH, parent, (caddr_t) 1, 0);
-      wait(&i);
-    }
-    exit(0);
-  } else
-    waitpid(x, NULL, 0);
-#endif /* __OpenBSD__ */
-#endif /* S_ANTITRACE */
-}
-
-int shell_exec(char *cmdline, char *input, char **output, char **erroutput)
-{
-  FILE *inpFile,
-   *outFile,
-   *errFile;
-  char tmpfile[161];
-  int x, fd;
-  int parent = getpid();
-
-  if (!cmdline)
-    return 0;
-  /* Set up temp files */
-  /* always use mkstemp() when handling temp filess! -dizz */
-  sprintf(tmpfile, STR("%s.in-XXXXXX"), tempdir);
-  if ((fd = mkstemp(tmpfile)) == -1 || (inpFile = fdopen(fd, "w+")) == NULL) {
-    if (fd != -1) {
-      unlink(tmpfile);
-      close(fd);
-    }
-    putlog(LOG_ERRORS, "*" , STR("exec: Couldn't open '%s': %s"), tmpfile, strerror(errno));
-    return 0;
-  }
-  unlink(tmpfile);
-  if (input) {
-    if (fwrite(input, 1, strlen(input), inpFile) != strlen(input)) {
-      fclose(inpFile);
-      putlog(LOG_ERRORS, "*", STR("exec: Couldn't write to '%s': %s"), tmpfile, strerror(errno));
-      return 0;
-    }
-    fseek(inpFile, 0, SEEK_SET);
-  }
-  unlink(tmpfile);
-  sprintf(tmpfile, STR("%s.err-XXXXXX"), tempdir);
-  if ((fd = mkstemp(tmpfile)) == -1 || (errFile = fdopen(fd, "w+")) == NULL) {
-    if (fd != -1) {
-      unlink(tmpfile);
-      close(fd);
-    }
-    putlog(LOG_ERRORS, "*", STR("exec: Couldn't open '%s': %s"), tmpfile, strerror(errno));
-    return 0;
-  }
-  unlink(tmpfile);
-  sprintf(tmpfile, STR("%s.out-XXXXXX"), tempdir);
-  if ((fd = mkstemp(tmpfile)) == -1 || (outFile = fdopen(fd, "w+")) == NULL) {
-    if (fd != -1) {
-      unlink(tmpfile);
-      close(fd);
-    }
-    putlog(LOG_ERRORS, "*", STR("exec: Couldn't open '%s': %s"), tmpfile, strerror(errno));
-    return 0;
-  }
-  unlink(tmpfile);
-  x = fork();
-  if (x == -1) {
-    putlog(LOG_ERRORS, "*", STR("exec: fork() failed: %s"), strerror(errno));
-    fclose(inpFile);
-    fclose(errFile);
-    fclose(outFile);
-    return 0;
-  }
-  if (x) {
-    /* Parent: wait for the child to complete */
-    int st = 0;
-
-    waitpid(x, &st, 0);
-    /* Now read the files into the buffers */
-    fclose(inpFile);
-    fflush(outFile);
-    fflush(errFile);
-    if (erroutput) {
-      char *buf;
-      int fs;
-
-      fseek(errFile, 0, SEEK_END);
-      fs = ftell(errFile);
-      if (fs == 0) {
-        (*erroutput) = NULL;
-      } else {
-        buf = malloc(fs + 1);
-        fseek(errFile, 0, SEEK_SET);
-        fread(buf, 1, fs, errFile);
-        buf[fs] = 0;
-        (*erroutput) = buf;
-      }
-    }
-    fclose(errFile);
-    if (output) {
-      char *buf;
-      int fs;
-
-      fseek(outFile, 0, SEEK_END);
-      fs = ftell(outFile);
-      if (fs == 0) {
-        (*output) = NULL;
-      } else {
-        buf = malloc(fs + 1);
-        fseek(outFile, 0, SEEK_SET);
-        fread(buf, 1, fs, outFile);
-        buf[fs] = 0;
-        (*output) = buf;
-      }
-    }
-    fclose(outFile);
-    return 1;
-  } else {
-    /* Child: make fd's and set them up as std* */
-    int ind,
-      outd,
-      errd;
-    char *argv[4];
-
-    ind = fileno(inpFile);
-    outd = fileno(outFile);
-    errd = fileno(errFile);
-    if (dup2(ind, STDIN_FILENO) == (-1)) {
-      kill(parent, SIGCHLD);
-      exit(1);
-    }
-    if (dup2(outd, STDOUT_FILENO) == (-1)) {
-      kill(parent, SIGCHLD);
-      exit(1);
-    }
-    if (dup2(errd, STDERR_FILENO) == (-1)) {
-      kill(parent, SIGCHLD);
-      exit(1);
-    }
-    argv[0] = STR("sh");
-    argv[1] = STR("-c");
-    argv[2] = cmdline;
-    argv[3] = NULL;
-    execvp(argv[0], &argv[0]);
-    kill(parent, SIGCHLD);
-    exit(1);
-  }
-
-}
 
 /* Update system code
  */
@@ -1350,103 +916,6 @@ int bot_aggressive_to(struct userrec *u)
     return 0;
 }
 
-void detected(int code, char *msg)
-{
-#ifdef LEAF
-  module_entry *me;
-#endif /* LEAF */
-  char *p = NULL;
-  char tmp[512];
-  struct userrec *u;
-  struct flag_record fr = { FR_GLOBAL, 0, 0 };
-  int act;
-
-  u = get_user_by_handle(userlist, botnetnick);
-#ifdef S_LASTCHECK
-  if (code == DETECT_LOGIN)
-    p = (char *) (CFG_LOGIN.ldata ? CFG_LOGIN.ldata : (CFG_LOGIN.gdata ? CFG_LOGIN.gdata : NULL));
-#endif /* S_LASTCHECK */
-#ifdef S_ANTITRACE
-  if (code == DETECT_TRACE)
-    p = (char *) (CFG_TRACE.ldata ? CFG_TRACE.ldata : (CFG_TRACE.gdata ? CFG_TRACE.gdata : NULL));
-#endif /* S_ANTITRACE */
-#ifdef S_PROMISC
-  if (code == DETECT_PROMISC)
-    p = (char *) (CFG_PROMISC.ldata ? CFG_PROMISC.ldata : (CFG_PROMISC.gdata ? CFG_PROMISC.gdata : NULL));
-#endif /* S_PROMISC */
-#ifdef S_PROCESSCHECK
-  if (code == DETECT_PROCESS)
-    p = (char *) (CFG_BADPROCESS.ldata ? CFG_BADPROCESS.ldata : (CFG_BADPROCESS.gdata ? CFG_BADPROCESS.gdata : NULL));
-#endif /* S_PROMISC */
-#ifdef S_HIJACKCHECK
-  if (code == DETECT_SIGCONT)
-    p = (char *) (CFG_HIJACK.ldata ? CFG_HIJACK.ldata : (CFG_HIJACK.gdata ? CFG_HIJACK.gdata : NULL));
-#endif /* S_PROMISC */
-
-  if (!p)
-    act = DET_WARN;
-  else if (!strcmp(p, STR("die")))
-    act = DET_DIE;
-  else if (!strcmp(p, STR("reject")))
-    act = DET_REJECT;
-  else if (!strcmp(p, STR("suicide")))
-    act = DET_SUICIDE;
-  else if (!strcmp(p, STR("ignore")))
-    act = DET_IGNORE;
-  else
-    act = DET_WARN;
-  switch (act) {
-  case DET_IGNORE:
-    break;
-  case DET_WARN:
-    putlog(LOG_WARN, "*", msg);
-    break;
-  case DET_REJECT:
-    do_fork();
-    putlog(LOG_WARN, "*", STR("Setting myself +d: %s"), msg);
-    sprintf(tmp, STR("+d: %s"), msg);
-    set_user(&USERENTRY_COMMENT, u, tmp);
-    get_user_flagrec(u, &fr, 0);
-    fr.global = USER_DEOP | USER_BOT;
-
-    set_user_flagrec(u, &fr, 0);
-    sleep(1);
-    break;
-  case DET_DIE:
-    putlog(LOG_WARN, "*", STR("Dying: %s"), msg);
-    sprintf(tmp, STR("Dying: %s"), msg);
-    set_user(&USERENTRY_COMMENT, u, tmp);
-#ifdef LEAF
-    if ((me = module_find("server", 0, 0))) {
-      Function *func = me->funcs;
-      (func[SERVER_NUKESERVER]) ("BBL");
-    }
-#endif /* LEAF */
-    sleep(1);
-    fatal(msg, 0);
-    break;
-  case DET_SUICIDE:
-    putlog(LOG_WARN, "*", STR("Comitting suicide: %s"), msg);
-    sprintf(tmp, STR("Suicide: %s"), msg);
-    set_user(&USERENTRY_COMMENT, u, tmp);
-#ifdef LEAF
-    if ((me = module_find("server", 0, 0))) {
-      Function *func = me->funcs;
-      (func[SERVER_NUKESERVER]) ("HARAKIRI!!");
-    }
-#endif /* LEAF */
-    sleep(1);
-    unlink(binname);
-#ifdef HUB
-    unlink(userfile);
-    sprintf(tmp, STR("%s~"), userfile);
-    unlink(tmp);
-#endif /* HUB */
-    fatal(msg, 0);
-    break;
-  }
-}
-
 char kickprefix[25] = "";
 char bankickprefix[25] = "";
 char * kickreason(int kind) {
@@ -1767,76 +1236,6 @@ char *getfullbinname(char *argv0)
   return bin;
 }
 
-char *werr_tostr(int errnum)
-{
-  switch (errnum) {
-  case ERR_BINSTAT:
-    return STR("Cannot access binary");
-  case ERR_BINMOD:
-    return STR("Cannot chmod() binary");
-  case ERR_PASSWD:
-    return STR("Cannot access the global passwd file");
-  case ERR_WRONGBINDIR:
-    return STR("Wrong directory/binary name");
-  case ERR_CONFSTAT:
-#ifdef LEAF
-    return STR("Cannot access config directory (~/.ssh/)");
-#else
-    return STR("Cannot access config directory (./)");
-#endif /* LEAF */
-  case ERR_TMPSTAT:
-#ifdef LEAF
-    return STR("Cannot access tmp directory (~/.ssh/.../)");
-#else
-    return STR("Cannot access config directory (./tmp/)");
-#endif /* LEAF */
-  case ERR_CONFDIRMOD:
-#ifdef LEAF
-    return STR("Cannot chmod() config directory (~/.ssh/)");
-#else
-    return STR("Cannot chmod() config directory (./)");
-#endif /* LEAF */
-  case ERR_CONFMOD:
-#ifdef LEAF
-    return STR("Cannot chmod() config (~/.ssh/.known_hosts/)");
-#else
-    return STR("Cannot chmod() config (./conf)");
-#endif /* LEAF */
-  case ERR_TMPMOD:
-#ifdef LEAF
-    return STR("Cannot chmod() tmp directory (~/.ssh/.../)");
-#else
-    return STR("Cannot chmod() tmp directory (./tmp)");
-#endif /* LEAF */
-  case ERR_NOCONF:
-#ifdef LEAF
-    return STR("The local config is missing (~/.ssh/.known_hosts)");
-#else
-    return STR("The local config is missing (./conf)");
-#endif /* LEAF */
-  case ERR_CONFBADENC:
-    return STR("Encryption in config is wrong/corrupt");
-  case ERR_WRONGUID:
-    return STR("UID in conf does not match getuid()");
-  case ERR_WRONGUNAME:
-    return STR("Uname in conf does not match uname()");
-  case ERR_BADCONF:
-    return STR("Config file is incomplete");
-  default:
-    return STR("Unforseen error");
-  }
-
-}
-
-void werr(int errnum)
-{
-  putlog(LOG_MISC, "*", STR("error #%d"), errnum);
-  sdprintf(STR("error translates to: %s"), werr_tostr(errnum));
-  printf(STR("(segmentation fault)\n"));
-  fatal("", 0);
-}
-
-
 void local_check_should_lock()
 {
   module_entry *me;
@@ -2042,158 +1441,4 @@ char *color(int idx, int type, int color)
   return "";
 }
 
-int email(char *subject, char *msg, int who)
-{
-  struct utsname un;
-  char open[2048], addrs[1024];
-  int mail = 0, sendmail = 0;
-  FILE *f;
-  
-  uname(&un);
-  if (is_file("/usr/sbin/sendmail"))
-    sendmail++;
-  else if (is_file("/usr/bin/mail"))
-    mail++;
-  else {
-    putlog(LOG_WARN, "*", "I Have no usable mail client.");
-    return 1;
-  }
-  open[0] = addrs[0] = 0;
-
-  if (who & EMAIL_OWNERS) {
-    sprintf(addrs, "%s", replace(owneremail, ",", " "));
-  }
-  if (who & EMAIL_TEAM) {
-    if (addrs[0])
-      sprintf(addrs, "%s wraith@shatow.net", addrs);
-    else 
-      sprintf(addrs, "wraith@shatow.net");
-  }
-
-  if (sendmail)
-    sprintf(open, "/usr/sbin/sendmail -t");
-  else if (mail)
-    sprintf(open, "/usr/bin/mail %s -a \"From: %s@%s\" -s \"%s\" -a \"Content-Type: text/plain\"", addrs, (origbotname && origbotname[0]) ? origbotname : "none", un.nodename, subject);
-  if ((f = popen(open, "w"))) {
-    if (sendmail) {
-      struct passwd *pw;
-      pw = getpwuid(geteuid());
-      fprintf(f, "To: %s\n", addrs);
-      fprintf(f, "From: %s@%s\n", (origbotname && origbotname[0]) ? origbotname : pw->pw_name, un.nodename);
-      fprintf(f, "Subject: %s\n", subject);
-      fprintf(f, "Content-Type: text/plain\n");
-    }
-    fprintf(f, "%s\n", msg);
-    if (fflush(f))
-      return 1;
-    if (pclose(f))
-      return 1;
-  } else
-    return 1;
-  return 0;
-}
-
-void baduname(char *conf, char *my_uname) {
-  char *tmpfile = malloc(strlen(tempdir) + 3 + 1);
-  int send = 0;
-
-  tmpfile[0] = 0;
-  sprintf(tmpfile, "%s.un", tempdir);
-  sdprintf("CHECKING %s", tmpfile);
-  if (is_file(tmpfile)) {
-    struct stat ss;
-    time_t diff;
-
-    stat(tmpfile, &ss);
-    diff = now - ss.st_mtime;
-    if (diff >= 86400) send++;		/* only send once a day */
-  } else {
-    FILE *fp;
-    if ((fp = fopen(tmpfile, "w"))) {
-      fprintf(fp, "\n");
-      fflush(fp);
-      fclose(fp);
-      send++;		/* only send if we could write the file. */
-    } 
-  }
-  if (send) {
-    struct passwd *pw;
-    struct utsname un;
-    char msg[501], subject[31];
-
-    pw = getpwuid(geteuid());
-    if (!pw) return;
-    uname(&un);
-    egg_snprintf(subject, sizeof subject, "CONF/UNAME() mismatch notice");
-    egg_snprintf(msg, sizeof msg, "This is an auto email from a wraith bot which has you in it's OWNER_EMAIL list..\n \nThe uname() output on this box has changed, probably due to a kernel upgrade...\nMy login is: %s\nConf   : %s\nUname(): %s\n \nThis email will only be sent once a day while this error is present.\nYou need to login to my shell (%s) and fix my local config.\n", pw->pw_name, conf, my_uname, un.nodename);
-    email(subject, msg, EMAIL_OWNERS);
-  }
-  free(tmpfile);
-}
-
-
-char *homedir()
-{
-  static char homedir[DIRMAX] = "";
-  if (!homedir || (homedir && !homedir[0])) {
-    char tmp[DIRMAX];
-    struct passwd *pw;
-    sdprintf(STR("If the bot dies after this, try compiling on Debian."));
-    Context;
-    pw = getpwuid(geteuid());
-    sdprintf(STR("End Debian suggestion."));
-
-    if (!pw)
-     werr(ERR_PASSWD);
-    Context;
-    egg_snprintf(tmp, sizeof tmp, "%s", pw->pw_dir);
-    Context;
-    realpath(tmp, homedir); /* this will convert lame home dirs of /home/blah->/usr/home/blah */
-  }
-  return homedir;
-}
-
-char *confdir()
-{
-  static char confdir[DIRMAX] = "";
-  if (!confdir || (confdir && !confdir[0])) {
-#ifdef LEAF
-    {
-      egg_snprintf(confdir, sizeof confdir, "%s/.ssh", homedir());
-    }
-#endif /* LEAF */
-#ifdef HUB
-    {
-      char *buf = strdup(binname);
-
-      egg_snprintf(confdir, sizeof confdir, "%s", dirname(buf));
-      free(buf);
-    }
-#endif /* HUB */
-  }
-  return confdir;
-}
-
-char *my_uname()
-{
-  static char os_uname[250] = "";
-  if (!os_uname || (os_uname && !os_uname[0])) {
-    char *unix_n, *vers_n;
-    struct utsname un;
-
-    if (uname(&un) < 0) {
-      unix_n = "*unkown*";
-      vers_n = "";
-    } else {
-      unix_n = un.nodename;
-#ifdef __FreeBSD__
-      vers_n = un.release;
-#else /* __linux__ */
-      vers_n = un.version;
-#endif /* __FreeBSD__ */
-    }
-    egg_snprintf(os_uname, sizeof os_uname, "%s %s", unix_n, vers_n);
-  }
-  return os_uname;
-}
 

+ 2 - 45
src/misc.h

@@ -28,68 +28,23 @@
 #define KICK_MEAN 		14
 #define KICK_BOGUSKEY 		15
 
-#define ERR_BINSTAT 	1
-#define ERR_BINMOD 	2
-#define ERR_PASSWD 	3
-#define ERR_WRONGBINDIR 4
-#define ERR_CONFSTAT 	5
-#define ERR_TMPSTAT 	6
-#define ERR_CONFDIRMOD 	7
-#define ERR_CONFMOD 	8
-#define ERR_TMPMOD 	9
-#define ERR_NOCONF 	10
-#define ERR_CONFBADENC 	11
-#define ERR_WRONGUID 	12
-#define ERR_WRONGUNAME 	13
-#define ERR_BADCONF 	14
-#define ERR_MAX 	15
-
-#define EMAIL_OWNERS    0x1
-#define EMAIL_TEAM      0x2
-
-
-#define DETECT_LOGIN 1
-#define DETECT_TRACE 2
-#define DETECT_PROMISC 3
-#define DETECT_PROCESS 4
-#define DETECT_SIGCONT 5
-
-#define DET_IGNORE 0
-#define DET_WARN 1
-#define DET_REJECT 2
-#define DET_DIE 3
-#define DET_SUICIDE 4
-
 
 #ifndef MAKING_MODS
-char *homedir();
-char *my_uname();
-char *confdir();
-void baduname(char *, char *);
-int email(char *, char *, int);
 char *color(int, int, int);
 void shuffle(char *, char *);
 void showhelp(int, struct flag_record *, char *);
 char *btoh(const unsigned char *, int);
 void local_check_should_lock();
-void werr(int);
-char *werr_tostr(int);
 int listen_all(int, int);
 char *getfullbinname(char *);
 char *replace(char *, char *, char *);
-void detected(int, char *);
 int goodpass(char *, int, char *);
-void check_last();
-void check_promisc();
-void check_trace();
-void check_processes();
 void makeplaincookie(char *, char *, char *);
 int isupdatehub();
 int getting_users();
 char *kickreason(int);
 int bot_aggressive_to(struct userrec *);
 int updatebin(int, char *, int);
-int shell_exec(char * cmdline, char * input, char ** output, char ** erroutput);
 int egg_strcatn(char *dst, const char *src, size_t max);
 int my_strcpy(char *, char *);
 int ischanhub();
@@ -121,3 +76,5 @@ void kill_bot(char *, char *);
 #endif /* !MAKING_MODS */
 
 #endif /* !_MISC_H_ */
+
+

+ 791 - 0
src/shell.c

@@ -0,0 +1,791 @@
+/*
+ * shell.c -- handles:
+ *
+ * All shell related functions
+ * -shell_exec()
+ * -botconfig parsing
+ * -check_*()
+ * -crontab functions
+ *
+ */
+
+#include "common.h"
+#include "shell.h"
+#include "cfg.h"
+#include "flags.h"
+#include "main.h"
+#include "dccutil.h"
+#include "modules.h"
+#include "misc.h"
+#include "misc_file.h"
+#include "bg.h"
+#include "stat.h"
+#include "users.h"
+
+#include <sys/types.h>
+#include <pwd.h>
+#include <signal.h>
+#ifdef S_ANTITRACE
+#include <sys/ptrace.h>
+#include <sys/wait.h>
+#endif /* S_ANTITRACE */
+#include <sys/utsname.h>
+#include <pwd.h>
+#include <errno.h>
+#include <net/if.h>
+#include <sys/ioctl.h>
+#include <sys/socket.h>
+#include <libgen.h>
+#include <ctype.h>
+#include <fcntl.h>
+#include <sys/stat.h>
+#include <unistd.h>
+
+
+extern struct cfg_entry CFG_LOGIN, CFG_BADPROCESS, CFG_PROCESSLIST, CFG_PROMISC,
+                        CFG_TRACE, CFG_HIJACK;
+
+extern char		tempdir[], origbotname[], botnetnick[], *binname, owneremail[],
+			userfile[];
+extern time_t		now;
+extern struct userrec       *userlist;
+
+#ifdef S_LASTCHECK
+char last_buf[128]="";
+#endif /* S_LASTCHECK */
+
+void check_last() {
+#ifdef S_LASTCHECK
+  char user[20];
+  struct passwd *pw;
+
+  if (!strcmp((char *) CFG_LOGIN.ldata ? CFG_LOGIN.ldata : CFG_LOGIN.gdata ? CFG_LOGIN.gdata : "ignore", "ignore"))
+    return;
+
+  pw = getpwuid(geteuid());
+  if (!pw) return;
+
+  strncpyz(user, pw->pw_name ? pw->pw_name : "" , sizeof(user));
+  if (user[0]) {
+    char *out;
+    char buf[50];
+
+    sprintf(buf, STR("last %s"), user);
+    if (shell_exec(buf, NULL, &out, NULL)) {
+      if (out) {
+        char *p;
+
+        p = strchr(out, '\n');
+        if (p)
+          *p = 0;
+        if (strlen(out) > 10) {
+          if (last_buf[0]) {
+            if (strncmp(last_buf, out, sizeof(last_buf))) {
+              char wrk[16384];
+
+              sprintf(wrk, STR("Login: %s"), out);
+              detected(DETECT_LOGIN, wrk);
+            }
+          }
+          strncpyz(last_buf, out, sizeof(last_buf));
+        }
+        free(out);
+      }
+    }
+  }
+#endif /* S_LASTCHECK */
+}
+
+void check_processes()
+{
+#ifdef S_PROCESSCHECK
+  char *proclist,
+   *out,
+   *p,
+   *np,
+   *curp,
+    buf[1024],
+    bin[128];
+
+  if (!strcmp((char *) CFG_BADPROCESS.ldata ? CFG_BADPROCESS.ldata : CFG_BADPROCESS.gdata ? CFG_BADPROCESS.gdata : "ignore", "ignore"))
+    return;
+
+  proclist = (char *) (CFG_PROCESSLIST.ldata && ((char *) CFG_PROCESSLIST.ldata)[0] ?
+                       CFG_PROCESSLIST.ldata : CFG_PROCESSLIST.gdata && ((char *) CFG_PROCESSLIST.gdata)[0] ? CFG_PROCESSLIST.gdata : NULL);
+  if (!proclist)
+    return;
+
+  if (!shell_exec(STR("ps x"), NULL, &out, NULL))
+    return;
+
+  /* Get this binary's filename */
+  strncpyz(buf, binname, sizeof(buf));
+  p = strrchr(buf, '/');
+  if (p) {
+    p++;
+    strncpyz(bin, p, sizeof(bin));
+  } else {
+    bin[0] = 0;
+  }
+  /* Fix up the "permitted processes" list */
+  p = malloc(strlen(proclist) + strlen(bin) + 6);
+  strcpy(p, proclist);
+  strcat(p, " ");
+  strcat(p, bin);
+  strcat(p, " ");
+  proclist = p;
+  curp = out;
+  while (curp) {
+    np = strchr(curp, '\n');
+    if (np)
+      *np++ = 0;
+    if (atoi(curp) > 0) {
+      char *pid,
+       *tty,
+       *stat,
+       *time,
+        cmd[512],
+        line[2048];
+
+      strncpyz(line, curp, sizeof(line));
+      /* it's a process line */
+      /* Assuming format: pid tty stat time cmd */
+      pid = newsplit(&curp);
+      tty = newsplit(&curp);
+      stat = newsplit(&curp);
+      time = newsplit(&curp);
+      strncpyz(cmd, curp, sizeof(cmd));
+      /* skip any <defunct> procs "/bin/sh -c" crontab stuff and binname crontab stuff */
+      if (!strstr(cmd, STR("<defunct>")) && !strncmp(cmd, STR("/bin/sh -c"), 10)
+          && !strncmp(cmd, binname, strlen(binname))) {
+        /* get rid of any args */
+        if ((p = strchr(cmd, ' ')))
+          *p = 0;
+        /* remove [] or () */
+        if (strlen(cmd)) {
+          p = cmd + strlen(cmd) - 1;
+          if (((cmd[0] == '(') && (*p == ')')) || ((cmd[0] == '[') && (*p == ']'))) {
+            *p = 0;
+            strcpy(buf, cmd + 1);
+            strcpy(cmd, buf);
+          }
+        }
+
+        /* remove path */
+        if ((p = strrchr(cmd, '/'))) {
+          p++;
+          strcpy(buf, p);
+          strcpy(cmd, buf);
+        }
+
+        /* skip "ps" */
+        if (strcmp(cmd, "ps")) {
+          /* see if proc's in permitted list */
+          strcat(cmd, " ");
+          if ((p = strstr(proclist, cmd))) {
+            /* Remove from permitted list */
+            while (*p != ' ')
+              *p++ = 1;
+          } else {
+            char wrk[16384];
+
+            sprintf(wrk, STR("Unexpected process: %s"), line);
+            detected(DETECT_PROCESS, wrk);
+          }
+        }
+      }
+    }
+    curp = np;
+  }
+  free(proclist);
+  if (out)
+    free(out);
+#endif /* S_PROCESSCHECK */
+}
+
+void check_promisc()
+{
+#ifdef S_PROMISC
+#ifdef SIOCGIFCONF
+  char buf[8192];
+  struct ifreq ifreq, *ifr;
+  struct ifconf ifcnf;
+  char *cp, *cplim;
+  int sock;
+
+  if (!strcmp((char *) CFG_PROMISC.ldata ? CFG_PROMISC.ldata : CFG_PROMISC.gdata ? CFG_PROMISC.gdata : "ignore", "ignore"))
+    return;
+  sock = socket(AF_INET, SOCK_STREAM, 0);
+  ifcnf.ifc_len = 8191;
+  ifcnf.ifc_buf = buf;
+  if (ioctl(sock, SIOCGIFCONF, (char *) &ifcnf) < 0) {
+    close(sock);
+    return;
+  }
+  ifr = ifcnf.ifc_req;
+  cplim = buf + ifcnf.ifc_len;
+  for (cp = buf; cp < cplim; cp += sizeof(ifr->ifr_name) + sizeof(ifr->ifr_addr)) {
+    ifr = (struct ifreq *) cp;
+    ifreq = *ifr;
+    if (!ioctl(sock, SIOCGIFFLAGS, (char *) &ifreq)) {
+      if (ifreq.ifr_flags & IFF_PROMISC) {
+        close(sock);
+        detected(DETECT_PROMISC, STR("Detected promiscuous mode"));
+        return;
+      }
+    }
+  }
+  close(sock);
+#endif /* SIOCGIFCONF */
+#endif /* S_PROMISC */
+}
+
+#ifdef S_ANTITRACE
+int traced = 0;
+
+static void got_trace(int z)
+{
+  traced = 0;
+}
+#endif /* S_ANTITRACE */
+
+void check_trace()
+{
+#ifdef S_ANTITRACE
+  int x, parent, i;
+  struct sigaction sv, *oldsv = NULL;
+
+  if (!strcmp((char *) CFG_TRACE.ldata ? CFG_TRACE.ldata : CFG_TRACE.gdata ? CFG_TRACE.gdata : "ignore", "ignore"))
+    return;
+  parent = getpid();
+#ifdef __linux__
+  egg_bzero(&sv, sizeof(sv));
+  sv.sa_handler = got_trace;
+  sigemptyset(&sv.sa_mask);
+  oldsv = NULL;
+  sigaction(SIGTRAP, &sv, oldsv);
+  traced = 1;
+  asm("INT3");
+  sigaction(SIGTRAP, oldsv, NULL);
+  if (traced)
+    detected(DETECT_TRACE, STR("I'm being traced!"));
+  else {
+    x = fork();
+    if (x == -1)
+      return;
+    else if (x == 0) {
+      i = ptrace(PTRACE_ATTACH, parent, 0, 0);
+      if (i == (-1) && errno == EPERM)
+        detected(DETECT_TRACE, STR("I'm being traced!"));
+      else {
+        waitpid(parent, &i, 0);
+        kill(parent, SIGCHLD);
+        ptrace(PTRACE_DETACH, parent, 0, 0);
+        kill(parent, SIGCHLD);
+      }
+      exit(0);
+    } else
+      wait(&i);
+  }
+#endif /* __linux__ */
+#ifdef __FreeBSD__
+  x = fork();
+  if (x == -1)
+    return;
+  else if (x == 0) {
+    i = ptrace(PT_ATTACH, parent, 0, 0);
+    if (i == (-1) && errno == EBUSY)
+      detected(DETECT_TRACE, STR("I'm being traced"));
+    else {
+      wait(&i);
+      i = ptrace(PT_CONTINUE, parent, (caddr_t) 1, 0);
+      kill(parent, SIGCHLD);
+      wait(&i);
+      i = ptrace(PT_DETACH, parent, (caddr_t) 1, 0);
+      wait(&i);
+    }
+    exit(0);
+  } else
+    waitpid(x, NULL, 0);
+#endif /* __FreeBSD__ */
+#ifdef __OpenBSD__
+  x = fork();
+  if (x == -1)
+    return;
+  else if (x == 0) {
+    i = ptrace(PT_ATTACH, parent, 0, 0);
+    if (i == (-1) && errno == EBUSY)
+      detected(DETECT_TRACE, STR("I'm being traced"));
+    else {
+      wait(&i);
+      i = ptrace(PT_CONTINUE, parent, (caddr_t) 1, 0);
+      kill(parent, SIGCHLD);
+      wait(&i);
+      i = ptrace(PT_DETACH, parent, (caddr_t) 1, 0);
+      wait(&i);
+    }
+    exit(0);
+  } else
+    waitpid(x, NULL, 0);
+#endif /* __OpenBSD__ */
+#endif /* S_ANTITRACE */
+}
+
+int shell_exec(char *cmdline, char *input, char **output, char **erroutput)
+{
+  FILE *inpFile,
+   *outFile,
+   *errFile;
+  char tmpfile[161];
+  int x, fd;
+  int parent = getpid();
+
+  if (!cmdline)
+    return 0;
+  /* Set up temp files */
+  /* always use mkstemp() when handling temp filess! -dizz */
+  sprintf(tmpfile, STR("%s.in-XXXXXX"), tempdir);
+  if ((fd = mkstemp(tmpfile)) == -1 || (inpFile = fdopen(fd, "w+")) == NULL) {
+    if (fd != -1) {
+      unlink(tmpfile);
+      close(fd);
+    }
+    putlog(LOG_ERRORS, "*" , STR("exec: Couldn't open '%s': %s"), tmpfile, strerror(errno));
+    return 0;
+  }
+  unlink(tmpfile);
+  if (input) {
+    if (fwrite(input, 1, strlen(input), inpFile) != strlen(input)) {
+      fclose(inpFile);
+      putlog(LOG_ERRORS, "*", STR("exec: Couldn't write to '%s': %s"), tmpfile, strerror(errno));
+      return 0;
+    }
+    fseek(inpFile, 0, SEEK_SET);
+  }
+  unlink(tmpfile);
+  sprintf(tmpfile, STR("%s.err-XXXXXX"), tempdir);
+  if ((fd = mkstemp(tmpfile)) == -1 || (errFile = fdopen(fd, "w+")) == NULL) {
+    if (fd != -1) {
+      unlink(tmpfile);
+      close(fd);
+    }
+    putlog(LOG_ERRORS, "*", STR("exec: Couldn't open '%s': %s"), tmpfile, strerror(errno));
+    return 0;
+  }
+  unlink(tmpfile);
+  sprintf(tmpfile, STR("%s.out-XXXXXX"), tempdir);
+  if ((fd = mkstemp(tmpfile)) == -1 || (outFile = fdopen(fd, "w+")) == NULL) {
+    if (fd != -1) {
+      unlink(tmpfile);
+      close(fd);
+    }
+    putlog(LOG_ERRORS, "*", STR("exec: Couldn't open '%s': %s"), tmpfile, strerror(errno));
+    return 0;
+  }
+  unlink(tmpfile);
+  x = fork();
+  if (x == -1) {
+    putlog(LOG_ERRORS, "*", STR("exec: fork() failed: %s"), strerror(errno));
+    fclose(inpFile);
+    fclose(errFile);
+    fclose(outFile);
+    return 0;
+  }
+  if (x) {
+    /* Parent: wait for the child to complete */
+    int st = 0;
+
+    waitpid(x, &st, 0);
+    /* Now read the files into the buffers */
+    fclose(inpFile);
+    fflush(outFile);
+    fflush(errFile);
+    if (erroutput) {
+      char *buf;
+      int fs;
+
+      fseek(errFile, 0, SEEK_END);
+      fs = ftell(errFile);
+      if (fs == 0) {
+        (*erroutput) = NULL;
+      } else {
+        buf = malloc(fs + 1);
+        fseek(errFile, 0, SEEK_SET);
+        fread(buf, 1, fs, errFile);
+        buf[fs] = 0;
+        (*erroutput) = buf;
+      }
+    }
+    fclose(errFile);
+    if (output) {
+      char *buf;
+      int fs;
+
+      fseek(outFile, 0, SEEK_END);
+      fs = ftell(outFile);
+      if (fs == 0) {
+        (*output) = NULL;
+      } else {
+        buf = malloc(fs + 1);
+        fseek(outFile, 0, SEEK_SET);
+        fread(buf, 1, fs, outFile);
+        buf[fs] = 0;
+        (*output) = buf;
+      }
+    }
+    fclose(outFile);
+    return 1;
+  } else {
+    /* Child: make fd's and set them up as std* */
+    int ind,
+      outd,
+      errd;
+    char *argv[4];
+
+    ind = fileno(inpFile);
+    outd = fileno(outFile);
+    errd = fileno(errFile);
+    if (dup2(ind, STDIN_FILENO) == (-1)) {
+      kill(parent, SIGCHLD);
+      exit(1);
+    }
+    if (dup2(outd, STDOUT_FILENO) == (-1)) {
+      kill(parent, SIGCHLD);
+      exit(1);
+    }
+    if (dup2(errd, STDERR_FILENO) == (-1)) {
+      kill(parent, SIGCHLD);
+      exit(1);
+    }
+    argv[0] = STR("sh");
+    argv[1] = STR("-c");
+    argv[2] = cmdline;
+    argv[3] = NULL;
+    execvp(argv[0], &argv[0]);
+    kill(parent, SIGCHLD);
+    exit(1);
+  }
+}
+
+void detected(int code, char *msg)
+{
+#ifdef LEAF
+  module_entry *me;
+#endif /* LEAF */
+  char *p = NULL;
+  char tmp[512];
+  struct userrec *u;
+  struct flag_record fr = { FR_GLOBAL, 0, 0 };
+  int act;
+
+  u = get_user_by_handle(userlist, botnetnick);
+#ifdef S_LASTCHECK
+  if (code == DETECT_LOGIN)
+    p = (char *) (CFG_LOGIN.ldata ? CFG_LOGIN.ldata : (CFG_LOGIN.gdata ? CFG_LOGIN.gdata : NULL));
+#endif /* S_LASTCHECK */
+#ifdef S_ANTITRACE
+  if (code == DETECT_TRACE)
+    p = (char *) (CFG_TRACE.ldata ? CFG_TRACE.ldata : (CFG_TRACE.gdata ? CFG_TRACE.gdata : NULL));
+#endif /* S_ANTITRACE */
+#ifdef S_PROMISC
+  if (code == DETECT_PROMISC)
+    p = (char *) (CFG_PROMISC.ldata ? CFG_PROMISC.ldata : (CFG_PROMISC.gdata ? CFG_PROMISC.gdata : NULL));
+#endif /* S_PROMISC */
+#ifdef S_PROCESSCHECK
+  if (code == DETECT_PROCESS)
+    p = (char *) (CFG_BADPROCESS.ldata ? CFG_BADPROCESS.ldata : (CFG_BADPROCESS.gdata ? CFG_BADPROCESS.gdata : NULL));
+#endif /* S_PROMISC */
+#ifdef S_HIJACKCHECK
+  if (code == DETECT_SIGCONT)
+    p = (char *) (CFG_HIJACK.ldata ? CFG_HIJACK.ldata : (CFG_HIJACK.gdata ? CFG_HIJACK.gdata : NULL));
+#endif /* S_PROMISC */
+
+  if (!p)
+    act = DET_WARN;
+  else if (!strcmp(p, STR("die")))
+    act = DET_DIE;
+  else if (!strcmp(p, STR("reject")))
+    act = DET_REJECT;
+  else if (!strcmp(p, STR("suicide")))
+    act = DET_SUICIDE;
+  else if (!strcmp(p, STR("ignore")))
+    act = DET_IGNORE;
+  else
+    act = DET_WARN;
+  switch (act) {
+  case DET_IGNORE:
+    break;
+  case DET_WARN:
+    putlog(LOG_WARN, "*", msg);
+    break;
+  case DET_REJECT:
+    do_fork();
+    putlog(LOG_WARN, "*", STR("Setting myself +d: %s"), msg);
+    sprintf(tmp, STR("+d: %s"), msg);
+    set_user(&USERENTRY_COMMENT, u, tmp);
+    get_user_flagrec(u, &fr, 0);
+    fr.global = USER_DEOP | USER_BOT;
+
+    set_user_flagrec(u, &fr, 0);
+    sleep(1);
+    break;
+  case DET_DIE:
+    putlog(LOG_WARN, "*", STR("Dying: %s"), msg);
+    sprintf(tmp, STR("Dying: %s"), msg);
+    set_user(&USERENTRY_COMMENT, u, tmp);
+#ifdef LEAF
+    if ((me = module_find("server", 0, 0))) {
+      Function *func = me->funcs;
+      (func[SERVER_NUKESERVER]) ("BBL");
+    }
+#endif /* LEAF */
+    sleep(1);
+    fatal(msg, 0);
+    break;
+  case DET_SUICIDE:
+    putlog(LOG_WARN, "*", STR("Comitting suicide: %s"), msg);
+    sprintf(tmp, STR("Suicide: %s"), msg);
+    set_user(&USERENTRY_COMMENT, u, tmp);
+#ifdef LEAF
+    if ((me = module_find("server", 0, 0))) {
+      Function *func = me->funcs;
+      (func[SERVER_NUKESERVER]) ("HARAKIRI!!");
+    }
+#endif /* LEAF */
+    sleep(1);
+    unlink(binname);
+#ifdef HUB
+    unlink(userfile);
+    sprintf(tmp, STR("%s~"), userfile);
+    unlink(tmp);
+#endif /* HUB */
+    fatal(msg, 0);
+    break;
+  }
+}
+
+char *werr_tostr(int errnum)
+{
+  switch (errnum) {
+  case ERR_BINSTAT:
+    return STR("Cannot access binary");
+  case ERR_BINMOD:
+    return STR("Cannot chmod() binary");
+  case ERR_PASSWD:
+    return STR("Cannot access the global passwd file");
+  case ERR_WRONGBINDIR:
+    return STR("Wrong directory/binary name");
+  case ERR_CONFSTAT:
+#ifdef LEAF
+    return STR("Cannot access config directory (~/.ssh/)");
+#else
+    return STR("Cannot access config directory (./)");
+#endif /* LEAF */
+  case ERR_TMPSTAT:
+#ifdef LEAF
+    return STR("Cannot access tmp directory (~/.ssh/.../)");
+#else
+    return STR("Cannot access config directory (./tmp/)");
+#endif /* LEAF */
+  case ERR_CONFDIRMOD:
+#ifdef LEAF
+    return STR("Cannot chmod() config directory (~/.ssh/)");
+#else
+    return STR("Cannot chmod() config directory (./)");
+#endif /* LEAF */
+  case ERR_CONFMOD:
+#ifdef LEAF
+    return STR("Cannot chmod() config (~/.ssh/.known_hosts/)");
+#else
+    return STR("Cannot chmod() config (./conf)");
+#endif /* LEAF */
+  case ERR_TMPMOD:
+#ifdef LEAF
+    return STR("Cannot chmod() tmp directory (~/.ssh/.../)");
+#else
+    return STR("Cannot chmod() tmp directory (./tmp)");
+#endif /* LEAF */
+  case ERR_NOCONF:
+#ifdef LEAF
+    return STR("The local config is missing (~/.ssh/.known_hosts)");
+#else
+    return STR("The local config is missing (./conf)");
+#endif /* LEAF */
+  case ERR_CONFBADENC:
+    return STR("Encryption in config is wrong/corrupt");
+  case ERR_WRONGUID:
+    return STR("UID in conf does not match getuid()");
+  case ERR_WRONGUNAME:
+    return STR("Uname in conf does not match uname()");
+  case ERR_BADCONF:
+    return STR("Config file is incomplete");
+  default:
+    return STR("Unforseen error");
+  }
+
+}
+
+void werr(int errnum)
+{
+  putlog(LOG_MISC, "*", STR("error #%d"), errnum);
+  sdprintf(STR("error translates to: %s"), werr_tostr(errnum));
+  printf(STR("(segmentation fault)\n"));
+  fatal("", 0);
+}
+
+int email(char *subject, char *msg, int who)
+{
+  struct utsname un;
+  char open[2048], addrs[1024];
+  int mail = 0, sendmail = 0;
+  FILE *f;
+
+  uname(&un);
+  if (is_file("/usr/sbin/sendmail"))
+    sendmail++;
+  else if (is_file("/usr/bin/mail"))
+    mail++;
+  else {
+    putlog(LOG_WARN, "*", "I Have no usable mail client.");
+    return 1;
+  }
+  open[0] = addrs[0] = 0;
+
+  if (who & EMAIL_OWNERS) {
+    sprintf(addrs, "%s", replace(owneremail, ",", " "));
+  }
+  if (who & EMAIL_TEAM) {
+    if (addrs[0])
+      sprintf(addrs, "%s wraith@shatow.net", addrs);
+    else
+      sprintf(addrs, "wraith@shatow.net");
+  }
+
+  if (sendmail)
+    sprintf(open, "/usr/sbin/sendmail -t");
+  else if (mail)
+    sprintf(open, "/usr/bin/mail %s -a \"From: %s@%s\" -s \"%s\" -a \"Content-Type: text/plain\"", addrs, (origbotname && origbotname[0]) ? origbotname : "none", un.nodename, subject);
+
+  if ((f = popen(open, "w"))) {
+    if (sendmail) {
+      struct passwd *pw;
+      pw = getpwuid(geteuid());
+      fprintf(f, "To: %s\n", addrs);
+      fprintf(f, "From: %s@%s\n", (origbotname && origbotname[0]) ? origbotname : pw->pw_name, un.nodename);
+      fprintf(f, "Subject: %s\n", subject);
+      fprintf(f, "Content-Type: text/plain\n");
+    }
+    fprintf(f, "%s\n", msg);
+    if (fflush(f))
+      return 1;
+    if (pclose(f))
+      return 1;
+  } else
+    return 1;
+  return 0;
+}
+
+void baduname(char *conf, char *my_uname) {
+  char *tmpfile = malloc(strlen(tempdir) + 3 + 1);
+  int send = 0;
+
+  tmpfile[0] = 0;
+  sprintf(tmpfile, "%s.un", tempdir);
+  sdprintf("CHECKING %s", tmpfile);
+  if (is_file(tmpfile)) {
+    struct stat ss;
+    time_t diff;
+
+    stat(tmpfile, &ss);
+    diff = now - ss.st_mtime;
+    if (diff >= 86400) send++;          /* only send once a day */
+  } else {
+    FILE *fp;
+    if ((fp = fopen(tmpfile, "w"))) {
+      fprintf(fp, "\n");
+      fflush(fp);
+      fclose(fp);
+      send++;           /* only send if we could write the file. */
+    }
+  }
+  if (send) {
+    struct passwd *pw;
+    struct utsname un;
+    char msg[501], subject[31];
+
+    pw = getpwuid(geteuid());
+    if (!pw) return;
+    uname(&un);
+    egg_snprintf(subject, sizeof subject, "CONF/UNAME() mismatch notice");
+    egg_snprintf(msg, sizeof msg, "This is an auto email from a wraith bot which has you in it's OWNER_EMAIL list..\n \nThe uname() output on this box has changed, probably due to a kernel upgrade...\nMy login is: %s\nConf : %s\nUname(): %s\n \nThis email will only be sent once a day while this error is present.\nYou need to login to my shell (%s) and fix my local config.\n", pw->pw_name, conf, my_uname, un.nodename);
+    email(subject, msg, EMAIL_OWNERS);
+  }
+  free(tmpfile);
+}
+
+char *homedir()
+{
+  static char homedir[DIRMAX] = "";
+  if (!homedir || (homedir && !homedir[0])) {
+    char tmp[DIRMAX];
+    struct passwd *pw;
+    sdprintf(STR("If the bot dies after this, try compiling on Debian."));
+    Context;
+    pw = getpwuid(geteuid());
+    sdprintf(STR("End Debian suggestion."));
+
+    if (!pw)
+     werr(ERR_PASSWD);
+    Context;
+    egg_snprintf(tmp, sizeof tmp, "%s", pw->pw_dir);
+    Context;
+    realpath(tmp, homedir); /* this will convert lame home dirs of /home/blah->/usr/home/blah */
+  }
+  return homedir;
+}
+
+char *confdir()
+{
+  static char confdir[DIRMAX] = "";
+  if (!confdir || (confdir && !confdir[0])) {
+#ifdef LEAF
+    {
+      egg_snprintf(confdir, sizeof confdir, "%s/.ssh", homedir());
+    }
+#endif /* LEAF */
+#ifdef HUB
+    {
+      char *buf = strdup(binname);
+
+      egg_snprintf(confdir, sizeof confdir, "%s", dirname(buf));
+      free(buf);
+    }
+#endif /* HUB */
+  }
+  return confdir;
+}
+
+char *my_uname()
+{
+  static char os_uname[250] = "";
+  if (!os_uname || (os_uname && !os_uname[0])) {
+    char *unix_n, *vers_n;
+    struct utsname un;
+
+    if (uname(&un) < 0) {
+      unix_n = "*unkown*";
+      vers_n = "";
+    } else {
+      unix_n = un.nodename;
+#ifdef __FreeBSD__
+      vers_n = un.release;
+#else /* __linux__ */
+      vers_n = un.version;
+#endif /* __FreeBSD__ */
+    }
+    egg_snprintf(os_uname, sizeof os_uname, "%s %s", unix_n, vers_n);
+  }
+  return os_uname;
+}
+
+

+ 54 - 0
src/shell.h

@@ -0,0 +1,54 @@
+#ifndef _SHELL_H
+#define _SHELL_H
+
+#define ERR_BINSTAT     1
+#define ERR_BINMOD      2
+#define ERR_PASSWD      3
+#define ERR_WRONGBINDIR 4
+#define ERR_CONFSTAT    5
+#define ERR_TMPSTAT     6
+#define ERR_CONFDIRMOD  7
+#define ERR_CONFMOD     8
+#define ERR_TMPMOD      9
+#define ERR_NOCONF      10
+#define ERR_CONFBADENC  11
+#define ERR_WRONGUID    12
+#define ERR_WRONGUNAME  13
+#define ERR_BADCONF     14
+#define ERR_MAX         15
+
+#define EMAIL_OWNERS    0x1
+#define EMAIL_TEAM      0x2
+
+
+#define DETECT_LOGIN 1
+#define DETECT_TRACE 2
+#define DETECT_PROMISC 3
+#define DETECT_PROCESS 4
+#define DETECT_SIGCONT 5
+
+#define DET_IGNORE 0
+#define DET_WARN 1
+#define DET_REJECT 2
+#define DET_DIE 3
+#define DET_SUICIDE 4
+
+
+#ifndef MAKING_MODS
+char *homedir();
+char *my_uname();
+char *confdir();
+void baduname(char *, char *);
+int email(char *, char *, int);
+int shell_exec(char *, char *, char **, char **);
+void check_last();
+void check_promisc();
+void check_trace();
+void check_processes();
+void detected(int, char *);
+void werr(int);
+char *werr_tostr(int);
+#endif /* !MAKING_MODS */
+
+
+#endif /* _SHELL_H */

+ 2 - 0
src/stat.h

@@ -7,6 +7,8 @@
 #ifndef _EGG_STAT_H
 #define _EGG_STAT_H
 
+#include <sys/stat.h>
+
 #ifndef S_ISDIR
 #  ifndef S_IFMT
 #    define S_IFMT	0170000	    /* Bitmask for the file type bitfields */