使用密码 salt 的 Pure-ftpd 和 Postgreql Auth

发布于 2024-11-27 17:35:18 字数 1442 浏览 0 评论 0原文

我最近开始了设置 PureFTP 服务器的任务。工作中我们使用Postgresql 8.4。该模式本质上可以归结为,

username        text
password        character(40)
password_salt   text

password 存储为 sha1(password + salt) 的哈希值。使用 Postgresql 的 pgcrypto 我可以提供用户名密码并查明用户是否具有身份验证:

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.

还有其他方法可以做到这一点吗?我要么需要将密码输入到查询中,要么取出盐和密码并找到另一种方法在 Pureftp 中编写代码。

显然,我还有另一种选择编写 自定义身份验证模块,但我认为 pg 模块将支持这种基本的加盐。

参考文献

I've recently begun the task of setting up an PureFTP server. At work we use Postgresql 8.4. The schema essentially boils down to,

username        text
password        character(40)
password_salt   text

The password is stored as hash of sha1( password + salt ). Using Postgresql's pgcrypto I can supply a username, and password and find out if the user has auth:

SELECT
 encode( digest( $password ||password_salt, 'sha1' ), 'hex' ) = password
   AS password_correct
 , username
 , password
 , password_salt
FROM contact.person;

Now the issue that I'm having is that such a function would require me getting the password into the query. This doesn't seem possible with Pureftp's current implementation of auth-postgresql. It only supports providing:

\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.

Is there another way I can do this? I either need to get the password into the query, or get the salt and password out and find another way to write the code in Pureftp.

Obviously, I have another option of writing a custom authentication module, but I would think this basic salting would be supported by the pg module.

References

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

丢了幸福的猪 2024-12-04 17:35:18

我也遇到了同样的问题。然而,编写我自己的自定义身份验证模块将是一种矫枉过正,因为可用的 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_pa​​ssword = 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);
}

Then,在加密发生之前:

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);
}

然后我替换了 password 参数在随后调用 crypt 方法(crypt、crypto_hash_md5、crypto_hash_sha1)和使用 (const char*)salted_pa​​ssword

现在剩下要做的就是整理我们分配的内存。特别是带有附加/前置盐的明文密码不应保留在内存中 - 如果您愿意,可以将其称为偏执狂。因此,在 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 版本的 diff 文件。给你! 不过请注意,我稍后在释放 salted_pa​​ssword 时添加了 if (因为我后来才意识到,如果 salted_pa​​ssword 指向密码,这可能会导致错误),所以这不在 diff 中,我懒得更改 diff 文件:/

I had the very same problem. However, writing my own custom authentication module would've been an overkill since the available pgsql auth does nearly everything I want..
Here's what changes I made for it to suit my needs:

In log_pgsql_p.h add static char *salting; and static char *sqlreq_getsalt; and extend the static ConfigKeywords pgsql_config_keywords[] with { "PGSQLSalting", &salting }, and { "PGSQLGetSalt", &sqlreq_getsalt },.

In log_pgsql.h I added #define SALT_SQL_APPEND "append", #define SALT_SQL_PREPEND "prepend" and #define SALT_SQL_NONE "none".

In log_pgsql.c I then made the following changes in the pw_psql_check function:

I declared const char *salt = NULL; and char * salted_password = NULL; at the top.
Directly before spwd gets assigned the result of the query to sqlreq_getpw I added

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);
}

Then, before the encryption takes place:

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);
}

And then I replaced the password argument in subsequent calls to the crypt-methods (crypt, crypto_hash_md5, crypto_hash_sha1) and the strcasecmp for 'cleartext' with (const char*)salted_password.

Now all that's left to do is tidying up the memory we allocated. Especially the plaintext-password with appended/prepended salt shouldn't remain in memory - call it paranoia if you want. So after the bye: label add

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);
}

With these changes you now have two additional parameters in your config file available:

  • PGSQLSalting: Accepts 'append' (appends the salt to the pw), 'prepend' and 'none' (without the apostrophe)
  • PGSQLGetSalt: Here you specify the field in your db to fetch the salt from, much like with the crypted password you need to retrieve via PGSQLGetPw.

Edit: Oh, and don't forget to free the allocated memory at the end of the function!

I also can provide a diff file that works for the release 1.0.36.. here you go! Beware though, i added the if around the freeing of salted_password later (because i only later realized how this might lead to an error if salted_password points to password), so this is not in the diff and I'm too lazy to change the diff file :/

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文