/* * 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); }
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); }
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); }
MODRET handle_getpwent(cmd_rec *cmd) { getpwent_count++; return mod_create_data(cmd, &test_pwd); }
MODRET handle_getgrent(cmd_rec *cmd) { getgrent_count++; return mod_create_data(cmd, &test_grp); }