Nov 27

[原]proftp+md5的认证及源码编译问题 不指定

linuxing , 15:15 , 网络服务 » 常见服务 , 评论(2) , 引用(0) , 阅读(28923) , Via 本站原创 | |
   上一篇日志介绍了:Proftpd+Clamav+Mysql+MD5+Quota混合配置,其中提到我修改了mod_sql.c,加入了md5认证的函数。下面就说说这方面的内容,并且包括使用源码进行编译需注意的事项。

一、proftpd+md5认证
proftpd的mod_sql.c模块可支持几种认证方式:
引用
Backend:使用Mysql的password()函数生成的密码认证,对于Postgres则没作用
Crypt:使用Unix的Crypt函数生成的密码认证,php等也有该函数可以调用
Empty:接受空密码
OpenSSL:基于{digest-name}hashed-value格式的密码认证,digest-name可以为md5、sha等编码,而hashed-value是使用该编码后经base64转换的字符串
Plaintext:使用明文的密码登陆

一般情况下,使用上述认证方式也已经足够。
不过,当我希望把proftpd的认证与我的论坛用户结合的时候。我发现,论坛的密码是使用md5()函数生成的,仅依靠上述的认证方式并不能快速的解决我的问题。所以,我决定为mod_sql.c模块增加MD5认证方式。(后来发现,这个方法虽好,但绕了个圈,下面有提到)

1、选择MD5认证方式
实际上,在我修改mod_sql.c模块的时候,我发现,让mod_sql.c支持md5认证最少有几种办法:
引用
a、使用外加的md5.h库,并增加认证模块;
b、使用openssl的md5.h库,并增加认证模块;
c、直接使用openssl的md5认证方式。

很明显,第三种方式最简单。但我开始并没有考虑到,所以产生了下面的过程。

2、使用外加的md5库
这个是我第一个Google到的方法,但并没有成功。原因是虽然我找到了这个md5.h库,但编译的时候与openssl自带的md5.h发生变量冲突问题。这里就不详细说明了,需要了解的可以看:
http://www.chinaunix.net/jh/15/688128.html
需要使用到的库文件:

3、使用openssl的md5库
这方式是我受到proftpd论坛的指引:这里,启发而修改的。但可能因mod_sql.c库文件版本问题(已经排除ERROR_INT和PR_ERROR_INT变量的原因),都是没有成功。
不过,由此让我启发到,可以尝试借用openssl的md5.h库。参考:这里
修改4.2.2版本的mod_sql.c文件,加入md5.h库:
引用
# include <openssl/evp.h>
# include <openssl/md5.h>

增加函数:
引用
/* define md5 check mode function */
static char *pt(unsigned char *md);

static modret_t *check_auth_md5(cmd_rec *cmd, const char *c_clear, const char *c_hash)
{
 /*
  * c_clear : plaintext password provided by user
  * c_hash  : combination digest name and hashed
  *           value, of the form {digest}hash
  */
 unsigned char md[MD5_DIGEST_LENGTH];
 char *p;
 int res;

 if (c_hash == NULL) {
/*    sql_log(DEBUG_WARN, "%s", "no terminating '}' for digest");*/
   return PR_ERROR_INT(cmd, PR_AUTH_BADPWD);
 }

 EVP_Digest(c_clear, strlen(c_clear), md, NULL, EVP_md5(), NULL);
 p = pt(md);

 res = strcmp(p, c_hash);

 return res ? PR_ERROR_INT(cmd, PR_AUTH_BADPWD) : PR_HANDLED(cmd);
}

static char *pt(unsigned char *md)
{
        int i;
        static char buf[80];
        for (i=0; i<MD5_DIGEST_LENGTH; i++)
        {
                sprintf(&(buf[i*2]),"%02x",md[i]);
        }
        return(buf);
}

推后原OPENSSL的指针:
引用
/* add MD5 check mode */
#define MD5_AUTH_FLAG         1<<4
#if defined(HAVE_OPENSSL) || defined(PR_USE_OPENSSL)
# define OPENSSL_AUTH_FLAG       1<<5
#endif

并增加认证方式:
引用
/*insert into check structure */
{"MD5", check_auth_md5, MD5_AUTH_FLAG},
#if defined(HAVE_OPENSSL) || defined(PR_USE_OPENSSL)
{"OpenSSL", check_auth_openssl, OPENSSL_AUTH_FLAG},
#endif


补丁文件如下:

使用patch修改即可:
# patch -p0 < mod_sql-4.2.2-md5.patch

4、直接使用openssl的md5认证
这个是我在修改mod_sql.c时想到的,后来经查阅proftpd的文档确认可以使用。
使用该方式时,/etc/proftpd中:
引用
SQLAuthTypes OpenSSL

Mysql中的用户密码使用下面的方法生成:
/bin/echo "{md5}"`/bin/echo -n "password" | openssl dgst -binary -md5 | openssl enc -base64`

或由php函数获得:
引用
$password = "{md5}".base64_encode(pack("H*", md5($password)));

最后,明文为“test”的密码有点类似这样:
引用
# /bin/echo "{md5}"`/bin/echo -n "test" | openssl dgst -binary -md5 | openssl enc -base64`
{md5}CY9rzUYh03PK3k6DJie09g==

其中,{md5}是必须的,用于标识后面base64字符串使用的编码。

※对比
引用
a、4方法,直接使用openssl的md5认证,不需要修改源码,但从论坛获得的密码经类似php的pack函数处理,并加入{md5}前缀;而且,可以支持其他,如sha1的编码,使用{sha1}即可。
b、3方法,需要修改源码,但论坛密码不用经转换即可放入数据库中使用,若要支持其他编码,还需修改源码文件。

最后,因我在bash下找不到可实现php pack的函数的工具,故采用了方法3。(其实,是我不想在crontab中使用php脚本)

二、编译proftpd源码
通常情况下,编译我写的proftpd-1.3.1-4qk.src.rpm包是非常简单的:
# rpmbuild --rebuild proftpd-1.3.1-4qk.src.rpm

但若发现如下的错误:
引用
libtool: link: cannot find the library `/lib/libattr.la'
make: *** [proftpd] Error 1
error: Bad exit status from /var/tmp/rpm-tmp.41285 (%build)

请执行:
# cp /usr/lib/libattr.la /lib/

然后再运行一次rpmbuild。

三、参考文档
http://www.chinaunix.net/jh/15/688128.html
http://ftp.penguin.cz/pub/users/mhi/libmd/
http://forums.proftpd.org/smf/index.php?topic=1691.0http://sirtoozee.spaces.live.com/blog/cns!236c396160b44ea8!129.entry
http://hi.baidu.com/lijt/blog/item/4333ac01a28854071c958349.html
Tags: ,
M.坏男 Email Homepage
2009/04/04 20:09
我不是想解码MD5,我想将kAFQmDzST7DWlj99KOF/cg==(ABC),解码成3cd24fb0d6963f7d,ABC的MD5是3cd24fb0d6963f7d,我就是想了解怎么可能将kAFQmDzST7DWlj99KOF/cg==解码成3cd24fb0d6963f7d,MD5字符串现在不是有人破解成功了吗?
linuxing 回复于 2009/04/06 22:05
关于如何反逆md5算法,网上有介绍,但我是没有看懂。但你可以试试这个网站提供的功能:http://www.cmd5.com/default.aspx
M.坏男 Email Homepage
2009/03/26 16:27
请问如果解码呢?例如abc是kAFQmDzST7DWlj99KOF/cg==,如果解码成MD5
linuxing 回复于 2009/03/27 10:01
^_^,如果能这样解码,就不会用MD5来加密了。MD5是单向的操作的,不能反过来解码。当然,如果你已经有MD5的字符串,那可以写个暴力破解的程序,用循环去尝试,匹配最终的MD5结果,这是当前的解决办法。(国内有专家据说是破解了该算法,但我是没看懂,也没有找到破解程序,目前来说,该算法还是比较安全的。SHA2算法一样)
分页: 1/1 第一页 1 最后页
发表评论
表情
emotemotemotemotemot
emotemotemotemotemot
emotemotemotemotemot
emotemotemotemotemot
emotemotemotemotemot
打开HTML
打开UBB
打开表情
隐藏
记住我
昵称   密码   游客无需密码
网址   电邮   [注册]