Example #1
0
char *dns_start(Function *global_funcs)
{
  int idx;

  global = global_funcs;

  module_register(MODULE_NAME, dns_table, 1, 0);
  if (!module_depend(MODULE_NAME, "eggdrop", 106, 0)) {
    module_undepend(MODULE_NAME);
    return "This module requires Eggdrop 1.6.0 or later.";
  }

  idx = new_dcc(&DCC_DNS, 0);
  if (idx < 0)
    return "NO MORE DCC CONNECTIONS -- Can't create DNS socket.";
  if (!init_dns_core()) {
    lostdcc(idx);
    return "DNS initialisation failed.";
  }
  dcc[idx].sock = resfd;
  dcc[idx].timeval = now;
  strcpy(dcc[idx].nick, "(dns)");

  add_hook(HOOK_SECONDLY, (Function) dns_check_expires);
  add_hook(HOOK_DNS_HOSTBYIP, (Function) dns_lookup);
  add_hook(HOOK_DNS_IPBYHOST, (Function) dns_forward);
  return NULL;
}
Example #2
0
void rehash_ip() {
  /* cache our ip on load instead of every 30 seconds */
  char *ip4 = NULL, *ip6 = NULL;

  if (cached_ip) {
    ip4 = strdup(myipstr(AF_INET));
    ip6 = strdup(myipstr(AF_INET6));
  }

  cache_my_ip();
  sdprintf("ip4: %s", myipstr(AF_INET));
  sdprintf("ip6: %s", myipstr(AF_INET6));

  /* Check if our ip changed during a rehash */
  if (ip4) {
    if (strcmp(ip4, myipstr(AF_INET)) || strcmp(ip6, myipstr(AF_INET6))) {
      if (tands > 0) {
        botnet_send_chat(-1, conf.bot->nick, "IP changed.");
        botnet_send_bye("IP changed.");
      }
      fatal("brb", 1);
    }

    free(ip4);
    free(ip6);
  }

  if (conf.bot->hub) {
    struct bot_addr *bi = (struct bot_addr *) get_user(&USERENTRY_BOTADDR, conf.bot->u);
    listen_all(bi->telnet_port, 0, 1);
    my_port = bi->telnet_port;
  } else if (conf.bot->localhub) {
    // If not listening on the domain socket, open it up
    bool listening = 0;
    for (int i = 0; i < dcc_total; i++) {
      if (dcc[i].type && (dcc[i].type == &DCC_TELNET) && (!strcmp(dcc[i].host, conf.localhub_socket)) && (!strcmp(dcc[i].nick, "(unix_domain"))) {
        listening = 1;
        break;
      }
    }
    if (!listening) {
      // Listen on the unix domain socket
      port_t port;
      int i = open_listen_addr_by_af(conf.localhub_socket, &port, AF_UNIX);
      if (i < 0) {
        putlog(LOG_ERRORS, "*", "Can't listen on %s - %s", conf.localhub_socket, i == -1 ? "it's taken." : "couldn't assign file.");
      } else {
        /* now setup dcc entry */
        int idx = new_dcc(&DCC_TELNET, 0);
        dcc[idx].addr = 0L;
        strlcpy(dcc[idx].host, conf.localhub_socket, sizeof(dcc[idx].host));
        dcc[idx].port = 0;
        dcc[idx].sock = i;
        dcc[idx].timeval = now;
        strlcpy(dcc[idx].nick, "(unix_domain)", sizeof(dcc[idx].nick));
        putlog(LOG_DEBUG, "*", "Listening on telnet %s", conf.localhub_socket);
      }
    }
  }
}
Example #3
0
/* idx nick conmask cmd par */
static void bot_rsim(char *botnick, char *code, char *msg)
{
  int ridx = -1, idx = -1, i = 0, rconmask;
  unsigned long status = 0;
  char *nick = NULL, *cmd = NULL, *rconchan = NULL, buf[UHOSTMAX] = "", *par = NULL, *parp = NULL;
  struct userrec *u = get_user_by_handle(userlist, botnick);

  if (bot_hublevel(u) == 999) {
    putlog(LOG_WARN, "*", "BOTCMD received from a leaf. HIJACK.");
    return;
  }

  par = parp = strdup(msg);
  ridx = atoi(newsplit(&par));
  nick = newsplit(&par);
  rconmask = atoi(newsplit(&par));
  rconchan = newsplit(&par);
  if (egg_isdigit(par[0]))
    status = (unsigned long) atoi(newsplit(&par));
  cmd = newsplit(&par);
  if (ridx < 0 || !nick || !cmd) {
    free(parp);
    return;
  }

  for (i = 0; i < dcc_total; i++) {
   /* See if we can find a simul-idx for the same ridx/nick */
   if (dcc[i].type && dcc[i].simul == ridx && !strcasecmp(dcc[i].nick, nick)) {
     putlog(LOG_DEBUG, "*", "Simul found old idx for %s: %d (ridx: %d)", nick, i, ridx);
     dcc[i].simultime = now;
     idx = i;
     break;
   }
  }

  if (idx < 0) {
    idx = new_dcc(&DCC_CHAT, sizeof(struct chat_info));
    putlog(LOG_DEBUG, "*", "Making new idx for %s@%s: %d ridx: %d", nick, botnick, idx, ridx);
    dcc[idx].sock = -1;
    dcc[idx].timeval = now;
    dcc[idx].simultime = now;
    dcc[idx].simul = ridx;
    dcc[idx].status = status;
    strlcpy(dcc[idx].simulbot, botnick, sizeof(dcc[idx].simulbot));
    dcc[idx].u.chat->con_flags = rconmask;
    struct chat_info dummy;
    strlcpy(dcc[idx].u.chat->con_chan, rconchan, sizeof(dummy.con_chan));
    dcc[idx].u.chat->strip_flags = STRIP_ALL;
    strlcpy(dcc[idx].nick, nick, sizeof(dcc[idx].nick));
    simple_snprintf(buf, sizeof buf, "%s@%s", nick, botnick);
    strlcpy(dcc[idx].host, buf, sizeof(dcc[idx].host));
    dcc[idx].addr = 0L;
    dcc[idx].user = get_user_by_handle(userlist, nick);
  }
  rmspace(par);
  check_bind_dcc(cmd, idx, par);
  free(parp);
}
Example #4
0
static int get_dns_idx()
{
	int i, sock;
       
	sock = -1;
	for (i = 0; i < nservers; i++) {
		if (!dns_ip) dns_ip = dns_next_server();
		sock = socket_create(dns_ip, DNS_PORT, NULL, 0, SOCKET_CLIENT | SOCKET_NONBLOCK | SOCKET_UDP);
		if (sock < 0) {
			/* Try the next server. */
			dns_ip = NULL;
		}
		else break;
	}
	if (i == nservers) return 1;
//	dns_idx = sockbuf_new();
//	sockbuf_set_handler(dns_idx, &dns_handler, NULL);
//	sockbuf_set_sock(dns_idx, sock, 0);
//        allocsock(sock, SOCK_CONNECT);

        if (sock >= 0 && dns_ip) {
          dns_idx = new_dcc(&dns_handler, 0);

          if (dns_idx < 0) {
           putlog(LOG_SERV, "*", "NO MORE DCC CONNECTIONS -- Can't create dns connection.");
           killsock(sock);
           return 1;
          }
          sdprintf("dns_idx: %d", dns_idx);
          dcc[dns_idx].sock = sock;
          dns_sock = sock;
          sdprintf("dns_sock: %d", dcc[dns_idx].sock);
          strlcpy(dcc[dns_idx].host, dns_ip, UHOSTLEN);
          strlcpy(dcc[dns_idx].nick, "(adns)", NICKLEN);
          sdprintf("dns_ip: %s", dns_ip);
          dcc[dns_idx].timeval = now;
          dns_handler.timeout_val = 0;
          return 0;
        }
	return 1;
}
Example #5
0
int main(int arg_c, char **arg_v)
{
  int i, xx;
  char s[25];
  FILE *f;
  struct sigaction sv;
  struct chanset_t *chan;
#ifdef DEBUG
  struct rlimit cdlim;
#endif
#ifdef STOP_UAC
  int nvpair[2];
#endif

/* Make sure it can write core, if you make debug. Else it's pretty
 * useless (dw)
 *
 * Only allow unlimited size core files when compiled with DEBUG defined.
 * This is not a good idea for normal builds -- in these cases, use the
 * default system resource limits instead.
 */
#ifdef DEBUG
  cdlim.rlim_cur = RLIM_INFINITY;
  cdlim.rlim_max = RLIM_INFINITY;
  setrlimit(RLIMIT_CORE, &cdlim);
#endif

#ifdef DEBUG_CONTEXT
  /* Initialise context list */
  for (i = 0; i < 16; i++)
    Context;
#endif

/* Include patch.h header for patch("...") */
#include "patch.h"

  argc = arg_c;
  argv = arg_v;

  /* Version info! */
  egg_snprintf(ver, sizeof ver, "eggdrop v%s", egg_version);
  egg_snprintf(version, sizeof version,
               "Eggdrop v%s (C) 1997 Robey Pointer (C) 2010 Eggheads",
               egg_version);
  /* Now add on the patchlevel (for Tcl) */
  sprintf(&egg_version[strlen(egg_version)], " %u", egg_numver);
  strcat(egg_version, egg_xtra);

/* For OSF/1 */
#ifdef STOP_UAC
  /* Don't print "unaligned access fixup" warning to the user */
  nvpair[0] = SSIN_UACPROC;
  nvpair[1] = UAC_NOPRINT;
  setsysinfo(SSI_NVPAIRS, (char *) nvpair, 1, NULL, 0);
#endif

  /* Set up error traps: */
  sv.sa_handler = got_bus;
  sigemptyset(&sv.sa_mask);
#ifdef SA_RESETHAND
  sv.sa_flags = SA_RESETHAND;
#else
  sv.sa_flags = 0;
#endif
  sigaction(SIGBUS, &sv, NULL);
  sv.sa_handler = got_segv;
  sigaction(SIGSEGV, &sv, NULL);
#ifdef SA_RESETHAND
  sv.sa_flags = 0;
#endif
  sv.sa_handler = got_fpe;
  sigaction(SIGFPE, &sv, NULL);
  sv.sa_handler = got_term;
  sigaction(SIGTERM, &sv, NULL);
  sv.sa_handler = got_hup;
  sigaction(SIGHUP, &sv, NULL);
  sv.sa_handler = got_quit;
  sigaction(SIGQUIT, &sv, NULL);
  sv.sa_handler = SIG_IGN;
  sigaction(SIGPIPE, &sv, NULL);
  sv.sa_handler = got_ill;
  sigaction(SIGILL, &sv, NULL);
  sv.sa_handler = got_alarm;
  sigaction(SIGALRM, &sv, NULL);

  /* Initialize variables and stuff */
  now = time(NULL);
  chanset = NULL;
  egg_memcpy(&nowtm, localtime(&now), sizeof(struct tm));
  lastmin = nowtm.tm_min;
  srandom((unsigned int) (now % (getpid() + getppid())));
  init_mem();
  init_language(1);
  if (argc > 1)
    for (i = 1; i < argc; i++)
      do_arg(argv[i]);

  printf("\n%s\n", version);

#ifndef CYGWIN_HACKS
  /* Don't allow eggdrop to run as root
   * This check isn't useful under cygwin and has been
   * reported to cause trouble in some situations.
   */
  if (((int) getuid() == 0) || ((int) geteuid() == 0))
    fatal("ERROR: Eggdrop will not run as root!", 0);
#endif

#ifndef REPLACE_NOTIFIER
  init_threaddata(1);
#endif
  init_userent();
  init_misc();
  init_bots();
  init_modules();
  if (backgrd)
    bg_prepare_split();
  init_tcl(argc, argv);
  init_language(0);
#ifdef STATIC
  link_statics();
#endif
  strncpyz(s, ctime(&now), sizeof s);
  strcpy(&s[11], &s[20]);
  putlog(LOG_ALL, "*", "--- Loading %s (%s)", ver, s);
  chanprog();
  if (!encrypt_pass) {
    printf(MOD_NOCRYPT);
    bg_send_quit(BG_ABORT);
    exit(1);
  }
  i = 0;
  for (chan = chanset; chan; chan = chan->next)
    i++;
  putlog(LOG_MISC, "*", "=== %s: %d channels, %d users.",
         botnetnick, i, count_users(userlist));
#ifdef TLS
  ssl_init();
#endif
  cache_miss = 0;
  cache_hit = 0;
  if (!pid_file[0])
    egg_snprintf(pid_file, sizeof pid_file, "pid.%s", botnetnick);

  /* Check for pre-existing eggdrop! */
  f = fopen(pid_file, "r");
  if (f != NULL) {
    fgets(s, 10, f);
    xx = atoi(s);
    i = kill(xx, SIGCHLD);      /* Meaningless kill to determine if pid
                                 * is used */
    if (i == 0 || errno != ESRCH) {
      printf(EGG_RUNNING1, botnetnick);
      printf(EGG_RUNNING2, pid_file);
      bg_send_quit(BG_ABORT);
      exit(1);
    }
  }

  /* Move into background? */
  if (backgrd) {
    bg_do_split();
  } else {                        /* !backgrd */
    xx = getpid();
    if (xx != 0) {
      FILE *fp;

      /* Write pid to file */
      unlink(pid_file);
      fp = fopen(pid_file, "w");
      if (fp != NULL) {
        fprintf(fp, "%u\n", xx);
        if (fflush(fp)) {
          /* Let the bot live since this doesn't appear to be a botchk */
          printf(EGG_NOWRITE, pid_file);
          fclose(fp);
          unlink(pid_file);
        } else
          fclose(fp);
      } else
        printf(EGG_NOWRITE, pid_file);
    }
  }

  use_stderr = 0;               /* Stop writing to stderr now */
  if (backgrd) {
    /* Ok, try to disassociate from controlling terminal (finger cross) */
#ifdef HAVE_SETPGID
    setpgid(0, 0);
#endif
    /* Tcl wants the stdin, stdout and stderr file handles kept open. */
    freopen("/dev/null", "r", stdin);
    freopen("/dev/null", "w", stdout);
    freopen("/dev/null", "w", stderr);
#ifdef CYGWIN_HACKS
    FreeConsole();
#endif
  }

  /* Terminal emulating dcc chat */
  if (!backgrd && term_z) {
    int n = new_dcc(&DCC_CHAT, sizeof(struct chat_info));

    getvhost(&dcc[n].sockname, AF_INET);
    dcc[n].sock = STDOUT;
    dcc[n].timeval = now;
    dcc[n].u.chat->con_flags = conmask;
    dcc[n].u.chat->strip_flags = STRIP_ALL;
    dcc[n].status = STAT_ECHO;
    strcpy(dcc[n].nick, "HQ");
    strcpy(dcc[n].host, "llama@console");
    /* HACK: Workaround not to pass literal "HQ" as a non-const arg */
    dcc[n].user = get_user_by_handle(userlist, dcc[n].nick);
    /* Make sure there's an innocuous HQ user if needed */
    if (!dcc[n].user) {
      userlist = adduser(userlist, dcc[n].nick, "none", "-", USER_PARTY);
      dcc[n].user = get_user_by_handle(userlist, dcc[n].nick);
    }
    setsock(STDOUT, 0);          /* Entry in net table */
    dprintf(n, "\n### ENTERING DCC CHAT SIMULATION ###\n\n");
    dcc_chatter(n);
  }

  then = now;
  online_since = now;
  autolink_cycle(NULL);         /* Hurry and connect to tandem bots */
  add_help_reference("cmds1.help");
  add_help_reference("cmds2.help");
  add_help_reference("core.help");
  add_hook(HOOK_SECONDLY, (Function) core_secondly);
  add_hook(HOOK_MINUTELY, (Function) core_minutely);
  add_hook(HOOK_HOURLY, (Function) core_hourly);
  add_hook(HOOK_REHASH, (Function) event_rehash);
  add_hook(HOOK_PRE_REHASH, (Function) event_prerehash);
  add_hook(HOOK_USERFILE, (Function) event_save);
  add_hook(HOOK_BACKUP, (Function) backup_userfile);
  add_hook(HOOK_DAILY, (Function) event_logfile);
  add_hook(HOOK_DAILY, (Function) event_resettraffic);
  add_hook(HOOK_LOADED, (Function) event_loaded);

  call_hook(HOOK_LOADED);

  debug0("main: entering loop");
  while (1) {
    mainloop(1);
  }
}
Example #6
0
/* Hook up to a server
 */
static void connect_server(void)
{
  char pass[121], botserver[UHOSTLEN];
  int servidx;
  unsigned int botserverport = 0;

  lastpingcheck = 0;
  trying_server = now;
  empty_msgq();
  if (newserverport) {          /* Jump to specified server */
    curserv = -1;             /* Reset server list */
    strcpy(botserver, newserver);
    botserverport = newserverport;
    strcpy(pass, newserverpass);
    newserver[0] = 0;
    newserverport = 0;
    newserverpass[0] = 0;
  } else {
    if (curserv == -1)
      curserv = 999;
    pass[0] = 0;
  }
  if (!cycle_time) {
    struct chanset_t *chan;
    struct server_list *x = serverlist;

    if (!x && !botserverport) {
      putlog(LOG_SERV, "*", "No servers in server list");
      cycle_time = 300;
      return;
    }

    servidx = new_dcc(&DCC_DNSWAIT, sizeof(struct dns_info));
    if (servidx < 0) {
      putlog(LOG_SERV, "*",
             "NO MORE DCC CONNECTIONS -- Can't create server connection.");
      return;
    }

    if (connectserver[0])       /* drummer */
      do_tcl("connect-server", connectserver);
    check_tcl_event("connect-server");
    next_server(&curserv, botserver, &botserverport, pass);
#ifdef TLS
    putlog(LOG_SERV, "*", "%s [%s]:%s%d", IRC_SERVERTRY, botserver,
           use_ssl ? "+" : "", botserverport);
    dcc[servidx].ssl = use_ssl;
#else
    putlog(LOG_SERV, "*", "%s [%s]:%d", IRC_SERVERTRY, botserver,
           botserverport);
#endif
    dcc[servidx].port = botserverport;
    strcpy(dcc[servidx].nick, "(server)");
    strncpyz(dcc[servidx].host, botserver, UHOSTLEN);

    botuserhost[0] = 0;

    nick_juped = 0;
    for (chan = chanset; chan; chan = chan->next)
      chan->status &= ~CHAN_JUPED;

    dcc[servidx].timeval = now;
    dcc[servidx].sock = -1;
    dcc[servidx].u.dns->host = get_data_ptr(strlen(dcc[servidx].host) + 1);
    strcpy(dcc[servidx].u.dns->host, dcc[servidx].host);
    dcc[servidx].u.dns->cbuf = get_data_ptr(strlen(pass) + 1);
    strcpy(dcc[servidx].u.dns->cbuf, pass);
    dcc[servidx].u.dns->dns_success = server_resolve_success;
    dcc[servidx].u.dns->dns_failure = server_resolve_failure;
    dcc[servidx].u.dns->dns_type = RES_IPBYHOST;
    dcc[servidx].u.dns->type = &SERVER_SOCKET;

    if (server_cycle_wait)
      /* Back to 1st server & set wait time.
       * Note: Put it here, just in case the server quits on us quickly
       */
      cycle_time = server_cycle_wait;
    else
      cycle_time = 0;

    /* I'm resolving... don't start another server connect request */
    resolvserv = 1;
    /* Resolve the hostname. */
    dcc_dnsipbyhost(dcc[servidx].host);
  }
}
Example #7
0
/* this only handles CHAT requests, otherwise it's handled in filesys */
static int filesys_DCC_CHAT(char *nick, char *from, char *handle,
			    char *object, char *keyword, char *text)
{
  char *param, *ip, *prt, buf[512], *msg = buf;
  int i, sock;
  struct userrec *u = get_user_by_handle(userlist, handle);
  struct flag_record fr =
  {FR_GLOBAL | FR_CHAN | FR_ANYWH, 0, 0, 0, 0, 0};

  Context;
  if (!strncasecmp(text, "SEND ", 5)) {
    filesys_dcc_send(nick, from, u, text + 5);
    return 1;
  }
  if (strncasecmp(text, "CHAT ", 5) || !u)
    return 0;
  strcpy(buf, text + 5);
  get_user_flagrec(u, &fr, 0);
  param = newsplit(&msg);
  if (dcc_total == max_dcc) {
    putlog(LOG_MISC, "*", DCC_TOOMANYDCCS2, "CHAT(file)", param, nick, from);
  } else if (glob_party(fr) || (!require_p && chan_op(fr)))
    return 0;			/* allow ctcp.so to pick up the chat */
  else if (!glob_xfer(fr)) {
    if (!quiet_reject)
      dprintf(DP_HELP, "NOTICE %s :.\n", nick, DCC_REFUSED3);
    putlog(LOG_MISC, "*", "%s: %s!%s", DCC_REFUSED, nick, from);
  } else if (u_pass_match(u, "-")) {
    if (!quiet_reject)
      dprintf(DP_HELP, "NOTICE %s :%s.\n", nick, DCC_REFUSED3);
    putlog(LOG_MISC, "*", "%s: %s!%s", DCC_REFUSED4, nick, from);
  } else if (!dccdir[0]) {
    putlog(LOG_MISC, "*", "%s: %s!%s", DCC_REFUSED5, nick, from);
  } else {
    ip = newsplit(&msg);
    prt = newsplit(&msg);
    sock = getsock(0);
    if (open_telnet_dcc(sock, ip, prt) < 0) {
      neterror(buf);
      if (!quiet_reject)
        dprintf(DP_HELP, "NOTICE %s :%s (%s)\n", nick,
	        DCC_CONNECTFAILED1, buf);
      putlog(LOG_MISC, "*", "%s: CHAT(file) (%s!%s)", DCC_CONNECTFAILED2,
	     nick, from);
      putlog(LOG_MISC, "*", "    (%s)", buf);
      killsock(sock);
    } else if ((atoi(prt) < min_dcc_port) || (atoi(prt) > max_dcc_port)) {
      /* invalid port range, do clients even use over 5000?? */
      if (!quiet_reject)
        dprintf(DP_HELP, "NOTICE %s :%s (invalid port)\n", nick,
	        DCC_CONNECTFAILED1);
      putlog(LOG_FILES, "*", "%s: %s!%s", DCC_REFUSED7, nick, from);

    } else {
      i = new_dcc(&DCC_FILES_PASS, sizeof(struct file_info));

      dcc[i].addr = my_atoul(ip);
      dcc[i].port = atoi(prt);
      dcc[i].sock = sock;
      strcpy(dcc[i].nick, u->handle);
      strcpy(dcc[i].host, from);
      dcc[i].status = STAT_ECHO;
      dcc[i].timeval = now;
      dcc[i].u.file->chat = get_data_ptr(sizeof(struct chat_info));
      bzero(dcc[i].u.file->chat, sizeof(struct chat_info));

      strcpy(dcc[i].u.file->chat->con_chan, "*");
      dcc[i].user = u;
      putlog(LOG_MISC, "*", "DCC connection: CHAT(file) (%s!%s)", nick, from);
      dprintf(i, "%s\n", DCC_ENTERPASS);
    }
  }
  return 1;
}
Example #8
0
/* received a ctcp-dcc */
static void filesys_dcc_send(char *nick, char *from, struct userrec *u,
			     char *text)
{
  char *param, *ip, *prt, buf[512], s1[512], *msg = buf;
  FILE *f;
  int atr = u ? u->flags : 0, i, j;

  Context;
  strcpy(buf, text);
  param = newsplit(&msg);
  if (!(atr & USER_XFER)) {
    putlog(LOG_FILES, "*",
	   "Refused DCC SEND %s (no access): %s!%s", param,
	   nick, from);
  } else if (!dccin[0] && !upload_to_cd) {
    dprintf(DP_HELP,
	    "NOTICE %s :DCC file transfers not supported.\n", nick);
    putlog(LOG_FILES, "*",
	   "Refused dcc send %s from %s!%s", param, nick, from);
  } else if (strchr(param, '/')) {
    dprintf(DP_HELP,
	    "NOTICE %s :Filename cannot have '/' in it...\n", nick);
    putlog(LOG_FILES, "*",
	   "Refused dcc send %s from %s!%s", param, nick, from);
  } else {
    ip = newsplit(&msg);
    prt = newsplit(&msg);
    if ((atoi(prt) < min_dcc_port) || (atoi(prt) > max_dcc_port)) {
      /* invalid port range, do clients even use over 5000?? */
      dprintf(DP_HELP, "NOTICE %s :%s (invalid port)\n", nick,
	      DCC_CONNECTFAILED1);
      putlog(LOG_FILES, "*", "Refused dcc send %s (%s): invalid port", param,
	     nick);
    } else if (atoi(msg) == 0) {
      dprintf(DP_HELP,
	      "NOTICE %s :Sorry, file size info must be included.\n",
	      nick);
      putlog(LOG_FILES, "*", "Refused dcc send %s (%s): no file size",
	     param, nick);
    } else if (atoi(msg) > (dcc_maxsize * 1024)) {
      dprintf(DP_HELP, "NOTICE %s :Sorry, file too large.\n", nick);
      putlog(LOG_FILES, "*",
	     "Refused dcc send %s (%s): file too large", param,
	     nick);
    } else {
      /* This looks like a good place for a sanity check. */
      if (!sanitycheck_dcc(nick, from, ip, prt))
	return;
      i = new_dcc(&DCC_FORK_SEND, sizeof(struct xfer_info));

      if (i < 0) {
	dprintf(DP_HELP, "NOTICE %s :Sorry, too many DCC connections.\n",
		nick);
	putlog(LOG_MISC, "*", "DCC connections full: SEND %s (%s!%s)",
	       param, nick, from);
      }
      dcc[i].addr = my_atoul(ip);
      dcc[i].port = atoi(prt);
      dcc[i].sock = -1;
      strcpy(dcc[i].nick, nick);
      strcpy(dcc[i].host, from);
      if (param[0] == '.')
	param[0] = '_';
      strncpy(dcc[i].u.xfer->filename, param, 120);
      dcc[i].u.xfer->filename[120] = 0;
      if (upload_to_cd) {
	char *p = get_user(&USERENTRY_DCCDIR, u);

	if (p)
	  sprintf(dcc[i].u.xfer->dir, "%s%s/", dccdir, p);
	else
	  sprintf(dcc[i].u.xfer->dir, "%s", dccdir);
      } else
	strcpy(dcc[i].u.xfer->dir, dccin);
      dcc[i].u.xfer->length = atoi(msg);
      sprintf(s1, "%s%s", dcc[i].u.xfer->dir, param);
      Context;
      f = fopen(s1, "r");
      if (f) {
	fclose(f);
	dprintf(DP_HELP, "NOTICE %s :That file already exists.\n", nick);
	lostdcc(i);
      } else {
	/* check for dcc-sends in process with the same filename */
	for (j = 0; j < dcc_total; j++)
	  if (j != i) {
	    if ((dcc[j].type->flags & (DCT_FILETRAN | DCT_FILESEND))
		== (DCT_FILETRAN | DCT_FILESEND)) {
	      if (!strcmp(param, dcc[j].u.xfer->filename)) {
		dprintf(DP_HELP,
		  "NOTICE %s :That file is already being sent.\n", nick);
		lostdcc(i);
		return;
	      }
	    }
	  }
	/* put uploads in /tmp first */
	sprintf(s1, "%s%s", tempdir, param);
	dcc[i].u.xfer->f = fopen(s1, "w");
	if (dcc[i].u.xfer->f == NULL) {
	  dprintf(DP_HELP,
		  "NOTICE %s :Can't create that file (temp dir error)\n",
		  nick);
	  lostdcc(i);
	} else {
	  dcc[i].timeval = now;
	  dcc[i].sock = getsock(SOCK_BINARY);
	  if (open_telnet_dcc(dcc[i].sock, ip, prt) < 0) {
	    dcc[i].type->eof(i);
	  }
	}
      }
    }
  }
}
Example #9
0
int main(int argc, char **argv)
{
  int xx, i;
#ifdef STOP_UAC
  int nvpair[2];
#endif
  char buf[520], s[25];
  FILE *f;
#ifndef ENABLE_STRIP
  struct rlimit cdlim;
#endif

  /* Don't allow Eggdrop to run as root. */
  if (((int) getuid() == 0) || ((int) geteuid() == 0))
    fatal("ERROR: Eggdrop will not run as root!", 0);

#ifndef ENABLE_STRIP
  cdlim.rlim_cur = RLIM_INFINITY;
  cdlim.rlim_max = RLIM_INFINITY;
  setrlimit(RLIMIT_CORE, &cdlim);
#endif

#include "patch.h"
  /* Version info! */
  egg_snprintf(ver, sizeof ver, "eggdrop v%s", egg_version);
  egg_snprintf(version, sizeof version,
               "Eggdrop v%s (C) 1997 Robey Pointer (C) 2005 Eggheads",
               egg_version);
  /* Now add on the patchlevel (for Tcl) */
  sprintf(&egg_version[strlen(egg_version)], " %u", egg_numver);
  strcat(egg_version, egg_xtra);

#ifdef STOP_UAC
  nvpair[0] = SSIN_UACPROC;
  nvpair[1] = UAC_NOPRINT;
  setsysinfo(SSI_NVPAIRS, (char *) nvpair, 1, NULL, 0);
#endif

  /* Set up error / signal traps. */
  setup_signal_traps();

  /* Initialize a few variables before main loop. */
  cache_miss = 0;
  cache_hit  = 0;
  chanset    = NULL;
  now        = time(NULL);

  egg_memcpy(&nowtm, localtime(&now), sizeof(struct tm));
  lastmin = nowtm.tm_min;

  /* Initialize random number generator. */
  srandom((unsigned int) (now % (getpid() + getppid())));

  init_mem();
  init_language(1);

  /* Process command line arguments. */
  process_args(argc, argv);

  printf("\n%s\n", version);

  init_dcc_max();
  init_userent();
  logfile_init(0);
  init_bots();
  init_net();
  init_modules();

  if (backgrd)
    bg_prepare_split();

  init_tcl(argc, argv);
  init_language(0);
  help_init();
  traffic_init();
  logfile_init(1);

#ifdef STATIC
  link_statics();
#endif

  strncpyz(s, ctime(&now), sizeof s);
  strcpy(&s[11], &s[20]);
  putlog(LOG_ALL, "*", "--- Loading %s (%s)", ver, s);

  /* Read configuration data. */
  readconfig();

  /* Check for encryption module. */
  if (!encrypt_pass) {
    printf(MOD_NOCRYPT);
    bg_send_quit(BG_ABORT);
    exit(1);
  }

  putlog(LOG_MISC, "*", "=== %s: %d channels, %d users.", botnetnick,
         count_channels(), count_users(userlist));

  if (!pid_file[0])
    egg_snprintf(pid_file, sizeof pid_file, "pid.%s", botnetnick);

  /* Check for pre-existing eggdrop! */
  f = fopen(pid_file, "r");
  if (f != NULL) {
    fgets(s, 10, f);
    xx = atoi(s);
    kill(xx, SIGCHLD); /* Meaningless kill to determine if PID is used. */
    if (errno != ESRCH) {
      printf(EGG_RUNNING1, botnetnick);
      printf(EGG_RUNNING2, pid_file);
      bg_send_quit(BG_ABORT);
      exit(1);
    }
  }

  /* Move into background? */
  if (backgrd) {
#ifndef CYGWIN_HACKS
    bg_do_split();
  }
  else {
#endif
    xx = getpid();
    if (xx != 0) {
      FILE *fp;

      /* Write PID to file. */
      unlink(pid_file);
      fp = fopen(pid_file, "w");
      if (fp != NULL) {
        fprintf(fp, "%u\n", xx);
        if (fflush(fp)) {
          /* Let the bot live since this doesn't appear to be a botchk. */
          printf("Cannot not write to '%s' (PID file).\n", pid_file);
          fclose(fp);
          unlink(pid_file);
        }
        else
          fclose(fp);
      }
      else
        printf("Cannot not write to '%s' (PID file).\n", pid_file);
#ifdef CYGWIN_HACKS
      printf("Launched into the background (PID: %d)\n\n", xx);
#endif
    }
  }

  use_stderr = 0;               /* Stop writing to stderr now */
  if (backgrd) {
    /* Ok, try to disassociate from controlling terminal (finger cross) */
#if defined(HAVE_SETPGID) && !defined(CYGWIN_HACKS)
    setpgid(0, 0);
#endif

    /* Tcl wants the stdin, stdout and stderr file handles kept open. */
    freopen("/dev/null", "r", stdin);
    freopen("/dev/null", "w", stdout);
    freopen("/dev/null", "w", stderr);

#ifdef CYGWIN_HACKS
    FreeConsole();
#endif
  }

  /* Terminal emulating dcc chat */
  if (!backgrd && term_z) {
    int n = new_dcc(&DCC_CHAT, sizeof(struct chat_info));

    dcc[n].addr = iptolong(getmyip());
    dcc[n].sock = STDOUT;
    dcc[n].timeval = now;
    dcc[n].u.chat->con_flags = conmask;
    dcc[n].u.chat->strip_flags = STRIP_ALL;
    dcc[n].status = STAT_ECHO;
    strcpy(dcc[n].nick, "HQ");
    strcpy(dcc[n].host, "llama@console");
    /* HACK: Workaround not to pass literal "HQ" as a non-const arg */
    dcc[n].user = get_user_by_handle(userlist, dcc[n].nick);
    /* Make sure there's an innocuous HQ user if needed */
    if (!dcc[n].user) {
      userlist = adduser(userlist, dcc[n].nick, "none", "-", USER_PARTY);
      dcc[n].user = get_user_by_handle(userlist, dcc[n].nick);
    }
    setsock(STDOUT, 0); /* Entry in net table */
    dprintf(n, "\n### ENTERING DCC CHAT SIMULATION ###\n\n");
    dcc_chatter(n);
  }

  then = now;
  online_since = now;
  autolink_cycle(NULL); /* Hurry and connect to tandem bots. */
  add_help_reference("cmds1.help");
  add_help_reference("cmds2.help");
  add_help_reference("core.help");

  /* Create hooks. */
  add_hook(HOOK_SECONDLY, (Function) core_secondly);
  add_hook(HOOK_MINUTELY, (Function) core_minutely);
  add_hook(HOOK_HOURLY, (Function) core_hourly);
  add_hook(HOOK_REHASH, (Function) event_rehash);
  add_hook(HOOK_PRE_REHASH, (Function) event_prerehash);
  add_hook(HOOK_USERFILE, (Function) event_save);
  add_hook(HOOK_BACKUP, (Function) backupuserfile);
  add_hook(HOOK_DAILY, (Function) event_logfile);
  add_hook(HOOK_DAILY, (Function) traffic_reset);
  add_hook(HOOK_LOADED, (Function) event_loaded);

  call_hook(HOOK_LOADED);

  debug0("main: entering loop");
  while (1) {
    int socket_cleanup = 0;

#ifdef USE_TCL_EVENTS
    /* Process a single Tcl event. */
    Tcl_DoOneEvent(TCL_ALL_EVENTS | TCL_DONT_WAIT);
#endif

    now = time(NULL);
    random();

    /* Every second... */
    if (now != then) {
      call_hook(HOOK_SECONDLY);
      then = now;
    }

    /* Only do this every so often. */
    if (!socket_cleanup) {
      socket_cleanup = 5;

      /* Remove dead dcc entries. */
      dcc_remove_lost();

      /* Check for server or dcc activity. */
      dequeue_sockets();
    }
    else {
      socket_cleanup--;
    }

    /* Free unused structures. */
    garbage_collect();

    xx = sockgets(buf, &i);
    if (xx >= 0) { /* Non-error */
      int idx;

      for (idx = 0; idx < dcc_total; idx++) {
        if (dcc[idx].sock != xx)
          continue;

        if (dcc[idx].type && dcc[idx].type->activity) {
          traffic_update_in(dcc[idx].type, (strlen(buf) + 1)); /* Traffic stats. */
          dcc[idx].type->activity(idx, buf, i);
        }
        else {
          putlog(LOG_MISC, "*", "!!! untrapped dcc activity: type %s, sock %d",
                 dcc[idx].type->name, dcc[idx].sock);
        }

        break;
      }
    }
    else if (xx == -1) { /* EOF */
      int idx;

      if (i == STDOUT && !backgrd)
        fatal("END OF FILE ON TERMINAL", 0);

      for (idx = 0; idx < dcc_total; idx++) {
        if (dcc[idx].sock != i)
          continue;

        if (dcc[idx].type && dcc[idx].type->eof) {
          dcc[idx].type->eof(idx);
        }
        else {
          putlog(LOG_MISC, "*",
                 "*** ATTENTION: DEAD SOCKET (%d) OF TYPE %s UNTRAPPED",
                 i, dcc[idx].type ? dcc[idx].type->name : "*UNKNOWN*");
          killsock(i);
          lostdcc(idx);
        }

        idx = dcc_total + 1;
      }

      if (idx == dcc_total) {
        putlog(LOG_MISC, "*",
               "(@) EOF socket %d, not a dcc socket, not anything.", i);
        close(i);
        killsock(i);
      }
    }
    else if (xx == -2 && errno != EINTR) { /* select() error */
      putlog(LOG_MISC, "*", "* Socket error #%d; recovering.", errno);
      for (i = 0; i < dcc_total; i++) {
        if ((fcntl(dcc[i].sock, F_GETFD, 0) == -1) && (errno == EBADF)) {
          putlog(LOG_MISC, "*",
                 "DCC socket %d (type %d, name '%s') expired -- pfft",
                 dcc[i].sock, dcc[i].type, dcc[i].nick);
          killsock(dcc[i].sock);
          lostdcc(i);
          i--;
        }
      }
    }
    else if (xx == -3) {
      call_hook(HOOK_IDLE);
      socket_cleanup = 0;       /* If we've been idle, cleanup & flush */
    }

    if (do_restart) {
      if (do_restart == -2) {
        rehash();
      }
      else {
        int f = 1;
        module_entry *p;
        Function startfunc;
        char name[256];


        check_tcl_event("prerestart");

        /* Unload as many modules as possible */
        while (f) {
          f = 0;

          for (p = module_list; p != NULL; p = p->next) {
            dependancy *d = dependancy_list;
            int ok = 1;

            while (ok && d) {
              if (d->needed == p)
                ok = 0;

              d = d->next;
            }
            if (ok) {
              strcpy(name, p->name);

              if (module_unload(name, botnetnick) == NULL) {
                f = 1;
                break;
              }
            }
          }
        }

        /* Make sure we don't have any modules left hanging around other than
         * "eggdrop" and the two that are supposed to be.
         */
        for (f = 0, p = module_list; p; p = p->next) {
          if (strcmp(p->name, "eggdrop") && strcmp(p->name, "encryption") &&
              strcmp(p->name, "uptime")) {
            f++;
          }
        }
        if (f != 0) {
          putlog(LOG_MISC, "*", MOD_STAGNANT);
        }

        /* Flush log files to disk. */
        flushlogs();

        /* Clean up Tcl stuff. */
        kill_tcl();

        /* Initialize stuff again. */
        init_tcl(argc, argv);
        init_language(0);
        help_init();
        traffic_init();
        logfile_init(1);

        /* This resets our modules which we didn't unload (encryption and uptime). */
        for (p = module_list; p; p = p->next) {
          if (p->funcs) {
            startfunc = p->funcs[MODCALL_START];
            startfunc(NULL);
          }
        }

        rehash();
        restart_chons();
        call_hook(HOOK_LOADED);
      }

      do_restart = 0;
    }
  }
}
Example #10
0
/* Received a ctcp-dcc.
 */
static void filesys_dcc_send(char *nick, char *from, struct userrec *u,
                             char *text)
{
  char *param, *ip, *prt, *buf = NULL, *msg;
  int atr = u ? u->flags : 0, i, j = 0;

  if (text[j] == '"') {
    text[j] = ' ';

    for (j = 1; text[j] != '"' && text[j] != '\0'; j++) {
      if (text[j] == ' ')
      {
        text[j] = '_';
      }
    }

    text[j] = ' ';
  }

  buf = nmalloc(strlen(text) + 1);
  msg = buf;
  strcpy(buf, text);
  param = newsplit(&msg);
  if (!(atr & USER_XFER)) {
    putlog(LOG_FILES, "*", "Refused DCC SEND %s (no access): %s!%s", param,
           nick, from);
    if (!quiet_reject)
      dprintf(DP_HELP, "NOTICE %s :No access\n", nick);
  } else if (!dccin[0] && !upload_to_cd) {
    dprintf(DP_HELP, "NOTICE %s :DCC file transfers not supported.\n", nick);
    putlog(LOG_FILES, "*", "Refused dcc send %s from %s!%s", param, nick, from);
  } else if (strchr(param, '/')) {
    dprintf(DP_HELP, "NOTICE %s :Filename cannot have '/' in it...\n", nick);
    putlog(LOG_FILES, "*", "Refused dcc send %s from %s!%s", param, nick, from);
  } else {
    ip = newsplit(&msg);
    prt = newsplit(&msg);
    if (atoi(prt) < 1024 || atoi(prt) > 65535) {
      /* Invalid port */
      dprintf(DP_HELP, "NOTICE %s :%s (invalid port)\n", nick,
              DCC_CONNECTFAILED1);
      putlog(LOG_FILES, "*", "Refused dcc send %s (%s): invalid port", param,
             nick);
    } else if (atoi(msg) == 0) {
      dprintf(DP_HELP, "NOTICE %s :Sorry, file size info must be included.\n",
              nick);
      putlog(LOG_FILES, "*", "Refused dcc send %s (%s): no file size",
             param, nick);
    } else if (dcc_maxsize && (atoi(msg) > (dcc_maxsize * 1024))) {
      dprintf(DP_HELP, "NOTICE %s :Sorry, file too large.\n", nick);
      putlog(LOG_FILES, "*", "Refused dcc send %s (%s): file too large", param,
             nick);
    } else {
      /* This looks like a good place for a sanity check. */
      if (!sanitycheck_dcc(nick, from, ip, prt)) {
        my_free(buf);
        return;
      }
      i = new_dcc(&DCC_DNSWAIT, sizeof(struct dns_info));
      if (i < 0) {
        dprintf(DP_HELP, "NOTICE %s :Sorry, too many DCC connections.\n", nick);
        putlog(LOG_MISC, "*", "DCC connections full: SEND %s (%s!%s)", param,
               nick, from);
        return;
      }
      dcc[i].addr = my_atoul(ip);
      dcc[i].port = atoi(prt);
      dcc[i].sock = -1;
      dcc[i].user = u;
      strcpy(dcc[i].nick, nick);
      strcpy(dcc[i].host, from);
      dcc[i].u.dns->cbuf = get_data_ptr(strlen(param) + 1);
      strcpy(dcc[i].u.dns->cbuf, param);
      dcc[i].u.dns->ibuf = atoi(msg);
      dcc[i].u.dns->ip = dcc[i].addr;
      dcc[i].u.dns->dns_type = RES_HOSTBYIP;
      dcc[i].u.dns->dns_success = filesys_dcc_send_hostresolved;
      dcc[i].u.dns->dns_failure = filesys_dcc_send_hostresolved;
      dcc[i].u.dns->type = &DCC_FORK_SEND;
      dcc_dnshostbyip(dcc[i].addr);
    }
  }
  my_free(buf);
}
Example #11
0
/* link to another bot */
int botlink(char *linker, int idx, char *nick)
{
  struct bot_addr *bi;
  struct userrec *u;
  register int i;

  Context;
  u = get_user_by_handle(userlist, nick);
  if (!u || !(u->flags & USER_BOT)) {
    if (idx >= 0)
      dprintf(idx, "%s %s\n", nick, BOT_BOTUNKNOWN);
  } else if (!strcasecmp(nick, botnetnick)) {
    if (idx >= 0)
      dprintf(idx, "%s\n", BOT_CANTLINKMYSELF);
  } else if (in_chain(nick) && (idx != -3)) {
    if (idx >= 0)
      dprintf(idx, "%s\n", BOT_ALREADYLINKED);
  } else {
    for (i = 0; i < dcc_total; i++)
      if ((dcc[i].user == u) &&
	  ((dcc[i].type == &DCC_FORK_BOT) ||
	   (dcc[i].type == &DCC_BOT_NEW))) {
	if (idx >= 0)
	  dprintf(idx, "%s\n", BOT_ALREADYLINKING);
	return 0;
      }
    /* address to connect to is in 'info' */
    bi = (struct bot_addr *) get_user(&USERENTRY_BOTADDR, u);
    if (!bi || !strlen(bi->address) || !bi->telnet_port) {
      if (idx >= 0) {
	dprintf(idx, "%s '%s'.\n", BOT_NOTELNETADDY, nick);
	dprintf(idx, "%s .chaddr %s %s\n",
		MISC_USEFORMAT, nick, MISC_CHADDRFORMAT);
      }
    } else if (dcc_total == max_dcc) {
      if (idx >= 0)
	dprintf(idx, "%s\n", DCC_TOOMANYDCCS1);
    } else {
      Context;
      correct_handle(nick);
      i = new_dcc(&DCC_FORK_BOT, sizeof(struct bot_info));

      dcc[i].port = bi->telnet_port;
      strcpy(dcc[i].nick, nick);
      strcpy(dcc[i].host, bi->address);
      dcc[i].timeval = now;
      strcpy(dcc[i].u.bot->linker, linker);
      strcpy(dcc[i].u.bot->version, "(primitive bot)");
      if (idx > -2)
	putlog(LOG_BOTS, "*", "%s %s at %s:%d ...", BOT_LINKING, nick,
	       bi->address, bi->telnet_port);
      dcc[i].u.bot->numver = idx;
      dcc[i].timeval = now;
      dcc[i].u.bot->port = dcc[i].port;		/* remember where i started */
      dcc[i].sock = getsock(SOCK_STRONGCONN);
      dcc[i].user = u;
      if (open_telnet_raw(dcc[i].sock, bi->address, dcc[i].port) < 0)
	failed_link(i);
      return 1;
    }
  }
  return 0;
}
Example #12
0
/* relay to another tandembot */
void tandem_relay(int idx, char *nick, register int i)
{
  struct chat_info *ci;
  struct userrec *u;
  struct bot_addr *bi;

  Context;
  u = get_user_by_handle(userlist, nick);
  if (!u || !(u->flags & USER_BOT)) {
    dprintf(idx, "%s %s\n", nick, BOT_BOTUNKNOWN);
    return;
  }
  if (!strcasecmp(nick, botnetnick)) {
    dprintf(idx, "%s\n", BOT_CANTRELAYMYSELF);
    return;
  }
  /* address to connect to is in 'info' */
  bi = (struct bot_addr *) get_user(&USERENTRY_BOTADDR, u);
  if (!bi) {
    dprintf(idx, "%s '%s'.\n", BOT_NOTELNETADDY, nick);
    dprintf(idx, "%s .chaddr %s %s\n",
	    MISC_USEFORMAT, nick, MISC_CHADDRFORMAT);

    return;
  }
  if (dcc_total == max_dcc) {
    dprintf(idx, "%s\n", DCC_TOOMANYDCCS1);
    return;
  }
  i = new_dcc(&DCC_FORK_RELAY, sizeof(struct relay_info));
  dcc[i].u.relay->chat = get_data_ptr(sizeof(struct chat_info));

  dcc[i].port = bi->relay_port;
  dcc[i].u.relay->port = dcc[i].port;
  dcc[i].addr = 0L;
  strcpy(dcc[i].nick, nick);
  dcc[i].user = u;
  strcpy(dcc[i].host, bi->address);
  dcc[i].u.relay->chat->away = NULL;
  dcc[i].status = 0;
  dcc[i].timeval = now;
  dcc[i].u.relay->chat->msgs_per_sec = 0;
  dcc[i].u.relay->chat->con_flags = 0;
  dcc[i].u.relay->chat->buffer = NULL;
  dcc[i].u.relay->chat->max_line = 0;
  dcc[i].u.relay->chat->line_count = 0;
  dcc[i].u.relay->chat->current_lines = 0;
  dprintf(idx, "%s %s @ %s:%d ...\n", BOT_CONNECTINGTO, nick,
	  bi->address, bi->relay_port);
  dprintf(idx, "%s\n", BOT_BYEINFO1);
  ci = dcc[idx].u.chat;
  dcc[idx].u.relay = get_data_ptr(sizeof(struct relay_info));

  dcc[idx].u.relay->chat = ci;
  dcc[idx].type = &DCC_PRE_RELAY;
  dcc[idx].u.relay->old_status = dcc[idx].status;
  dcc[i].sock = getsock(SOCK_STRONGCONN);
  dcc[idx].u.relay->sock = dcc[i].sock;
  dcc[i].u.relay->sock = dcc[idx].sock;
  dcc[i].timeval = now;
  if (open_telnet_raw(dcc[i].sock, dcc[i].host, dcc[i].port) < 0)
    failed_tandem_relay(i);
}