windows-tests-nm-20090130
authorAsanka Herath <asanka@secure-endpoints.com>
Sat, 31 Jan 2009 03:08:55 +0000 (03:08 +0000)
committerJeffrey Altman <jaltman@secure-endpoints.com>
Sat, 31 Jan 2009 03:08:55 +0000 (03:08 +0000)
LICENSE BSD

A test application that produces verifiable random test files.

====================
This delta was composed from multiple commits as part of the CVS->Git migration.
The checkin message with each commit was inconsistent.
The following are the additional commit messages.
====================
LICENSE BSD

make it build in the openafs build tree

src/WINNT/tests/nmtest/NTMakefile [new file with mode: 0644]
src/WINNT/tests/nmtest/nmtest.c [new file with mode: 0644]

diff --git a/src/WINNT/tests/nmtest/NTMakefile b/src/WINNT/tests/nmtest/NTMakefile
new file mode 100644 (file)
index 0000000..ba7fc9f
--- /dev/null
@@ -0,0 +1,31 @@
+#                                                                                                                                
+# Copyright (c) 2009 Secure Endpoints Inc.
+#
+
+RELDIR=WINNT\tests\nmtest
+!INCLUDE ..\..\..\config\NTMakefile.$(SYS_NAME)
+!INCLUDE ..\..\..\config\NTMakefile.version
+
+idirs:
+!       if !(exist($(OJT)\WINNT\tests))
+                md $(OJT)\WINNT\tests
+!       endif
+!       if !(exist($(OJT)\WINNT\tests\nmtest))
+                md $(OJT)\WINNT\tests\nmtest
+!       endif
+
+EXEDIR = $(DESTDIR)\bin
+
+OBJS = $(OUT)\nmtest.obj
+
+$(EXEDIR)\nmtest.exe: $(OBJS)
+        $(EXECONLINK) dnsapi.lib mpr.lib iphlpapi.lib shell32.lib userenv.lib
+        $(_VC_MANIFEST_EMBED_EXE)
+        $(EXEPREP)
+        $(CODESIGN_USERLAND)
+
+install: idirs $(EXEDIR)\nmtest.exe
+
+clean::
+        
+
diff --git a/src/WINNT/tests/nmtest/nmtest.c b/src/WINNT/tests/nmtest/nmtest.c
new file mode 100644 (file)
index 0000000..d7604a4
--- /dev/null
@@ -0,0 +1,670 @@
+/* 
+ * Copyright (c) 2009 - Secure Endpoints Inc.
+ *
+ * Author: Asanka Herath <asanka@secure-endpoints.com>
+ */
+
+#include<windows.h>
+#include<wincrypt.h>
+#include<stdlib.h>
+#include<stdio.h>
+
+#define BLOCKSIZE 1024
+#define MAX_PARAM 1
+
+typedef __int64 offset_t;
+
+HCRYPTPROV h_prov = 0;
+
+offset_t N = 0;
+offset_t M = 0;
+const char * filename = "";
+BOOL  verify = FALSE;
+BOOL  show_offsets = FALSE;
+
+typedef struct hash_data {
+    offset_t offset;
+    DWORD    param;
+} hash_data;
+
+#define ROUNDUP(x, align) (((((x) - 1) / (align)) + 1) * (align))
+
+void dump_hex(BYTE * buffer, int cb)
+{
+    static const char *htable[] = {
+        "0","1","2","3","4","5","6","7","8","9","A","B","C","D","E","F"
+    };
+    int i;
+
+    for (i=0; i < cb; i++) {
+        if ((i % 16) == 0) {
+            fprintf(stderr, "\n%08X : ", i);
+        }
+
+        fprintf(stderr, "%s%s",
+                htable[(buffer[i] >> 4) & 0xf],
+                htable[(buffer[i] & 0xf)]);
+
+        if ((i % 16) == 8)
+            fprintf(stderr, "-");
+        else
+            fprintf(stderr, " ");
+    }
+
+    fprintf(stderr, "\n");
+}
+
+#define CCall(f) if (!f) goto done;
+
+BOOL init_test_data(void)
+{
+    return CryptAcquireContext(&h_prov, NULL, MS_DEF_PROV, PROV_RSA_FULL,
+                               CRYPT_VERIFYCONTEXT | CRYPT_SILENT);
+}
+
+void exit_test_data(void)
+{
+    if (h_prov)
+        CryptReleaseContext(h_prov, 0);
+    h_prov = 0;
+}
+
+BOOL generate_test_data_block(offset_t offset, DWORD param, BYTE buffer[BLOCKSIZE])
+{
+    HCRYPTHASH h_hash = 0;
+    HCRYPTKEY  h_key = 0;
+    hash_data  d;
+    DWORD      cb_data;
+    BOOL rv = FALSE;
+
+    ZeroMemory(&d, sizeof(d));
+
+    d.offset = offset;
+    d.param = param;
+
+    CCall(CryptCreateHash(h_prov, CALG_SHA1, 0, 0, &h_hash));
+    CCall(CryptHashData(h_hash, (BYTE *) &d, sizeof(d), 0));
+    CCall(CryptDeriveKey(h_prov, CALG_RC4, h_hash, CRYPT_NO_SALT, &h_key));
+
+    ZeroMemory(buffer, BLOCKSIZE);
+    cb_data = BLOCKSIZE;
+    CCall(CryptEncrypt(h_key, 0, TRUE, 0, buffer, &cb_data, cb_data));
+
+    //dump_hex(buffer, 32);
+
+    rv = TRUE;
+ done:
+
+    if (h_hash)
+        CryptDestroyHash(h_hash);
+    if (h_key)
+        CryptDestroyKey(h_key);
+
+    return rv;
+}
+
+BOOL verify_test_data_block(offset_t offset, DWORD param, BYTE buffer[BLOCKSIZE])
+{
+    BYTE expected[BLOCKSIZE];
+
+    if (!generate_test_data_block(offset, param, expected)) {
+        return FALSE;
+    }
+    if (!memcmp(expected, buffer, BLOCKSIZE)) {
+        if (param > 0 && show_offsets)
+            printf("... [%I64d]\n", offset, param);
+        return TRUE;
+    }
+
+    return FALSE;
+}
+
+typedef struct bitmap {
+    DWORD    magic;
+    offset_t length;
+    offset_t o_data;
+    BYTE     bits[1];
+} bitmap;
+
+#define BMAGIC 0xbeefface
+
+#define NBITMAPBYTES(n) (ROUNDUP((n)/BLOCKSIZE, 8)/8)
+#define BITMAPSIZE(n) (sizeof(bitmap) + NBITMAPBYTES(n) - 1)
+#define FILESIZE(n)   (DATAOFFSET(n) + (n))
+#define DATAOFFSET(n) ROUNDUP(BITMAPSIZE(n), BLOCKSIZE)
+
+bitmap * allocbits(offset_t N)
+{
+    bitmap * b;
+
+    b = malloc(BITMAPSIZE(N));
+    if (b == NULL)
+        return NULL;
+
+    memset(b, 0, BITMAPSIZE(N));
+
+    b->magic = BMAGIC;
+    b->length = N;
+    b->o_data = DATAOFFSET(N);
+
+    return b;
+}
+
+void freebits(bitmap * b)
+{
+    if (b)
+        free(b);
+}
+
+void setbit(bitmap * b, offset_t o)
+{
+    if (o < b->o_data || o >= b->o_data + b->length || (o % BLOCKSIZE) != 0) {
+        fprintf(stderr, "Internal error. Invalid offset\n");
+        exit(1);
+    }
+
+    o = (o - b->o_data) / BLOCKSIZE;
+
+    b->bits[o / 8] |= (1 << (o & 7));
+}
+
+BOOL getbit(bitmap * b, offset_t o)
+{
+    if (o < b->o_data || o >= b->o_data + b->length || (o % BLOCKSIZE) != 0) {
+        fprintf(stderr, "Internal error. Invalid offset\n");
+        exit(1);
+    }
+
+    o = (o - b->o_data) / BLOCKSIZE;
+
+    return !!(b->bits[o / 8] & (1 << (o & 7)));
+}
+
+BOOL write_bitmap(HANDLE h, bitmap * b)
+{
+    LARGE_INTEGER li;
+    OVERLAPPED ov;
+    offset_t b_size, o;
+    BOOL success = FALSE;
+
+    ZeroMemory(&ov, sizeof(ov));
+
+    b_size = BITMAPSIZE(b->length);
+
+    li.QuadPart = 0;
+
+    if (!SetFilePointerEx(h, li, &li, FILE_BEGIN)) {
+        fprintf(stderr, "Can't set file pointer. GLE=%d\n", GetLastError());
+        goto done;
+    }
+
+    for (o = 0; o < b_size; o += BLOCKSIZE) {
+        BYTE buffer[BLOCKSIZE];
+        DWORD n_written = 0;
+
+        if (o + BLOCKSIZE <= b_size) {
+            memcpy(buffer, ((BYTE *) b) + o, BLOCKSIZE);
+        } else {
+            memcpy(buffer, ((BYTE *) b) + o, (b_size - o));
+            memset(buffer + (b_size - o), 0, BLOCKSIZE - (b_size - o));
+        }
+
+        li.QuadPart = o;
+        ov.Offset = li.LowPart;
+        ov.OffsetHigh = li.HighPart;
+
+        if (!LockFileEx(h, LOCKFILE_EXCLUSIVE_LOCK, 0, BLOCKSIZE, 0, &ov)) {
+            fprintf(stderr, "Can't lock file. GLE=%d\n", GetLastError());
+            goto done;
+        }
+
+        if (!WriteFile(h, buffer, BLOCKSIZE, &n_written, NULL) || n_written != BLOCKSIZE) {
+            fprintf(stderr, "Can't write data. GLE=%d\n", GetLastError());
+            goto done;
+        }
+
+        if (!UnlockFileEx(h, 0, BLOCKSIZE, 0, &ov)) {
+            fprintf(stderr, "Can't unlock file. GLE=%d\n", GetLastError());
+            goto done;
+        }
+    }
+
+    li.QuadPart = 0;
+    if (!SetFilePointerEx(h, li, &li, FILE_CURRENT)) {
+        fprintf(stderr, "Can't set file pointer. GLE=%d\n", GetLastError());
+        goto done;
+    }
+
+    if (li.QuadPart != b->o_data) {
+        fprintf(stderr, "Current file pointer is not at start of data.\n");
+        goto done;
+    }
+
+    success = TRUE;
+
+ done:
+
+    return success;    
+}
+
+bitmap* read_bitmap(HANDLE h)
+{
+    LARGE_INTEGER li;
+    OVERLAPPED ov;
+    bitmap * bfile = NULL;
+    bitmap * bprep = NULL;
+    bitmap * brv = NULL;
+    BYTE buffer[BLOCKSIZE];
+    DWORD n_read = 0;
+    offset_t o;
+
+    ZeroMemory(&ov, sizeof(ov));
+
+    li.QuadPart = 0;
+
+    if (!SetFilePointerEx(h, li, &li, FILE_BEGIN)) {
+        fprintf(stderr, "Can't set file pointer. GLE=%d\n", GetLastError());
+        goto done;
+    }
+
+    ov.Offset = 0;
+    ov.OffsetHigh = 0;
+
+    if (!LockFileEx(h, 0, 0, BLOCKSIZE, 0, &ov)) {
+        fprintf(stderr, "Can't lock file. GLE=%d\n", GetLastError());
+        goto done;
+    }
+
+    if (!ReadFile(h, buffer, BLOCKSIZE, &n_read, NULL) || n_read != BLOCKSIZE) {
+        fprintf(stderr, "Can't read data. GLE=%d\n", GetLastError());
+        goto done;
+    }
+
+    if (!UnlockFileEx(h, 0, BLOCKSIZE, 0, &ov)) {
+        fprintf(stderr, "Can't unlock file. GLE=%d\n", GetLastError());
+        goto done;
+    }
+
+    bfile = (bitmap *)buffer;
+
+    if (bfile->magic != BMAGIC) {
+        fprintf(stderr, "Corrupt data. Magic number is invalid\n");
+        goto done;
+    }
+
+    if (!GetFileSizeEx(h, &li)) {
+        fprintf(stderr, "Can't get file size. GLE=%d\n", GetLastError());
+        goto done;
+    }
+
+    if (li.QuadPart != FILESIZE(bfile->length)) {
+        fprintf(stderr, "Corrupt data. Invalid file size.\n");
+        goto done;
+    }
+
+    if (bfile->o_data != DATAOFFSET(bfile->length)) {
+        fprintf(stderr, "Corrupt data. Invalid data offset.\n");
+        goto done;
+    }
+
+    bprep = allocbits(bfile->length);
+
+    if (bprep == NULL) {
+        fprintf(stderr, "Can't allocate memory for bitmap\n");
+        goto done;
+    }
+
+    memcpy(bprep, bfile, __min(BITMAPSIZE(bfile->length), BLOCKSIZE));
+
+    for (o = BLOCKSIZE; o < BITMAPSIZE(bprep->length); o += BLOCKSIZE) {
+        li.QuadPart = o;
+        ov.Offset = li.LowPart;
+        ov.OffsetHigh = li.HighPart;
+
+        if (!LockFileEx(h, 0, 0, BLOCKSIZE, 0, &ov)) {
+            fprintf(stderr, "Can't lock file. GLE=%d\n", GetLastError());
+            goto done;
+        }
+
+        if (!ReadFile(h, buffer, BLOCKSIZE, &n_read, NULL) || n_read != BLOCKSIZE) {
+            fprintf(stderr, "Can't read data. GLE=%d\n", GetLastError());
+            goto done;
+        }
+
+        if (!UnlockFileEx(h, 0, BLOCKSIZE, 0, &ov)) {
+            fprintf(stderr, "Can't unlock file. GLE=%d\n", GetLastError());
+            goto done;
+        }
+
+        memcpy(((BYTE *) bprep) + o, buffer, __min(BITMAPSIZE(bprep->length) - o, BLOCKSIZE));
+    }
+
+    li.QuadPart = 0;
+    if (!SetFilePointerEx(h, li, &li, FILE_CURRENT)) {
+        fprintf(stderr, "Can't set file pointer. GLE=%d\n", GetLastError());
+        goto done;
+    }
+
+    if (li.QuadPart != bprep->o_data) {
+        fprintf(stderr, "Current file pointer not at start of data.\n");
+        goto done;
+    }
+
+    brv = bprep;
+
+ done:
+    if (brv == NULL && bprep != NULL) {
+        freebits(bprep);
+    }
+    return brv;
+}
+
+int do_verify_test(void)
+{
+    HANDLE h_file = NULL;
+    int rv = 1;
+    offset_t offset;
+    LARGE_INTEGER li;
+    OVERLAPPED ov;
+    bitmap * b = NULL;
+
+    printf("Verifying test data file [%s]\n", filename);
+
+    h_file = CreateFile(filename, GENERIC_READ, FILE_SHARE_WRITE, NULL,
+                        OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN, NULL);
+    if (h_file == INVALID_HANDLE_VALUE) {
+        fprintf(stderr, "Can't open file [%s] GLE=%d\n", filename, GetLastError());
+        goto done;
+    }
+
+    b = read_bitmap(h_file);
+
+    if (b == NULL) {
+        goto done;
+    }
+
+    N = b->length;
+
+    printf("File size N = %I64d\n", N);
+
+    if (!init_test_data()) {
+        fprintf(stderr, "Initialize crypto. GLE=%d\n", GetLastError());
+        goto done;
+    }
+
+    printf("Verifying data ... \n");
+
+    ZeroMemory(&ov, sizeof(ov));
+
+    for (offset = b->o_data; offset < b->o_data+N; offset += BLOCKSIZE) {
+        BYTE buffer[BLOCKSIZE];
+        DWORD n_read = 0;
+
+        li.QuadPart = offset;
+        ov.Offset = li.LowPart;
+        ov.OffsetHigh = li.HighPart;
+
+        if (!LockFileEx(h_file, 0, 0, BLOCKSIZE, 0, &ov)) {
+            printf("ERROR\n");
+            fprintf(stderr, "Can't lock file. GLE=%d\n", GetLastError());
+            goto done;
+        }
+
+        if (!ReadFile(h_file, buffer, BLOCKSIZE, &n_read, NULL) || n_read != BLOCKSIZE) {
+            printf("ERROR\n");
+            fprintf(stderr, "Can't read data. GLE=%d\n", GetLastError());
+            goto done;
+        }
+
+        if (!verify_test_data_block(offset, ((getbit(b, offset))? 1 : 0), buffer)) {
+            printf("VERIFY FAILED\n");
+            fprintf(stderr, "Verification failed at offset %I64d\n", offset);
+            goto done;
+        }
+
+        if (!UnlockFileEx(h_file, 0, BLOCKSIZE, 0, &ov)) {
+            printf("ERROR\n");
+            fprintf(stderr, "Can't unlock file. GLE=%d\n", GetLastError());
+            goto done;
+        }
+    }
+
+    printf("Verify succeeded!\n");
+
+    rv = 0;
+
+ done:
+    if (b)
+        freebits(b);
+
+    if (h_file)
+        CloseHandle(h_file);
+
+    exit_test_data();
+
+    return rv;
+}
+
+int do_write_test(void)
+{
+    HANDLE h_file = NULL;
+    int rv = 1;
+    offset_t offset;
+    OVERLAPPED ov;
+    bitmap * b = NULL;
+
+    printf("Generating test data file [%s]\n", filename);
+
+    N = (((N - 1)/BLOCKSIZE) + 1) * BLOCKSIZE;
+    M = (((M - 1)/BLOCKSIZE) + 1) * BLOCKSIZE;
+
+    printf("Using N = %I64d and M = %I64d\n", N, M);
+
+    h_file = CreateFile(filename, GENERIC_WRITE, FILE_SHARE_WRITE, NULL,
+                        CREATE_ALWAYS, FILE_FLAG_RANDOM_ACCESS, NULL);
+    if (h_file == INVALID_HANDLE_VALUE) {
+        fprintf(stderr, "Can't create file [%s] GLE=%d\n", filename, GetLastError());
+        goto done;
+    }
+
+    b = allocbits(N);
+    if (b == NULL) {
+        fprintf(stderr, "Can't allocate bitmap.\n");
+        goto done;
+    }
+
+    if (!init_test_data()) {
+        fprintf(stderr, "Initialize crypto. GLE=%d\n", GetLastError());
+        goto done;
+    }
+
+    printf("Phase 1: Generating test data ... ");
+
+    if (!write_bitmap(h_file, b)) {
+        goto done;
+    }
+
+    ZeroMemory(&ov, sizeof(ov));
+
+    for (offset = b->o_data; offset < b->o_data + N; offset += BLOCKSIZE) {
+        BYTE buffer[BLOCKSIZE];
+        DWORD n_written = 0;
+        LARGE_INTEGER li;
+
+        if (!generate_test_data_block(offset, 0, buffer)) {
+            printf("ERROR\n");
+            fprintf(stderr, "Can't generate test data. GLE=%d\n", GetLastError());
+            goto done;
+        }
+
+        li.QuadPart = offset;
+        ov.Offset = li.LowPart;
+        ov.OffsetHigh = li.HighPart;
+
+        if (!LockFileEx(h_file, LOCKFILE_EXCLUSIVE_LOCK, 0, BLOCKSIZE, 0, &ov)) {
+            printf("ERROR\n");
+            fprintf(stderr, "Can't lock file. GLE=%d\n", GetLastError());
+            goto done;
+        }
+
+        if (!WriteFile(h_file, buffer, BLOCKSIZE, &n_written, NULL) || n_written != BLOCKSIZE) {
+            printf("ERROR\n");
+            fprintf(stderr, "Can't write data. GLE=%d\n", GetLastError());
+            goto done;
+        }
+
+        if (!UnlockFileEx(h_file, 0, BLOCKSIZE, 0, &ov)) {
+            printf("ERROR\n");
+            fprintf(stderr, "Can't unlock file. GLE=%d\n", GetLastError());
+            goto done;
+        }
+    }
+
+    printf("Done\n");
+
+    if (!FlushFileBuffers(h_file)) {
+        fprintf(stderr, "Can't flush file. GLE=%d\n", GetLastError());
+        goto done;
+    }
+
+    printf("Phase 2: Overwriting test data ... \n");
+
+    for (offset = 0; offset < M; offset += BLOCKSIZE) {
+        offset_t orandom;
+        BYTE buffer[BLOCKSIZE];
+        LARGE_INTEGER li;
+        DWORD n_written = 0;
+
+        if (!CryptGenRandom(h_prov, sizeof(orandom), (BYTE *) &orandom)) {
+            printf("ERROR\n");
+            fprintf(stderr, "Can't generate random number. GLE=%d\n", GetLastError());
+            goto done;
+        }
+
+        if (orandom < 0)
+            orandom = -orandom;
+        orandom = ((orandom % N) / BLOCKSIZE) * BLOCKSIZE;
+        orandom += b->o_data;
+
+        if (show_offsets)
+            printf("... [%I64d]\n", orandom);
+
+        if (!generate_test_data_block(orandom, 1, buffer)) {
+            printf("ERROR\n");
+            fprintf(stderr, "Can't generate test data. GLE=%d\n", GetLastError());
+            goto done;
+        }
+
+        li.QuadPart = orandom;
+        ov.Offset = li.LowPart;
+        ov.OffsetHigh = li.HighPart;
+
+        if (!LockFileEx(h_file, LOCKFILE_EXCLUSIVE_LOCK, 0, BLOCKSIZE, 0, &ov)) {
+            printf("ERROR\n");
+            fprintf(stderr, "Can't lock file. GLE=%d\n", GetLastError());
+            goto done;
+        }
+
+        if (!SetFilePointerEx(h_file, li, NULL, FILE_BEGIN)) {
+            printf("ERROR\n");
+            fprintf(stderr, "Can't set file pointer. GLE=%d\n", GetLastError());
+            goto done;
+        }
+
+        if (!WriteFile(h_file, buffer, BLOCKSIZE, &n_written, NULL) || n_written != BLOCKSIZE) {
+            printf("ERROR\n");
+            fprintf(stderr, "Can't write data. GLE=%d\n", GetLastError());
+            goto done;
+        }
+
+        if (!UnlockFileEx(h_file, 0, BLOCKSIZE, 0, &ov)) {
+            printf("ERROR\n");
+            fprintf(stderr, "Can't unlock file. GLE=%d\n", GetLastError());
+            goto done;
+        }
+
+        setbit(b, orandom);
+    }
+
+    if (!write_bitmap(h_file, b)) {
+        goto done;
+    }
+
+    printf("Done.\n");
+
+    rv = 0;
+
+ done:
+    if (b)
+        freebits(b);
+
+    if (h_file)
+        CloseHandle(h_file);
+
+    exit_test_data();
+
+    return rv;
+}
+
+BOOL show_usage(const char * fn)
+{
+    fprintf(stderr,
+            "%s : Generate or verify test data file.\n"
+            "\n"
+            "Usage: %s [-r <filename> | -w <N> <M> <filename>]\n"
+            "\n"
+            "  -w <N> <M> <filename> :\n"
+            "     First writes N bytes of random data into <filename> and then\n"
+            "     overwrites M bytes with different random data.\n"
+            "\n"
+            "  -r <filename> : \n"
+            "     Verify the contents of <filename>.  Verification succeeds if\n"
+            "     the contents of <filename> was generated using the -w option\n",
+            fn, fn);
+    return FALSE;
+}
+
+BOOL parse_cmdline(int argc, char ** argv)
+{
+    if (argc == 3) {
+        if (strcmp(argv[1], "-r"))
+            return show_usage(argv[0]);
+        verify = TRUE;
+        N = 0;
+        M = 0;
+        filename = argv[2];
+        return TRUE;
+    }
+
+    if (argc == 5) {
+        if (strcmp(argv[1], "-w"))
+            return show_usage(argv[0]);
+        verify = FALSE;
+        N = atol(argv[2]);
+        if (N == 0)
+            return show_usage(argv[0]);
+        M = atol(argv[3]);
+        if (M == 0)
+            return show_usage(argv[0]);
+        filename = argv[4];
+        return TRUE;
+    }
+
+    return show_usage(argv[0]);
+}
+
+int do_tests(void)
+{
+    if (verify)
+        return do_verify_test();
+    else
+        return do_write_test();
+}
+
+int main(int argc, char ** argv)
+{
+    if (!parse_cmdline(argc, argv))
+        return 1;
+
+    return do_tests();
+}