1 /***************************************************************************
2  begin       : Tue May 03 2005
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 "globals_l.h"
16 #include "aqhbci/banking/user.h"
17 #include "aqhbci/banking/provider_l.h"
18 #include "aqhbci/banking/provider_tan.h"
19 
20 #include <gwenhywfar/text.h>
21 
22 
23 #include <stdlib.h>
24 #include <stdio.h>
25 #include <errno.h>
26 
27 
28 
29 
30 static GWEN_DB_NODE *_readCommandLine(GWEN_DB_NODE *dbArgs, int argc, char **argv);
31 static int _readFile(const char *fname, GWEN_BUFFER *dbuf);
32 static const AH_TAN_METHOD *_getSelectedTanMethod(AB_USER *u, int tanMethodId);
33 
34 
35 
36 
37 
AH_Control_Test1(AB_PROVIDER * pro,GWEN_DB_NODE * dbArgs,int argc,char ** argv)38 int AH_Control_Test1(AB_PROVIDER *pro,
39                      GWEN_DB_NODE *dbArgs,
40                      int argc,
41                      char **argv)
42 {
43   int rv;
44   GWEN_DB_NODE *db;
45   uint32_t uid;
46   AB_USER *u=NULL;
47   uint32_t tanMethodId;
48   const char *challengFile;
49   GWEN_BUFFER *challengeBuf=NULL;
50 
51   db=_readCommandLine(dbArgs, argc, argv);
52   if (db==NULL) {
53     fprintf(stderr, "ERROR: Could not parse arguments\n");
54     return 1;
55   }
56 
57   challengFile=GWEN_DB_GetCharValue(db, "challengeFile", 0, NULL);
58   if (!(challengFile && *challengFile)) {
59     fprintf(stderr, "ERROR: Missing challenge file\n");
60     return 1;
61   }
62 
63   uid=(uint32_t) GWEN_DB_GetIntValue(db, "userId", 0, 0);
64   if (uid==0) {
65     fprintf(stderr, "ERROR: Invalid or missing unique user id\n");
66     return 1;
67   }
68 
69   tanMethodId=(uint32_t) GWEN_DB_GetIntValue(db, "tanMethodId", 0, 0);
70   if (tanMethodId==0) {
71     fprintf(stderr, "ERROR: Invalid or missing tan method if\n");
72     return 1;
73   }
74 
75   if (challengFile) {
76     GWEN_BUFFER *dbuf;
77 
78     dbuf=GWEN_Buffer_new(0, 256, 0, 1);
79     rv=_readFile(challengFile, dbuf);
80     if (rv<0) {
81       fprintf(stderr, "ERROR: Could not read file \"%s\": %d\n", challengFile, rv);
82       GWEN_Buffer_free(dbuf);
83       return 2;
84     }
85 
86     challengeBuf=GWEN_Buffer_new(0, 256, 0, 1);
87     rv=GWEN_Text_ToHexBuffer(GWEN_Buffer_GetStart(dbuf),
88                              GWEN_Buffer_GetUsedBytes(dbuf),
89                              challengeBuf,
90                              0, 0, 0);
91     if (rv<0) {
92       fprintf(stderr, "ERROR: Could not hex encode file \"%s\": %d\n", challengFile, rv);
93       GWEN_Buffer_free(challengeBuf);
94       GWEN_Buffer_free(dbuf);
95       return 2;
96     }
97     GWEN_Buffer_free(dbuf);
98   }
99 
100 
101   rv=AB_Provider_HasUser(pro, uid);
102   if (rv<0) {
103     fprintf(stderr, "ERROR: User with id %lu not found\n", (unsigned long int) uid);
104     GWEN_Buffer_free(challengeBuf);
105     return 2;
106   }
107   rv=AB_Provider_GetUser(pro, uid, 1, 1, &u);
108   if (rv<0) {
109     fprintf(stderr, "ERROR: User with id %lu not found\n", (unsigned long int) uid);
110     GWEN_Buffer_free(challengeBuf);
111     return 2;
112   }
113   else {
114     const AH_TAN_METHOD *tanMethod;
115     char tanBuffer[16];
116 
117     tanMethod=_getSelectedTanMethod(u, tanMethodId);
118     if (tanMethod==NULL) {
119       fprintf(stderr, "ERROR: TAN method with id %lu not found\n", (unsigned long int) tanMethodId);
120       GWEN_Buffer_free(challengeBuf);
121       return 2;
122     }
123 
124     rv=AH_Provider_InputTanWithChallenge(pro,
125                                          u,
126                                          tanMethod,
127                                          "Could be a real challenge string but it isn't",
128                                          GWEN_Buffer_GetStart(challengeBuf),
129                                          tanBuffer,
130                                          1,
131                                          sizeof(tanBuffer)-1);
132     if (rv<0) {
133       fprintf(stderr, "ERROR: Error in TAN input (%d)\n", rv);
134       GWEN_Buffer_free(challengeBuf);
135       return 2;
136     }
137   }
138 
139 
140   AB_User_free(u);
141 
142   return 0;
143 }
144 
145 
146 
147 
_readCommandLine(GWEN_DB_NODE * dbArgs,int argc,char ** argv)148 GWEN_DB_NODE *_readCommandLine(GWEN_DB_NODE *dbArgs, int argc, char **argv)
149 {
150   GWEN_DB_NODE *db;
151   int rv;
152   const GWEN_ARGS args[]= {
153     {
154       GWEN_ARGS_FLAGS_HAS_ARGUMENT, /* flags */
155       GWEN_ArgsType_Int,            /* type */
156       "userId",                     /* name */
157       0,                            /* minnum */
158       1,                            /* maxnum */
159       "u",                          /* short option */
160       "user",                       /* long option */
161       "Specify the unique user id",    /* short description */
162       "Specify the unique user id"     /* long description */
163     },
164     {
165       GWEN_ARGS_FLAGS_HAS_ARGUMENT, /* flags */
166       GWEN_ArgsType_Int,            /* type */
167       "tanMethodId",                /* name */
168       1,                            /* minnum */
169       1,                            /* maxnum */
170       "m",                          /* short option */
171       NULL,                         /* long option */
172       "Specify the TAN method id",  /* short description */
173       "Specify the TAN method id"     /* long description */
174     },
175     {
176       GWEN_ARGS_FLAGS_HAS_ARGUMENT, /* flags */
177       GWEN_ArgsType_Char,           /* type */
178       "challengeFile",              /* name */
179       1,                            /* minnum */
180       1,                            /* maxnum */
181       "f",                          /* short option */
182       NULL,                         /* long option */
183       "Specify the challenge file to load", /* short */
184       "Specify the challenge file to load" /* long */
185     },
186     {
187       GWEN_ARGS_FLAGS_HELP | GWEN_ARGS_FLAGS_LAST, /* flags */
188       GWEN_ArgsType_Int,            /* type */
189       "help",                       /* name */
190       0,                            /* minnum */
191       0,                            /* maxnum */
192       "h",                          /* short option */
193       "help",                       /* long option */
194       "Show this help screen",      /* short description */
195       "Show this help screen"       /* long description */
196     }
197   };
198 
199   db=GWEN_DB_GetGroup(dbArgs, GWEN_DB_FLAGS_DEFAULT, "local");
200   rv=GWEN_Args_Check(argc, argv, 1,
201                      0 /*GWEN_ARGS_MODE_ALLOW_FREEPARAM*/,
202                      args,
203                      db);
204   if (rv==GWEN_ARGS_RESULT_ERROR) {
205     fprintf(stderr, "ERROR: Could not parse arguments\n");
206     return NULL;
207   }
208   else if (rv==GWEN_ARGS_RESULT_HELP) {
209     GWEN_BUFFER *ubuf;
210 
211     ubuf=GWEN_Buffer_new(0, 1024, 0, 1);
212     if (GWEN_Args_Usage(args, ubuf, GWEN_ArgsOutType_Txt)) {
213       fprintf(stderr, "ERROR: Could not create help string\n");
214       return NULL;
215     }
216     fprintf(stdout, "%s\n", GWEN_Buffer_GetStart(ubuf));
217     GWEN_Buffer_free(ubuf);
218     return NULL;
219   }
220 
221   return db;
222 }
223 
224 
225 
226 
_readFile(const char * fname,GWEN_BUFFER * dbuf)227 int _readFile(const char *fname, GWEN_BUFFER *dbuf)
228 {
229   FILE *f;
230 
231   f=fopen(fname, "rb");
232   if (f) {
233     while (!feof(f)) {
234       uint32_t l;
235       ssize_t s;
236       char *p;
237 
238       GWEN_Buffer_AllocRoom(dbuf, 1024);
239       l=GWEN_Buffer_GetMaxUnsegmentedWrite(dbuf);
240       p=GWEN_Buffer_GetPosPointer(dbuf);
241       s=fread(p, 1, l, f);
242       if (s==0)
243         break;
244       if (s==(ssize_t)-1) {
245         DBG_ERROR(0,
246                   "fread(%s): %s",
247                   fname, strerror(errno));
248         fclose(f);
249         return GWEN_ERROR_IO;
250       }
251 
252       GWEN_Buffer_IncrementPos(dbuf, s);
253       GWEN_Buffer_AdjustUsedBytes(dbuf);
254     }
255 
256     fclose(f);
257     return 0;
258   }
259   else {
260     DBG_ERROR(0,
261               "fopen(%s): %s",
262               fname, strerror(errno));
263     return GWEN_ERROR_IO;
264   }
265 }
266 
267 
268 
_getSelectedTanMethod(AB_USER * u,int tanMethodId)269 const AH_TAN_METHOD *_getSelectedTanMethod(AB_USER *u, int tanMethodId)
270 {
271   const AH_TAN_METHOD_LIST *tanMethodList;
272 
273   tanMethodList=AH_User_GetTanMethodDescriptions(u);
274   if (tanMethodList) {
275     const AH_TAN_METHOD *tanMethod;
276 
277     tanMethod=AH_TanMethod_List_First(tanMethodList);
278     while (tanMethod) {
279       int combinedVersion;
280 
281       combinedVersion=AH_TanMethod_GetFunction(tanMethod)+(AH_TanMethod_GetGvVersion(tanMethod)*1000);
282       if (combinedVersion==tanMethodId)
283         return tanMethod;
284       tanMethod=AH_TanMethod_List_Next(tanMethod);
285     }
286   }
287 
288   return NULL;
289 }
290 
291 
292 
293