Check-in [330efa4f3b]
Overview
Comment:Updated ignores

Updated read_tlv to return a list

Added a free_tlv function

Updated value->str conversion functions to be more flexible/direct

Added sample code to select all PKI applets/files

Simplified TLV entity

Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1:330efa4f3bb6e0e6f40dd55c33bb6290ff0e41d1
User & Date: rkeene on 2010-05-12 19:35:41
Other Links: manifest | tags
Context
2010-05-12
21:52
Added routines for reading certificates

Updated OpenSession to use PC/SC certificates

Comment and debugging update

Updated to read in larger chunks to improve speed check-in: 06e07b8f0d user: rkeene tags: trunk

19:35
Updated ignores

Updated read_tlv to return a list

Added a free_tlv function

Updated value->str conversion functions to be more flexible/direct

Added sample code to select all PKI applets/files

Simplified TLV entity check-in: 330efa4f3b user: rkeene tags: trunk

17:25
Updated PC/SC error messages to include text return value as well as numeric value

Minor reorganization check-in: 2d8b4030f7 user: rkeene tags: trunk

Changes

Modified cackey.c from [d5b94d106d] to [e9e3a11241].

   172    172   		fprintf(stderr, "\n");
   173    173   	}
   174    174   
   175    175   	return(retval);
   176    176   }
   177    177   
   178    178   static const char *CACKEY_DEBUG_FUNC_TAG_TO_STR(unsigned char tag) {
   179         -	const char *retval = NULL;
   180         -
   181    179   	switch (tag) {
   182    180   		case GSCIS_TAG_CARDID:
   183         -			retval = "GSCIS_TAG_CARDID";
   184         -			break;
          181  +			return("GSCIS_TAG_CARDID");
   185    182   		case GSCIS_TAG_CCC_VER:
   186         -			retval = "GSCIS_TAG_CCC_VER";
   187         -			break;
          183  +			return("GSCIS_TAG_CCC_VER");
   188    184   		case GSCIS_TAG_CCG_VER:
   189         -			retval = "GSCIS_TAG_CCG_VER";
   190         -			break;
          185  +			return("GSCIS_TAG_CCG_VER");
   191    186   		case GSCIS_TAG_CARDURL:
   192         -			retval = "GSCIS_TAG_CARDURL";
   193         -			break;
          187  +			return("GSCIS_TAG_CARDURL");
   194    188   		case GSCIS_TAG_PKCS15:
   195         -			retval = "GSCIS_TAG_PKCS15";
   196         -			break;
          189  +			return("GSCIS_TAG_PKCS15");
   197    190   		case GSCIS_TAG_REG_DATA_MODEL:
   198         -			retval = "GSCIS_TAG_REG_DATA_MODEL";
   199         -			break;
          191  +			return("GSCIS_TAG_REG_DATA_MODEL");
   200    192   		case GSCIS_TAG_ACR_TABLE:
   201         -			retval = "GSCIS_TAG_ACR_TABLE";
   202         -			break;
          193  +			return("GSCIS_TAG_ACR_TABLE");
   203    194   		case GSCIS_TAG_CARD_APDU:
   204         -			retval = "GSCIS_TAG_CARD_APDU";
   205         -			break;
          195  +			return("GSCIS_TAG_CARD_APDU");
   206    196   		case GSCIS_TAG_REDIRECTION:
   207         -			retval = "GSCIS_TAG_REDIRECTION";
   208         -			break;
          197  +			return("GSCIS_TAG_REDIRECTION");
   209    198   		case GSCIS_TAG_CT:
   210         -			retval = "GSCIS_TAG_CT";
   211         -			break;
          199  +			return("GSCIS_TAG_CT");
   212    200   		case GSCIS_TAG_ST:
   213         -			retval = "GSCIS_TAG_ST";
   214         -			break;
          201  +			return("GSCIS_TAG_ST");
   215    202   		case GSCIS_TAG_NEXTCCC:
   216         -			retval = "GSCIS_TAG_NEXTCCC";
   217         -			break;
          203  +			return("GSCIS_TAG_NEXTCCC");
   218    204   		case GSCIS_TAG_FNAME:
   219         -			retval = "GSCIS_TAG_FNAME";
   220         -			break;
          205  +			return("GSCIS_TAG_FNAME");
   221    206   		case GSCIS_TAG_MNAME:
   222         -			retval = "GSCIS_TAG_MNAME";
   223         -			break;
          207  +			return("GSCIS_TAG_MNAME");
   224    208   		case GSCIS_TAG_LNAME:
   225         -			retval = "GSCIS_TAG_LNAME";
   226         -			break;
          209  +			return("GSCIS_TAG_LNAME");
   227    210   		case GSCIS_TAG_SUFFIX:
   228         -			retval = "GSCIS_TAG_SUFFIX";
   229         -			break;
          211  +			return("GSCIS_TAG_SUFFIX");
   230    212   		case GSCIS_TAG_GOVT_AGENCY:
   231         -			retval = "GSCIS_TAG_GOVT_AGENCY";
   232         -			break;
          213  +			return("GSCIS_TAG_GOVT_AGENCY");
   233    214   		case GSCIS_TAG_BUREAU:
   234         -			retval = "GSCIS_TAG_BUREAU";
   235         -			break;
          215  +			return("GSCIS_TAG_BUREAU");
   236    216   		case GSCIS_TAG_BUREAU_CODE:
   237         -			retval = "GSCIS_TAG_BUREAU_CODE";
   238         -			break;
          217  +			return("GSCIS_TAG_BUREAU_CODE");
   239    218   		case GSCIS_TAG_DEPT_CODE:
   240         -			retval = "GSCIS_TAG_DEPT_CODE";
   241         -			break;
          219  +			return("GSCIS_TAG_DEPT_CODE");
   242    220   		case GSCIS_TAG_TITLE:
   243         -			retval = "GSCIS_TAG_TITLE";
   244         -			break;
          221  +			return("GSCIS_TAG_TITLE");
   245    222   		case GSCIS_TAG_BUILDING:
   246         -			retval = "GSCIS_TAG_BUILDING";
   247         -			break;
          223  +			return("GSCIS_TAG_BUILDING");
   248    224   		case GSCIS_TAG_OFFICE_ADDR1:
   249         -			retval = "GSCIS_TAG_OFFICE_ADDR1";
   250         -			break;
          225  +			return("GSCIS_TAG_OFFICE_ADDR1");
   251    226   		case GSCIS_TAG_OFFICE_ADDR2:
   252         -			retval = "GSCIS_TAG_OFFICE_ADDR2";
   253         -			break;
          227  +			return("GSCIS_TAG_OFFICE_ADDR2");
   254    228   		case GSCIS_TAG_OFFICE_CITY:
   255         -			retval = "GSCIS_TAG_OFFICE_CITY";
   256         -			break;
          229  +			return("GSCIS_TAG_OFFICE_CITY");
   257    230   		case GSCIS_TAG_OFFICE_STATE:
   258         -			retval = "GSCIS_TAG_OFFICE_STATE";
   259         -			break;
          231  +			return("GSCIS_TAG_OFFICE_STATE");
   260    232   		case GSCIS_TAG_OFFICE_ZIP:
   261         -			retval = "GSCIS_TAG_OFFICE_ZIP";
   262         -			break;
          233  +			return("GSCIS_TAG_OFFICE_ZIP");
   263    234   		case GSCIS_TAG_OFFICE_COUNTRY:
   264         -			retval = "GSCIS_TAG_OFFICE_COUNTRY";
   265         -			break;
          235  +			return("GSCIS_TAG_OFFICE_COUNTRY");
   266    236   		case GSCIS_TAG_OFFICE_PHONE:
   267         -			retval = "GSCIS_TAG_OFFICE_PHONE";
   268         -			break;
          237  +			return("GSCIS_TAG_OFFICE_PHONE");
   269    238   		case GSCIS_TAG_OFFICE_PHONE_EXT:
   270         -			retval = "GSCIS_TAG_OFFICE_PHONE_EXT";
   271         -			break;
          239  +			return("GSCIS_TAG_OFFICE_PHONE_EXT");
   272    240   		case GSCIS_TAG_OFFICE_FAX:
   273         -			retval = "GSCIS_TAG_OFFICE_FAX";
   274         -			break;
          241  +			return("GSCIS_TAG_OFFICE_FAX");
   275    242   		case GSCIS_TAG_OFFICE_EMAIL:
   276         -			retval = "GSCIS_TAG_OFFICE_EMAIL";
   277         -			break;
          243  +			return("GSCIS_TAG_OFFICE_EMAIL");
   278    244   		case GSCIS_TAG_OFFICE_ROOM:
   279         -			retval = "GSCIS_TAG_OFFICE_ROOM";
   280         -			break;
          245  +			return("GSCIS_TAG_OFFICE_ROOM");
   281    246   		case GSCIS_TAG_NONGOV_AGENCY:
   282         -			retval = "GSCIS_TAG_NONGOV_AGENCY";
   283         -			break;
          247  +			return("GSCIS_TAG_NONGOV_AGENCY");
   284    248   		case GSCIS_TAG_SSN_DESIGNATOR:
   285         -			retval = "GSCIS_TAG_SSN_DESIGNATOR";
   286         -			break;
          249  +			return("GSCIS_TAG_SSN_DESIGNATOR");
   287    250   		case GSCIS_TAG_SSN:
   288         -			retval = "GSCIS_TAG_SSN";
   289         -			break;
          251  +			return("GSCIS_TAG_SSN");
   290    252   		case GSCIS_TAG_DOB:
   291         -			retval = "GSCIS_TAG_DOB";
   292         -			break;
          253  +			return("GSCIS_TAG_DOB");
   293    254   		case GSCIS_TAG_GENDER:
   294         -			retval = "GSCIS_TAG_GENDER";
   295         -			break;
          255  +			return("GSCIS_TAG_GENDER");
   296    256   		case GSCIS_TAG_USERID:
   297         -			retval = "GSCIS_TAG_USERID";
   298         -			break;
          257  +			return("GSCIS_TAG_USERID");
   299    258   		case GSCIS_TAG_DOMAIN:
   300         -			retval = "GSCIS_TAG_DOMAIN";
   301         -			break;
          259  +			return("GSCIS_TAG_DOMAIN");
   302    260   		case GSCIS_TAG_PASSWORD:
   303         -			retval = "GSCIS_TAG_PASSWORD";
   304         -			break;
          261  +			return("GSCIS_TAG_PASSWORD");
   305    262   		case GSCIS_TAG_ISSUERID:
   306         -			retval = "GSCIS_TAG_ISSUERID";
   307         -			break;
          263  +			return("GSCIS_TAG_ISSUERID");
   308    264   		case GSCIS_TAG_SERNO:
   309         -			retval = "GSCIS_TAG_SERNO";
   310         -			break;
          265  +			return("GSCIS_TAG_SERNO");
   311    266   		case GSCIS_TAG_ISSUE_DATE:
   312         -			retval = "GSCIS_TAG_ISSUE_DATE";
   313         -			break;
          267  +			return("GSCIS_TAG_ISSUE_DATE");
   314    268   		case GSCIS_TAG_EXPIRE_DATE:
   315         -			retval = "GSCIS_TAG_EXPIRE_DATE";
   316         -			break;
          269  +			return("GSCIS_TAG_EXPIRE_DATE");
   317    270   		case GSCIS_TAG_CARD_TYPE:
   318         -			retval = "GSCIS_TAG_CARD_TYPE";
   319         -			break;
          271  +			return("GSCIS_TAG_CARD_TYPE");
   320    272   		case GSCIS_TAG_SECURITY_CODE:
   321         -			retval = "GSCIS_TAG_SECURITY_CODE";
   322         -			break;
          273  +			return("GSCIS_TAG_SECURITY_CODE");
   323    274   		case GSCIS_TAG_CARDID_AID:
   324         -			retval = "GSCIS_TAG_CARDID_AID";
   325         -			break;
          275  +			return("GSCIS_TAG_CARDID_AID");
   326    276   		case GSCIS_TAG_CERTIFICATE:
   327         -			retval = "GSCIS_TAG_CERTIFICATE";
   328         -			break;
          277  +			return("GSCIS_TAG_CERTIFICATE");
   329    278   		case GSCIS_TAG_CERT_ISSUE_DATE:
   330         -			retval = "GSCIS_TAG_CERT_ISSUE_DATE";
   331         -			break;
          279  +			return("GSCIS_TAG_CERT_ISSUE_DATE");
   332    280   		case GSCIS_TAG_CERT_EXPIRE_DATE:
   333         -			retval = "GSCIS_TAG_CERT_EXPIRE_DATE";
   334         -			break;
          281  +			return("GSCIS_TAG_CERT_EXPIRE_DATE");
   335    282   	}
   336    283   
   337         -	if (retval == NULL) {
   338         -		retval = "UNKNOWN";
   339         -	}
   340         -
   341         -	return(retval);
          284  +	return("UNKNOWN");
   342    285   }
   343    286   
   344    287   static const char *CACKEY_DEBUG_FUNC_SCARDERR_TO_STR(LONG retcode) {
   345         -	const char *retval = NULL;
   346         -
   347    288   	switch (retcode) {
   348    289   		case SCARD_S_SUCCESS:
   349         -			retval = "SCARD_S_SUCCESS";
   350         -			break;
          290  +			return("SCARD_S_SUCCESS");
   351    291   		case SCARD_E_CANCELLED:
   352         -			retval = "SCARD_E_CANCELLED";
   353         -			break;
          292  +			return("SCARD_E_CANCELLED");
   354    293   		case SCARD_E_CANT_DISPOSE:
   355         -			retval = "SCARD_E_CANT_DISPOSE";
   356         -			break;
          294  +			return("SCARD_E_CANT_DISPOSE");
   357    295   		case SCARD_E_INSUFFICIENT_BUFFER:
   358         -			retval = "SCARD_E_INSUFFICIENT_BUFFER";
   359         -			break;
          296  +			return("SCARD_E_INSUFFICIENT_BUFFER");
   360    297   		case SCARD_E_INVALID_ATR:
   361         -			retval = "SCARD_E_INVALID_ATR";
   362         -			break;
          298  +			return("SCARD_E_INVALID_ATR");
   363    299   		case SCARD_E_INVALID_HANDLE:
   364         -			retval = "SCARD_E_INVALID_HANDLE";
   365         -			break;
          300  +			return("SCARD_E_INVALID_HANDLE");
   366    301   		case SCARD_E_INVALID_PARAMETER:
   367         -			retval = "SCARD_E_INVALID_PARAMETER";
   368         -			break;
          302  +			return("SCARD_E_INVALID_PARAMETER");
   369    303   		case SCARD_E_INVALID_TARGET:
   370         -			retval = "SCARD_E_INVALID_TARGET";
   371         -			break;
          304  +			return("SCARD_E_INVALID_TARGET");
   372    305   		case SCARD_E_INVALID_VALUE:
   373         -			retval = "SCARD_E_INVALID_VALUE";
   374         -			break;
          306  +			return("SCARD_E_INVALID_VALUE");
   375    307   		case SCARD_E_NO_MEMORY:
   376         -			retval = "SCARD_E_NO_MEMORY";
   377         -			break;
          308  +			return("SCARD_E_NO_MEMORY");
   378    309   		case SCARD_E_UNKNOWN_READER:
   379         -			retval = "SCARD_E_UNKNOWN_READER";
   380         -			break;
          310  +			return("SCARD_E_UNKNOWN_READER");
   381    311   		case SCARD_E_TIMEOUT:
   382         -			retval = "SCARD_E_TIMEOUT";
   383         -			break;
          312  +			return("SCARD_E_TIMEOUT");
   384    313   		case SCARD_E_SHARING_VIOLATION:
   385         -			retval = "SCARD_E_SHARING_VIOLATION";
   386         -			break;
          314  +			return("SCARD_E_SHARING_VIOLATION");
   387    315   		case SCARD_E_NO_SMARTCARD:
   388         -			retval = "SCARD_E_NO_SMARTCARD";
   389         -			break;
          316  +			return("SCARD_E_NO_SMARTCARD");
   390    317   		case SCARD_E_UNKNOWN_CARD:
   391         -			retval = "SCARD_E_UNKNOWN_CARD";
   392         -			break;
          318  +			return("SCARD_E_UNKNOWN_CARD");
   393    319   		case SCARD_E_PROTO_MISMATCH:
   394         -			retval = "SCARD_E_PROTO_MISMATCH";
   395         -			break;
          320  +			return("SCARD_E_PROTO_MISMATCH");
   396    321   		case SCARD_E_NOT_READY:
   397         -			retval = "SCARD_E_NOT_READY";
   398         -			break;
          322  +			return("SCARD_E_NOT_READY");
   399    323   		case SCARD_E_SYSTEM_CANCELLED:
   400         -			retval = "SCARD_E_SYSTEM_CANCELLED";
   401         -			break;
          324  +			return("SCARD_E_SYSTEM_CANCELLED");
   402    325   		case SCARD_E_NOT_TRANSACTED:
   403         -			retval = "SCARD_E_NOT_TRANSACTED";
   404         -			break;
          326  +			return("SCARD_E_NOT_TRANSACTED");
   405    327   		case SCARD_E_READER_UNAVAILABLE:
   406         -			retval = "SCARD_E_READER_UNAVAILABLE";
   407         -			break;
          328  +			return("SCARD_E_READER_UNAVAILABLE");
   408    329   		case SCARD_W_UNSUPPORTED_CARD:
   409         -			retval = "SCARD_W_UNSUPPORTED_CARD";
   410         -			break;
          330  +			return("SCARD_W_UNSUPPORTED_CARD");
   411    331   		case SCARD_W_UNRESPONSIVE_CARD:
   412         -			retval = "SCARD_W_UNRESPONSIVE_CARD";
   413         -			break;
          332  +			return("SCARD_W_UNRESPONSIVE_CARD");
   414    333   		case SCARD_W_UNPOWERED_CARD:
   415         -			retval = "SCARD_W_UNPOWERED_CARD";
   416         -			break;
          334  +			return("SCARD_W_UNPOWERED_CARD");
   417    335   		case SCARD_W_RESET_CARD:
   418         -			retval = "SCARD_W_RESET_CARD";
   419         -			break;
          336  +			return("SCARD_W_RESET_CARD");
   420    337   		case SCARD_W_REMOVED_CARD:
   421         -			retval = "SCARD_W_REMOVED_CARD";
   422         -			break;
          338  +			return("SCARD_W_REMOVED_CARD");
   423    339   		case SCARD_E_PCI_TOO_SMALL:
   424         -			retval = "SCARD_E_PCI_TOO_SMALL";
   425         -			break;
          340  +			return("SCARD_E_PCI_TOO_SMALL");
   426    341   		case SCARD_E_READER_UNSUPPORTED:
   427         -			retval = "SCARD_E_READER_UNSUPPORTED";
   428         -			break;
          342  +			return("SCARD_E_READER_UNSUPPORTED");
   429    343   		case SCARD_E_DUPLICATE_READER:
   430         -			retval = "SCARD_E_DUPLICATE_READER";
   431         -			break;
          344  +			return("SCARD_E_DUPLICATE_READER");
   432    345   		case SCARD_E_CARD_UNSUPPORTED:
   433         -			retval = "SCARD_E_CARD_UNSUPPORTED";
   434         -			break;
          346  +			return("SCARD_E_CARD_UNSUPPORTED");
   435    347   		case SCARD_E_NO_SERVICE:
   436         -			retval = "SCARD_E_NO_SERVICE";
   437         -			break;
          348  +			return("SCARD_E_NO_SERVICE");
   438    349   		case SCARD_E_SERVICE_STOPPED:
   439         -			retval = "SCARD_E_SERVICE_STOPPED";
   440         -			break;
          350  +			return("SCARD_E_SERVICE_STOPPED");
   441    351   		case SCARD_W_INSERTED_CARD:
   442         -			retval = "SCARD_W_INSERTED_CARD";
   443         -			break;
          352  +			return("SCARD_W_INSERTED_CARD");
   444    353   		case SCARD_E_UNSUPPORTED_FEATURE:
   445         -			retval = "SCARD_E_UNSUPPORTED_FEATURE";
   446         -			break;
   447         -	}
   448         -
   449         -	if (retval == NULL) {
   450         -		retval = "UNKNOWN";
   451         -	}
   452         -
   453         -	return(retval);
          354  +			return("SCARD_E_UNSUPPORTED_FEATURE");
          355  +	}
          356  +
          357  +	return("UNKNOWN");
          358  +}
          359  +
          360  +static const char *CACKEY_DEBUG_FUNC_OBJID_TO_STR(uint16_t objid) {
          361  +	switch (objid) {
          362  +		case 0x2000:
          363  +			return("CACKEY_TLV_OBJID_GENERALINFO");
          364  +		case 0x2100:
          365  +			return("CACKEY_TLV_OBJID_PROPERSONALINFO");
          366  +		case 0x3000:
          367  +			return("CACKEY_TLV_OBJID_ACCESSCONTROL");
          368  +		case 0x4000:
          369  +			return("CACKEY_TLV_OBJID_LOGIN");
          370  +		case 0x5000:
          371  +			return("CACKEY_TLV_OBJID_CARDINFO");
          372  +		case 0x6000:
          373  +			return("CACKEY_TLV_OBJID_BIOMETRICS");
          374  +		case 0x7000:
          375  +			return("CACKEY_TLV_OBJID_DIGITALSIGCERT");
          376  +		case 0x0200:
          377  +			return("CACKEY_TLV_OBJID_CAC_PERSON");
          378  +		case 0x0202:
          379  +			return("CACKEY_TLV_OBJID_CAC_BENEFITS");
          380  +		case 0x0203:
          381  +			return("CACKEY_TLV_OBJID_CAC_OTHERBENEFITS");
          382  +		case 0x0201:
          383  +			return("CACKEY_TLV_OBJID_CAC_PERSONNEL");
          384  +		case 0x02FE:
          385  +			return("CACKEY_TLV_OBJID_CAC_PKICERT");
          386  +	}
          387  +	
          388  +	return("UNKNOWN");
          389  +}
          390  +
          391  +static const char *CACKEY_DEBUG_FUNC_APPTYPE_TO_STR(uint8_t apptype) {
          392  +	switch (apptype) {
          393  +		case 0x01:
          394  +			return("CACKEY_TLV_APP_GENERIC");
          395  +		case 0x02:
          396  +			return("CACKEY_TLV_APP_SKI");
          397  +		case 0x03:
          398  +			return("CACKEY_TLV_APP_GENERIC | CACKEY_TLV_APP_SKI");
          399  +		case 0x04:
          400  +			return("CACKEY_TLV_APP_PKI");
          401  +		case 0x05:
          402  +			return("CACKEY_TLV_APP_GENERIC | CACKEY_TLV_APP_PKI");
          403  +		case 0x06:
          404  +			return("CACKEY_TLV_APP_SKI | CACKEY_TLV_APP_PKI");
          405  +		case 0x07:
          406  +			return("CACKEY_TLV_APP_GENERIC | CACKEY_TLV_APP_SKI | CACKEY_TLV_APP_PKI");
          407  +	}
          408  +
          409  +	return("INVALID");
   454    410   }
   455    411   
   456    412   #  define malloc(x) CACKEY_DEBUG_FUNC_MALLOC(x, __func__)
   457    413   #  define realloc(x, y) CACKEY_DEBUG_FUNC_REALLOC(x, y, __func__)
   458    414   #else
   459    415   #  define CACKEY_DEBUG_PRINTF(x...) /**/
   460    416   #  define CACKEY_DEBUG_PRINTBUF(f, x, y) /**/
   461    417   #  define CACKEY_DEBUG_PERROR(x) /**/
   462    418   #  define CACKEY_DEBUG_FUNC_TAG_TO_STR(x) "DEBUG_DISABLED"
   463    419   #  define CACKEY_DEBUG_FUNC_SCARDERR_TO_STR(x) "DEBUG_DISABLED"
          420  +#  define CACKEY_DEBUG_FUNC_OBJID_TO_STR(x) "DEBUG_DISABLED"
          421  +#  define CACKEY_DEBUG_FUNC_APPTYPE_TO_STR(x) "DEBUG_DISABLED"
   464    422   #endif
   465    423   
   466    424   struct cackey_identity {
   467    425   	CK_ATTRIBUTE *attributes;
   468    426   	CK_ULONG attributes_count;
   469    427   };
   470    428   
................................................................................
   505    463   
   506    464   	char *pcsc_reader;
   507    465   
   508    466   	int pcsc_card_connected;
   509    467   	SCARDHANDLE pcsc_card;
   510    468   };
   511    469   
          470  +typedef enum {
          471  +	CACKEY_TLV_APP_GENERIC = 0x01,
          472  +	CACKEY_TLV_APP_SKI     = 0x02,
          473  +	CACKEY_TLV_APP_PKI     = 0x04
          474  +} cackey_tlv_apptype;
          475  +
          476  +typedef enum {
          477  +	CACKEY_TLV_OBJID_GENERALINFO       = 0x2000,
          478  +	CACKEY_TLV_OBJID_PROPERSONALINFO   = 0x2100,
          479  +	CACKEY_TLV_OBJID_ACCESSCONTROL     = 0x3000,
          480  +	CACKEY_TLV_OBJID_LOGIN             = 0x4000,
          481  +	CACKEY_TLV_OBJID_CARDINFO          = 0x5000,
          482  +	CACKEY_TLV_OBJID_BIOMETRICS        = 0x6000,
          483  +	CACKEY_TLV_OBJID_DIGITALSIGCERT    = 0x7000,
          484  +	CACKEY_TLV_OBJID_CAC_PERSON        = 0x0200,
          485  +	CACKEY_TLV_OBJID_CAC_BENEFITS      = 0x0202,
          486  +	CACKEY_TLV_OBJID_CAC_OTHERBENEFITS = 0x0203,
          487  +	CACKEY_TLV_OBJID_CAC_PERSONNEL     = 0x0201,
          488  +	CACKEY_TLV_OBJID_CAC_PKICERT       = 0x02FE
          489  +} cackey_tlv_objectid;
          490  +
   512    491   struct cackey_tlv_cardurl {
          492  +	unsigned char        rid[5];
          493  +	cackey_tlv_apptype   apptype;
          494  +	cackey_tlv_objectid  objectid;
          495  +	cackey_tlv_objectid  appid;
          496  +	unsigned char        pinid;
   513    497   };
   514    498   
          499  +struct cackey_tlv_entity;
   515    500   struct cackey_tlv_entity {
   516    501   	uint8_t tag;
   517    502   	size_t length;
   518         -	unsigned char *value_buf; /* Raw buffer */
   519         -	void *value;
          503  +
          504  +	union {
          505  +		void *value;
          506  +		struct cackey_tlv_cardurl *value_cardurl;
          507  +		uint8_t value_byte;
          508  +	};
          509  +
          510  +	struct cackey_tlv_entity *_next;
   520    511   };
   521    512   
   522    513   /* CACKEY Global Handles */
   523    514   static void *cackey_biglock = NULL;
   524    515   static struct cackey_session cackey_sessions[128];
   525    516   static struct cackey_slot cackey_slots[128];
   526    517   static int cackey_initialized = 0;
................................................................................
   915    906   	}
   916    907   
   917    908   	CACKEY_DEBUG_PRINTF("Successfully selected file");
   918    909   
   919    910   	return(0);
   920    911   }
   921    912   
   922         -static int cackey_read_tlv(struct cackey_slot *slot, int follow_url) {
   923         -	struct cackey_tlv_entity curr_entity;
          913  +static void cackey_free_tlv(struct cackey_tlv_entity *root) {
          914  +	struct cackey_tlv_entity *curr, *next;
          915  +
          916  +	for (curr = root; curr; curr = next) {
          917  +		next = curr->_next;
          918  +
          919  +		switch (curr->tag) {
          920  +			case GSCIS_TAG_ACR_TABLE:
          921  +				if (curr->value) {
          922  +					free(curr->value);
          923  +				}
          924  +				break;
          925  +			case GSCIS_TAG_CARDURL:
          926  +				if (curr->value_cardurl) {
          927  +					free(curr->value_cardurl);
          928  +				}
          929  +				break;
          930  +		}
          931  +
          932  +		free(curr);
          933  +	}
          934  +
          935  +	return;
          936  +}
          937  +
          938  +static struct cackey_tlv_entity *cackey_read_tlv(struct cackey_slot *slot) {
          939  +	struct cackey_tlv_entity *curr_entity, *root = NULL, *last = NULL;
   924    940   	unsigned char tlen_buf[2], tval_buf[1024], *tval;
   925    941   	unsigned char vlen_buf[2], vval_buf[8192], *vval;
          942  +	unsigned char *tmpbuf;
   926    943   	ssize_t tlen, vlen;
   927    944   	ssize_t read_ret;
   928    945   	size_t offset_t = 0, offset_v = 0;
   929         -	int select_ret;
          946  +	unsigned char tag;
          947  +	size_t length;
   930    948   
   931    949   	CACKEY_DEBUG_PRINTF("Called");
   932    950   
   933    951   	read_ret = cackey_read_buffer(slot, tlen_buf, sizeof(tlen_buf), 1, offset_t);
   934    952   	if (read_ret != sizeof(tlen_buf)) {
   935    953   		CACKEY_DEBUG_PRINTF("Read failed, returning in failure");
   936    954   
   937         -		return(0);
          955  +		return(NULL);
   938    956   	}
   939    957   
   940    958   	tlen = (tlen_buf[1] << 8) | tlen_buf[0];
   941    959   
   942    960   	read_ret = cackey_read_buffer(slot, vlen_buf, sizeof(vlen_buf), 2, offset_v);
   943    961   	if (read_ret != sizeof(vlen_buf)) {
   944    962   		CACKEY_DEBUG_PRINTF("Read failed, returning in failure");
   945    963   
   946         -		return(0);
          964  +		return(NULL);
   947    965   	}
   948    966   
   949    967   	vlen = (vlen_buf[1] << 8) | vlen_buf[0];
   950    968   
   951    969   	CACKEY_DEBUG_PRINTF("Tag Length = %i, Value Length = %i", tlen, vlen);
   952    970   
   953    971   	tlen -= 2;
................................................................................
   955    973   
   956    974   	vlen -= 2;
   957    975   	offset_v += 2;
   958    976   
   959    977   	if (tlen > sizeof(tval_buf)) {
   960    978   		CACKEY_DEBUG_PRINTF("Tag length is too large, returning in failure");
   961    979   
   962         -		return(0);
          980  +		return(NULL);
   963    981   	}
   964    982   
   965    983   	if (vlen > sizeof(vval_buf)) {
   966    984   		CACKEY_DEBUG_PRINTF("Value length is too large, returning in failure");
   967    985   
   968         -		return(0);
          986  +		return(NULL);
   969    987   	}
   970    988   
   971    989   	read_ret = cackey_read_buffer(slot, tval_buf, tlen, 1, offset_t);
   972    990   	if (read_ret != tlen) {
   973    991   		CACKEY_DEBUG_PRINTF("Unable to read entire T-buffer, returning in failure");
   974    992   
   975         -		return(0);
          993  +		return(NULL);
   976    994   	}
   977    995   
   978    996   	read_ret = cackey_read_buffer(slot, vval_buf, vlen, 2, offset_v);
   979    997   	if (read_ret != vlen) {
   980    998   		CACKEY_DEBUG_PRINTF("Unable to read entire V-buffer, returning in failure");
   981    999   
   982         -		return(0);
         1000  +		return(NULL);
   983   1001   	}
   984   1002   
   985   1003   	tval = tval_buf;
   986   1004   	vval = vval_buf;
   987   1005   	while (tlen > 0 && vlen > 0) {
   988         -		curr_entity.tag = *tval;
         1006  +		tag = *tval;
   989   1007   		tval++;
   990   1008   		tlen--;
   991   1009   
   992   1010   		if (*tval == 0xff) {
   993         -			curr_entity.length = (tval[2] << 8) | tval[1];
         1011  +			length = (tval[2] << 8) | tval[1];
   994   1012   			tval += 3;
   995   1013   			tlen -= 3;
   996   1014   		} else {
   997         -			curr_entity.length = *tval;
         1015  +			length = *tval;
   998   1016   			tval++;
   999   1017   			tlen--;
  1000   1018   		}
  1001   1019   
  1002         -		CACKEY_DEBUG_PRINTF("Tag: %s (%02x)", CACKEY_DEBUG_FUNC_TAG_TO_STR(curr_entity.tag), (unsigned int) curr_entity.tag);
  1003         -		CACKEY_DEBUG_PRINTBUF("Value:", vval, curr_entity.length);
  1004         -		vval += curr_entity.length;
  1005         -		vlen -= curr_entity.length;
         1020  +		CACKEY_DEBUG_PRINTF("Tag: %s (%02x)", CACKEY_DEBUG_FUNC_TAG_TO_STR(tag), (unsigned int) tag);
         1021  +		CACKEY_DEBUG_PRINTBUF("Value:", vval, length);
         1022  +		vval += length;
         1023  +		vlen -= length;
  1006   1024   
  1007         -		switch (curr_entity.tag) {
         1025  +		curr_entity = NULL;
         1026  +		switch (tag) {
  1008   1027   			case GSCIS_TAG_CARDURL:
  1009         -				if (follow_url) {
  1010         -					unsigned char aid[7];
  1011         -					memcpy(aid, vval, 5);
  1012         -					memcpy(aid + 5, vval + 8, 2);
  1013         -
  1014         -					select_ret = cackey_select_applet(slot, aid, 7);
  1015         -					if (select_ret < 0) {
  1016         -						CACKEY_DEBUG_PRINTF("Failed to select applet");
  1017         -						break;
  1018         -					}
  1019         -
  1020         -					cackey_read_tlv(slot, 0);
  1021         -				}
  1022         -				break;
  1023         -		}
  1024         -	}
  1025         -
  1026         -	return(0);
         1028  +				curr_entity = malloc(sizeof(*curr_entity));
         1029  +				curr_entity->value_cardurl = malloc(sizeof(*curr_entity->value_cardurl));
         1030  +
         1031  +				memcpy(curr_entity->value_cardurl->rid, vval, 5);
         1032  +				curr_entity->value_cardurl->apptype = vval[5];
         1033  +				curr_entity->value_cardurl->objectid = (vval[6] << 8) | vval[7];
         1034  +				curr_entity->value_cardurl->appid = (vval[8] << 8) | vval[9];
         1035  +
         1036  +				curr_entity->tag = tag;
         1037  +				curr_entity->_next = NULL;
         1038  +
         1039  +				break;
         1040  +			case GSCIS_TAG_ACR_TABLE:
         1041  +				curr_entity = malloc(sizeof(*curr_entity));
         1042  +				tmpbuf = malloc(length);
         1043  +
         1044  +				memcpy(tmpbuf, vval, length);
         1045  +
         1046  +				curr_entity->tag = tag;
         1047  +				curr_entity->length = length;
         1048  +				curr_entity->value = tmpbuf;
         1049  +				curr_entity->_next = NULL;
         1050  +
         1051  +				break;
         1052  +			case GSCIS_TAG_PKCS15:
         1053  +				curr_entity = malloc(sizeof(*curr_entity));
         1054  +
         1055  +				curr_entity->tag = tag;
         1056  +				curr_entity->value_byte = vval[0];
         1057  +				curr_entity->_next = NULL;
         1058  +
         1059  +				break;
         1060  +		}
         1061  +
         1062  +		if (curr_entity != NULL) {
         1063  +			if (root == NULL) {
         1064  +				root = curr_entity;
         1065  +			}
         1066  +
         1067  +			if (last != NULL) {
         1068  +				last->_next = curr_entity;
         1069  +			}
         1070  +
         1071  +			last = curr_entity;
         1072  +		}
         1073  +	}
         1074  +
         1075  +	return(root);
  1027   1076   }
  1028   1077   
  1029   1078   /* Returns 1 if a token is in the specified slot, 0 otherwise */
  1030   1079   static int cackey_token_present(struct cackey_slot *slot) {
         1080  +	struct cackey_tlv_entity *tlvs, *curr;
  1031   1081   	unsigned char ccc_aid[] = {0xa0, 0x00, 0x00, 0x01, 0x16, 0xdb, 0x00};
         1082  +	unsigned char curr_aid[7];
  1032   1083   	int send_ret;
  1033   1084   
  1034   1085   	/* Select the CCC Applet */
  1035   1086   	send_ret = cackey_select_applet(slot, ccc_aid, sizeof(ccc_aid));
  1036   1087   	if (send_ret < 0) {
  1037   1088   		return(0);
  1038   1089   	}
  1039   1090   
  1040         -	cackey_read_tlv(slot, 1);
         1091  +	tlvs = cackey_read_tlv(slot);
         1092  +
         1093  +	for (curr = tlvs; curr; curr = curr->_next) {
         1094  +		CACKEY_DEBUG_PRINTF("Found tag: %s", CACKEY_DEBUG_FUNC_TAG_TO_STR(curr->tag));
         1095  +		switch (curr->tag) {
         1096  +			case GSCIS_TAG_CARDURL:
         1097  +				if ((curr->value_cardurl->apptype & CACKEY_TLV_APP_PKI) == CACKEY_TLV_APP_PKI) {
         1098  +					CACKEY_DEBUG_PRINTBUF("RID:", curr->value_cardurl->rid, sizeof(curr->value_cardurl->rid));
         1099  +					CACKEY_DEBUG_PRINTF("AppID = %s/%04lx", CACKEY_DEBUG_FUNC_OBJID_TO_STR(curr->value_cardurl->appid), (unsigned long) curr->value_cardurl->appid);
         1100  +					CACKEY_DEBUG_PRINTF("ObjectID = %s/%04lx", CACKEY_DEBUG_FUNC_OBJID_TO_STR(curr->value_cardurl->objectid), (unsigned long) curr->value_cardurl->objectid);
         1101  +
         1102  +					memcpy(curr_aid, curr->value_cardurl->rid, sizeof(curr->value_cardurl->rid));
         1103  +					curr_aid[sizeof(curr_aid) - 2] = (curr->value_cardurl->appid >> 8) & 0xff;
         1104  +					curr_aid[sizeof(curr_aid) - 1] = curr->value_cardurl->appid & 0xff;
         1105  +
         1106  +					cackey_select_applet(slot, curr_aid, sizeof(curr_aid));
         1107  +					cackey_select_file(slot, curr->value_cardurl->objectid);
         1108  +				}
         1109  +				break;
         1110  +		}
         1111  +	}
         1112  +
         1113  +	cackey_free_tlv(tlvs);
  1041   1114   
  1042   1115   	return(1);
  1043   1116   }
  1044   1117   
  1045   1118   /* Returns 0 on success */
  1046   1119   static int cackey_mutex_create(void **mutex) {
  1047   1120   	pthread_mutex_t *pthread_mutex;