• PAM从入门到精通(十五)


    接前一篇文章:PAM从入门到精通(十四)

    本文参考:

    《The Linux-PAM Application Developers' Guide》

    先再来重温一下PAM系统架构

    更加形象的形式:

    六、整体流程示例

    1. 官方文档中的例程及解析

    PAM从入门到精通(四)起到上一回止,整体结合实例讲解了《The Linux-PAM Application Developers' Guide》中的“Chapter 3. The public interface to Linux-PAM”中的3.1,实际上对应了上图中的PAM-API部分。不过看了各函数之后,对于总体流程还是缺少了了解和把握。本回就以一个示例(代码)将之前这些函数串起来,以对于总体流程以及各函数之间的顺序和关系有更好的理解。

    示例代码参见《The Linux-PAM Application Developers' Guide》的“Chapter 8. An example application ”。

    为了了解Linux PAM应用程序的编写方式,我们包括以下示例。它会提示用户输入密码,并在标准输出中指示他们的帐户是否有效,其返回代码也指示成功与否(0表示成功;1表示失败)。

    代码如下:

    1. /*
    2. This program was contributed by Shane Watts
    3. [modifications by AGM and kukuk]
    4. You need to add the following (or equivalent) to the
    5. /etc/pam.d/check_user file:
    6. # check authorization
    7. auth required pam_unix.so
    8. account required pam_unix.so
    9. */
    10. #include
    11. #include
    12. #include
    13. static struct pam_conv conv = {
    14. misc_conv,
    15. NULL
    16. }
    17. int main(int argc, char *argv[])
    18. {
    19. pam_handle_t *pamh=NULL;
    20. int retval;
    21. const char *user="nobody";
    22. if(argc == 2) {
    23. user = argv[1];
    24. }
    25. if(argc > 2) {
    26. fprintf(stderr, "Usage: check_user [username]\n");
    27. exit(1);
    28. }
    29. retval = pam_start("check_user", user, &conv, &pamh);
    30. if (retval == PAM_SUCCESS)
    31. retval = pam_authenticate(pamh, 0); /* is user really user? */
    32. if (retval == PAM_SUCCESS)
    33. retval = pam_acct_mgmt(pamh, 0); /* permitted access? */
    34. /* This is where we have been authorized or not. */
    35. if (retval == PAM_SUCCESS) {
    36. fprintf(stdout, "Authenticated\n");
    37. } else {
    38. fprintf(stdout, "Not Authenticated\n");
    39. }
    40. if (pam_end(pamh,retval) != PAM_SUCCESS) { /* close Linux-PAM */
    41. pamh = NULL;
    42. fprintf(stderr, "check_user: failed to release authenticator\n");
    43. exit(1);
    44. }
    45. return ( retval == PAM_SUCCESS ? 0:1 ); /* indicate success */
    46. }

    说实话,这代码写得很一般,argc为1时的情况没有考虑进来。不过不必关注这些细枝末节,人家把主要的流程讲清楚了。整个流程分为以下步骤:

    (1)pam_start函数

    代码片段:

        retval = pam_start("check_user", user, &conv, &pamh);

    作用:

    PAM事务初始化。

    pam_start函数创建PAM上下文并启动PAM事务。它是应用程序需要调用的第一个PAM函数。事务状态完全包含在此句柄标识的结构中,因此可以并行处理多个事务。但是不可能对不同的事务使用相同的句柄,每个新的上下文都需要一个新的句柄。

    (2)pam_authenticate函数

    代码片段:

        retval = pam_authenticate(pamh, 0); /* is user really user? */

    作用:

    对用户进行身份认证。

    pam_authenticate函数用于对用户进行身份验证。用户被要求提供一个基于身份验证服务的身份验证令牌,通常这是一个密码,但也可能是指纹。

    PAM服务模块可以请求用户通过对话机制输入其用户名(参见pam_start()和pam_conv())。经过身份验证的用户名称将出现在PAM的PAM_USER项中。可以通过调用pam_get_item()来恢复此项目。

    (3)pam_acct_mgmt函数

    代码片段:

        retval = pam_acct_mgmt(pamh, 0); /* permitted access? */

    作用:

    账户验证管理。

    pam_acct_mgmt函数用于确定用户的帐户是否有效。它检查身份验证令牌和帐户过期与否,并验证访问限制。其通常在用户经过身份验证后调用。

    (4)pam_end

    代码片段:

    1. if (pam_end(pamh,retval) != PAM_SUCCESS) { /* close Linux-PAM */
    2. pamh = NULL;
    3. fprintf(stderr, "check_user: failed to release authenticator\n");
    4. exit(1);
    5. }

    作用:

    PAM事务终止。

    pam_end函数终止pam事务,是应用程序应在pam上下文中调用的最后一个函数。此函数为与pam_set_item和pam_get_item函数关联的项释放了所有内存。调用pam_end()后,与此类对象关联的指针不再有效。

  • 相关阅读:
    Flutter --- 配置多个Flutter SDK
    k3s安装
    Springboot实现websocket(连接前jwt验证token)
    Mysql行级锁
    网站监控定时任务网址url监控神器
    HarmonyOS鸿蒙-DevEco Studio工具
    NVIDIA NCCL 源码学习(二)- bootstrap网络连接的建立
    左右手切换工具xmouse v1.2版本发布
    JS-事件委托-阻止事件冒泡和阻止默认行为-滚动事件-加载事件-元素尺寸位置
    .Net MVC 使用Areas后存在相同Controller时报错的解决办法; 从上下文获取请求的Area名及Controller名
  • 原文地址:https://blog.csdn.net/phmatthaus/article/details/133941933