Tag - linux

linux    2016-03-07 00:47:18    791    0    0

本文代码涉及所有文件存放在
https://github.com/ochapman/passwd_demo.git

熟悉linux的人应该用过修改用户密码工具passwd,如下所示:

ochapman@ubuntu14:~/code/pam$ passwd
Changing password for ochapman.
(current) UNIX password:

提示了修改谁的密码,并要求输入当前的密码。
一般情况下,读取当前密码,校验当前密码是否正确,再去更新shadow/passwd文件…
linux下,这类工作主要由PAM承包
图片标题
PAM能抽象到什么程度呢,本文将用一个简单的例子展示PAM的威力。

简单例子

下面是一个简单的例子,实现了passwd的基本功能

/*
 *  passwd_demo
 *  a simple passwd utility for showing PAM usage
 *  derived from shadow
 */

#include <stdio.h>
#include <errno.h>
#include <sys/types.h>
#include <stdbool.h>
#include <stdlib.h>
#include <security/pam_appl.h>
#include <security/pam_misc.h>

#define SHADOW_PAM_CONVERSATION misc_conv

static struct pam_conv conv = {
    SHADOW_PAM_CONVERSATION,
    NULL
};

void do_pam_passwd (const char *user, bool silent, bool change_expired)
{
    pam_handle_t *pamh = NULL;
    int flags = 0, ret;

    if (silent)
        flags |= PAM_SILENT;
    if (change_expired)
      
linux    2016-02-16 08:55:30    433    0    0

经常阅读后台程序源码的话,会看到在初始化时dup2相关的函数,例如nginx的

fd = open("/dev/null", O_RDWR);
if (fd == -1) {
    ngx_log_error(NGX_LOG_EMERG, log, ngx_errno,
                  "open(\"/dev/null\") failed");
    return NGX_ERROR;
}

if (dup2(fd, STDIN_FILENO) == -1) {
    ngx_log_error(NGX_LOG_EMERG, log, ngx_errno, "dup2(STDIN) failed");
    return NGX_ERROR;
}

if (dup2(fd, STDOUT_FILENO) == -1) {
    ngx_log_error(NGX_LOG_EMERG, log, ngx_errno, "dup2(STDOUT) failed");
    return NGX_ERROR;
}
#if 0
if (dup2(fd, STDERR_FILENO) == -1) {
    ngx_log_error(NGX_LOG_EMERG, log, ngx_errno, "dup2(STDERR) failed");
    return NGX_ERROR;
}
#endif

if (fd > STDERR_FILENO) {
    if (close(fd) == -1) {
        ngx_log_error(NGX_LOG_EMERG, log, ngx_errno, "close() failed");
        return NGX_ERROR;
    }
}

return NGX_OK;

dup2到底做了什么

dup2的定义

int dup2(int oldfd, int newfd);

从内核代码fs/file.c,实际在SYSCALL_DEFINE3(dup3, unsigned int, oldfd, unsigned int, newfd, i