/*
 * cmd_escapestring: certain strings sent to a database should be properly
 *  escaped -- for instance, quotes need to be escaped to insure that 
 *  a query string is properly formatted.  cmd_escapestring does whatever
 *  is necessary to escape the special characters in a string. 
 *
 * Inputs:
 *  cmd->argv[0]: connection name
 *  cmd->argv[1]: string to escape
 *
 * Returns:
 *  this command CANNOT fail.  The return string is null-terminated and 
 *  stored in the data field of the modret_t structure.
 *
 * Notes:
 *  Different languages may escape different characters in different ways.
 *  A backend should handle this correctly, where possible.  If there is
 *  no client library function to do the string conversion, it is strongly
 *  recommended that the backend module writer do whatever is necessry (read
 *  the database documentation and figure it out) to do the conversion
 *  themselves in this function.
 *
 *  A backend MUST supply a working escapestring implementation.  Simply
 *  copying the data from argv[0] into the data field of the modret allows
 *  for possible SQL injection attacks when this backend is used.
 */
MODRET cmd_escapestring(cmd_rec * cmd) {
  conn_entry_t *entry = NULL;
  db_conn_t *conn = NULL;
  char *unescaped = NULL;
  char *escaped = NULL;

  sql_log(DEBUG_FUNC, "%s", "entering \tpostgres cmd_escapestring");

  _sql_check_cmd(cmd, "cmd_escapestring");

  if (cmd->argc != 2) {
    sql_log(DEBUG_FUNC, "%s", "exiting \tpostgres cmd_escapestring");
    return ERROR_MSG(cmd, MOD_SQL_POSTGRES_VERSION, "badly formed request");
  }

  /* get the named connection */
  entry = _sql_get_connection(cmd->argv[0]);
  if (!entry) {
    sql_log(DEBUG_FUNC, "%s", "exiting \tpostgres cmd_escapestring");
    return ERROR_MSG(cmd, MOD_SQL_POSTGRES_VERSION, "unknown named connection");
  }

  conn = (db_conn_t *) entry->data;

  /* Note: the PQescapeString() function appeared in the C API as of
   * Postgres-7.2.
   */
  unescaped = cmd->argv[1];
  escaped = (char *) pcalloc(cmd->tmp_pool, sizeof(char) *
    (strlen(unescaped) * 2) + 1);

  PQescapeString(escaped, unescaped, strlen(unescaped));

  sql_log(DEBUG_FUNC, "%s", "exiting \tpostgres cmd_escapestring");
  return mod_create_data(cmd, (void *) escaped);
}
Beispiel #2
0
MODRET pw_getpwnam(cmd_rec *cmd) {
  struct passwd *pw;
  const char *name;

  name = cmd->argv[0];
  if (persistent_passwd) {
    pw = p_getpwnam(name);

  } else {
    pw = getpwnam(name);
  }

  if (auth_unix_opts & AUTH_UNIX_OPT_MAGIC_TOKEN_CHROOT) {
    char *home_dir, *ptr;

    /* Here is where we do the "magic token" chroot monstrosity inflicted
     * on the world by wu-ftpd.
     *
     * If the magic token '/./' appears in the user's home directory, the
     * directory portion before the token is the directory to use for
     * the chroot; the directory portion after the token is the directory
     * to use for the initial chdir.
     */

    home_dir = pstrdup(cmd->tmp_pool, pw->pw_dir);

    /* We iterate through the home directory string since it is possible
     * for the '.' character to appear without it being part of the magic
     * token.
     */
    ptr = strchr(home_dir, '.');
    while (ptr != NULL) {
      pr_signals_handle();

      /* If we're at the start of the home directory string, stop looking:
       * this home directory is not really valid anyway.
       */
      if (ptr == home_dir) {
        break;
      }

      /* Back up one character. */
      ptr--;

      /* If we're at the start of the home directory now, stop looking:
       * this home directory cannot contain a valid magic token.  I.e.
       *
       * /./home/foo
       *
       * cannot be valid, as there is no directory portion before the
       * token.
       */
      if (ptr == home_dir) {
        break;
      }

      if (strncmp(ptr, "/./", 3) == 0) {
        char *default_chdir;
        config_rec *c;

        *ptr = '\0';
        default_chdir = pstrdup(cmd->tmp_pool, ptr + 2);

        /* In order to make sure that this user is chrooted to this
         * directory, we remove all DefaultRoot directives and add a new
         * one.  Same for the DefaultChdir directive.
         */

        (void) remove_config(main_server->conf, "DefaultRoot", FALSE);
        c = add_config_param_set(&main_server->conf, "DefaultRoot", 1, NULL);
        c->argv[0] = pstrdup(c->pool, home_dir);

        (void) remove_config(main_server->conf, "DefaultChdir", FALSE);
        c = add_config_param_set(&main_server->conf, "DefaultChdir", 1, NULL);
        c->argv[0] = pstrdup(c->pool, default_chdir);

        pr_log_debug(DEBUG9, "AuthUnixOption magicTokenChroot: "
          "found magic token in '%s', using 'DefaultRoot %s' and "
          "'DefaultChdir %s'", pw->pw_dir, home_dir, default_chdir);

        /* We need to use a long-lived memory pool for overwriting the
         * normal home directory.
         */
        pw->pw_dir = pstrdup(session.pool, home_dir);

        break;
      }

      ptr = strchr(ptr + 2, '.');
    }
  }

  return pw ? mod_create_data(cmd, pw) : PR_DECLINED(cmd);
}
Beispiel #3
0
MODRET authfile_getgroups(cmd_rec *cmd) {
  struct passwd *pwd = NULL;
  struct group *grp = NULL;
  array_header *gids = NULL, *groups = NULL;
  char *name = cmd->argv[0];

  if (name == NULL) {
    return PR_DECLINED(cmd);
  }

  if (af_setpwent() < 0) {
    return PR_DECLINED(cmd);
  }

  if (af_setgrent() < 0) {
    return PR_DECLINED(cmd);
  }

  /* Check for NULLs */
  if (cmd->argv[1])
    gids = (array_header *) cmd->argv[1];

  if (cmd->argv[2])
    groups = (array_header *) cmd->argv[2];

  /* Retrieve the necessary info. */
  pwd = af_getpwnam(name);
  if (pwd == NULL) {
    return PR_DECLINED(cmd);
  }

  /* Populate the first group ID and name. */
  if (gids) {
    *((gid_t *) push_array(gids)) = pwd->pw_gid;
  }

  if (groups &&
      (grp = af_getgrgid(pwd->pw_gid)) != NULL) {
    *((char **) push_array(groups)) = pstrdup(session.pool, grp->gr_name);
  }

  af_setgrent();

  /* This is where things get slow, expensive, and ugly.  Loop through
   * everything, checking to make sure we haven't already added it.
   */
  while ((grp = af_getgrent()) != NULL &&
      grp->gr_mem) {
    char **gr_mems = NULL;

    pr_signals_handle();

    /* Loop through each member name listed */
    for (gr_mems = grp->gr_mem; *gr_mems; gr_mems++) {

      /* If it matches the given username... */
      if (strcmp(*gr_mems, pwd->pw_name) == 0) {

        /* ...add the GID and name */
        if (gids)
          *((gid_t *) push_array(gids)) = grp->gr_gid;

        if (groups)
          *((char **) push_array(groups)) = pstrdup(session.pool, grp->gr_name);
      }
    }
  }

  if (gids && gids->nelts > 0) {
    return mod_create_data(cmd, (void *) &gids->nelts);

  } else if (groups && groups->nelts > 0) {
    return mod_create_data(cmd, (void *) &groups->nelts);
  }

  return PR_DECLINED(cmd);
}
Beispiel #4
0
MODRET handle_getpwent(cmd_rec *cmd) {
    getpwent_count++;
    return mod_create_data(cmd, &test_pwd);
}
Beispiel #5
0
MODRET handle_getgrent(cmd_rec *cmd) {
    getgrent_count++;
    return mod_create_data(cmd, &test_grp);
}