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