使用 pam_mkhomedir 和 mysql 为 vsftpd 动态创建目录

使用 pam_mkhomedir 和 mysql 为 vsftpd 动态创建目录

我已经使用以下说明安装了 vsftpd

http://www.camcloud.com/blog/setup-vsftpd-with-virtual-users-using-mysql

我试图在每个用户登录 ftp 服务器时自动/动态地创建目录。

我有以下/etc/pam.d/vsftpd内容才不是自动创建目录。

静态目录配置代码

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

我的问题是如何正确使用pam_mkhomedir使用 mysql 的用户名创建目录。我找到了这个文档https://www.dalemacartney.com/2012/07/30/auto-creation-of-user-home-directories-in-linux/

我想知道这是否是正确的配置,我还想知道如何为目录设置他的用户名。我没有在代码中看到应用用户名的任何地方,或者这只是在幕后发生的事情?

动态目录配置代码

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

答案1

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

如您所见,pam_mkhomedir.so作用于会议等级。这意味着它的作用用户已(由设施auth)进行身份验证。为此,它定义了以下 PAM 特定函数:

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

正如我所说,当用户通过身份验证时会调用此函数。因此,当它检索 PAM 用户句柄时...

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

...它可以访问一个名称经过验证的,现有用户。有了这些信息,模块将能够通过简单的方法检索它需要的内容(主目录的路径)getpwnam(3)图书馆电话:

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

这将返回以下结构,其中填充有关用户的信息:

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 */
};

现在,如果您想知道这些信息来自哪里,请查看/etc/nsswitch.conf。这名称服务开关(NSS) 在此提供有关以下方面的信息名字一般来说(可以是用户名、别名、组、主机……参见nsswitch.conf(5)更多细节)。如果您遵循的指南足够完整,它应该让您配置 PAMNSS:第一个处理身份验证和帐户/会话管理,而另一个仅提供名称信息。换句话说,第一个可以执行读/写操作,而第二个是只读的。

一旦pam_mkhomedir.so检索到用户主目录的路径,它所要做的就是检查它是否存在,如果不存在则创建它:

/* 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, ...);

create_homedir函数是由模块本身定义的,我将其粘贴到这里有点太长了。只把它看作一个大mkdir(2)呼叫,它处理特定情况并确保一切顺利。如果您对更多细节感兴趣,请查看pam_mkhomedir.so的源代码。我用了这个版本的对于我的回答(它是由贾森·冈索普,他的名字也出现在我的pam_mkhomedir.so联机帮助页)。

现在,就我而言,我认为您遵循的指南有点不完整,或者至少,它让您创建的 MySQL 表是:

+----------+-------------+------+-----+---------+----------------+
| 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    |                |
+----------+-------------+------+-----+---------+----------------+

该表可能足够详细,足以让 VSFTPd 正常工作。由于它配置了主根目录,因此可以轻松确定用户的主目录:$ftp_root/username。这实际上是通过local_root参数设置的:

local_root=/home/vsftpd/$USER

不过,pam_mkhomedir.so不是VSFTPd。它不使用这种机制,而是依赖于NSS(通过getpwnam(3))。问题是:您的 MySQL 表没有为 NSS 提供足够的信息来填充struct passwd我们之前看到的信息。为了让 NSS 使用 MySQL 作为源,您需要安装nss-mysql,这需要更大的 MySQL 表。这将需要调整 VSFTPd 配置,但让 VSFTPd 和 nss-mysql 共存应该没有问题。

这个目录给出了最小 nss-mysql 设置的示例。 MySQL用户表定义如下:

+-----------------------+--------------+------+-----+---------+----------------+
| 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    |                |
+-----------------------+--------------+------+-----+---------+----------------+

现在,您自己可能不需要所有这些字段,但请记住struct passwd我们之前看到的结构,并确保 nss-mysql 有足够的数据来填充它:)此外,nss-mysql 配置文件足够灵活,可供您使用任何事物的默认值。

相关内容