2 votos

Vsftpd/pam_userdb.de modo - auto-create virtual directorios home de los usuarios

Programa de instalación:

  • Linux de Amazon EC2
  • vsftpd
  • Autenticación PAM con pam_userdb.así
  • Los nombres de usuario/contraseñas escritas a Berkeley base de datos de usuario desde una fuente externa (lsyncd).

Hay muchos 1000s de usuarios virtuales, hasta la fecha, he manualmente pre-creados los directorios de inicio para todos ellos bajo /home/vsftpd

drwx------    2 vsftpd users     4096 Apr 11 15:28 user0123
drwx------    2 vsftpd users     4096 Apr 11 15:28 user0124
...

#%PAM-1.0
auth required pam_userdb.so db=/usr/local/vsftpd_auth/vsftpd_userdb crypt=none
account required pam_userdb.so db=/usr/local/vsftpd_auth/vsftpd_userdb

Quiero evitar manualmente la pre-creación de los directorios para que las nuevas entradas a la base de datos Berkeley DB funcionará automáticamente sin necesidad de cambiar cada nodo.

La búsqueda de rendimientos preguntas similares para LDAP y MySQL de la autenticación mediante:

  • pam_mkhomedir.así
  • /etc/nsswitch.conf

Pero me parece que no puede poner todo junto para resolver este problema para Berkeley DB.

0voto

Terminé la implementación de un módulo de PAM para vsftpd virtual de los usuarios, basado libremente en pam_mkhomedir.así. Estoy seguro de que puede ser mejorado, pero a continuación es una versión de trabajo.

Uso:

pam_mkhomedir_vsftpd_virt.so [debug] vsftpd_user=<vsftpd_user> basedir=<basedir> 
  • vsftpd_user - normalmente vsftpd
  • basedir - suele estar en /home/vsftpd/

/etc/pam.d/vsftpd:

#%PAM-1.0
auth requisite pam_userdb.so db=/path/to/userdb crypt=none
account requisite pam_userdb.so db=/path/to/userdb
account required pam_mkhomedir_vsftpd_virt.so debug vsftpd_user=vsftpd basedir=/home/vsftpd/
  • He cambiado auth y cuenta para pam_userdb.así que para 'necesarios' para evitar la creación de directorios de si userdb de autenticación no pasa.
  • He implementado el módulo para actuar en el nivel de cuenta debido a que las sesiones no se usa en mi vsftpd contexto.

Compilación:

gcc -fPIC -c pam_mkhomedir_vsftpd_virt.c
gcc -shared -o pam_mkhomedir_vsftpd_virt.so pam_mkhomedir_vsftpd_virt.o -lpam
  • Instalar pam_mkhomedir_vsftpd_virt.así con el resto de los módulos PAM.

Código:

#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <pwd.h>
#include <unistd.h>
#include <syslog.h>

/* For now we will use the service function for account management
 */
#define PAM_SM_ACCOUNT
#include <security/pam_modules.h>

#define MAX_HOMEDIR_SIZE 100

typedef struct {
    bool debug;
    const char *vsftpd_user;
    const char *basedir;
    const char *user;
    char homedir[MAX_HOMEDIR_SIZE+1];
} options_t;

static int parse_input(pam_handle_t *pamh, int flags, int argc, const char **argv, options_t *options) {
    int rc;
    int basedir_len;
    int total_len;
    bool add_slash = false;
    int i;

    /* Retrieve the user name
     */
    rc = pam_get_item(pamh, PAM_USER, (void *)&options->user);

    if (rc != PAM_SUCCESS || options->user == NULL || *(options->user) == '\0') {
        pam_syslog(pamh, LOG_ERR, "cannot retrieve the user name");
        return PAM_USER_UNKNOWN;
    }

    /* Retrieve the module parms
     */
    for (i = 0 ; i < argc; *argv++, i++) {
        if (strcmp(*argv, "debug") == 0) {
            options->debug = true;
        }
        else if (strncmp(*argv, "vsftpd_user=", 12) == 0) {
            options->vsftpd_user = *argv+12;
        }
        else if (strncmp(*argv, "basedir=", 8) == 0) {
            options->basedir = *argv+8;
        }
        else {
            pam_syslog(pamh, LOG_ERR, "unknown option '%s'", *argv);
        }
    }

    /* Validate input
     */
    if (options->vsftpd_user == NULL || *(options->vsftpd_user) == '\0') {
        pam_syslog(pamh, LOG_ERR, "cannot retrieve the vsftpd user");
        return PAM_NO_MODULE_DATA;
    }

    if (options->basedir == NULL || *(options->basedir) == '\0') {
        pam_syslog(pamh, LOG_ERR, "cannot retrieve the base dir");
        return PAM_NO_MODULE_DATA;
    }

    if (options->basedir[0] != '/') {
        pam_syslog(pamh, LOG_ERR, "base dir must start with '/'");
        return PAM_NO_MODULE_DATA;
    }

    /* Check whether we need to add a slash to the path
     */
    basedir_len = (int) strlen(options->basedir);

    if (options->basedir[basedir_len-1] != '/')
        add_slash = true;

    /* Verify we haven't exceeded the max dir length
     */
    total_len = basedir_len + (int) strlen(options->user) + (add_slash?1:0);

    if (total_len > MAX_HOMEDIR_SIZE) {
        pam_syslog(pamh, LOG_ERR, "home directory max length of %d exceeded '%d'", MAX_HOMEDIR_SIZE, total_len);
        return PAM_BUF_ERR;
    }

    /* Create the homedir string
     */
    snprintf(options->homedir, MAX_HOMEDIR_SIZE+1, "%s%s%s", options->basedir, add_slash?"/":"", options->user);

    /* Finished parsing input, log what we got...
     */
    if (options->debug) {
        pam_syslog(pamh, LOG_DEBUG, "vsftpd user '%s'", options->vsftpd_user);
        pam_syslog(pamh, LOG_DEBUG, "base directory '%s'", options->basedir);
        pam_syslog(pamh, LOG_DEBUG, "user '%s'", options->user);
        pam_syslog(pamh, LOG_DEBUG, "home directory '%s'", options->homedir);
    }

    return PAM_SUCCESS;
}

static int create_homedir(pam_handle_t *pamh, options_t *options) {
    struct stat status;
    struct passwd *pwd;
    const char *vsftpd_user = options->vsftpd_user;
    char *homedir = options->homedir;

    /* Retrieve passwd data for the vsftpd user
     */
    pwd = getpwnam(vsftpd_user);

    if (pwd == NULL) {
        pam_syslog(pamh, LOG_ERR, "unable to get user creds for '%s'", vsftpd_user);
        return PAM_CRED_INSUFFICIENT;
    }

    /* Check if home directory already exists
     */
    if (stat(homedir, &status) == 0) {
        if (options->debug)
            pam_syslog(pamh, LOG_DEBUG, "home directory '%s' already exists", homedir);
        return PAM_SUCCESS;
    }

    /* Home directory doesn't exist, create it
     */
    if (options->debug)
        pam_syslog(pamh, LOG_DEBUG, "creating home directory '%s'", homedir);

    if (mkdir(homedir, 0700) != 0) {
        pam_syslog(pamh, LOG_ERR, "unable to create home directory '%s'", homedir);
        return PAM_PERM_DENIED;
    }

    if (chmod(homedir, 0700) != 0 || chown(homedir, pwd->pw_uid, pwd->pw_gid) != 0) {
        pam_syslog(pamh, LOG_ERR, "unable to change perms on directory '%s'", homedir);
        return PAM_PERM_DENIED;
    }

    return PAM_SUCCESS;
}

/* PAM Account Management function
 */
PAM_EXTERN int pam_sm_acct_mgmt(pam_handle_t *pamh, int flags, int argc, const char **argv) {
    options_t options;
    int rc;

    memset(&options, 0, sizeof(options_t));

    rc = parse_input(pamh, flags, argc, argv, &options);

    if (rc != PAM_SUCCESS) {
        return rc;
    }

    rc = create_homedir(pamh, &options);

    if (rc != PAM_SUCCESS) {
        return rc;
    }

    return PAM_SUCCESS;
}

EnMiMaquinaFunciona.com

EnMiMaquinaFunciona es una comunidad de administradores de sistemas en la que puedes resolver tus problemas y dudas.
Puedes consultar las preguntas de otros sysadmin, hacer tus propias preguntas o resolver las de los demás.

Powered by: