1 /*
2  *  (C) Copyright 2001-2006 Wojtek Kaniewski <wojtekka@irc.pl>
3  *
4  *  This program is free software; you can redistribute it and/or modify
5  *  it under the terms of the GNU Lesser General Public License Version
6  *  2.1 as published by the Free Software Foundation.
7  *
8  *  This program is distributed in the hope that it will be useful,
9  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
10  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11  *  GNU Lesser General Public License for more details.
12  *
13  *  You should have received a copy of the GNU Lesser General Public
14  *  License along with this program; if not, write to the Free Software
15  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307,
16  *  USA.
17  */
18 
19 #include "internal.h"
20 
21 #include <stdio.h>
22 #include <stdlib.h>
23 #include <unistd.h>
24 #include <string.h>
25 
26 #include "fileio.h"
27 
28 static inline int
gg_mkstemp(char * path)29 gg_mkstemp(char *path)
30 {
31 	mode_t old_umask, file_mask;
32 	int ret;
33 
34 	file_mask = S_IRWXO | S_IRWXG;
35 	old_umask = umask(file_mask);
36 #ifdef HAVE_MKSTEMP
37 	ret = mkstemp(path);
38 #else
39 #ifdef _WIN32
40 	if (_mktemp_s(path, strlen(path) + 1) != 0)
41 #else
42 	/* coverity[secure_temp : FALSE]
43 	 *
44 	 * mktemp may be unsafe, because it creates files with predictable
45 	 * names, but it's not a real problem for automatic tests.
46 	 */
47 	if (strcmp(mktemp(path), "") == 0)
48 #endif
49 		ret = -1;
50 	else
51 		ret = open(path, O_EXCL | O_RDWR | O_CREAT, file_mask);
52 #endif
53 	umask(old_umask);
54 
55 	return ret;
56 }
57 
sha1_to_string(uint8_t * sha1)58 static char *sha1_to_string(uint8_t *sha1)
59 {
60 	static char str[41];
61 	size_t i;
62 
63 	for (i = 0; i < 20; i++)
64 		sprintf(str + i * 2, "%02x", sha1[i]);
65 
66 	return str;
67 }
68 
sha1_compare(uint8_t * sha1,const char * str)69 static int sha1_compare(uint8_t *sha1, const char *str)
70 {
71 	size_t i;
72 
73 	for (i = 0; i < 20; i++) {
74 		unsigned int byte;
75 
76 		sscanf(str + i * 2, "%02x", &byte);
77 
78 		if (byte != sha1[i])
79 			return 0;
80 	}
81 
82 	return 1;
83 }
84 
85 struct login_hash {
86 	const char *password;
87 	uint32_t seed;
88 	const char *expect;
89 };
90 
91 struct login_hash login_hashes[] = {
92 	{ "AAAA", 0x41414141, "c08598945e566e4e53cf3654c922fa98003bf2f9" },
93 	{ "test", 0x41424344, "459d3fbcfd3a91ef4fe64e151d950e0997af4ba4" },
94 };
95 
test_login_hash(const char * password,uint32_t seed,const char * expect)96 static void test_login_hash(const char *password, uint32_t seed, const char *expect)
97 {
98 	uint8_t result[20];
99 
100 	if (gg_login_hash_sha1_2(password, seed, result) == -1) {
101 		fprintf(stderr, "gg_login_hash_sha1_2() failed for \"%s\", 0x%08x\n", password, seed);
102 		exit(1);
103 	}
104 
105 	if (!sha1_compare(result, expect)) {
106 		printf("hash failed for \"%s\", 0x%08x, expected %s, got %s\n",
107 			password, seed, expect, sha1_to_string(result));
108 		exit(1);
109 	}
110 }
111 
112 struct file_hash {
113 	unsigned int megs;
114 	const char *expect;
115 };
116 
117 struct file_hash file_hashes[] = {
118 	{ 0, "da39a3ee5e6b4b0d3255bfef95601890afd80709" },
119 	{ 1, "ad03e557eeed1f108ed9f5a54f9d0255f69c168e" },
120 	{ 2, "45afb38af4ba1e161f6fde18818a4acbe87a1c88" },
121 	{ 9, "940a5611380985416844aa6fb3767b38e4aac59f" },
122 	{ 10, "8f7659b0fa3994fcce2be062bbea0d183e9bc44e" },
123 	{ 11, "43c12a04edda27d2a87c8c85aa5680bf36bdb0c0" },
124 	{ 12, "f40bdc59b7b073735e6e53ce9fa67f17978ef236" },
125 };
126 
test_file_hash(unsigned int megs,const char * expect)127 static void test_file_hash(unsigned int megs, const char *expect)
128 {
129 	int fd;
130 	size_t i;
131 	char name[32];
132 	uint8_t result[20];
133 
134 	strcpy(name, "hashdata.XXXXXX");
135 
136 	fd = gg_mkstemp(name);
137 
138 	if (fd == -1) {
139 		fprintf(stderr, "Unable to create temporary file\n");
140 		exit(1);
141 	}
142 
143 	for (i = 1; i <= megs; i++) {
144 		unsigned char j;
145 
146 		if (lseek(fd, i * 1048756 - 1, SEEK_SET) == (off_t) -1) {
147 			fprintf(stderr, "Unable to seek past end of file\n");
148 			goto fail;
149 		}
150 
151 		j = i;
152 
153 		if (write(fd, &j, sizeof(j)) != sizeof(j)) {
154 			fprintf(stderr, "Unable to write past end of file\n");
155 			goto fail;
156 		}
157 	}
158 
159 	if (gg_file_hash_sha1(fd, result) == -1) {
160 		fprintf(stderr, "gg_file_hash_sha1() failed for %d megs\n", megs);
161 		goto fail;
162 	}
163 
164 	if (!sha1_compare(result, expect)) {
165 		printf("hash failed for %d mesgs, expected %s, got %s\n", megs, expect, sha1_to_string(result));
166 		goto fail;
167 	}
168 
169 	close(fd);
170 	unlink(name);
171 	return;
172 
173 fail:
174 	close(fd);
175 	unlink(name);
176 	exit(1);
177 }
178 
main(void)179 int main(void)
180 {
181 	unsigned int i;
182 
183 	for (i = 0; i < sizeof(login_hashes) / sizeof(login_hashes[0]); i++)
184 		test_login_hash(login_hashes[i].password, login_hashes[i].seed, login_hashes[i].expect);
185 
186 	for (i = 0; i < sizeof(file_hashes) / sizeof(file_hashes[0]); i++)
187 		test_file_hash(file_hashes[i].megs, file_hashes[i].expect);
188 
189 	return 0;
190 }
191