Beispiel #1
0
int pr_ctrls_flush_response(pr_ctrls_t *ctrl) {

  /* Sanity check */
  if (!ctrl) {
    errno = EINVAL;
    return -1;
  }

  /* Make sure the callback(s) added responses */
  if (ctrl->ctrls_cb_resps) {
    if (pr_ctrls_send_msg(ctrl->ctrls_cl->cl_fd, ctrl->ctrls_cb_retval,
        ctrl->ctrls_cb_resps->nelts,
        (char **) ctrl->ctrls_cb_resps->elts) < 0)
      return -1;
  }

  return 0;
}
Beispiel #2
0
int main(int argc, char *argv[]) {
  unsigned char verbose = FALSE;
  char **respargv = NULL;
  const char *cmdopts = "hs:v";

  register int i = 0;
  char *socket_file = PR_RUN_DIR "/proftpd.sock";
  int sockfd = -1, optc = 0, status = 0, respargc = 0;
  unsigned int reqargc = 0;
  pool *ctl_pool = NULL;
  array_header *reqargv = NULL;

  /* Make sure we were called with at least one argument. */
  if (argc-1 < 1) {
    fprintf(stdout, "%s: missing required arguments\n", program);
    exit(1);
  }

  /* Set the POSIXLY_CORRECT environment variable, so that control handlers
   * can themselves have optional flags.
   */
  if (putenv("POSIXLY_CORRECT=1") < 0) {
    fprintf(stderr, "%s: unable to set POSIXLY_CORRECT: %s\n", program,
      strerror(errno));
    exit(1);
  }

  opterr = 0;
  while ((optc = getopt(argc, argv, cmdopts)) != -1) {
    switch (optc) {
      case 'h':
        usage();
        return 0;

      case 's':
        if (*optarg != '/') {
          fprintf(stderr, "%s: alternate socket path must be an absolute "
            "path\n", program);
          return 1;
        }

        socket_file = optarg;
        break;

      case 'v':
        verbose = TRUE;
        break;

      case '?':
        fprintf(stdout, "%s: unknown option: %c\n", program, (char) optopt);
        break;
    }
  }

  signal(SIGPIPE, sig_pipe);

  /* Allocate some memory for proftpd objects. */
  ctl_pool = make_sub_pool(NULL);

  reqargv = make_array(ctl_pool, 0, sizeof(char *));

  /* Process the command-line args into an array_header. */
  for (i = optind; i < argc; i++) {
    if (verbose)
      fprintf(stdout, "%s: adding \"%s\" to reqargv\n", program, argv[i]);
    *((char **) push_array(reqargv)) = pstrdup(ctl_pool, argv[i]);
    reqargc++;
  }

  /* Don't forget to NULL-terminate the array. */
  *((char **) push_array(reqargv)) = NULL;

  /* Open a connection to the socket maintained by mod_ctrls. */
  if (verbose)
    fprintf(stdout, "%s: contacting server using '%s'\n", program,
      socket_file);

  sockfd = pr_ctrls_connect(socket_file);
  if (sockfd < 0) {
    fprintf(stderr, "%s: error contacting server using '%s': %s\n", program,
      socket_file, strerror(errno));
    exit(1);
  }

  if (verbose)
    fprintf(stdout, "%s: sending control request\n", program);

  if (pr_ctrls_send_msg(sockfd, 0, reqargc, (char **) reqargv->elts) < 0) {
    fprintf(stderr, "%s: error sending request: %s\n", program,
      strerror(errno));
    exit(1);
  }

  /* Read and display the responses. */

  if (verbose)
    fprintf(stdout, "%s: receiving control response\n", program);

  /* Manually set errno to this value, so that if an error (like a segfault)
   * occurs, the error string displayed to the user is more indicative of
   * the cause of the lack of responses.
   */
  errno = EPERM;

  if ((respargc = pr_ctrls_recv_response(ctl_pool, sockfd, &status,
      &respargv)) < 0) {
    fprintf(stdout, "%s: error receiving response: %s\n", program,
      strerror(errno));
    exit(1);
  }

  if (respargv != NULL) {
    for (i = 0; i < respargc; i++)
      fprintf(stdout, "%s: %s\n", program, respargv[i]);

  } else
    fprintf(stdout, "%s: no response from server\n", program);

  destroy_pool(ctl_pool);
  ctl_pool = NULL;

  return 0;
}
Beispiel #3
0
static int ctrls_get_creds_basic(struct sockaddr_un *sock, int cl_fd,
    unsigned int max_age, uid_t *uid, gid_t *gid, pid_t *pid) {
  pid_t cl_pid = 0;
  char *tmp = NULL;
  time_t stale_time;
  struct stat st;

  /* Check the path -- hmmm... */
  PRIVS_ROOT
  while (stat(sock->sun_path, &st) < 0) {
    int xerrno = errno;

    if (xerrno == EINTR) {
      pr_signals_handle();
      continue;
    }

    PRIVS_RELINQUISH
    pr_trace_msg(trace_channel, 2, "error: unable to stat %s: %s",
      sock->sun_path, strerror(xerrno));
    (void) close(cl_fd);

    errno = xerrno;
    return -1;
  }
  PRIVS_RELINQUISH

  /* Is it a socket? */
  if (pr_ctrls_issock_unix(st.st_mode) < 0) {
    (void) close(cl_fd);
    errno = ENOTSOCK;
    return -1;
  }

  /* Are the perms _not_ rwx------? */
  if (st.st_mode & (S_IRWXG|S_IRWXO) ||
      ((st.st_mode & S_IRWXU) != PR_CTRLS_CL_MODE)) {
    pr_trace_msg(trace_channel, 3,
      "error: unable to accept connection: incorrect mode");
    (void) close(cl_fd);
    errno = EPERM;
    return -1;
  }

  /* Is it new enough? */
  stale_time = time(NULL) - max_age;

  if (st.st_atime < stale_time ||
      st.st_ctime < stale_time ||
      st.st_mtime < stale_time) {
    char *msg = "error: stale connection";

    pr_trace_msg(trace_channel, 3,
      "unable to accept connection: stale connection");

    /* Log the times being compared, to aid in debugging this situation. */
    if (st.st_atime < stale_time) {
      time_t age = stale_time - st.st_atime;

      pr_trace_msg(trace_channel, 3,
         "last access time of '%s' is %lu secs old (must be less than %u secs)",
         sock->sun_path, (unsigned long) age, max_age);
    }

    if (st.st_ctime < stale_time) {
      time_t age = stale_time - st.st_ctime;

      pr_trace_msg(trace_channel, 3,
         "last change time of '%s' is %lu secs old (must be less than %u secs)",
         sock->sun_path, (unsigned long) age, max_age);
    }

    if (st.st_mtime < stale_time) {
      time_t age = stale_time - st.st_mtime;

      pr_trace_msg(trace_channel, 3,
         "last modified time of '%s' is %lu secs old (must be less than %u "
         "secs)", sock->sun_path, (unsigned long) age, max_age);
    }

    if (pr_ctrls_send_msg(cl_fd, -1, 1, &msg) < 0) {
      pr_trace_msg(trace_channel, 2, "error sending message: %s",
        strerror(errno));
    }

    (void) close(cl_fd);

    errno = ETIMEDOUT;
    return -1;
  }

  /* Parse the PID out of the path */
  tmp = sock->sun_path;
  tmp += strlen("/tmp/ftp.cl");
  cl_pid = atol(tmp);

  /* Return the IDs of the caller */
  if (uid)
    *uid = st.st_uid;

  if (gid)
    *gid = st.st_gid;

  if (pid)
    *pid = cl_pid;

  return 0;
}