Project

General

Profile

aqbanking-change-keys.patch

thbe, 09/11/2019 06:57 PM

Download (53.7 KB)

View differences:

src/libs/plugins/backends/aqhbci/admjobs/Makefile.am
14 14
noinst_HEADERS=\
15 15
  jobgetkeys_l.h jobgetkeys_p.h \
16 16
  jobsendkeys_l.h jobsendkeys_p.h \
17
  jobchangekeys_l.h jobchangekeys_p.h \
17 18
  jobtan_l.h jobtan_p.h \
18 19
  jobgetsepainfo_l.h jobgetsepainfo_p.h \
19 20
  jobgetsysid_l.h jobgetsysid_p.h \
......
22 23
libhbciadmjobs_la_SOURCES=\
23 24
  jobgetkeys.c \
24 25
  jobsendkeys.c \
26
  jobchangekeys.c \
25 27
  jobtan.c \
26 28
  jobgetsepainfo.c \
27 29
  jobgetsysid.c \
......
40 42
xmlfiles=\
41 43
  $(srcdir)/jobgetkeys.xml \
42 44
  $(srcdir)/jobsendkeys.xml \
45
  $(srcdir)/jobchangekeys.xml \
43 46
  $(srcdir)/jobtan.xml \
44 47
  $(srcdir)/jobgetsepainfo.xml \
45 48
  $(srcdir)/jobgetsysid.xml \
src/libs/plugins/backends/aqhbci/admjobs/jobchangekeys.c
1
/***************************************************************************
2

  
3
 ***************************************************************************
4
 *          Please see toplevel file COPYING for license details           *
5
 ***************************************************************************/
6

  
7

  
8
#ifdef HAVE_CONFIG_H
9
# include <config.h>
10
#endif
11

  
12

  
13
#include "jobchangekeys_p.h"
14
#include "../banking/user_l.h"
15
#include "../banking/provider_l.h"
16
#include <gwenhywfar/ctplugin.h>
17
#include <gwenhywfar/ctfile_be.h>
18

  
19
#include <stdarg.h>
20
#include <unistd.h>
21

  
22

  
23
/*
24
  Mögliche Wechsel:
25

  
26
  medium			type	mode
27

  
28
  datei				RDH		1		karte o. cert	RAH	9
29
  datei				RDH		1		datei			RAH	10
30
  karte o. cert		RDH		1		karte o. cert	RAH	9
31
  datei				RDH		2		karte o. cert	RAH	9
32
  datei				RDH		2		datei			RAH	10
33
  karte o. cert		RDH		5		karte o. cert	RAH	9
34

  
35
  ohne Schlüsselwechsel:
36
  karte o. cert		RDH		9		karte o. cert	RAH	9
37
  datei				RDH		10		karte o. cert	RAH	9
38
  datei				RDH		10		datei			RAH	10
39
*/
40

  
41

  
42
GWEN_INHERIT(AH_JOB, AH_JOB_CHANGEKEYS)
43

  
44
const char *fmtStr(char *buff, size_t buffLen, const char *fmt, ...)  __attribute__ ((format (printf, 3, 4)));
45
const char *fmtStr(char *buff, size_t buffLen, const char *fmt, ...)
46
{
47
	va_list args;
48
	va_start(args, fmt);
49
	vsnprintf(buff, buffLen - 1, fmt, args);
50
	buff[buffLen - 1] = 0;
51
	va_end(args);
52
	return buff;
53
}
54

  
55
#define FB fmtBuff, sizeof(fmtBuff)
56

  
57
int onError(const char *m, int rv)
58
{
59
	DBG_ERROR(AQHBCI_LOGDOMAIN, "%s", m);
60
	GWEN_Gui_MessageBox(GWEN_GUI_MSG_FLAGS_TYPE_ERROR,
61
				I18N("Change keys: error"), I18N(m), I18N("OK"), NULL, NULL, 0);
62
	return rv;
63
}
64

  
65

  
66
struct AH_JOB_CHANGEKEYS
67
{
68
	uint16_t flags;
69
	uint8_t *canceled;
70
	AB_PROVIDER *pro;
71
	AB_USER *u;
72
	AB_USER *uTmp;
73
	const char *fm;
74
	char *tt, *tn;
75
	uint32_t kvVCurr, kvSCurr, kvACurr;
76
	GWEN_CRYPT_TOKEN *ct;
77
	const GWEN_CRYPT_TOKEN_CONTEXT *ctx;
78
	int tokenCtxId;
79
	const GWEN_CRYPT_TOKEN_KEYINFO *kiV, *kiS, *kiA;
80
	int8_t resp;
81
	GWEN_BUFFER *emsg;
82
};
83

  
84
const char *strUpper(char *s)
85
{
86
	size_t l = strlen(s);
87
	for(size_t i = 0; i < l; i++)
88
	{
89
		if((s[i] >= 'a') && (s[i] <= 'z'))
90
			s[i] -= 0x20;
91

  
92
	}
93
	return s;
94
}
95

  
96
int8_t getKeyInfo(AH_HBCI *h, const char *tt, const char *tn, uint32_t cid, GWEN_CRYPT_TOKEN **ct, const GWEN_CRYPT_TOKEN_CONTEXT **ctx,
97
				  const GWEN_CRYPT_TOKEN_KEYINFO **kiV, const GWEN_CRYPT_TOKEN_KEYINFO **kiS, const GWEN_CRYPT_TOKEN_KEYINFO **kiA)
98
{
99
	int8_t res = 0;
100
	uint32_t f = GWEN_CRYPT_TOKEN_KEYFLAGS_HASMODULUS | GWEN_CRYPT_TOKEN_KEYFLAGS_HASEXPONENT |
101
							GWEN_CRYPT_TOKEN_KEYFLAGS_HASKEYVERSION | GWEN_CRYPT_TOKEN_KEYFLAGS_HASKEYNUMBER;
102
	if(!*ct && (((AB_Banking_GetCryptToken(AH_HBCI_GetBankingApi(h), tt, tn, ct) < 0)) || !*ct))
103
	{
104
		DBG_ERROR(AQHBCI_LOGDOMAIN, "AB_Banking_GetCryptToken() failed (tt '%s', tn '%s').", tt, tn);
105
		return -1;
106
	}
107
	if(GWEN_Crypt_Token_Open(*ct, 0, 0) < 0)
108
	{
109
		DBG_ERROR(AQHBCI_LOGDOMAIN, "GWEN_Crypt_Token_Open() failed.");
110
		return -1;
111
	}
112
	*ctx = GWEN_Crypt_Token_GetContext(*ct, cid, 0);
113
	if(!*ctx)
114
	{
115
		DBG_ERROR(AQHBCI_LOGDOMAIN, "GWEN_Crypt_Token_GetContext() failed (cid %ld).", (long)cid);
116
		return -1;
117
	}
118
	for(uint8_t i = 0; i < 3; i++)
119
	{
120
		uint32_t kid = 0;
121
		const GWEN_CRYPT_TOKEN_KEYINFO **ki = NULL;
122
		char kl = '?';
123
		switch(i)
124
		{
125
		case 0: kid = GWEN_Crypt_Token_Context_GetDecipherKeyId(*ctx); ki = kiV, kl = 'V'; break;
126
		case 1: kid = GWEN_Crypt_Token_Context_GetSignKeyId(*ctx); ki = kiS; kl = 'S'; break;
127
		case 2: kid = GWEN_Crypt_Token_Context_GetAuthSignKeyId(*ctx); ki = kiA; kl = 'D'; break;
128
		}
129
		if((kl == 'D') && !strcmp(tt, "ddvcard"))
130
			continue;
131
		if((*ki = GWEN_Crypt_Token_GetKeyInfo(*ct, kid, f, 0)) == NULL)
132
		{
133
			DBG_ERROR(AQHBCI_LOGDOMAIN, "GWEN_Crypt_Token_GetKeyInfo() (%c) failed.", kl);
134
			res = -1;
135
			break;
136
		}
137
	}
138
	return res;
139
}
140

  
141
int8_t tokenHasKeys(GWEN_CRYPT_TOKEN *ct, const GWEN_CRYPT_TOKEN_CONTEXT *ctx)
142
{
143
	int8_t res = 2;
144
	for(uint8_t i = 0; (res > 0) && (i < 2); i++)
145
	{
146
		const GWEN_CRYPT_TOKEN_KEYINFO *ki = NULL;
147
		int kn = 0, kv = 0;
148
		uint32_t flags = 0;
149
		uint32_t id = (i == 0) ? GWEN_Crypt_Token_Context_GetDecipherKeyId(ctx) : GWEN_Crypt_Token_Context_GetVerifyKeyId(ctx);
150
		if(res == 2)
151
			res = 1;
152
		if(!id)
153
			res = -1;
154
		else
155
			ki = GWEN_Crypt_Token_GetKeyInfo(ct, id, 0, 0);
156
		if(!ki)
157
			res = -1;
158
		else
159
		{
160
			kn = GWEN_Crypt_Token_KeyInfo_GetKeyNumber(ki);
161
			kv = GWEN_Crypt_Token_KeyInfo_GetKeyVersion(ki);
162
			flags = GWEN_Crypt_Token_KeyInfo_GetFlags(ki);
163
		}
164
		if((res >= 0) && (!kn || !kv || !(flags & GWEN_CRYPT_TOKEN_KEYFLAGS_HASMODULUS) || !(flags & GWEN_CRYPT_TOKEN_KEYFLAGS_HASEXPONENT)))
165
			res = 0;
166
		DBG_NOTICE(AQHBCI_LOGDOMAIN, "%s(): id %ld %d %d m %d e %d -> %d.", __FUNCTION__, (long)id, kn, kv,
167
				   (flags & GWEN_CRYPT_TOKEN_KEYFLAGS_HASMODULUS) != 0, (flags & GWEN_CRYPT_TOKEN_KEYFLAGS_HASEXPONENT) != 0, res);
168
	}
169
	return (res == 1) ? 1 : 0;
170
}
171

  
172
#if 1
173
int8_t setKeyVersion(GWEN_CRYPT_TOKEN *ct, const GWEN_CRYPT_TOKEN_CONTEXT *ctx, const GWEN_CRYPT_TOKEN_KEYINFO *ki, char t, uint32_t kv)
174
{
175
	int8_t ret = 0;
176
	GWEN_CRYPT_TOKEN_KEYINFO *kin = NULL;
177
	uint32_t kid = 0;
178

  
179
	switch(t)
180
	{
181
	case 'V': kid = GWEN_Crypt_Token_Context_GetDecipherKeyId(ctx); break;
182
	case 'S': kid = GWEN_Crypt_Token_Context_GetSignKeyId(ctx); break;
183
	case 'A': kid = GWEN_Crypt_Token_Context_GetAuthSignKeyId(ctx); break;
184
	default:
185
		DBG_ERROR(AQHBCI_LOGDOMAIN, "type %c invalid.", t);
186
		return -1;
187
	}
188

  
189
	kin = GWEN_Crypt_Token_KeyInfo_dup(ki);
190

  
191
	if(kv > 999)
192
		kv = 1;
193
	DBG_NOTICE(AQHBCI_LOGDOMAIN, "%s(): key %ld '%c' set version %ld.", __FUNCTION__, (long)kid, t, (long)kv);
194
	GWEN_Crypt_Token_KeyInfo_SetKeyVersion(kin, kv);
195
	if(GWEN_Crypt_Token_SetKeyInfo(ct, kid, kin, 0))
196
	{
197
		DBG_ERROR(AQHBCI_LOGDOMAIN, "%s(): GWEN_Crypt_Token_SetKeyInfo() failed.", __FUNCTION__);
198
		ret = -1;
199
	}
200
	GWEN_Crypt_Token_KeyInfo_free(kin);
201
	if(ret)
202
		return ret;
203
	if((ret == 0) && (ki = GWEN_Crypt_Token_GetKeyInfo(ct, kid, 0, 0)) == NULL)
204
	{
205
		DBG_ERROR(AQHBCI_LOGDOMAIN, "%s(): GWEN_Crypt_Token_GetKeyInfo() (%c) failed.", __FUNCTION__, t);
206
		ret = -1;
207
	}
208
	if(ret)
209
		return ret;
210
	DBG_NOTICE(AQHBCI_LOGDOMAIN, "%s(): key '%c' version now %d.", __FUNCTION__, t, GWEN_Crypt_Token_KeyInfo_GetKeyVersion(ki));
211
	return 0;
212
}
213
#endif
214

  
215
#define FJCK_CHMEDIA		1
216
#define FJCK_CHKEY			2
217
#define FJCK_CHPROFILE		4
218
#define FJCK_SRCFILE		8
219
#define FJCK_DSTFILE		16
220
#define FJCK_DSTFILE_EXISTS	32
221

  
222
void GWENHYWFAR_CB GWENHYWFAR_CB AH_Job_ChangeKeys_FreeData(void *bp, void *p);
223
int AH_Job_ChangeKeys_NextMsg(AH_JOB *j);
224

  
225
AH_JOB *AH_Job_ChangeKeys_new(AB_PROVIDER *pro, AB_USER *u, GWEN_DB_NODE *args, uint8_t *canceled)
226
{
227
	int res = 0;
228
	char fmtBuff[256];
229
	AH_JOB *j = NULL;
230
	AH_JOB_CHANGEKEYS *jd = NULL;
231
	AB_USER *uTmp = NULL;
232
	AH_HBCI *h = AH_Provider_GetHbci(pro);
233
	uint16_t flags = FJCK_CHKEY | FJCK_CHMEDIA | FJCK_CHPROFILE;
234
	AH_CRYPT_MODE cryptModeNew = AH_CryptMode_None;
235
	int cryptTypeNew = -1;
236
	int tokenCtxIdNew = -1;
237
	const char *tt = NULL;
238
	const char *tn = NULL;
239
	char *ttn = NULL, *tnn = NULL;
240
	const char *scmn = NULL;
241
	GWEN_CRYPT_TOKEN *ct = NULL, *ctNew = NULL;
242
	const GWEN_CRYPT_TOKEN_CONTEXT *ctx = NULL, *ctxNew = NULL;
243
	const GWEN_CRYPT_TOKEN_KEYINFO *kiV = NULL, *kiS = NULL, *kiA = NULL, *kiVNew = NULL, *kiSNew = NULL, *kiANew = NULL;
244
	GWEN_PLUGIN *plg = NULL;
245
	GWEN_PLUGIN_MANAGER *pm = GWEN_PluginManager_FindPluginManager(GWEN_CRYPT_TOKEN_PLUGIN_TYPENAME);
246
	const char *cmn = "?", *fm = "?", *fmn = "?";
247

  
248
	assert(h);
249

  
250
	//GWEN_DB_Dump(args, 0);
251
	ttn = strdup(GWEN_DB_GetCharValue(args, "tokenType", 0, ""));
252
	tnn = strdup(GWEN_DB_GetCharValue(args, "tokenName", 0, ""));
253
	scmn = GWEN_DB_GetCharValue(args, "cryptMode", 0, "");
254
	cryptTypeNew = GWEN_DB_GetIntValue(args, "cryptType", 0, -1);
255
	tokenCtxIdNew = GWEN_DB_GetIntValue(args, "context", 0, -1);
256

  
257
	if(scmn && *scmn)
258
	{
259
		if(!strcasecmp(scmn, "RDH"))
260
			cryptModeNew = AH_CryptMode_Rdh;
261
		else if(!strcasecmp(scmn, "RAH"))
262
			cryptModeNew = AH_CryptMode_Rah;
263
	}
264

  
265
	tt = AH_User_GetTokenType(u);
266
	tn = AH_User_GetTokenName(u);
267
	if(!strcasecmp(tt, "ohbci"))
268
		flags |= FJCK_SRCFILE;
269
	if(!*ttn)
270
	{
271
		free(ttn);
272
		ttn = NULL;
273
		if(*tnn && !strchr(tnn, '/') && !strchr(tnn, '\\')) // assume thats a card number
274
		{
275
			size_t l = strlen(tnn);
276
			size_t i = 0;
277
			for(; i < l; i++)
278
			{
279
				if((tnn[i] < '0') || (tnn[i] > '9'))
280
					break;
281
			}
282
			if(i == l)
283
			{
284
				ttn = strdup("card");
285
				if(l < 10)
286
				{
287
					char *tmp = strdup("0000000000");
288
					for(i = 0; i < l; i++)
289
						tmp[9 - i] = tnn[(l - 1) - i];
290
					free(tnn);
291
					tnn = tmp;
292
				}
293
			}
294
		}
295
	}
296
	if(ttn && !*ttn)
297
	{
298
		free(ttn);
299
		ttn = NULL;
300
	}
301
	if(!ttn)
302
		ttn = strdup(tt);
303
	if(!strcasecmp(ttn, "file") || !strcasecmp(ttn, "ohbci"))
304
	{
305
		flags |= FJCK_DSTFILE;
306
		free(ttn);
307
		ttn = strdup("ohbci");
308
	}
309
	else if(!strstr(ttn, "card"))
310
		res = onError(fmtStr(FB, "Ungültiger token-typ '%s'.", ttn), -1);
311
	if(!*tnn)
312
	{
313
		free(tnn);
314
		tnn = strdup(tn);
315
		if(!strcasecmp(tt, "ohbci"))
316
			flags |= FJCK_DSTFILE;
317
	}
318

  
319
	if(res == 0)
320
	{
321
		if(!access(tnn, F_OK))
322
			flags |= FJCK_DSTFILE_EXISTS;
323

  
324
		if(!strcasecmp(tt, ttn) && !strcmp(tn, tnn))
325
		{
326
			if(cryptModeNew == AH_CryptMode_None)
327
				cryptModeNew = AH_User_GetCryptMode(u);
328
			if(cryptTypeNew < 0)
329
				cryptTypeNew = AH_User_GetRdhType(u);
330
		}
331
		if(cryptModeNew == AH_CryptMode_None)
332
			res = onError("Crypt-mode muss angegeben werden.", -1);
333
		if((res == 0) && (cryptTypeNew < 0))
334
			res = onError("Crypt-typ muss angegeben werden.", -1);
335
	}
336

  
337
	if(tokenCtxIdNew < 0)
338
		tokenCtxIdNew = 1;
339

  
340
	fm = (flags & FJCK_SRCFILE) ? "Schlüsseldatei" : "Chipkarte";
341
	fmn = (flags & FJCK_DSTFILE) ? "Schlüsseldatei" : "Chipkarte";
342

  
343
	DBG_INFO(AQHBCI_LOGDOMAIN, "'%s' '%s' -> '%s' '%s', file %d exists %d'.", tt, tn, ttn, tnn, (flags & FJCK_DSTFILE) != 0, (flags & FJCK_DSTFILE_EXISTS) != 0);
344

  
345
	if(res == 0)
346
	{
347
		if((((flags & FJCK_SRCFILE) != 1) == ((flags & FJCK_DSTFILE) != 1)) && !strcmp(tn, tnn))
348
			res = onError("Schlüsseländerung ohne Medienänderung z.Zt. nicht unterstützt.", -1);
349
	}
350

  
351
	if(res == 0)
352
	{
353
		switch(cryptModeNew)
354
		{
355
		case AH_CryptMode_Rah: cmn = "RAH"; break;
356
		case AH_CryptMode_Rdh: cmn = "RDH"; break;
357
		default:
358
			cmn = "unknown";
359
		}
360
		if(!strcasecmp(tt, ttn) && !strcmp(tn, tnn))
361
			flags &= ~FJCK_CHMEDIA;
362
		if((AH_User_GetCryptMode(u) == cryptModeNew) && (AH_User_GetRdhType(u) == cryptTypeNew))
363
			flags &= ~FJCK_CHPROFILE;
364
		DBG_INFO(AQHBCI_LOGDOMAIN, "'%s %d' -> '%s' '%s' '%s %d', change: m %d, k %d, p %d.", AH_CryptMode_toString(AH_User_GetCryptMode(u)), AH_User_GetRdhType(u),
365
				ttn, tnn, AH_CryptMode_toString(cryptModeNew), cryptTypeNew, (flags & FJCK_CHMEDIA) != 0, (flags & FJCK_CHKEY) != 0, (flags & FJCK_CHPROFILE) != 0);
366
		if(flags & FJCK_CHPROFILE)
367
		{
368
			res = -1;
369
			switch(AH_User_GetCryptMode(u))
370
			{
371
			case AH_CryptMode_Rdh:
372
				switch(cryptModeNew)
373
				{
374
				case AH_CryptMode_Rdh:
375
					onError("Änderung des Schlüsselsprofils nach RDH nicht unterstützt.", -1);
376
					break;
377
				default:
378
					if(!(flags & FJCK_SRCFILE) && !(flags & FJCK_DSTFILE) && (AH_User_GetRdhType(u) == 9) && (cryptTypeNew == 9))
379
						res = 1;
380
					else if((flags & FJCK_SRCFILE) && !(flags & FJCK_DSTFILE) && (AH_User_GetRdhType(u) == 10) && (cryptTypeNew == 9))
381
						res = 1;
382
					else if((flags & FJCK_SRCFILE) && (flags & FJCK_DSTFILE) && (AH_User_GetRdhType(u) == 10) && (cryptTypeNew == 10))
383
						res = 1;
384
					if(res == 1)
385
					{
386
						flags &= ~FJCK_CHKEY;
387
						res = 0;
388
					}
389
					else
390
					{
391
						if(flags & FJCK_SRCFILE)
392
						{
393
							switch(AH_User_GetRdhType(u))
394
							{
395
							case 1:
396
							case 2:
397
								if(!(flags & FJCK_DSTFILE) && (cryptTypeNew == 9))
398
									res = 0;
399
								if((flags & FJCK_DSTFILE) && (cryptTypeNew == 10))
400
									res = 0;
401
								break;
402
							default:;
403
							}
404
						}
405
						else
406
						{
407
							switch(AH_User_GetRdhType(u))
408
							{
409
							case 1:
410
							case 5:
411
								if(!(flags & FJCK_DSTFILE) && (cryptTypeNew == 9))
412
									res = 0;
413
								break;
414
							default:;
415
							}
416
						}
417
						if(res)
418
							onError(fmtStr(FB, "Änderung des Schlüsselsprofils von %s RDH-%d nach %s RAH-%d nicht unterstützt.",
419
								   fm, AH_User_GetRdhType(u), fmn, cryptTypeNew), -1);
420
					}
421
				}
422
				break;
423
			default:
424
				onError("Änderung des Sicherheitsprofils nur von RDH aus unterstützt.", -1);
425
			}
426
		}
427
		if(res)
428
			*canceled = 2;
429
	}
430

  
431
	if(res == 0)
432
	{
433
		// keyinfo current token
434
		if(getKeyInfo(h, AH_User_GetTokenType(u), AH_User_GetTokenName(u), AH_User_GetTokenContextId(u), &ct, &ctx, &kiV, &kiS, &kiA)
435
				|| !ct || !ctx || !kiV || !kiS || !kiA)
436
		{
437
			DBG_INFO(AQHBCI_LOGDOMAIN, "getKeyInfo() ct %p, ctx %p, ki %p %p %p.", ct, ctx, kiV, kiS, kiA);
438
			if(!ct || !ctx)
439
				res = onError("Could not get token.", -1);
440
			else
441
				res = onError("Sicherheitsmedium für diesen Vorgang nicht geeignet.", -1);
442
		}
443
	}
444

  
445
	if((res == 0) && (flags & FJCK_CHMEDIA))
446
	{
447
		char *tokenNew = NULL;
448
		if(!strcmp(ttn, "card"))
449
		{
450
			GWEN_BUFFER *ctn = GWEN_Buffer_new(0, 64, 0, 1);
451
			GWEN_BUFFER *cmn = GWEN_Buffer_new(0, 64, 0, 1);
452
			for(; res == 0;)
453
			{
454
				res = AB_Banking_CheckCryptToken(AB_Provider_GetBanking(pro), GWEN_Crypt_Token_Device_Card, ctn, cmn);
455
				DBG_INFO(AQHBCI_LOGDOMAIN, "card: '%s' '%s'.", GWEN_Buffer_GetStart(ctn), GWEN_Buffer_GetStart(cmn));
456
				if(res)
457
					res = onError("AB_Banking_CheckCryptToken() failed.", -1);
458
				else
459
				{
460
					if(tokenNew)
461
						free(tokenNew);
462
					tokenNew = strdup(GWEN_Buffer_GetStart(ctn));
463
					if(!strcmp(tnn, GWEN_Buffer_GetStart(cmn)))
464
						break;
465
					if(GWEN_Gui_MessageBox(GWEN_GUI_MSG_FLAGS_TYPE_INFO, I18N("Change keys: insert card"),
466
								fmtStr(FB, "Chipkarte '%s' wird benötigt.", tnn), I18N("Abort"), I18N("OK"), NULL, 0) != 2)
467
						res = -2;
468
				}
469
			}
470
			GWEN_Buffer_free(ctn);
471
			GWEN_Buffer_free(cmn);
472
			if(tokenNew)
473
			{
474
				free(ttn);
475
				ttn = tokenNew;
476
				tokenNew = NULL;
477
			}
478
		}
479

  
480
		if(tokenNew)
481
			free(tokenNew);
482

  
483
		if(res == 0)
484
			plg = GWEN_PluginManager_GetPlugin(pm, ttn);
485
		if(!plg && (res == 0))
486
			res = onError(fmtStr(FB, "Could not get plugin for new tokentype '%s'.", ttn), -1);
487
		if(plg && (flags & FJCK_DSTFILE))
488
		{
489
			// diff. context?
490
			if((flags & FJCK_SRCFILE) && !strcmp(tn, tnn))
491
				res = onError(fmtStr(FB, "Die alte und neue Schlüsseldatei darf nicht identisch sein."), -1);
492
			else
493
			{
494
				uint8_t del = 1;
495
				tokenCtxIdNew = 1;
496
				if(flags & FJCK_DSTFILE_EXISTS)
497
				{
498
					del = 0;
499
					res = GWEN_Gui_MessageBox(GWEN_GUI_MSG_FLAGS_TYPE_INFO, I18N("Change keys: confirm"),
500
								fmtStr(FB, "Die Schlüsseldatei '%s' existiert bereits.", tnn), I18N("Abort"), I18N("Use"), I18N("Delete"), 0);
501
					if(res == 1)
502
						res = -1;
503
					else if(res == 2) // use
504
					{
505
						res = 0;
506
						//flags &= ~FJCK_CHKEY;
507
						if(getKeyInfo(h, ttn, tnn, tokenCtxIdNew, &ctNew, &ctxNew, &kiVNew, &kiSNew, &kiANew)
508
								|| !ctNew || !ctxNew || !kiVNew || !kiSNew || !kiANew)
509
							res = onError("Could not get token for new keyfile.", -1);
510
					}
511
					else if(GWEN_Gui_MessageBox(GWEN_GUI_MSG_FLAGS_TYPE_INFO, I18N("Change keys: confirm"),
512
										fmtStr(FB, "Schlüsseldatei '%s' wirklich löschen?", tnn), I18N("Abort"), I18N("Delete"), NULL, 0) != 2)
513
						res = -1;
514
					else
515
					{
516
						res = 0;
517
						del = 1;
518
					}
519
					if(res)
520
					{
521
						res = onError("Canceled.", -1);
522
						*canceled = 1;
523
					}
524
					else if(del)
525
						unlink(tnn);
526
				}
527
				if((res == 0) && del)
528
				{
529
					if(GWEN_Gui_MessageBox(GWEN_GUI_MSG_FLAGS_TYPE_INFO, I18N("Change keys: confirm"),
530
									fmtStr(FB, "Schlüsseldatei '%s' wird erzeugt.", tnn), I18N("Abort"), I18N("OK"), NULL, 0) != 2)
531
					{
532
						res = onError("Canceled.", -1);
533
						*canceled = 1;
534
					}
535
					if(res == 0)
536
					{
537
						ctNew = GWEN_Crypt_Token_Plugin_CreateToken(plg, tnn);
538
						if(!ctNew)
539
							res = onError(fmtStr(FB, "Could not create crypt token '%s'.", tnn), -1);
540
						else if(GWEN_Crypt_Token_Create(ctNew, 0) < 0)
541
							res = onError(fmtStr(FB, "Could not create keyfile '%s'.", GWEN_Crypt_Token_GetTokenName(ctNew)), -1);
542
						else if(GWEN_Crypt_Token_Close(ctNew, 0, 0))
543
							res = onError("Could not close token.", -1);
544
					}
545
				}
546
			}
547
		}
548
		// keyinfo dest. token
549
		if(res == 0)
550
		{
551
			if(getKeyInfo(h, ttn, tnn, tokenCtxIdNew, &ctNew, &ctxNew, &kiVNew, &kiSNew, &kiANew)
552
					|| !ctNew || !ctxNew || !kiVNew || !kiSNew || !kiANew)
553
			{
554
				DBG_NOTICE(AQHBCI_LOGDOMAIN, "getKeyInfo() ct %p, ctx %p, ki %p %p %p.", ct, ctx, kiV, kiS, kiA);
555
				if(!ct || !ctx)
556
					res = onError("Could not get token.", -1);
557
				else
558
					res = onError("Sicherheitsmedium für diesen Vorgang nicht geeignet.", -1);
559
			}
560
		}
561
		if((res == 0) && !(flags & FJCK_DSTFILE))
562
		{
563
			int tnV = GWEN_Crypt_Token_KeyInfo_GetKeyNumber(kiVNew);
564
			int tnS = GWEN_Crypt_Token_KeyInfo_GetKeyNumber(kiSNew);
565
			if((cryptTypeNew != tnV) || (cryptTypeNew != tnS))
566
			{
567
				DBG_ERROR(AQHBCI_LOGDOMAIN, "rdh-type %d, card %d/%d..", cryptTypeNew, tnV, tnS);
568
				res = onError("Ziel-Sicherheitsmedium für diesen Vorgang nicht geeignet.", -1);
569
			}
570
		}
571
	}
572
#if 1
573
	if(res == 0)
574
	{
575
		// how get key-pair from token?
576
		if(!(flags & FJCK_CHKEY) && (flags & FJCK_CHMEDIA))
577
			res = onError("Sicherheitsprofilwechsel ohne Sicherheitsmedienwechsel nicht implementiert.", -1);
578
	}
579
#endif
580
	if(res == 0)
581
	{
582
		if(flags & FJCK_CHMEDIA)
583
		{
584
			char *cm = strdup(AH_CryptMode_toString(AH_User_GetCryptMode(u)));
585
			const char *m = fmtStr(FB, "Wechsel des Sicherheitsmediums von\n    %s '%s', %s-%d\nnach\n    %s '%s', %s-%d\ndurchführen?",
586
							   fm, tn, strUpper(cm), AH_User_GetRdhType(u), fmn, tnn, cmn, cryptTypeNew);
587
			free(cm);
588
			if(GWEN_Gui_MessageBox(GWEN_GUI_MSG_FLAGS_TYPE_INFO, I18N("Change keys: confirm"),
589
																m, I18N("Abort"), I18N("OK"), NULL, 0) != 2)
590
			{
591
				res = -1;
592
				*canceled = 1;
593
			}
594
		}
595
	}
596

  
597
	if(res == 0)
598
	{
599
		uTmp = AB_Provider_CreateUserObject(pro);
600
		AH_User_SetCryptMode(uTmp, cryptModeNew);
601
		AH_User_SetRdhType(uTmp, cryptTypeNew);
602
		AH_User_SetTokenType(uTmp, ttn);
603
		AH_User_SetTokenName(uTmp, tnn);
604
		AH_User_SetTokenContextId(uTmp, tokenCtxIdNew);
605
		AB_User_SetBankCode(uTmp, AB_User_GetBankCode(u));
606
		AH_User_SetHbciVersion(uTmp, AH_User_GetHbciVersion(u));
607
		AH_User_SetServerUrl(uTmp, AH_User_GetServerUrl(u));
608

  
609
		DBG_NOTICE(AQHBCI_LOGDOMAIN, "chng k %d p %d m %d, token: open %d ctx %d knr dst %d %d %d.",
610
				   (flags & FJCK_CHKEY) != 0, (flags & FJCK_CHPROFILE) != 0, (flags & FJCK_CHMEDIA) != 0, GWEN_Crypt_Token_IsOpen(ctNew), tokenCtxIdNew,
611
				 kiVNew ? GWEN_Crypt_Token_KeyInfo_GetKeyNumber(kiVNew) : - 1, kiSNew ? GWEN_Crypt_Token_KeyInfo_GetKeyNumber(kiSNew) : -1, kiANew ? GWEN_Crypt_Token_KeyInfo_GetKeyNumber(kiANew) : -1);
612
	}
613

  
614
	if(res == 0)
615
	{
616
		j = AH_Job_new((flags & FJCK_DSTFILE) ? "JobChangeKeys" : "JobChangeKeysA", pro, u, NULL, 0);
617
		DBG_INFO(AQHBCI_LOGDOMAIN, "%s(): j %p u %p '%s'.", __FUNCTION__, j, u, j ? AH_Job_GetCode(j) : "-");
618
		if(!j)
619
			res = onError("AH_Job_new() failed.", -1);
620
	}
621

  
622
	if(res == 0)
623
	{
624
		GWEN_NEW_OBJECT(AH_JOB_CHANGEKEYS, jd);
625
		GWEN_INHERIT_SETDATA(AH_JOB, AH_JOB_CHANGEKEYS, j, jd, AH_Job_ChangeKeys_FreeData);
626

  
627
		AH_Job_SetNextMsgFn(j, AH_Job_ChangeKeys_NextMsg);
628

  
629
		args = AH_Job_GetArguments(j);
630
		assert(args);
631
	}
632

  
633
	if(res == 0)
634
	{
635
		char *cm = strdup(AH_CryptMode_toString(cryptModeNew));
636
		strUpper(cm);
637
		for(uint8_t i = 0; i < 3; i++)
638
		{
639
			const char *kt = "?";
640
			GWEN_DB_NODE *db = NULL;
641

  
642
			if(i < 2)
643
			{
644
				switch(i)
645
				{
646
				case 0: kt = "V"; db = GWEN_DB_GetGroup(args, GWEN_DB_FLAGS_DEFAULT, "getcryptKey"); break;
647
				case 1: kt = "S"; db = GWEN_DB_GetGroup(args, GWEN_DB_FLAGS_DEFAULT, "getsignKey"); break;
648
				}
649

  
650
				// HKISA
651
				GWEN_DB_SetCharValue(db, GWEN_DB_FLAGS_OVERWRITE_VARS, "secProfile/code", cm);
652
				GWEN_DB_SetIntValue(db, GWEN_DB_FLAGS_OVERWRITE_VARS, "secProfile/version", cryptTypeNew);
653

  
654
				GWEN_DB_SetCharValue(db, GWEN_DB_FLAGS_OVERWRITE_VARS, "key/userid", AH_User_GetPeerId(u));
655
				GWEN_DB_SetCharValue(db, GWEN_DB_FLAGS_OVERWRITE_VARS, "key/keyType", kt);
656
				GWEN_DB_SetIntValue(db, GWEN_DB_FLAGS_OVERWRITE_VARS, "key/keynum", 999);
657
				GWEN_DB_SetIntValue(db, GWEN_DB_FLAGS_OVERWRITE_VARS, "key/keyversion", 999);
658
			}
659

  
660
			switch(i)
661
			{
662
			case 0: kt = "V"; db = GWEN_DB_GetGroup(args, GWEN_DB_FLAGS_DEFAULT, "setcryptKey"); break;
663
			case 1: kt = "S"; db = GWEN_DB_GetGroup(args, GWEN_DB_FLAGS_DEFAULT, "setsignKey"); break;
664
			case 2: kt = "D"; db = GWEN_DB_GetGroup(args, GWEN_DB_FLAGS_DEFAULT, "setauthKey"); break;
665
			}
666
			// HKSAK
667
			GWEN_DB_SetCharValue(db, GWEN_DB_FLAGS_OVERWRITE_VARS, "secProfile/code", cm);
668
			GWEN_DB_SetIntValue(db, GWEN_DB_FLAGS_OVERWRITE_VARS, "secProfile/version", cryptTypeNew);
669
			GWEN_DB_SetCharValue(db, GWEN_DB_FLAGS_OVERWRITE_VARS, "key/userid", AH_User_GetPeerId(u));
670
			GWEN_DB_SetCharValue(db, GWEN_DB_FLAGS_OVERWRITE_VARS, "key/keyType", kt);
671
			GWEN_DB_SetCharValue(db, GWEN_DB_FLAGS_OVERWRITE_VARS, "keyName/keyType", kt);
672
			GWEN_DB_SetCharValue(db, GWEN_DB_FLAGS_OVERWRITE_VARS, "keyName/userid", AH_User_GetPeerId(u));
673
		}
674
		free(cm);
675
	}
676
	if(res)
677
	{
678
		if(j)
679
			AH_Job_free(j);
680
		j = NULL;
681
		if(res == -2)
682
			*canceled = 2;
683
	}
684

  
685
	if(jd)
686
	{
687
		jd->flags = flags;
688
		jd->canceled = canceled;
689
		jd->pro = pro;
690
		jd->u = u;
691
		jd->uTmp = uTmp;
692
		jd->fm = fmn;
693
		jd->tt = ttn;
694
		jd->tn = tnn;
695
		jd->kvVCurr = kiV ? GWEN_Crypt_Token_KeyInfo_GetKeyVersion(kiV) : 0;
696
		jd->kvSCurr = kiS ? GWEN_Crypt_Token_KeyInfo_GetKeyVersion(kiS) : 0;
697
		jd->kvACurr = kiA ? GWEN_Crypt_Token_KeyInfo_GetKeyVersion(kiA) : 0;
698
		jd->ct = ctNew;
699
		jd->ctx = ctxNew;
700
		jd->tokenCtxId = tokenCtxIdNew;
701
		jd->kiV = kiVNew;
702
		jd->kiS = kiSNew;
703
		jd->kiA = kiANew;
704
		jd->resp = -1;
705
		jd->emsg = NULL;
706
	}
707

  
708
	if(ctNew)
709
		GWEN_Crypt_Token_Close(ctNew, 0, 0);
710
	if(ct)
711
		GWEN_Crypt_Token_Close(ct, 0, 0);
712

  
713
	return j;
714
}
715

  
716
int onServerKeysImported(AH_JOB_CHANGEKEYS *jd)
717
{
718
	// serverkeys imported (knowing server-keys length is necessary for some key-types when created)
719
	// create keys if required
720

  
721
	char fmtBuff[256];
722
	AH_HBCI *h = AH_Provider_GetHbci(jd->pro);
723
	int res = 0;
724
	const char *m = NULL;
725
	const char *btn1 = NULL, *btn2 = NULL, *btn3 = NULL;
726
	uint8_t ok = 0;
727

  
728
	DBG_NOTICE(AQHBCI_LOGDOMAIN, "%s(): flags 0x%04X.", __FUNCTION__, jd->flags);
729
	if(jd->flags & FJCK_CHKEY)
730
	{
731
		//if(!jd->kiV || !GWEN_Crypt_Token_KeyInfo_GetKeyNumber(jd->kiV) || !jd->kiS || !GWEN_Crypt_Token_KeyInfo_GetKeyNumber(jd->kiS))
732
		if(!tokenHasKeys(jd->ct, jd->ctx))
733
		{
734
			m = fmtStr(FB, "Neue Schlüssel werden auf %s '%s' erzeugt.", jd->fm, jd->tn);
735
			btn1 = "Abort";
736
			btn2 = "OK";
737
			ok = 2;
738
		}
739
		else
740
		{
741
#if 0
742
			// TODO check keys are compatible with cryptmode
743
			// if so, ...
744
			{
745
				m = fmtStr(FB, "Auf %s '%s' sind Schlüssel vorhanden,\nsollen dennoch neue Schlüssel erzeugt werden?", fmn, tnn);
746
				btn1 = "Abort";
747
				btn2 = "No";
748
				btn3 = "Yes";
749
				ok = 3;
750
			}
751
			else
752
			{
753
				m = fmtStr(FB, "Auf %s '%s' vorhandene Schlüssel können nicht verwendet werden,\nneue Schlüssel werden erzeugt.", fmn, tnn);
754
				btn1 = "Abort";
755
				btn2 = "OK";
756
				ok = 2;
757
			}
758
#else
759
			m = fmtStr(FB, "Auf %s '%s' sind Schlüssel vorhanden die verwendet werden können,\n"
760
					   "wenn sie zum gewählten Verschlüsselungsverfahren passen.\n"
761
					   "Sollen neue Schlüssel erzeugt werden?", jd->fm, jd->tn);
762
			btn1 = "Abort";
763
			btn2 = "No";
764
			btn3 = "Yes";
765
			ok = 3;
766
#endif
767
		}
768
		res = GWEN_Gui_MessageBox(GWEN_GUI_MSG_FLAGS_TYPE_INFO, I18N("Change keys: confirm"),
769
																		m, I18N(btn1), I18N(btn2), btn3 ? I18N(btn3) : NULL, 0);
770
		if(res == 1)
771
		{
772
			res = -1;
773
			*jd->canceled = 1;
774
		}
775
		else
776
		{
777
			if(res == ok)
778
			{
779
				res = 0;
780
				DBG_INFO(AQHBCI_LOGDOMAIN, "creating keys...");
781
				res = AH_Provider_CreateKeys(jd->pro, jd->uTmp, 1);
782
				if(res)
783
					res = onError(fmtStr(FB, "Could not create keys (%d).", res), -1);
784
				DBG_INFO(AQHBCI_LOGDOMAIN, "creating keys done.");
785
			}
786
			else
787
				res = 0;
788
		}
789
	}
790
	else
791
		res = -1;
792
	if((res == 0) && (getKeyInfo(h, jd->tt, jd->tn, jd->tokenCtxId, &jd->ct, &jd->ctx, &jd->kiV, &jd->kiS, &jd->kiA)
793
			|| !jd->ct || !jd->ctx || !jd->kiV || !jd->kiS || !jd->kiA))
794
		res = onError("Could not get key-info.", -1);
795

  
796
	if(res == 0)
797
	{
798
#if 1
799
		if(!(jd->flags & FJCK_CHPROFILE))
800
		{
801
			// set keyversion from current token + 1 on dest.-token
802
			uint32_t kvV = jd->kvVCurr ? (jd->kvVCurr + 1) : 0;
803
			uint32_t kvS = jd->kvSCurr ? (jd->kvSCurr + 1) : 0;
804
			uint32_t kvA = jd->kvACurr ? (jd->kvACurr + 1) : 0;
805
			DBG_NOTICE(AQHBCI_LOGDOMAIN, "set keyversions %ld -> %ld, %ld -> %ld, %ld -> %ld.",
806
							(long)jd->kvVCurr, (long)kvV, (long)jd->kvSCurr, (long)kvS, (long)jd->kvACurr, (long)kvA);
807
			if(kvV)
808
				setKeyVersion((GWEN_CRYPT_TOKEN*)jd->ct, jd->ctx, jd->kiV, 'V', kvV);
809
			if(kvS)
810
				setKeyVersion((GWEN_CRYPT_TOKEN*)jd->ct, jd->ctx, jd->kiS, 'S', kvS);
811
			if(!(jd->flags & FJCK_DSTFILE) && kvA)
812
				setKeyVersion((GWEN_CRYPT_TOKEN*)jd->ct, jd->ctx, jd->kiA, 'A', kvA);
813
		}
814
#endif
815
		if(jd->flags & FJCK_CHKEY)
816
		{
817
			if(!jd->kiS || !GWEN_Crypt_Token_KeyInfo_GetKeyNumber(jd->kiS))
818
			{
819
				DBG_INFO(AQHBCI_LOGDOMAIN, "Kein Signierschlüssel.");
820
				res = onError("Kein Signierschlüssel auf dem Ziel-medium gefunden.", -1);
821
			}
822
			else
823
			{
824
				int sc = GWEN_Crypt_Token_KeyInfo_GetSignCounter(jd->kiS);
825
				DBG_INFO(AQHBCI_LOGDOMAIN, "%s(): sig counter %d.", __FUNCTION__, sc);
826
				if(sc > 1)
827
				{
828
					if(!(jd->flags & FJCK_DSTFILE))
829
						res = onError("Der Sequenzzähler kann nicht zurückgesetzt werden.", -1);
830
					else
831
					{
832
						res = GWEN_Gui_MessageBox(GWEN_GUI_MSG_FLAGS_TYPE_INFO, I18N("Change keys: confirm"),
833
												"Der Sequenzzähler wird zurückgesetzt.", I18N("Abort"), I18N("OK"), NULL, 0);
834
						if(res != 2)
835
							res = -1;
836
						else
837
							res = 0;
838
					}
839
					if(res == 0)
840
					{
841
						DBG_INFO(AQHBCI_LOGDOMAIN, "%s(): reset sig counter.", __FUNCTION__);
842
						GWEN_Crypt_Token_KeyInfo_SetSignCounter((GWEN_CRYPT_TOKEN_KEYINFO*)jd->kiS, 1);
843
					}
844
				}
845
			}
846
		}
847
	}
848

  
849
	if(res == 0)
850
	{
851
		if(getKeyInfo(h, jd->tt, jd->tn, jd->tokenCtxId, &jd->ct, &jd->ctx, &jd->kiV, &jd->kiS, &jd->kiA)
852
				|| !jd->ct || !jd->ctx || !jd->kiV || !jd->kiS || !jd->kiA)
853
			res = onError("Could not get key-info.", -1);
854
	}
855

  
856
	if((res == 0) && !jd->ctx)
857
		res = onError("Missing new ctx.", -1);
858

  
859
	return res;
860
}
861

  
862
#define RSP_NOSRVRSP	1
863
#define RSP_WARN		2
864
#define RSP_ERR			3
865

  
866
int8_t parseResponse(AH_JOB *j)
867
{
868
	int8_t res = 0;
869
	int rc = 0;
870
	uint8_t gotResp = 0;
871
	AH_JOB_CHANGEKEYS *jd = GWEN_INHERIT_GETDATA(AH_JOB, AH_JOB_CHANGEKEYS, j);
872
	GWEN_DB_NODE *n = AH_Job_GetResponses(j);
873
	if(AH_Job_GetStatus(j) != AH_JobStatusAnswered)
874
		rc = -1;
875
	assert(n);
876
	jd->emsg = GWEN_Buffer_new(NULL, 2048, 0, 0);
877
	n = GWEN_DB_GetFirstGroup(n);
878
	while(n)
879
	{
880
		//GWEN_DB_Dump(n, 0);
881
		if(!strcmp(GWEN_DB_GroupName(n), "SegResult"))
882
		{
883
			int mn = GWEN_DB_GetIntValue(n, "security/msgnum", 0, -1);
884
			if(mn == 2)
885
			{
886
				gotResp = 1;
887
				if((rc >= 0) && (rc < 9000))
888
				{
889
					rc = GWEN_DB_GetIntValue(n, "data/SegResult/result/resultcode", 0, -1);
890
					if(rc == 3250)
891
					{
892
						DBG_NOTICE(AQHBCI_LOGDOMAIN, "%s(): response %d tells us: no HKEND.", __FUNCTION__, rc);
893
						res = 1;
894
						rc = 0;
895
					}
896
					else
897
					{
898
						GWEN_Buffer_AppendString(jd->emsg, GWEN_DB_GetCharValue(n, "data/SegResult/result/text", 0, "?"));
899
						GWEN_Buffer_AppendString(jd->emsg, "\n");
900
					}
901
				}
902
				DBG_NOTICE(AQHBCI_LOGDOMAIN, "result %d.", rc);
903
				DBG_NOTICE(AQHBCI_LOGDOMAIN, "result '%s'.", GWEN_Buffer_GetStart(jd->emsg));
904
			}
905
			else
906
			{
907
				DBG_NOTICE(AQHBCI_LOGDOMAIN, "%s(): #%d result %d '%s'.", __FUNCTION__,
908
						   GWEN_DB_GetIntValue(n, "security/msgnum", 0, -1),
909
						   GWEN_DB_GetIntValue(n, "data/SegResult/result/resultcode", 0, -1),
910
						   GWEN_DB_GetCharValue(n, "data/SegResult/result/text", 0, "?"));
911
				if(GWEN_DB_GetIntValue(n, "data/SegResult/result/resultcode", 0, -1) >= 9000)
912
				{
913
					rc = GWEN_DB_GetIntValue(n, "data/SegResult/result/resultcode", 0, -1);
914
					GWEN_Buffer_AppendString(jd->emsg, GWEN_DB_GetCharValue(n, "data/SegResult/result/text", 0, "?"));
915
					GWEN_Buffer_AppendString(jd->emsg, "\n");
916
				}
917
			}
918
		}
919
		n = GWEN_DB_GetNextGroup(n);
920
	}
921
	if(!gotResp)
922
		jd->resp = RSP_NOSRVRSP;
923
	else
924
		jd->resp = (rc < 3000) ? 0 : (rc < 9000) ? RSP_WARN : RSP_ERR;
925
	return res;
926
}
927

  
928
void GWENHYWFAR_CB GWENHYWFAR_CB AH_Job_ChangeKeys_FreeData(void *bp, void *p)
929
{
930
	AH_JOB_CHANGEKEYS *jd = (AH_JOB_CHANGEKEYS*)p;
931
	DBG_NOTICE(AQHBCI_LOGDOMAIN, "%s(): %p uTmp %p.", __FUNCTION__, jd, jd->uTmp);
932

  
933
	if(jd->uTmp)
934
		AB_User_free(jd->uTmp);
935
	if(jd->tt)
936
		free(jd->tt);
937
	if(jd->tn)
938
		free(jd->tn);
939
	if(jd->emsg)
940
		GWEN_Buffer_free(jd->emsg);
941

  
942
	GWEN_FREE_OBJECT(jd);
943
}
944

  
945
int AH_Job_ChangeKeys_NextMsg(AH_JOB *j)
946
{
947
	int rv = 0;
948
	int mn = -1;
949
	unsigned int jmn = 0;
950
	GWEN_DB_NODE *dbr = NULL;
951
	AH_JOB_CHANGEKEYS *jd;
952
	assert(j);
953
	jmn = AH_Job_GetMsgNum(j);
954
	dbr = AH_Job_GetResponses(j);
955
	dbr = GWEN_DB_GetFirstGroup(dbr);
956
	DBG_NOTICE(AQHBCI_LOGDOMAIN, "%s(): jmn %d.", __FUNCTION__, jmn);
957
	while(dbr)
958
	{
959
		//GWEN_DB_Dump(dbr, 0);
960
		rv = AH_Job_CheckEncryption(j, dbr);
961
		if(rv)
962
		{
963
			DBG_ERROR(AQHBCI_LOGDOMAIN, "%s(): AH_Job_CheckEncryption() failed (%d).", __FUNCTION__, rv);
964
			return -1;
965
		}
966
		rv = AH_Job_CheckSignature(j, dbr);
967
		if(rv)
968
		{
969
			DBG_ERROR(AQHBCI_LOGDOMAIN, "%s(): AH_Job_CheckSignature() failed (%d).", __FUNCTION__, rv);
970
			return -1;
971
		}
972
		if(!strcasecmp(GWEN_DB_GroupName(dbr), "MsgTail"))
973
		{
974
			mn = GWEN_DB_GetIntValue(dbr, "security/msgnum", 0, -1);
975
			if(mn < 0)
976
			{
977
				DBG_ERROR(AQHBCI_LOGDOMAIN, "%s: find msgnum failed.", __FUNCTION__);
978
			}
979
			else if((mn == 1) && (jmn == mn))
980
			{
981
				const GWEN_CRYPT_KEY *bk = NULL;
982
				GWEN_CRYPT_KEY *bkCurrV = NULL, *bkCurrS = NULL;
983
				jd = GWEN_INHERIT_GETDATA(AH_JOB, AH_JOB_CHANGEKEYS, j);
984
				assert(jd);
985
				// get actual serverkeys to restore later
986
				bk = AH_User_GetBankPubCryptKey(jd->u);
987
				if(bk)
988
					bkCurrV = GWEN_Crypt_KeyRsa_dup(bk);
989
				bk = AH_User_GetBankPubSignKey(jd->u);
990
				if(bk)
991
					bkCurrS = GWEN_Crypt_KeyRsa_dup(bk);
992
				rv = AH_Job_CommitSystemData(j, 0);
993
				if(rv != 0)
994
				{
995
					DBG_ERROR(AQHBCI_LOGDOMAIN, "%s(): AH_Job_CommitSystemData() failed(%d).", __FUNCTION__, rv);
996
				}
997
				else if(!GWEN_Crypt_Token_IsOpen(jd->ct) && (GWEN_Crypt_Token_Open(jd->ct, 0, 0) < 0))
998
					rv = onError("GWEN_Crypt_Token_Open() failed.", -1);
999
				else
1000
				{
1001
					GWEN_Gui_ProgressLog(0, GWEN_LoggerLevel_Info, I18N("Serverkeys imported."));
1002
					DBG_NOTICE(AQHBCI_LOGDOMAIN, "%s(): serverkeys should be imported now.", __FUNCTION__);
1003
					// some cryptmodes need length of serverkeys
1004
					// AH_Provider_CreateKeys() reads the length from user-token,
1005
					// which is the temporary user with the new token,
1006
					// so store server-keys from actual user (the now imported) on the new token
1007
					//DBG_NOTICE(AQHBCI_LOGDOMAIN, "%s(): ctx %p.", __FUNCTION__, jd->ctx);
1008
					jd->ctx = GWEN_Crypt_Token_GetContext(jd->ct, jd->tokenCtxId, 0);
1009
					//DBG_NOTICE(AQHBCI_LOGDOMAIN, "%s(): -> ctx %p.", __FUNCTION__, jd->ctx);
1010
					for(uint8_t i = 0; (rv == 0) && (i < 2); i++)
1011
					{
1012
						const GWEN_CRYPT_TOKEN_KEYINFO *tmp = NULL;
1013
						uint8_t *m = NULL, *e = NULL;
1014
						uint32_t ml = 0, el = 0;
1015
						uint32_t id = 0;
1016
						bk = NULL;
1017
						switch(i)
1018
						{
1019
						case 0:
1020
							bk = AH_User_GetBankPubCryptKey(jd->u);
1021
							id = GWEN_Crypt_Token_Context_GetEncipherKeyId(jd->ctx);
1022
							AH_User_SetBankPubCryptKey(jd->uTmp, (GWEN_CRYPT_KEY*)bk);
1023
							break;
1024
						case 1:
1025
							bk = AH_User_GetBankPubSignKey(jd->u);
1026
							id = GWEN_Crypt_Token_Context_GetVerifyKeyId(jd->ctx);
1027
							AH_User_SetBankPubSignKey(jd->uTmp, (GWEN_CRYPT_KEY*)bk);
1028
							break;
1029
						}
1030

  
1031
						if(!bk)
1032
						{
1033
							if(i == 0)
1034
							{
1035
								DBG_ERROR(AQHBCI_LOGDOMAIN, "%s(): get bankkey failed.", __FUNCTION__);
1036
								rv = -1;
1037
							}
1038
							else
1039
								DBG_NOTICE(AQHBCI_LOGDOMAIN, "%s(): bank has no signkey.", __FUNCTION__);
1040
							continue;
1041
						}
1042

  
1043
						ml = GWEN_Crypt_Key_GetKeySize(bk);
1044
						el = 3;
1045

  
1046
						if(ml)
1047
						{
1048
							m = malloc(ml);
1049
							e = malloc(el);
1050
							GWEN_Crypt_KeyRsa_GetModulus(bk, m, &ml);
1051
							GWEN_Crypt_KeyRsa_GetExponent(bk, e, &el);
1052
						}
1053
						tmp = GWEN_Crypt_Token_GetKeyInfo(jd->ct, id, 0, 0);
1054
						DBG_NOTICE(AQHBCI_LOGDOMAIN, "%s(): k %ld m %ld %p e %ld %p.", __FUNCTION__, (long)id, (long)ml, m, (long)el, e);
1055
						if(!tmp)
1056
						{
1057
							DBG_ERROR(AQHBCI_LOGDOMAIN, "%s(): damn, get keyinfo '%c' failed.", __FUNCTION__, (i == 0) ? 'V' : 'S');
1058
							rv = onError("GWEN_Crypt_Token_GetKeyInfo() failed.", -1);
1059
						}
1060
						if(rv == 0)
1061
						{
1062
							GWEN_CRYPT_TOKEN_KEYINFO *ki = GWEN_Crypt_Token_KeyInfo_dup(tmp);
1063
							uint32_t flags = GWEN_Crypt_Token_KeyInfo_GetFlags(ki);
1064
							GWEN_Crypt_Token_KeyInfo_SetFlags(ki, flags | GWEN_CRYPT_TOKEN_KEYFLAGS_HASMODULUS | GWEN_CRYPT_TOKEN_KEYFLAGS_HASEXPONENT);
1065
							GWEN_Crypt_Token_KeyInfo_SetModulus(ki, m, ml);
1066
							GWEN_Crypt_Token_KeyInfo_SetExponent(ki, e, el);
1067
							GWEN_Crypt_Token_KeyInfo_SetKeySize(ki, ml);
1068
							GWEN_Crypt_Token_KeyInfo_SetKeyNumber(ki, GWEN_Crypt_Key_GetKeyNumber(bk));
1069
							GWEN_Crypt_Token_KeyInfo_SetKeyVersion(ki, GWEN_Crypt_Key_GetKeyVersion(bk));
1070
							if(GWEN_Crypt_Token_SetKeyInfo(jd->ct, id, ki, 0))
1071
							{
1072
								DBG_ERROR(AQHBCI_LOGDOMAIN, "%s(): GWEN_Crypt_Token_SetKeyInfo() failed.", __FUNCTION__);
1073
								rv = -1;
1074
							}
1075
							else
1076
								ki = NULL;
1077
							if(ki)
1078
								GWEN_Crypt_Token_KeyInfo_free(ki);
1079
						}
1080
						if(m)
1081
							free(m);
1082
						if(e)
1083
							free(e);
1084
					}
1085
					if(rv == 0)
1086
					{
1087
						rv = onServerKeysImported(jd);
1088
						if(rv != 0)
1089
							DBG_ERROR(AQHBCI_LOGDOMAIN, "%s(): onServerKeysImported() failed.", __FUNCTION__);
1090
					}
1091
					// serverkeys set in job_commit() must restored
1092
					if(bkCurrV)
1093
					{
1094
						AH_User_SetBankPubCryptKey(jd->u, bkCurrV);
1095
						DBG_NOTICE(AQHBCI_LOGDOMAIN, "%s(): serverkey 'V' restored.", __FUNCTION__);
1096
						GWEN_Crypt_Key_free(bkCurrV);
1097
					}
1098
					if(bkCurrS)
1099
					{
1100
						AH_User_SetBankPubSignKey(jd->u, bkCurrS);
1101
						DBG_NOTICE(AQHBCI_LOGDOMAIN, "%s(): serverkey 'S' restored.", __FUNCTION__);
1102
						GWEN_Crypt_Key_free(bkCurrS);
1103
					}
1104
					if(rv == 0)
1105
					{
1106
						// update segment-data
1107
						GWEN_DB_NODE *args = AH_Job_GetArguments(j);
1108
						assert(args);
1109
						for(uint8_t i = 0; (rv == 0) && (i < 3); i++)
1110
						{
1111
							GWEN_DB_NODE *db = NULL;
1112
							const GWEN_CRYPT_TOKEN_KEYINFO *ki = NULL;
1113
							const uint8_t *kd = NULL;
1114
							uint32_t kdsz = 0;
1115
							const char *kt = "?";
1116
							int kn = 0, kv = 0;
1117

  
1118
							switch(i)
1119
							{
1120
							case 0: kt = "V"; ki = jd->kiV; db = GWEN_DB_GetGroup(args, GWEN_DB_FLAGS_DEFAULT, "setcryptKey"); break;
1121
							case 1: kt = "S"; ki = jd->kiS; db = GWEN_DB_GetGroup(args, GWEN_DB_FLAGS_DEFAULT, "setsignKey"); break;
1122
							case 2: kt = "D"; ki = jd->kiA; db = GWEN_DB_GetGroup(args, GWEN_DB_FLAGS_DEFAULT, "setauthKey"); break;
1123
							}
1124

  
1125
							if(!ki)
1126
							{
1127
								if(i < 2)
1128
								{
1129
									DBG_ERROR(AQHBCI_LOGDOMAIN, "%s(): get keyinfo '%s' failed.", __FUNCTION__, kt);
1130
									rv = -1;
1131
								}
1132
								else
1133
									DBG_NOTICE(AQHBCI_LOGDOMAIN, "%s(): token has no authkey.", __FUNCTION__);
1134
								continue;
1135
							}
1136

  
1137
							kd = GWEN_Crypt_Token_KeyInfo_GetModulusData(ki);
1138
							kdsz = GWEN_Crypt_Token_KeyInfo_GetModulusLen(ki);
1139
							if(!kd || !kdsz)
1140
							{
1141
								DBG_ERROR(AQHBCI_LOGDOMAIN, "No modulus in '%s' key.", kt);
1142
								rv = -1;
1143
								break;
1144
							}
1145
							GWEN_DB_SetBinValue(db, GWEN_DB_FLAGS_OVERWRITE_VARS, "key/modulus", kd, kdsz);
1146

  
1147
							kd = GWEN_Crypt_Token_KeyInfo_GetExponentData(ki);
1148
							kdsz = GWEN_Crypt_Token_KeyInfo_GetExponentLen(ki);
1149
							if(!kd || !kdsz)
1150
							{
1151
								DBG_ERROR(AQHBCI_LOGDOMAIN, "No exponent in '%s' key.", kt);
1152
								rv = -1;
1153
								break;
1154
							}
1155
							GWEN_DB_SetBinValue(db, GWEN_DB_FLAGS_OVERWRITE_VARS, "key/exponent", kd, kdsz);
1156

  
1157
							kd = GWEN_Crypt_Token_KeyInfo_GetCertificateData(ki);
1158
							kdsz = GWEN_Crypt_Token_KeyInfo_GetCertificateLen(ki);
1159
							if(kd && kdsz)
1160
							{
1161
								GWEN_DB_SetIntValue(db, GWEN_DB_FLAGS_OVERWRITE_VARS, "cert/type", GWEN_Crypt_Token_KeyInfo_GetCertType(ki));
1162
								GWEN_DB_SetBinValue(db, GWEN_DB_FLAGS_OVERWRITE_VARS, "cert/cert", kd, kdsz);
1163
							}
1164
							else
1165
								DBG_NOTICE(AQHBCI_LOGDOMAIN, "No cert for '%s' on token.", kt);
1166

  
1167
							kn = GWEN_Crypt_Token_KeyInfo_GetKeyNumber(ki);
1168
							kv = GWEN_Crypt_Token_KeyInfo_GetKeyVersion(ki);
1169
							GWEN_DB_SetIntValue(db, GWEN_DB_FLAGS_OVERWRITE_VARS, "key/keynum", kn);
1170
							GWEN_DB_SetIntValue(db, GWEN_DB_FLAGS_OVERWRITE_VARS, "key/keyversion", kv);
1171
							GWEN_DB_SetIntValue(db, GWEN_DB_FLAGS_OVERWRITE_VARS, "keyName/keynum", kn);
1172
							GWEN_DB_SetIntValue(db, GWEN_DB_FLAGS_OVERWRITE_VARS, "keyName/keyversion", kv);
1173
						}
1174
					}
1175
				}
1176
			}
1177
			else if((mn == 2) && (jmn == mn))
1178
			{
1179
				int8_t resp = parseResponse(j);
1180
				DBG_NOTICE(AQHBCI_LOGDOMAIN, "%s: resp %d, %s HKEND.", __FUNCTION__, resp, (resp == 1) ? "no" : "next");
1181
				if(resp == 1) // since 5.99.25 no chance to prevent HKEND :-(
1182
					return 0;
1183
			}
1184
		}
1185
		dbr = GWEN_DB_GetNextGroup(dbr);
1186
	}
1187
	return (rv == 0) ? 1 : -1;
1188
}
1189

  
1190
int AH_Job_ChangeKeys_finish(AB_PROVIDER *pro, AH_JOB *job, int res)
1191
{
1192
	AH_JOB_CHANGEKEYS *jd = NULL;
1193
	AB_USER *u = NULL;
1194
	AB_USER *uTmp = NULL;
1195
	if(!job)
1196
		return res;
1197
	jd = GWEN_INHERIT_GETDATA(AH_JOB, AH_JOB_CHANGEKEYS, job);
1198
	if(*jd->canceled)
1199
	{
1200
		DBG_NOTICE(AQHBCI_LOGDOMAIN, "%s(): user canceled.", __FUNCTION__);
1201
		jd->resp = -1;
1202
	}
1203
	u = jd->u;
1204
	uTmp = jd->uTmp;
1205

  
1206
	res = -1;
1207
	if(jd->resp >= 0)
1208
	{
1209
		char fmtBuff[1024];
1210
		const char *m = NULL;
1211
		const char *btn1 = I18N("Abort");
1212
		const char *btn2 = I18N("Finish");
1213
		if(jd->resp == RSP_NOSRVRSP)
1214
		{
1215
			GWEN_Gui_MessageBox(GWEN_GUI_MSG_FLAGS_TYPE_INFO, I18N("Change keys: Error"),
1216
							"Der Bankserver hat keine Antwort zur Schlüsseländerung gesendet.", I18N("OK"), NULL, NULL, 0);
1217
			res = -1;
1218
		}
1219
		else
1220
		{
1221
			if((jd->resp == RSP_WARN) || (jd->resp == RSP_ERR))
1222
			{
1223
				m = strdup(fmtStr(FB, "Der Bankserver meldet %s:\n\n'%s'\n\n"
1224
						   "Es ist möglich, dass der neue Schlüssel dennoch angenommenn wurde.\n"
1225
						   "Neue Schlüssel / neues Medium übernehmen?", (jd->resp == RSP_ERR) ? "Fehler" : "Warnungen",
1226
							GWEN_Buffer_GetStart(jd->emsg)));
1227
				btn1 = I18N("No");
1228
				btn2 = fmtStr(FB, "%s, %s", I18N("Yes"), I18N("finish"));
1229
			}
1230
			else
1231
			{
1232
				m = strdup(fmtStr(FB, "Die Übermittlung der Schlüssel ergab keinen Fehler,\n"
1233
						"aus den Meldungen des Bankservers sollte eine Übernahme ersichtlich sein:\n\n%s\nNeue Schlüssel / neues Medium\n"
1234
						"wird übernommen.", GWEN_Buffer_GetStart(jd->emsg)));
1235
			}
1236
			if(GWEN_Gui_MessageBox(GWEN_GUI_MSG_FLAGS_TYPE_INFO, I18N("Change keys: confirm"),
1237
																		m, btn1, btn2, NULL, 0) == 2)
1238
				res = 0;
1239
		}
1240
		if(m)
1241
			free((char*)m);
1242
	}
1243
	DBG_NOTICE(AQHBCI_LOGDOMAIN, "%s(): %d/%d %p %p.", __FUNCTION__, jd->resp, res, u, uTmp);
1244
	if(uTmp)
1245
	{
1246
		DBG_INFO(AQHBCI_LOGDOMAIN, "%s: tt '%s' tn '%s' rdh %d cm %d ctx-id %d.", __FUNCTION__,
1247
				  AH_User_GetTokenType(uTmp), AH_User_GetTokenName(uTmp), AH_User_GetRdhType(uTmp),
1248
				  AH_User_GetCryptMode(uTmp), AH_User_GetTokenContextId(uTmp));
1249
		if(res == 0)
1250
		{
1251
			if(AB_Provider_BeginExclUseUser(pro, u))
1252
			{
1253
				DBG_ERROR(AQHBCI_LOGDOMAIN, "%s(): AB_Provider_BeginExclUseUser() failed.", __FUNCTION__);
1254
				res = -1;
1255
			}
1256
			else
1257
			{
1258
				AH_User_SetBankPubCryptKey(u, AH_User_GetBankPubCryptKey(uTmp));
1259
				AH_User_SetBankPubSignKey(u, AH_User_GetBankPubSignKey(uTmp));
1260
				AH_User_SetTokenType(u, AH_User_GetTokenType(uTmp));
1261
				AH_User_SetTokenName(u, AH_User_GetTokenName(uTmp));
1262
				AH_User_SetRdhType(u, AH_User_GetRdhType(uTmp));
1263
				AH_User_SetCryptMode(u, AH_User_GetCryptMode(uTmp));
1264
				AH_User_SetTokenContextId(u, AH_User_GetTokenContextId(uTmp));
1265
				if(AB_Provider_EndExclUseUser(pro, u, 0))
1266
				{
1267
					DBG_ERROR(AQHBCI_LOGDOMAIN, "%s(): AB_Provider_EndExclUseUser() failed.", __FUNCTION__);
1268
					res = -1;
1269
				}
1270
			}
1271
		}
1272
		AB_Provider_DeleteUser(pro, AB_User_GetUniqueId(uTmp));
1273
	}
1274

  
1275
	return res;
1276
}
src/libs/plugins/backends/aqhbci/admjobs/jobchangekeys.xml
1
<!--
2
/***************************************************************************
3

  
4
***************************************************************************
5
*          Please see toplevel file COPYING for license details           *
6
***************************************************************************/
7
 -->
8

  
9
<SEGs>
10
	<SEGdef id="ChangeKeys"
11
			code="HKSAK"
12
			version="3"
13
			pversion="300"
14
			delimiter="+"
15
			terminator="'">
16
		<GROUP type="SegHead" name="head" />
17
		<ELEM name="context" type="num" maxsize="1" />
18
		<ELEM name="fntyp" type="num" maxsize="3" />
19
		<GROUP type="SecProfile" name="secProfile" />
20
		<GROUP name="keyName" type="signkeyname" />
21
		<GROUP name="key" type="signkey" trustlevel="3" />
22
		<GROUP name="cert" type="cert" minnum="0" />
23
		<VALUES>
24
			<VALUE path="head/code">%code</VALUE>
25
			<VALUE path="head/version">%version</VALUE>
26
			<VALUE path="context">2</VALUE>
27
			<VALUE path="fntyp">112</VALUE>
28
		</VALUES>
29
	</SEGdef>
30
</SEGs>
31

  
32
<JOBs>
33
	<JOBdef id="JobChangeKeys"
34
			version="4"
35
			dlg="1"
36
			needbpd="0"
37
	>
38
		<MESSAGE name="open" >
39
			<SEG type="Ident" name="ident" />
40
			<SEG type="Prepare" name="prepare" version="3" />
41
			<SEG type="GetKey" version="3" name="getcryptKey" />
42
			<SEG type="GetKey" version="3" name="getsignKey" />
43
		</MESSAGE>
44
		<MESSAGE>
45
			<SEG type="ChangeKeys" version="3" name="setcryptKey" />
46
			<SEG type="ChangeKeys" version="3" name="setsignKey" />
47
		</MESSAGE>
48
		<MESSAGE name="close" >
49
			<SEG type="DialogEnd" />
50
		</MESSAGE>
51
	</JOBdef>
52

  
53
	<JOBdef id="JobChangeKeysA"
54
			version="4"
55
			dlg="1"
56
			needbpd="0"
57
	>
58
		<MESSAGE name="open" >
59
			<SEG type="Ident" name="ident" />
60
			<SEG type="Prepare" name="prepare" version="3" />
61
			<SEG type="GetKey" version="3" name="getcryptKey" />
62
			<SEG type="GetKey" version="3" name="getsignKey" />
63
		</MESSAGE>
64
		<MESSAGE>
65
			<SEG type="ChangeKeys" version="3" name="setcryptKey" />
66
			<SEG type="ChangeKeys" version="3" name="setsignKey" />
67
			<SEG type="ChangeKeys" version="3" name="setauthKey" />
68
		</MESSAGE>
69
		<MESSAGE name="close" >
70
			<SEG type="DialogEnd" />
71
		</MESSAGE>
72
	</JOBdef>
73
</JOBs>
74

  
src/libs/plugins/backends/aqhbci/admjobs/jobchangekeys_l.h
1
/***************************************************************************
2

  
3
 ***************************************************************************
4
 *          Please see toplevel file COPYING for license details           *
5
 ***************************************************************************/
6

  
7

  
8
#ifndef AH_JOBCHANGEKEYS_L_H
9
#define AH_JOBCHANGEKEYS_L_H
10

  
11

  
12
#include "aqhbci_l.h"
13
#include "job_l.h"
14

  
15

  
16
AH_JOB *AH_Job_ChangeKeys_new(AB_PROVIDER *pro, AB_USER *u, GWEN_DB_NODE *args, uint8_t *canceled);
17

  
18
int AH_Job_ChangeKeys_finish(AB_PROVIDER *pro, AH_JOB *job, int res);
19

  
20

  
21

  
22
#endif
23

  
src/libs/plugins/backends/aqhbci/admjobs/jobchangekeys_p.h
1
#ifndef AH_JOBLOCKKEYS_P_H
2
#define AH_JOBLOCKKEYS_P_H
3

  
4

  
5
#include "jobchangekeys_l.h"
6

  
7
typedef struct AH_JOB_CHANGEKEYS AH_JOB_CHANGEKEYS;
8

  
9

  
10
#endif
11

  
src/libs/plugins/backends/aqhbci/banking/provider.c
47 47
/* admin jobs */
48 48
#include "jobgetkeys_l.h"
49 49
#include "jobsendkeys_l.h"
50
#include "jobchangekeys_l.h"
50 51
#include "jobgetsepainfo_l.h"
51 52
#include "jobgetsysid_l.h"
52 53
#include "jobgetbankinfo_l.h"
src/libs/plugins/backends/aqhbci/banking/provider.h
146 146
                              int withAuthKey,
147 147
                              int withProgress, int nounmount, int doLock);
148 148

  
149
/**
150
 */
151
int AH_Provider_ChangeUserKeys(AB_PROVIDER *pro, AB_USER *u, GWEN_DB_NODE *args, int withProgress, int nounmount, int doLock);
152

  
149 153
/**
150 154
 * Retrieve the SSL certificate for the given user. This is only needed for
151 155
 * PIN/TAN mode.
src/libs/plugins/backends/aqhbci/banking/provider_online.c
825 825
}
826 826

  
827 827

  
828
int AH_Provider_ChangeUserKeys(AB_PROVIDER *pro, AB_USER *u, GWEN_DB_NODE *args, int withProgress, int nounmount, int doLock)
829
{
830
	int res = 0;
831
	uint8_t canceled = 0;
832
	AH_JOB *job = NULL;
833
	AB_IMEXPORTER_CONTEXT *ctx = NULL;
834

  
835
	assert(u);
836

  
837
	job = AH_Job_ChangeKeys_new(pro, u, args, &canceled);
838
	if(!job)
839
	{
840
		res = -2;
841
		if(!canceled)
842
		{
843
			DBG_ERROR(AQHBCI_LOGDOMAIN, "Unexplainable, 'AH_Job_ChangeKeys_new' not supported.");
844
			GWEN_Gui_ProgressLog(0, GWEN_LoggerLevel_Error, I18N("Unexplainable, 'AH_Job_ChangeKeys_new' not supported."));
845
			res = -1;
846
		}
847
		if(canceled == 2)
848
			res = -1;
849
	}
850

  
851
	if(!res)
852
	{
853
		ctx = AB_ImExporterContext_new();
854
		if(!ctx)
855
		{
856
			DBG_ERROR(AQHBCI_LOGDOMAIN, "Error getting ctx.");
857
			res = -1;
... This diff was truncated because it exceeds the maximum size that can be displayed.