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