#define FID_DF_GSM 0x7F20
#define FID_EF_IMSI 0x6F07
static response select_file(SCARDHANDLE hCard, WORD fileid)
{
/* 用来选择SIM卡文件的函数, 实际上就是发送一个APDU
* 因为这几个函数基本相同,所以剩下的都省略了 */
BYTE apdu[] = { 0xA0, 0xA4, 0x00, 0x00, 0x02, /* >> */ 0x00, 0x00 /* << file
id */ };
BYTE buf[4];
apdu[5] = (fileid>>8) & 0xFF;
apdu[6] = fileid & 0xFF;
return trans(hCard, apdu, sizeof(apdu), buf, sizeof(buf));
}
static response get_response(SCARDHANDLE hCard, BYTE *out, DWORD len);
static response read_record_abs(SCARDHANDLE hCard, DWORD index, BYTE *out,
DWORD rlen);
static response write_record_abs(SCARDHANDLE hCard, DWORD index, const BYTE
*in, DWORD len);
#define fail_if(exp, errmsg) \
if(exp) { \
ret = 0; \
if(errmsg) \
err = (errmsg); \
goto finish; \
}
static int inline trans_succeeded(response r)
{
/* SW的第一个字节是这些说明成功 */
return r.sw1 == 0x90 || r.sw1 == 0x9F || r.sw1 == 0x91;
}
typedef struct {
/* 这个结构是SELECT 指令以后的 GET RESPONSE取得的数据 */
WORD rfu1;
WORD size; /* 文件大小 */
WORD fid; /* 文件ID */
BYTE ftype; /* 文件类型 */
BYTE rfu2[5];
BYTE cb; /* gsmdata的长度 */
BYTE gsmdata[0];
} __attribute__((packed)) select_resp;
static int token_manipulate(token *ptok, int op)
{
/* 读写 SIM 卡的函数,读写的大部分代码相同,就写在一个函数里了 */
SCARDCONTEXT ctx = 0;
SCARDHANDLE hCard = 0;
char *reader = NULL;
char *err = NULL;
DWORD dwActiveProtocol, nRec, dwRecSize;
response resp;
BYTE buf[300];
int ret = 1;
int status;
reader = get_setting("reader");
fail_if(!reader, _("** PLEASE SPECIFY CARD READER NAME IN CONFIG FILE OR
PAM PARAMETERS **"));
fail_if(SCARD_S_SUCCESS != SCardEstablishContext(SCARD_SCOPE_SYSTEM,
NULL, NULL, &ctx), _("SCardEstablishContext failed"));
status = SCardConnect(
ctx,
reader,
SCARD_SHARE_EXCLUSIVE,
SCARD_PROTOCOL_T0,
&hCard,
&dwActiveProtocol
); /* 连接 SIM卡 */
fail_if(status == SCARD_E_NO_SMARTCARD, _("No smartcard is currently in
reader."));
fail_if(status != SCARD_S_SUCCESS, _("SCardConnect failed"));
fail_if(!trans_succeeded(select_file(hCard, FID_MF)), _("APDU failure"));
/* 选择 Master File */
ail_if(!trans_succeeded(select_file(hCard, FID_DF_TELECOM)), _("APDU
failure")); /* 选择DF_TELECOM */
resp = selectfile(hCard, FIDEFSMS); /* 选择短信文件 */
f
fail_if(!trans_succeeded(resp), _("APDU failure"));
resp = get_response(hCard, buf, resp.sw2); /* 取得上一个 SELECT 指令的
RESPONSE, resp.sw2是的长度 */
fail_if(!trans_succeeded(resp), _("APDU failure"));
dwRecSize = ((select_resp *)buf)->gsmdata[1]; /* 这里表示短信文件一条记
录的长度 */
nRec = bswap(((select_resp *)buf)->size) / dwRecSize; /* 通过文件长度和
记录长度计算出一共有几条记录 */
/* 保存的时候从短信的第四个字节开始,第一个字节保持为0,这样即使SIM卡被 |