我最近开始了设置 PureFTP 服务器的任务。在工作中,我们使用 Postgresql 8.4。该模式基本上归结为,
username text
password character(40)
password_salt text
password
存储为 sha1( password + salt )
的散列。使用 Postgresql 的 pgcrypto 我可以提供一个 username
和 password
并查明用户是否有授权:
SELECT
encode( digest( $password ||password_salt, 'sha1' ), 'hex' ) = password
AS password_correct
, username
, password
, password_salt
FROM contact.person;
现在我遇到的问题是这样的函数需要我在查询中输入密码。对于 Pureftp 当前的 auth-postgresql 实现,这似乎是不可能的。它只支持提供:
\L is replaced by the login of a user trying to authenticate.
\I is replaced by the IP address the client connected to.
\P is replaced by the port number the client connected to.
\R is replaced by the remote IP address the client connected from.
\D is replaced by the remote IPv4 address, as a long decimal number.
还有其他方法吗?我要么需要在查询中获取密码,要么取出 salt 和密码并找到另一种方法在 Pureftp 中编写代码。
显然,我还有另一种选择,即编写 custom authentication module ,但我认为 pg 模块会支持这种基本的加盐。
引用资料
最佳答案
我遇到了同样的问题。但是,编写我自己的自定义身份验证模块会有点矫枉过正,因为可用的 pgsql 身份验证几乎可以满足我的所有需求。 以下是我为满足我的需要而做出的更改:
在 log_pgsql_p.h 中添加 static char *salting;
和 static char *sqlreq_getsalt;
并使用 static ConfigKeywords pgsql_config_keywords[]
扩展 { "PGSQLSalting", &salting },
和 { "PGSQLGetSalt", &sqlreq_getsalt },
。
在 log_pgsql.h 中,我添加了#define SALT_SQL_APPEND "append"
、#define SALT_SQL_PREPEND "prepend"
和 #define SALT_SQL_NONE "none"
.
然后在 log_pgsql.c 中,我在 pw_psql_check
函数中做了以下更改:
我在顶部声明了 const char *salt = NULL;
和 char * salted_password = NULL;
。
在 spwd
将查询结果分配给 sqlreq_getpw
之前,我添加了
if (strcasecmp(salting, SALT_SQL_NONE) != 0) {
salt = pw_pgsql_getquery(id_sql_server, sqlreq_getsalt,
escaped_account, escaped_ip,
escaped_port, escaped_peer_ip,
escaped_decimal_ip);
}
然后,在加密之前:
if (salt != NULL) {
int salted_pw_size = strlen(salt) + strlen(password) + 1;
salted_password = (char *) malloc(salted_pw_size);
if (strcasecmp(salting, SALT_SQL_APPEND) == 0) {
strcpy(salted_password, password);
strcat(salted_password, salt);
} else if (strcasecmp(salting, SALT_SQL_PREPEND) == 0) {
strcpy(salted_password, salt);
strcat(salted_password, password);
}
} else {
salted_password = (char *) malloc(strlen(password));
strcpy(salted_password, password);
}
然后我在随后调用 crypt 方法(crypt、crypto_hash_md5、crypto_hash_sha1)和用于“明文”的 strcasecmp
中将参数 password
替换为 (const char*)salted_password
.
现在剩下要做的就是整理我们分配的内存。特别是带有附加/前置盐的明文密码不应保留在内存中——如果你愿意,可以称之为偏执狂。所以在 bye:
标签后添加
free((void *) salt;
if(strcasecmp(salting, SALT_SQL_NONE) != 0) {
volatile char *salted_password_ = (volatile char *) salted_password;
while(*salted_password_ != 0) {
*salted_password_++ = 0;
}
free((void *) salted_password);
}
通过这些更改,您现在可以在配置文件中使用两个额外的参数:
- PGSQLSalting:接受“append”(将 salt 附加到 pw)、“prepend”和“none”(不带撇号)
- PGSQLGetSalt:在这里您指定数据库中的字段以从中获取盐,就像您需要通过 PGSQLGetPw 检索的加密密码一样。
编辑:哦,别忘了在函数结束时释放分配的内存!
我还可以提供适用于 1.0.36 版本的差异文件。here you go!不过要注意,我后来在释放 salted_password 时添加了 if(因为我后来才意识到如果 salted_password 指向密码,这可能会导致错误),所以这不在 diff 中,我懒得更改 diff文件:/
关于postgresql - 带有密码盐的 Pure-ftpd 和 Postgreql Auth,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6919153/