1 /***************************************************************************
2  begin       : Thu Aug 01 2019
3  copyright   : (C) 2019 by Martin Preuss
4  email       : martin@libchipcard.de
5 
6  ***************************************************************************
7  * This file is part of the project "AqBanking".                           *
8  * Please see toplevel file COPYING of that project for license details.   *
9  ***************************************************************************/
10 
11 #ifdef HAVE_CONFIG_H
12 # include <config.h>
13 #endif
14 
15 
16 #include "./session.h"
17 #include "s_message.h"
18 
19 #include "service/bpd/bpd_read.h"
20 
21 #include <gwenhywfar/debug.h>
22 
23 
24 
25 /* ------------------------------------------------------------------------------------------------
26  * forward declarations
27  * ------------------------------------------------------------------------------------------------
28  */
29 
30 static AQFINTS_MESSAGE *createMessage(AQFINTS_SESSION *sess, const char *bankCode);
31 static int mkGetAnonBpdMessage(AQFINTS_SESSION *sess, const char *bankCode, GWEN_BUFFER *destBuffer);
32 static AQFINTS_BPD *extractBpd(AQFINTS_SESSION *sess, const uint8_t *ptrBuffer, uint32_t lenBuffer);
33 
34 
35 
36 /* ------------------------------------------------------------------------------------------------
37  * implementations
38  * ------------------------------------------------------------------------------------------------
39  */
40 
41 
42 
AQFINTS_Session_GetAnonBpd(AQFINTS_SESSION * sess,const char * bankCode,AQFINTS_BPD ** pBpd)43 int AQFINTS_Session_GetAnonBpd(AQFINTS_SESSION *sess, const char *bankCode, AQFINTS_BPD **pBpd)
44 {
45   GWEN_BUFFER *destBuffer;
46   int rv;
47   AQFINTS_BPD *bpd;
48 
49   destBuffer=GWEN_Buffer_new(0, 256, 0, 1);
50   rv=mkGetAnonBpdMessage(sess, bankCode, destBuffer);
51   if (rv<0) {
52     DBG_ERROR(AQFINTS_LOGDOMAIN, "here (%d)", rv);
53     GWEN_Buffer_free(destBuffer);
54     return rv;
55   }
56 
57   rv=AQFINTS_Session_Connect(sess);
58   if (rv<0) {
59     DBG_ERROR(AQFINTS_LOGDOMAIN, "here (%d)", rv);
60     GWEN_Buffer_free(destBuffer);
61     return rv;
62   }
63 
64   rv=AQFINTS_Session_SendMessage(sess,
65                                  GWEN_Buffer_GetStart(destBuffer),
66                                  GWEN_Buffer_GetUsedBytes(destBuffer));
67   if (rv<0) {
68     DBG_ERROR(AQFINTS_LOGDOMAIN, "here (%d)", rv);
69     AQFINTS_Session_Disconnect(sess);
70     GWEN_Buffer_free(destBuffer);
71     return rv;
72   }
73 
74   GWEN_Buffer_Reset(destBuffer);
75 
76   rv=AQFINTS_Session_ReceiveMessage(sess, destBuffer);
77   if (rv<0) {
78     DBG_ERROR(AQFINTS_LOGDOMAIN, "here (%d)", rv);
79     AQFINTS_Session_Disconnect(sess);
80     GWEN_Buffer_free(destBuffer);
81     return rv;
82   }
83 
84   AQFINTS_Session_Disconnect(sess);
85 
86   bpd=extractBpd(sess,
87                  (const uint8_t *) GWEN_Buffer_GetStart(destBuffer),
88                  GWEN_Buffer_GetUsedBytes(destBuffer));
89   if (bpd==NULL) {
90     DBG_ERROR(AQFINTS_LOGDOMAIN, "No BPD extracted");
91     GWEN_Buffer_free(destBuffer);
92     return rv;
93   }
94 
95   GWEN_Buffer_free(destBuffer);
96 
97   *pBpd=bpd;
98   return 0;
99 }
100 
101 
102 
extractBpd(AQFINTS_SESSION * sess,const uint8_t * ptrBuffer,uint32_t lenBuffer)103 AQFINTS_BPD *extractBpd(AQFINTS_SESSION *sess, const uint8_t *ptrBuffer, uint32_t lenBuffer)
104 {
105   AQFINTS_SEGMENT_LIST *segmentList;
106   AQFINTS_PARSER *parser;
107   AQFINTS_BPD *bpd;
108   int rv;
109 
110   parser=AQFINTS_Session_GetParser(sess);
111   segmentList=AQFINTS_Segment_List_new();
112   rv=AQFINTS_Parser_ReadIntoSegmentList(parser, segmentList, ptrBuffer, lenBuffer);
113   if (rv<0) {
114     DBG_ERROR(AQFINTS_LOGDOMAIN, "here (%d)", rv);
115     AQFINTS_Segment_List_free(segmentList);
116     return NULL;
117   }
118 
119   rv=AQFINTS_Parser_ReadSegmentListToDb(parser, segmentList);
120   if (rv<0) {
121     DBG_ERROR(AQFINTS_LOGDOMAIN, "here (%d)", rv);
122     AQFINTS_Segment_List_free(segmentList);
123     return NULL;
124   }
125 
126   bpd=AQFINTS_Session_ExtractBpdFromSegmentList(sess, segmentList);
127   if (bpd==NULL) {
128     DBG_ERROR(AQFINTS_LOGDOMAIN, "Empty BPD");
129     AQFINTS_Segment_List_free(segmentList);
130     return NULL;
131   }
132 
133   AQFINTS_Segment_List_free(segmentList);
134   return bpd;
135 }
136 
137 
138 
139 
140 
mkGetAnonBpdMessage(AQFINTS_SESSION * sess,const char * bankCode,GWEN_BUFFER * destBuffer)141 int mkGetAnonBpdMessage(AQFINTS_SESSION *sess, const char *bankCode, GWEN_BUFFER *destBuffer)
142 {
143   AQFINTS_MESSAGE *message;
144   AQFINTS_SEGMENT_LIST *segmentList;
145   AQFINTS_SEGMENT *segment;
146   int rv;
147 
148   message=createMessage(sess, bankCode);
149   if (message==NULL) {
150     DBG_ERROR(AQFINTS_LOGDOMAIN, "No message created");
151     return GWEN_ERROR_INVALID;
152   }
153 
154   segmentList=AQFINTS_Message_GetSegmentList(message);
155 
156   segment=AQFINTS_Segment_List_Last(segmentList);
157   assert(segment);
158 
159   rv=AQFINTS_Session_WrapMessageHeadAndTail(sess, segmentList,
160                                             AQFINTS_Message_GetDialogId(message),
161                                             AQFINTS_Message_GetMessageNumber(message),
162                                             AQFINTS_Message_GetRefMessageNumber(message),
163                                             AQFINTS_Segment_GetSegmentNumber(segment));
164   if (rv<0) {
165     DBG_ERROR(AQFINTS_LOGDOMAIN, "here (%d)", rv);
166     AQFINTS_Message_free(message);
167     return rv;
168   }
169 
170   AQFINTS_Segment_List_SampleBuffers(segmentList, destBuffer);
171   AQFINTS_Message_free(message);
172   return 0;
173 }
174 
175 
176 
177 
178 
179 
createMessage(AQFINTS_SESSION * sess,const char * bankCode)180 AQFINTS_MESSAGE *createMessage(AQFINTS_SESSION *sess, const char *bankCode)
181 {
182   AQFINTS_PARSER *parser;
183   int hbciVersion;
184   AQFINTS_MESSAGE *message;
185   AQFINTS_SEGMENT *defSegment;
186   AQFINTS_SEGMENT *segment;
187   GWEN_DB_NODE *dbSegment;
188 
189   parser=AQFINTS_Session_GetParser(sess);
190   hbciVersion=AQFINTS_Session_GetHbciVersion(sess);
191 
192   message=AQFINTS_Message_new();
193   AQFINTS_Message_SetMessageNumber(message, AQFINTS_Session_GetLastMessageNumSent(sess)+1);
194 
195   /* ident */
196   defSegment=AQFINTS_Parser_FindSegmentHighestVersionForProto(parser, "HKIDN", hbciVersion);
197   if (defSegment==NULL) {
198     DBG_ERROR(AQFINTS_LOGDOMAIN, "No matching definition segment found for HKIDN (proto=%d)", hbciVersion);
199     return NULL;
200   }
201   segment=AQFINTS_Segment_new();
202   AQFINTS_Segment_copy(segment, defSegment);
203   dbSegment=GWEN_DB_Group_new("ident");
204   AQFINTS_Segment_SetDbData(segment, dbSegment);
205   GWEN_DB_SetIntValue(dbSegment, GWEN_DB_FLAGS_OVERWRITE_VARS, "country", 280);
206   GWEN_DB_SetCharValue(dbSegment, GWEN_DB_FLAGS_OVERWRITE_VARS, "bankCode", bankCode);
207   GWEN_DB_SetCharValue(dbSegment, GWEN_DB_FLAGS_OVERWRITE_VARS, "customerId", "9999999999");
208   GWEN_DB_SetCharValue(dbSegment, GWEN_DB_FLAGS_OVERWRITE_VARS, "systemId", "0");
209   GWEN_DB_SetIntValue(dbSegment, GWEN_DB_FLAGS_OVERWRITE_VARS, "status", 0);
210   AQFINTS_Message_AddSegment(message, segment);
211 
212   /* prepare */
213   defSegment=AQFINTS_Parser_FindSegmentHighestVersionForProto(parser, "HKVVB", hbciVersion);
214   if (defSegment==NULL) {
215     DBG_ERROR(AQFINTS_LOGDOMAIN, "No matching definition segment found for HKVVB (proto=%d)", hbciVersion);
216     return NULL;
217   }
218   segment=AQFINTS_Segment_new();
219   AQFINTS_Segment_copy(segment, defSegment);
220   dbSegment=GWEN_DB_Group_new("ident");
221   AQFINTS_Segment_SetDbData(segment, dbSegment);
222   GWEN_DB_SetIntValue(dbSegment, GWEN_DB_FLAGS_OVERWRITE_VARS, "bpdVersion", 0);
223   GWEN_DB_SetIntValue(dbSegment, GWEN_DB_FLAGS_OVERWRITE_VARS, "updVersion", 0);
224   GWEN_DB_SetIntValue(dbSegment, GWEN_DB_FLAGS_OVERWRITE_VARS, "lang", 1);
225   GWEN_DB_SetCharValue(dbSegment, GWEN_DB_FLAGS_OVERWRITE_VARS, "product", "AqBanking");
226   GWEN_DB_SetCharValue(dbSegment, GWEN_DB_FLAGS_OVERWRITE_VARS, "version", "5.99");
227   AQFINTS_Message_AddSegment(message, segment);
228 
229   return message;
230 }
231 
232 
233 
234 
235