kerberos - gss_accept_sec_context() 错误:ASN.1 结构缺少必填字段
问题描述
我正在尝试在 Ubuntu 上实现 Kerberos 身份验证。
run_kerberos_server.sh
#!/usr/bin/env bash
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
docker stop krb5-server && docker rm krb5-server && true
docker run -d --network=altexy --name krb5-server \
-e KRB5_REALM=EXAMPLE.COM -e KRB5_KDC=localhost -e KRB5_PASS=12345 \
-v /etc/localtime:/etc/localtime:ro \
-v /etc/timezone:/etc/timezone:ro \
--network-alias example.com \
-p 88:88 -p 464:464 -p 749:749 gcavalcante8808/krb5-server
echo "=== Init krb5-server docker container ==="
docker exec krb5-server /bin/sh -c "
# Create users bob as normal user
# and add principal for the service
cat << EOF | kadmin.local
add_principal -randkey \"HTTP/service.example.com@EXAMPLE.COM\"
ktadd -k /etc/krb5-service.keytab -norandkey \"HTTP/service.example.com@EXAMPLE.COM\"
ktadd -k /etc/admin.keytab -norandkey \"admin/admin@EXAMPLE.COM\"
listprincs
quit
EOF
"
echo "=== Copy keytabs ==="
docker cp krb5-server:/etc/krb5-service.keytab "${DIR}"/krb5-service.keytab
docker cp krb5-server:/etc/admin.keytab "${DIR}"/admin.keytab
获取 Kerberos 票证:
alex@alex-secfense:~/projects/proxy-auth/etc/kerberos$ kinit admin/admin@EXAMPLE.COM
Password for admin/admin@EXAMPLE.COM:
alex@alex-secfense:~/projects/proxy-auth/etc/kerberos$ klist
Ticket cache: FILE:/tmp/krb5cc_1000
Default principal: admin/admin@EXAMPLE.COM
Valid starting Expires Service principal
16.12.2020 12:05:38 17.12.2020 00:05:38 krbtgt/EXAMPLE.COM@EXAMPLE.COM
renew until 17.12.2020 12:05:35
然后我启动 nginx,也在 Docker 容器中,图像来自openresty/openresty:xenial
. 我的/etc/hosts
文件有127.0.0.1 service.example.com
行。
我的 Firefox 配置为network.negotiate-auth.trusted-uris
=service.example.com
我打开service.example.com:<mapped_port> page in Firefox, nginx responds with 401 and Firefox send
Authorization: Negotiate ...` 标题。
我的服务器端代码(错误和结果处理被剥离):
MYAPI int authenticate(const char* token, size_t length)
{
gss_buffer_desc service = GSS_C_EMPTY_BUFFER;
gss_name_t my_gss_name = GSS_C_NO_NAME;
gss_cred_id_t my_gss_creds = GSS_C_NO_CREDENTIAL;
OM_uint32 minor_status;
OM_uint32 major_status;
gss_ctx_id_t gss_context = GSS_C_NO_CONTEXT;
gss_name_t client_name = GSS_C_NO_NAME;
gss_buffer_desc output_token = GSS_C_EMPTY_BUFFER;
gss_buffer_desc input_token = GSS_C_EMPTY_BUFFER;
input_token.length = length;
input_token.value = (void*)token;
major_status = gss_accept_sec_context(&minor_status, &gss_context, my_gss_creds, &input_token,
GSS_C_NO_CHANNEL_BINDINGS, &client_name, NULL, &output_token, NULL, NULL, NULL);
return 0;
}
最终,我得到gss_accept_sec_context() error:ASN.1 structure is missing a required field
错误。
相同的代码适用于 Windows Kerberos 设置。
知道这是什么意思或如何调试问题吗?
我确实定义了KRB5_TRACE=/<log_file_name>
环境变量并看到如下行:
[7] 1607798057.341744: Sending request (937 bytes) to EXAMPLE.COM
[6] 1608109670.292389: Sending request (937 bytes) to EXAMPLE.COM
[6] 1608109670.660887: Sending request (937 bytes) to EXAMPLE.COM
可能是DNS问题?
更新:我错过了在调用之前指定要在服务器端使用的 keyatb 文件gss_accept_sec_context
(再次删除了错误处理):
OM_uint32 major_status = gsskrb5_register_acceptor_identity(keytab_filename)
解决方案
您的代码打破了上下文完成的基本概念。它违反了 RFC 7546 并且不值得信赖,而且您完全忽略了主要/次要。现在,由于 ASN.1 编码被破坏,您的令牌会在运行中以某种方式被修改。
- 传输前后转储令牌并进行比较。
- 先从
gss-server
和gss-client
开始。 - 阅读他们的代码并实现你的同类。不要偏离上下文看完成的命令,
- 在 Firefox 获得服务票证后显示票证缓存。
一旦您需要令牌,请使用https://lapo.it/asn1js/显示检查它们。
推荐阅读
- c# - 数字前的 OrderBy 自定义比较器特定字母
- java - 如何在 InternalResourceViewResolver Spring MVC 中配置多个文件夹?
- tensorflow - 即使在训练后量化之后,“模型未量化”
- c++ - linux上的CMake FindJNI问题
- python - 如何正确使用 tft.compute_and_apply_vocabulary 和 tft.tfidf?
- python - 在递归查找最大路径和时,附加二叉树的左或右方向
- batch-file - 提取子字符串并在一行中对批处理文件变量应用字符串替换
- python-3.x - 如何使用 WMI 从 python 中的远程计算机检索文件
- c# - 如何在 C# 中将 int 值转换为 hh:mm?
- sql - 根据不同的列类型连接两个表