在针对Active Directory进行身份验证时,程序正在使用PAM_PERM_DENIED(7),而ssh正在运行

时间:2016-07-21 16:58:12

标签: linux active-directory pam

我正在使用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

2 个答案:

答案 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凭据,因此将执行您的代码。这种方法也有其局限性:

  • 您的程序将始终依赖于运行它的主机的AD集成设置,即正确的Kerberos,PAM和/或Samba配置,
  • &#34;系统-AUTH&#34;是基于RedHat的发行版特定的PAM服务的名称,它可能在基于Debian的系统上丢失。

如果代码只需要使用PAM子系统对AD进行身份验证并使用&#34; system-auth&#34;服务不是必需的,那么以下最小配置可能会有所帮助。同样,如果没有合格的Linux管理员,这将是一个非常冒险的风险:

  1. 在Red Hat上安装pam_krb5软件包,在Debian上安装libpam-krb5。
  2. 在我的Ubuntu框中找到pam_krb5.so的确切位置 /lib/x86_64-linux-gnu/security/pam_krb5.so
  3. 使用以下内容创建新的服务描述文件/etc/pam.d/krb5auth(从man page复制):
  4. 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
    
    1. 测试新服务,我建议使用快速Python会话 python-pam。输入用户名为&#39; greg&#39;或者作为 &#39; greg@JAMIE_AD1.NET' ;,大写有时对Kerberos很重要。
    2. 更改代码中的pam_start()调用以使用pam_start( "krb5auth",并用手指。

答案 1 :(得分:0)

首先,感谢用户无助于他的帮助和努力工作。

最后,问题最终出现在与最终产品相关联的本地库集中的库中。注意:来自系统的。它是一个本地库,不再需要,但覆盖了Active Directory所需的一些PAM功能(例如,LDAP,工作正常。)用户无效,让我有勇气测试配置,然后尝试限制最简单的例子,如下所示(我应该从头开始做!)

上面的例子,当使用命令gcc example.c -o example -lpam编译时,将完全正常。我在这个例子中遇到的问题是我在系统中编译它,它正在输入很多其他库。

从库列表中删除“坏”库(花了一些时间来完成...)后,最终产品运行良好,并且可以正常登录到Active Directory。

感谢所有花了一些时间研究它的人。