手机使用也会认为这一条记录是"未使用"的 */
switch(op) {
case 1: // 读取
fail_if(!trans_succeeded(read_record_abs(hCard, 1, buf, dwRecSize)),
_("APDU failure"));
memcpy(ptok, &buf[4], LEN);
break;
case 2: // 写入
memset(buf, 0xFF, sizeof(buf));
buf[0] = 0;
memcpy(&buf[4], ptok, LEN);
fail_if(!trans_succeeded(write_record_abs(hCard, 1, buf, dwRecSize)),
_("APDU failure"));
break;
default:
break;
}
finish:
/* 清理现场 */
if(hCard) SCardDisconnect(hCard, SCARD_RESET_CARD);
if(ctx) SCardReleaseContext(ctx);
if(err) card_setstrerror(err);
return ret;
}
int read_token(token *out)
{
return token_manipulate(out, 1);
}
int write_token(token *in)
{
return token_manipulate(in, 2);
部署
程序写好了,该设置一下开始使用了!
首先把卡和登录信息都准备好
proton@Proton:~/my_projects/pam_iccard$ sudo touch /etc/cards
proton@Proton:~/my_projects/pam_iccard$ ./initcard
Enter your PIN:
Card initialized.
proton@Proton:~/my_projects/pam_iccard$ ./registercard
PIN:
Registered.
proton@Proton:~/my_projects/pam_iccard$
这两个工具都很简单,看名字就能猜出用途, 源码就不再贴出来了。
然后在把/etc/pam.d/common-auth 复制一份,删除原来的 pam_unix.so 一行,并且添加这
一行:
auth sufficient /path/to/module/pam_iccard.so reader=Your_Smartcard_Reader_Name
保存成 common-auth-smartcard。
然后修改相应的文件(login、gdm、gnome-screensaver、polkit-1、su等等),把其中的
@include common-auth
改成
@include common-auth-smartcard
这样就完成了!
看一下效果:
Ubuntu 10.04.2 LTS Proton tty1
Proton login: proton
Read card failed: No smartcard is currently in reader.
Login incorrect
Proton login: proton
PIN:
Last login: Thu Mar 10 17:06:26 CST 2011 on tty1
Linux Proton 2.6.32-29-preempt #58-Ubuntu SMP PREEMPT Fri Feb 11 21:21:37
UTC 2
11 x86_64 GNU/Linux
Ubuntu 10.04.2 LTS
Welcome to Ubuntu!
* Documentation: https://help.ubuntu.com/
27 packages can be updated.
16 updates are security updates.
proton@Proton:~$
一次完整的通信
由一次登录过程产生的通信如下
-->: A0 A4 00 00 02 3F 00 # CLA=0xA0 INS=0xA4(SELECT,选择文件) P3=2 说明附
带 2 个字节的数据,P3后就是这两个字节的数据,也就是文件ID
<--: 9F 17 # 表示成功,并且有 0x17 字节的数据可以通过 GET RESPONSE 指令获取,
下同
-->: A0 A4 00 00 02 7F 10
<--: 9F 17
-->: A0 A4 00 00 02 6F 3C
<--: 9F 0F
-->: A0 C0 00 00 0F # INS=0xC0(GET RESPONSE) P3表示长度
<--: 00 00 00 B0 6F 3C 04 00 11 FF 55 01 02 01 B0 90 00 # 最后两个字节总是SW,
0x9000 表示成功。之前的字节就是数据,可以根据上文的select_resp结构对号入座
-->: A0 B2 01 04 B0 # INS=0xB2(READ RECORD), P1 表示记录号, P2 的 0x04 表示是
绝对位置,P3表示大小
<--: 00 FF FF FF 43 41 52 44 8B 86 5C 59 ...... FF FF 90 00 # 这就是一条短信,
也就是我们需要的认证标记,因为很长就省略了。
后记
程序在 Ubuntu 10.04.2 LTS x86_64 上测试成功。
因为程序分成了两部分(PAM 和对 SIM 卡的操作),很自然的会想这两部分除了这样还可以 |