linux c语言 密码,Linux 双因子认证(密码+PIN)C语言版

Linux 双因子认证(密码+PIN)C语言版.md

4fd12c60b7cda9b8a79377215e8213ed.png

关键字

Linux C语言 PAM SSH 2 Two Multi Factor Authentication Login 双因子 多因子 密保 TOKEN 一次性口令 PASSPOD OTP yubikey 认证 安全 登录

实现效果

最简单的实现的方式,用户SSH登录时需要输入用户名+PIN+密码方式才能登录。

这里的PIN是一个字符串,例如”ipcpu.com”或者电话号码6192*,固定死的,不会变,所有用户共享。

[root@control.ipcpu.com~]#ssh ipcpu@211.81.175.101

PIN:6192***

Password:

[ipcpu@s18.ipcpu.com~]$

[ipcpu@s18.ipcpu.com~]$

[ipcpu@s18.ipcpu.com~]$id

uid=501(ipcpu)gid=501(ipcpu)groups=501(ipcpu)

实现代码(C语言)

/*******************************************************************************

* file: 2ndfactor.c

* author: www.ipcpu.com

* description: PAM module to provide 2 factor authentication

*******************************************************************************/

#include

#include

#include

#include

#include

#include

/* expected hook */

PAM_EXTERNintpam_sm_setcred(pam_handle_t*pamh,intflags,intargc,constchar**argv){

returnPAM_SUCCESS;

}

/* this function is ripped from pam_unix/support.c, it lets us do IO via PAM */

intconverse(pam_handle_t*pamh,intnargs,structpam_message**message,structpam_response**response){

intretval;

structpam_conv*conv;

retval=pam_get_item(pamh,PAM_CONV,(constvoid**)&conv);

if(retval==PAM_SUCCESS){

retval=conv->conv(nargs,(conststructpam_message**)message,response,conv->appdata_ptr);

}

returnretval;

}

/* expected hook, this is where custom stuff happens */

PAM_EXTERNintpam_sm_authenticate(pam_handle_t*pamh,intflags,intargc,constchar**argv){

intretval;

inti;

/* these guys will be used by converse() */

char*input;

char*pin="6192***";

structpam_message msg[1],*pm

sg[1];

structpam_response*resp;

/* getting the username that was used in the previous authentication */

constchar*username;

if((retval=pam_get_user(pamh,&username,"login: "))!=PAM_SUCCESS){

returnretval;

}

/*ak47@ipcpu.com,code start here!*/

/* setting up conversation call prompting for one-time code */

pmsg[0]=&msg[0];

msg[0].msg_style=PAM_PROMPT_ECHO_ON;

msg[0].msg="PIN: ";

/*variable resp used to recive keyboard input*/

resp=NULL;

if((retval=converse(pamh,1,pmsg,&resp))!=PAM_SUCCESS){

// if this function fails, make sure that ChallengeResponseAuthentication in sshd_config is set to yes

returnretval;

}

/* retrieving user input,give PIN to variable input */

if(resp){

if((flags&PAM_DISALLOW_NULL_AUTHTOK)&&resp[0].resp==NULL){

free(resp);

returnPAM_AUTH_ERR;

}

input=resp[0].resp;

resp[0].resp=NULL;

}else{

returnPAM_CONV_ERR;

}

/* comparing user input with known code */

if(strcmp(input,pin)==0){

/* good to go! */

free(input);

returnPAM_SUCCESS;

}else{

/* wrong pin */

free(input);

returnPAM_AUTH_ERR;

}

/* we shouldn't read this point, but if we do, we might as well return something bad */

returnPAM_AUTH_ERR;

}

编译方法:

#@编译之前需要安装pam-devel包,否则会报错

gcc-fPIC-lcurl-c2ndfactor.c

ld-x--shared-o/lib/security/2ndfactor.so2ndfactor.o

将其配置到/etc/pam.d/sshd,SSH配置中打开ChallengeResponseAuthentication

[root@IPCPU-11~]#head/etc/pam.d/sshd

#%PAM-1.0

auth requisite2ndfactor.so

auth required pam_sepermit.so

auth include password-auth

account required pam_nologin.so

account include password-auth

password include password-auth

# pam_selinux.so close should be the first session rule

session required pam_selinux.so close

session required pam_loginuid.so

[root@IPCPU-11~]#

进阶-每个用户使用独立的PIN

使用固定的PIN优点太low了,接下来我们介绍进阶的办法,每个人用自己的PIN。

首先PIN需要有个地方存放起来,我们就直接使用/etc/passwd的comment字段来存储。

可以通过命令 usermod来修改。如下,

[root@IPCPU-11~]#usermod-c6192***root

[root@IPCPU-11~]#cat/etc/passwd

root:x:0:0:6192***:/root:/bin/bash

PAM模块代码

/*******************************************************************************

* file: pin.c

* author: www.ipcpu.com

* description: PAM module to provide 2 factor authentication

*******************************************************************************/

#include

#include

#include

#include

#include

#include

#include

#include

//#include

/* expected hook */

PAM_EXTERNintpam_sm_setcred(pam_handle_t*pamh,intflags,intargc,constchar**argv){

returnPAM_SUCCESS;

}

/* this function is ripped from pam_unix/support.c, it lets us do IO via PAM */

intconverse(pam_handle_t*pamh,intnargs,structpam_message**message,structpam_response**response){

intretval;

structpam_conv*conv;

retval=pam_get_item(pamh,PAM_CONV,(constvoid**)&conv);

if(retval==PAM_SUCCESS){

retval=conv->conv(nargs,(conststructpam_message**)message,response,conv->appdata_ptr);

}

returnretval;

}

/* expected hook, this is where custom stuff happens */

PAM_EXTERNintpam_sm_authenticate(pam_handle_t*pamh,intflags,intargc,constchar**argv){

intretval;

inti;

/* these guys will be used by converse() */

char*input;

structpam_message msg[1],*pmsg[1];

structpam_response*resp;

/* getting the username that was used in the previous authentication */

constchar*username;

if((retval=pam_get_user(pamh,&username,"login: "))!=PAM_SUCCESS){

returnretval;

}

/* get user comment from /etc/passwd */

structpasswd*pwd;

structpasswd pwdbuf;

charpwbuffer[2*PATH_MAX];

char*gecos;

if((retval=getpwnam_r(username,&pwdbuf,pwbuffer,sizeof(pwbuffer),&pwd))!=PAM_SUCCESS||NULL==pwd){

//syslog(LOG_ERR|LOG_AUTHPRIV, "PIN-PAM:could not get comment." );

//gecos = "jshjdkshakg";

//syslog(LOG_ERR|LOG_AUTHPRIV, "PIN-PAM:gecos:%s.", gecos );

//return retval ;

returnPAM_AUTH_ERR;

}else{

gecos=pwd->pw_gecos;

//syslog(LOG_ERR|LOG_AUTHPRIV, "PIN-PAM:get comment ok." );

//syslog(LOG_ERR|LOG_AUTHPRIV, "PIN-PAM:gecos:%s.", gecos );

}

/* setting up conversation call prompting for one-time code */

pmsg[0]=&msg[0];

msg[0].msg_style=PAM_PROMPT_ECHO_OFF;

msg[0].msg="PIN: ";

/*variable resp used to recive keyboard input*/

resp=NULL;

if((retval=converse(pamh,1,pmsg,&resp))!=PAM_SUCCESS){

// if this function fails, make sure that ChallengeResponseAuthentication in sshd_config is set to yes

returnretval;

}

/* retrieving user input,give PIN to variable input */

if(resp){

if((flags&PAM_DISALLOW_NULL_AUTHTOK)&&resp[0].resp==NULL){

free(resp);

returnPAM_AUTH_ERR;

}

input=resp[0].resp;

resp[0].resp=NULL;

}else{

returnPAM_CONV_ERR;

}

/* comparing user input with known code */

if(strcmp(input,gecos)==0){

/* right to go! */

free(input);

syslog(LOG_ERR|LOG_AUTHPRIV,"PIN-PAM:success.%s:%s.",username,gecos);

returnPAM_SUCCESS;

}else{

/* wrong pin !*/

free(input);

syslog(LOG_ERR|LOG_AUTHPRIV,"PIN-PAM:failed.%s:%s.",username,gecos);

returnPAM_AUTH_ERR;

}

/* we shouldn't read this point, but if we do, we might as well return something bad */

returnPAM_AUTH_ERR;

}

参考文章

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值