1 /***************************************************************************
2 begin : Mon Mar 01 2004
3 copyright : (C) 2018 by Martin Preuss
4 email : martin@libchipcard.de
5
6 ***************************************************************************
7 * Please see toplevel file COPYING for license details *
8 ***************************************************************************/
9
10 #ifdef HAVE_CONFIG_H
11 # include <config.h>
12 #endif
13
14
15 #include "job_swift.h"
16
17 #include "aqhbci/banking/user_l.h"
18
19 #include <aqbanking/i18n_l.h>
20 #include <aqbanking/backendsupport/user.h>
21
22 #include <gwenhywfar/db.h>
23 #include <gwenhywfar/debug.h>
24
25
26
27
AH_Job_CheckEncryption(AH_JOB * j,GWEN_DB_NODE * dbRsp)28 int AH_Job_CheckEncryption(AH_JOB *j, GWEN_DB_NODE *dbRsp)
29 {
30 AB_USER *user;
31 const char *sExpectedCrypter;
32
33 assert(j);
34
35 user=AH_Job_GetUser(j);
36 assert(user);
37
38 if (AH_User_GetCryptMode(user)==AH_CryptMode_Pintan) {
39 DBG_DEBUG(AQHBCI_LOGDOMAIN, "Not checking security in PIN/TAN mode");
40 }
41 else {
42 GWEN_DB_NODE *dbSecurity;
43 const char *s;
44
45 assert(dbRsp);
46 dbSecurity=GWEN_DB_GetGroup(dbRsp, GWEN_PATH_FLAGS_NAMEMUSTEXIST, "security");
47 if (!dbSecurity) {
48 DBG_ERROR(AQHBCI_LOGDOMAIN, "No security settings, should not happen");
49 GWEN_Gui_ProgressLog(0,
50 GWEN_LoggerLevel_Error,
51 I18N("Response without security info (internal)"));
52 return AB_ERROR_SECURITY;
53 }
54
55 s=GWEN_DB_GetCharValue(dbSecurity, "crypter", 0, 0);
56 if (s) {
57 DBG_DEBUG(AQHBCI_LOGDOMAIN, "Response encrypted with key [%s]", s);
58
59 if (*s=='!' || *s=='?') {
60 DBG_ERROR(AQHBCI_LOGDOMAIN, "Encrypted with invalid key (%s)", s);
61 GWEN_Gui_ProgressLog(0,
62 GWEN_LoggerLevel_Error,
63 I18N("Response encrypted with invalid key"));
64 return AB_ERROR_SECURITY;
65 }
66 }
67
68 sExpectedCrypter=AH_Job_GetExpectedCrypter(j);
69 if (sExpectedCrypter) {
70 /* check crypter */
71 if (!s) {
72 DBG_ERROR(AQHBCI_LOGDOMAIN,
73 "Response is not encrypted (but expected to be)");
74 GWEN_Gui_ProgressLog(0,
75 GWEN_LoggerLevel_Error,
76 I18N("Response is not encrypted as expected"));
77 return AB_ERROR_SECURITY;
78
79 }
80
81 if (strcasecmp(s, sExpectedCrypter)!=0) {
82 DBG_WARN(AQHBCI_LOGDOMAIN,
83 "Not encrypted with the expected key "
84 "(exp: \"%s\", is: \"%s\"",
85 sExpectedCrypter, s);
86 /*
87 GWEN_Gui_ProgressLog(
88 0,
89 GWEN_LoggerLevel_Error,
90 I18N("Response not encrypted with expected key"));
91 return AB_ERROR_SECURITY;
92 */
93 }
94 }
95 else {
96 DBG_DEBUG(AQHBCI_LOGDOMAIN, "No specific encrypter expected");
97 }
98 }
99
100 return 0;
101 }
102
103
104
AH_Job_CheckSignature(AH_JOB * j,GWEN_DB_NODE * dbRsp)105 int AH_Job_CheckSignature(AH_JOB *j, GWEN_DB_NODE *dbRsp)
106 {
107 AB_USER *user;
108 const char *sExpectedSigner;
109
110 assert(j);
111
112 user=AH_Job_GetUser(j);
113 assert(user);
114
115 if (AH_User_GetCryptMode(user)==AH_CryptMode_Pintan) {
116 DBG_DEBUG(AQHBCI_LOGDOMAIN, "Not checking signature in PIN/TAN mode");
117 }
118 else {
119 GWEN_DB_NODE *dbSecurity;
120 int i;
121 uint32_t uFlags;
122
123 assert(j);
124
125 uFlags=AH_User_GetFlags(user);
126
127 assert(dbRsp);
128 dbSecurity=GWEN_DB_GetGroup(dbRsp, GWEN_PATH_FLAGS_NAMEMUSTEXIST,
129 "security");
130 if (!dbSecurity) {
131 DBG_ERROR(AQHBCI_LOGDOMAIN,
132 "No security settings, should not happen");
133 GWEN_Gui_ProgressLog(
134 0,
135 GWEN_LoggerLevel_Error,
136 I18N("Response without security info (internal)"));
137 return GWEN_ERROR_GENERIC;
138 }
139
140 /* check for invalid signers */
141 for (i=0; ; i++) {
142 const char *s;
143
144 s=GWEN_DB_GetCharValue(dbSecurity, "signer", i, 0);
145 if (!s)
146 break;
147 if (*s=='!') {
148 DBG_ERROR(AQHBCI_LOGDOMAIN,
149 "Invalid signature found, will not tolerate it");
150 GWEN_Gui_ProgressLog(0,
151 GWEN_LoggerLevel_Error,
152 I18N("Invalid bank signature"));
153 return AB_ERROR_SECURITY;
154 }
155 } /* for */
156
157 sExpectedSigner=AH_Job_GetExpectedSigner(j);
158 if (sExpectedSigner && !(uFlags & AH_USER_FLAGS_BANK_DOESNT_SIGN)) {
159 /* check signer */
160 for (i=0; ; i++) {
161 const char *s;
162
163 s=GWEN_DB_GetCharValue(dbSecurity, "signer", i, 0);
164 if (!s) {
165 DBG_ERROR(AQHBCI_LOGDOMAIN,
166 "Not signed by expected signer (%d)", i);
167 GWEN_Gui_ProgressLog(0,
168 GWEN_LoggerLevel_Error,
169 I18N("Response not signed by the bank"));
170 if (i==0) {
171 int button;
172
173 /* check whether the user want's to accept the unsigned message */
174 button=GWEN_Gui_MessageBox(GWEN_GUI_MSG_FLAGS_TYPE_WARN |
175 GWEN_GUI_MSG_FLAGS_CONFIRM_B1 |
176 GWEN_GUI_MSG_FLAGS_SEVERITY_DANGEROUS,
177 I18N("Security Warning"),
178 I18N("The HBCI response of the bank has not been signed by the bank, \n"
179 "contrary to what has been expected. This can be the case because the \n"
180 "bank just stopped signing their HBCI responses. This error message \n"
181 "would also occur if there were a replay attack against your computer \n"
182 "in progress right now, which is probably quite unlikely. \n"
183 " \n"
184 "Please contact your bank and ask them whether their HBCI server \n"
185 "stopped signing the HBCI responses. If the bank is concerned about \n"
186 "your security, it should not stop signing the HBCI responses. \n"
187 " \n"
188 "Do you nevertheless want to accept this response this time or always?"
189 "<html><p>"
190 "The HBCI response of the bank has not been signed by the bank, \n"
191 "contrary to what has been expected. This can be the case because the \n"
192 "bank just stopped signing their HBCI responses. This error message \n"
193 "would also occur if there were a replay attack against your computer \n"
194 "in progress right now, which is probably quite unlikely. \n"
195 "</p><p>"
196 "Please contact your bank and ask them whether their HBCI server \n"
197 "stopped signing the HBCI responses. If the bank is concerned about \n"
198 "your security, it should not stop signing the HBCI responses. \n"
199 "</p><p>"
200 "Do you nevertheless want to accept this response this time or always?"
201 "</p></html>"
202 ),
203 I18N("Accept this time"),
204 I18N("Accept always"),
205 I18N("Abort"), 0);
206 if (button==1) {
207 GWEN_Gui_ProgressLog(0,
208 GWEN_LoggerLevel_Notice,
209 I18N("User accepts this unsigned "
210 "response"));
211 AH_Job_SetExpectedSigner(j, 0);
212 break;
213 }
214 else if (button==2) {
215 GWEN_Gui_ProgressLog(0,
216 GWEN_LoggerLevel_Notice,
217 I18N("User accepts all further unsigned "
218 "responses"));
219 AH_User_AddFlags(user, AH_USER_FLAGS_BANK_DOESNT_SIGN);
220 AH_Job_SetExpectedSigner(j, NULL);
221 break;
222 }
223 else {
224 GWEN_Gui_ProgressLog(0,
225 GWEN_LoggerLevel_Error,
226 I18N("Aborted"));
227 return AB_ERROR_SECURITY;
228 }
229 }
230 else {
231 int ii;
232
233 DBG_ERROR(AQHBCI_LOGDOMAIN,
234 "Job signed with unexpected key(s)"
235 "(was expecting \"%s\"):",
236 sExpectedSigner);
237 for (ii=0; ; ii++) {
238 s=GWEN_DB_GetCharValue(dbSecurity, "signer", ii, 0);
239 if (!s)
240 break;
241 DBG_ERROR(AQHBCI_LOGDOMAIN,
242 "Signed unexpectedly with key \"%s\"", s);
243 }
244 return AB_ERROR_SECURITY;
245 }
246 }
247 else {
248 if (strcasecmp(s, sExpectedSigner)==0) {
249 DBG_DEBUG(AQHBCI_LOGDOMAIN,
250 "Jobs signed as expected with \"%s\"",
251 sExpectedSigner);
252 break;
253 }
254 else if (*s!='!' && *s!='?') {
255 DBG_INFO(AQHBCI_LOGDOMAIN,
256 "Signer name does not match expected name (%s!=%s), "
257 "but we accept it anyway",
258 s, sExpectedSigner);
259 break;
260 }
261 }
262 } /* for */
263 DBG_DEBUG(AQHBCI_LOGDOMAIN, "Signature check ok");
264 }
265 else {
266 DBG_DEBUG(AQHBCI_LOGDOMAIN, "No signature expected");
267 }
268 }
269 return 0;
270 }
271
272