static int tc_log_console_send(TCLogContext *ctx, TCLogType type, const char *tag, const char *fmt, va_list ap) { int is_dynbuf = TC_FALSE, truncated = TC_FALSE; /* flag: we must use a dynamic (larger than static) buffer? */ char buf[TC_LOG_BUF_SIZE]; char *msg = buf; size_t size = sizeof(buf); const char *templ = NULL; /* sanity check, avoid {under,over}flow; */ type = TC_CLAMP(type, TC_LOG_ERR, TC_LOG_MARK); /* sanity check, avoid dealing with NULL as much as we can */ if (!ctx->use_colors && type != TC_LOG_MARK) { type = TC_LOG_MSG; } tag = (tag != NULL) ?tag :""; fmt = (fmt != NULL) ?fmt :""; /* TC_LOG_EXTRA special handling: force always empty tag */ tag = (type == TC_LOG_MARK) ?"" :tag; templ = log_template(type); size = strlen(templ) + strlen(tag) + strlen(fmt) + 1; if (size > sizeof(buf)) { /* * we use malloc/fprintf instead of tc_malloc because * we want custom error messages */ msg = malloc(size); if (msg != NULL) { is_dynbuf = TC_TRUE; } else { fprintf(stderr, "(%s) CRITICAL: can't get memory in " "tc_log() output will be truncated.\n", __FILE__); /* force reset to default values */ msg = buf; size = sizeof(buf) - 1; truncated = TC_TRUE; } } else { size = sizeof(buf) - 1; } /* construct real format string */ tc_snprintf(msg, size, templ, tag, fmt); vfprintf(ctx->f, msg, ap); if (is_dynbuf) { free(msg); } /* ensure that all *other* messages are written */ /* we don't (yet) honor the flush_threshold */ fflush(ctx->f); return (truncated) ?-1 :0; }
CK_RV C_GetAttributeValue(CK_SESSION_HANDLE hSession, /* the session's handle */ CK_OBJECT_HANDLE hObject, /* the object's handle */ CK_ATTRIBUTE_PTR pTemplate, /* specifies attributes, gets values */ CK_ULONG ulCount) /* attributes in template */ { /* This function returns the values from the object. Object is cached so objects are read only once and remain valid until new session is setup with token. Objects are allready initialized (but not read) during connection with token. */ int status, ret = 0; P11_SESSION *pSession = NULL; P11_SLOT *pSlot = NULL; P11_OBJECT *pObject = NULL; unsigned int j = 0; void *pValue = NULL; CK_ULONG len = 0; log_trace(WHERE, "I: enter"); if (p11_get_init() != BEIDP11_INITIALIZED) { log_trace(WHERE, "I: leave, CKR_CRYPTOKI_NOT_INITIALIZED"); return (CKR_CRYPTOKI_NOT_INITIALIZED); } ret = p11_lock(); if (ret != CKR_OK) return ret; log_trace(WHERE, "S: C_GetAttributeValue(hObject=%d)",hObject); ret = p11_get_session(hSession, &pSession); if (ret) { log_trace(WHERE, "E: Invalid session handle (%d)", hSession); goto cleanup; } pSlot = p11_get_slot(pSession->hslot); if (pSlot == NULL) { log_trace(WHERE, "E: p11_get_slot(%d) returns null", pSession->hslot); ret = CKR_SLOT_ID_INVALID; goto cleanup; } pObject = p11_get_slot_object(pSlot, hObject); if (pObject == NULL) { log_trace(WHERE, "E: slot %d: object %d does not exist", pSession->hslot, hObject); ret = CKR_OBJECT_HANDLE_INVALID; goto cleanup; } //read object from token if not cached allready if (pObject->state != P11_CACHED) { ret = cal_read_object(pSession->hslot, pObject); if (ret != 0) { log_trace(WHERE, "E: p11_read_object() returned %d", ret); goto cleanup; } } /* if (pSlot->login_type < 0) //CKU_SO=0; CKU_USER=1 { if (p11_get_attribute_value(pObject->pAttr, pObject->count, CKA_PRIVATE, (CK_VOID_PTR *) &pbPrivate, &len) != CKR_OK) { log_trace(WHERE, "E: missing CKA_PRIVATE attribute in our object: bad implementation"); continue; } if ( (len == sizeof(CK_BBOOL)) && (*pbPrivate == CK_TRUE) ) { log_trace(WHERE, "E: Not allowed to retrieve private objects"); continue; } }*/ //retrieve all objects as listed in template and fill the template //action is done for all attributes, even if some attributes give errors or buffer is too small //there is however only one return code to return so we have to keep the most important return code. for (j = 0; j < ulCount; j++) { status = p11_get_attribute_value(pObject->pAttr, pObject->count, pTemplate[j].type, (CK_VOID_PTR *) &pValue, &len); if (status != CKR_OK) { log_template("E: C_GetAttributeValue status != CKR_OK", &pTemplate[j], 1); log_trace(WHERE, "E: p11_get_attribute_value (object=%d) returned %s", hObject, log_map_error(status)); pTemplate[j].ulValueLen = (CK_ULONG) -1; ret = status; continue; } if (pTemplate[j].pValue == NULL) { /* in this case we return the real length of the value */ pTemplate[j].ulValueLen = len; continue; } if (len > pTemplate[j].ulValueLen) { pTemplate[j].ulValueLen = (CK_ULONG) -1; ret = CKR_BUFFER_TOO_SMALL; continue; } pTemplate[j].ulValueLen = len; memcpy(pTemplate[j].pValue, pValue, len); } if (ulCount != 0) log_template("I: Template out:", pTemplate, ulCount); cleanup: p11_unlock(); return ret; }
CK_RV C_FindObjectsInit(CK_SESSION_HANDLE hSession, /* the session's handle */ CK_ATTRIBUTE_PTR pTemplate, /* attribute values to match */ CK_ULONG ulCount) /* attributes in search template */ { P11_SESSION *pSession = NULL; P11_FIND_DATA *pData = NULL; int ret; CK_ULONG *pclass = NULL; CK_ULONG len = 0; CK_BBOOL addIdObjects = CK_FALSE; CK_BYTE filesToCacheFlag = CACHED_DATA_TYPE_ALL; CK_BYTE allowCardRead = P11_DISPLAY_NO; log_trace(WHERE, "I: enter"); if (p11_get_init() != BEIDP11_INITIALIZED) { log_trace(WHERE, "I: leave, CKR_CRYPTOKI_NOT_INITIALIZED"); return (CKR_CRYPTOKI_NOT_INITIALIZED); } ret = p11_lock(); if (ret != CKR_OK) return ret; log_trace(WHERE, "S: C_FindObjectsInit(session %d)", hSession); if (ulCount == 0) log_trace(WHERE, "I: empty template => search all objects"); else log_template("I: Search template:", pTemplate, ulCount); /* add check here to avoid useless calls to C_FindObjects() */ /* reason to add this is that e.g. Firefox for every certificate in its store starts a find operation with CKA_CLASS_TYPE */ /* that is unknown by this implementation */ /* CKA_CLASS_TYPE we support is only CKO_CERTIFICATE, CKO_PRIVATE_KEY and CKO_PUBLIC_KEY */ /* Sun-PKCS11 cannot handle CKR_ATTRIBUTE_VALUE_INVALID properly so => initialize search and findObjects will just return 0 matching objects in case of CKO_DATA */ if (ulCount) { ret = p11_get_attribute_value(pTemplate, ulCount, CKA_CLASS, (CK_VOID_PTR *) &pclass, &len); if ( (ret == 0) && (len == sizeof(CK_ULONG) ) ) { //CKO_SECRET_KEY is not supported but for SUN-PKCS11 we allow a search that will result in 0 objects if ( (*pclass != CKO_CERTIFICATE) && (*pclass != CKO_PRIVATE_KEY) && (*pclass != CKO_PUBLIC_KEY) && (*pclass != CKO_SECRET_KEY) && (*pclass != CKO_DATA)) { log_trace(WHERE, "I: CKA_CLASS (%0x) not supported by this PKCS11 module", *pclass); ret = CKR_ATTRIBUTE_VALUE_INVALID; goto cleanup; } else if (*pclass == CKO_DATA) { addIdObjects = CK_TRUE; } } //We only return the CKO_DATA objects when specifically asked for, this to prevent webbrowsers //to read the entire carddata, while they only need the certificates. //(e.g. we saw firefox do a C_FindObjectsInit with only the auth cert's CKA_VALUE and its value // in the template) //else if (len == 0)// no CKA_CLASS attribute in the template //{ // addIdObjects = CK_TRUE; //} } //see comment above, We only return the CKO_DATA objects when specifically asked for //else //{ // addIdObjects = CK_TRUE; //} ret = p11_get_session(hSession, &pSession); // if (pSession == NULL) if (ret) { log_trace(WHERE, "E: Invalid session (%d) (%s)", hSession, log_map_error(ret)); //if (ret == CKR_DEVICE_REMOVED) //ret = CKR_SESSION_HANDLE_INVALID; //ret = CKR_FUNCTION_FAILED; goto cleanup; } //is there an active search operation for this session if (pSession->Operation[P11_OPERATION_FIND].active) { log_trace(WHERE, "W: Session %d: search operation allready exists", hSession); ret = CKR_OPERATION_ACTIVE; goto cleanup; } if(addIdObjects == CK_TRUE) { //parse the search template CK_UTF8CHAR* pLabel; CK_UTF8CHAR* pObjectID; ret = p11_get_attribute_value(pTemplate, ulCount, CKA_OBJECT_ID, (CK_VOID_PTR *) &pObjectID, &len); if ( (ret == 0) && (len > 0 ) ) { SetParseFlagByObjectID(&filesToCacheFlag,pObjectID,len); } else { ret = p11_get_attribute_value(pTemplate, ulCount, CKA_LABEL, (CK_VOID_PTR *) &pLabel, &len); if ( (ret == 0) && (len > 0 ) ) { SetParseFlagByLabel(&filesToCacheFlag,pLabel,len); } } if((filesToCacheFlag != CACHED_DATA_TYPE_CARDDATA) && (filesToCacheFlag != CACHED_DATA_TYPE_RNCERT)) { if ((pSession->bReadDataAllowed == P11_READDATA_ASK) & (eidmw_readpermission != P11_READDATA_ALWAYS)) { allowCardRead = AllowCardReading(); switch(allowCardRead) { case P11_DISPLAY_YES: pSession->bReadDataAllowed = P11_READDATA_ALLOWED; break; case P11_DISPLAY_ALWAYS: pSession->bReadDataAllowed = P11_READDATA_ALLOWED; eidmw_readpermission = P11_READDATA_ALWAYS; //allowed for as long as this pkcs11 instance exists, put it in some variable log_trace(WHERE, "I: Al reading from the card"); break; case P11_DISPLAY_NO: //keep asking //case P11_DISPLAY_NEVER: //pSession->bReadDataAllowed = P11_READDATA_REFUSED; default: log_trace(WHERE, "I: User does not allow reading from the card"); ret = CKR_FUNCTION_FAILED; goto cleanup; break; } } else if (pSession->bReadDataAllowed == P11_READDATA_REFUSED) { log_trace(WHERE, "I: User did not allow reading from the card during this session"); ret = CKR_FUNCTION_FAILED; goto cleanup; } } } /* init search operation */ pData = (P11_FIND_DATA *)pSession->Operation[P11_OPERATION_FIND].pData; if(pData == NULL) { pSession->Operation[P11_OPERATION_FIND].pData = (P11_FIND_DATA *) malloc (sizeof(P11_FIND_DATA)); pData = (P11_FIND_DATA *)pSession->Operation[P11_OPERATION_FIND].pData; if (pData == NULL) { log_trace( WHERE, "E: error allocating memory"); ret = CKR_HOST_MEMORY; goto cleanup; } } //first handle = 1 pData->hCurrent = 1; pData->pSearch = NULL; pData->size = 0; //keep search template if at least one entry in the search template if (ulCount > 0) { pData->pSearch = (CK_ATTRIBUTE_PTR) malloc(sizeof(CK_ATTRIBUTE)*ulCount); if (pData->pSearch == NULL) { log_trace(WHERE, "E: error allocating memory for object search template()"); ret = CKR_HOST_MEMORY; goto cleanup; } memset(pData->pSearch,0,sizeof(CK_ATTRIBUTE)*ulCount); ret = p11_copy_object(pTemplate, ulCount, pData->pSearch); if (ret) { log_trace(WHERE, "E: p11_copy_object() returned %d", ret); goto cleanup; } } pData->size = ulCount; //set search operation to active state since there can be only one pSession->Operation[P11_OPERATION_FIND].active = 1; if ( addIdObjects ) { //check if the data isn't cached already if( ((filesToCacheFlag != CACHED_DATA_TYPE_ALL) && ((pSession->bCardDataCashed & filesToCacheFlag) == FALSE)) || ((filesToCacheFlag == CACHED_DATA_TYPE_ALL) && (pSession->bCardDataCashed != CACHED_DATA_TYPE_ALL)) ) { CK_ULONG counter = 0; CK_ULONG flagsToCheckListLen = 6; CK_BYTE flagsToCheckList[6] = {CACHED_DATA_TYPE_ID,CACHED_DATA_TYPE_ADDRESS,CACHED_DATA_TYPE_PHOTO, CACHED_DATA_TYPE_RNCERT,CACHED_DATA_TYPE_SIGN_DATA_FILE,CACHED_DATA_TYPE_SIGN_ADDRESS_FILE}; switch(filesToCacheFlag) { case CACHED_DATA_TYPE_ALL: //cache and parse whatever isn't cached already //first check if carddata is cashed already, if not parse and cache it if( (pSession->bCardDataCashed & CACHED_DATA_TYPE_CARDDATA) == 0){ ret = cal_get_card_data(pSession->hslot); if (ret != 0){ log_trace(WHERE, "E: cal_read_ID_files() returned %d", ret); goto cleanup; } } //check which other files are cached already, parse and cache those that aren't while(counter < flagsToCheckListLen){ ret = cal_read_ID_files(pSession->hslot,flagsToCheckList[counter]); if (ret != 0){ log_trace(WHERE, "E: cal_read_ID_files() returned %d", ret); goto cleanup; } counter++; } break; case CACHED_DATA_TYPE_CARDDATA: //cache and parse only the carddata ret = cal_get_card_data(pSession->hslot); if (ret != 0){ log_trace(WHERE, "E: cal_read_ID_files() returned %d", ret); goto cleanup; } break; default: //cache and parse only the requested file type ret = cal_read_ID_files(pSession->hslot,filesToCacheFlag); if (ret != 0){ log_trace(WHERE, "E: cal_read_ID_files() returned %d", ret); goto cleanup; } } //remember the file(s) we cashed pSession->bCardDataCashed |= filesToCacheFlag; } } ret = CKR_OK; cleanup: p11_unlock(); return ret; }