1
2
LC_Client_AddCardTypesByAtr(LC_CLIENT * cl,LC_CARD * card)3 int LC_Client_AddCardTypesByAtr(LC_CLIENT *cl, LC_CARD *card){
4 GWEN_XMLNODE *cardNode;
5 const unsigned char *atr;
6 unsigned int atrLen;
7 GWEN_BUFFER *hexAtr;
8 int types=0;
9 int done;
10
11 DBG_DEBUG(0, "Adding card types...");
12
13 /* get ATR, convert it to hex */
14 atrLen=LC_Card_GetAtr(card, &atr);
15 if (atr==0 || atrLen==0) {
16 DBG_INFO(0, "No ATR");
17 return 1;
18 }
19 hexAtr=GWEN_Buffer_new(0, 256, 0, 1);
20 if (GWEN_Text_ToHexBuffer((const char*)atr, atrLen, hexAtr, 0, 0, 0)) {
21 DBG_ERROR(LC_LOGDOMAIN, "Internal error");
22 abort();
23 }
24
25 cardNode=GWEN_XMLNode_FindFirstTag(cl->cardNodes, "card", 0, 0);
26 if (!cardNode) {
27 DBG_ERROR(LC_LOGDOMAIN, "No card nodes.");
28 return -1;
29 }
30 while(cardNode) {
31 const char *name;
32 const char *tp;
33 const char *xtp;
34 int sameBaseType=0;
35
36 name=GWEN_XMLNode_GetProperty(cardNode, "name", 0);
37 assert(name);
38 tp=GWEN_XMLNode_GetProperty(cardNode, "type", 0);
39
40 DBG_VERBOUS(LC_LOGDOMAIN, "Checking card \"%s\"", name);
41 xtp=LC_Card_GetCardType(card);
42 sameBaseType=(tp && xtp && strcasecmp(tp, xtp)==0);
43 if (sameBaseType) {
44 GWEN_XMLNODE *nAtrs;
45
46 nAtrs=GWEN_XMLNode_FindFirstTag(cardNode, "cardinfo", 0, 0);
47 if (nAtrs)
48 nAtrs=GWEN_XMLNode_FindFirstTag(nAtrs, "atrs", 0, 0);
49 if (nAtrs) {
50 GWEN_XMLNODE *nAtr;
51
52 nAtr=GWEN_XMLNode_GetFirstTag(nAtrs);
53 while(nAtr) {
54 GWEN_XMLNODE *nData;
55
56 nData=GWEN_XMLNode_GetFirstData(nAtr);
57 if (nData) {
58 const char *p;
59
60 p=GWEN_XMLNode_GetData(nData);
61 if (p) {
62 GWEN_BUFFER *dbuf;
63
64 /* compress ATR from XML file */
65 dbuf=GWEN_Buffer_new(0, 256, 0, 1);
66 while(*p) {
67 if (!isspace(*p))
68 GWEN_Buffer_AppendByte(dbuf, *p);
69 p++;
70 } /* while */
71 if (-1!=GWEN_Text_ComparePattern(GWEN_Buffer_GetStart(hexAtr),
72 GWEN_Buffer_GetStart(dbuf),
73 0)) {
74 DBG_DEBUG(LC_LOGDOMAIN, "Card \"%s\" matches ATR", name);
75 if (LC_Card_AddCardType(card, name)) {
76 DBG_INFO(LC_LOGDOMAIN, "Added card type \"%s\"", name);
77 types++;
78 }
79 }
80 GWEN_Buffer_free(dbuf);
81 } /* if data */
82 } /* if data node */
83 nAtr=GWEN_XMLNode_GetNextTag(nAtr);
84 } /* while */
85 } /* if atrs */
86 } /* if sameBaseType */
87 cardNode=GWEN_XMLNode_FindNextTag(cardNode, "card", 0, 0);
88 } /* while */
89 GWEN_Buffer_free(hexAtr);
90
91 /* add all cards whose base types are contained in the list.
92 * repeat this as long as we added cards */
93 done=0;
94 while(!done) {
95 done=1;
96 cardNode=GWEN_XMLNode_FindFirstTag(cl->cardNodes, "card", 0, 0);
97 while(cardNode) {
98 const char *name;
99 const char *extends;
100
101 name=GWEN_XMLNode_GetProperty(cardNode, "name", 0);
102 assert(name);
103 extends=GWEN_XMLNode_GetProperty(cardNode, "extends", 0);
104 if (extends) {
105 if (GWEN_StringList_HasString(LC_Card_GetCardTypes(card), extends)) {
106 if (LC_Card_AddCardType(card, name)) {
107 DBG_INFO(LC_LOGDOMAIN, "Added card type \"%s\"", name);
108 types++;
109 done=0;
110 }
111 }
112 }
113 cardNode=GWEN_XMLNode_FindNextTag(cardNode, "card", 0, 0);
114 }
115 } /* while */
116
117 return (types!=0)?0:1;
118 }
119
120
121
LC_Client__FindCommandInCardNode(GWEN_XMLNODE * node,const char * commandName,const char * driverType,const char * readerType)122 GWEN_XMLNODE *LC_Client__FindCommandInCardNode(GWEN_XMLNODE *node,
123 const char *commandName,
124 const char *driverType,
125 const char *readerType){
126 GWEN_XMLNODE *cmds;
127 GWEN_XMLNODE *n;
128
129 DBG_INFO(LC_LOGDOMAIN,
130 "Searching in \"%s\" (%s/%s)",
131 GWEN_XMLNode_GetProperty(node, "name", "(noname)"),
132 driverType?driverType:"(none)",
133 readerType?readerType:"(none)");
134
135 cmds=GWEN_XMLNode_FindNode(node,
136 GWEN_XMLNodeTypeTag,
137 "commands");
138 if (!cmds) {
139 DBG_INFO(LC_LOGDOMAIN, "No commands in card data");
140 return 0;
141 }
142
143 /* first try exact match */
144 if (driverType && readerType) {
145 DBG_DEBUG(LC_LOGDOMAIN, "Searching for %s/%s/%s",
146 driverType, readerType, commandName);
147 n=GWEN_XMLNode_FindFirstTag(cmds,
148 "command",
149 "name",
150 commandName);
151 while(n) {
152 if (strcasecmp(GWEN_XMLNode_GetProperty(n, "driver", ""),
153 driverType)==0 &&
154 strcasecmp(GWEN_XMLNode_GetProperty(n, "reader", ""),
155 readerType)==0) {
156 DBG_DEBUG(LC_LOGDOMAIN,
157 "Found command in %s/%s", driverType, readerType);
158 return n;
159 }
160 n=GWEN_XMLNode_FindNextTag(n, "command", "name", commandName);
161 } /* while */
162 }
163
164 if (driverType) {
165 /* try match of driver only */
166 DBG_DEBUG(LC_LOGDOMAIN, "Searching for %s/%s",
167 driverType, commandName);
168 n=GWEN_XMLNode_FindFirstTag(cmds,
169 "command",
170 "name",
171 commandName);
172 while(n) {
173 if (strcasecmp(GWEN_XMLNode_GetProperty(n, "driver", ""),
174 driverType)==0) {
175 DBG_DEBUG(LC_LOGDOMAIN, "Found command in %s", driverType);
176 return n;
177 }
178 n=GWEN_XMLNode_FindNextTag(n, "command", "name", commandName);
179 } /* while */
180 }
181
182 /* try match of command name only */
183 DBG_DEBUG(LC_LOGDOMAIN, "Searching for %s", commandName);
184 n=GWEN_XMLNode_FindFirstTag(cmds,
185 "command",
186 "name",
187 commandName);
188 while(n) {
189 if (!GWEN_XMLNode_GetProperty(n, "driver", 0))
190 return n;
191 n=GWEN_XMLNode_FindNextTag(n, "command", "name", commandName);
192 } /* while */
193
194 return n;
195 }
196
197
198
LC_Client_FindCommandInCardNode(GWEN_XMLNODE * node,const char * commandName,const char * driverType,const char * readerType)199 GWEN_XMLNODE *LC_Client_FindCommandInCardNode(GWEN_XMLNODE *node,
200 const char *commandName,
201 const char *driverType,
202 const char *readerType) {
203 GWEN_XMLNODE *n;
204
205 n=LC_Client__FindCommandInCardNode(node, commandName,
206 driverType, readerType);
207 if (n==0)
208 n=LC_Client__FindCommandInCardNode(node, commandName,
209 driverType, 0);
210 if (n==0)
211 n=LC_Client__FindCommandInCardNode(node, commandName,
212 0, 0);
213
214 return n;
215 }
216
217
218
LC_Client_FindCommandInCardFamily(GWEN_XMLNODE * cardNodes,GWEN_STRINGLIST * handled,const char * cardType,const char * commandName,const char * driverType,const char * readerType)219 GWEN_XMLNODE *LC_Client_FindCommandInCardFamily(GWEN_XMLNODE *cardNodes,
220 GWEN_STRINGLIST *handled,
221 const char *cardType,
222 const char *commandName,
223 const char *driverType,
224 const char *readerType){
225 GWEN_XMLNODE *node;
226
227 DBG_DEBUG(LC_LOGDOMAIN, "Searching in family of \"%s\"", cardType);
228 node=GWEN_XMLNode_FindFirstTag(cardNodes, "card", "name", cardType);
229 if (node) {
230 while(node) {
231 GWEN_XMLNODE *n;
232 const char *parent;
233
234 cardType=GWEN_XMLNode_GetProperty(node, "name", 0);
235 assert(cardType);
236 DBG_VERBOUS(LC_LOGDOMAIN, "Searching in \"%s\" (%s/%s)",
237 GWEN_XMLNode_GetProperty(node, "name", "(noname)"),
238 driverType?driverType:"(none)",
239 readerType?readerType:"(none)");
240 if (!GWEN_StringList_HasString(handled, cardType)) {
241 n=LC_Client_FindCommandInCardNode(node, commandName,
242 driverType, readerType);
243 GWEN_StringList_AppendString(handled, cardType, 0, 1);
244 if (n) {
245 return n;
246 }
247 }
248 else {
249 DBG_INFO(LC_LOGDOMAIN, "Card type \"%s\" already handled",
250 cardType);
251 }
252
253 /* search in parents */
254 parent=GWEN_XMLNode_GetProperty(node, "extends", 0);
255 if (!parent) {
256 DBG_VERBOUS(LC_LOGDOMAIN, "Card type \"%s\" has no parent",
257 GWEN_XMLNode_GetProperty(node, "name", "(noname)"));
258 break;
259 }
260 DBG_DEBUG(LC_LOGDOMAIN, "Searching for extended card \"%s\"", parent);
261 node=GWEN_XMLNode_FindFirstTag(cardNodes,
262 "card",
263 "name",
264 parent);
265 if (!node) {
266 DBG_WARN(LC_LOGDOMAIN,
267 "Extended card \"%s\" not found",
268 parent);
269 break;
270 }
271 DBG_DEBUG(LC_LOGDOMAIN, "Searching in parent \"%s\"", parent);
272 } /* while */
273 }
274 else {
275 DBG_INFO(LC_LOGDOMAIN, "Card \"%s\" not found", cardType);
276 }
277 DBG_DEBUG(0, "Command \"%s\" not found", commandName);
278 return 0;
279 }
280
281
282
283 GWEN_XMLNODE*
LC_Client_FindCommandInCardTypes(GWEN_XMLNODE * cardNodes,const GWEN_STRINGLIST * cardTypes,const char * commandName,const char * driverType,const char * readerType)284 LC_Client_FindCommandInCardTypes(GWEN_XMLNODE *cardNodes,
285 const GWEN_STRINGLIST *cardTypes,
286 const char *commandName,
287 const char *driverType,
288 const char *readerType){
289 GWEN_STRINGLIST *handled;
290 GWEN_STRINGLISTENTRY *se;
291 GWEN_XMLNODE *node=0;
292
293 handled=GWEN_StringList_new();
294 se=GWEN_StringList_FirstEntry(cardTypes);
295 while(se) {
296 const char *s;
297
298 s=GWEN_StringListEntry_Data(se);
299 assert(s);
300
301 DBG_INFO(LC_LOGDOMAIN,
302 "Searching in card type \"%s\"", s);
303 node=LC_Client_FindCommandInCardFamily(cardNodes,
304 handled,
305 s,
306 commandName,
307 driverType,
308 readerType);
309 if (node)
310 break;
311 se=GWEN_StringListEntry_Next(se);
312 } /* while */
313
314 return node;
315 }
316
317
318
LC_Client_FindCardCommand(LC_CLIENT * cl,LC_CARD * card,const char * commandName)319 GWEN_XMLNODE *LC_Client_FindCardCommand(LC_CLIENT *cl,
320 LC_CARD *card,
321 const char *commandName) {
322 GWEN_XMLNODE *n;
323
324 n=LC_Card_GetCardNode(card);
325 if (n) {
326 const char *cardName;
327 GWEN_STRINGLIST *sl;
328
329 cardName=GWEN_XMLNode_GetProperty(n, "name", 0);
330 assert(cardName);
331 DBG_INFO(LC_LOGDOMAIN, "Preselected card type \"%s\"", cardName);
332
333 sl=GWEN_StringList_new();
334 n=LC_Client_FindCommandInCardFamily(cl->cardNodes,
335 sl,
336 cardName,
337 commandName,
338 LC_Card_GetDriverType(card),
339 LC_Card_GetReaderType(card));
340 GWEN_StringList_free(sl);
341 if (n)
342 return n;
343 return 0;
344 }
345 return LC_Client_FindCommandInCardTypes(cl->cardNodes,
346 LC_Card_GetCardTypes(card),
347 commandName,
348 LC_Card_GetDriverType(card),
349 LC_Card_GetReaderType(card));
350 }
351
352
353
LC_Client_FindResultInNode(GWEN_XMLNODE * node,int sw1,int sw2)354 GWEN_XMLNODE *LC_Client_FindResultInNode(GWEN_XMLNODE *node,
355 int sw1, int sw2) {
356 GWEN_XMLNODE *rnode;
357 GWEN_XMLNODE *n;
358 int lsw1, lsw2;
359
360 DBG_DEBUG(0, "Searching for result type of %02x/%02x", sw1, sw2);
361 while(node) {
362 rnode=GWEN_XMLNode_FindNode(node,
363 GWEN_XMLNodeTypeTag,
364 "results");
365 if (rnode) {
366 /* first try exact match */
367 n=GWEN_XMLNode_GetFirstTag(rnode);
368 while(n) {
369 if (1==sscanf(GWEN_XMLNode_GetProperty(n, "sw1", "-1"),
370 "%i", &lsw1) &&
371 1==sscanf(GWEN_XMLNode_GetProperty(n, "sw2", "-1"),
372 "%i", &lsw2)) {
373 DBG_VERBOUS(0, "Checking %02x/%02x", lsw1, lsw2);
374 if (lsw1==sw1 && lsw2==sw2) {
375 return n;
376 }
377 }
378 else {
379 DBG_WARN(0, "Bad SW1 or SW2 value");
380 }
381 n=GWEN_XMLNode_GetNextTag(n);
382 } /* while */
383
384 /* try SW1 only */
385 n=GWEN_XMLNode_GetFirstTag(rnode);
386 while(n) {
387 if (1==sscanf(GWEN_XMLNode_GetProperty(n, "sw1", "-1"),
388 "%i", &lsw1) &&
389 1==sscanf(GWEN_XMLNode_GetProperty(n, "sw2", "-1"),
390 "%i", &lsw2)) {
391 if (lsw1==sw1 && lsw2==-1) {
392 return n;
393 }
394 }
395 else {
396 DBG_WARN(0, "Bad SW1 or SW2 value");
397 }
398 n=GWEN_XMLNode_GetNextTag(n);
399 } /* while */
400 } /* if rnode */
401
402 /* select parent */
403 node=GWEN_XMLNode_GetParent(node);
404 }
405
406 return 0;
407 }
408
409
410
LC_Client_FindResult(LC_CLIENT * cl,GWEN_XMLNODE * cmdNode,int sw1,int sw2)411 GWEN_XMLNODE *LC_Client_FindResult(LC_CLIENT *cl,
412 GWEN_XMLNODE *cmdNode,
413 int sw1, int sw2) {
414 GWEN_XMLNODE *tmpNode;
415 GWEN_XMLNODE *rnode;
416
417 /* first find result in command node */
418 rnode=LC_Client_FindResultInNode(cmdNode, sw1, sw2);
419 if (rnode)
420 return rnode;
421 rnode=LC_Client_FindResultInNode(cmdNode, -1, -1);
422 if (rnode)
423 return rnode;
424
425 /* try in node <commands> */
426 tmpNode=GWEN_XMLNode_GetParent(cmdNode);
427 if (!tmpNode)
428 return 0;
429 rnode=LC_Client_FindResultInNode(tmpNode, sw1, sw2);
430 if (rnode)
431 return rnode;
432 rnode=LC_Client_FindResultInNode(tmpNode, -1, -1);
433 if (rnode)
434 return rnode;
435
436 /* try in current card node */
437 tmpNode=GWEN_XMLNode_GetParent(tmpNode);
438 if (!tmpNode)
439 return 0;
440 rnode=LC_Client_FindResultInNode(tmpNode, sw1, sw2);
441 if (rnode)
442 return rnode;
443 rnode=LC_Client_FindResultInNode(tmpNode, -1, -1);
444 if (rnode)
445 return rnode;
446
447 /* try in parents */
448 for(;;) {
449 const char *parent;
450
451 parent=GWEN_XMLNode_GetProperty(tmpNode, "extends", 0);
452 if (!parent) {
453 break;
454 }
455 tmpNode=GWEN_XMLNode_FindFirstTag(cl->cardNodes,
456 "card",
457 "name",
458 parent);
459 if (!tmpNode)
460 break;
461
462 rnode=LC_Client_FindResultInNode(tmpNode, sw1, sw2);
463 if (rnode) {
464 break;
465 }
466 rnode=LC_Client_FindResultInNode(tmpNode, -1, -1);
467 if (rnode) {
468 break;
469 }
470 } /* for */
471
472 return rnode;
473 }
474
475
476
LC_Client_FindResponseInNode(GWEN_XMLNODE * cmd,const char * typ)477 GWEN_XMLNODE *LC_Client_FindResponseInNode(GWEN_XMLNODE *cmd,
478 const char *typ) {
479 GWEN_XMLNODE *rnode;
480 GWEN_XMLNODE *n;
481 const char *ltyp;
482
483 DBG_DEBUG(0, "Searching for response type \"%s\"", typ);
484 rnode=GWEN_XMLNode_FindNode(cmd,
485 GWEN_XMLNodeTypeTag,
486 "responses");
487 if (!rnode) {
488 DBG_DEBUG(0, "No <responses> tag in command definition");
489 return 0;
490 }
491
492 /* first try exact match */
493 n=GWEN_XMLNode_GetFirstTag(rnode);
494 while(n) {
495 ltyp=GWEN_XMLNode_GetProperty(n, "type", 0);
496 if (ltyp) {
497 if (strcasecmp(ltyp, typ)==0)
498 return n;
499 }
500 n=GWEN_XMLNode_GetNextTag(n);
501 } /* while */
502
503 /* then try a response without any type */
504 n=GWEN_XMLNode_GetFirstTag(rnode);
505 while(n) {
506 ltyp=GWEN_XMLNode_GetProperty(n, "type", 0);
507 if (!ltyp)
508 return n;
509 n=GWEN_XMLNode_GetNextTag(n);
510 } /* while */
511
512 return 0;
513 }
514
515
516
LC_Client_FindResponse(LC_CLIENT * cl,GWEN_XMLNODE * cmdNode,const char * typ)517 GWEN_XMLNODE *LC_Client_FindResponse(LC_CLIENT *cl,
518 GWEN_XMLNODE *cmdNode,
519 const char *typ) {
520 GWEN_XMLNODE *tmpNode;
521 GWEN_XMLNODE *rnode;
522
523 /* first find response in command node */
524 rnode=LC_Client_FindResponseInNode(cmdNode, typ);
525 if (rnode)
526 return rnode;
527
528 /* try in node <commands> */
529 tmpNode=GWEN_XMLNode_GetParent(cmdNode);
530 if (!tmpNode)
531 return 0;
532 rnode=LC_Client_FindResponseInNode(tmpNode, typ);
533 if (rnode)
534 return rnode;
535
536 /* try in current card node */
537 tmpNode=GWEN_XMLNode_GetParent(tmpNode);
538 if (!tmpNode)
539 return 0;
540 rnode=LC_Client_FindResponseInNode(tmpNode, typ);
541 if (rnode)
542 return rnode;
543
544 /* try in parents */
545 for(;;) {
546 const char *parent;
547
548 parent=GWEN_XMLNode_GetProperty(tmpNode, "extends", 0);
549 if (!parent) {
550 break;
551 }
552 tmpNode=GWEN_XMLNode_FindFirstTag(cl->cardNodes,
553 "card",
554 "name",
555 parent);
556 if (!tmpNode)
557 break;
558
559 rnode=LC_Client_FindResponseInNode(tmpNode, typ);
560 if (rnode) {
561 break;
562 }
563 } /* for */
564
565 return rnode;
566 }
567
568
569
LC_Client__BuildApdu(LC_CLIENT * cl,GWEN_XMLNODE * node,GWEN_DB_NODE * cmdData,GWEN_BUFFER * gbuf)570 LC_CLIENT_RESULT LC_Client__BuildApdu(LC_CLIENT *cl,
571 GWEN_XMLNODE *node,
572 GWEN_DB_NODE *cmdData,
573 GWEN_BUFFER *gbuf) {
574 GWEN_XMLNODE *sendNode;
575 GWEN_XMLNODE *dataNode;
576 GWEN_XMLNODE *apduNode;
577 GWEN_BUFFER *dataBuffer;
578 unsigned int i;
579 int j;
580
581 assert(cl);
582
583 sendNode=GWEN_XMLNode_FindNode(node, GWEN_XMLNodeTypeTag, "send");
584 if (!sendNode) {
585 DBG_INFO(LC_LOGDOMAIN,
586 "No <send> tag in command definition, do not execute");
587 return LC_Client_ResultDontExecute;
588 }
589
590 apduNode=GWEN_XMLNode_FindNode(sendNode,
591 GWEN_XMLNodeTypeTag, "apdu");
592 if (!apduNode) {
593 DBG_ERROR(LC_LOGDOMAIN, "No <apdu> tag in command definition");
594 abort();
595 }
596
597 dataBuffer=GWEN_Buffer_new(0, 256, 0, 1);
598 dataNode=GWEN_XMLNode_FindNode(sendNode,
599 GWEN_XMLNodeTypeTag, "data");
600 if (dataNode) {
601 /* there is a data node, sample data */
602 if (GWEN_MsgEngine_CreateMessageFromNode(cl->msgEngine,
603 dataNode,
604 dataBuffer,
605 cmdData)) {
606 DBG_ERROR(LC_LOGDOMAIN, "Error creating data for APDU");
607 GWEN_Buffer_free(dataBuffer);
608 GWEN_Buffer_AppendString(gbuf, "Error creating APDU data from command");
609 return -1;
610 }
611 }
612
613 if (GWEN_MsgEngine_CreateMessageFromNode(cl->msgEngine,
614 apduNode,
615 gbuf,
616 cmdData)) {
617 DBG_ERROR(LC_LOGDOMAIN, "Error creating APDU");
618 GWEN_Buffer_free(dataBuffer);
619 GWEN_Buffer_AppendString(gbuf, "Error creating APDU from command");
620 return -1;
621 }
622
623 i=GWEN_Buffer_GetUsedBytes(dataBuffer);
624 if (i) {
625 GWEN_Buffer_AppendByte(gbuf, (unsigned char)i);
626 GWEN_Buffer_AppendBuffer(gbuf, dataBuffer);
627 }
628 GWEN_Buffer_free(dataBuffer);
629
630 j=0;
631 if (1!=sscanf(GWEN_XMLNode_GetProperty(apduNode, "lr", "0"),
632 "%i", &j))
633 j=0;
634
635 if (j!=-1) {
636 j=GWEN_DB_GetIntValue(cmdData, "lr", 0, -1);
637 if (j==-1) {
638 if (1!=sscanf(GWEN_XMLNode_GetProperty(apduNode, "lr", "-1"),
639 "%i", &j))
640 j=-1;
641 }
642 }
643 if (j>=0)
644 GWEN_Buffer_AppendByte(gbuf, (unsigned char)j);
645
646 return 0;
647 }
648
649
650
LC_Client_ParseResult(LC_CLIENT * cl,GWEN_XMLNODE * node,GWEN_BUFFER * gbuf,GWEN_DB_NODE * rspData)651 int LC_Client_ParseResult(LC_CLIENT *cl,
652 GWEN_XMLNODE *node,
653 GWEN_BUFFER *gbuf,
654 GWEN_DB_NODE *rspData){
655 unsigned int i;
656 int sw1, sw2;
657 GWEN_DB_NODE *dbTmp;
658 GWEN_XMLNODE *rnode;
659
660 GWEN_Buffer_Rewind(gbuf); /* just in case ... */
661 i=GWEN_Buffer_GetUsedBytes(gbuf);
662 if (i<2) {
663 DBG_ERROR(LC_LOGDOMAIN, "Answer too small (less than 2 bytes)");
664 return -1;
665 }
666 sw1=(unsigned char)(GWEN_Buffer_GetStart(gbuf)[i-2]);
667 sw2=(unsigned char)(GWEN_Buffer_GetStart(gbuf)[i-1]);
668 GWEN_Buffer_Crop(gbuf, 0, i-2);
669 /* store result */
670 dbTmp=GWEN_DB_GetGroup(rspData,
671 GWEN_DB_FLAGS_DEFAULT |
672 GWEN_DB_FLAGS_OVERWRITE_GROUPS,
673 "result");
674 assert(dbTmp);
675 GWEN_DB_SetIntValue(dbTmp, GWEN_DB_FLAGS_DEFAULT,
676 "sw1", sw1);
677 GWEN_DB_SetIntValue(dbTmp, GWEN_DB_FLAGS_DEFAULT,
678 "sw2", sw2);
679
680 rnode=LC_Client_FindResult(cl, node, sw1, sw2);
681 if (rnode) {
682 const char *t;
683 GWEN_XMLNODE *tnode;
684 GWEN_BUFFER *txtbuf;
685 int first;
686
687 t=GWEN_XMLNode_GetProperty(rnode, "type", "success");
688 DBG_INFO(0, "Result is: %s", t);
689 GWEN_DB_SetCharValue(dbTmp,
690 GWEN_DB_FLAGS_DEFAULT,
691 "type", t);
692 /* get text */
693 txtbuf=GWEN_Buffer_new(0, 256, 0, 1);
694 first=1;
695 tnode=GWEN_XMLNode_GetFirstData(rnode);
696 while(tnode) {
697 const char *p;
698
699 p=GWEN_XMLNode_GetData(tnode);
700 if (p) {
701 if (!first)
702 GWEN_Buffer_AppendByte(txtbuf, ' ');
703 GWEN_Buffer_AppendString(txtbuf, p);
704 }
705 if (first)
706 first=0;
707 tnode=GWEN_XMLNode_GetNextData(tnode);
708 } /* while */
709
710 if (GWEN_Buffer_GetUsedBytes(txtbuf))
711 GWEN_DB_SetCharValue(dbTmp, GWEN_DB_FLAGS_DEFAULT, "text",
712 GWEN_Buffer_GetStart(txtbuf));
713 GWEN_Buffer_free(txtbuf);
714 }
715 else {
716 DBG_ERROR(LC_LOGDOMAIN,
717 "Result for %02x/%02x not found, assuming error",
718 sw1, sw2);
719 GWEN_DB_SetCharValue(dbTmp,
720 GWEN_DB_FLAGS_DEFAULT,
721 "type", "error");
722 GWEN_DB_SetCharValue(dbTmp,
723 GWEN_DB_FLAGS_DEFAULT,
724 "text", "Result not found");
725 }
726
727 return 0;
728 }
729
730
731
LC_Client_ParseResponse(LC_CLIENT * cl,GWEN_XMLNODE * node,GWEN_BUFFER * gbuf,GWEN_DB_NODE * rspData)732 int LC_Client_ParseResponse(LC_CLIENT *cl,
733 GWEN_XMLNODE *node,
734 GWEN_BUFFER *gbuf,
735 GWEN_DB_NODE *rspData){
736 GWEN_DB_NODE *dbTmp;
737 GWEN_XMLNODE *rnode;
738 const char *p;
739
740 assert(cl);
741
742 GWEN_Buffer_Rewind(gbuf); /* just in case ... */
743
744 p=GWEN_DB_GetCharValue(rspData, "result/type", 0, 0);
745 if (!p) {
746 DBG_ERROR(LC_LOGDOMAIN, "No result type given");
747 return -1;
748 }
749 dbTmp=GWEN_DB_GetGroup(rspData,
750 GWEN_DB_FLAGS_DEFAULT |
751 GWEN_DB_FLAGS_OVERWRITE_GROUPS,
752 "response");
753 if (!dbTmp) {
754 DBG_ERROR(LC_LOGDOMAIN, "No matching response tag found");
755 return -1;
756 }
757
758 rnode=LC_Client_FindResponse(cl, node, p);
759 if (!rnode) {
760 DBG_DEBUG(0, "Did not find response");
761 if (GWEN_Buffer_GetUsedBytes(gbuf)) {
762 GWEN_DB_SetBinValue(dbTmp,
763 GWEN_DB_FLAGS_OVERWRITE_VARS,
764 "data",
765 GWEN_Buffer_GetStart(gbuf),
766 GWEN_Buffer_GetUsedBytes(gbuf));
767 }
768 }
769 else {
770 if (GWEN_MsgEngine_ParseMessage(cl->msgEngine,
771 rnode,
772 gbuf,
773 dbTmp,
774 GWEN_MSGENGINE_READ_FLAGS_DEFAULT)){
775 DBG_ERROR(LC_LOGDOMAIN, "Error parsing response");
776 return -1;
777 }
778 }
779
780 return 0;
781 }
782
783
784
LC_Client_ParseAnswer(LC_CLIENT * cl,GWEN_XMLNODE * node,GWEN_BUFFER * gbuf,GWEN_DB_NODE * rspData)785 int LC_Client_ParseAnswer(LC_CLIENT *cl,
786 GWEN_XMLNODE *node,
787 GWEN_BUFFER *gbuf,
788 GWEN_DB_NODE *rspData){
789 assert(cl);
790
791 if (LC_Client_ParseResult(cl, node, gbuf, rspData)) {
792 DBG_INFO(0, "Error parsing result");
793 return -1;
794 }
795
796 if (LC_Client_ParseResponse(cl, node, gbuf, rspData)){
797 DBG_INFO(0, "Error parsing response");
798 return -1;
799 }
800
801 return 0;
802 }
803
804
805
LC_Client_BuildApdu(LC_CLIENT * cl,LC_CARD * card,const char * command,GWEN_DB_NODE * cmdData,GWEN_BUFFER * buf)806 LC_CLIENT_RESULT LC_Client_BuildApdu(LC_CLIENT *cl,
807 LC_CARD *card,
808 const char *command,
809 GWEN_DB_NODE *cmdData,
810 GWEN_BUFFER *buf) {
811 GWEN_XMLNODE *node;
812 LC_CLIENT_RESULT res;
813
814 DBG_INFO(LC_LOGDOMAIN, "Building APDU for command \"%s\"", command);
815 /* lookup card command */
816 DBG_INFO(LC_LOGDOMAIN, "- looking up command");
817 node=LC_Card_FindCommand(card, command);
818 if (!node) {
819 DBG_INFO(LC_LOGDOMAIN, "Command \"%s\" not found",
820 command);
821 return LC_Client_ResultNotFound;
822 }
823
824 /* build APDU */
825 DBG_INFO(LC_LOGDOMAIN, "- building APDU");
826 res=LC_Client__BuildApdu(cl, node, cmdData, buf);
827 if (res!=LC_Client_ResultOk) {
828 DBG_INFO(LC_LOGDOMAIN,
829 "Error building APDU for command \"%s\" (%d)",
830 command, res);
831 return res;
832 }
833
834 return LC_Client_ResultOk;
835 }
836
837
838
LC_Client_ExecCommand(LC_CLIENT * cl,LC_CARD * card,const char * commandName,GWEN_DB_NODE * cmdData,GWEN_DB_NODE * rspData)839 LC_CLIENT_RESULT LC_Client_ExecCommand(LC_CLIENT *cl,
840 LC_CARD *card,
841 const char *commandName,
842 GWEN_DB_NODE *cmdData,
843 GWEN_DB_NODE *rspData) {
844 GWEN_XMLNODE *node;
845 GWEN_BUFFER *buf;
846 GWEN_BUFFER *rbuf;
847 LC_CLIENT_RESULT res;
848 LC_CLIENT_CMDTARGET t;
849 const char *s;
850
851 DBG_INFO(LC_LOGDOMAIN, "Executing command \"%s\"", commandName);
852
853 /* lookup card command */
854 DBG_INFO(LC_LOGDOMAIN, "- looking up command");
855 node=LC_Card_FindCommand(card, commandName);
856 if (!node) {
857 DBG_INFO(LC_LOGDOMAIN, "Command \"%s\" not found",
858 commandName);
859 return LC_Client_ResultNotFound;
860 }
861
862 /* determine target of the command */
863 DBG_INFO(LC_LOGDOMAIN, "- determining target");
864 t=LC_Client_CmdTargetCard;
865 s=GWEN_XMLNode_GetProperty(node, "target", "card");
866 if (s) {
867 if (strcasecmp(s, "card")==0)
868 t=LC_Client_CmdTargetCard;
869 else if (strcasecmp(s, "reader")==0)
870 t=LC_Client_CmdTargetReader;
871 else {
872 DBG_ERROR(LC_LOGDOMAIN,
873 "Invalid target given in command \"%s\": %s",
874 commandName, s);
875 return LC_Client_ResultCfgError;
876 }
877 }
878
879 /* build APDU */
880 DBG_INFO(LC_LOGDOMAIN, "- building APDU");
881 buf=GWEN_Buffer_new(0, 256, 0, 1);
882 res=LC_Client__BuildApdu(cl, node, cmdData, buf);
883 if (res!=LC_Client_ResultOk) {
884 DBG_INFO(LC_LOGDOMAIN,
885 "Error building APDU for command \"%s\" (%d)",
886 commandName, res);
887 GWEN_Buffer_free(buf);
888 return res;
889 }
890
891 /* send APDU */
892 DBG_INFO(LC_LOGDOMAIN, "- sending APDU, waiting for answer");
893 rbuf=GWEN_Buffer_new(0, 256, 0, 1);
894 res=LC_Card_ExecApdu(card,
895 GWEN_Buffer_GetStart(buf),
896 GWEN_Buffer_GetUsedBytes(buf),
897 rbuf,
898 t);
899 if (res!=LC_Client_ResultOk) {
900 DBG_INFO(LC_LOGDOMAIN, "here (%d)", res);
901 GWEN_Buffer_free(rbuf);
902 GWEN_Buffer_free(buf);
903 return res;
904 }
905 GWEN_Buffer_free(buf);
906
907 /* parse answer */
908 DBG_INFO(LC_LOGDOMAIN, "- parsing response");
909 if (LC_Client_ParseAnswer(cl, node, rbuf, rspData)) {
910 DBG_INFO(LC_LOGDOMAIN, "Error parsing answer");
911 GWEN_Buffer_free(rbuf);
912 return LC_Client_ResultCmdError;
913 }
914
915 /* store response data */
916 if (GWEN_Buffer_GetUsedBytes(rbuf)) {
917 GWEN_DB_SetBinValue(rspData, GWEN_DB_FLAGS_OVERWRITE_VARS,
918 "data",
919 GWEN_Buffer_GetStart(rbuf),
920 GWEN_Buffer_GetUsedBytes(rbuf));
921 }
922 GWEN_Buffer_free(rbuf);
923
924 /* check for error result of command */
925 s=GWEN_DB_GetCharValue(rspData, "result/type", 0, "error");
926 if (strcasecmp(s, "success")!=0) {
927 DBG_INFO(LC_LOGDOMAIN, "Command execution error flagged by card (%s)",
928 s?s:"(none)");
929 return LC_Client_ResultCmdError;
930 }
931
932 /* done */
933 return LC_Client_ResultOk;
934 }
935
936
937
938
939
940
941
942
943
944