/* Prints all results that can be found in the outbox into the interactor */ static void gnc_hbci_printresult(HBCI_Outbox *outbox, GNCInteractor *inter) { /* Got no sysid. */ GWEN_DB_NODE *rsp, *n; g_assert(outbox); if (!inter) return; rsp = HBCI_Outbox_response(outbox); n = GWEN_DB_GetFirstGroup(rsp); while (n) { if (strcasecmp(GWEN_DB_GroupName(n), "msgresult") == 0) { GWEN_DB_NODE *r = GWEN_DB_GetFirstGroup(n); while (r) { if (strcasecmp(GWEN_DB_GroupName(r), "result") == 0) { gchar *logtext; int resultcode; const char *text, *elementref, *param; resultcode = GWEN_DB_GetIntValue(r, "resultcode", 0, 0); text = GWEN_DB_GetCharValue(r, "text", 0, "Response without text"); elementref = GWEN_DB_GetCharValue(r, "elementref", 0, ""); param = GWEN_DB_GetCharValue(r, "param", 0, ""); if (strlen(elementref) > 0 || strlen(param) > 0) logtext = g_strdup_printf("%s (%d; Elementref %s; Param %s)", text, resultcode, elementref, param); else logtext = g_strdup_printf("%s (%d)", text, resultcode); GNCInteractor_add_log_text(inter, logtext); g_free(logtext); } r = GWEN_DB_GetNextGroup(r); } } else if (strcasecmp(GWEN_DB_GroupName(n), "segresult") == 0) { GWEN_DB_NODE *r = GWEN_DB_GetFirstGroup(n); while (r) { if (strcasecmp(GWEN_DB_GroupName(r), "result") == 0) { } r = GWEN_DB_GetNextGroup(r); } } n = GWEN_DB_GetNextGroup(n); } /* while */ GWEN_DB_Group_free(rsp); }
void AH_User_LoadSepaDescriptors(AB_USER *u) { AH_USER *ue; GWEN_DB_NODE *db; int rv; assert(u); ue=GWEN_INHERIT_GETDATA(AB_USER, AH_USER, u); assert(ue); /* read directly from BPD */ GWEN_StringList_Clear(ue->sepaDescriptors); db=GWEN_DB_Group_new("bpd"); rv=AH_Job_SampleBpdVersions("JobGetAccountSepaInfo", u, db); if (rv<0) { DBG_INFO(AQHBCI_LOGDOMAIN, "No BPD for TAN job"); } else { GWEN_DB_NODE *dbV; dbV=GWEN_DB_GetFirstGroup(db); while(dbV) { int version; version=atoi(GWEN_DB_GroupName(dbV)); if (version>0) { GWEN_DB_NODE *dbT; /* always overwrite with latest version received */ GWEN_StringList_Clear(ue->sepaDescriptors); dbT=GWEN_DB_FindFirstGroup(dbV, "SupportedSepaFormats"); if (!dbT) { DBG_INFO(AQHBCI_LOGDOMAIN, "No SEPA descriptor found"); } while(dbT) { int i; for (i=0; i<100; i++) { const char *s; s=GWEN_DB_GetCharValue(dbT, "format", i, NULL); if (! (s && *s)) break; GWEN_StringList_AppendString(ue->sepaDescriptors, s, 0, 1); DBG_INFO(AQHBCI_LOGDOMAIN, "Adding SEPA descriptor [%s] for GV version %d", s, version); } dbT=GWEN_DB_FindNextGroup(dbT, "SupportedSepaFormats"); } } dbV=GWEN_DB_GetNextGroup(dbV); } } GWEN_DB_Group_free(db); }
int GWEN_DBIO_XmlDb__ExportGroup(GWEN_DBIO *dbio, GWEN_DB_NODE *data, GWEN_XMLNODE *node, const char *newName) { const char *s; GWEN_XMLNODE *n; GWEN_DB_NODE *dbT; int rv; if (newName) s=newName; else s=GWEN_DB_GroupName(data); assert(s && *s); n=GWEN_XMLNode_new(GWEN_XMLNodeTypeTag, s); GWEN_XMLNode_SetProperty(n, "type", "group"); GWEN_XMLNode_AddChild(node, n); /* store variables */ dbT=GWEN_DB_GetFirstVar(data); while(dbT) { if (!(GWEN_DB_GetNodeFlags(dbT) & GWEN_DB_NODE_FLAGS_VOLATILE)) { rv=GWEN_DBIO_XmlDb__ExportVar(dbio, dbT, n); if (rv) { DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv); return rv; } } dbT=GWEN_DB_GetNextVar(dbT); } /* store groups */ dbT=GWEN_DB_GetFirstGroup(data); while(dbT) { if (!(GWEN_DB_GetNodeFlags(dbT) & GWEN_DB_NODE_FLAGS_VOLATILE)) { rv=GWEN_DBIO_XmlDb__ExportGroup(dbio, dbT, n, 0); if (rv) { DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv); return rv; } } dbT=GWEN_DB_GetNextGroup(dbT); } return 0; }
int AH_Msg_VerifyPinTan(AH_MSG *hmsg, GWEN_DB_NODE *gr) { AH_HBCI *h; GWEN_LIST *sigheads; GWEN_LIST *sigtails; GWEN_DB_NODE *n; int nonSigHeads; int nSigheads; unsigned int dataBegin; // char *dataStart; // unsigned int dataLength; unsigned int i; AB_USER *u; assert(hmsg); h=AH_Dialog_GetHbci(hmsg->dialog); assert(h); u=AH_Dialog_GetDialogOwner(hmsg->dialog); assert(u); /* let's go */ sigheads=GWEN_List_new(); /* enumerate signature heads */ nonSigHeads=0; nSigheads=0; n=GWEN_DB_GetFirstGroup(gr); while(n) { if (strcasecmp(GWEN_DB_GroupName(n), "SigHead")==0) { /* found a signature head */ if (nonSigHeads) { DBG_ERROR(AQHBCI_LOGDOMAIN, "Found some unsigned parts at the beginning"); GWEN_List_free(sigheads); return GWEN_ERROR_BAD_DATA; } GWEN_List_PushBack(sigheads, n); nSigheads++; } else if (strcasecmp(GWEN_DB_GroupName(n), "MsgHead")!=0) { if (nSigheads) break; nonSigHeads++; } n=GWEN_DB_GetNextGroup(n); } /* while */ if (!n) { if (nSigheads) { DBG_ERROR(AQHBCI_LOGDOMAIN, "Found Signature heads but no other segments"); GWEN_List_free(sigheads); return GWEN_ERROR_BAD_DATA; } DBG_DEBUG(AQHBCI_LOGDOMAIN, "No signatures"); GWEN_List_free(sigheads); return 0; } /* store begin of signed data */ dataBegin=GWEN_DB_GetIntValue(n, "segment/pos", 0, 0); if (!dataBegin) { DBG_ERROR(AQHBCI_LOGDOMAIN, "No position specifications in segment"); GWEN_List_free(sigheads); return GWEN_ERROR_BAD_DATA; } /* now get first signature tail */ while(n) { if (strcasecmp(GWEN_DB_GroupName(n), "SigTail")==0) { unsigned int currpos; /* found a signature tail */ currpos=GWEN_DB_GetIntValue(n, "segment/pos", 0, 0); if (!currpos || dataBegin>currpos) { DBG_ERROR(AQHBCI_LOGDOMAIN, "Bad position specification in Signature tail"); GWEN_List_free(sigheads); return GWEN_ERROR_BAD_DATA; } // dataLength=currpos-dataBegin; break; } n=GWEN_DB_GetNextGroup(n); } /* while */ if (!n) { DBG_ERROR(AQHBCI_LOGDOMAIN, "No signature tail found"); GWEN_List_free(sigheads); return GWEN_ERROR_BAD_DATA; } sigtails=GWEN_List_new(); while(n) { if (strcasecmp(GWEN_DB_GroupName(n), "SigTail")!=0) break; GWEN_List_PushBack(sigtails, n); n=GWEN_DB_GetNextGroup(n); } /* while */ if (!n) { DBG_ERROR(AQHBCI_LOGDOMAIN, "Message tail expected"); GWEN_List_free(sigheads); GWEN_List_free(sigtails); return GWEN_ERROR_BAD_DATA; } if (strcasecmp(GWEN_DB_GroupName(n), "MsgTail")!=0) { DBG_ERROR(AQHBCI_LOGDOMAIN, "Unexpected segment (msg tail expected)"); GWEN_List_free(sigheads); GWEN_List_free(sigtails); return GWEN_ERROR_BAD_DATA; } n=GWEN_DB_GetNextGroup(n); if (n) { DBG_ERROR(AQHBCI_LOGDOMAIN, "Unexpected segment (end expected)"); GWEN_List_free(sigheads); GWEN_List_free(sigtails); return GWEN_ERROR_BAD_DATA; } if (GWEN_List_GetSize(sigheads)!= GWEN_List_GetSize(sigtails)) { DBG_ERROR(AQHBCI_LOGDOMAIN, "Number of signature heads (%d) does not match " "number of signature tails (%d)", GWEN_List_GetSize(sigheads), GWEN_List_GetSize(sigtails)); GWEN_List_free(sigheads); GWEN_List_free(sigtails); return GWEN_ERROR_BAD_DATA; } /* ok, now verify all signatures */ // dataStart=GWEN_Buffer_GetStart(hmsg->buffer)+dataBegin; for (i=0; i< GWEN_List_GetSize(sigtails); i++) { GWEN_DB_NODE *sighead; GWEN_DB_NODE *sigtail; const char *signerId; /* get signature tail */ sigtail=(GWEN_DB_NODE*)GWEN_List_GetBack(sigtails); /* get corresponding signature head */ sighead=(GWEN_DB_NODE*)GWEN_List_GetFront(sigheads); if (!sighead || !sigtail) { DBG_ERROR(AQHBCI_LOGDOMAIN, "No signature head/tail left (internal error)"); GWEN_List_free(sigheads); GWEN_List_free(sigtails); return GWEN_ERROR_INTERNAL; } GWEN_List_PopBack(sigtails); GWEN_List_PopFront(sigheads); signerId=GWEN_DB_GetCharValue(sighead, "key/userid", 0, I18N("unknown")); /* some checks */ if (strcasecmp(GWEN_DB_GetCharValue(sighead, "ctrlref", 0, ""), GWEN_DB_GetCharValue(sigtail, "ctrlref", 0, ""))!=0) { DBG_ERROR(AQHBCI_LOGDOMAIN, "Non-matching signature tail"); GWEN_List_free(sigheads); GWEN_List_free(sigtails); return GWEN_ERROR_BAD_DATA; } /* verify signature */ DBG_INFO(AQHBCI_LOGDOMAIN, "Message signed by \"%s\"", signerId); AH_Msg_AddSignerId(hmsg, signerId); DBG_DEBUG(AQHBCI_LOGDOMAIN, "Verification done"); } /* for */ GWEN_List_free(sigheads); GWEN_List_free(sigtails); return 0; }
int AHB_DTAUS__Export(GWEN_DBIO *dbio, GWEN_SYNCIO *sio, GWEN_DB_NODE *data, GWEN_DB_NODE *cfg, uint32_t flags){ AB_VALUE *sumEUR; AB_VALUE *sumDEM; AB_VALUE *sumBankCodes; AB_VALUE *sumAccountIds; unsigned int cSets; GWEN_BUFFER *dst; GWEN_DB_NODE *gr; int isDebitNote; //int isEuro; const uint8_t *p; uint32_t size; int rv; isDebitNote=(strcasecmp(GWEN_DB_GetCharValue(cfg, "type", 0, "transfer"), "debitnote")==0); //isEuro=(strcasecmp(GWEN_DB_GetCharValue(cfg, "currency", 0, "EUR"), // "EUR")==0); cSets=0; sumEUR=AB_Value_new(); sumDEM=AB_Value_new(); sumBankCodes=AB_Value_new(); sumAccountIds=AB_Value_new(); dst=GWEN_Buffer_new(0, 1024, 0, 1); GWEN_Buffer_SetHardLimit(dst, AHB_DTAUS_HARDLIMIT); /* create A set */ if (AHB_DTAUS__CreateSetA(dst, cfg)) { DBG_INFO(AQBANKING_LOGDOMAIN, "Error creating A set"); GWEN_Buffer_free(dst); AB_Value_free(sumAccountIds); AB_Value_free(sumBankCodes); AB_Value_free(sumDEM); AB_Value_free(sumEUR); return -1; } /* create C sets */ gr=GWEN_DB_GetFirstGroup(data); while(gr) { const char *gn; gn=GWEN_DB_GroupName(gr); if ((isDebitNote && strcasecmp(gn, "debitnote")==0) || (!isDebitNote && (strcasecmp(gn, "transfer")==0 || strcasecmp(gn, "transaction")==0))){ if (AHB_DTAUS__CreateSetC(dst, cfg, gr, sumEUR, sumDEM, sumBankCodes, sumAccountIds)) { DBG_ERROR(AQBANKING_LOGDOMAIN, "Error creating C set from this data:"); GWEN_DB_Dump(gr, 2); GWEN_Buffer_free(dst); AB_Value_free(sumAccountIds); AB_Value_free(sumBankCodes); AB_Value_free(sumDEM); AB_Value_free(sumEUR); return -1; } cSets++; } /* if group matches */ else { DBG_ERROR(AQBANKING_LOGDOMAIN, "Ignoring group [%s]", GWEN_DB_GroupName(gr)); } gr=GWEN_DB_GetNextGroup(gr); } /* while */ /* create E set */ if (AHB_DTAUS__CreateSetE(dst, cfg, cSets, sumEUR, sumDEM, sumBankCodes, sumAccountIds)) { DBG_INFO(AQBANKING_LOGDOMAIN, "Error creating E set"); GWEN_Buffer_free(dst); AB_Value_free(sumAccountIds); AB_Value_free(sumBankCodes); AB_Value_free(sumDEM); AB_Value_free(sumEUR); return -1; } AB_Value_free(sumAccountIds); AB_Value_free(sumBankCodes); AB_Value_free(sumDEM); AB_Value_free(sumEUR); /* DTAUS finished, write it */ p=(const uint8_t*)GWEN_Buffer_GetStart(dst); size=GWEN_Buffer_GetUsedBytes(dst); rv=GWEN_SyncIo_WriteForced(sio, p, size); if (rv<0) { DBG_ERROR(AQBANKING_LOGDOMAIN, "Broken pipe"); GWEN_Buffer_free(dst); return GWEN_ERROR_IO; } GWEN_Buffer_free(dst); return 0; }
int AHB_DTAUS__CreateSetA(GWEN_BUFFER *dst, GWEN_DB_NODE *cfg) { unsigned int i; GWEN_TIME *gt; char buffer[16]; int day, month, year; const char *p; GWEN_DB_NODE *dbT; DBG_DEBUG(AQBANKING_LOGDOMAIN, "Creating A set"); /* field 1, 2: record header */ GWEN_Buffer_AppendString(dst, "0128A"); /* field 3: type */ p=GWEN_DB_GetCharValue(cfg, "type", 0, "transfer"); if (strcasecmp(p, "transfer")==0 || strcasecmp(p, "transaction")==0) GWEN_Buffer_AppendString(dst, "GK"); else if (strcasecmp(p, "debitnote")==0) GWEN_Buffer_AppendString(dst, "LK"); else { DBG_ERROR(AQBANKING_LOGDOMAIN, "Unknown group \"%s\"", GWEN_DB_GroupName(cfg)); return -1; } /* field 4: bank code */ if (AHB_DTAUS__AddNum(dst, 8, GWEN_DB_GetCharValue(cfg, "bankCode", 0, "0"))) { DBG_ERROR(AQBANKING_LOGDOMAIN, "Error writing bankCode to buffer"); return -1; } /* field 5: 0s */ for (i=0; i<8; i++) GWEN_Buffer_AppendByte(dst, '0'); /* field 6: sender name */ if (AHB_DTAUS__AddWord(dst, 27, GWEN_DB_GetCharValue(cfg, "name", 0, "0"))) { DBG_ERROR(AQBANKING_LOGDOMAIN, "Error writing name to buffer"); return -1; } /* field 7: date */ gt=GWEN_CurrentTime(); if (GWEN_Time_GetBrokenDownDate(gt, &day, &month, &year)) { DBG_ERROR(AQBANKING_LOGDOMAIN, "Unable to break down date"); GWEN_Time_free(gt); return -1; } GWEN_Time_free(gt); snprintf(buffer, sizeof(buffer), "%02d%02d%02d", day, month+1, year%100); if (AHB_DTAUS__AddWord(dst, 6, buffer)) { DBG_ERROR(AQBANKING_LOGDOMAIN, "Error writing to buffer"); return -1; } /* field 8: blanks */ for (i=0; i<4; i++) GWEN_Buffer_AppendByte(dst, ' '); /* field 9: account id */ if (AHB_DTAUS__AddNum(dst, 10, GWEN_DB_GetCharValue(cfg, "accountid", 0, ""))) { DBG_ERROR(AQBANKING_LOGDOMAIN, "Error writing accountid to buffer"); return -1; } /* field 10: customer reference */ if (AHB_DTAUS__AddNum(dst, 10, GWEN_DB_GetCharValue(cfg, "custref", 0, "0"))) { DBG_ERROR(AQBANKING_LOGDOMAIN, "Error writing custref to buffer"); return -1; } /* field 11a: blanks */ for (i=0; i<15; i++) GWEN_Buffer_AppendByte(dst, ' '); /* field 11b: date of execution */ dbT=GWEN_DB_GetGroup(cfg, GWEN_PATH_FLAGS_NAMEMUSTEXIST, "execdate"); if (dbT) { GWEN_TIME *ti; ti=GWEN_Time_fromDb(dbT); if (!ti) { DBG_ERROR(AQBANKING_LOGDOMAIN, "Bad execution date"); return -1; } if (GWEN_Time_GetBrokenDownDate(ti, &day, &month, &year)) { DBG_ERROR(AQBANKING_LOGDOMAIN, "Bad execution date"); GWEN_Time_free(ti); return -1; } snprintf(buffer, sizeof(buffer), "%02d%02d%04d", day, month+1, year); if (AHB_DTAUS__AddWord(dst, 8, buffer)) { DBG_ERROR(AQBANKING_LOGDOMAIN, "Error writing execdate to buffer"); GWEN_Time_free(ti); return -1; } GWEN_Time_free(ti); } else { if (AHB_DTAUS__AddWord(dst, 8, "")) { DBG_ERROR(AQBANKING_LOGDOMAIN, "Error writing to buffer"); return -1; } } /* field 11c: blanks */ for (i=0; i<24; i++) GWEN_Buffer_AppendByte(dst, ' '); /* field 12: currency */ p=GWEN_DB_GetCharValue(cfg, "currency", 0, "EUR"); if (strcasecmp(p, "EUR")==0) GWEN_Buffer_AppendByte(dst, '1'); else if (strcasecmp(p, "DEM")==0) GWEN_Buffer_AppendByte(dst, ' '); else { DBG_ERROR(AQBANKING_LOGDOMAIN, "Unknown currency \"%s\"", p); return -1; } return 0; }
int AH_Msg_VerifyRdh2(AH_MSG *hmsg, GWEN_DB_NODE *gr) { AH_HBCI *h; GWEN_LIST *sigheads; GWEN_LIST *sigtails; GWEN_DB_NODE *n; int nonSigHeads; int nSigheads; unsigned int dataBegin; char *dataStart; unsigned int dataLength; unsigned int i; AB_USER *u; GWEN_CRYPT_TOKEN *ct; const GWEN_CRYPT_TOKEN_CONTEXT *ctx; const GWEN_CRYPT_TOKEN_KEYINFO *ki; uint32_t keyId; int ksize; int rv; uint32_t gid; assert(hmsg); h=AH_Dialog_GetHbci(hmsg->dialog); assert(h); u=AH_Dialog_GetDialogOwner(hmsg->dialog); assert(u); gid=0; /* get crypt token of signer */ rv=AB_Banking_GetCryptToken(AH_HBCI_GetBankingApi(h), AH_User_GetTokenType(u), AH_User_GetTokenName(u), &ct); if (rv) { DBG_INFO(AQHBCI_LOGDOMAIN, "Could not get crypt token for user \"%s\" (%d)", AB_User_GetUserId(u), rv); return rv; } /* open CryptToken if necessary */ if (!GWEN_Crypt_Token_IsOpen(ct)) { GWEN_Crypt_Token_AddModes(ct, GWEN_CRYPT_TOKEN_MODE_DIRECT_SIGN); rv=GWEN_Crypt_Token_Open(ct, 0, gid); if (rv) { DBG_INFO(AQHBCI_LOGDOMAIN, "Could not open crypt token for user \"%s\" (%d)", AB_User_GetUserId(u), rv); return rv; } } /* get context and key info */ ctx=GWEN_Crypt_Token_GetContext(ct, AH_User_GetTokenContextId(u), gid); if (ctx==NULL) { DBG_INFO(AQHBCI_LOGDOMAIN, "Context %d not found on crypt token [%s:%s]", AH_User_GetTokenContextId(u), GWEN_Crypt_Token_GetTypeName(ct), GWEN_Crypt_Token_GetTokenName(ct)); return GWEN_ERROR_NOT_FOUND; } /* let's go */ sigheads=GWEN_List_new(); /* enumerate signature heads */ nonSigHeads=0; nSigheads=0; n=GWEN_DB_GetFirstGroup(gr); while(n) { if (strcasecmp(GWEN_DB_GroupName(n), "SigHead")==0) { /* found a signature head */ if (nonSigHeads) { DBG_ERROR(AQHBCI_LOGDOMAIN, "Found some unsigned parts at the beginning"); GWEN_List_free(sigheads); return GWEN_ERROR_BAD_DATA; } GWEN_List_PushBack(sigheads, n); nSigheads++; } else if (strcasecmp(GWEN_DB_GroupName(n), "MsgHead")!=0) { if (nSigheads) break; nonSigHeads++; } n=GWEN_DB_GetNextGroup(n); } /* while */ if (!n) { if (nSigheads) { DBG_ERROR(AQHBCI_LOGDOMAIN, "Found Signature heads but no other segments"); GWEN_List_free(sigheads); return GWEN_ERROR_BAD_DATA; } DBG_DEBUG(AQHBCI_LOGDOMAIN, "No signatures"); GWEN_List_free(sigheads); return 0; } /* only now we need the verify key */ keyId=GWEN_Crypt_Token_Context_GetVerifyKeyId(ctx); if (keyId==0) { DBG_INFO(AQHBCI_LOGDOMAIN, "No verify key id on crypt token [%s:%s]", GWEN_Crypt_Token_GetTypeName(ct), GWEN_Crypt_Token_GetTokenName(ct)); return GWEN_ERROR_NOT_FOUND; } ki=GWEN_Crypt_Token_GetKeyInfo(ct, keyId, 0xffffffff, gid); if (ki==NULL) { DBG_INFO(AQHBCI_LOGDOMAIN, "Keyinfo %04x not found on crypt token [%s:%s]", keyId, GWEN_Crypt_Token_GetTypeName(ct), GWEN_Crypt_Token_GetTokenName(ct)); /* no longer return an error, it might be ok to not have a key info * even if we do not propagate the error here the check functions will * later find out that the signature is missing */ return 0; } ksize=GWEN_Crypt_Token_KeyInfo_GetKeySize(ki); assert(ksize<=256); /* store begin of signed data */ dataBegin=GWEN_DB_GetIntValue(n, "segment/pos", 0, 0); if (!dataBegin) { DBG_ERROR(AQHBCI_LOGDOMAIN, "No position specifications in segment"); GWEN_List_free(sigheads); return GWEN_ERROR_BAD_DATA; } /* now get first signature tail */ while(n) { if (strcasecmp(GWEN_DB_GroupName(n), "SigTail")==0) { unsigned int currpos; /* found a signature tail */ currpos=GWEN_DB_GetIntValue(n, "segment/pos", 0, 0); if (!currpos || dataBegin>currpos) { DBG_ERROR(AQHBCI_LOGDOMAIN, "Bad position specification in Signature tail"); GWEN_List_free(sigheads); return GWEN_ERROR_BAD_DATA; } dataLength=currpos-dataBegin; break; } n=GWEN_DB_GetNextGroup(n); } /* while */ if (!n) { DBG_ERROR(AQHBCI_LOGDOMAIN, "No signature tail found"); GWEN_List_free(sigheads); return GWEN_ERROR_BAD_DATA; } sigtails=GWEN_List_new(); while(n) { if (strcasecmp(GWEN_DB_GroupName(n), "SigTail")!=0) break; GWEN_List_PushBack(sigtails, n); n=GWEN_DB_GetNextGroup(n); } /* while */ if (!n) { DBG_ERROR(AQHBCI_LOGDOMAIN, "Message tail expected"); GWEN_List_free(sigheads); GWEN_List_free(sigtails); return GWEN_ERROR_BAD_DATA; } if (strcasecmp(GWEN_DB_GroupName(n), "MsgTail")!=0) { DBG_ERROR(AQHBCI_LOGDOMAIN, "Unexpected segment (msg tail expected)"); GWEN_List_free(sigheads); GWEN_List_free(sigtails); return GWEN_ERROR_BAD_DATA; } n=GWEN_DB_GetNextGroup(n); if (n) { DBG_ERROR(AQHBCI_LOGDOMAIN, "Unexpected segment (end expected)"); GWEN_List_free(sigheads); GWEN_List_free(sigtails); return GWEN_ERROR_BAD_DATA; } if (GWEN_List_GetSize(sigheads)!= GWEN_List_GetSize(sigtails)) { DBG_ERROR(AQHBCI_LOGDOMAIN, "Number of signature heads (%d) does not match " "number of signature tails (%d)", GWEN_List_GetSize(sigheads), GWEN_List_GetSize(sigtails)); GWEN_List_free(sigheads); GWEN_List_free(sigtails); return GWEN_ERROR_BAD_DATA; } /* ok, now verify all signatures */ dataStart=GWEN_Buffer_GetStart(hmsg->buffer)+dataBegin; for (i=0; i< GWEN_List_GetSize(sigtails); i++) { GWEN_DB_NODE *sighead; GWEN_DB_NODE *sigtail; const uint8_t *p; uint32_t l; int rv; uint8_t hash[20]; const char *signerId; /* get signature tail */ sigtail=(GWEN_DB_NODE*)GWEN_List_GetBack(sigtails); /* get corresponding signature head */ sighead=(GWEN_DB_NODE*)GWEN_List_GetFront(sigheads); if (!sighead || !sigtail) { DBG_ERROR(AQHBCI_LOGDOMAIN, "No signature head/tail left (internal error)"); GWEN_List_free(sigheads); GWEN_List_free(sigtails); return GWEN_ERROR_INTERNAL; } GWEN_List_PopBack(sigtails); GWEN_List_PopFront(sigheads); signerId=GWEN_DB_GetCharValue(sighead, "key/userid", 0, I18N("unknown")); /* some checks */ if (strcasecmp(GWEN_DB_GetCharValue(sighead, "ctrlref", 0, ""), GWEN_DB_GetCharValue(sigtail, "ctrlref", 0, ""))!=0) { DBG_ERROR(AQHBCI_LOGDOMAIN, "Non-matching signature tail"); GWEN_List_free(sigheads); GWEN_List_free(sigtails); return GWEN_ERROR_BAD_DATA; } /* hash signature head and data */ if (1) { GWEN_MDIGEST *md; /* hash sighead + data */ p=(const uint8_t*)GWEN_Buffer_GetStart(hmsg->buffer); p+=GWEN_DB_GetIntValue(sighead, "segment/pos", 0, 0); l=GWEN_DB_GetIntValue(sighead, "segment/length", 0, 0); md=GWEN_MDigest_Rmd160_new(); rv=GWEN_MDigest_Begin(md); if (rv==0) /* digest signature head */ rv=GWEN_MDigest_Update(md, p, l); if (rv==0) /* digest data */ rv=GWEN_MDigest_Update(md, (const uint8_t*)dataStart, dataLength); if (rv==0) rv=GWEN_MDigest_End(md); if (rv<0) { DBG_ERROR(AQHBCI_LOGDOMAIN, "Hash error (%d)", rv); GWEN_MDigest_free(md); GWEN_List_free(sigheads); GWEN_List_free(sigtails); return rv; } memmove(hash, GWEN_MDigest_GetDigestPtr(md), GWEN_MDigest_GetDigestSize(md)); GWEN_MDigest_free(md); } /* verify signature */ p=GWEN_DB_GetBinValue(sigtail, "signature", 0, 0, 0, &l); if (p && l) { GWEN_CRYPT_PADDALGO *algo; algo=GWEN_Crypt_PaddAlgo_new(GWEN_Crypt_PaddAlgoId_Iso9796_2); GWEN_Crypt_PaddAlgo_SetPaddSize(algo, ksize); rv=GWEN_Crypt_Token_Verify(ct, keyId, algo, hash, 20, p, l, 0, gid); GWEN_Crypt_PaddAlgo_free(algo); if (rv) { if (rv==GWEN_ERROR_NO_KEY) { DBG_ERROR(AQHBCI_LOGDOMAIN, "Unable to verify signature of user \"%s\" (no key)", signerId); GWEN_Gui_ProgressLog(gid, GWEN_LoggerLevel_Error, I18N("Unable to verify signature (no key)")); } else { GWEN_BUFFER *tbuf; tbuf=GWEN_Buffer_new(0, 32, 0, 1); if (rv==GWEN_ERROR_VERIFY) { DBG_ERROR(AQHBCI_LOGDOMAIN, "Invalid signature of user \"%s\"", signerId); GWEN_Gui_ProgressLog(gid, GWEN_LoggerLevel_Error, I18N("Invalid signature!!!")); GWEN_Buffer_AppendString(tbuf, "!"); } else { GWEN_Gui_ProgressLog(gid, GWEN_LoggerLevel_Error, I18N("Could not verify signature")); DBG_ERROR(AQHBCI_LOGDOMAIN, "Could not verify data with medium of user \"%s\" (%d)", AB_User_GetUserId(u), rv); GWEN_Buffer_AppendString(tbuf, "?"); } GWEN_Buffer_AppendString(tbuf, signerId); AH_Msg_AddSignerId(hmsg, GWEN_Buffer_GetStart(tbuf)); GWEN_Buffer_free(tbuf); } } else { DBG_INFO(AQHBCI_LOGDOMAIN, "Message signed by \"%s\"", signerId); AH_Msg_AddSignerId(hmsg, signerId); } } else { DBG_DEBUG(AQHBCI_LOGDOMAIN, "No signature"); GWEN_List_free(sigheads); GWEN_List_free(sigtails); return GWEN_ERROR_BAD_DATA; } DBG_DEBUG(AQHBCI_LOGDOMAIN, "Verification done"); } /* for */ GWEN_List_free(sigheads); GWEN_List_free(sigtails); return 0; }
void AH_User_LoadTanMethods(AB_USER *u) { AH_USER *ue; assert(u); ue=GWEN_INHERIT_GETDATA(AB_USER, AH_USER, u); assert(ue); /* read directly from BPD */ if (ue->cryptMode==AH_CryptMode_Pintan) { GWEN_DB_NODE *db; int rv; AH_TanMethod_List_Clear(ue->tanMethodDescriptions); db=GWEN_DB_Group_new("bpd"); rv=AH_Job_SampleBpdVersions("JobTan", u, db); if (rv<0) { DBG_INFO(AQHBCI_LOGDOMAIN, "No BPD for TAN job"); } else { GWEN_DB_NODE *dbV; dbV=GWEN_DB_GetFirstGroup(db); while(dbV) { int version; version=atoi(GWEN_DB_GroupName(dbV)); if (version>0) { GWEN_DB_NODE *dbT; dbT=GWEN_DB_FindFirstGroup(dbV, "tanMethod"); if (!dbT) { DBG_INFO(AQHBCI_LOGDOMAIN, "No tan method found"); } while(dbT) { AH_TAN_METHOD *tm; const char *s; tm=AH_TanMethod_new(); AH_TanMethod_SetFunction(tm, GWEN_DB_GetIntValue(dbT, "function", 0, 0)); AH_TanMethod_SetProcess(tm, GWEN_DB_GetIntValue(dbT, "process", 0, 0)); AH_TanMethod_SetMethodId(tm, GWEN_DB_GetCharValue(dbT, "methodId", 0, 0)); AH_TanMethod_SetMethodName(tm, GWEN_DB_GetCharValue(dbT, "methodName", 0, 0)); AH_TanMethod_SetTanMaxLen(tm, GWEN_DB_GetIntValue(dbT, "tanMaxLen", 0, 0)); AH_TanMethod_SetFormatId(tm, GWEN_DB_GetCharValue(dbT, "formatId", 0, 0)); AH_TanMethod_SetPrompt(tm, GWEN_DB_GetCharValue(dbT, "prompt", 0, 0)); AH_TanMethod_SetReturnMaxLen(tm, GWEN_DB_GetIntValue(dbT, "returnMaxLen", 0, 0)); AH_TanMethod_SetMaxActiveLists(tm, GWEN_DB_GetIntValue(dbT, "maxActiveLists", 0, 0)); AH_TanMethod_SetGvVersion(tm, GWEN_DB_GetIntValue(dbT, "gvVersion", 0, 0)); s=GWEN_DB_GetCharValue(dbT, "multiTanAllowed", 0, NULL); if (s && strcasecmp(s, "j")==0) AH_TanMethod_SetMultiTanAllowed(tm, 1); AH_TanMethod_SetTimeShiftAllowed(tm, GWEN_DB_GetIntValue(dbT, "timeShiftAllowed", 0, 0)); AH_TanMethod_SetTanListMode(tm, GWEN_DB_GetIntValue(dbT, "tanListMode", 0, 0)); s=GWEN_DB_GetCharValue(dbT, "stornoAllowed", 0, NULL); if (s && strcasecmp(s, "j")==0) AH_TanMethod_SetStornoAllowed(tm, 1); s=GWEN_DB_GetCharValue(dbT, "needChallengeClass", 0, NULL); if (s && strcasecmp(s, "j")==0) AH_TanMethod_SetNeedChallengeClass(tm, 1); s=GWEN_DB_GetCharValue(dbT, "needChallengeAmount", 0, NULL); if (s && strcasecmp(s, "j")==0) AH_TanMethod_SetNeedChallengeAmount(tm, 1); AH_TanMethod_SetInitMode(tm, GWEN_DB_GetIntValue(dbT, "initMode", 0, 0)); s=GWEN_DB_GetCharValue(dbT, "tanMediumIdNeeded", 0, NULL); if (s && strcasecmp(s, "j")==0) AH_TanMethod_SetNeedTanMediumId(tm, 1); AH_TanMethod_SetMaxActiveTanMedia(tm, GWEN_DB_GetIntValue(dbT, "maxActiveMedia", 0, 0)); DBG_INFO(AQHBCI_LOGDOMAIN, "Adding TAN method %d [%s] for GV version %d", AH_TanMethod_GetFunction(tm), AH_TanMethod_GetMethodId(tm), version); AH_TanMethod_SetGvVersion(tm, version); AH_TanMethod_List_Add(tm, ue->tanMethodDescriptions); dbT=GWEN_DB_FindNextGroup(dbT, "tanMethod"); } } dbV=GWEN_DB_GetNextGroup(dbV); } } GWEN_DB_Group_free(db); } }