我正在使用Active Domain jamie_ad1.net
,我在那里有一个用户greg。
当我ssh -l greg@jamie_ad1.net x.x.x.x
我成功登录时
但是,当我在我的程序中验证用户时,我的process_user()
函数(下面)返回错误7(PAM_PERM_DENIED
- 调用者没有所需的权限。)
我做错了什么?请注意,在ssh
期间,正在使用/etc/pam.d/system-auth
。我在我的程序中也使用相同的PAM服务名"system_auth"
(我也使用了“sshd”和“login” - 都失败了。)
static int process_user( const char* uname, const char* pwd )
{
int rv = 0 ;
struct pam_conv conv ;
pam_handle_t* pamh = NULL;
conv.conv = &pamauth_conv ;
conv.appdata_ptr = ( void* )pwd ;
if (
(( rv = pam_start( "system-auth", uname, &conv, &pamh )) == PAM_SUCCESS )
&& (( rv = pam_acct_mgmt(pamh, PAM_SILENT | PAM_DISALLOW_NULL_AUTHTOK )) == PAM_SUCCESS )
&& (( rv = pam_authenticate( pamh, PAM_SILENT | PAM_DISALLOW_NULL_AUTHTOK )) == PAM_SUCCESS )
)
...
pam_end( pamh, rv ) ;
...
}
下面我展示process_user()
使用的convesation功能
在gdb
下,我看到num_msg
为1,msg[ 0 ]->msg
为"Password: "
,并且该函数正确设置p[ 0 ].resp
为密码(我已检查过)密码是否正确。)
static int pamauth_conv( int num_msg, const struct pam_message** msg, struct pam_response** resp, void* appdata_ptr )
{
int rv = PAM_SUCCESS ;
struct pam_response* p = NULL ;
int i ;
p = calloc( num_msg, sizeof( struct pam_response )) ;
if ( p == NULL )
rv = PAM_BUF_ERR ;
else
{
for ( i = 0; ( rv == PAM_SUCCESS ) && ( i < num_msg ); i++ )
if ( strcmp( msg[ i ]->msg, "Password: " ) == 0 ) /* support password conversation only */
{
p[ i ].resp = strdup(( char* )appdata_ptr ) ;
if ( p[ i ].resp == NULL )
rv = PAM_BUF_ERR;
}
}
if ( rv == PAM_SUCCESS )
*resp = p ;
else if ( p )
{
for ( i = 0; i < num_msg; i++ )
if ( p[ i ].resp )
free( p[ i ].resp ) ;
free( p ) ;
}
return rv ;
}
注意: pam_acct_mgmt()
调用返回SUCCESS,因此确认greg@jamie_ad1.net用户存在。投诉是pam_authenticate()
。
/etc/pam.d/system-auth
的内容,与`/etc/pam.d/password-auth'完全相同:
#%PAM-1.0
# This file is auto-generated.
# User changes will be destroyed the next time authconfig is run.
auth required pam_env.so
auth sufficient pam_fprintd.so
auth sufficient pam_unix.so nullok try_first_pass
auth requisite pam_succeed_if.so uid >= 500 quiet
auth sufficient pam_ldap.so use_first_pass
auth sufficient pam_winbind.so use_first_pass
auth required pam_deny.so
account required pam_unix.so broken_shadow
account sufficient pam_localuser.so
account sufficient pam_succeed_if.so uid < 500 quiet
account [default=bad success=ok user_unknown=ignore] pam_ldap.so
account [default=bad success=ok user_unknown=ignore] pam_winbind.so
account required pam_permit.so
password requisite pam_cracklib.so try_first_pass retry=3 type=
password sufficient pam_unix.so sha512 shadow nullok try_first_pass use_authtok
password sufficient pam_ldap.so use_authtok
password sufficient pam_winbind.so use_authtok
password required pam_deny.so
session optional pam_keyinit.so revoke
session required pam_limits.so
session optional pam_oddjob_mkhomedir.so umask=0077
session [success=1 default=ignore] pam_succeed_if.so service in crond quiet use_uid
session required pam_unix.so
session optional pam_ldap.so
/etc/pam.d/sshd
的内容
#%PAM-1.0
auth需要pam_sepermit.so
auth包括password-auth
帐户需要pam_nologin.so
帐户包括密码验证
密码包括password-auth
session required pam_selinux.so close
session required pam_loginuid.so
session required pam_selinux.so open env_params
session optional pam_keyinit.so force revoke
session include password-auth
session required pam_lastlog.so showfailed
答案 0 :(得分:4)
使用SSH客户端登录是有效的,因为它不使用PAM子系统在外部AD主机上进行身份验证。 SSH客户端在其配置(GSSAPIAuthentication
或/etc/ssh/ssh_config
或/etc/ssh_config
)中检查~/.ssh/config
标志并调用GSSAPI库。 GSSAPI使用Kerberos,它在运行程序的Linux主机上安装并正确配置。
如果程序的目的是针对Active Directory验证用户凭据,那么它应该执行相同的操作并调用GSSAPI。另一种方法(可能更容易使用)可以通过LDAP API进行身份验证。请注意,AD安装有时会拒绝通过未加密的LDAP进行简单的纯文本身份验证,并且需要基于SASL的身份验证或SSL连接。
在您的代码中调用pam_start( "system-auth",
意味着&#34;以与此Linux主机上其他基于PAM的服务相同的方式验证用户&#34;。为了使其工作,应该联系Linux主机管理员(配置Kerberos客户端的那个)并让她/他完成integration with the Active Directory。成功设置的结果是基于PAM的服务(如login,su,sshd等)将开始理解AD凭据,因此将执行您的代码。这种方法也有其局限性:
如果代码只需要使用PAM子系统对AD进行身份验证并使用&#34; system-auth&#34;服务不是必需的,那么以下最小配置可能会有所帮助。同样,如果没有合格的Linux管理员,这将是一个非常冒险的风险:
pam_krb5.so
的确切位置
/lib/x86_64-linux-gnu/security/pam_krb5.so
。/etc/pam.d/krb5auth
(从man page复制):auth sufficient /lib/x86_64-linux-gnu/security/pam_krb5.so minimum_uid=1000 session required /lib/x86_64-linux-gnu/security/pam_krb5.so minimum_uid=1000 account required /lib/x86_64-linux-gnu/security/pam_krb5.so minimum_uid=1000 password sufficient /lib/x86_64-linux-gnu/security/pam_krb5.so minimum_uid=1000
pam_start( "krb5auth",
并用手指。答案 1 :(得分:0)
首先,感谢用户无助于他的帮助和努力工作。
最后,问题最终出现在与最终产品相关联的本地库集中的库中。注意:来自系统的不。它是一个本地库,不再需要,但覆盖了Active Directory所需的一些PAM功能(例如,LDAP,工作正常。)用户无效,让我有勇气测试配置,然后尝试限制最简单的例子,如下所示(我应该从头开始做!)
上面的例子,当使用命令gcc example.c -o example -lpam
编译时,将完全正常。我在这个例子中遇到的问题是我在系统中编译它,它正在输入很多其他库。
从库列表中删除“坏”库(花了一些时间来完成...)后,最终产品运行良好,并且可以正常登录到Active Directory。
感谢所有花了一些时间研究它的人。