gwenhywfar  4.6.0beta
sar.c
Go to the documentation of this file.
1 /***************************************************************************
2  begin : Wed Jun 22 2011
3  copyright : (C) 2011 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 #ifdef HAVE_CONFIG_H
26 # include <config.h>
27 #endif
28 
29 
30 #include "sar_p.h"
31 #include "gwen_sar_fileheader_l.h"
32 #include "i18n_l.h"
33 
34 #include <gwenhywfar/misc.h>
35 #include <gwenhywfar/debug.h>
36 #include <gwenhywfar/tlv.h>
37 #include <gwenhywfar/gui.h>
38 #include <gwenhywfar/text.h>
39 #include <gwenhywfar/cryptmgrkeys.h>
40 
41 #include <sys/types.h>
42 #include <sys/stat.h>
43 #include <unistd.h>
44 
45 #include <errno.h>
46 #include <string.h>
47 
48 
49 
51  GWEN_SAR *sr;
52 
54  sr->refCount=1;
55 
56  sr->headers=GWEN_SarFileHeader_List_new();
57 
58  return sr;
59 }
60 
61 
62 
64  assert(sr);
65  assert(sr->refCount);
66  sr->refCount++;
67 }
68 
69 
70 
72  if (sr) {
73  assert(sr->refCount);
74  if (sr->refCount==1) {
75  free(sr->archiveName);
76  GWEN_SarFileHeader_List_free(sr->headers);
77  GWEN_SyncIo_free(sr->archiveSio);
78  sr->refCount=0;
79  GWEN_FREE_OBJECT(sr);
80  }
81  else {
82  sr->refCount--;
83  }
84  }
85 }
86 
87 
88 
89 int GWEN_Sar_CreateArchive(GWEN_SAR *sr, const char *aname) {
90  GWEN_SYNCIO *sio;
91  int rv;
92 
93  assert(sr);
94  assert(sr->refCount);
95 
96  assert(aname);
97  if (sr->openMode!=GWEN_Sar_OpenMode_Closed) {
98  DBG_ERROR(GWEN_LOGDOMAIN, "Archive already open");
99  return GWEN_ERROR_OPEN;
100  }
101 
102  free(sr->archiveName);
103  sr->archiveName=strdup(aname);
112  rv=GWEN_SyncIo_Connect(sio);
113  if (rv<0) {
114  DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
115  GWEN_SyncIo_free(sio);
116  return rv;
117  }
118 
119  sr->archiveSio=sio;
120  sr->openMode=GWEN_Sar_OpenMode_Created;
121 
122  sr->signaturePos=0;
123  sr->signatureSize=0;
124 
125  return 0;
126 }
127 
128 
129 
130 int GWEN_Sar_OpenArchive(GWEN_SAR *sr, const char *aname,
132  uint32_t acc) {
133  GWEN_SYNCIO *sio;
134  int rv;
135 
136  assert(sr);
137  assert(sr->refCount);
138 
139  assert(aname);
140  if (sr->openMode!=GWEN_Sar_OpenMode_Closed) {
141  DBG_ERROR(GWEN_LOGDOMAIN, "Archive already open");
142  return GWEN_ERROR_OPEN;
143  }
144 
145  free(sr->archiveName);
146  sr->archiveName=strdup(aname);
147  sio=GWEN_SyncIo_File_new(aname, cm);
148  GWEN_SyncIo_AddFlags(sio, acc);
149  rv=GWEN_SyncIo_Connect(sio);
150  if (rv<0) {
151  DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
152  GWEN_SyncIo_free(sio);
153  return rv;
154  }
155 
156  sr->archiveSio=sio;
157  sr->openMode=GWEN_Sar_OpenMode_Opened;
158 
159  sr->signaturePos=0;
160  sr->signatureSize=0;
161 
162  rv=GWEN_Sar_ScanFile(sr);
163  if (rv<0) {
164  DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
165  sr->archiveSio=NULL;
166  sr->openMode=GWEN_Sar_OpenMode_Closed;
167  GWEN_SyncIo_free(sio);
168  return rv;
169  }
170 
171  return 0;
172 }
173 
174 
175 
176 int GWEN_Sar_CloseArchive(GWEN_SAR *sr, int abandon) {
177  int rv;
178 
179  assert(sr);
180  assert(sr->refCount);
181 
182  if (sr->openMode!=GWEN_Sar_OpenMode_Opened &&
183  sr->openMode!=GWEN_Sar_OpenMode_Created) {
184  DBG_ERROR(GWEN_LOGDOMAIN, "Archive not open");
185  return GWEN_ERROR_NOT_OPEN;
186  }
187 
188  if (!abandon) {
189  /* flush */
190  rv=GWEN_SyncIo_Flush(sr->archiveSio);
191  if (rv<0) {
192  DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
193  GWEN_SyncIo_Disconnect(sr->archiveSio);
194  GWEN_SyncIo_free(sr->archiveSio);
195  sr->archiveSio=NULL;
196  free(sr->archiveName);
197  sr->archiveName=NULL;
198  sr->openMode=GWEN_Sar_OpenMode_Closed;
199  return rv;
200  }
201  }
202 
203  /* disconnect */
204  rv=GWEN_SyncIo_Disconnect(sr->archiveSio);
205  if (rv<0) {
206  DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
207  GWEN_SyncIo_free(sr->archiveSio);
208  sr->archiveSio=NULL;
209  free(sr->archiveName);
210  sr->archiveName=NULL;
211  sr->openMode=GWEN_Sar_OpenMode_Closed;
212  return rv;
213  }
214 
215  GWEN_SyncIo_free(sr->archiveSio);
216  sr->archiveSio=NULL;
217  free(sr->archiveName);
218  sr->archiveName=NULL;
219  sr->openMode=GWEN_Sar_OpenMode_Closed;
220  return 0;
221 }
222 
223 
224 
226  const char *s;
227  uint16_t v8;
228  uint32_t v32;
229  uint64_t v64;
230  uint8_t hbuf[8];
231  const GWEN_TIME *ti;
232  int rv;
233 
234  /* header version */
235  v32=GWEN_SAR_HEADER_VERSION;
236  hbuf[0]=(v32>>24) & 0xff;
237  hbuf[1]=(v32>>16) & 0xff;
238  hbuf[2]=(v32>>8) & 0xff;
239  hbuf[3]=v32 & 0xff;
240  GWEN_TLV_DirectlyToBuffer(GWEN_SAR_TAG_HEADER_VERSION, 0x00, hbuf, 4, 1, tbuf);
241 
242  /* status */
243  v8=GWEN_SarFileHeader_GetStatus(fh) & 0xff;
244  hbuf[0]=v8;
245  GWEN_TLV_DirectlyToBuffer(GWEN_SAR_TAG_HEADER_STATUS, 0x00, hbuf, 1, 1, tbuf);
246 
247  /* flags */
249  hbuf[0]=(v32>>24) & 0xff;
250  hbuf[1]=(v32>>16) & 0xff;
251  hbuf[2]=(v32>>8) & 0xff;
252  hbuf[3]=v32 & 0xff;
253  GWEN_TLV_DirectlyToBuffer(GWEN_SAR_TAG_HEADER_FLAGS, 0x00, hbuf, 4, 1, tbuf);
254 
255  /* path */
257  if (s && *s)
258  GWEN_TLV_DirectlyToBuffer(GWEN_SAR_TAG_HEADER_PATH, 0x00, s, strlen(s)+1, 1, tbuf);
259 
260  /* file type */
261  v8=GWEN_SarFileHeader_GetFileType(fh) & 0xff;
262  hbuf[0]=v8;
263  GWEN_TLV_DirectlyToBuffer(GWEN_SAR_TAG_HEADER_TYPE, 0x00, hbuf, 1, 1, tbuf);
264 
265  /* permissions */
267  hbuf[0]=(v32>>24) & 0xff;
268  hbuf[1]=(v32>>16) & 0xff;
269  hbuf[2]=(v32>>8) & 0xff;
270  hbuf[3]=v32 & 0xff;
271  GWEN_TLV_DirectlyToBuffer(GWEN_SAR_TAG_HEADER_PERM, 0x00, hbuf, 4, 1, tbuf);
272 
273  /* atime */
275  if (ti) {
276  GWEN_BUFFER *xbuf;
277 
278  xbuf=GWEN_Buffer_new(0, 32, 0, 1);
279  rv=GWEN_Time_toUtcString(ti, "YYYYMMDDhhmmss", xbuf);
280  if (rv>=0)
281  GWEN_TLV_DirectlyToBuffer(GWEN_SAR_TAG_HEADER_ATIME, 0x00,
282  GWEN_Buffer_GetStart(xbuf),
284  1,
285  tbuf);
286  GWEN_Buffer_free(xbuf);
287  }
288 
289  /* mtime */
291  if (ti) {
292  GWEN_BUFFER *xbuf;
293 
294  xbuf=GWEN_Buffer_new(0, 32, 0, 1);
295  rv=GWEN_Time_toUtcString(ti, "YYYYMMDDhhmmss", xbuf);
296  if (rv>=0)
297  GWEN_TLV_DirectlyToBuffer(GWEN_SAR_TAG_HEADER_MTIME, 0x00,
298  GWEN_Buffer_GetStart(xbuf),
300  1,
301  tbuf);
302  GWEN_Buffer_free(xbuf);
303  }
304 
305  /* ctime */
307  if (ti) {
308  GWEN_BUFFER *xbuf;
309 
310  xbuf=GWEN_Buffer_new(0, 32, 0, 1);
311  rv=GWEN_Time_toUtcString(ti, "YYYYMMDDhhmmss", xbuf);
312  if (rv>=0)
313  GWEN_TLV_DirectlyToBuffer(GWEN_SAR_TAG_HEADER_CTIME, 0x00,
314  GWEN_Buffer_GetStart(xbuf),
316  1,
317  tbuf);
318  GWEN_Buffer_free(xbuf);
319  }
320 
321  /* file size */
323  hbuf[0]=(v64>>56) & 0xff;
324  hbuf[1]=(v64>>48) & 0xff;
325  hbuf[2]=(v64>>40) & 0xff;
326  hbuf[3]=(v64>>32) & 0xff;
327  hbuf[4]=(v64>>24) & 0xff;
328  hbuf[5]=(v64>>16) & 0xff;
329  hbuf[6]=(v64>>8) & 0xff;
330  hbuf[7]=v64 & 0xff;
331  GWEN_TLV_DirectlyToBuffer(GWEN_SAR_TAG_HEADER_SIZE, 0x00, hbuf, 8, 1, tbuf);
332 
333  return 0;
334 }
335 
336 
337 
338 uint64_t GWEN_Sar_ReadUint64(const uint8_t *p, uint32_t bs) {
339  uint64_t v=0;
340 
341  switch(bs) {
342  case 8:
343  v=(((uint64_t)(p[0]))<<56)+
344  (((uint64_t)(p[1]))<<48)+
345  (((uint64_t)(p[2]))<<40)+
346  (((uint64_t)(p[3]))<<32)+
347  (((uint64_t)(p[4]))<<24)+
348  (((uint64_t)(p[5]))<<16)+
349  (((uint64_t)(p[6]))<<8)+
350  ((uint64_t)(p[7]));
351  break;
352  case 7:
353  v=(((uint64_t)(p[0]))<<48)+
354  (((uint64_t)(p[1]))<<40)+
355  (((uint64_t)(p[2]))<<32)+
356  (((uint64_t)(p[3]))<<24)+
357  (((uint64_t)(p[4]))<<16)+
358  (((uint64_t)(p[5]))<<8)+
359  ((uint64_t)(p[6]));
360  break;
361  case 6:
362  v=(((uint64_t)(p[0]))<<40)+
363  (((uint64_t)(p[1]))<<32)+
364  (((uint64_t)(p[2]))<<24)+
365  (((uint64_t)(p[3]))<<16)+
366  (((uint64_t)(p[4]))<<8)+
367  ((uint64_t)(p[5]));
368  break;
369  case 5:
370  v=(((uint64_t)(p[0]))<<32)+
371  (((uint64_t)(p[1]))<<24)+
372  (((uint64_t)(p[2]))<<16)+
373  (((uint64_t)(p[3]))<<8)+
374  ((uint64_t)(p[4]));
375  break;
376  case 4:
377  v=(((uint64_t)(p[0]))<<24)+
378  (((uint64_t)(p[1]))<<16)+
379  (((uint64_t)(p[2]))<<8)+
380  ((uint64_t)(p[3]));
381  break;
382  case 3:
383  v=(((uint64_t)(p[0]))<<16)+
384  (((uint64_t)(p[1]))<<8)+
385  ((uint64_t)(p[2]));
386  break;
387  case 2:
388  v=(((uint64_t)(p[0]))<<8)+
389  ((uint64_t)(p[1]));
390  break;
391  case 1:
392  v=((uint64_t)(p[0]));
393  break;
394 
395  default:
396  DBG_ERROR(GWEN_LOGDOMAIN, "Unsupported size of %d for uint32", bs);
397  break;
398  }
399 
400  return v;
401 }
402 
403 
404 
406  while(GWEN_Buffer_GetBytesLeft(mbuf)) {
407  GWEN_TLV *tlv;
408 
409  tlv=GWEN_TLV_fromBuffer(mbuf, 1);
410  if (tlv) {
411  const uint8_t *p;
412  uint32_t bs;
413  uint64_t v;
414  GWEN_TIME *ti;
415 
416  p=GWEN_TLV_GetTagData(tlv);
417  bs=GWEN_TLV_GetTagLength(tlv);
418  switch(GWEN_TLV_GetTagType(tlv)) {
419  case GWEN_SAR_TAG_HEADER_VERSION:
420  v=GWEN_Sar_ReadUint64(p, bs);
421  DBG_DEBUG(GWEN_LOGDOMAIN, "File Header Version: %08x", (unsigned int) (v & 0xffffffff));
422  break;
423 
424  case GWEN_SAR_TAG_HEADER_STATUS:
425  v=GWEN_Sar_ReadUint64(p, bs);
426  GWEN_SarFileHeader_SetStatus(fh, v & 0xffffffff);
427  break;
428 
429  case GWEN_SAR_TAG_HEADER_FLAGS:
430  v=GWEN_Sar_ReadUint64(p, bs);
431  GWEN_SarFileHeader_SetFlags(fh, v & 0xffffffff);
432  break;
433 
434  case GWEN_SAR_TAG_HEADER_PATH:
435  GWEN_SarFileHeader_SetPath(fh, (const char*)p);
436  break;
437 
438  case GWEN_SAR_TAG_HEADER_TYPE:
439  v=GWEN_Sar_ReadUint64(p, bs);
440  GWEN_SarFileHeader_SetFileType(fh, v & 0xffffffff);
441  break;
442 
443  case GWEN_SAR_TAG_HEADER_PERM:
444  v=GWEN_Sar_ReadUint64(p, bs);
445  GWEN_SarFileHeader_SetPermissions(fh, v & 0xffffffff);
446  break;
447 
448  case GWEN_SAR_TAG_HEADER_ATIME:
449  ti=GWEN_Time_fromUtcString((const char*) p, "YYYYMMDDhhmmss");
451  break;
452 
453  case GWEN_SAR_TAG_HEADER_MTIME:
454  ti=GWEN_Time_fromUtcString((const char*) p, "YYYYMMDDhhmmss");
456  break;
457 
458  case GWEN_SAR_TAG_HEADER_CTIME:
459  ti=GWEN_Time_fromUtcString((const char*) p, "YYYYMMDDhhmmss");
461  break;
462 
463  case GWEN_SAR_TAG_HEADER_SIZE:
464  v=GWEN_Sar_ReadUint64(p, bs);
466  break;
467  default:
468  DBG_WARN(GWEN_LOGDOMAIN, "Ignoring unknown tag %d", GWEN_TLV_GetTagType(tlv));
469  break;
470  }
471 
472  }
473  else {
474  DBG_ERROR(GWEN_LOGDOMAIN, "No TLV in buffer");
475  return GWEN_ERROR_BAD_DATA;
476  }
477  }
478  return 0;
479 }
480 
481 
482 
484  int rv;
485  const char *fname;
486  uint64_t fsize;
487  uint64_t bytesDone;
488  GWEN_BUFFER *hbuf;
489 
490  assert(sr);
491  assert(sr->refCount);
492 
493  fname=GWEN_SarFileHeader_GetPath(fh);
494  assert(fname);
496 
497  /* create TLV header */
498  hbuf=GWEN_Buffer_new(0, 32, 0, 1);
499  rv=GWEN_TLV_WriteHeader(GWEN_SAR_TAG_FILE, 0x00, fsize, 1, hbuf);
500  if (rv<0) {
501  DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
502  GWEN_Buffer_free(hbuf);
503  return rv;
504  }
505 
506  /* write TLV header */
507  rv=GWEN_SyncIo_WriteForced(sr->archiveSio,
508  (const uint8_t*) GWEN_Buffer_GetStart(hbuf),
510  if (rv<0) {
511  DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
512  GWEN_Buffer_free(hbuf);
513  return rv;
514  }
515 
516  GWEN_Buffer_free(hbuf);
517 
518  /* copy file if fsize>0 */
519  if (fsize>0) {
520  GWEN_SYNCIO *sio;
521  uint32_t pid;
522 
523  /* open input file */
526  rv=GWEN_SyncIo_Connect(sio);
527  if (rv<0) {
528  DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
529  GWEN_SyncIo_free(sio);
530  return rv;
531  }
532 
537  I18N("File Operation"),
538  I18N("Copying file into archive"),
539  fsize,
540  0);
541  bytesDone=0;
542  while(fsize) {
543  uint8_t fbuf[10240];
544  uint64_t bs;
545 
546  bs=fsize;
547  if (bs>sizeof(fbuf))
548  bs=sizeof(fbuf);
549 
550  /* read from input */
551  rv=GWEN_SyncIo_Read(sio, fbuf, bs);
552  if (rv<0) {
553  DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
556  GWEN_SyncIo_free(sio);
557  return rv;
558  }
559  bs=rv;
560 
561  /* digest data */
562  rv=GWEN_MDigest_Update(md, fbuf, bs);
563  if (rv<0) {
564  DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
567  GWEN_SyncIo_free(sio);
568  return rv;
569  }
570 
571  /* write to archive */
572  rv=GWEN_SyncIo_WriteForced(sr->archiveSio, fbuf, bs);
573  if (rv<0) {
574  DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
577  GWEN_SyncIo_free(sio);
578  return rv;
579  }
580 
581  if (bs>fsize) {
582  DBG_ERROR(GWEN_LOGDOMAIN, "Internal error: bs>fsize (%lu>%lu)",
583  (unsigned long int)bs, (unsigned long int) fsize);
586  GWEN_SyncIo_free(sio);
587  return rv;
588  }
589 
590  bytesDone+=bs;
591  fsize-=bs;
592 
593  /* advance progress bar */
594  rv=GWEN_Gui_ProgressAdvance(pid, bytesDone);
595  if (rv<0) {
596  DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
599  GWEN_SyncIo_free(sio);
600  return rv;
601  }
602 
603  } /* while */
605 
606  /* close input file */
608  GWEN_SyncIo_free(sio);
609  }
610 
611  return 0;
612 }
613 
614 
615 
617 #if _BSD_SOURCE || _XOPEN_SOURCE >= 500 || (_XOPEN_SOURCE && _XOPEN_SOURCE_EXTENDED) || _POSIX_C_SOURCE >= 200112L || defined(OS_DARWIN)
618  int rv;
619  const char *fname;
620  GWEN_BUFFER *hbuf;
621  char lbuf[300];
622  int len;
623 
624  assert(sr);
625  assert(sr->refCount);
626 
627  fname=GWEN_SarFileHeader_GetPath(fh);
628  assert(fname);
629 
630  /* read link content */
631  rv=readlink(fname, lbuf, sizeof(lbuf)-1);
632  if (rv<0) {
633  DBG_ERROR(GWEN_LOGDOMAIN, "readlink(%s): %d (%s)",
634  fname, errno, strerror(errno));
635  return GWEN_ERROR_IO;
636  }
637  len=rv;
638  lbuf[len]=0;
639 
640  /* create TLV header */
641  hbuf=GWEN_Buffer_new(0, rv+8, 0, 1);
642  GWEN_TLV_DirectlyToBuffer(GWEN_SAR_TAG_FILE, 0x00,
643  lbuf, len+1,
644  1, hbuf);
645 
646 
647  /* write TLV */
648  rv=GWEN_SyncIo_WriteForced(sr->archiveSio,
649  (const uint8_t*) GWEN_Buffer_GetStart(hbuf),
651  if (rv<0) {
652  DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
653  GWEN_Buffer_free(hbuf);
654  return rv;
655  }
656  GWEN_Buffer_free(hbuf);
657 
658  /* digest data */
659  rv=GWEN_MDigest_Update(md, (const uint8_t*) lbuf, len+1);
660  if (rv<0) {
661  DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
662  return rv;
663  }
664 
665  return 0;
666 #else
667 # warning "Function readlink() is not available"
668  DBG_ERROR(GWEN_LOGDOMAIN, "Function readlink() is not available");
669  return GWEN_ERROR_IO;
670 #endif
671 }
672 
673 
674 
676  int rv;
677 
678  switch(GWEN_SarFileHeader_GetFileType(fh)) {
680  rv=GWEN_Sar_AddAndDigestFileReg(sr, fh, md);
681  break;
683  rv=0;
684  break;
686  rv=GWEN_Sar_AddAndDigestFileLink(sr, fh, md);
687  break;
688  default:
689  DBG_ERROR(GWEN_LOGDOMAIN, "File type %d not supported", GWEN_SarFileHeader_GetFileType(fh));
690  return GWEN_ERROR_INVALID;
691  }
692 
693  if (rv<0) {
694  DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
695  return rv;
696  }
697 
698  return 0;
699 }
700 
701 
702 
703 int GWEN_Sar_AddFile(GWEN_SAR *sr, const char *fname) {
704  struct stat st;
705  int rv;
707  GWEN_TIME *ti;
708  GWEN_BUFFER *hbuf;
709  GWEN_BUFFER *xbuf;
710  GWEN_MDIGEST *md;
711  uint64_t pos;
712 
713  assert(sr);
714  assert(sr->refCount);
715 
716  /* stat file to be added */
717 #if _BSD_SOURCE || _XOPEN_SOURCE >= 500 || _XOPEN_SOURCE && _XOPEN_SOURCE_EXTENDED
718  rv=lstat(fname, &st);
719 #else
720  rv=stat(fname, &st);
721 #endif
722  if (rv) {
723  DBG_ERROR(GWEN_LOGDOMAIN, "stat(%s): %d (%s)",
724  fname, errno, strerror(errno));
725  return GWEN_ERROR_IO;
726  }
727 
728  /* create and setup file header */
730 
731  /* path */
732  GWEN_SarFileHeader_SetPath(fh, fname);
733 
734  /* file type */
735  switch(st.st_mode & S_IFMT) {
736 #ifdef S_IFLNK
737  case S_IFLNK:
739  break;
740 #endif
741  case S_IFREG:
743  break;
744  case S_IFDIR:
746  break;
747  default:
749  return GWEN_ERROR_INVALID;
750  }
751 
752  /* permissions */
756 
757 #ifdef S_IRGRP
759 #endif
760 #ifdef S_IWGRP
762 #endif
763 #ifdef S_IXGRP
765 #endif
766 
767 #ifdef S_IROTH
769 #endif
770 #ifdef S_IWOTH
772 #endif
773 #ifdef S_IXOTH
775 #endif
776 
777  /* atime */
778  ti=GWEN_Time_fromSeconds(st.st_atime);
780 
781  /* mtime */
782  ti=GWEN_Time_fromSeconds(st.st_mtime);
784 
785  /* ctime */
786  ti=GWEN_Time_fromSeconds(st.st_ctime);
788 
789  /* file size */
790  GWEN_SarFileHeader_SetFileSize(fh, st.st_size);
791 
792 
793  /* prepare header */
794  hbuf=GWEN_Buffer_new(0, 256, 0, 1);
795  GWEN_Buffer_ReserveBytes(hbuf, 16);
796  rv=GWEN_Sar_FileHeaderToTlv(fh, hbuf);
797  if (rv<0) {
798  DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
799  GWEN_Buffer_free(hbuf);
801  return rv;
802  }
803 
804  /* create TLV header for file header */
805  xbuf=GWEN_Buffer_new(0, 16, 0, 1);
806  rv=GWEN_TLV_WriteHeader(GWEN_SAR_TAG_HEADER, 0xe0,
807  GWEN_Buffer_GetUsedBytes(hbuf), 1, xbuf);
808  if (rv<0) {
809  DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
810  GWEN_Buffer_free(xbuf);
811  GWEN_Buffer_free(hbuf);
813  return rv;
814  }
815 
816  /* insert TLV header into file header buffer */
817  GWEN_Buffer_SetPos(hbuf, 0);
819  GWEN_Buffer_GetStart(xbuf),
822  GWEN_Buffer_free(xbuf);
823 
824  /* seek to end of file */
825  pos=GWEN_SyncIo_File_Seek(sr->archiveSio, 0, GWEN_SyncIo_File_Whence_End);
826  if (pos<0) {
827  DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", (int) pos);
828  GWEN_Buffer_free(hbuf);
830  return (int) pos;
831  }
832 
833  /* write header into archive file */
834  rv=GWEN_SyncIo_WriteForced(sr->archiveSio,
835  (const uint8_t*) GWEN_Buffer_GetStart(hbuf),
837  if (rv<0) {
838  DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
839  GWEN_Buffer_free(hbuf);
841  return rv;
842  }
843 
844  /* prepare digest */
846  rv=GWEN_MDigest_Begin(md);
847  if (rv<0) {
848  DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
849  GWEN_MDigest_free(md);
850  GWEN_Buffer_free(hbuf);
852  return rv;
853  }
854 
855  /* digest header */
856  rv=GWEN_MDigest_Update(md, (const uint8_t*) GWEN_Buffer_GetStart(hbuf), GWEN_Buffer_GetUsedBytes(hbuf));
857  if (rv<0) {
858  DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
859  GWEN_MDigest_free(md);
860  GWEN_Buffer_free(hbuf);
862  return rv;
863  }
864 
865  GWEN_Buffer_Reset(hbuf);
866 
867  /* copy file into archive */
868  rv=GWEN_Sar_AddAndDigestFile(sr, fh, md);
869  if (rv<0) {
870  DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
871  GWEN_MDigest_free(md);
872  GWEN_Buffer_free(hbuf);
874  return rv;
875  }
876 
877  /* finish hash */
878  rv=GWEN_MDigest_End(md);
879  if (rv<0) {
880  DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
881  GWEN_MDigest_free(md);
882  GWEN_Buffer_free(hbuf);
884  return rv;
885  }
886 
887  /* create hash TLV */
888  GWEN_TLV_DirectlyToBuffer(GWEN_SAR_TAG_HASH, 0x00,
891  1, hbuf);
892  GWEN_MDigest_free(md);
893 
894  /* write hash into archive file */
895  rv=GWEN_SyncIo_WriteForced(sr->archiveSio,
896  (const uint8_t*) GWEN_Buffer_GetStart(hbuf),
898  if (rv<0) {
899  DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
900  GWEN_Buffer_free(hbuf);
902  return rv;
903  }
904 
905  /* done */
906  GWEN_Buffer_free(hbuf);
908  return 0;
909 }
910 
911 
912 
913 
915  int rv;
916  int64_t pos;
917  GWEN_BUFFER *mbuf;
918  GWEN_SAR_FILEHEADER *lastHeader=NULL;
919 
920  assert(sr);
921  assert(sr->refCount);
922 
923  sr->signaturePos=0;
924  sr->signatureSize=0;
925 
926  /* scan all TLV elements */
927  pos=0;
928  mbuf=GWEN_Buffer_new(0, 1024, 0, 1);
929  for (;;) {
930  int64_t startOfTagHeader;
931  int64_t startOfTagData;
932  unsigned int tagType;
933  uint32_t tagLength;
934  uint32_t fullTagSize;
935  uint32_t bs;
936  GWEN_TLV *tlv;
937  uint8_t buffer[32];
938 
939  startOfTagHeader=pos;
940  rv=GWEN_SyncIo_Read(sr->archiveSio, buffer, sizeof(buffer));
941  if (rv<0) {
942  if (rv==GWEN_ERROR_EOF)
943  break;
944  DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
945  GWEN_Buffer_free(mbuf);
946  return rv;
947  }
948  else if (rv==0) {
949  DBG_VERBOUS(GWEN_LOGDOMAIN, "EOF met");
950  break;
951  }
952  bs=rv;
953 
954  /* read start of fileheader TLV */
955  tlv=GWEN_TLV_new();
956  rv=GWEN_TLV_ReadHeader(tlv, buffer, bs, 1);
957  if (rv<2) {
958  DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
959  GWEN_TLV_free(tlv);
960  GWEN_Buffer_free(mbuf);
961  return rv;
962  }
963  /* got it, now calculate start of tag data */
964  startOfTagData=pos+rv;
965  tagLength=GWEN_TLV_GetTagLength(tlv);
966  tagType=GWEN_TLV_GetTagType(tlv);
967  fullTagSize=GWEN_TLV_GetTagSize(tlv);
968  GWEN_TLV_free(tlv);
969 
970  /* seek to start of header data */
971  pos=GWEN_SyncIo_File_Seek(sr->archiveSio, startOfTagData, GWEN_SyncIo_File_Whence_Set);
972  if (pos<0) {
973  DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", (int) pos);
974  GWEN_Buffer_free(mbuf);
975  return (int) pos;
976  }
977 
978  /* now read or skip info */
979  if (tagType==GWEN_SAR_TAG_HEADER) {
981  const char *s;
982 
983  /* alloc memory for data */
984  GWEN_Buffer_AllocRoom(mbuf, tagLength);
985 
986  /* read header data */
987  rv=GWEN_SyncIo_ReadForced(sr->archiveSio, (uint8_t*) GWEN_Buffer_GetStart(mbuf), tagLength);
988  if (rv<0) {
989  DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
990  GWEN_Buffer_free(mbuf);
991  return rv;
992  }
993  GWEN_Buffer_IncrementPos(mbuf, tagLength);
995  GWEN_Buffer_Rewind(mbuf);
996 
997  /* now parse header */
999  rv=GWEN_Sar_TlvToFileHeader(mbuf, fh);
1000  if (rv<0) {
1001  DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
1003  GWEN_Buffer_free(mbuf);
1004  return rv;
1005  }
1006 
1007  GWEN_SarFileHeader_SetHeaderStartPos(fh, startOfTagHeader);
1008  GWEN_SarFileHeader_SetHeaderSize(fh, fullTagSize);
1009 
1011  DBG_DEBUG(GWEN_LOGDOMAIN, "Got entry [%s]", s?s:"(empty)");
1012 
1013  GWEN_SarFileHeader_List_Add(fh, sr->headers);
1014  lastHeader=fh;
1015  }
1016  else if (tagType==GWEN_SAR_TAG_FILE) {
1017  if (lastHeader==NULL) {
1018  DBG_ERROR(GWEN_LOGDOMAIN, "Bad file structure: No file header before data");
1019  GWEN_Buffer_free(mbuf);
1020  return GWEN_ERROR_BAD_DATA;
1021  }
1023  GWEN_SarFileHeader_GetFileSize(lastHeader)!=tagLength) {
1024  DBG_ERROR(GWEN_LOGDOMAIN, "File size in header and in archive differ (%s: hs=%lu, ts=%lu)",
1025  GWEN_SarFileHeader_GetPath(lastHeader),
1026  (unsigned long int) GWEN_SarFileHeader_GetFileSize(lastHeader),
1027  (unsigned long int) tagLength);
1028  GWEN_Buffer_free(mbuf);
1029  return GWEN_ERROR_BAD_DATA;
1030  }
1031  /* only store position of file data */
1032  GWEN_SarFileHeader_SetDataPos(lastHeader, startOfTagData);
1033  GWEN_SarFileHeader_SetDataSize(lastHeader, tagLength);
1034 
1035  /* skip data */
1036  pos=GWEN_SyncIo_File_Seek(sr->archiveSio, tagLength, GWEN_SyncIo_File_Whence_Current);
1037  if (pos<0) {
1038  DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", (int) pos);
1039  GWEN_Buffer_free(mbuf);
1040  return (int) pos;
1041  }
1042  }
1043  else if (tagType==GWEN_SAR_TAG_HASH) {
1044  if (lastHeader==NULL) {
1045  DBG_ERROR(GWEN_LOGDOMAIN, "Bad file structure: No file header before data");
1046  GWEN_Buffer_free(mbuf);
1047  return GWEN_ERROR_BAD_DATA;
1048  }
1049  /* only store position of file data */
1050  GWEN_SarFileHeader_SetHashPos(lastHeader, startOfTagData);
1051 
1052  /* skip data */
1053  pos=GWEN_SyncIo_File_Seek(sr->archiveSio, tagLength, GWEN_SyncIo_File_Whence_Current);
1054  if (pos<0) {
1055  DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", (int) pos);
1056  GWEN_Buffer_free(mbuf);
1057  return (int) pos;
1058  }
1059  }
1060  else if (tagType==GWEN_SAR_TAG_SIGNATURE) {
1061  /* only store position of file data */
1062  DBG_INFO(GWEN_LOGDOMAIN, "Signature found");
1063  sr->signaturePos=startOfTagData;
1064  sr->signatureSize=tagLength;
1065 
1066  /* skip data */
1067  pos=GWEN_SyncIo_File_Seek(sr->archiveSio, tagLength, GWEN_SyncIo_File_Whence_Current);
1068  if (pos<0) {
1069  DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", (int) pos);
1070  GWEN_Buffer_free(mbuf);
1071  return (int) pos;
1072  }
1073  }
1074  else {
1075  DBG_WARN(GWEN_LOGDOMAIN, "Unknown TAG %d, ignoring", (int) tagType);
1076  /* just skip data */
1077  pos=GWEN_SyncIo_File_Seek(sr->archiveSio, tagLength, GWEN_SyncIo_File_Whence_Current);
1078  if (pos<0) {
1079  DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", (int) pos);
1080  GWEN_Buffer_free(mbuf);
1081  return (int) pos;
1082  }
1083  }
1084 
1085  GWEN_Buffer_Reset(mbuf);
1086  pos=startOfTagData+tagLength;
1087  } /* for */
1088 
1089  /* done */
1090  GWEN_Buffer_free(mbuf);
1091  return 0;
1092 }
1093 
1094 
1095 
1097  int rv;
1098  const char *fname;
1099  uint32_t perms;
1100  uint64_t dpos;
1101  uint64_t fsize;
1102  uint64_t bytesDone;
1103  uint64_t hsize;
1104  uint64_t hpos;
1105  uint64_t mpos;
1106  uint64_t pos;
1107  GWEN_MDIGEST *md;
1108 
1109  assert(sr);
1110  assert(sr->refCount);
1111 
1113  rv=GWEN_MDigest_Begin(md);
1114  if (rv<0) {
1115  DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
1116  GWEN_MDigest_free(md);
1117  return rv;
1118  }
1119 
1120  fname=GWEN_SarFileHeader_GetPath(fh);
1121  assert(fname);
1125 
1128  if (hsize>0) {
1129  GWEN_BUFFER *mbuf;
1130 
1131  /* seek to start of header */
1132  pos=GWEN_SyncIo_File_Seek(sr->archiveSio, hpos, GWEN_SyncIo_File_Whence_Set);
1133  if (pos<0) {
1134  DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", (int) pos);
1135  GWEN_MDigest_free(md);
1136  return (int) pos;
1137  }
1138 
1139  mbuf=GWEN_Buffer_new(0, hsize, 0, 1);
1140  rv=GWEN_SyncIo_ReadForced(sr->archiveSio,
1141  (uint8_t*) GWEN_Buffer_GetStart(mbuf),
1142  hsize);
1143  if (rv<0) {
1144  DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
1145  GWEN_Buffer_free(mbuf);
1146  GWEN_MDigest_free(md);
1147  return rv;
1148  }
1149  GWEN_Buffer_IncrementPos(mbuf, hsize);
1151 
1152  /* digest TLV */
1153  rv=GWEN_MDigest_Update(md, (const uint8_t*) GWEN_Buffer_GetStart(mbuf), GWEN_Buffer_GetUsedBytes(mbuf));
1154  if (rv<0) {
1155  DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
1156  GWEN_Buffer_free(mbuf);
1157  GWEN_MDigest_free(md);
1158  return rv;
1159  }
1160  GWEN_Buffer_free(mbuf);
1161  }
1162 
1163  /* copy file if fsize>0 */
1164  if (1) {
1165  GWEN_SYNCIO *sio=NULL;
1166  uint32_t pid;
1167 
1168  /* open input file */
1169  if (!checkOnly) {
1172  GWEN_SyncIo_AddFlags(sio, perms);
1173  rv=GWEN_SyncIo_Connect(sio);
1174  if (rv<0) {
1175  DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
1176  GWEN_SyncIo_free(sio);
1177  GWEN_MDigest_free(md);
1178  return rv;
1179  }
1180  }
1181 
1182  if (fsize>0) {
1183  /* seek to start of data */
1184  pos=GWEN_SyncIo_File_Seek(sr->archiveSio, dpos, GWEN_SyncIo_File_Whence_Set);
1185  if (pos<0) {
1186  DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", (int) pos);
1187  if (!checkOnly) {
1189  GWEN_SyncIo_free(sio);
1190  }
1191  GWEN_MDigest_free(md);
1192  return (int) pos;
1193  }
1194 
1195  /* start extracting */
1200  I18N("File Operation"),
1201  I18N("Extracting file from archive"),
1202  fsize,
1203  0);
1204  bytesDone=0;
1205  while(fsize) {
1206  uint8_t fbuf[10240];
1207  uint64_t bs;
1208 
1209  bs=fsize;
1210  if (bs>sizeof(fbuf))
1211  bs=sizeof(fbuf);
1212 
1213  /* read from input */
1214  rv=GWEN_SyncIo_Read(sr->archiveSio, fbuf, bs);
1215  if (rv<0) {
1216  DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
1217  GWEN_Gui_ProgressEnd(pid);
1218  if (!checkOnly) {
1220  GWEN_SyncIo_free(sio);
1221  }
1222  GWEN_MDigest_free(md);
1223  return rv;
1224  }
1225  bs=rv;
1226 
1227  /* digest data */
1228  rv=GWEN_MDigest_Update(md, fbuf, bs);
1229  if (rv<0) {
1230  DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
1231  GWEN_Gui_ProgressEnd(pid);
1232  if (!checkOnly) {
1234  GWEN_SyncIo_free(sio);
1235  }
1236  GWEN_MDigest_free(md);
1237  return rv;
1238  }
1239 
1240  if (!checkOnly) {
1241  /* write to archive */
1242  rv=GWEN_SyncIo_WriteForced(sio, fbuf, bs);
1243  if (rv<0) {
1244  DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
1245  GWEN_Gui_ProgressEnd(pid);
1246  if (!checkOnly) {
1248  GWEN_SyncIo_free(sio);
1249  }
1250  GWEN_MDigest_free(md);
1251  return rv;
1252  }
1253  }
1254 
1255  if (bs>fsize) {
1256  DBG_ERROR(GWEN_LOGDOMAIN, "Internal error: bs>fsize (%lu>%lu)",
1257  (unsigned long int)bs, (unsigned long int) fsize);
1258  GWEN_Gui_ProgressEnd(pid);
1259  if (!checkOnly) {
1261  GWEN_SyncIo_free(sio);
1262  }
1263  GWEN_MDigest_free(md);
1264  return rv;
1265  }
1266 
1267  bytesDone+=bs;
1268  fsize-=bs;
1269 
1270  /* advance progress bar */
1271  rv=GWEN_Gui_ProgressAdvance(pid, bytesDone);
1272  if (rv<0) {
1273  DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
1274  GWEN_Gui_ProgressEnd(pid);
1275  if (!checkOnly) {
1277  GWEN_SyncIo_free(sio);
1278  }
1279  GWEN_MDigest_free(md);
1280  return rv;
1281  }
1282 
1283  } /* while */
1284  GWEN_Gui_ProgressEnd(pid);
1285  }
1286 
1287  if (!checkOnly) {
1288  /* close output file */
1290  GWEN_SyncIo_free(sio);
1291  }
1292 
1293  /* finish hash */
1294  rv=GWEN_MDigest_End(md);
1295  if (rv<0) {
1296  DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
1297  GWEN_MDigest_free(md);
1298  return rv;
1299  }
1300 
1301  /* read and check hash */
1303  if (mpos) {
1304  GWEN_BUFFER *mbuf;
1305 
1306  /* seek to end of file */
1307  pos=GWEN_SyncIo_File_Seek(sr->archiveSio, mpos, GWEN_SyncIo_File_Whence_Set);
1308  if (pos<0) {
1309  DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", (int) pos);
1310  GWEN_MDigest_free(md);
1311  return (int) pos;
1312  }
1313 
1314  /* read 20 bytes of hash */
1315  mbuf=GWEN_Buffer_new(0, 20, 0, 1);
1316  rv=GWEN_SyncIo_ReadForced(sr->archiveSio,
1317  (uint8_t*) GWEN_Buffer_GetStart(mbuf),
1318  20);
1319  if (rv<0) {
1320  DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
1321  GWEN_Buffer_free(mbuf);
1322  GWEN_MDigest_free(md);
1323  return rv;
1324  }
1325  GWEN_Buffer_IncrementPos(mbuf, 20);
1327 
1328  if (memcmp(GWEN_MDigest_GetDigestPtr(md),
1329  GWEN_Buffer_GetStart(mbuf),
1330  20)!=0) {
1331  DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
1332  DBG_ERROR(0, "Hash don't match:");
1333  GWEN_Text_LogString((const char*) GWEN_MDigest_GetDigestPtr(md), 20,
1335 
1338  GWEN_Buffer_free(mbuf);
1339  GWEN_MDigest_free(md);
1340  return GWEN_ERROR_BAD_DATA;
1341  }
1342 
1343  GWEN_Buffer_free(mbuf);
1344  }
1345 
1346  GWEN_MDigest_free(md);
1347  }
1348 
1349  return 0;
1350 }
1351 
1352 
1353 
1355 #if _BSD_SOURCE || _XOPEN_SOURCE >= 500 || (_XOPEN_SOURCE && _XOPEN_SOURCE_EXTENDED) || _POSIX_C_SOURCE >= 200112L || defined(OS_DARWIN)
1356  int rv;
1357  const char *fname;
1358  uint32_t perms;
1359  uint64_t dpos;
1360  uint64_t fsize;
1361  uint64_t hsize;
1362  uint64_t hpos;
1363  uint64_t mpos;
1364  uint64_t pos;
1365  GWEN_MDIGEST *md;
1366 
1367  assert(sr);
1368  assert(sr->refCount);
1369 
1371  rv=GWEN_MDigest_Begin(md);
1372  if (rv<0) {
1373  DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
1374  GWEN_MDigest_free(md);
1375  return rv;
1376  }
1377 
1378  fname=GWEN_SarFileHeader_GetPath(fh);
1380  assert(fname);
1381  fsize=GWEN_SarFileHeader_GetDataSize(fh); /* not FileSize!! */
1383 
1386  if (hsize>0) {
1387  GWEN_BUFFER *mbuf;
1388 
1389  /* seek to header pos */
1390  pos=GWEN_SyncIo_File_Seek(sr->archiveSio, hpos, GWEN_SyncIo_File_Whence_Set);
1391  if (pos<0) {
1392  DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", (int) pos);
1393  GWEN_MDigest_free(md);
1394  return (int) pos;
1395  }
1396 
1397  mbuf=GWEN_Buffer_new(0, hsize, 0, 1);
1398  rv=GWEN_SyncIo_ReadForced(sr->archiveSio,
1399  (uint8_t*) GWEN_Buffer_GetStart(mbuf),
1400  hsize);
1401  if (rv<0) {
1402  DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
1403  GWEN_Buffer_free(mbuf);
1404  GWEN_MDigest_free(md);
1405  return rv;
1406  }
1407  GWEN_Buffer_IncrementPos(mbuf, hsize);
1409 
1410  /* digest header TLV */
1411  rv=GWEN_MDigest_Update(md, (const uint8_t*) GWEN_Buffer_GetStart(mbuf), GWEN_Buffer_GetUsedBytes(mbuf));
1412  if (rv<0) {
1413  DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
1414  GWEN_Buffer_free(mbuf);
1415  GWEN_MDigest_free(md);
1416  return rv;
1417  }
1418  GWEN_Buffer_free(mbuf);
1419  }
1420 
1421  /* seek to data pos */
1422  pos=GWEN_SyncIo_File_Seek(sr->archiveSio, dpos, GWEN_SyncIo_File_Whence_Set);
1423  if (pos<0) {
1424  DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", (int) pos);
1425  GWEN_MDigest_free(md);
1426  return (int) pos;
1427  }
1428 
1429  /* copy file if fsize>0 */
1430  if (fsize>0) { /* fsize is the size of the file tag data */
1431  GWEN_BUFFER *mbuf;
1432 
1433  mbuf=GWEN_Buffer_new(0, fsize, 0, 1);
1434  rv=GWEN_SyncIo_ReadForced(sr->archiveSio,
1435  (uint8_t*) GWEN_Buffer_GetStart(mbuf),
1436  fsize);
1437  if (rv<0) {
1438  DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
1439  GWEN_Buffer_free(mbuf);
1440  GWEN_MDigest_free(md);
1441  return rv;
1442  }
1443  GWEN_Buffer_IncrementPos(mbuf, fsize);
1445 
1446  /* digest TLV */
1447  rv=GWEN_MDigest_Update(md, (const uint8_t*) GWEN_Buffer_GetStart(mbuf), GWEN_Buffer_GetUsedBytes(mbuf));
1448  if (rv<0) {
1449  DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
1450  GWEN_Buffer_free(mbuf);
1451  GWEN_MDigest_free(md);
1452  return rv;
1453  }
1454 
1455  if (!checkOnly) {
1456  mode_t mode=0;
1457 
1458  if (symlink(GWEN_Buffer_GetStart(mbuf), fname)) {
1459  DBG_ERROR(GWEN_LOGDOMAIN, "symlink(%s, %s): %d (%s)",
1460  GWEN_Buffer_GetStart(mbuf),
1461  fname, errno, strerror(errno));
1462  GWEN_Buffer_free(mbuf);
1463  GWEN_MDigest_free(md);
1464  return GWEN_ERROR_IO;
1465  }
1466  /* owner perms */
1467  if (perms & GWEN_SYNCIO_FILE_FLAGS_UREAD)
1468  mode|=S_IRUSR;
1469  if (perms & GWEN_SYNCIO_FILE_FLAGS_UWRITE)
1470  mode|=S_IWUSR;
1471  if (perms & GWEN_SYNCIO_FILE_FLAGS_UEXEC)
1472  mode|=S_IXUSR;
1473 
1474 #if 0 /* CHMOD on symlinks doesn't work */
1475 
1476  /* group perms */
1477 #ifdef S_IRGRP
1478  if (perms & GWEN_SYNCIO_FILE_FLAGS_GREAD) mode|=S_IRGRP;
1479 #endif
1480 #ifdef S_IWGRP
1481  if (perms & GWEN_SYNCIO_FILE_FLAGS_GWRITE) mode|=S_IWGRP;
1482 #endif
1483 #ifdef S_IXGRP
1484  if (perms & GWEN_SYNCIO_FILE_FLAGS_GEXEC) mode|=S_IXGRP;
1485 #endif
1486 
1487  /* other perms */
1488 #ifdef S_IROTH
1489  if (perms & GWEN_SYNCIO_FILE_FLAGS_OREAD) mode|=S_IROTH;
1490 #endif
1491 #ifdef S_IWOTH
1492  if (perms & GWEN_SYNCIO_FILE_FLAGS_OWRITE) mode|=S_IWOTH;
1493 #endif
1494 #ifdef S_IXOTH
1495  if (perms & GWEN_SYNCIO_FILE_FLAGS_OEXEC) mode|=S_IXOTH;
1496 #endif
1497 
1498  rv=chmod(fname, mode);
1499  if (rv<0) {
1500  DBG_WARN(GWEN_LOGDOMAIN, "chmod(%s): %d (%s), ignoring",
1501  fname, errno, strerror(errno));
1502  }
1503 
1504 #endif
1505  }
1506  GWEN_Buffer_free(mbuf);
1507  }
1508 
1509  /* finish hash */
1510  rv=GWEN_MDigest_End(md);
1511  if (rv<0) {
1512  DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
1513  GWEN_MDigest_free(md);
1514  return rv;
1515  }
1516 
1517  /* read and check hash */
1519  if (mpos) {
1520  GWEN_BUFFER *mbuf;
1521 
1522  /* seek to end of file */
1523  pos=GWEN_SyncIo_File_Seek(sr->archiveSio, mpos, GWEN_SyncIo_File_Whence_Set);
1524  if (pos<0) {
1525  DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", (int) pos);
1526  GWEN_MDigest_free(md);
1527  return (int) pos;
1528  }
1529 
1530  /* read 20 bytes of hash */
1531  mbuf=GWEN_Buffer_new(0, 20, 0, 1);
1532  rv=GWEN_SyncIo_ReadForced(sr->archiveSio,
1533  (uint8_t*) GWEN_Buffer_GetStart(mbuf),
1534  20);
1535  if (rv<0) {
1536  DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
1537  GWEN_Buffer_free(mbuf);
1538  GWEN_MDigest_free(md);
1539  if (!checkOnly)
1540  unlink(fname);
1541  return rv;
1542  }
1543  GWEN_Buffer_IncrementPos(mbuf, 20);
1545 
1546  if (memcmp(GWEN_MDigest_GetDigestPtr(md),
1547  GWEN_Buffer_GetStart(mbuf),
1548  20)!=0) {
1549  DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
1550  GWEN_Buffer_free(mbuf);
1551  GWEN_MDigest_free(md);
1552  if (!checkOnly)
1553  unlink(fname);
1554  return GWEN_ERROR_BAD_DATA;
1555  }
1556 
1557  GWEN_Buffer_free(mbuf);
1558  }
1559 
1560  GWEN_MDigest_free(md);
1561 
1562  return 0;
1563 #else
1564 # warning "Function symlink() is not available"
1565  DBG_ERROR(GWEN_LOGDOMAIN, "Function symlink() is not available");
1566  return GWEN_ERROR_IO;
1567 #endif
1568 }
1569 
1570 
1571 
1573  int rv;
1574  const char *fname;
1575  uint64_t dpos;
1576  uint64_t fsize;
1577  uint64_t hsize;
1578  uint64_t hpos;
1579  uint64_t mpos;
1580  uint64_t pos;
1581  GWEN_MDIGEST *md;
1582  GWEN_BUFFER *mbuf;
1583  uint32_t perms;
1584 
1585  assert(sr);
1586  assert(sr->refCount);
1587 
1589  rv=GWEN_MDigest_Begin(md);
1590  if (rv<0) {
1591  DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
1592  GWEN_MDigest_free(md);
1593  return rv;
1594  }
1595 
1596  fname=GWEN_SarFileHeader_GetPath(fh);
1597  assert(fname);
1599  fsize=GWEN_SarFileHeader_GetDataSize(fh); /* not FileSize!! */
1601 
1604  assert(hsize);
1605 
1606  /* seek to end of file */
1607  pos=GWEN_SyncIo_File_Seek(sr->archiveSio, hpos, GWEN_SyncIo_File_Whence_Set);
1608  if (pos<0) {
1609  DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", (int) pos);
1610  GWEN_MDigest_free(md);
1611  return (int) pos;
1612  }
1613 
1614  mbuf=GWEN_Buffer_new(0, hsize, 0, 1);
1615  rv=GWEN_SyncIo_ReadForced(sr->archiveSio,
1616  (uint8_t*) GWEN_Buffer_GetStart(mbuf),
1617  hsize);
1618  if (rv<0) {
1619  DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
1620  GWEN_Buffer_free(mbuf);
1621  GWEN_MDigest_free(md);
1622  return rv;
1623  }
1624  GWEN_Buffer_IncrementPos(mbuf, hsize);
1626 
1627  /* digest TLV */
1628  rv=GWEN_MDigest_Update(md, (const uint8_t*) GWEN_Buffer_GetStart(mbuf), GWEN_Buffer_GetUsedBytes(mbuf));
1629  if (rv<0) {
1630  DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
1631  GWEN_Buffer_free(mbuf);
1632  GWEN_MDigest_free(md);
1633  return rv;
1634  }
1635  GWEN_Buffer_free(mbuf);
1636 
1637  /* finish hash */
1638  rv=GWEN_MDigest_End(md);
1639  if (rv<0) {
1640  DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
1641  GWEN_MDigest_free(md);
1642  return rv;
1643  }
1644 
1645  /* read and check hash */
1647  if (mpos) {
1648  GWEN_BUFFER *mbuf;
1649 
1650  /* seek to end of file */
1651  pos=GWEN_SyncIo_File_Seek(sr->archiveSio, mpos, GWEN_SyncIo_File_Whence_Set);
1652  if (pos<0) {
1653  DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", (int) pos);
1654  GWEN_MDigest_free(md);
1655  return (int) pos;
1656  }
1657 
1658  /* read 20 bytes of hash */
1659  mbuf=GWEN_Buffer_new(0, 20, 0, 1);
1660  rv=GWEN_SyncIo_ReadForced(sr->archiveSio,
1661  (uint8_t*) GWEN_Buffer_GetStart(mbuf),
1662  20);
1663  if (rv<0) {
1664  DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
1665  GWEN_Buffer_free(mbuf);
1666  GWEN_MDigest_free(md);
1667  unlink(fname);
1668  return rv;
1669  }
1670  GWEN_Buffer_IncrementPos(mbuf, 20);
1672 
1673  if (memcmp(GWEN_MDigest_GetDigestPtr(md),
1674  GWEN_Buffer_GetStart(mbuf),
1675  20)!=0) {
1676  DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
1677  GWEN_Buffer_free(mbuf);
1678  GWEN_MDigest_free(md);
1679  unlink(fname);
1680  return GWEN_ERROR_BAD_DATA;
1681  }
1682 
1683  GWEN_Buffer_free(mbuf);
1684  }
1685 
1686  GWEN_MDigest_free(md);
1687 
1688  if (!checkOnly) {
1689  mode_t mode=0;
1690 
1691  /* owner perms */
1692  if (perms & GWEN_SYNCIO_FILE_FLAGS_UREAD)
1693  mode|=S_IRUSR;
1694  if (perms & GWEN_SYNCIO_FILE_FLAGS_UWRITE)
1695  mode|=S_IWUSR;
1696  if (perms & GWEN_SYNCIO_FILE_FLAGS_UEXEC)
1697  mode|=S_IXUSR;
1698 
1699  /* group perms */
1700 #ifdef S_IRGRP
1701  if (perms & GWEN_SYNCIO_FILE_FLAGS_GREAD) mode|=S_IRGRP;
1702 #endif
1703 #ifdef S_IWGRP
1704  if (perms & GWEN_SYNCIO_FILE_FLAGS_GWRITE) mode|=S_IWGRP;
1705 #endif
1706 #ifdef S_IXGRP
1707  if (perms & GWEN_SYNCIO_FILE_FLAGS_GEXEC) mode|=S_IXGRP;
1708 #endif
1709 
1710  /* other perms */
1711 #ifdef S_IROTH
1712  if (perms & GWEN_SYNCIO_FILE_FLAGS_OREAD) mode|=S_IROTH;
1713 #endif
1714 #ifdef S_IWOTH
1715  if (perms & GWEN_SYNCIO_FILE_FLAGS_OWRITE) mode|=S_IWOTH;
1716 #endif
1717 #ifdef S_IXOTH
1718  if (perms & GWEN_SYNCIO_FILE_FLAGS_OEXEC) mode|=S_IXOTH;
1719 #endif
1720 
1721  /* create folder */
1722 #ifndef OS_WIN32
1723  rv=mkdir(fname, mode);
1724 #else
1725  rv=mkdir(fname);
1726 #endif
1727  if (rv) {
1728  DBG_ERROR(GWEN_LOGDOMAIN, "mkdir(%s): %d (%s)",
1729  fname, errno, strerror(errno));
1730  return GWEN_ERROR_IO;
1731  }
1732  }
1733 
1734  return 0;
1735 }
1736 
1737 
1738 
1739 int GWEN_Sar_ExtractAndDigestFile(GWEN_SAR *sr, const GWEN_SAR_FILEHEADER *fh, int checkOnly) {
1740  int rv;
1741 
1742  switch(GWEN_SarFileHeader_GetFileType(fh)) {
1744  rv=GWEN_Sar_ExtractAndDigestFileReg(sr, fh, checkOnly);
1745  break;
1747  rv=GWEN_Sar_ExtractAndDigestFileDir(sr, fh, checkOnly);
1748  break;
1750  rv=GWEN_Sar_ExtractAndDigestFileLink(sr, fh, checkOnly);
1751  break;
1752  default:
1753  DBG_ERROR(GWEN_LOGDOMAIN, "File type %d not supported", GWEN_SarFileHeader_GetFileType(fh));
1754  return GWEN_ERROR_INVALID;
1755  }
1756 
1757  if (rv<0) {
1758  DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
1759  return rv;
1760  }
1761 
1762  return 0;
1763 }
1764 
1765 
1766 
1768  int rv;
1769 
1770  rv=GWEN_Sar_ExtractAndDigestFile(sr, fh, 0);
1771  if (rv<0) {
1772  DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
1773  return rv;
1774  }
1775 
1776  return rv;
1777 }
1778 
1779 
1780 
1782  int rv;
1783 
1784  rv=GWEN_Sar_ExtractAndDigestFile(sr, fh, 1);
1785  if (rv<0) {
1786  DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
1787  return rv;
1788  }
1789 
1790  return rv;
1791 }
1792 
1793 
1794 
1795 const GWEN_SAR_FILEHEADER_LIST *GWEN_Sar_GetHeaders(GWEN_SAR *sr) {
1796  assert(sr);
1797  assert(sr->refCount);
1798  return sr->headers;
1799 }
1800 
1801 
1802 
1803 int GWEN_Sar__UnpackArchive(const char *inFile, const char *where) {
1804  GWEN_SAR *sr;
1805  int rv;
1806  const GWEN_SAR_FILEHEADER_LIST *fhl;
1807 
1808  /* open archive file */
1809  sr=GWEN_Sar_new();
1810  rv=GWEN_Sar_OpenArchive(sr, inFile,
1813  if (rv<0) {
1814  DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
1815  return rv;
1816  }
1817 
1818  /* change to "where" */
1819  if (chdir(where)) {
1820  DBG_ERROR(GWEN_LOGDOMAIN, "chdir(%s): %s", where, strerror(errno));
1821  GWEN_Sar_CloseArchive(sr, 1);
1822  GWEN_Sar_free(sr);
1823  return GWEN_ERROR_IO;
1824  }
1825 
1826  fhl=GWEN_Sar_GetHeaders(sr);
1827  if (fhl) {
1828  const GWEN_SAR_FILEHEADER *fh;
1829  uint32_t pid;
1830 
1835  I18N("File Operation"),
1836  I18N("Unpacking archive file"),
1837  GWEN_SarFileHeader_List_GetCount(fhl),
1838  0);
1839 
1840  fh=GWEN_SarFileHeader_List_First(fhl);
1841  while(fh) {
1842  const char *s;
1843 
1845  rv=GWEN_Sar_ExtractFile(sr, fh);
1846  if (rv<0) {
1847  DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
1848  GWEN_Gui_ProgressEnd(pid);
1849  GWEN_Sar_CloseArchive(sr, 1);
1850  GWEN_Sar_free(sr);
1851  }
1852 
1854  if (rv<0) {
1855  DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
1856  GWEN_Gui_ProgressEnd(pid);
1857  GWEN_Sar_CloseArchive(sr, 1);
1858  GWEN_Sar_free(sr);
1859  return rv;
1860  }
1861 
1862  fh=GWEN_SarFileHeader_List_Next(fh);
1863  }
1864  GWEN_Gui_ProgressEnd(pid);
1865  }
1866 
1867  rv=GWEN_Sar_CloseArchive(sr, 0);
1868  if (rv<0) {
1869  fprintf(stderr, "Error closing archive (%d)\n", rv);
1870  return 2;
1871  }
1872 
1873  return 0;
1874 }
1875 
1876 
1877 
1878 int GWEN_Sar_UnpackArchive(const char *inFile, const char *where) {
1879  char savedPwd[300];
1880  int rv;
1881 
1882  /* get current working dir */
1883  if (getcwd(savedPwd, sizeof(savedPwd)-1)==NULL) {
1884  DBG_ERROR(GWEN_LOGDOMAIN, "getcwd(): %s", strerror(errno));
1885  return GWEN_ERROR_IO;
1886  }
1887  savedPwd[sizeof(savedPwd)-1]=0;
1888 
1889  rv=GWEN_Sar__UnpackArchive(inFile, where);
1890  if (rv<0) {
1891  DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
1892  }
1893 
1894  /* change back to previous pwd */
1895  if (chdir(savedPwd)) {
1896  DBG_ERROR(GWEN_LOGDOMAIN, "chdir(%s): %s", savedPwd, strerror(errno));
1897  return GWEN_ERROR_IO;
1898  }
1899 
1900  return rv;
1901 }
1902 
1903 
1904 
1906  int rv;
1907  GWEN_SAR_FILEHEADER_LIST *fhl;
1908 
1909  assert(sr);
1910  assert(sr->refCount);
1911 
1912  if (sr->openMode!=GWEN_Sar_OpenMode_Opened &&
1913  sr->openMode!=GWEN_Sar_OpenMode_Created) {
1914  DBG_ERROR(GWEN_LOGDOMAIN, "Archive not open");
1915  return GWEN_ERROR_NOT_OPEN;
1916  }
1917 
1918  if (sr->signaturePos!=0 || sr->signatureSize!=0) {
1919  DBG_ERROR(GWEN_LOGDOMAIN, "There already is a signature in the archive file");
1920  return GWEN_ERROR_INVALID;
1921  }
1922 
1923  fhl=sr->headers;
1924  if (fhl) {
1925  GWEN_SAR_FILEHEADER *fh;
1926  uint32_t pid;
1927  GWEN_MDIGEST *md;
1928  uint8_t hashBuf[21];
1929  GWEN_BUFFER *sbuf;
1930  GWEN_BUFFER *tbuf;
1931  int64_t pos;
1932 
1934  rv=GWEN_MDigest_Begin(md);
1935  if (rv<0) {
1936  DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
1937  GWEN_MDigest_free(md);
1938  return rv;
1939  }
1940 
1941  /* clear SIGNED flags */
1942  fh=GWEN_SarFileHeader_List_First(fhl);
1943  while(fh) {
1945  fh=GWEN_SarFileHeader_List_Next(fh);
1946  }
1947 
1948  /* calculate hash over all file hashes */
1953  I18N("File Operation"),
1954  I18N("Signing archive file"),
1955  GWEN_SarFileHeader_List_GetCount(fhl),
1956  0);
1957  fh=GWEN_SarFileHeader_List_First(fhl);
1958  while(fh) {
1959  const char *s;
1960  uint64_t hpos;
1961 
1964  if (hpos==0) {
1965  DBG_WARN(GWEN_LOGDOMAIN, "File %s has no valid hash", s?s:"(unnamed)");
1966  }
1967  else {
1968  /* seek to start of hash */
1969  pos=GWEN_SyncIo_File_Seek(sr->archiveSio, hpos, GWEN_SyncIo_File_Whence_Set);
1970  if (pos<0) {
1971  DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", (int) pos);
1972  GWEN_Gui_ProgressEnd(pid);
1973  GWEN_MDigest_free(md);
1974  return (int) pos;
1975  }
1976 
1977  /* read hash */
1978  rv=GWEN_SyncIo_ReadForced(sr->archiveSio, hashBuf, 20);
1979  if (rv<0) {
1980  DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
1981  GWEN_Gui_ProgressEnd(pid);
1982  GWEN_MDigest_free(md);
1983  return rv;
1984  }
1985 
1986  /* digest hash */
1987  rv=GWEN_MDigest_Update(md, hashBuf, 20);
1988  if (rv<0) {
1989  DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
1990  GWEN_Gui_ProgressEnd(pid);
1991  GWEN_MDigest_free(md);
1992  return rv;
1993  }
1994 
1995 
1997  }
1998 
2000  if (rv<0) {
2001  DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
2002  GWEN_Gui_ProgressEnd(pid);
2003  GWEN_MDigest_free(md);
2004  return rv;
2005  }
2006 
2007  fh=GWEN_SarFileHeader_List_Next(fh);
2008  }
2009 
2010  /* finish hash */
2011  rv=GWEN_MDigest_End(md);
2012  if (rv<0) {
2013  DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
2014  GWEN_Gui_ProgressEnd(pid);
2015  GWEN_MDigest_free(md);
2016  return rv;
2017  }
2018 
2019  /* sign hash */
2020  sbuf=GWEN_Buffer_new(0, 256, 0, 1);
2021  rv=GWEN_CryptMgr_Sign(cm,
2024  sbuf);
2025  if (rv<0) {
2026  DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
2027  GWEN_Buffer_free(sbuf);
2028  GWEN_Gui_ProgressEnd(pid);
2029  GWEN_MDigest_free(md);
2030  return rv;
2031  }
2032  GWEN_MDigest_free(md);
2033 
2034  /* create signature TLV */
2035  tbuf=GWEN_Buffer_new(0, 256, 0, 1);
2036  rv=GWEN_TLV_DirectlyToBuffer(GWEN_SAR_TAG_SIGNATURE, 0x00,
2037  GWEN_Buffer_GetStart(sbuf),
2039  1, tbuf);
2040  if (rv<0) {
2041  DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
2042  GWEN_Buffer_free(tbuf);
2043  GWEN_Buffer_free(sbuf);
2044  GWEN_Gui_ProgressEnd(pid);
2045  return rv;
2046  }
2047 
2048  /* seek to end of file */
2049  pos=GWEN_SyncIo_File_Seek(sr->archiveSio, 0, GWEN_SyncIo_File_Whence_End);
2050  if (pos<0) {
2051  DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", (int) pos);
2052  GWEN_Buffer_free(tbuf);
2053  GWEN_Buffer_free(sbuf);
2054  GWEN_Gui_ProgressEnd(pid);
2055  return (int) pos;
2056  }
2057 
2058  /* write TLV into archive file */
2059  rv=GWEN_SyncIo_WriteForced(sr->archiveSio,
2060  (const uint8_t*) GWEN_Buffer_GetStart(tbuf),
2061  GWEN_Buffer_GetUsedBytes(tbuf));
2062  if (rv<0) {
2063  DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
2064  GWEN_Buffer_free(tbuf);
2065  GWEN_Buffer_free(sbuf);
2066  GWEN_Gui_ProgressEnd(pid);
2067  return rv;
2068  }
2069 
2070 
2071  GWEN_Buffer_free(tbuf);
2072  GWEN_Buffer_free(sbuf);
2073 
2074  GWEN_Gui_ProgressEnd(pid);
2075  }
2076 
2077  return 0;
2078 }
2079 
2080 
2081 
2083  int rv;
2084  GWEN_SAR_FILEHEADER_LIST *fhl;
2085 
2086  assert(sr);
2087  assert(sr->refCount);
2088 
2089  if (sr->openMode!=GWEN_Sar_OpenMode_Opened &&
2090  sr->openMode!=GWEN_Sar_OpenMode_Created) {
2091  DBG_ERROR(GWEN_LOGDOMAIN, "Archive not open");
2092  return GWEN_ERROR_NOT_OPEN;
2093  }
2094 
2095  if (sr->signaturePos==0 || sr->signatureSize==0) {
2096  DBG_ERROR(GWEN_LOGDOMAIN, "No valid signature data in the archive file");
2097  return GWEN_ERROR_INVALID;
2098  }
2099 
2100  fhl=sr->headers;
2101  if (fhl) {
2102  GWEN_SAR_FILEHEADER *fh;
2103  uint32_t pid;
2104  GWEN_MDIGEST *md;
2105  uint8_t hashBuf[21];
2106  GWEN_BUFFER *sbuf;
2107  GWEN_BUFFER *hbuf;
2108  int64_t pos;
2109 
2111  rv=GWEN_MDigest_Begin(md);
2112  if (rv<0) {
2113  DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
2114  GWEN_MDigest_free(md);
2115  return rv;
2116  }
2117 
2118  /* clear SIGNED flags */
2119  fh=GWEN_SarFileHeader_List_First(fhl);
2120  while(fh) {
2122  fh=GWEN_SarFileHeader_List_Next(fh);
2123  }
2124 
2125  /* calculate hash over all file hashes */
2130  I18N("File Operation"),
2131  I18N("Signing archive file"),
2132  GWEN_SarFileHeader_List_GetCount(fhl),
2133  0);
2134  fh=GWEN_SarFileHeader_List_First(fhl);
2135  while(fh) {
2136  const char *s;
2137  uint64_t hpos;
2138 
2141  if (hpos==0) {
2142  DBG_WARN(GWEN_LOGDOMAIN, "File %s has no valid hash", s?s:"(unnamed)");
2143  }
2144  else {
2145  /* seek to start of hash */
2146  pos=GWEN_SyncIo_File_Seek(sr->archiveSio, hpos, GWEN_SyncIo_File_Whence_Set);
2147  if (pos<0) {
2148  DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", (int) pos);
2149  GWEN_Gui_ProgressEnd(pid);
2150  GWEN_MDigest_free(md);
2151  return (int) pos;
2152  }
2153 
2154  /* read hash */
2155  rv=GWEN_SyncIo_ReadForced(sr->archiveSio, hashBuf, 20);
2156  if (rv<0) {
2157  DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
2158  GWEN_Gui_ProgressEnd(pid);
2159  GWEN_MDigest_free(md);
2160  return rv;
2161  }
2162 
2163  /* digest hash */
2164  rv=GWEN_MDigest_Update(md, hashBuf, 20);
2165  if (rv<0) {
2166  DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
2167  GWEN_Gui_ProgressEnd(pid);
2168  GWEN_MDigest_free(md);
2169  return rv;
2170  }
2171 
2172 
2174  }
2175 
2177  if (rv<0) {
2178  DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
2179  GWEN_Gui_ProgressEnd(pid);
2180  GWEN_MDigest_free(md);
2181  return rv;
2182  }
2183 
2184  fh=GWEN_SarFileHeader_List_Next(fh);
2185  }
2186 
2187  /* finish hash */
2188  rv=GWEN_MDigest_End(md);
2189  if (rv<0) {
2190  DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
2191  GWEN_Gui_ProgressEnd(pid);
2192  GWEN_MDigest_free(md);
2193  return rv;
2194  }
2195 
2196  /* seek to start of signature data */
2197  pos=GWEN_SyncIo_File_Seek(sr->archiveSio, sr->signaturePos, GWEN_SyncIo_File_Whence_Set);
2198  if (pos<0) {
2199  DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", (int) pos);
2200  GWEN_Gui_ProgressEnd(pid);
2201  GWEN_MDigest_free(md);
2202  return (int) pos;
2203  }
2204 
2205  /* read signature data */
2206  sbuf=GWEN_Buffer_new(0, sr->signatureSize, 0, 1);
2207  rv=GWEN_SyncIo_ReadForced(sr->archiveSio,
2208  (uint8_t*) GWEN_Buffer_GetStart(sbuf),
2209  sr->signatureSize);
2210  if (rv<0) {
2211  DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
2212  GWEN_Buffer_free(sbuf);
2213  GWEN_Gui_ProgressEnd(pid);
2214  GWEN_MDigest_free(md);
2215  return rv;
2216  }
2217  GWEN_Buffer_IncrementPos(sbuf, sr->signatureSize);
2219 
2220  /* verify signature */
2221  hbuf=GWEN_Buffer_new(0, 256, 0, 1);
2222  rv=GWEN_CryptMgr_Verify(cm,
2223  (const uint8_t*) GWEN_Buffer_GetStart(sbuf),
2225  hbuf);
2226  if (rv<0) {
2227  DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
2228  GWEN_Buffer_free(hbuf);
2229  GWEN_Buffer_free(sbuf);
2230  GWEN_Gui_ProgressEnd(pid);
2231  GWEN_MDigest_free(md);
2232  return rv;
2233  }
2234  GWEN_Buffer_free(sbuf);
2235 
2236  /* verify hash */
2237  if (GWEN_Buffer_GetUsedBytes(hbuf)!=20) {
2238  DBG_ERROR(GWEN_LOGDOMAIN, "Invalid size of signed hash (%d)", GWEN_Buffer_GetUsedBytes(hbuf));
2239  GWEN_Buffer_free(hbuf);
2240  GWEN_Gui_ProgressEnd(pid);
2241  GWEN_MDigest_free(md);
2242  return GWEN_ERROR_BAD_DATA;
2243  }
2244  if (memcmp(GWEN_Buffer_GetStart(hbuf), GWEN_MDigest_GetDigestPtr(md), 20)!=0) {
2245  DBG_ERROR(GWEN_LOGDOMAIN, "Invalid hash, data is invalid!");
2246  GWEN_Buffer_free(hbuf);
2247  GWEN_Gui_ProgressEnd(pid);
2248  GWEN_MDigest_free(md);
2249  return GWEN_ERROR_VERIFY;
2250  }
2251  DBG_INFO(GWEN_LOGDOMAIN, "Signature is valid");
2252 
2253  GWEN_MDigest_free(md);
2254  GWEN_Buffer_free(hbuf);
2255 
2256  GWEN_Gui_ProgressEnd(pid);
2257  }
2258 
2259  return 0;
2260 }
2261 
2262 
2263 
2264 int GWEN_Sar_VerifyArchive(const char *inFile, const char *signer, GWEN_CRYPT_KEY *key) {
2265  GWEN_SAR *sr;
2266  int rv;
2267 
2268  /* open archive file */
2269  sr=GWEN_Sar_new();
2270  rv=GWEN_Sar_OpenArchive(sr, inFile,
2273  if (rv<0) {
2274  DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
2275  GWEN_Sar_free(sr);
2276  return rv;
2277  }
2278  else {
2279  GWEN_CRYPTMGR *cm;
2280 
2281  cm=GWEN_CryptMgrKeys_new(NULL, NULL, signer, key, 0);
2282 
2283  /* verify */
2284  rv=GWEN_Sar_Verify(sr, cm);
2285  if (rv<0) {
2286  DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
2287  GWEN_CryptMgr_free(cm);
2288  GWEN_Sar_CloseArchive(sr, 1);
2289  GWEN_Sar_free(sr);
2290  return rv;
2291  }
2292  GWEN_CryptMgr_free(cm);
2293 
2294  /* close archive */
2295  rv=GWEN_Sar_CloseArchive(sr, 0);
2296  if (rv<0) {
2297  DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
2298  GWEN_Sar_CloseArchive(sr, 1);
2299  GWEN_Sar_free(sr);
2300  return rv;
2301  }
2302  GWEN_Sar_free(sr);
2303  return 0;
2304  }
2305 }
2306 
2307 
2308 
2309 int GWEN_Sar_SignArchive(const char *inFile, const char *signer, GWEN_CRYPT_KEY *key) {
2310  GWEN_SAR *sr;
2311  int rv;
2312 
2313  /* open archive file */
2314  sr=GWEN_Sar_new();
2315  rv=GWEN_Sar_OpenArchive(sr, inFile,
2318  if (rv<0) {
2319  DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
2320  GWEN_Sar_free(sr);
2321  return rv;
2322  }
2323  else {
2324  GWEN_CRYPTMGR *cm;
2325 
2326  cm=GWEN_CryptMgrKeys_new(NULL, NULL, signer, key, 0);
2327 
2328  /* verify */
2329  rv=GWEN_Sar_Sign(sr, cm);
2330  if (rv<0) {
2331  DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
2332  GWEN_CryptMgr_free(cm);
2333  GWEN_Sar_CloseArchive(sr, 1);
2334  GWEN_Sar_free(sr);
2335  return rv;
2336  }
2337  GWEN_CryptMgr_free(cm);
2338 
2339  /* close archive */
2340  rv=GWEN_Sar_CloseArchive(sr, 0);
2341  if (rv<0) {
2342  DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
2343  GWEN_Sar_CloseArchive(sr, 1);
2344  GWEN_Sar_free(sr);
2345  return rv;
2346  }
2347  GWEN_Sar_free(sr);
2348  return 0;
2349  }
2350 }
2351 
2352 
2353 
2354 int GWEN_Sar_CheckArchive(const char *inFile) {
2355  GWEN_SAR *sr;
2356  int rv;
2357  const GWEN_SAR_FILEHEADER_LIST *fhl;
2358 
2359  /* open archive file */
2360  sr=GWEN_Sar_new();
2361  rv=GWEN_Sar_OpenArchive(sr, inFile,
2364  if (rv<0) {
2365  DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
2366  return rv;
2367  }
2368 
2369  fhl=GWEN_Sar_GetHeaders(sr);
2370  if (fhl) {
2371  const GWEN_SAR_FILEHEADER *fh;
2372  uint32_t pid;
2373 
2378  I18N("File Operation"),
2379  I18N("Checking archive file"),
2380  GWEN_SarFileHeader_List_GetCount(fhl),
2381  0);
2382 
2383  fh=GWEN_SarFileHeader_List_First(fhl);
2384  while(fh) {
2385  const char *s;
2386 
2388  rv=GWEN_Sar_CheckFile(sr, fh);
2389  if (rv<0) {
2390  DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
2391  GWEN_Gui_ProgressEnd(pid);
2392  GWEN_Sar_CloseArchive(sr, 1);
2393  GWEN_Sar_free(sr);
2394  }
2395 
2397  if (rv<0) {
2398  DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
2399  GWEN_Gui_ProgressEnd(pid);
2400  GWEN_Sar_CloseArchive(sr, 1);
2401  GWEN_Sar_free(sr);
2402  return rv;
2403  }
2404 
2405  fh=GWEN_SarFileHeader_List_Next(fh);
2406  }
2407  GWEN_Gui_ProgressEnd(pid);
2408  }
2409 
2410  rv=GWEN_Sar_CloseArchive(sr, 0);
2411  if (rv<0) {
2412  fprintf(stderr, "Error closing archive (%d)\n", rv);
2413  return 2;
2414  }
2415  GWEN_Sar_free(sr);
2416 
2417  return 0;
2418 }
2419 
2420 
2421