Ejemplo n.º 1
0
static int checkscript(void)
{
	char *prog[2];
	struct stat s;
	int pid, w;

	if (stat("check", &s) == -1) {
		if (errno == ENOENT) return 1;
		bb_perror_msg(WARN"cannot stat %s/check", *service);
		return 0;
	}
	/* if (!(s.st_mode & S_IXUSR)) return 1; */
	if ((pid = fork()) == -1) {
		bb_perror_msg(WARN"cannot fork for %s/check", *service);
		return 0;
	}
	if (!pid) {
		prog[0] = "./check";
		prog[1] = 0;
		close(1);
		execve("check", prog, environ);
		bb_perror_msg(WARN"cannot run %s/check", *service);
		_exit(0);
	}
	while (wait_pid(&w, pid) == -1) {
		if (errno == EINTR) continue;
		bb_perror_msg(WARN"cannot wait for child %s/check", *service);
		return 0;
	}
	return !wait_exitcode(w);
}
Ejemplo n.º 2
0
int checkscript() {
  char *prog[2];
  struct stat s;
  int pid, w;

  if (stat("check", &s) == -1) {
    if (errno == error_noent) return(1);
    outs2(WARN); outs2("unable to stat "); outs2(*service); outs2("/check: ");
    outs2(error_str(errno)); flush2("\n");
    return(0);
  }
  /* if (!(s.st_mode & S_IXUSR)) return(1); */
  if ((pid =fork()) == -1) {
    outs2(WARN); outs2("unable to fork for "); outs2(*service);
    outs2("/check: "); outs2(error_str(errno)); flush2("\n");
    return(0);
  }
  if (!pid) {
    prog[0] ="./check";
    prog[1] =0;
    close(1);
    execve("check", prog, environ);
    outs2(WARN); outs2("unable to run "); outs2(*service); outs2("/check: ");
    outs2(error_str(errno)); flush2("\n");
    _exit(0);
  }
  while (wait_pid(&w, pid) == -1) {
    if (errno == error_intr) continue;
    outs2(WARN); outs2("unable to wait for child "); outs2(*service);
    outs2("/check: "); outs2(error_str(errno)); flush2("\n");
    return(0);
  }
  return(!wait_exitcode(w));
}
Ejemplo n.º 3
0
void doanddie(char *user, unsigned int userlen /* including 0 byte */,
    char *pass)
{
  int child;
  int wstat;
  int pi[2];
 
  close(3);
  if (pipe(pi) == -1) die_pipe();
  if (pi[0] != 3) die_pipe();
  switch(child = fork()) {
    case -1:
      die_fork();
    case 0:
      close(pi[1]);
      sig_pipedefault();
      execvp(*childargs,childargs);
      _exit(1);
  }
  close(pi[0]);
  substdio_fdbuf(&ssup,subwrite,pi[1],upbuf,sizeof upbuf);
  if (substdio_put(&ssup,user,userlen) == -1) die_write();
  if (substdio_put(&ssup,pass,str_len(pass) + 1) == -1) die_write();
  if (substdio_puts(&ssup,"<") == -1) die_write();
  if (substdio_puts(&ssup,unique) == -1) die_write();
  if (substdio_puts(&ssup,hostname) == -1) die_write();
  if (substdio_put(&ssup,">",2) == -1) die_write();
  if (substdio_flush(&ssup) == -1) die_write();
  close(pi[1]);
  byte_zero(pass,str_len(pass));
  byte_zero(upbuf,sizeof upbuf);
  if (wait_pid(&wstat,child) == -1) die();
  if (wait_crashed(wstat)) die_childcrashed();
  switch (wait_exitcode(wstat)) {
    case 0: die();
    case 1: die_1();
    case 2: die_2();
    case 25: die_25();
    case 3: die_3();
    case 4: die_4();
    case 5: die_5();
    case 6: die_6();
    case 61: die_61();
    case 62: die_62();
    case 7: die_7();
    case 8: die_nomem();
    default: die_unknown();
  }
  die();
}
Ejemplo n.º 4
0
void
pbsexec(void)
{
	char *(args[3]);
	int child, wstat;

	if (pbstool == 0 || *pbstool == 0) return;

	if (env_get("NOPBS")) return;

	switch (child = fork()) {
	case -1:
		return;
	case 0:
		/* the pbstool may not read or write to the connection */
		close(0); open_read("/dev/null");
		close(1); open_write("/dev/null");
		close(3);
		
		args[0] = pbstool;
		args[1] = 0;
		execvp(*args, args);
		_exit(111);
	}

	wait_pid(&wstat,child);
	if (wait_crashed(wstat))
		logit(2, "pbsexec: %s crashed\n", pbstool);
	else if (wait_exitcode(wstat))
		logit(2, "pbsexec: %s failed, exit code %d\n",
		    pbstool, wait_exitcode(wstat));
	else
		logit(64, "pbsexec: %s OK\n", pbstool);

	return;
}
Ejemplo n.º 5
0
void sig_child_handler() {
  int wstat;
  int i;

  while ((i =wait_nohang(&wstat)) > 0) {
    if (phccmax) ipsvd_phcc_rem(i);
    if (cnum) cnum--;
    if (verbose) {
      bufnum[fmt_ulong(bufnum, i)] =0;
      out(INFO); out("end "); out(bufnum); out(" exit ");
      bufnum[fmt_ulong(bufnum, (unsigned long)wait_exitcode(wstat))] =0;
      out(bufnum); flush("\n");
    }
  }
  if (verbose) connection_status();
}
Ejemplo n.º 6
0
static unsigned custom(struct svdir *s, char c)
{
	int pid;
	int w;
	char a[10];
	struct stat st;
	char *prog[2];

	if (s->islog) return 0;
	strcpy(a, "control/?");
	a[8] = c; /* replace '?' */
	if (stat(a, &st) == 0) {
		if (st.st_mode & S_IXUSR) {
			pid = vfork();
			if (pid == -1) {
				warn_cannot("vfork for control/?");
				return 0;
			}
			if (!pid) {
				/* child */
				if (haslog && dup2(logpipe.wr, 1) == -1)
					warn_cannot("setup stdout for control/?");
				prog[0] = a;
				prog[1] = NULL;
				execv(a, prog);
				fatal_cannot("run control/?");
			}
			/* parent */
			while (safe_waitpid(pid, &w, 0) == -1) {
				warn_cannot("wait for child control/?");
				return 0;
			}
			return !wait_exitcode(w);
		}
	} else {
		if (errno != ENOENT)
			warn_cannot("stat control/?");
	}
	return 0;
}
Ejemplo n.º 7
0
int main(int argc,const char * const *argv,const char * const *envp)
{
  char ch;
  int wstat;
  int pi[2];
  int i;
  int ignored;

  if (!argv[1])
    strerr_die1x(100,"fghack: usage: fghack child");

  if (pipe(pi) == -1)
    strerr_die2sys(111,FATAL,"unable to create pipe: ");

  switch(pid = fork()) {
    case -1:
      strerr_die2sys(111,FATAL,"unable to fork: ");
    case 0:
      close(pi[0]);
      for (i = 0;i < 30;++i)
        ignored = dup(pi[1]);
      pathexec_run(argv[1],argv + 1,envp);
      strerr_die4sys(111,FATAL,"unable to run ",argv[1],": ");
  }

  close(pi[1]);

  for (;;) {
    i = buffer_unixread(pi[0],&ch,1);
    if ((i == -1) && (errno == error_intr)) continue;
    if (i == 1) continue;
    break;
  }

  if (wait_pid(&wstat,pid) == -1)
    strerr_die2sys(111,FATAL,"wait failed: ");
  if (wait_crashed(wstat))
    strerr_die2x(111,FATAL,"child crashed");
  _exit(wait_exitcode(wstat));
}
Ejemplo n.º 8
0
Archivo: runit.c Proyecto: Gottox/runit
int main (int argc, const char * const *argv, char * const *envp) {
  const char * prog[2];
  int pid, pid2;
  int wstat;
  int st;
  iopause_fd x;
#ifndef IOPAUSE_POLL
  fd_set rfds;
  struct timeval t;
#endif
  char ch;
  int ttyfd;
  struct stat s;

  if (getpid() != 1) strerr_die2x(111, FATAL, "must be run as process no 1.");
  setsid();

  sig_block(sig_alarm);
  sig_block(sig_child);
  sig_catch(sig_child, sig_child_handler);
  sig_block(sig_cont);
  sig_catch(sig_cont, sig_cont_handler);
  sig_block(sig_hangup);
  sig_block(sig_int);
  sig_catch(sig_int, sig_int_handler);
  sig_block(sig_pipe);
  sig_block(sig_term);

  /* console */
  if ((ttyfd =open_write("/dev/console")) != -1) {
    dup2(ttyfd, 0); dup2(ttyfd, 1); dup2(ttyfd, 2);
    if (ttyfd > 2) close(ttyfd);
  }

  /* create selfpipe */
  while (pipe(selfpipe) == -1) {
    strerr_warn2(FATAL, "unable to create selfpipe, pausing: ", &strerr_sys);
    sleep(5);
  }
  coe(selfpipe[0]);
  coe(selfpipe[1]);
  ndelay_on(selfpipe[0]);
  ndelay_on(selfpipe[1]);

#ifdef RB_DISABLE_CAD
  /* activate ctrlaltdel handling, glibc, dietlibc */
  if (RB_DISABLE_CAD == 0) reboot_system(0);
#endif

  strerr_warn3(INFO, "$Id: 25da3b86f7bed4038b8a039d2f8e8c9bbcf0822b $",
               ": booting.", 0);

  /* runit */
  for (st =0; st < 3; st++) {
    /* if (st == 2) logwtmp("~", "reboot", ""); */
    while ((pid =fork()) == -1) {
      strerr_warn4(FATAL, "unable to fork for \"", stage[st], "\" pausing: ",
                   &strerr_sys);
      sleep(5);
    }
    if (!pid) {
      /* child */
      prog[0] =stage[st];
      prog[1] =0;

      /* stage 1 gets full control of console */
      if (st == 0) {
        if ((ttyfd =open("/dev/console", O_RDWR)) != -1) {
#ifdef TIOCSCTTY 
          ioctl(ttyfd, TIOCSCTTY, (char *)0);
#endif
          dup2(ttyfd, 0);
          if (ttyfd > 2) close(ttyfd);
        }
        else
          strerr_warn2(WARNING, "unable to open /dev/console: ", &strerr_sys);
      }
      else
        setsid();

      sig_unblock(sig_alarm);
      sig_unblock(sig_child);
      sig_uncatch(sig_child);
      sig_unblock(sig_cont);
      sig_ignore(sig_cont);
      sig_unblock(sig_hangup);
      sig_unblock(sig_int);
      sig_uncatch(sig_int);
      sig_unblock(sig_pipe);
      sig_unblock(sig_term);
            
      strerr_warn3(INFO, "enter stage: ", stage[st], 0);
      execve(*prog, (char *const *)prog, envp);
      strerr_die4sys(0, FATAL, "unable to start child: ", stage[st], ": ");
    }

    x.fd =selfpipe[0];
    x.events =IOPAUSE_READ;
    for (;;) {
      int child;

      sig_unblock(sig_child);
      sig_unblock(sig_cont);
      sig_unblock(sig_int);
#ifdef IOPAUSE_POLL
      poll(&x, 1, 14000);
#else
      t.tv_sec =14; t.tv_usec =0;
      FD_ZERO(&rfds);
      FD_SET(x.fd, &rfds);
      select(x.fd +1, &rfds, (fd_set*)0, (fd_set*)0, &t);
#endif
      sig_block(sig_cont);
      sig_block(sig_child);
      sig_block(sig_int);
      
      while (read(selfpipe[0], &ch, 1) == 1) {}
      while ((child =wait_nohang(&wstat)) > 0)
        if (child == pid) break;
      if (child == -1) {
        strerr_warn2(WARNING, "wait_nohang, pausing: ", &strerr_sys);
        sleep(5);
      }

      /* reget stderr */
      if ((ttyfd =open_write("/dev/console")) != -1) {
        dup2(ttyfd, 2);
        if (ttyfd > 2) close(ttyfd);
      }

      if (child == pid) {
        if (wait_exitcode(wstat) != 0) {
          if (wait_crashed(wstat))
            strerr_warn3(WARNING, "child crashed: ", stage[st], 0);
          else
            strerr_warn3(WARNING, "child failed: ", stage[st], 0);
          if (st == 0)
            /* this is stage 1 */
            if (wait_crashed(wstat) || (wait_exitcode(wstat) == 100)) {
              strerr_warn3(INFO, "leave stage: ", stage[st], 0);
              strerr_warn2(WARNING, "skipping stage 2...", 0);
              st++;
              break;
            }
          if (st == 1)
            /* this is stage 2 */
            if (wait_crashed(wstat) || (wait_exitcode(wstat) == 111)) {
              strerr_warn2(WARNING, "killing all processes in stage 2...", 0);
              kill(-pid, 9);
              sleep(5);
              strerr_warn2(WARNING, "restarting.", 0);
              st--;
              break;
            }
        }
        strerr_warn3(INFO, "leave stage: ", stage[st], 0);
        break;
      }
      if (child != 0) {
        /* collect terminated children */
        write(selfpipe[1], "", 1);
        continue;
      }

      /* sig? */
      if (!sigc  && !sigi) {
#ifdef DEBUG
        strerr_warn2(WARNING, "poll: ", &strerr_sys);
#endif
        continue;
      }
      if (st != 1) {
        strerr_warn2(WARNING, "signals only work in stage 2.", 0);
        sigc =sigi =0;
        continue;
      }
      if (sigi && (stat(CTRLALTDEL, &s) != -1) && (s.st_mode & S_IXUSR)) {
        strerr_warn2(INFO, "ctrl-alt-del request...", 0);
        prog[0] =CTRLALTDEL; prog[1] =0;
        while ((pid2 =fork()) == -1) {
          strerr_warn4(FATAL, "unable to fork for \"", CTRLALTDEL,
                       "\" pausing: ", &strerr_sys);
          sleep(5);
        }
        if (!pid2) {
          /* child */
          strerr_warn3(INFO, "enter stage: ", prog[0], 0);
          execve(*prog, (char *const *) prog, envp);
          strerr_die4sys(0, FATAL, "unable to start child: ", prog[0], ": ");
        }
        if (wait_pid(&wstat, pid2) == -1)
          strerr_warn2(FATAL, "wait_pid: ", &strerr_sys);
        if (wait_crashed(wstat))
          strerr_warn3(WARNING, "child crashed: ", CTRLALTDEL, 0);
        strerr_warn3(INFO, "leave stage: ", prog[0], 0);
        sigi =0;
        sigc++;
      }
      if (sigc && (stat(STOPIT, &s) != -1) && (s.st_mode & S_IXUSR)) {
        int i;
        /* unlink(STOPIT); */
        chmod(STOPIT, 0);

        /* kill stage 2 */
#ifdef DEBUG
        strerr_warn2(WARNING, "sending sigterm...", 0);
#endif
        kill(pid, sig_term);
        i =0;
        while (i < 5) {
          if ((child =wait_nohang(&wstat)) == pid) {
#ifdef DEBUG
            strerr_warn2(WARNING, "stage 2 terminated.", 0);
#endif
            pid =0;
            break;
          }
          if (child) continue;
          if (child == -1) 
            strerr_warn2(WARNING, "wait_nohang: ", &strerr_sys);
#ifdef DEBUG
          strerr_warn2(WARNING, "waiting...", 0);
#endif
          sleep(1);
          i++;
        }
        if (pid) {
          /* still there */
          strerr_warn2(WARNING,
                       "stage 2 not terminated, sending sigkill...", 0);
          kill(pid, 9);
          if (wait_pid(&wstat, pid) == -1)
            strerr_warn2(WARNING, "wait_pid: ", &strerr_sys);
        }
        sigc =0;
        strerr_warn3(INFO, "leave stage: ", stage[st], 0);

        /* enter stage 3 */
        break;
      }
      sigc =sigi =0;
#ifdef DEBUG
      strerr_warn2(WARNING, "no request.", 0);
#endif
    }
  }

  /* reget stderr */
  if ((ttyfd =open_write("/dev/console")) != -1) {
    dup2(ttyfd, 2);
    if (ttyfd > 2) close(ttyfd);
  }

#ifdef RB_AUTOBOOT
  /* fallthrough stage 3 */
  strerr_warn2(INFO, "sending KILL signal to all processes...", 0);
  kill(-1, SIGKILL);

  pid =fork();
  switch (pid) {
  case  0:
  case -1:
  if ((stat(REBOOT, &s) != -1) && (s.st_mode & S_IXUSR)) {
    strerr_warn2(INFO, "system reboot.", 0);
    sync();
    reboot_system(RB_AUTOBOOT);
  }
  else {
#ifdef RB_POWER_OFF
    strerr_warn2(INFO, "power off...", 0);
    sync();
    reboot_system(RB_POWER_OFF);
    sleep(2);
#endif
#ifdef RB_HALT_SYSTEM
    strerr_warn2(INFO, "system halt.", 0);
    sync();
    reboot_system(RB_HALT_SYSTEM);
#else
#ifdef RB_HALT
    strerr_warn2(INFO, "system halt.", 0);
    sync();
    reboot_system(RB_HALT);
#else
    strerr_warn2(INFO, "system reboot.", 0);
    sync();
    reboot_system(RB_AUTOBOOT);
#endif
#endif
  }
  if (pid == 0) _exit(0);
  break;
  default:
  sig_unblock(sig_child);
  while (wait_pid(0, pid) == -1);
  }
#endif

  for (;;) sig_pause();
  /* not reached */
  strerr_die2x(0, INFO, "exit.");
  return(0);
}
Ejemplo n.º 9
0
void fullcurrent(struct cyclog *d)
{
  int fd;
  int pid;
  int wstat;

  while (fchdir(d->fddir) == -1)
    pause3("unable to switch to ",d->dir,", pausing: ");

  while (fsync(d->fdcurrent) == -1)
    pause3("unable to write ",d->dir,"/current to disk, pausing: ");
  close(d->fdcurrent);

  while (rename("current","previous") == -1)
    pause3("unable to rename current to previous in directory ",d->dir,", pausing: ");
  while ((d->fdcurrent = open_append("current")) == -1)
    pause3("unable to create ",d->dir,"/current, pausing: ");
  coe(d->fdcurrent);
  d->bytes = 0;
  while (fchmod(d->fdcurrent,0644) == -1)
    pause3("unable to set mode of ",d->dir,"/current, pausing: ");

  while (chmod("previous",0744) == -1)
    pause3("unable to set mode of ",d->dir,"/previous, pausing: ");

  if (!d->processor)
    finish(d,"previous","s");
  else {
    for (;;) {
      while ((pid = fork()) == -1)
        pause3("unable to fork for processor in ",d->dir,", pausing: ");
      if (!pid) {
        startprocessor(d);
        strerr_die4sys(111,FATAL,"unable to run ",d->processor,": ");
      }
      if (wait_pid(&wstat,pid) == -1)
        pause3("wait failed for processor in ",d->dir,", pausing: ");
      else if (wait_crashed(wstat))
        pause3("processor crashed in ",d->dir,", pausing: ");
      else if (!wait_exitcode(wstat))
        break;
      strerr_warn4(WARNING,"processor failed in ",d->dir,", pausing",0);
      deepsleep(5);
    }

    while ((fd = open_append("processed")) == -1)
      pause3("unable to create ",d->dir,"/processed, pausing: ");
    while (fsync(fd) == -1)
      pause3("unable to write ",d->dir,"/processed to disk, pausing: ");
    while (fchmod(fd,0744) == -1)
      pause3("unable to set mode of ",d->dir,"/processed, pausing: ");
    close(fd);

    while ((fd = open_append("newstate")) == -1)
      pause3("unable to create ",d->dir,"/newstate, pausing: ");
    while (fsync(fd) == -1)
      pause3("unable to write ",d->dir,"/newstate to disk, pausing: ");
    close(fd);

    while (unlink("previous") == -1)
      pause3("unable to remove ",d->dir,"/previous, pausing: ");
    while (rename("newstate","state") == -1)
      pause3("unable to rename newstate to state in directory ",d->dir,", pausing: ");
    finish(d,"processed","s");
  }
}
Ejemplo n.º 10
0
void doit(int t) {
  int fakev4=0;
  int j;
  SSL *ssl;
  int wstat;
  uint32 scope_id;
  int sslctl[2];
  char *s;
  unsigned long tmp_long;
  char sslctl_cmd;
  stralloc ssl_env = { 0 };
  buffer ssl_env_buf;

  if (pipe(pi) == -1) strerr_die2sys(111,DROP,"unable to create pipe: ");
  if (pipe(po) == -1) strerr_die2sys(111,DROP,"unable to create pipe: ");
  if (socketpair(AF_UNIX, SOCK_STREAM, 0, sslctl) == -1) strerr_die2sys(111,DROP,"unable to create socketpair: ");

  switch(fork()) {
    case -1:
      strerr_die2sys(111,DROP,"unable to fork: ");
    case 0:
      /* Child */
      break;
    default:
      /* Parent */

      close(pi[0]); close(po[1]); close(sslctl[1]);

      if ((s=env_get("SSL_CHROOT")))
        if (chroot(s) == -1)
          strerr_die2x(111,DROPSSL,"unable to chroot");

      if ((s=env_get("SSL_GID"))) {
        scan_ulong(s,&tmp_long);
        gid = tmp_long;
      }
      if (gid) if (prot_gid(gid) == -1) strerr_die2sys(111,DROPSSL,"unable to set gid: ");

      if ((s=env_get("SSL_UID"))) {
        scan_ulong(s,&tmp_long);
        uid = tmp_long;
      }
      if (uid) if (prot_uid(uid) == -1)
        strerr_die2sys(111,DROPSSL,"unable to set uid: ");

      /* This will exit on a fatal error or if the client quits
       * without activating SSL
       */
      sslctl_cmd = ucspitls_master_wait_for_activation(sslctl[0]);

      /* If we got here, SSL must have been activated */
      ssl = ssl_new(ctx,t);
      if (!ssl) strerr_die2x(111,DROP,"unable to create SSL instance");
      if (ndelay_on(t) == -1)
        strerr_die2sys(111,DROP,"unable to set socket options: ");
      if (ssl_timeoutaccept(ssl,ssltimeout) == -1)
        strerr_die3x(111,DROP,"unable to accept SSL: ",ssl_error_str(ssl_errno));

      if (verbosity >= 2) {
        strnum[fmt_ulong(strnum,getpid())] = 0;
        strerr_warn3("sslserver: ssl ",strnum," accept ",0);
      }

      if (flagclientcert) {
        switch(ssl_verify(ssl,verifyhost)) {
          case -1:
            strerr_die2x(111,DROP,"unable to verify client certificate");
          case -2:
            strerr_die2x(111,DROP,"no client certificate");
          case -3:
            strerr_die2x(111,DROP,"client name does not match certificate");
          default: break;
        }
      }

      if (sslctl_cmd == 'Y') {
        ssl_server_env(ssl, &ssl_env);
        stralloc_0(&ssl_env); /* Add another NUL */

        buffer_init(&ssl_env_buf,buffer_unixwrite,sslctl[0],NULL,0);
        if (buffer_putflush(&ssl_env_buf, ssl_env.s, ssl_env.len) == -1) {
          strerr_die2sys(111, FATAL, "unable to write SSL environment: ");
        }
      } else if (sslctl_cmd != 'y') {
        strerr_die2x(111,DROP,"Protocol error on SSL control descriptor: invalid command character read");
      }

      if (close(sslctl[0]) != 0) {
        strerr_die2sys(111, DROP, "Error closing SSL control socket: ");
      }

      if (ssl_io(ssl,pi[1],po[0],io_opt) != 0)
        strerr_die3x(111,DROP,"unable to speak SSL: ",ssl_error_str(ssl_errno));
      if (wait_nohang(&wstat) > 0)
        _exit(wait_exitcode(wstat));
      ssl_close(ssl);
      _exit(0);
  }

  /* Child-only below this point */
  if (close(sslctl[0]) != 0) { 
    strerr_die2sys(111, DROP, "Error closing SSL control socket: ");
  }

  if (!forcev6 && ip6_isv4mapped(remoteip))
    fakev4=1;
  if (fakev4)
    remoteipstr[ip4_fmt(remoteipstr,remoteip+12)] = 0;
  else
    remoteipstr[ip6_fmt(remoteipstr,remoteip)] = 0;

  if (verbosity >= 2) {
    strnum[fmt_ulong(strnum,getpid())] = 0;
    strerr_warn4("sslserver: pid ",strnum," from ",remoteipstr,0);
  }

  if (socket_local6(t,localip,&localport,&scope_id) == -1)
    strerr_die2sys(111,DROP,"unable to get local address: ");

  if (fakev4)
    localipstr[ip4_fmt(localipstr,localip+12)] = 0;
  else
    localipstr[ip6_fmt(localipstr,localip)] = 0;
  remoteportstr[fmt_ulong(remoteportstr,remoteport)] = 0;

  if (!localhost)
    if (dns_name6(&localhostsa,localip) == 0)
      if (localhostsa.len) {
	if (!stralloc_0(&localhostsa)) drop_nomem();
	localhost = localhostsa.s;
      }
  env("PROTO",fakev4?"SSL":"SSL6");
  env("SSLLOCALIP",localipstr);
  env("SSL6LOCALIP",localipstr);
  env("SSLLOCALPORT",localportstr);
  env("SSL6LOCALPORT",localportstr);
  env("SSLLOCALHOST",localhost);
  env("SSL6LOCALHOST",localhost);
  if (!fakev4 && scope_id)
    env("SSL6INTERFACE",socket_getifname(scope_id));

  if (flagtcpenv) {
    env("TCPLOCALIP",localipstr);
    env("TCP6LOCALIP",localipstr);
    env("TCPLOCALPORT",localportstr);
    env("TCP6LOCALPORT",localportstr);
    env("TCPLOCALHOST",localhost);
    env("TCP6LOCALHOST",localhost);
    if (!fakev4 && scope_id)
      env("TCP6INTERFACE",socket_getifname(scope_id));
  }

  if (flagremotehost)
    if (dns_name6(&remotehostsa,remoteip) == 0)
      if (remotehostsa.len) {
	if (flagparanoid) {
	  verifyhost = remoteipstr;
	  if (dns_ip6(&tmp,&remotehostsa) == 0)
	    for (j = 0;j + 16 <= tmp.len;j += 16)
	      if (byte_equal(remoteip,16,tmp.s + j)) {
		flagparanoid = 0;
		break;
	      }
	  }
	if (!flagparanoid) {
	  if (!stralloc_0(&remotehostsa)) drop_nomem();
	  remotehost = remotehostsa.s;
	  verifyhost = remotehostsa.s;
	}
      }
  env("SSLREMOTEIP",remoteipstr);
  env("SSL6REMOTEIP",remoteipstr);
  remoteipstr[ip6_fmt(remoteipstr,remoteip)]=0;
  env("SSLREMOTEPORT",remoteportstr);
  env("SSL6REMOTEPORT",remoteportstr);
  env("SSLREMOTEHOST",remotehost);
  env("SSL6REMOTEHOST",remotehost);
  if (flagtcpenv) {
    env("TCPREMOTEIP",remoteipstr);
    env("TCP6REMOTEIP",remoteipstr);
    env("TCPREMOTEPORT",remoteportstr);
    env("TCP6REMOTEPORT",remoteportstr);
    env("TCPREMOTEHOST",remotehost);
    env("TCP6REMOTEHOST",remotehost);
  }

  if (flagremoteinfo) {
    if (remoteinfo6(&tcpremoteinfo,remoteip,remoteport,localip,localport,timeout,netif) == -1)
      flagremoteinfo = 0;
    if (!stralloc_0(&tcpremoteinfo)) drop_nomem();
  }
  env("SSLREMOTEINFO",flagremoteinfo ? tcpremoteinfo.s : 0);
  env("SSL6REMOTEINFO",flagremoteinfo ? tcpremoteinfo.s : 0);
  if (flagtcpenv) {
    env("TCPREMOTEINFO",flagremoteinfo ? tcpremoteinfo.s : 0);
    env("TCP6REMOTEINFO",flagremoteinfo ? tcpremoteinfo.s : 0);
  }

  if (fnrules) {
    int fdrules;
    fdrules = open_read(fnrules);
    if (fdrules == -1) {
      if (errno != error_noent) drop_rules();
      if (!flagallownorules) drop_rules();
    }
    else {
      int fakev4=0;
      char* temp;
      if (!forcev6 && ip6_isv4mapped(remoteip))
	fakev4=1;
      if (fakev4)
	temp=remoteipstr+7;
      else
	temp=remoteipstr;
      if (rules(found,fdrules,temp,remotehost,flagremoteinfo ? tcpremoteinfo.s : 0) == -1) drop_rules();
      close(fdrules);
    }
  }

  if (verbosity >= 2) {
    strnum[fmt_ulong(strnum,getpid())] = 0;
    if (!stralloc_copys(&tmp,"sslserver: ")) drop_nomem();
    safecats(flagdeny ? "deny" : "ok");
    cats(" "); safecats(strnum);
    cats(" "); if (localhost) safecats(localhost);
    cats(":"); safecats(localipstr);
    cats(":"); safecats(localportstr);
    cats(" "); if (remotehost) safecats(remotehost);
    cats(":"); safecats(remoteipstr);
    cats(":"); if (flagremoteinfo) safecats(tcpremoteinfo.s);
    cats(":"); safecats(remoteportstr);
    cats("\n");
    buffer_putflush(buffer_2,tmp.s,tmp.len);
  }

  if (flagdeny) _exit(100);

  if (gid) if (prot_gid(gid) == -1)
    strerr_die2sys(111,FATAL,"unable to set gid: ");
  if (uid) if (prot_uid(uid) == -1)
    strerr_die2sys(111,FATAL,"unable to set uid: ");

  close(pi[1]); close(po[0]);

  sig_uncatch(sig_child);
  sig_unblock(sig_child);
  sig_uncatch(sig_term);
  sig_uncatch(sig_pipe);

  if (fcntl(sslctl[1],F_SETFD,0) == -1)
    strerr_die2sys(111,FATAL,"unable to clear close-on-exec flag");
  strnum[fmt_ulong(strnum,sslctl[1])]=0;
  setenv("SSLCTLFD",strnum,1);

  if (fcntl(pi[0],F_SETFD,0) == -1)
    strerr_die2sys(111,FATAL,"unable to clear close-on-exec flag");
  strnum[fmt_ulong(strnum,pi[0])]=0;
  setenv("SSLREADFD",strnum,1);

  if (fcntl(po[1],F_SETFD,0) == -1)
    strerr_die2sys(111,FATAL,"unable to clear close-on-exec flag");
  strnum[fmt_ulong(strnum,po[1])]=0;
  setenv("SSLWRITEFD",strnum,1);
  
  if (flagsslwait) {
    if (fd_copy(0,t) == -1)
      strerr_die2sys(111,DROP,"unable to set up descriptor 0: ");
    if (fd_copy(1,t) == -1)
      strerr_die2sys(111,DROP,"unable to set up descriptor 1: ");
  } else {
    if (fd_move(0,pi[0]) == -1)
      strerr_die2sys(111,DROP,"unable to set up descriptor 0: ");
    if (fd_move(1,po[1]) == -1)
      strerr_die2sys(111,DROP,"unable to set up descriptor 1: ");
  }

  if (flagkillopts)
    socket_ipoptionskill(t);
  if (!flagdelay)
    socket_tcpnodelay(t);

  if (*banner) {
    buffer_init(&b,buffer_unixwrite,1,bspace,sizeof bspace);
    if (buffer_putsflush(&b,banner) == -1)
      strerr_die2sys(111,DROP,"unable to print banner: ");
  }

  if (!flagsslwait) {
    strnum[fmt_ulong(strnum,flagsslenv)] = 0;
    strerr_warn2("flagsslenv: ", strnum, 0);
    ucspitls(flagsslenv,0,1);
  }

  pathexec(prog);
  strerr_die4sys(111,DROP,"unable to run ",*prog,": ");
}
Ejemplo n.º 11
0
void doit(int t) {
  int j;
  SSL *ssl;
  int wstat;
  int sslctl[2];
  char *s;
  unsigned long tmp_long;
  char ssl_cmd;
  stralloc ssl_env = { 0 };
  int bytesleft;
  char envbuf[8192];
  int childpid;
  
  if (pipe(pi) == -1) strerr_die2sys(111,DROP,"unable to create pipe: ");
  if (pipe(po) == -1) strerr_die2sys(111,DROP,"unable to create pipe: ");
  if (socketpair(AF_UNIX, SOCK_STREAM, 0, sslctl) == -1) strerr_die2sys(111,DROP,"unable to create socketpair: ");
 
  if ((j = ip_fmt(&remoteipsa,&remoteaddr)))
    strerr_die3x(111,DROP,"unable to print remote ip",gai_strerror(j));

  if (flagremotehost) {
    if (dns_name(&remotehostsa,&remoteaddr) == 0)
      if (remotehostsa.len) {
	if (flagparanoid) {
	  struct addrinfo *reverse, hints = {0};
	  verifyhost = remoteipsa.s;
	  hints.ai_family = remoteaddr.sa4.sin_family;
	  if (remoteaddr.sa6.sin6_family == AF_INET6) {
	    hints.ai_flags = AI_V4MAPPED | AI_ALL;
	  }
	  if (getaddrinfo(remotehostsa.s, NULL, &hints, &reverse) == 0) {
	    hints.ai_next = reverse;
	    while (hints.ai_next) {
	      if (hints.ai_next->ai_family == AF_INET
		  && remoteaddr.sa4.sin_family == AF_INET
		  && byte_equal(&remoteaddr.sa4.sin_addr, 4, &((struct sockaddr_in*) hints.ai_next->ai_addr)->sin_addr)
		  || hints.ai_next->ai_family == AF_INET6
		     && remoteaddr.sa6.sin6_family == AF_INET6
		     && byte_equal(remoteaddr.sa6.sin6_addr.s6_addr, 16,
				   &((struct sockaddr_in6*) hints.ai_next->ai_addr)->sin6_addr.s6_addr)) {
		flagparanoid = 0;
		break;
	      }
	      hints.ai_next = hints.ai_next->ai_next;
	    }
	    freeaddrinfo(reverse);
	  }
	}
	if (!flagparanoid) {
	  remotehost = remotehostsa.s;
	  verifyhost = remotehostsa.s;
	}
      }
  }

  switch(childpid=fork()) {
    case -1:
      strerr_die2sys(111,DROP,"unable to fork: ");
    case 0:
      /* Child */
      close(sslctl[0]);
      break;
    default:
      /* Parent */
      
      close(pi[0]); close(po[1]); close(sslctl[1]);

      if ((s=env_get("SSL_CHROOT")))
        if (chroot(s) == -1) {
          kill(childpid, SIGTERM);
          strerr_die2x(111,DROP,"unable to chroot");
        }
      
      if ((s=env_get("SSL_GID"))) {
        scan_ulong(s,&tmp_long);
        gid = tmp_long;
      }
      if (gid) if (prot_gid(gid) == -1) {
        kill(childpid, SIGTERM);
        strerr_die2sys(111,FATAL,"unable to set gid: ");
      }

      if ((s=env_get("SSL_UID"))) {
        scan_ulong(s,&tmp_long);
        uid = tmp_long;
      }
      if (uid)
        if (prot_uid(uid) == -1) {
          kill(childpid, SIGTERM);
          strerr_die2sys(111,FATAL,"unable to set uid: ");
        }

      /* Read the TLS command socket.  This will block until/unless
       * TLS is requested.
       */
      if (read(sslctl[0],&ssl_cmd,1) == 1) {
        ssl = ssl_new(ctx,t);
        if (!ssl) {
          kill(childpid, SIGTERM);
          strerr_die2x(111,DROP,"unable to create SSL instance");
        }
        if (ndelay_on(t) == -1) {
          kill(childpid, SIGTERM);
          strerr_die2sys(111,DROP,"unable to set socket options: ");
        }
        if (ssl_timeoutaccept(ssl,ssltimeout) == -1) {
          kill(childpid, SIGTERM);
          strerr_die3x(111,DROP,"unable to accept SSL: ",ssl_error_str(ssl_errno));
        }
      }
        
      if (verbosity >= 2) {
        strnum[fmt_ulong(strnum,getpid())] = 0;
        strerr_warn3("sslserver: ssl ",strnum," accept ",0);
      }
        
      if (flagclientcert) {
        switch(ssl_verify(ssl,verifyhost)) {
          case -1:
	    kill(childpid, SIGTERM);
            strerr_die2x(111,DROP,"unable to verify client certificate");
          case -2:
	    kill(childpid, SIGTERM);
            strerr_die2x(111,DROP,"no client certificate");
          case -3:
	    kill(childpid, SIGTERM);
            strerr_die3x(111,DROP,"certificate name does not match client fqdn: ",verifyhost);
          default: break;
        }
      }
      
      if (ssl_cmd == 'Y') {
        ssl_server_env(ssl, &ssl_env);
        if(!stralloc_0(&ssl_env)) drop_nomem(); /* Add another NUL */
        env("SSLCTL",ssl_env.s); 

        for(bytesleft = ssl_env.len; bytesleft>0; bytesleft-=j)
          if ( (j=write(sslctl[0], ssl_env.s, bytesleft)) < 0) {
            kill(childpid, SIGTERM);
            strerr_die2sys(111, FATAL, "unable to write SSL environment: ");
          }
      }

      if (ssl_cmd == 'Y' || ssl_cmd == 'y') {
        if (ssl_io(ssl,pi[1],po[0],progtimeout) != 0) {
          kill(childpid, SIGTERM);
          strerr_die3x(111,DROP,"unable to speak SSL: ",ssl_error_str(ssl_errno));
        }
        if (wait_nohang(&wstat) > 0)
          _exit(wait_exitcode(wstat)); 
        ssl_close(ssl);
      }
      kill(childpid, SIGTERM);
      _exit(0);
  }

  /* Child-only below this point */

  if (verbosity >= 2) {
    strnum[fmt_ulong(strnum,getpid())] = 0;
    strerr_warn4("sslserver: pid ",strnum," from ",remoteipsa.s,0);
  }

  if (socket_local(t,&localaddr,&localport) == -1)
    strerr_die2sys(111,DROP,"unable to get local address: ");

  if ((j = ip_fmt(&localipsa,&localaddr)))
    strerr_die3x(111,DROP,"unable to print local address: ",gai_strerror(j));
  remoteportstr[fmt_ulong(remoteportstr,remoteport)] = 0;

  if (!localhost)
    if (dns_name(&localhostsa,&localaddr) == 0)
      if (localhostsa.len) {
	if (!stralloc_0(&localhostsa)) drop_nomem();
	localhost = localhostsa.s;
      }
  /* If remoteipsa.s contain ':' colon character will assume it is IPv6 */
  if (byte_chr(remoteipsa.s, remoteipsa.len, ':') < remoteipsa.len)
    env("PROTO","SSL6");
  else
    env("PROTO","SSL");
  env("SSLLOCALIP",localipsa.s);
  env("SSLLOCALPORT",localportstr);
  env("SSLLOCALHOST",localhost);
  if (flagtcpenv) {
    env("TCPLOCALIP",localipsa.s);
    env("TCPLOCALPORT",localportstr);
    env("TCPLOCALHOST",localhost);
  }

  env("SSLREMOTEIP",remoteipsa.s);
  env("SSLREMOTEPORT",remoteportstr);
  env("SSLREMOTEHOST",remotehost);
  if (flagtcpenv) {
    env("TCPREMOTEIP",remoteipsa.s);
    env("TCPREMOTEPORT",remoteportstr);
    env("TCPREMOTEHOST",remotehost);
  }

  if (flagremoteinfo) {
    if (remoteinfo(&tcpremoteinfo,&remoteaddr,&localaddr,timeout) == -1)
      flagremoteinfo = 0;
    if (!stralloc_0(&tcpremoteinfo)) drop_nomem();
  }
  env("SSLREMOTEINFO",flagremoteinfo ? tcpremoteinfo.s : 0);
  if (flagtcpenv)
    env("TCPREMOTEINFO",flagremoteinfo ? tcpremoteinfo.s : 0);

  if (fnrules) {
    int fdrules;
    fdrules = open_read(fnrules);
    if (fdrules == -1) {
      if (errno != error_noent) drop_rules();
      if (!flagallownorules) drop_rules();
    }
    else {
      if (rules(found,fdrules,&remoteaddr,remotehost,flagremoteinfo ? tcpremoteinfo.s : 0) == -1)
	drop_rules();
      close(fdrules);
    }
  }

  if (verbosity >= 2) {
    strnum[fmt_ulong(strnum,getpid())] = 0;
    if (!stralloc_copys(&tmp,"sslserver: ")) drop_nomem();
    safecats(flagdeny ? "deny" : "ok");
    cats(" "); safecats(strnum);
    cats(" "); if (localhost) safecats(localhost);
    cats(":"); safecats(localipsa.s);
    cats(":"); safecats(localportstr);
    cats(" "); if (remotehost) safecats(remotehost);
    cats(":"); safecats(remoteipsa.s);
    cats(":"); if (flagremoteinfo) safecats(tcpremoteinfo.s);
    cats(":"); safecats(remoteportstr);
    cats("\n");
    buffer_putflush(buffer_2,tmp.s,tmp.len);
  }

  if (flagdeny) _exit(100);

  if (gid) if (prot_gid(gid) == -1)
    strerr_die2sys(111,FATAL,"unable to set gid: ");
  if (uid) if (prot_uid(uid) == -1)
    strerr_die2sys(111,FATAL,"unable to set uid: ");

  close(pi[1]); close(po[0]); close(sslctl[0]);

  sig_uncatch(sig_child);
  sig_unblock(sig_child);
  sig_uncatch(sig_term);
  sig_uncatch(sig_pipe);

  if (fcntl(sslctl[1],F_SETFD,0) == -1)
    strerr_die2sys(111,FATAL,"unable to clear close-on-exec flag");
  strnum[fmt_ulong(strnum,sslctl[1])]=0;
  env("SSLCTLFD",strnum);

  if (fcntl(pi[0],F_SETFD,0) == -1)
    strerr_die2sys(111,FATAL,"unable to clear close-on-exec flag");
  strnum[fmt_ulong(strnum,pi[0])]=0;
  env("SSLREADFD",strnum);

  if (fcntl(po[1],F_SETFD,0) == -1)
    strerr_die2sys(111,FATAL,"unable to clear close-on-exec flag");
  strnum[fmt_ulong(strnum,po[1])]=0;
  env("SSLWRITEFD",strnum);

  if (flagsslwait) {
    if (fd_copy(0,t) == -1)
      strerr_die2sys(111,DROP,"unable to set up descriptor 0: ");
    if (fd_copy(1,t) == -1)
      strerr_die2sys(111,DROP,"unable to set up descriptor 1: ");
  } else {
    if (fd_move(0,pi[0]) == -1)
      strerr_die2sys(111,DROP,"unable to set up descriptor 0: ");
    if (fd_move(1,po[1]) == -1)
      strerr_die2sys(111,DROP,"unable to set up descriptor 1: ");
  }

  if (flagkillopts)
    socket_ipoptionskill(t);
  if (!flagdelay)
    socket_tcpnodelay(t);

  if (*banner) {
    buffer_init(&b,buffer_unixwrite,1,bspace,sizeof bspace);
    if (buffer_putsflush(&b,banner) == -1)
      strerr_die2sys(111,DROP,"unable to print banner: ");
  }

  if (!flagsslwait) {
    ssl_cmd = flagsslenv ? 'Y' : 'y';
    if (write(sslctl[1], &ssl_cmd, 1) < 1)
      strerr_die2sys(111,DROP,"unable to start SSL: ");
    if (flagsslenv) {
      while ((j=read(sslctl[1],envbuf,8192)) > 0) {
        stralloc_catb(&ssl_env,envbuf,j);
        if (ssl_env.len >= 2 && ssl_env.s[ssl_env.len-2]==0 && ssl_env.s[ssl_env.len-1]==0)
          break;
      }
      if (j < 0)
        strerr_die2sys(111,DROP,"unable to read SSL environment: ");
      pathexec_multienv(&ssl_env);
    }
  }
      
  pathexec(prog);
  strerr_die4sys(111,DROP,"unable to run ",*prog,": ");
}
Ejemplo n.º 12
0
const char *
auth_close(struct call *cc, stralloc *user, const char *pre)
{
	const char *s;
	int wstat;
	int exitcode;
	char c;

	s = 0; c = 0;
	if ((long)cc->pid == -1)
		return "454 unable to start authentication process. "
		    "(#4.3.0)\r\n";
	
	if (cc->flagabort)
		s = "501 authentication exchange aborted. (#4.3.0)\r\n";
	if (cc->flagerr)
		s = "454 authentication process write failure. (#4.3.0)\r\n";
	
	if (!cc->flagerr && !cc->flagabort) {
		if (call_getc(cc, &c) == -1) {
			s = "454 authentication process read failure. "
			    "(#4.3.0)\r\n";
		} else
		switch (c) {
		case 'K':
			if (!stralloc_copys(user, pre!=0?pre:"")) {
				s = "421 out of memory (#4.3.0)\r\n"; 
				break;
			}
			while (call_getc(cc, &c) == 1) {
				if (!stralloc_append(user, &c)) {
					s = "421 out of memory (#4.3.0)\r\n"; 
					break;
				}
			}
			if (cc->flagerr)
				s = "454 authentication process read "
				    "failure. (#4.3.0)\r\n";
			else
				s = "235 nice to meet you\r\n";
			break;
		case 'D':
			s = "535 authentication failure\r\n";
			break;
		case 'Z':
			s = "501 authentication exchange failed\r\n";
			break;
		default:
			s = "454 authentication process failure. (#4.3.0)\r\n";
			break;
		}
	}
	close(cc->tofd);
	close(cc->fromfd);
      
	if ((unsigned long)wait_pid(&wstat,cc->pid) != cc->pid)
		return "454 authentication waitpid surprise (#4.3.0)\r\n";
	if (wait_crashed(wstat))
		return "454 authentication process crashed (#4.3.0)\r\n";
	exitcode = wait_exitcode(wstat);
	switch (exitcode) {
	case 0:
		return s;
	default:
		return "454 temporary authentication failure (#4.3.0)\r\n";
	}
}