1
0
mirror of https://github.com/hashcat/hashcat.git synced 2025-02-18 10:32:04 +00:00
hashcat/src/filehandling.c
Alex Stanev 7252091d3b Correct check for gz header.
gzip format is described in rfc1952.
From there, first 2 bytes (0x1f8b) are header;
next is Compression method (0x08 for deflate, this is the general used method);
and 4th byte is Flags. Some compression tools don't set this and we can't process the gzips.
zlib plays well in this cases, so we can just drop the check for the 4th byte.
2020-12-26 22:49:05 +02:00

678 lines
11 KiB
C

/**
* Author......: See docs/credits.txt
* License.....: MIT
*/
#include "common.h"
#include "types.h"
#include "memory.h"
#include "shared.h"
#include "filehandling.h"
#if defined (__CYGWIN__)
// workaround for zlib with cygwin build
int _wopen (const char *path, int oflag, ...)
{
va_list ap;
va_start (ap, oflag);
int r = open (path, oflag, ap);
va_end (ap);
return r;
}
#endif
bool hc_fopen (HCFILE *fp, const char *path, char *mode)
{
if (path == NULL || mode == NULL) return false;
int oflag = -1;
int fmode = S_IRUSR|S_IWUSR;
if (strncmp (mode, "a", 1) == 0 || strncmp (mode, "ab", 2) == 0)
{
oflag = O_WRONLY | O_CREAT | O_APPEND;
#if defined(MSDOS) || defined(OS2) || defined(WIN32) || defined(_WIN32) || defined(__CYGWIN__)
if (strncmp (mode, "ab", 2) == 0) oflag |= O_BINARY;
#endif
}
else if (strncmp (mode, "r", 1) == 0 || strncmp (mode, "rb", 2) == 0)
{
oflag = O_RDONLY;
fmode = -1;
#if defined(MSDOS) || defined(OS2) || defined(WIN32) || defined(_WIN32) || defined(__CYGWIN__)
if (strncmp (mode, "rb", 2) == 0) oflag |= O_BINARY;
#endif
}
else if (strncmp (mode, "w", 1) == 0 || strncmp (mode, "wb", 2) == 0)
{
oflag = O_WRONLY | O_CREAT | O_TRUNC;
#if defined(MSDOS) || defined(OS2) || defined(WIN32) || defined(_WIN32) || defined(__CYGWIN__)
if (strncmp (mode, "wb", 2) == 0) oflag |= O_BINARY;
#endif
}
else
{
// ADD more strncmp to handle more "mode"
return false;
}
fp->pfp = NULL;
fp->is_gzip = false;
fp->is_zip = false;
unsigned char check[4] = { 0 };
int fd_tmp = open (path, O_RDONLY);
if (fd_tmp != -1)
{
lseek (fd_tmp, 0, SEEK_SET);
if (read (fd_tmp, check, sizeof (check)) > 0)
{
if (check[0] == 0x1f && check[1] == 0x8b && check[2] == 0x08) fp->is_gzip = true;
if (check[0] == 0x50 && check[1] == 0x4b && check[2] == 0x03 && check[3] == 0x04) fp->is_zip = true;
}
close (fd_tmp);
}
if (fmode == -1)
{
fp->fd = open (path, oflag);
}
else
{
fp->fd = open (path, oflag, fmode);
}
if (fp->fd == -1 && fp->is_zip == false) return false;
if (fp->is_gzip)
{
if ((fp->gfp = gzdopen (fp->fd, mode)) == NULL) return false;
}
else if (fp->is_zip)
{
if ((fp->ufp = unzOpen64 (path)) == NULL) return false;
if (unzOpenCurrentFile (fp->ufp) != UNZ_OK) return false;
}
else
{
if ((fp->pfp = fdopen (fp->fd, mode)) == NULL) return false;
}
fp->path = path;
fp->mode = mode;
return true;
}
size_t hc_fread (void *ptr, size_t size, size_t nmemb, HCFILE *fp)
{
size_t n = -1;
if (fp == NULL) return n;
if (fp->is_gzip)
{
n = gzfread (ptr, size, nmemb, fp->gfp);
}
else if (fp->is_zip)
{
unsigned s = size * nmemb;
n = unzReadCurrentFile (fp->ufp, ptr, s);
}
else
{
#if defined (_WIN)
// 4 GB fread () limit for windows systems ?
// see: https://social.msdn.microsoft.com/Forums/vstudio/en-US/7c913001-227e-439b-bf07-54369ba07994/fwrite-issues-with-large-data-write
#define GIGABYTE (1024u * 1024u * 1024u)
if (((size * nmemb) / GIGABYTE) < 4)
{
n = fread (ptr, size, nmemb, fp->pfp);
}
else
{
if ((size / GIGABYTE) > 3) return -1;
size_t elements_max = (3u * GIGABYTE) / size;
size_t elements_left = nmemb;
size_t off = 0;
n = 0;
while (elements_left > 0)
{
size_t elements_cur = elements_max;
if (elements_left < elements_max) elements_cur = elements_left;
size_t ret = fread (ptr + off, size, elements_cur, fp->pfp);
if (ret != elements_cur) return -1;
n += ret;
off += ret * size;
elements_left -= ret;
}
}
#else
n = fread (ptr, size, nmemb, fp->pfp);
#endif
}
return n;
}
size_t hc_fwrite (const void *ptr, size_t size, size_t nmemb, HCFILE *fp)
{
size_t n = -1;
if (fp == NULL) return n;
if (fp->is_gzip)
{
n = gzfwrite (ptr, size, nmemb, fp->gfp);
}
else if (fp->is_zip)
{
}
else
{
#if defined (_WIN)
// 4 GB fwrite () limit for windows systems ?
// see: https://social.msdn.microsoft.com/Forums/vstudio/en-US/7c913001-227e-439b-bf07-54369ba07994/fwrite-issues-with-large-data-write
#define GIGABYTE (1024u * 1024u * 1024u)
if (((size * nmemb) / GIGABYTE) < 4)
{
n = fwrite (ptr, size, nmemb, fp->pfp);
}
else
{
if ((size / GIGABYTE) > 3) return -1;
size_t elements_max = (3u * GIGABYTE) / size;
size_t elements_left = nmemb;
size_t off = 0;
n = 0;
while (elements_left > 0)
{
size_t elements_cur = elements_max;
if (elements_left < elements_max) elements_cur = elements_left;
size_t ret = fwrite (ptr + off, size, elements_cur, fp->pfp);
if (ret != elements_cur) return -1;
n += ret;
off += ret * size;
elements_left -= ret;
}
}
#else
n = fwrite (ptr, size, nmemb, fp->pfp);
#endif
}
return n;
}
int hc_fseek (HCFILE *fp, off_t offset, int whence)
{
int r = -1;
if (fp == NULL) return r;
if (fp->is_gzip)
{
r = gzseek (fp->gfp, offset, whence);
}
else if (fp->is_zip)
{
/*
// untested and not used in wordlist engine
zlib_filefunc64_32_def *d = NULL;
if (whence == SEEK_SET)
{
r = ZSEEK64 (*d, fp->ufp, offset, ZLIB_FILEFUNC_SEEK_SET);
}
else if (whence == SEEK_CUR)
{
r = ZSEEK64 (*d, fp->ufp, offset, ZLIB_FILEFUNC_SEEK_CUR);
}
else if (whence == SEEK_END)
{
r = ZSEEK64 (*d, fp->ufp, offset, ZLIB_FILEFUNC_SEEK_END);
}
// or
// r = unzSetOffset (fp->ufp, offset);
*/
}
else
{
r = fseeko (fp->pfp, offset, whence);
}
return r;
}
void hc_rewind (HCFILE *fp)
{
if (fp == NULL) return;
if (fp->is_gzip)
{
gzrewind (fp->gfp);
}
else if (fp->is_zip)
{
unzGoToFirstFile (fp->ufp);
}
else
{
rewind (fp->pfp);
}
}
off_t hc_ftell (HCFILE *fp)
{
off_t n = 0;
if (fp == NULL) return -1;
if (fp->is_gzip)
{
n = (off_t) gztell (fp->gfp);
}
else if (fp->is_zip)
{
n = unztell (fp->ufp);
}
else
{
n = ftello (fp->pfp);
}
return n;
}
int hc_fputc (int c, HCFILE *fp)
{
int r = -1;
if (fp == NULL) return r;
if (fp->is_gzip)
{
r = gzputc (fp->gfp, c);
}
else if (fp->is_zip)
{
}
else
{
r = fputc (c, fp->pfp);
}
return r;
}
int hc_fgetc (HCFILE *fp)
{
int r = -1;
if (fp == NULL) return r;
if (fp->is_gzip)
{
r = gzgetc (fp->gfp);
}
else if (fp->is_zip)
{
unsigned char c = 0;
if (unzReadCurrentFile (fp->ufp, &c, 1) == 1) r = (int) c;
}
else
{
r = fgetc (fp->pfp);
}
return r;
}
char *hc_fgets (char *buf, int len, HCFILE *fp)
{
char *r = NULL;
if (fp == NULL) return r;
if (fp->is_gzip)
{
r = gzgets (fp->gfp, buf, len);
}
else if (fp->is_zip)
{
if (unzReadCurrentFile (fp->ufp, buf, len) > 0) r = buf;
}
else
{
r = fgets (buf, len, fp->pfp);
}
return r;
}
int hc_vfprintf (HCFILE *fp, const char *format, va_list ap)
{
int r = -1;
if (fp == NULL) return r;
if (fp->is_gzip)
{
r = gzvprintf (fp->gfp, format, ap);
}
else if (fp->is_zip)
{
}
else
{
r = vfprintf (fp->pfp, format, ap);
}
return r;
}
int hc_fprintf (HCFILE *fp, const char *format, ...)
{
int r = -1;
if (fp == NULL) return r;
va_list ap;
va_start (ap, format);
if (fp->is_gzip)
{
r = gzvprintf (fp->gfp, format, ap);
}
else if (fp->is_zip)
{
}
else
{
r = vfprintf (fp->pfp, format, ap);
}
va_end (ap);
return r;
}
int hc_fscanf (HCFILE *fp, const char *format, void *ptr)
{
if (fp == NULL) return -1;
char *buf = (char *) hcmalloc (HCBUFSIZ_TINY);
if (buf == NULL) return -1;
char *b = hc_fgets (buf, HCBUFSIZ_TINY - 1, fp);
if (b == NULL)
{
hcfree (buf);
return -1;
}
sscanf (b, format, ptr);
hcfree (buf);
return 1;
}
int hc_fileno (HCFILE *fp)
{
if (fp == NULL) return 1;
return fp->fd;
}
int hc_feof (HCFILE *fp)
{
int r = -1;
if (fp == NULL) return r;
if (fp->is_gzip)
{
r = gzeof (fp->gfp);
}
else if (fp->is_zip)
{
r = unzeof (fp->ufp);
}
else
{
r = feof (fp->pfp);
}
return r;
}
void hc_fflush (HCFILE *fp)
{
if (fp == NULL) return;
if (fp->is_gzip)
{
gzflush (fp->gfp, Z_SYNC_FLUSH);
}
else if (fp->is_zip)
{
}
else
{
fflush (fp->pfp);
}
}
void hc_fclose (HCFILE *fp)
{
if (fp == NULL) return;
if (fp->is_gzip)
{
gzclose (fp->gfp);
}
else if (fp->is_zip)
{
unzCloseCurrentFile (fp->ufp);
unzClose (fp->ufp);
}
else
{
fclose (fp->pfp);
}
fp->fd = -1;
fp->pfp = NULL;
fp->is_gzip = false;
fp->is_zip = false;
fp->path = NULL;
fp->mode = NULL;
}
size_t fgetl (HCFILE *fp, char *line_buf, const size_t line_sz)
{
size_t line_truncated = 0;
size_t line_len = 0;
while (!hc_feof (fp))
{
const int c = hc_fgetc (fp);
if (c == EOF) break;
if (line_len == line_sz)
{
line_truncated++;
continue;
}
line_buf[line_len] = (char) c;
line_len++;
if (c == '\n') break;
}
if (line_truncated > 0)
{
fprintf (stderr, "\nOversized line detected! Truncated %" PRIu64 " bytes\n", (u64) line_truncated);
}
if (line_len == 0) return 0;
while (line_len)
{
if (line_buf[line_len - 1] == '\n')
{
line_len--;
continue;
}
if (line_buf[line_len - 1] == '\r')
{
line_len--;
continue;
}
break;
}
line_buf[line_len] = 0;
return (line_len);
}
u64 count_lines (HCFILE *fp)
{
u64 cnt = 0;
char *buf = (char *) hcmalloc (HCBUFSIZ_LARGE + 1);
char prev = '\n';
while (!hc_feof (fp))
{
size_t nread = hc_fread (buf, sizeof (char), HCBUFSIZ_LARGE, fp);
if (nread < 1) continue;
size_t i;
for (i = 0; i < nread; i++)
{
if (prev == '\n') cnt++;
prev = buf[i];
}
}
hcfree (buf);
return cnt;
}
size_t in_superchop (char *buf)
{
size_t len = strlen (buf);
while (len)
{
if (buf[len - 1] == '\n')
{
len--;
buf[len] = 0;
continue;
}
if (buf[len - 1] == '\r')
{
len--;
buf[len] = 0;
continue;
}
break;
}
return len;
}
size_t superchop_with_length (char *buf, const size_t len)
{
size_t new_len = len;
while (new_len)
{
if (buf[new_len - 1] == '\n')
{
new_len--;
buf[new_len] = 0;
continue;
}
if (buf[new_len - 1] == '\r')
{
new_len--;
buf[new_len] = 0;
continue;
}
break;
}
return new_len;
}