gwenhywfar  4.6.0beta
cgui.c
Go to the documentation of this file.
1 /***************************************************************************
2  begin : Tue Oct 02 2002
3  copyright : (C) 2002 by Martin Preuss
4  email : martin@libchipcard.de
5 
6  ***************************************************************************
7  * *
8  * This library is free software; you can redistribute it and/or *
9  * modify it under the terms of the GNU Lesser General Public *
10  * License as published by the Free Software Foundation; either *
11  * version 2.1 of the License, or (at your option) any later version. *
12  * *
13  * This library is distributed in the hope that it will be useful, *
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of *
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
16  * Lesser General Public License for more details. *
17  * *
18  * You should have received a copy of the GNU Lesser General Public *
19  * License along with this library; if not, write to the Free Software *
20  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, *
21  * MA 02111-1307 USA *
22  * *
23  ***************************************************************************/
24 
25 
26 #ifdef HAVE_CONFIG_H
27 # include <config.h>
28 #endif
29 
30 #define DISABLE_DEBUGLOG
31 
32 
33 #ifndef ICONV_CONST
34 # define ICONV_CONST
35 #endif
36 
37 
38 #include "cgui_p.h"
39 #include "i18n_l.h"
40 
41 #include <gwenhywfar/gui_be.h>
42 #include <gwenhywfar/inherit.h>
43 #include <gwenhywfar/debug.h>
44 #include <gwenhywfar/misc.h>
45 #include <gwenhywfar/db.h>
46 #include <gwenhywfar/gwentime.h>
47 #include <gwenhywfar/mdigest.h>
48 #include <gwenhywfar/text.h>
49 
50 
51 #include <stdlib.h>
52 #include <string.h>
53 #include <ctype.h>
54 #ifdef HAVE_TERMIOS_H
55 # include <termios.h>
56 #endif
57 #include <unistd.h>
58 #include <fcntl.h>
59 #include <stdio.h>
60 #include <errno.h>
61 
62 #ifdef HAVE_SIGNAL_H
63 # include <signal.h>
64 #endif
65 
66 
67 
68 GWEN_INHERIT(GWEN_GUI, GWEN_GUI_CGUI)
69 
70 
71 
72 
74  GWEN_GUI *gui;
75  GWEN_GUI_CGUI *cgui;
76 
77  gui=GWEN_Gui_new();
78  GWEN_NEW_OBJECT(GWEN_GUI_CGUI, cgui);
79  cgui->progressList=GWEN_Gui_CProgress_List_new();
80  GWEN_INHERIT_SETDATA(GWEN_GUI, GWEN_GUI_CGUI, gui, cgui,
82 
92 
93  cgui->checkCertFn=GWEN_Gui_SetCheckCertFn(gui, GWEN_Gui_CGui_CheckCert);
94 
95  cgui->dbCerts=GWEN_DB_Group_new("certs");
96 
97  return gui;
98 }
99 
100 
101 
103  GWEN_GUI_CGUI *cgui;
104 
105  cgui=(GWEN_GUI_CGUI*)p;
106  GWEN_Gui_CProgress_List_free(cgui->progressList);
107  GWEN_DB_Group_free(cgui->dbCerts);
108  GWEN_FREE_OBJECT(cgui);
109 }
110 
111 
112 
113 const char *GWEN_Gui_CGui_GetCharSet(const GWEN_GUI *gui) {
114  return GWEN_Gui_GetCharSet(gui);
115 }
116 
117 
118 
119 void GWEN_Gui_CGui_SetCharSet(GWEN_GUI *gui, const char *s) {
120  GWEN_Gui_SetCharSet(gui, s);
121 }
122 
123 
124 
127 }
128 
129 
130 
132  if (i)
134  else
136 }
137 
138 
139 
142 }
143 
144 
145 
147  if (i)
149  else
151 }
152 
153 
154 
155 void GWEN_Gui_CGui_SetPasswordDb(GWEN_GUI *gui, GWEN_DB_NODE *dbPasswords, int persistent) {
156  GWEN_Gui_SetPasswordDb(gui, dbPasswords, persistent);
157 }
158 
159 
160 
162  return GWEN_Gui_GetPasswordDb(gui);
163 }
164 
165 
166 
167 
168 
170  int chr;
171 #ifdef HAVE_TERMIOS_H
172  struct termios OldAttr, NewAttr;
173  int AttrChanged = 0;
174 #endif
175 #if HAVE_DECL_SIGPROCMASK
176  sigset_t snew, sold;
177 #endif
178 
179  // disable canonical mode to receive a single character
180 #if HAVE_DECL_SIGPROCMASK
181  sigemptyset(&snew);
182  sigaddset(&snew, SIGINT);
183  sigaddset(&snew, SIGSTOP);
184  sigprocmask(SIG_BLOCK, &snew, &sold);
185 #endif
186 #ifdef HAVE_TERMIOS_H
187  if (0 == tcgetattr (fileno (stdin), &OldAttr)){
188  NewAttr = OldAttr;
189  NewAttr.c_lflag &= ~ICANON;
190  NewAttr.c_lflag &= ~ECHO;
191  tcsetattr (fileno (stdin), TCSAFLUSH, &NewAttr);
192  AttrChanged = !0;
193  }
194 #endif
195 
196  for (;;) {
197  chr=getchar();
198  if (waitFor) {
199  if (chr==-1 ||
200  chr==GWEN_GUI_CGUI_CHAR_ABORT ||
201  chr==GWEN_GUI_CGUI_CHAR_ENTER ||
202  chr==waitFor)
203  break;
204  }
205  else
206  break;
207  }
208 
209 #ifdef HAVE_TERMIOS_H
210  /* re-enable canonical mode (if previously disabled) */
211  if (AttrChanged)
212  tcsetattr (fileno (stdin), TCSADRAIN, &OldAttr);
213 #endif
214 
215 #if HAVE_DECL_SIGPROCMASK
216  sigprocmask(SIG_BLOCK, &sold, 0);
217 #endif
218 
219  return chr;
220 }
221 
222 
223 
225  uint32_t flags,
226  char *buffer,
227  int minLen,
228  int maxLen,
229  uint32_t guiid){
230 #ifdef HAVE_TERMIOS_H
231  struct termios OldInAttr, NewInAttr;
232  struct termios OldOutAttr, NewOutAttr;
233  int AttrInChanged = 0;
234  int AttrOutChanged = 0;
235 #endif
236  int chr;
237  unsigned int pos;
238  int rv;
239 #if HAVE_DECL_SIGPROCMASK
240  sigset_t snew, sold;
241 #endif
242 
243  /* if possible, disable echo from stdin to stderr during password
244  * entry */
245 #if HAVE_DECL_SIGPROCMASK
246  sigemptyset(&snew);
247  sigaddset(&snew, SIGINT);
248  sigaddset(&snew, SIGSTOP);
249  sigprocmask(SIG_BLOCK, &snew, &sold);
250 #endif
251 
252 #ifdef HAVE_TERMIOS_H
253  if (0 == tcgetattr (fileno (stdin), &OldInAttr)){
254  NewInAttr = OldInAttr;
255  NewInAttr.c_lflag &= ~ECHO;
256  NewInAttr.c_lflag &= ~ICANON;
257  tcsetattr (fileno (stdin), TCSAFLUSH, &NewInAttr);
258  AttrInChanged = !0;
259  }
260  if (0 == tcgetattr (fileno (stderr), &OldOutAttr)){
261  NewOutAttr = OldOutAttr;
262  NewOutAttr.c_lflag &= ~ICANON;
263  tcsetattr (fileno (stderr), TCSAFLUSH, &NewOutAttr);
264  AttrOutChanged = !0;
265  }
266 #endif
267 
268  pos=0;
269  rv=0;
270  for (;;) {
271  chr=getchar();
272  if (chr==GWEN_GUI_CGUI_CHAR_DELETE) {
273  if (pos) {
274  pos--;
275  fprintf(stderr, "%c %c", 8, 8);
276  }
277  }
278  else if (chr==GWEN_GUI_CGUI_CHAR_ENTER) {
279  if (minLen && pos<minLen) {
280  if (pos==0 && (flags & GWEN_GUI_INPUT_FLAGS_ALLOW_DEFAULT)) {
284  I18N("Empty Input"),
285  I18N("Your input was empty.\n"
286  "Do you want to use the default?"),
287  I18N("Yes"),
288  I18N("No"),
289  I18N("Abort"), guiid);
290  if (rv==1) {
292  break;
293  }
294  else {
296  break;
297  }
298  }
299  else {
300  /* too few characters */
301  fprintf(stderr, "\007");
302  }
303  }
304  else {
305  fprintf(stderr, "\n");
306  buffer[pos]=0;
307  rv=0;
308  break;
309  }
310  }
311  else {
312  if (pos<maxLen) {
313  if (chr==GWEN_GUI_CGUI_CHAR_ABORT) {
314  DBG_INFO(GWEN_LOGDOMAIN, "User aborted");
316  break;
317  }
318  else {
319  if ((flags & GWEN_GUI_INPUT_FLAGS_NUMERIC) &&
320  !isdigit(chr)) {
321  /* bad character */
322  fprintf(stderr, "\007");
323  }
324  else {
325  if (flags & GWEN_GUI_INPUT_FLAGS_SHOW)
326  fprintf(stderr, "%c", chr);
327  else
328  fprintf(stderr, "*");
329  buffer[pos++]=chr;
330  buffer[pos]=0;
331  }
332  }
333  }
334  else {
335  /* buffer full */
336  fprintf(stderr, "\007");
337  }
338  }
339  } /* for */
340 
341 #ifdef HAVE_TERMIOS_H
342  /* re-enable echo (if previously disabled) */
343  if (AttrOutChanged)
344  tcsetattr (fileno (stderr), TCSADRAIN, &OldOutAttr);
345  if (AttrInChanged)
346  tcsetattr (fileno (stdin), TCSADRAIN, &OldInAttr);
347 #endif
348 
349 #if HAVE_DECL_SIGPROCMASK
350  sigprocmask(SIG_BLOCK, &sold, 0);
351 #endif
352  return rv;
353 }
354 
355 
356 
358  uint32_t flags,
359  const char *title,
360  const char *text,
361  const char *b1,
362  const char *b2,
363  const char *b3,
364  GWEN_UNUSED uint32_t guiid) {
365  GWEN_GUI_CGUI *cgui;
366  GWEN_BUFFER *tbuf;
367  int c;
368 
369  assert(gui);
370  cgui=GWEN_INHERIT_GETDATA(GWEN_GUI, GWEN_GUI_CGUI, gui);
371  assert(cgui);
372 
373  tbuf=GWEN_Buffer_new(0, 256, 0, 1);
374  GWEN_Gui_GetRawText(gui, text, tbuf);
375 
378  fprintf(stderr,
379  "Got the following dangerous message:\n%s\n",
380  GWEN_Buffer_GetStart(tbuf));
381  GWEN_Buffer_free(tbuf);
382  return 0;
383  }
384  else {
386  "Auto-answering the following message with %d:\n%s",
388  GWEN_Buffer_GetStart(tbuf));
389  GWEN_Buffer_free(tbuf);
390  return GWEN_GUI_MSG_FLAGS_CONFIRM_BUTTON(flags);
391  }
392  }
393 
394  fprintf(stderr, "===== %s =====\n", title);
395  fprintf(stderr, "%s\n", GWEN_Buffer_GetStart(tbuf));
396  GWEN_Buffer_free(tbuf);
397  tbuf=0;
398 
399  if (b1) {
400  fprintf(stderr, "(1) %s", b1);
401  if (b2) {
402  fprintf(stderr, " (2) %s", b2);
403  if (b3) {
404  fprintf(stderr, " (3) %s", b3);
405  }
406  }
407  fprintf(stderr, "\n");
408  }
409  fprintf(stderr, "Please enter your choice: ");
410  for(;;) {
412  if (c==EOF) {
413  fprintf(stderr, "Aborted.\n");
415  }
416  if (!b1 && c==13)
417  return 0;
418  if (c=='1' && b1) {
419  fprintf(stderr, "1\n");
420  return 1;
421  }
422  else if (c=='2' && b2) {
423  fprintf(stderr, "2\n");
424  return 2;
425  }
426  else if (c=='3' && b3) {
427  fprintf(stderr, "3\n");
428  return 3;
429  }
430  else {
431  fprintf(stderr, "%c", 7);
432  }
433  } /* for */
434 
435 }
436 
437 
438 
440  uint32_t flags,
441  const char *title,
442  const char *text,
443  char *buffer,
444  int minLen,
445  int maxLen,
446  uint32_t guiid) {
447  int rv;
448  GWEN_BUFFER *tbuf;
449 
450  assert(gui);
451  tbuf=GWEN_Buffer_new(0, 256, 0, 1);
452  GWEN_Gui_GetRawText(gui, text, tbuf);
453 
454  fprintf(stderr, "===== %s =====\n", title);
455  fprintf(stderr, "%s\n", GWEN_Buffer_GetStart(tbuf));
456  GWEN_Buffer_free(tbuf);
457  tbuf=0;
458 
459  if (flags & GWEN_GUI_INPUT_FLAGS_CONFIRM) {
460  for (;;) {
461  char *lbuffer=0;
462 
463  lbuffer=(char*)malloc(maxLen);
464  if (!lbuffer) {
465  DBG_ERROR(GWEN_LOGDOMAIN, "Not enough memory for %d bytes", maxLen);
466  return GWEN_ERROR_INVALID;
467  }
468  fprintf(stderr, "Input: ");
469  rv=GWEN_Gui_CGui__input(gui, flags, lbuffer, minLen, maxLen, guiid);
470  if (rv) {
471  free(lbuffer);
472  return rv;
473  }
474 
475  fprintf(stderr, "Again: ");
476  rv=GWEN_Gui_CGui__input(gui, flags, buffer, minLen, maxLen, guiid);
477  if (rv) {
478  free(lbuffer);
479  return rv;
480  }
481  if (strcmp(lbuffer, buffer)!=0) {
482  fprintf(stderr,
483  "ERROR: Entries do not match, please try (again or abort)\n");
484  }
485  else {
486  rv=0;
487  break;
488  }
489 
490  } /* for */
491  }
492  else {
493  fprintf(stderr, "Input: ");
494  rv=GWEN_Gui_CGui__input(gui, flags, buffer, minLen, maxLen, guiid);
495  }
496 
497  if ((rv==0) && (GWEN_Gui_GetFlags(gui) & GWEN_CGUI_FLAGS_PERMPASSWORDS))
498  return 1;
499  return rv;
500 }
501 
502 
503 
505  GWEN_UNUSED uint32_t flags,
506  const char *title,
507  const char *text,
508  GWEN_UNUSED uint32_t guiid) {
509  GWEN_GUI_CGUI *cgui;
510  GWEN_BUFFER *tbuf;
511 
512  assert(gui);
513  cgui=GWEN_INHERIT_GETDATA(GWEN_GUI, GWEN_GUI_CGUI, gui);
514  assert(cgui);
515 
516  tbuf=GWEN_Buffer_new(0, 256, 0, 1);
517  GWEN_Gui_GetRawText(gui, text, tbuf);
518 
519  fprintf(stderr, "----- %s -----\n", title);
520  fprintf(stderr, "%s\n", GWEN_Buffer_GetStart(tbuf));
521  GWEN_Buffer_free(tbuf);
522  tbuf=0;
523 
524  return ++(cgui->nextBoxId);
525 }
526 
527 
528 
529 void GWEN_Gui_CGui_HideBox(GWEN_GUI *gui, GWEN_UNUSED uint32_t id) {
530  GWEN_GUI_CGUI *cgui;
531 
532  assert(gui);
533  cgui=GWEN_INHERIT_GETDATA(GWEN_GUI, GWEN_GUI_CGUI, gui);
534  assert(cgui);
535 
536  /* nothing to do right now */
537 }
538 
539 
540 
542  uint32_t progressFlags,
543  const char *title,
544  const char *text,
545  uint64_t total,
546  GWEN_UNUSED uint32_t guiid) {
547  GWEN_GUI_CGUI *cgui;
548  GWEN_GUI_CPROGRESS *cp;
549 
550  assert(gui);
551  cgui=GWEN_INHERIT_GETDATA(GWEN_GUI, GWEN_GUI_CGUI, gui);
552  assert(cgui);
553 
554  cp=GWEN_Gui_CProgress_new(gui,
555  ++(cgui->nextProgressId),
556  progressFlags,
557  title,
558  text,
559  total);
560  GWEN_Gui_CProgress_List_Insert(cp, cgui->progressList);
561  return GWEN_Gui_CProgress_GetId(cp);
562 }
563 
564 
565 
567  GWEN_GUI_CGUI *cgui;
568  GWEN_GUI_CPROGRESS *cp;
569 
570  assert(gui);
571  cgui=GWEN_INHERIT_GETDATA(GWEN_GUI, GWEN_GUI_CGUI, gui);
572  assert(cgui);
573 
574  cp=GWEN_Gui_CProgress_List_First(cgui->progressList);
575  if (id==0)
576  return cp;
577  while(cp) {
578  if (GWEN_Gui_CProgress_GetId(cp)==id)
579  break;
580  cp=GWEN_Gui_CProgress_List_Next(cp);
581  } /* while */
582 
583  return cp;
584 }
585 
586 
587 
589  uint32_t id,
590  uint64_t progress) {
591  GWEN_GUI_CGUI *cgui;
592  GWEN_GUI_CPROGRESS *cp;
593 
594  assert(gui);
595  cgui=GWEN_INHERIT_GETDATA(GWEN_GUI, GWEN_GUI_CGUI, gui);
596  assert(cgui);
597 
598  cp=GWEN_Gui_CGui__findProgress(gui, id);
599  if (!cp) {
600  DBG_DEBUG(GWEN_LOGDOMAIN, "Progress object %u not found", id);
601  return 0;
602  }
603  else {
604  return GWEN_Gui_CProgress_Advance(cp, progress);
605  }
606 }
607 
608 
609 
610 int GWEN_Gui_CGui_ProgressSetTotal(GWEN_GUI *gui, uint32_t id, uint64_t total) {
611  GWEN_GUI_CGUI *cgui;
612  GWEN_GUI_CPROGRESS *cp;
613 
614  assert(gui);
615  cgui=GWEN_INHERIT_GETDATA(GWEN_GUI, GWEN_GUI_CGUI, gui);
616  assert(cgui);
617 
618  cp=GWEN_Gui_CGui__findProgress(gui, id);
619  if (!cp) {
620  DBG_DEBUG(GWEN_LOGDOMAIN, "Progress object %u not found", id);
621  }
622  else
623  GWEN_Gui_CProgress_SetTotal(cp, total);
624  return 0;
625 }
626 
627 
628 
630  uint32_t id,
631  GWEN_LOGGER_LEVEL level,
632  const char *text) {
633  GWEN_GUI_CGUI *cgui;
634  GWEN_GUI_CPROGRESS *cp;
635 
636  assert(gui);
637  cgui=GWEN_INHERIT_GETDATA(GWEN_GUI, GWEN_GUI_CGUI, gui);
638  assert(cgui);
639 
640  cp=GWEN_Gui_CGui__findProgress(gui, id);
641  if (!cp) {
642  DBG_DEBUG(GWEN_LOGDOMAIN, "Progress object %u not found", id);
643  return 0;
644  }
645  else {
646  return GWEN_Gui_CProgress_Log(cp, level, text);
647  }
648 }
649 
650 
651 
652 int GWEN_Gui_CGui_ProgressEnd(GWEN_GUI *gui,uint32_t id) {
653  GWEN_GUI_CGUI *cgui;
654  GWEN_GUI_CPROGRESS *cp;
655 
656  assert(gui);
657  cgui=GWEN_INHERIT_GETDATA(GWEN_GUI, GWEN_GUI_CGUI, gui);
658  assert(cgui);
659 
660  cp=GWEN_Gui_CGui__findProgress(gui, id);
661  if (!cp) {
662  DBG_DEBUG(GWEN_LOGDOMAIN, "Progress object %u not found", id);
663  return 0;
664  }
665  else {
666  int rv;
667 
668  rv=GWEN_Gui_CProgress_End(cp);
669  GWEN_Gui_CProgress_List_Del(cp);
671  return rv;
672  }
673 }
674 
675 
676 
678  GWEN_UNUSED const char *docTitle,
679  GWEN_UNUSED const char *docType,
680  GWEN_UNUSED const char *descr,
681  GWEN_UNUSED const char *text,
682  GWEN_UNUSED uint32_t guiid) {
684 }
685 
686 
687 
688 int GWEN_Gui_CGui__HashPair(const char *token,
689  const char *pin,
690  GWEN_BUFFER *buf) {
691  GWEN_MDIGEST *md;
692  int rv;
693 
694  /* hash token and pin */
696  rv=GWEN_MDigest_Begin(md);
697  if (rv==0)
698  rv=GWEN_MDigest_Update(md, (const uint8_t*)token, strlen(token));
699  if (rv==0)
700  rv=GWEN_MDigest_Update(md, (const uint8_t*)pin, strlen(pin));
701  if (rv==0)
702  rv=GWEN_MDigest_End(md);
703  if (rv<0) {
704  DBG_ERROR(GWEN_LOGDOMAIN, "Hash error (%d)", rv);
705  GWEN_MDigest_free(md);
706  return rv;
707  }
708 
711  buf,
712  0, 0, 0);
713  GWEN_MDigest_free(md);
714  return 0;
715 }
716 
717 
718 
720  const GWEN_SSLCERTDESCR *cd,
721  GWEN_SYNCIO *sio, uint32_t guiid) {
722  GWEN_GUI_CGUI *cgui;
723  const char *hash;
724  const char *status;
725  GWEN_BUFFER *hbuf;
726  int i;
727 
728  assert(gui);
729  cgui=GWEN_INHERIT_GETDATA(GWEN_GUI, GWEN_GUI_CGUI, gui);
730  assert(cgui);
731 
734 
735  hbuf=GWEN_Buffer_new(0, 64, 0, 1);
736  GWEN_Gui_CGui__HashPair(hash, status, hbuf);
737 
738  i=GWEN_DB_GetIntValue(cgui->dbCerts, GWEN_Buffer_GetStart(hbuf), 0, 1);
739  if (i==0) {
741  "Automatically accepting certificate [%s]",
742  hash);
743  GWEN_Buffer_free(hbuf);
744  return 0;
745  }
746 
748  uint32_t fl;
749 
753  "Automatically accepting valid new certificate [%s]",
754  hash);
755  GWEN_Buffer_free(hbuf);
756  return 0;
757  }
758  else {
760  "Automatically rejecting certificate [%s] (noninteractive)",
761  hash);
762  GWEN_Buffer_free(hbuf);
764  }
765  }
766 
767  if (cgui->checkCertFn) {
768  i=cgui->checkCertFn(gui, cd, sio, guiid);
769  if (i==0) {
771  GWEN_Buffer_GetStart(hbuf), i);
772  }
773  GWEN_Buffer_free(hbuf);
774 
775  return i;
776  }
777  else {
778  GWEN_Buffer_free(hbuf);
780  }
781 }
782 
783 
784 
786  GWEN_GUI_CGUI *cgui;
787 
788  assert(gui);
789  cgui=GWEN_INHERIT_GETDATA(GWEN_GUI, GWEN_GUI_CGUI, gui);
790  assert(cgui);
791 
792  GWEN_DB_Group_free(cgui->dbCerts);
793  cgui->dbCerts=dbCerts;
794 }
795 
796 
797 
799  GWEN_GUI_CGUI *cgui;
800 
801  assert(gui);
802  cgui=GWEN_INHERIT_GETDATA(GWEN_GUI, GWEN_GUI_CGUI, gui);
803  assert(cgui);
804 
805  return cgui->dbCerts;
806 }
807 
808