Пример #1
0
static int af_setpwent(pool *p) {

  if (af_user_file != NULL) {
    if (af_user_file->af_file != NULL) {
      /* If already opened, rewind */
      rewind(af_user_file->af_file);
      return 0;

    } else {
      int xerrno;

      PRIVS_ROOT
      af_user_file->af_file = fopen(af_user_file->af_path, "r");
      xerrno = errno;
      PRIVS_RELINQUISH

      if (af_user_file->af_file == NULL) {
        struct stat st;

        if (pr_fsio_stat(af_user_file->af_path, &st) == 0) {
          pr_log_pri(PR_LOG_WARNING,
            "error: unable to open AuthUserFile file '%s' (file owned by "
            "UID %s, GID %s, perms %04o, accessed by UID %s, GID %s): %s",
            af_user_file->af_path, pr_uid2str(p, st.st_uid),
            pr_gid2str(p, st.st_gid), st.st_mode & ~S_IFMT,
            pr_uid2str(p, geteuid()), pr_gid2str(p, getegid()),
            strerror(xerrno));

        } else {
          pr_log_pri(PR_LOG_WARNING,
            "error: unable to open AuthUserFile file '%s': %s",
            af_user_file->af_path, strerror(xerrno));
        }

        errno = xerrno;
        return -1;
      }

      /* As the file may contain sensitive data, we do not want it lingering
       * around in stdio buffers.
       */
      (void) setvbuf(af_user_file->af_file, NULL, _IONBF, 0);

      if (fcntl(fileno(af_user_file->af_file), F_SETFD, FD_CLOEXEC) < 0) {
        pr_log_pri(PR_LOG_WARNING, MOD_AUTH_FILE_VERSION
          ": unable to set CLOEXEC on AuthUserFile %s (fd %d): %s",
          af_user_file->af_path, fileno(af_user_file->af_file),
          strerror(errno));
      }

      pr_log_debug(DEBUG7, MOD_AUTH_FILE_VERSION ": using passwd file '%s'",
        af_user_file->af_path);
      return 0;
    }
  }

  pr_trace_msg(trace_channel, 8, "no AuthUserFile configured");
  errno = EPERM;
  return -1;
}
Пример #2
0
static int copy_symlink(pool *p, const char *src_dir, const char *src_path,
    const char *dst_dir, const char *dst_path, uid_t uid, gid_t gid) {
  char *link_path = pcalloc(p, PR_TUNABLE_BUFFER_SIZE);
  int len;

  len = pr_fsio_readlink(src_path, link_path, PR_TUNABLE_BUFFER_SIZE-1);
  if (len < 0) {
    pr_log_pri(PR_LOG_WARNING, "CreateHome: error reading link '%s': %s",
      src_path, strerror(errno));
    return -1;
  }
  link_path[len] = '\0';

  /* If the target of the link lies within the src path, rename that portion
   * of the link to be the corresponding part of the dst path.
   */
  if (strncmp(link_path, src_dir, strlen(src_dir)) == 0) {
    link_path = pdircat(p, dst_dir, link_path + strlen(src_dir), NULL);
  }

  if (pr_fsio_symlink(link_path, dst_path) < 0) {
    pr_log_pri(PR_LOG_WARNING, "CreateHome: error symlinking '%s' to '%s': %s",
      link_path, dst_path, strerror(errno));
    return -1;
  }

  /* Make sure the new symlink has the proper ownership. */
  if (pr_fsio_chown(dst_path, uid, gid) < 0) {
    pr_log_pri(PR_LOG_WARNING, "CreateHome: error chown'ing '%s' to %u/%u: %s",
      dst_path, (unsigned int) uid, (unsigned int) gid, strerror(errno));
  }

  return 0; 
}
Пример #3
0
static int wrap_is_usable_file(char *filename) {
  struct stat statbuf;
  pr_fh_t *fh = NULL;

  /* check the easy case first */
  if (filename == NULL)
    return FALSE;

  if (pr_fsio_stat(filename, &statbuf) == -1) {
    pr_log_pri(PR_LOG_INFO, MOD_WRAP_VERSION ": \"%s\": %s", filename,
      strerror(errno));
    return FALSE;
  }

  /* OK, the file exists.  Now, to make sure that the current process
   * can _read_ the file
   */
  fh = pr_fsio_open(filename, O_RDONLY);
  if (fh == NULL) {
    pr_log_pri(PR_LOG_INFO, MOD_WRAP_VERSION ": \"%s\": %s", filename,
      strerror(errno));
    return FALSE;
  }
  pr_fsio_close(fh);

  return TRUE;
}
Пример #4
0
struct passwd *pr_auth_getpwent(pool *p) {
  cmd_rec *cmd = NULL;
  modret_t *mr = NULL;
  struct passwd *res = NULL;

  cmd = make_cmd(p, 0);
  mr = dispatch_auth(cmd, "getpwent", NULL);

  if (MODRET_ISHANDLED(mr) && MODRET_HASDATA(mr))
    res = mr->data;

  if (cmd->tmp_pool) {
    destroy_pool(cmd->tmp_pool);
    cmd->tmp_pool = NULL;
  }

  /* Sanity check */
  if (res == NULL)
    return NULL;

  /* Make sure the UID and GID are not -1 */
  if (res->pw_uid == (uid_t) -1) {
    pr_log_pri(PR_LOG_ERR, "error: UID of -1 not allowed");
    return NULL;
  }

  if (res->pw_gid == (gid_t) -1) {
    pr_log_pri(PR_LOG_ERR, "error: GID of -1 not allowed");
    return NULL;
  }

  return res;
}
Пример #5
0
static int copy_symlink(pool *p, const char *src_path, const char *dst_path) {
  char *link_path = pcalloc(p, PR_TUNABLE_BUFFER_SIZE);
  int len;

  len = pr_fsio_readlink(src_path, link_path, PR_TUNABLE_BUFFER_SIZE-1);
  if (len < 0) {
    int xerrno = errno;

    pr_log_pri(PR_LOG_WARNING, MOD_COPY_VERSION ": error reading link '%s': %s",
      src_path, strerror(xerrno));

    errno = xerrno;
    return -1;
  }
  link_path[len] = '\0';

  if (pr_fsio_symlink(link_path, dst_path) < 0) {
    int xerrno = errno;

    pr_log_pri(PR_LOG_WARNING, MOD_COPY_VERSION
      ": error symlinking '%s' to '%s': %s", link_path, dst_path,
      strerror(xerrno));

    errno = xerrno;
    return -1;
  }

  return 0;
}
Пример #6
0
static RETSIGTYPE sig_alarm(int signo) {
  struct sigaction act;

  act.sa_handler = sig_alarm;
  sigemptyset(&act.sa_mask);
  act.sa_flags = 0;

#ifdef SA_INTERRUPT
  act.sa_flags |= SA_INTERRUPT;
#endif

  /* Install this handler for SIGALRM. */
  if (sigaction(SIGALRM, &act, NULL) < 0) {
    pr_log_pri(PR_LOG_WARNING,
      "unable to install SIGALRM handler via sigaction(2): %s",
      strerror(errno));
  }

#ifdef HAVE_SIGINTERRUPT
  if (siginterrupt(SIGALRM, 1) < 0) {
    pr_log_pri(PR_LOG_WARNING,
      "unable to allow SIGALRM to interrupt system calls: %s", strerror(errno));
  }
#endif

  recvd_signal_flags |= RECEIVED_SIG_ALRM;
  nalarms++;

  /* Reset the alarm */
  _total_time += _current_timeout;
  if (_current_timeout) {
    _alarmed_time = time(NULL);
    alarm(_current_timeout);
  }
}
Пример #7
0
/* Masks/unmasks all important signals (as opposed to blocking alarms)
 */
static void mask_signals(unsigned char block) {
  static sigset_t mask_sigset;

  if (block) {
    sigemptyset(&mask_sigset);

    sigaddset(&mask_sigset, SIGTERM);
    sigaddset(&mask_sigset, SIGCHLD);
    sigaddset(&mask_sigset, SIGUSR1);
    sigaddset(&mask_sigset, SIGINT);
    sigaddset(&mask_sigset, SIGQUIT);
    sigaddset(&mask_sigset, SIGALRM);
#ifdef SIGIO
    sigaddset(&mask_sigset, SIGIO);
#endif
#ifdef SIGBUS
    sigaddset(&mask_sigset, SIGBUS);
#endif
    sigaddset(&mask_sigset, SIGHUP);

    if (sigprocmask(SIG_BLOCK, &mask_sigset, NULL) < 0) {
      pr_log_pri(PR_LOG_NOTICE,
        "unable to block signal set: %s", strerror(errno));
    }

  } else {
    if (sigprocmask(SIG_UNBLOCK, &mask_sigset, NULL) < 0) {
      pr_log_pri(PR_LOG_NOTICE,
        "unable to unblock signal set: %s", strerror(errno));
    }
  }
}
Пример #8
0
static int create_dir(const char *dir, uid_t uid, gid_t gid,
    mode_t mode) {
  mode_t prev_mask;
  struct stat st;
  int res = -1;

  pr_fs_clear_cache2(dir);
  res = pr_fsio_stat(dir, &st);

  if (res == -1 &&
      errno != ENOENT) {
    int xerrno = errno;

    pr_log_pri(PR_LOG_WARNING, "error checking '%s': %s", dir,
      strerror(xerrno));

    errno = xerrno;
    return -1;
  }

  /* The directory already exists. */
  if (res == 0) {
    pr_trace_msg(trace_channel, 8, "'%s' already exists", dir);
    pr_log_debug(DEBUG3, "CreateHome: '%s' already exists", dir);
    return 0;
  }

  /* The given mode is absolute, not subject to any Umask setting. */
  prev_mask = umask(0);

  if (pr_fsio_mkdir(dir, mode) < 0) {
    int xerrno = errno;

    umask(prev_mask);
    pr_log_pri(PR_LOG_WARNING, "error creating '%s': %s", dir,
      strerror(xerrno));

    errno = xerrno;
    return -1;
  }

  umask(prev_mask);

  if (pr_fsio_chown(dir, uid, gid) < 0) {
    int xerrno = errno;

    pr_log_pri(PR_LOG_WARNING, "error setting ownership of '%s': %s", dir,
      strerror(xerrno));

    errno = xerrno;
    return -1;
  }

  pr_trace_msg(trace_channel, 8, "directory '%s' created", dir);
  pr_log_debug(DEBUG6, "CreateHome: directory '%s' created", dir);
  return 0;
}
Пример #9
0
static int dso_init(void) {
#ifdef PR_USE_CTRLS
  register unsigned int i = 0;
#endif /* PR_USE_CTRLS */

  /* Allocate the pool for this module's use. */
  dso_pool = make_sub_pool(permanent_pool);
  pr_pool_tag(dso_pool, MOD_DSO_VERSION);

  lt_dlpreload_default(lt_preloaded_symbols);

  /* Initialize libltdl. */
  if (lt_dlinit() < 0) {
    pr_log_pri(PR_LOG_ERR, MOD_DSO_VERSION ": error initializing libltdl: %s",
      lt_dlerror());
    return -1;
  }

  /* Explicitly set the search path used for opening modules. */
  if (lt_dlsetsearchpath(dso_module_path) < 0) {
    pr_log_pri(PR_LOG_ERR, MOD_DSO_VERSION ": error setting module path: %s",
      lt_dlerror());
    return -1;
  }

#ifdef PR_USE_CTRLS
  /* Register ctrls handlers. */
  for (i = 0; dso_acttab[i].act_action; i++) {
    pool *sub_pool = make_sub_pool(dso_pool);

    /* Allocate and initialize the ACL for this control. */
    dso_acttab[i].act_acl = pcalloc(sub_pool, sizeof(ctrls_acl_t));
    dso_acttab[i].act_acl->acl_pool = sub_pool;
    pr_ctrls_init_acl(dso_acttab[i].act_acl);

    if (pr_ctrls_register(&dso_module, dso_acttab[i].act_action,
        dso_acttab[i].act_desc, dso_acttab[i].act_cb) < 0)
      pr_log_pri(PR_LOG_INFO, MOD_DSO_VERSION
        ": error registering '%s' control: %s", dso_acttab[i].act_action,
        strerror(errno));
  }
#endif /* PR_USE_CTRLS */

  /* Ideally, we'd call register a listener for the 'core.exit' event
   * and call lt_dlexit() there, politely freeing up any resources allocated
   * by the ltdl library.  However, it's possible that other modules, later in
   * the dispatch cycles, may need to use pointers to memory in shared modules
   * that would become invalid by such finalization.  So we skip it, for now.
   *
   * If there was a way to schedule this handler, to happen after all other
   * exit handlers, that'd be best.
   */
  pr_event_register(&dso_module, "core.restart", dso_restart_ev, NULL);

  return 0;
}
Пример #10
0
static int af_setpwent(void) {

  if (af_user_file != NULL) {
    if (af_user_file->af_file != NULL) {
      /* If already opened, rewind */
      rewind(af_user_file->af_file);
      return 0;

    } else {
      int xerrno;

      PRIVS_ROOT
      af_user_file->af_file = fopen(af_user_file->af_path, "r");
      xerrno = errno;
      PRIVS_RELINQUISH

      if (af_user_file->af_file == NULL) {
        struct stat st;

        if (pr_fsio_stat(af_user_file->af_path, &st) == 0) {
          pr_log_pri(PR_LOG_WARNING,
            "error: unable to open AuthUserFile file '%s' (file owned by "
            "UID %lu, GID %lu, perms %04o, accessed by UID %lu, GID %lu): %s",
            af_user_file->af_path, (unsigned long) st.st_uid,
            (unsigned long) st.st_gid, st.st_mode & ~S_IFMT,
            (unsigned long) geteuid(), (unsigned long) getegid(),
            strerror(xerrno));

        } else {
          pr_log_pri(PR_LOG_WARNING,
            "error: unable to open AuthUserFile file '%s': %s",
            af_user_file->af_path, strerror(xerrno));
        }

        errno = xerrno;
        return -1;
      }

      if (fcntl(fileno(af_user_file->af_file), F_SETFD, FD_CLOEXEC) < 0) {
        pr_log_pri(PR_LOG_WARNING, MOD_AUTH_FILE_VERSION
          ": unable to set CLOEXEC on AuthUserFile %s (fd %d): %s",
          af_user_file->af_path, fileno(af_user_file->af_file),
          strerror(errno));
      }

      pr_log_debug(DEBUG7, MOD_AUTH_FILE_VERSION ": using passwd file '%s'",
        af_user_file->af_path);
      return 0;
    }
  }

  pr_trace_msg(trace_channel, 8, "no AuthUserFile configured");
  errno = EPERM;
  return -1;
}
Пример #11
0
static void dynmasq_refresh(void) {
    server_rec *s;

    pr_log_debug(DEBUG2, MOD_DYNMASQ_VERSION
                 ": resolving all MasqueradeAddress directives (could take a little while)");

    for (s = (server_rec *) server_list->xas_list; s; s = s->next) {
        config_rec *c;

        c = find_config(s->conf, CONF_PARAM, "MasqueradeAddress", FALSE);
        if (c != NULL) {
            const char *masq_addr;
            pr_netaddr_t *na;

            masq_addr = c->argv[1];

            pr_netaddr_clear_ipcache(masq_addr);
            na = pr_netaddr_get_addr(s->pool, masq_addr, NULL);
            if (na != NULL) {
                /* Compare the obtained netaddr with the one already present.
                 * Only update the "live" netaddr if they differ.
                 */
                pr_log_debug(DEBUG2, MOD_DYNMASQ_VERSION
                             ": resolved MasqueradeAddress '%s' to IP address %s", masq_addr,
                             pr_netaddr_get_ipstr(na));

                if (pr_netaddr_cmp(c->argv[0], na) != 0) {
                    pr_log_pri(PR_LOG_DEBUG, MOD_DYNMASQ_VERSION
                               ": MasqueradeAddress '%s' updated for new address %s (was %s)",
                               masq_addr, pr_netaddr_get_ipstr(na),
                               pr_netaddr_get_ipstr(c->argv[0]));

                    /* Overwrite the old netaddr pointer.  Note that this constitutes
                     * a minor memory leak, as there currently isn't a way to free
                     * the memory used by a netaddr object.  Hrm.
                     */
                    c->argv[0] = na;

                } else {
                    pr_log_debug(DEBUG2, MOD_DYNMASQ_VERSION
                                 ": MasqueradeAddress '%s' has not changed addresses", masq_addr);
                }

            } else {
                pr_log_pri(PR_LOG_INFO, MOD_DYNMASQ_VERSION
                           ": unable to resolve '%s', keeping previous address", masq_addr);
            }
        }
    }

    return;
}
Пример #12
0
static int mcache_init(void) {
  const char *version;

  memcache_pool = make_sub_pool(permanent_pool);
  pr_pool_tag(memcache_pool, MOD_MEMCACHE_VERSION);

  memcache_server_lists = make_array(memcache_pool, 2,
    sizeof(memcached_server_st **));

  memcache_init();

  pr_event_register(&memcache_module, "core.restart", mcache_restart_ev, NULL);

  version = memcached_lib_version();
  if (strcmp(version, LIBMEMCACHED_VERSION_STRING) != 0) {
    pr_log_pri(PR_LOG_INFO, MOD_MEMCACHE_VERSION
      ": compiled using libmemcached-%s headers, but linked to "
      "libmemcached-%s library", LIBMEMCACHED_VERSION_STRING, version);

  } else {
    pr_log_debug(DEBUG2, MOD_MEMCACHE_VERSION ": using libmemcached-%s",
      version);
  }

  return 0;
}
Пример #13
0
void init_bindings(void) {
  int res = 0;

#ifdef PR_USE_IPV6
  int sock;

  /* Check to see whether we can actually create an IPv6 socket. */
  sock = socket(AF_INET6, SOCK_STREAM, IPPROTO_TCP);
  if (sock < 0) {
    pr_netaddr_disable_ipv6();

  } else {
    (void) close(sock);
  }
#endif /* PR_USE_IPV6 */

  if (ServerType == SERVER_INETD) {
    res = init_inetd_bindings();

  } else if (ServerType == SERVER_STANDALONE) {
    res = init_standalone_bindings();
  }

  if (res < 0) {
    pr_log_pri(PR_LOG_ERR, "%s",
      "Unable to start proftpd; check logs for more details");
    exit(1);
  }
}
Пример #14
0
int xferlog_open(const char *path) {

  if (path == NULL) {
    if (xferlogfd != -1) {
      xferlog_close();
    }

    return 0;
  }

  if (xferlogfd == -1) {
    pr_log_debug(DEBUG6, "opening TransferLog '%s'", path);
    pr_log_openfile(path, &xferlogfd, PR_TUNABLE_XFER_LOG_MODE);

    if (xferlogfd < 0) {
      int xerrno = errno;

      pr_log_pri(PR_LOG_NOTICE, "unable to open TransferLog '%s': %s",
        path, strerror(xerrno));

      errno = xerrno;
    }
  }

  return xferlogfd;
}
Пример #15
0
struct group *pr_auth_getgrgid(pool *p, gid_t gid) {
  cmd_rec *cmd = NULL;
  modret_t *mr = NULL;
  struct group *res = NULL;

  cmd = make_cmd(p, 1, (void *) &gid);
  mr = dispatch_auth(cmd, "getgrgid", NULL);

  if (MODRET_ISHANDLED(mr) && MODRET_HASDATA(mr))
    res = mr->data;

  if (cmd->tmp_pool) {
    destroy_pool(cmd->tmp_pool);
    cmd->tmp_pool = NULL;
  }

  /* Sanity check */
  if (res == NULL) {
    errno = ENOENT;
    return NULL;
  }

  /* Make sure the GID is not -1 */
  if (res->gr_gid == (gid_t) -1) {
    pr_log_pri(PR_LOG_ERR, "error: GID of -1 not allowed");
    return NULL;
  }

  pr_log_debug(DEBUG10, "retrieved group '%s' for GID %lu",
    res->gr_name, (unsigned long) gid);
  return res;
}
Пример #16
0
static int sftppam_init(void) {
#if defined(PR_SHARED_MODULE)
  pr_event_register(&sftp_pam_module, "core.module-unload",
    sftppam_mod_unload_ev, NULL);
#endif /* !PR_SHARED_MODULE */

  /* Prepare our driver. */
  memset(&sftppam_driver, 0, sizeof(sftppam_driver));
  sftppam_driver.open = sftppam_driver_open;
  sftppam_driver.authenticate = sftppam_driver_authenticate;
  sftppam_driver.close = sftppam_driver_close;

  /* Register ourselves with mod_sftp. */
  if (sftp_kbdint_register_driver("pam", &sftppam_driver) < 0) {
    int xerrno = errno;

    pr_log_pri(PR_LOG_NOTICE, MOD_SFTP_PAM_VERSION
      ": notice: error registering 'keyboard-interactive' driver: %s",
      strerror(xerrno));

    errno = xerrno;
    return -1;
  }

  return 0;
}
Пример #17
0
static void *null_alloc(size_t size) {
  void *ret = NULL;

  if (size == 0) {
    /* Yes, this code is correct.
     *
     * The size argument is the originally requested amount of memory.
     * null_alloc() is called because smalloc() returned NULL.  But why,
     * exactly?  If the requested size is zero, then it may not have been
     * an error -- or it may be because the system is actually out of memory.
     * To differentiate, we do a malloc(0) call here if the requested size is
     * zero.  If malloc(0) returns NULL, then we really do have an error.
     */
    ret = malloc(size);
  }

  if (ret == NULL) {
    pr_log_pri(PR_LOG_ALERT, "Out of memory!");
#ifdef PR_USE_DEVEL
    if (debug_flags & PR_POOL_DEBUG_FL_OOM_DUMP_POOLS) {
      pr_pool_debug_memory(oom_printf);
    }
#endif
    exit(1);
  }

  return ret;
}
Пример #18
0
static void qos_data_connect_ev(const void *event_data, void *user_data) {
  const struct socket_ctx *sc;

  sc = event_data;

  /* Only set TOS flags on IPv4 sockets; IPv6 sockets don't seem to support
   * them.
   */
  if (pr_netaddr_get_family(sc->addr) == AF_INET) {
    config_rec *c;
    c = find_config(sc->server->conf, CONF_PARAM, "QoSOptions", FALSE);
    if (c) {
      int dataqos, res;

      dataqos = *((int *) c->argv[1]);

      res = setsockopt(sc->sockfd, ip_level, IP_TOS, (void *) &dataqos,
        sizeof(dataqos));
      if (res < 0) {
        pr_log_pri(PR_LOG_NOTICE, MOD_QOS_VERSION
          ": error setting data socket IP_TOS: %s", strerror(errno));
      }
    }
  }
}
Пример #19
0
static int af_setpwent(void) {

  if (af_user_file) {
    if (af_user_file->af_file) {
      /* If already opened, rewind */
      rewind(af_user_file->af_file);
      return 0;

    } else {
      af_user_file->af_file = fopen(af_user_file->af_path, "r");
      if (af_user_file->af_file == NULL) {
        pr_log_pri(PR_LOG_ERR, "error: unable to open passwd file '%s': %s",
          af_user_file->af_path, strerror(errno));
        return -1;
      }

      pr_log_debug(DEBUG7, MOD_AUTH_FILE_VERSION ": using passwd file '%s'",
        af_user_file->af_path);
      return 0;
    }
  }

  errno = EPERM;
  return -1;
}
Пример #20
0
static struct group *af_getgrent(void) {
  struct group *grp = NULL, *res = NULL;

  if (!af_group_file ||
      !af_group_file->af_file) {
    errno = EINVAL;
    return NULL;
  }

  while (TRUE) {
#ifdef HAVE_FGETGRENT
    pr_signals_handle();
    grp = fgetgrent(af_group_file->af_file);
#else
    char *cp = NULL, *buf = NULL;
    int buflen = BUFSIZ;

    pr_signals_handle();

    buf = malloc(BUFSIZ);
    if (buf == NULL) {
      pr_log_pri(PR_LOG_CRIT, "%s", "Out of memory!");
      _exit(1);
    }
    grp = NULL;

    while (af_getgrentline(&buf, &buflen, af_group_file->af_file) != NULL) {

      /* Ignore comment and empty lines */
      if (buf[0] == '\0' ||
          buf[0] == '#') {
        continue;
      }

      cp = strchr(buf, '\n');
      if (cp != NULL)
        *cp = '\0';

      grp = af_getgrp(buf);
      free(buf);

      break;
    }
#endif /* !HAVE_FGETGRENT */

    /* If grp is NULL now, the file is empty - nothing more to be read. */
    if (grp == NULL) {
      break;
    }

    if (af_allow_grent(grp) < 0) {
      continue;
    }

    res = grp;
    break;
  }

  return res;
}
Пример #21
0
struct group *pr_auth_getgrent(pool *p) {
  cmd_rec *cmd = NULL;
  modret_t *mr = NULL;
  struct group *res = NULL;

  cmd = make_cmd(p, 0);
  mr = dispatch_auth(cmd, "getgrent", NULL);

  if (MODRET_ISHANDLED(mr) &&
      MODRET_HASDATA(mr)) {
    res = mr->data;
  }

  if (cmd->tmp_pool) {
    destroy_pool(cmd->tmp_pool);
    cmd->tmp_pool = NULL;
  }

  /* Sanity check */
  if (res == NULL)
    return NULL;

  /* Make sure the GID is not -1 */
  if (res->gr_gid == (gid_t) -1) {
    pr_log_pri(PR_LOG_WARNING, "error: GID of -1 not allowed");
    return NULL;
  }

  return res;
}
Пример #22
0
static int dynmasq_init(void) {
#if defined(PR_SHARED_MODULE)
    pr_event_register(&dynmasq_module, "core.module-unload",
                      dynmasq_mod_unload_ev, NULL);
#endif /* !PR_SHARED_MODULE */

    pr_event_register(&dynmasq_module, "core.postparse", dynmasq_postparse_ev,
                      NULL);
    pr_event_register(&dynmasq_module, "core.restart", dynmasq_restart_ev,
                      NULL);

#ifdef PR_USE_CTRLS
    if (pr_ctrls_register(&dynmasq_module, "dynmasq", "mod_dynmasq controls",
                          dynmasq_handle_dynmasq) < 0) {
        pr_log_pri(PR_LOG_NOTICE, MOD_DYNMASQ_VERSION
                   ": error registering 'dynmasq' control: %s", strerror(errno));

    } else {
        register unsigned int i;

        dynmasq_act_pool = make_sub_pool(permanent_pool);
        pr_pool_tag(dynmasq_act_pool, "DynMasq Controls Pool");

        for (i = 0; dynmasq_acttab[i].act_action; i++) {
            dynmasq_acttab[i].act_acl = palloc(dynmasq_act_pool, sizeof(ctrls_acl_t));
            pr_ctrls_init_acl(dynmasq_acttab[i].act_acl);
        }
    }
#endif /* PR_USE_CTRLS */

    return 0;
}
Пример #23
0
static unsigned int sym_type_hash(pr_stash_type_t sym_type, const char *name,
    size_t namelen) {
  unsigned int hash;

  /* XXX Ugly hack to support mixed cases of directives in config files. */
  if (sym_type != PR_SYM_CONF) {
    hash = symtab_hash(name, namelen);

  } else {
    register unsigned int i;
    char *buf;

    buf = malloc(namelen+1);
    if (buf == NULL) {
      pr_log_pri(PR_LOG_ALERT, "Out of memory!");
      exit(1);
    }

    buf[namelen] = '\0';
    for (i = 0; i < namelen; i++) {
      buf[i] = tolower((int) name[i]);
    }

    hash = symtab_hash(buf, namelen);
    free(buf);
  }

  return hash;
}
Пример #24
0
int pr_scoreboard_add_entry(void) {
  unsigned char found_slot = FALSE;

  if (scoreboard_fd < 0) {
    errno = EINVAL;
    return -1;
  }

  /* Write-lock the scoreboard file. */
  if (wlock_scoreboard() < 0)
    return -1;

  /* No interruptions, please. */
  pr_signals_block();

  /* If the scoreboard is open, the file position is already past the
   * header.
   */
  while (TRUE) {
    int res = 0;
    while ((res = read(scoreboard_fd, &entry, sizeof(entry))) ==
        sizeof(entry)) {

      /* If this entry's PID is marked as zero, it means this slot can be
       * reused.
       */
      if (!entry.sce_pid) {
        entry_lock.l_start = lseek(scoreboard_fd, 0, SEEK_CUR) - sizeof(entry);
        found_slot = TRUE;
        break;
      }
    }

    if (res == 0) {
      entry_lock.l_start = lseek(scoreboard_fd, 0, SEEK_CUR);
      found_slot = TRUE;
    }

    if (found_slot)
      break;
  }

  memset(&entry, '\0', sizeof(entry));

  entry.sce_pid = getpid();
  entry.sce_uid = geteuid();
  entry.sce_gid = getegid();

  if (write_entry() < 0)
    pr_log_pri(PR_LOG_NOTICE, "error writing scoreboard entry: %s",
      strerror(errno));

  pr_signals_unblock();

  /* We can unlock the scoreboard now. */
  unlock_scoreboard();

  return 0;
}
Пример #25
0
static void wrap_log_request_denied(int priority,
    struct request_info *request) {
  pr_log_pri(priority, MOD_WRAP_VERSION ": refused connection from %s",
    eval_client(request));

  /* done */
  return;
}
Пример #26
0
static struct passwd *af_getpasswd(const char *buf, unsigned int lineno) {
  register unsigned int i;
  register char *cp = NULL;
  char *ep = NULL, *buffer = NULL;
  char **fields = NULL;
  struct passwd *pwd = NULL;

  fields = pwdfields;
  buffer = pwdbuf;
  pwd = &pwent;

  sstrncpy(buffer, buf, BUFSIZ-1);
  buffer[BUFSIZ-1] = '\0';

  for (cp = buffer, i = 0; i < NPWDFIELDS && cp; i++) {
    fields[i] = cp;
    while (*cp && *cp != ':') {
      ++cp;
    }

    if (*cp) {
      *cp++ = '\0';

    } else {
      cp = 0;
    }
  }

  if (i != NPWDFIELDS) {
    pr_log_pri(PR_LOG_ERR, "Malformed entry in AuthUserFile file (line %u)",
      lineno);
    return NULL;
  }

  if (*fields[2] == '\0' ||
      *fields[3] == '\0') {
    return NULL;
  }

  pwd->pw_name = fields[0];
  pwd->pw_passwd = fields[1];

  if (fields[2][0] == '\0' ||
     ((pwd->pw_uid = strtol(fields[2], &ep, 10)) == 0 && *ep)) {
       return NULL;
  }

  if (fields[3][0] == '\0' ||
     ((pwd->pw_gid = strtol(fields[3], &ep, 10)) == 0 && *ep)) {
       return NULL;
  }

  pwd->pw_gecos = fields[4];
  pwd->pw_dir = fields[5];
  pwd->pw_shell = fields[6];

  return pwd;
}
Пример #27
0
static int wrap_is_usable_file(char *filename) {
  struct stat st;
  pr_fh_t *fh = NULL;

  /* check the easy case first */
  if (filename == NULL)
    return FALSE;

  /* Make sure that the current process can _read_ the file. */
  fh = pr_fsio_open(filename, O_RDONLY);
  if (fh == NULL) {
    int xerrno = errno;

    pr_log_pri(PR_LOG_NOTICE, MOD_WRAP_VERSION ": failed to read \"%s\": %s",
      filename, strerror(xerrno));

    errno = xerrno;
    return FALSE;
  }

  if (pr_fsio_fstat(fh, &st) < 0) {
    int xerrno = errno;

    pr_log_pri(PR_LOG_NOTICE, MOD_WRAP_VERSION ": failed to stat \"%s\": %s",
      filename, strerror(xerrno));

    pr_fsio_close(fh);
    errno = xerrno;
    return FALSE;
  }

  if (S_ISDIR(st.st_mode)) {
    int xerrno = EISDIR;

    pr_log_pri(PR_LOG_NOTICE, MOD_WRAP_VERSION ": unable to use \"%s\": %s",
      filename, strerror(xerrno));

    pr_fsio_close(fh);
    errno = xerrno;
    return FALSE;
  }

  pr_fsio_close(fh);
  return TRUE;
}
Пример #28
0
const char *pr_netaddr_get_ipstr(pr_netaddr_t *na) {
#ifdef PR_USE_IPV6
  char buf[INET6_ADDRSTRLEN];
#else
  char buf[INET_ADDRSTRLEN];
#endif /* PR_USE_IPV6 */
  int res = 0;
  
  if (!na) {
    errno = EINVAL;
    return NULL;
  }

  /* If this pr_netaddr_t has already been resolved to an IP string, return the
   * cached string.
   */
  if (na->na_have_ipstr)
    return na->na_ipstr;

  memset(buf, '\0', sizeof(buf));
  res = pr_getnameinfo(pr_netaddr_get_sockaddr(na),
    pr_netaddr_get_sockaddr_len(na), buf, sizeof(buf), NULL, 0, NI_NUMERICHOST);

  if (res != 0) {
    if (res != EAI_SYSTEM) {
      pr_log_pri(PR_LOG_INFO, "getnameinfo error: %s", pr_gai_strerror(res));

    } else {
      pr_log_pri(PR_LOG_INFO, "getnameinfo system error: [%d] %s",
        errno, strerror(errno));
    }

    return NULL;
  }

  /* Copy the string into the pr_netaddr_t cache as well, so we only
   * have to do this once for this pr_netaddr_t.
   */
  memset(na->na_ipstr, '\0', sizeof(na->na_ipstr));
  sstrncpy(na->na_ipstr, buf, sizeof(na->na_ipstr));
  na->na_have_ipstr = TRUE;

  return na->na_ipstr;
}
Пример #29
0
static struct group *af_getgrp(const char *buf, unsigned int lineno) {
  int i;
  char *cp;

  i = strlen(buf) + 1;

  if (!grpbuf) {
    grpbuf = malloc(i);

  } else {
    char *new_buf;

    new_buf = realloc(grpbuf, i);
    if (new_buf == NULL) {
      return NULL;
    }

    grpbuf = new_buf;
  }

  if (!grpbuf)
    return NULL;

  sstrncpy(grpbuf, buf, i);

  cp = strrchr(grpbuf, '\n');
  if (cp) {
    *cp = '\0';
  }

  for (cp = grpbuf, i = 0; i < NGRPFIELDS && cp; i++) {
    grpfields[i] = cp;

    cp = strchr(cp, ':');
    if (cp) {
      *cp++ = 0;
    }
  }

  if (i < (NGRPFIELDS - 1)) {
    pr_log_pri(PR_LOG_ERR, "Malformed entry in AuthGroupFile file (line %u)",
      lineno);
    return NULL;
  }

  if (*grpfields[2] == '\0') {
    return NULL;
  }

  grent.gr_name = grpfields[0];
  grent.gr_passwd = grpfields[1];
  grent.gr_gid = atoi(grpfields[2]);
  grent.gr_mem = af_getgrmems(grpfields[3]);

  return &grent;
}
Пример #30
0
static void null_alloc(void) {
  pr_log_pri(PR_LOG_ALERT, "Out of memory!");
#ifdef PR_USE_DEVEL
  if (debug_flags & PR_POOL_DEBUG_FL_OOM_DUMP_POOLS) {
    pr_pool_debug_memory(oom_printf);
  }
#endif

  exit(1);
}