1 /***************************************************************************
2     begin       : Sat Dec 01 2018
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 
11 /* included from provider.c */
12 
13 
14 
15 
16 
readFile(const char * fname,GWEN_BUFFER * dbuf)17 static int readFile(const char *fname, GWEN_BUFFER *dbuf)
18 {
19   FILE *f;
20 
21   f=fopen(fname, "rb");
22   if (f) {
23     while (!feof(f)) {
24       uint32_t l;
25       ssize_t s;
26       char *p;
27 
28       GWEN_Buffer_AllocRoom(dbuf, 1024);
29       l=GWEN_Buffer_GetMaxUnsegmentedWrite(dbuf);
30       p=GWEN_Buffer_GetPosPointer(dbuf);
31       s=fread(p, 1, l, f);
32       if (s==0)
33         break;
34       if (s==(ssize_t)-1) {
35         DBG_ERROR(AQPAYPAL_LOGDOMAIN,
36                   "fread(%s): %s",
37                   fname, strerror(errno));
38         fclose(f);
39         return GWEN_ERROR_IO;
40       }
41 
42       GWEN_Buffer_IncrementPos(dbuf, s);
43       GWEN_Buffer_AdjustUsedBytes(dbuf);
44     }
45 
46     fclose(f);
47     return 0;
48   }
49   else {
50     DBG_ERROR(AQPAYPAL_LOGDOMAIN,
51               "fopen(%s): %s",
52               fname, strerror(errno));
53     return GWEN_ERROR_IO;
54   }
55 }
56 
57 
58 
writeToFile(FILE * f,const char * p,int len)59 static int writeToFile(FILE *f, const char *p, int len)
60 {
61   while (len>0) {
62     ssize_t l;
63     ssize_t s;
64 
65     l=1024;
66     if (l>len)
67       l=len;
68     s=fwrite(p, 1, l, f);
69     if (s==(ssize_t)-1 || s==0) {
70       DBG_ERROR(AQPAYPAL_LOGDOMAIN,
71                 "fwrite: %s",
72                 strerror(errno));
73       return GWEN_ERROR_IO;
74     }
75     p+=s;
76     len-=s;
77   }
78 
79   return 0;
80 }
81 
82 
83 
writeFile(const char * fname,const char * p,int len)84 static int writeFile(const char *fname, const char *p, int len)
85 {
86   FILE *f;
87 
88   f=fopen(fname, "wb");
89   if (f) {
90     int rv;
91 
92     rv=writeToFile(f, p, len);
93     if (rv<0) {
94       DBG_ERROR(AQPAYPAL_LOGDOMAIN, "here (%d)", rv);
95       fclose(f);
96       return rv;
97     }
98     if (fclose(f)) {
99       DBG_ERROR(AQPAYPAL_LOGDOMAIN, "here (%d)", rv);
100       return rv;
101     }
102   }
103   else {
104     DBG_ERROR(AQPAYPAL_LOGDOMAIN, "fopen(%s): %s",
105               fname, strerror(errno));
106     return GWEN_ERROR_IO;
107   }
108 
109   return 0;
110 }
111 
112 
113 
114 
APY_Provider_ReadUserApiSecrets(AB_PROVIDER * pro,const AB_USER * u,GWEN_BUFFER * secbuf)115 int APY_Provider_ReadUserApiSecrets(AB_PROVIDER *pro, const AB_USER *u, GWEN_BUFFER *secbuf)
116 {
117   APY_PROVIDER *xp;
118   int rv;
119   GWEN_BUFFER *pbuf;
120   GWEN_BUFFER *sbuf;
121   GWEN_BUFFER *tbuf;
122   const char *uid;
123   char text[512];
124   char pw[129];
125 
126   assert(pro);
127   xp=GWEN_INHERIT_GETDATA(AB_PROVIDER, APY_PROVIDER, pro);
128   assert(xp);
129 
130   uid=AB_User_GetUserId(u);
131   if (!(uid && *uid)) {
132     DBG_ERROR(AQPAYPAL_LOGDOMAIN, "No user id");
133     return GWEN_ERROR_INVALID;
134   }
135 
136   pbuf=GWEN_Buffer_new(0, 256, 0, 1);
137   rv=AB_Provider_GetUserDataDir(pro, pbuf);
138   if (rv<0) {
139     DBG_INFO(AQPAYPAL_LOGDOMAIN, "here (%d)", rv);
140     GWEN_Buffer_free(pbuf);
141     return rv;
142   }
143 
144   GWEN_Buffer_AppendString(pbuf, GWEN_DIR_SEPARATOR_S);
145   GWEN_Text_UnescapeToBufferTolerant(uid, pbuf);
146   GWEN_Buffer_AppendString(pbuf, ".sec");
147 
148   sbuf=GWEN_Buffer_new(0, 256, 0, 1);
149   rv=readFile(GWEN_Buffer_GetStart(pbuf), sbuf);
150   if (rv<0) {
151     DBG_INFO(AQPAYPAL_LOGDOMAIN, "here (%d)", rv);
152     GWEN_Buffer_free(sbuf);
153     GWEN_Buffer_free(pbuf);
154     return rv;
155   }
156 
157   snprintf(text, sizeof(text)-1,
158            I18N("Please enter the password for \n"
159                 "Paypal user %s\n"
160                 "<html>"
161                 "Please enter the password for Paypal user <i>%s</i></br>"
162                 "</html>"),
163            uid, uid);
164   text[sizeof(text)-1]=0;
165 
166   tbuf=GWEN_Buffer_new(0, 256, 0, 1);
167   GWEN_Buffer_AppendString(tbuf, "PASSWORD_");
168   GWEN_Text_UnescapeToBufferTolerant(GWEN_Buffer_GetStart(pbuf), tbuf);
169 
170   rv=GWEN_Gui_GetPassword(0,
171                           GWEN_Buffer_GetStart(tbuf),
172                           I18N("Enter Password"),
173                           text,
174                           pw,
175                           4,
176                           sizeof(pw)-1,
177                           GWEN_Gui_PasswordMethod_Text, NULL,
178                           0);
179   if (rv<0) {
180     DBG_INFO(AQPAYPAL_LOGDOMAIN, "here (%d)", rv);
181     GWEN_Buffer_free(tbuf);
182     GWEN_Buffer_free(sbuf);
183     GWEN_Buffer_free(pbuf);
184     return rv;
185   }
186 
187   rv=GWEN_SmallTresor_Decrypt((const uint8_t *) GWEN_Buffer_GetStart(sbuf),
188                               GWEN_Buffer_GetUsedBytes(sbuf),
189                               pw,
190                               secbuf,
191                               AQPAYPAL_PASSWORD_ITERATIONS,
192                               AQPAYPAL_CRYPT_ITERATIONS);
193   /* overwrite password ASAP */
194   memset(pw, 0, sizeof(pw));
195   GWEN_Buffer_free(tbuf);
196   GWEN_Buffer_free(sbuf);
197   GWEN_Buffer_free(pbuf);
198   if (rv<0) {
199     DBG_INFO(AQPAYPAL_LOGDOMAIN, "here (%d)", rv);
200     return rv;
201   }
202 
203   return 0;
204 }
205 
206 
207 
APY_Provider_WriteUserApiSecrets(AB_PROVIDER * pro,const AB_USER * u,const char * sec)208 int APY_Provider_WriteUserApiSecrets(AB_PROVIDER *pro, const AB_USER *u, const char *sec)
209 {
210   APY_PROVIDER *xp;
211   int rv;
212   GWEN_BUFFER *pbuf;
213   GWEN_BUFFER *sbuf;
214   GWEN_BUFFER *tbuf;
215   const char *uid;
216   char text[512];
217   char pw[129];
218 
219   assert(pro);
220   xp=GWEN_INHERIT_GETDATA(AB_PROVIDER, APY_PROVIDER, pro);
221   assert(xp);
222 
223   uid=AB_User_GetUserId(u);
224   if (!(uid && *uid)) {
225     DBG_ERROR(AQPAYPAL_LOGDOMAIN, "No user id");
226     return GWEN_ERROR_INVALID;
227   }
228 
229   pbuf=GWEN_Buffer_new(0, 256, 0, 1);
230   rv=AB_Provider_GetUserDataDir(pro, pbuf);
231   if (rv<0) {
232     DBG_INFO(AQPAYPAL_LOGDOMAIN, "here (%d)", rv);
233     GWEN_Buffer_free(pbuf);
234     return rv;
235   }
236 
237   /* make sure the data dir exists */
238   DBG_INFO(0, "Looking for [%s]", GWEN_Buffer_GetStart(pbuf));
239   rv=GWEN_Directory_GetPath(GWEN_Buffer_GetStart(pbuf), 0);
240   if (rv<0) {
241     DBG_INFO(AQPAYPAL_LOGDOMAIN, "here (%d)", rv);
242     GWEN_Buffer_free(pbuf);
243     return rv;
244   }
245 
246   GWEN_Buffer_AppendString(pbuf, GWEN_DIR_SEPARATOR_S);
247   GWEN_Text_UnescapeToBufferTolerant(uid, pbuf);
248   GWEN_Buffer_AppendString(pbuf, ".sec");
249 
250   snprintf(text, sizeof(text)-1,
251            I18N("Please enter the password for \n"
252                 "Paypal user %s\n"
253                 "<html>"
254                 "Please enter the password for Paypal user <i>%s</i></br>"
255                 "</html>"),
256            uid, uid);
257   text[sizeof(text)-1]=0;
258 
259   tbuf=GWEN_Buffer_new(0, 256, 0, 1);
260   GWEN_Buffer_AppendString(tbuf, "PASSWORD_");
261   GWEN_Text_UnescapeToBufferTolerant(GWEN_Buffer_GetStart(pbuf), tbuf);
262 
263   rv=GWEN_Gui_GetPassword(GWEN_GUI_INPUT_FLAGS_CONFIRM,
264                           GWEN_Buffer_GetStart(tbuf),
265                           I18N("Enter Password"),
266                           text,
267                           pw,
268                           4,
269                           sizeof(pw)-1,
270                           GWEN_Gui_PasswordMethod_Text, NULL,
271                           0);
272   if (rv<0) {
273     DBG_INFO(AQPAYPAL_LOGDOMAIN, "here (%d)", rv);
274     GWEN_Buffer_free(tbuf);
275     GWEN_Buffer_free(pbuf);
276     return rv;
277   }
278   GWEN_Buffer_free(tbuf);
279 
280   sbuf=GWEN_Buffer_new(0, 256, 0, 1);
281   rv=GWEN_SmallTresor_Encrypt((const uint8_t *) sec,
282                               strlen(sec),
283                               pw,
284                               sbuf,
285                               AQPAYPAL_PASSWORD_ITERATIONS,
286                               AQPAYPAL_CRYPT_ITERATIONS);
287   /* overwrite password ASAP */
288   memset(pw, 0, sizeof(pw));
289   if (rv<0) {
290     DBG_INFO(AQPAYPAL_LOGDOMAIN, "here (%d)", rv);
291     GWEN_Buffer_free(sbuf);
292     GWEN_Buffer_free(pbuf);
293     return rv;
294   }
295 
296   /* write file */
297   rv=writeFile(GWEN_Buffer_GetStart(pbuf),
298                GWEN_Buffer_GetStart(sbuf),
299                GWEN_Buffer_GetUsedBytes(sbuf));
300   if (rv<0) {
301     DBG_INFO(AQPAYPAL_LOGDOMAIN, "here (%d)", rv);
302     GWEN_Buffer_free(sbuf);
303     GWEN_Buffer_free(pbuf);
304     return rv;
305   }
306 
307   GWEN_Buffer_free(sbuf);
308   GWEN_Buffer_free(pbuf);
309 
310   return 0;
311 }
312 
313