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