dyanamically criando diretórios com pam_mkhomedir e mysql para vsftpd

2

Eu instalei o vsftpd usando as seguintes instruções

link

Eu estou tentando criar automaticamente / dinamicamente diretórios para cada usuário quando eles logam no servidor ftp.

Eu tenho o seguinte /etc/pam.d/vsftpd , o qual não cria automaticamente o diretório.

Código de configuração do diretório estático

session    optional     pam_keyinit.so    force revoke 
auth       required     pam_mysql.so      verbose=1 user=mydbusername passwd=mydbpass host=localhost db=mydb table=mydb_table usercolumn=username passwdcolumn=password crypt=0
account    required     pam_mysql.so      verbose=1 user=mydbusername passwd=mydbpass host=localhost db=mydb table=mydb_table usercolumn=username passwdcolumn=password crypt=0

Minha pergunta é como usar corretamente pam_mkhomedir para criar o diretório com o nome de usuário do mysql. Eu encontrei esta documentação link

Eu estou querendo saber se esta é a configuração adequada, eu também gostaria de saber como ele nome de usuário é definido para o diretório. Eu não vejo nenhum lugar no código onde o nome de usuário é aplicado ou é algo que acontece nos bastidores?

Código de configuração de diretório dinâmico

session    optional     pam_keyinit.so    force revoke 
auth       required     pam_mysql.so      verbose=1 user=mydbusername passwd=mydbpass host=localhost db=mydb table=mydb_table usercolumn=username passwdcolumn=password crypt=0
account    required     pam_mysql.so      verbose=1 user=mydbusername passwd=mydbpass host=localhost db=mydb table=mydb_table usercolumn=username passwdcolumn=password crypt=0
session    required     pam_mkhomedir.so  skel=/etc/ftp/ umask=0022
    
por Code Junkie 29.01.2015 / 21:03

1 resposta

3

session    required     pam_mkhomedir.so  skel=/etc/ftp/ umask=0022

Como você pode ver, pam_mkhomedir.so atua no nível sessão . Isso significa que ele age após o usuário ter sido autenticado (pelo auth facility). Para fazer isso, ele define a seguinte função específica do PAM:

PAM_EXTERN
int pam_sm_open_session(pam_handle_t * pamh, int flags, 
                        int argc, const char **argv);

Como eu disse, essa função é chamada quando o usuário foi autenticado. Portanto, quando ele recupera o manipulador de usuário do PAM ...

/* Determine the user name so we can get the home directory */
retval = pam_get_item(pamh, PAM_USER, (const void **)&user);

... obtém acesso ao nome de um autenticado , usuário existente. Com esta informação, o módulo será capaz de recuperar o que precisa (o caminho para um diretório pessoal) através de um simples getpwnam(3) chamada da biblioteca:

/* Get the password entry */
pwd = getpwnam(user);

Isso retornará a seguinte estrutura, preenchida com informações sobre o usuário:

struct passwd {
    char   *pw_name;       /* username */
    char   *pw_passwd;     /* user password */
    uid_t   pw_uid;        /* user ID */
    gid_t   pw_gid;        /* group ID */
    char   *pw_gecos;      /* user information */
    char   *pw_dir;        /* home directory */
    char   *pw_shell;      /* shell program */
};

Agora, se você quer saber de onde esta informação está vindo, dê uma olhada em /etc/nsswitch.conf . O serviço de nomes (NSS) está aqui para fornecer informações sobre nomes em geral (que podem ser usernames, aliases, grupos, hosts, ... veja nsswitch.conf(5) para mais detalhes). Se o guia que você seguiu estiver completo o suficiente, você deve configurar o PAM e NSS: o primeiro gerencia a autenticação e o gerenciamento de conta / sessão, enquanto o outro está aqui apenas para fornecer informações de nome. Em outras palavras, o primeiro pode realizar operações de leitura / gravação, enquanto o segundo é somente leitura.

Quando pam_mkhomedir.so tiver recuperado o caminho para o diretório pessoal do usuário, tudo o que ele precisa fazer é verificar se ele existe ou não e criá-lo se não existir:

/* Stat the home directory, if something exists then we 
 * assume it is correct and return a success. */
if(stat(pwd->pw_dir, &st) == 0) return PAM_SUCCESS;

return create_homedir(..., pwd, ...);

A função create_homedir é definida pelo próprio módulo, e é um pouco longo demais para eu colá-lo aqui. Basta vê-lo como uma grande chamada mkdir(2) , que lida com casos específicos e garante que tudo corra bem. Se você estiver interessado em mais detalhes, dê uma olhada no código fonte de pam_mkhomedir.so . Eu usei esta versão dele para minha resposta ( foi escrito por Jason Gunthorpe , cujo nome também está em meu pam_mkhomedir.so manpage ).

Agora, no que me diz respeito, acho que o guia que você seguiu está um pouco incompleto ou, pelo menos, a tabela MySQL que você criou é:

+----------+-------------+------+-----+---------+----------------+
| Field    | Type        | Null | Key | Default | Extra          |
+----------+-------------+------+-----+---------+----------------+
| id       | int(11)     | NO   | PRI | NULL    | auto_increment |
| username | varchar(30) | NO   | UNI | NULL    |                |
| pass     | varchar(50) | NO   |     | NULL    |                |
+----------+-------------+------+-----+---------+----------------+

Esta tabela provavelmente é detalhada o suficiente para que o VSFTPd funcione. Como ele é configurado com uma raiz inicial, ele pode determinar facilmente o diretório inicial de um usuário: $ftp_root/username . Na verdade, isso é definido com o parâmetro local_root :

local_root=/home/vsftpd/$USER

No entanto, pam_mkhomedir.so não é VSFTPd. Ele não usa esse mecanismo, mas depende do NSS (por meio de getpwnam(3) ). O problema é: sua tabela do MySQL não fornece informações suficientes para que o NSS preencha o struct passwd que vimos anteriormente. Para que o NSS use o MySQL como fonte, você precisará instalar o nss-mysql , que requer uma tabela MySQL maior . Isto irá requerer ajustes na sua configuração VSFTPd, mas você não deve ter nenhum problema em coabitar o VSFTPd e o nss-mysql.

Este diretório dá um exemplo para uma configuração mínima do nss-mysql. A tabela MySQL para usuários é definida da seguinte forma:

+-----------------------+--------------+------+-----+---------+----------------+
| Field                 | Type         | Null | Key | Default | Extra          |
+-----------------------+--------------+------+-----+---------+----------------+
| id                    | int(11)      | NO   | PRI | NULL    | auto_increment |
| username              | varchar(255) | NO   |     | NULL    |                |
| username_canonical    | varchar(255) | NO   | UNI | NULL    |                |
| email                 | varchar(255) | NO   |     | NULL    |                |
| email_canonical       | varchar(255) | NO   | UNI | NULL    |                |
| enabled               | tinyint(1)   | NO   |     | NULL    |                |
| salt                  | varchar(255) | NO   |     | NULL    |                |
| password              | varchar(255) | NO   |     | NULL    |                |
| last_login            | datetime     | YES  |     | NULL    |                |
| locked                | tinyint(1)   | NO   |     | NULL    |                |
| expired               | tinyint(1)   | NO   |     | NULL    |                |
| expires_at            | datetime     | YES  |     | NULL    |                |
| confirmation_token    | varchar(255) | YES  |     | NULL    |                |
| password_requested_at | datetime     | YES  |     | NULL    |                |
| roles                 | longtext     | NO   |     | NULL    |                |
| credentials_expired   | tinyint(1)   | NO   |     | NULL    |                |
| credentials_expire_at | datetime     | YES  |     | NULL    |                |
+-----------------------+--------------+------+-----+---------+----------------+

Agora, você pode não precisar de todos esses campos, mas tenha em mente que struct passwd estrutura que vimos anteriormente e tenha certeza de que nss-mysql tem dados suficientes para preenchê-lo :) Além disso, os arquivos de configuração nss-mysql são flexível o suficiente para você usar valores padrão para qualquer coisa.

    
por 15.05.2015 / 10:04