LDAP/SASL/GSSAPI/Kerberos编程API(3)--LDAP/SASL
2021-03-15 00:33
标签:char tgs async file lib util uid 绑定 回调 二.SASL/GSSAPI(不含krb5库) 2.解析 可返回的值还有: 2) 3)跟踪测试 3.编译 4.运行 SASL的GSSAPI不提供交互输入口令,而是直接读取票据.我们可用kinit来先生成票据,下面krblinlin是Kerberos用户主体 linlin@vmcln:~$ ls /tmp 再次执行,已成功读出ldap目录信息 三.SASL/GSSAPI + krb5 2.解析 2)本文将测试MEMORY、FILE两种类型票据 3)代码#13处不会销毁票据(包括内存票据、文件票据) 3.编译 2)编译成文件票据执行文件testldapkrb_f 4.服务端环境 5.在客户机上运行 2)安装mit库 或者下载debian 9 libsasl2-modules-gssapi-heimdal软件包安装到debian 11 3)客户机配置 为了匹配ldap应用服务ldap/vmkdc主体,/etc/hosts要增加一行如下: linlin@vmcln:~$ cat /etc/resolv.conf linlin@vmcln:~$ cat /etc/krb5.conf 4)执行票据是内存类型的命令 5)执行票据是文件类型的命令 无需设环境变量,命令生成票据和SASL/GSSAPI默认都是/tmp/krb5cc_1000 可见在/tmp生成了票据krb5cc_1000文件 再用ldap工具测试 加-d调试 查看vmkdc的kdc log 四.跟踪调试 1.debian 10版本以上(新版)libsasl2-modules-gssapi-heimdal的BUG 测试文件票据 说明新版libsasl2-modules-gssapi-heimdal对内存票据有问题,不是生成的内存票据有问题,而是读取内存票据的功能有BUG 2)用新版libsasl2-modules-gssapi-mit或者debian 9(旧版)libsasl2-modules-gssapi-heimdal代替新版libsasl2-modules-gssapi-heimdal,读取内存票据已正常 2.环境变量 1.2)/etc/krb5.conf添加一行 default_ccache_name = KEYRING:persistent:%{uid} linlin@vmcln:~$ ./testldapkrb_m 2)运行之前设环境变量 也可在程序源码里开头设置环境变量,这样执行命令就不需输入环境变量 我没去研究/etc/krb5.conf里能否配置default_ccache_name为进程内存票据以便不需设环境变量,即使能也不妥,因为其它的krb5程序会用到/etc/krb5.conf, 3)小结: 3.客户端无配置/etc/krb5.conf LDAP/SASL/GSSAPI API能否在程序里指定realm,我没去探究,在此就按提示配置/etc/krb5.conf解决 4.关于ldap/vmkdc@CTP.NET还是ldap/vmkdc.ctp.net@CTP.NET的匹配问题 1)在客户机vmcln(192.168.1.20)上测试 1.1)查看配置 或者 即/etc/hosts不再添加一行 192.168.1.11 vmkdc 解析主机,而是完全由dns解析,DNS服务器正向解析vmkdc、vmkdc.ctp.net为192.168.1.11,反向解析192.168.1.11为vmkdc.ctp.net 1.2)测试 linlin@vmcln:~$ ldapwhoami -Y GSSAPI -h 192.168.1.11 查看kdc log 1.3)往vmkdc添加ldap/vmkdc.ctp.net主体再测试 导出到krb5.keytab 应该是追加而不是覆盖,查看可见包含了ldap/vmkdc@CTP.NET和ldap/vmkdc.ctp.net@CTP.NET 回到客户机 查看kdc log 2)在服务器vmkdc(192.168.1.11)本机上测试 2.1)代码#12处为连接到地址192.168.1.11 查看kdc log 2.2)代码#12处改为 ldap_initialize(&ld,"ldap://127.0.0.1/"),即连接本地服务器 当/etc/resolv.conf为空 linlin@vmkdc:~$ KRB5CCNAME="MEMORY:dhcp_ld_krb5_cc" ./testldapkrb_m_local 查看kdc log 将resolv.conf改为vmkdc同网段但不存在的地址 为何连接本地127.0.0.1时SASL/GSSAPI却能拼接出正确的ldap/vmkdc ? 临时改主机名 查看主机名结果为vmabc.efg 查看kdc log 五.SASL/GSSAPI客户程序总结: 3.客户机拼接出的app/xxx.yyy和应用服务器的app/xxx.yyy要匹配一致 4.在规划域、主机名时,尽可能服务器、客户机、应用服务主体、DNS解析都设为全限定名,这样可省却不可预知的陷阱. 六.后记 will disable reverse DNS lookup on clients. The default setting is “true”. 不知设 rdns = false 禁用反向解析是不是可以解决客户机和应用服务器主体不匹配问题?留待各位读者探索 LDAP/SASL/GSSAPI/Kerberos编程API(3)--LDAP/SASL 标签:char tgs async file lib util uid 绑定 回调 原文地址:https://blog.51cto.com/13752418/2476879
客户机:vmcln(192.168.1.20)
root@vmcln:/# apt-get install libkrb5-dev libldap2-dev libsasl2-dev
1.源代码
//源文件名:testsasl.c#include
1)回调函数
代码#1处直接返回LDAP_SUCCESS即可,ldap_sasl_interactive_bind_s就成功.这个是最简单能成功的回调函数代码,应该也是很不规范.至于如何编写完善的回调函数代码,其实我也不懂
LDAP_PARAM_ERROR、LDAP_OTHER、LDAP_PARAM_ERROR,这几个返回错误,ldap_sasl_interactive_bind_s便失败.
代码#2处不能直接填LDAP_SUCCESS或NULL,否则会出错提示‘Error: Local error‘,必需填为回调函数
ldap_sasl_interactive_bind_s的GSSAPI会读取/etc/krb5.conf和票据/tmp/krb5cc_1000
linlin@vmcln:~$ gcc -o testsasl testsasl.c -lldap -llber -lsasl2
linlin@vmcln:~$ ls /tmp
(空)
linlin@vmcln:~$ ./testsasl
SASL/GSSAPI authentication started 开始SASL/GSSAPI认证
Error: Local error
Additional info: SASL(-1): generic failure: GSSAPI Error: Unspecified GSS failure. Minor code may provide more information (No Kerberos credentials available (default cache: FILE:/tmp/krb5cc_1000))
linlin@vmcln:~$
失败,提示没有有效票据,找不到/tmp/krb5cc_1000
linlin@vmcln:~$ kinit --no-forwardable krblinlin
krblinlin@CTP.NET‘s Password: 输入口令
linlin@vmcln:~$
因为我的KDC服务端是heimdal,需带参数no-forwardable.如果服务端是mit则不用带参数no-forwardable
krb5cc_1000
linlin@vmcln:~$
已见到票据,由kinit生成
linlin@vmcln:~$ ./testsasl
SASL/GSSAPI authentication started
SASL username: krblinlin@CTP.NET 这里可以看到krblinlin用户,即testsasl程序里不传入用户、口令,而是通过票据
SASL SSF: 56
SASL data security layer installed.
Success!
dn: ou=dns,dc=ctp,dc=net
attribute = objectClass
attribute = ou
...
基于上面代码增加krb5用户输入口令登录认证,目的是程序自己生成票据
1.源代码
//源文件名:testldapkrb.c #include
1)代码#11处,票据可以是
MEMORY : 进程内存里的票据,随进程的结束而销毁
FILE : 文件系统上的票据,不会自动销毁,即使系统重启,所以要防范票据在生存期内被复制走盗用登录.当然票据通常是放在/tmp下,一般系统的启动/关闭都会清理/tmp目录.
在#11处分别编译
‘MEMORY ‘的名称随便定,我不清楚是否有规范的名称
‘FILE‘指定/tmp/krb5cc_1000作为票据文件.当前登录用户linlin的uid为1000,在当前用户运行有关的SASL/GSSAPI,默认票据路径文件/tmp/krb5cc_1000.所以上面程序为配合默认路径文件,写死了 "FILE:/tmp/krb5cc_1000" 与之保持一致,运行命令就不用再指定环境变量(除非程序生成票据与默认路径文件不一致)
1)编译成内存票据执行文件testldapkrb_m
#11处,按"MEMORY:dhcp_ld_krb5_cc"编译
linlin@vmcln:~$ gcc -o testldapkrb_m testldapkrb.c -lldap -llber -lsasl2 -lkrb5
#11处,改为"FILE:/tmp/krb5cc_1000"编译
linlin@vmcln:~$ gcc -o testldapkrb_f testldapkrb.c -lldap -llber -lsasl2 -lkrb5
krb5+ldap+dns在同一台机器上vmkdc(192.168.1.11)
机器名:vmkdc
ldap应用服务主体:ldap/vmkdc@CTP.NET
1)客户端环境
平台 : debian 11
sasl的modules: mit或heimdal
root@vmcln:/# apt-get install libsasl2-modules-gssapi-mit
在客户机vmcln(192.168.1.20)上是按#12处连接LDAP服务器192.168.1.11
192.168.1.11 vmkdc
domain ctp.net
search ctp.net
nameserver 192.168.1.11
linlin@vmcln:~$
显示指定了DNS服务器192.168.1.11
[libdefaults]
default_realm = CTP.NET
linlin@vmcln:~$
/etc/krb5.conf仅配置default_realm 这个就可,KDC地址可通过DNS的SRV(服务)资源记录获得
在命令之前要设环境变量,完整命令如下:
linlin@vmcln:~$ KRB5CCNAME="MEMORY:dhcp_ld_krb5_cc" ./testldapkrb_m
...
Successfully store creds
SASL/GSSAPI authentication started
SASL username: krblinlin@CTP.NET
SASL SSF: 56
SASL data security layer installed.
Success!
dn: ou=dns,dc=ctp,dc=net
attribute = objectClass
attribute = ou
...
已成功
linlin@vmcln:~$ ls /tmp
(空)
linlin@vmcln:~$
linlin@vmcln:~$ ./testldapkrb_f
begin get init creds password
get init creds password OK
Successfully store creds 生成了票据
SASL/GSSAPI authentication started
SASL username: krblinlin@CTP.NET
SASL SSF: 56
SASL data security layer installed.
Success!
dn: ou=dns,dc=ctp,dc=net
attribute = objectClass
attribute = ou
...
已成功
linlin@vmcln:~$ ls /tmp
krb5cc_1000
linlin@vmcln:~$ ldapwhoami -Y GSSAPI -h 192.168.1.11
SASL/GSSAPI authentication started
SASL username: krblinlin@CTP.NET
SASL SSF: 56
SASL data security layer installed.
dn:uid=krblinlin,cn=gssapi,cn=auth
linlin@vmcln:~$
可见ldapwhoami用到上面程序生成的票据krb5cc_1000已成功
linlin@vmcln:~$ ldapwhoami -Y GSSAPI -h 192.168.1.11 -d -1
ldap_create
ldap_url_parse_ext(ldap://192.168.1.11)
ldap_sasl_interactive_bind: user selected: GSSAPI
ldap_int_sasl_bind: GSSAPI
ldap_new_connection 1 1 0
ldap_int_open_connection
ldap_connect_to_host: TCP 192.168.1.11:389
ldap_new_socket: 3
ldap_prepare_socket: 3
ldap_connect_to_host: Trying 192.168.1.11:389
ldap_pvt_connect: fd: 3 tm: -1 async: 0
attempting to connect:
connect success
ldap_int_sasl_open: host=vmkdc 注意此处主机名,应该是反向解析192.168.1.11出vmkdc
SASL/GSSAPI authentication started
ldap_sasl_bind
ldap_send_initial_request
ldap_send_server_request
ber_scanf fmt ({it) ber:
...
TGS-REQ krblinlin@CTP.NET from IPv4:192.168.1.20 for ldap/vmkdc@CTP.NET [canonicalize]
注意日志出现的‘ldap/vmkdc@CTP.NET‘,应该是客户端通过/etc/hosts反向解析ldap服务器(192.168.1.11,本实验是krb5和ldap在同一台机器vmkdc上)拼接出ldap/vmkdc@CTP.NET,并与ldap的应用服务主体(ldap/vmkdc@CTP.NET)一致
上面是已先给出正常运行的结论,是我逐步调试后的结果.实际调试的过程是很凌乱,下面整理总结第三章节(SASL/GSSAPI + krb5)调试过程
1)新版libsasl2-modules-gssapi-heimdal
测试内存票据
linlin@vmcln:~$ KRB5CCNAME="MEMORY:dhcp_ld_krb5_cc" ./testldapkrb_m
...
Successfully store creds
SASL/GSSAPI authentication started
Error: Local error
Additional info: SASL(-1): generic failure: GSSAPI Error: Miscellaneous failure (see text) (Did not find a plugin for ccache_ops)
内存票据失败,根据所提示的‘Did not find a plugin for ccache_ops‘查看源码、搜索网上资料,找不到ccache_ops问题所在
linlin@vmcln:~$ ls /tmp
(空)
linlin@vmcln:~$ ./testldapkrb_f
...
Successfully store creds
SASL/GSSAPI authentication started
SASL username: krblinlin@CTP.NET
SASL SSF: 56
SASL data security layer installed.
Success!
dn: ou=dns,dc=ctp,dc=net
attribute = objectClass
attribute = ou
...
文件票据正常
root@vmcln:/home/linlin#
linlin@vmcln:~$ KRB5CCNAME="MEMORY:dhcp_ld_krb5_cc" ./testldapkrb_m
...
Successfully store creds
SASL/GSSAPI authentication started
SASL username: krblinlin@CTP.NET
SASL SSF: 256
SASL data security layer installed.
Success!
dn: ou=dns,dc=ctp,dc=net
attribute = objectClass
attribute = ou
...
1)不设环境变量
1.1)/etc/krb5.conf缺省的default_ccache_name
linlin@vmcln:~$ ./testldapkrb_m
...
Successfully store creds 到此步是通过krb5密码认证成功的,并已生成了票据在内存
SASL/GSSAPI authentication started 开始LDAP/SASL/GSSAPI认证,在此失败,提示找不到票据
Error: Local error
Additional info: SASL(-1): generic failure: GSSAPI Error: Miscellaneous failure (see text) (get-principal lstat(/tmp/krb5cc_1000))
根据错误提示,无环境变量,SASL/GSSAPI 默认是/tmp/krb5cc_1000
{uid}表示登录用户的uid号,如当前用户linlin的uid为1000
...
Successfully store creds
SASL/GSSAPI authentication started
Error: Local error
Additional info: SASL(-1): generic failure: GSSAPI Error: Unspecified GSS failure. Minor code may provide more information (No Kerberos credentials available (default cache: KEYRING:persistent:1000))
从错误提示已说明是按krb5.conf的配置KEYRING:persistent:1000作SASL/GSSAPI缺省值,也说明无配置default_ccache_name,krb5.conf的缺省是FILE:/tmp/krb5cc_1000
linlin@vmcln:~$ KRB5CCNAME="MEMORY:dhcp_ld_krb5_cc" ./testldapkrb_m
...
Successfully store creds
SASL/GSSAPI authentication started
SASL username: krblinlin@CTP.NET
SASL SSF: 256
SASL data security layer installed.
Success!
dn: ou=dns,dc=ctp,dc=net
attribute = objectClass
attribute = ou
...
已成功
int ret = setenv("KRB5CCNAME", "MEMORY:dhcp_ld_krb5_cc", 1);
况且通常的krb5程序可以不需自己生成票据,只要有别的程序(如kinit)提供生成票据即可.如果default_ccache_name为进程内存票据,那岂不是其它的krb5程序必须自己生成票据到内存
SASL/GSSAPI应该是优先读取环境变量KRB5CCNAME,然后才是/etc/krb5.conf
linlin@vmcln:~$ KRB5CCNAME="MEMORY:dhcp_ld_krb5_cc" ./testldapkrb_m
...
Successfully store creds 到此步是通过krb5密码认证成功的,并已生成了票据
SASL/GSSAPI authentication started 开始LDAP/SASL/GSSAPI认证,在此失败,提示找不到 realm
Error: Local error
Additional info: SASL(-1): generic failure: GSSAPI Error: Unspecified GSS failure. Minor code may provide more information (Configuration file does not specify default realm)
linlin@vmcln:~$
本文实验环境krb5+ldap+dns在同一台机器vmkdc上linlin@vmcln:~$cat /etc/resolv.conf
domain ctp.net
search ctp.net
nameserver 192.168.1.11
linlin@vmcln:~$ hostname -d
ctp.net
linlin@vmcln:~$cat /etc/resolv.conf
nameserver 192.168.1.11
linlin@vmcln:~$ hostname -d
hostname: Temporary failure in name resolution
linlin@vmcln:~$cat /etc/hosts
127.0.0.1 localhost
linlin@vmcln:~$
linlin@vmcln:~$ ./testldapkrb_f
...
Successfully store creds
SASL/GSSAPI authentication started
Error: Local error
Additional info: SASL(-1): generic failure: GSSAPI Error: Unspecified GSS failure. Minor code may provide more information (Server not found in Kerberos database)
失败
SASL/GSSAPI authentication started
ldap_sasl_interactive_bind_s: Local error (-2)
additional info: SASL(-1): generic failure: GSSAPI Error: Unspecified GSS failure. Minor code may provide more information (Server not found in Kerberos database)
linlin@vmcln:~$
失败
2019-12-16T08:17:08 Got TGS FAST request
2019-12-16T08:17:08 TGS-REQ krblinlin@CTP.NET from IPv4:192.168.1.20 for ldap/vmkdc.ctp.net@CTP.NET [canonicalize]
2019-12-16T08:17:08 Searching referral for vmkdc.ctp.net
2019-12-16T08:17:08 Server not found in database: ldap/vmkdc.ctp.net@CTP.NET: no such entry found in hdb 找不到主体
2019-12-16T08:17:08 Failed building TGS-REP to IPv4:192.168.1.20
注意日志出现的是‘ldap/vmkdc.ctp.net@CTP.NET‘,应该是在客户机通过DNS服务器反向解析192.168.1.11出vmkdc.ctp.net,并拼接出ldap/vmkdc.ctp.net@CTP.NET,但在KDC并没有该主体
到服务器
root@vmkdc:~# kadmin -l
新增
kadmin> add -r ldap/vmkdc.ctp.net
kadmin> ext -k /etc/ldap/krb5.keytab ldap/vmkdc.ctp.netroot@vmkdc:~# ktutil -k /etc/ldap/krb5.keytab list
/etc/ldap/krb5.keytab:
Vno Type Principal Aliases
1 aes256-cts-hmac-sha1-96 ldap/vmkdc@CTP.NET
1 des3-cbc-sha1 ldap/vmkdc@CTP.NET
1 arcfour-hmac-md5 ldap/vmkdc@CTP.NET
1 aes256-cts-hmac-sha1-96 ldap/vmkdc.ctp.net@CTP.NET
1 des3-cbc-sha1 ldap/vmkdc.ctp.net@CTP.NET
1 arcfour-hmac-md5 ldap/vmkdc.ctp.net@CTP.NET
root@vmkdc:~#
linlin@vmcln:~$ KRB5CCNAME="MEMORY:dhcp_ld_krb5_cc" ./testldapkrb_m
...
Successfully store creds
SASL/GSSAPI authentication started
Error: Invalid credentials
Additional info: SASL(-13): authentication failure: GSSAPI Failure: gss_accept_sec_context
linlin@vmcln:~$
krb5.keytab里虽有ldap/vmkdc.ctp.net@CTP.NET,但仍失败
2019-12-17T01:52:16 TGS-REQ krblinlin@CTP.NET from IPv4:192.168.1.20 for ldap/vmkdc.ctp.net@CTP.NET [canonicalize]
2019-12-17T01:52:16 TGS-REQ authtime: 2019-12-17T01:52:16 starttime: 2019-12-17T01:52:16 endtime: 2019-12-18T01:52:16 renew till: unset
2019-12-17T01:52:16 sending 639 bytes to IPv4:192.168.1.20
虽然在KDC已找到了ldap/vmkdc.ctp.net@CTP.NET,但可能是ldap应用服务是使用ldap/vmkdc@CTP.NET主体,两者不一致导致失败
/etc/hosts的内容
127.0.0.1 localhost
linlin@vmkdc:~$ KRB5CCNAME="MEMORY:dhcp_ld_krb5_cc" ./testldapkrb_m
...
Successfully store creds
SASL/GSSAPI authentication started
Error: Local error
Additional info: SASL(-1): generic failure: GSSAPI Error: Unspecified GSS failure. Minor code may provide more information (Server not found in Kerberos database)
linlin@vmkdc:~$
失败
2019-12-17T00:46:30 TGS-REQ krblinlin@CTP.NET from IPv4:127.0.0.1 for ldap/localhost@CTP.NET
2019-12-17T00:46:30 Server not found in database: ldap/localhost@CTP.NET: no such entry found in hdb
注意日志出现的‘ldap/localhost@CTP.NET‘,在KDC不存在
重新编译为testldapkrb_m_local
或设nameserver 127.0.0.1
或设nameserver 192.168.2.3 不同KDC服务器网段随便不存在的地址
...
Successfully store creds
SASL/GSSAPI authentication started
SASL username: krblinlin@CTP.NET
SASL SSF: 56
SASL data security layer installed.
Success!
dn: ou=dns,dc=ctp,dc=net
attribute = objectClass
attribute = ou
...
已成功
2019-12-17T00:35:17 TGS-REQ krblinlin@CTP.NET from IPv4:127.0.0.1 for ldap/vmkdc@CTP.NET [canonicalize]
2019-12-17T00:35:17 TGS-REQ authtime: 2019-12-17T00:35:17 starttime: 2019-12-17T00:35:17 endtime: 2019-12-18T00:35:17 renew till: unset
2019-12-17T00:35:17 sending 623 bytes to IPv4:127.0.0.1
注意日志已是‘ldap/vmkdc@CTP.NET‘
nameserver 192.168.1.55
再次运行./testldapkrb_m_local也成功,但很慢很慢
查看主机名
linlin@vmkdc:~$ hostname
vmkdc
linlin@vmkdc:~$
是不是连接本地127.0.0.1时SASL/GSSAPI根据hostname结果?
linlin@vmkdc:~$ su
root@vmkdc:/home/linlin# hostname vmabc.efg
root@vmkdc:/home/linlin# exit
linlin@vmkdc:~$ hostname
vmabc.efg
linlin@vmkdc:~$ KRB5CCNAME="MEMORY:dhcp_ld_krb5_cc" ./testldapkrb_m_local
...
Successfully store creds
SASL/GSSAPI authentication started
Error: Local error
Additional info: SASL(-1): generic failure: GSSAPI Error: Unspecified GSS failure. Minor code may provide more information (Server not found in Kerberos database)
linlin@vmkdc:~$
失败
2019-12-17T01:34:59 TGS-REQ krblinlin@CTP.NET from IPv4:127.0.0.1 for ldap/vmabc.efg@CTP.NET [canonicalize]
注意日志出现的‘ldap/vmabc.efg@CTP.NET‘,确实根据hostname结果(而非主机名称解析dns或/etc/hosts)
1.对于读取票据位置,环境变量KRB5CCNAME优先,然后才按/etc/krb5.conf
2.
连接本地127.0.0.1时,SASL/GSSAPI根据hostname结果
连接远程地址192.168.1.11时,SASL/GSSAPI根据dns或/etc/hosts反向解析出名称拼接出ldap/xxx.yyy,或者解析不到就拼接出ldap/localhost
即本文最好设定服务器全限定名vmkdc.ctp.net,应用服务主体ldap/vmkdc.ctp.net@CTP.NET,这样客户机/etc/hosts就不需添加192.168.1.11 vmkdc一行
本人水平有限,文中难免有错漏,更多的/etc/krb5.conf的参数配置,请参考有关MIT的文档.
我在MIT文档查阅到
[libdefaults]
rdns = false
上一篇:C#命名规则和编码规范
文章标题:LDAP/SASL/GSSAPI/Kerberos编程API(3)--LDAP/SASL
文章链接:http://soscw.com/index.php/essay/64732.html