1 /* SAMHAIN file system integrity testing */
2 /* Copyright (C) 2015 Rainer Wichmann */
3 /* */
4 /* This program is free software; you can redistribute it */
5 /* and/or modify */
6 /* it under the terms of the GNU General Public License as */
7 /* published by */
8 /* the Free Software Foundation; either version 2 of the License, or */
9 /* (at your option) any later version. */
10 /* */
11 /* This program is distributed in the hope that it will be useful, */
12 /* but WITHOUT ANY WARRANTY; without even the implied warranty of */
13 /* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */
14 /* GNU General Public License for more details. */
15 /* */
16 /* You should have received a copy of the GNU General Public License */
17 /* along with this program; if not, write to the Free Software */
18 /* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
19
20 #include "config_xor.h"
21 #include "samhain.h"
22 #include "sh_utils.h"
23
24 #include <stdio.h>
25 #include <string.h>
26
27 /*
28 * gen_uuid.c --- generate a DCE-compatible uuid
29 *
30 * Copyright (C) 1996, 1997, 1998, 1999 Theodore Ts'o.
31 *
32 * %Begin-Header%
33 * Redistribution and use in source and binary forms, with or without
34 * modification, are permitted provided that the following conditions
35 * are met:
36 * 1. Redistributions of source code must retain the above copyright
37 * notice, and the entire permission notice in its entirety,
38 * including the disclaimer of warranties.
39 * 2. Redistributions in binary form must reproduce the above copyright
40 * notice, this list of conditions and the following disclaimer in the
41 * documentation and/or other materials provided with the distribution.
42 * 3. The name of the author may not be used to endorse or promote
43 * products derived from this software without specific prior
44 * written permission.
45 *
46 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
47 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
48 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ALL OF
49 * WHICH ARE HEREBY DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE
50 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
51 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
52 * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
53 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
54 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
55 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
56 * USE OF THIS SOFTWARE, EVEN IF NOT ADVISED OF THE POSSIBILITY OF SUCH
57 * DAMAGE.
58 * %End-Header%
59 */
60
61 #define UUID_SIZE 36
62
63 struct uuid {
64 UINT32 time_low;
65 UINT16 time_mid;
66 UINT16 time_hi_and_version;
67 UINT16 clock_seq;
68 UBYTE node[6];
69 };
70
71 typedef unsigned char uuid_t[16];
72
73
uuid_pack(const struct uuid * uu,uuid_t ptr)74 static void uuid_pack(const struct uuid *uu, uuid_t ptr)
75 {
76 UINT32 tmp;
77 unsigned char *out = ptr;
78
79 tmp = uu->time_low;
80 out[3] = (unsigned char) tmp;
81 tmp >>= 8;
82 out[2] = (unsigned char) tmp;
83 tmp >>= 8;
84 out[1] = (unsigned char) tmp;
85 tmp >>= 8;
86 out[0] = (unsigned char) tmp;
87
88 tmp = uu->time_mid;
89 out[5] = (unsigned char) tmp;
90 tmp >>= 8;
91 out[4] = (unsigned char) tmp;
92
93 tmp = uu->time_hi_and_version;
94 out[7] = (unsigned char) tmp;
95 tmp >>= 8;
96 out[6] = (unsigned char) tmp;
97
98 tmp = uu->clock_seq;
99 out[9] = (unsigned char) tmp;
100 tmp >>= 8;
101 out[8] = (unsigned char) tmp;
102
103 memcpy(out+10, uu->node, 6);
104 return;
105 }
106
uuid_unpack(const uuid_t in,struct uuid * uu)107 static void uuid_unpack(const uuid_t in, struct uuid *uu)
108 {
109 const uint8_t *ptr = in;
110 uint32_t tmp;
111
112 tmp = *ptr++;
113 tmp = (tmp << 8) | *ptr++;
114 tmp = (tmp << 8) | *ptr++;
115 tmp = (tmp << 8) | *ptr++;
116 uu->time_low = tmp;
117
118 tmp = *ptr++;
119 tmp = (tmp << 8) | *ptr++;
120 uu->time_mid = tmp;
121
122 tmp = *ptr++;
123 tmp = (tmp << 8) | *ptr++;
124 uu->time_hi_and_version = tmp;
125
126 tmp = *ptr++;
127 tmp = (tmp << 8) | *ptr++;
128 uu->clock_seq = tmp;
129
130 memcpy(uu->node, ptr, 6);
131 return;
132 }
133
get_random_bytes(unsigned char * buf,size_t len)134 static void get_random_bytes(unsigned char * buf, size_t len)
135 {
136 unsigned int j;
137
138 union {
139 UINT32 i;
140 char c[sizeof(UINT32)];
141 } u;
142
143 do {
144 u.i = taus_get();
145
146 for (j= 0; j < sizeof(UINT32); j++)
147 {
148 if (len) {
149 --len;
150 *buf = u.c[j];
151 ++buf;
152 }
153 }
154 } while (len);
155
156 return;
157 }
158
uuid_generate_random(uuid_t out)159 static void uuid_generate_random(uuid_t out)
160 {
161 uuid_t buf;
162 struct uuid uu;
163
164 get_random_bytes(buf, sizeof(buf));
165 uuid_unpack(buf, &uu);
166
167 /* Version and variant
168 */
169 uu.clock_seq = (uu.clock_seq & 0x3FFF) | 0x8000;
170 uu.time_hi_and_version = (uu.time_hi_and_version & 0x0FFF)
171 | 0x4000;
172 uuid_pack(&uu, out);
173 return;
174 }
175
176 static const char *fmt_lower = N_("%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x");
177
uuid_unparse(const uuid_t uu,char * out,size_t len)178 static void uuid_unparse(const uuid_t uu, char *out, size_t len)
179 {
180 struct uuid uuid;
181 char fmt[80];
182
183
184 sl_strlcpy(fmt, _(fmt_lower), sizeof(fmt));
185
186 uuid_unpack(uu, &uuid);
187
188 sl_snprintf (out, len, fmt,
189 uuid.time_low, uuid.time_mid, uuid.time_hi_and_version,
190 uuid.clock_seq >> 8, uuid.clock_seq & 0xFF,
191 uuid.node[0], uuid.node[1], uuid.node[2],
192 uuid.node[3], uuid.node[4], uuid.node[5]);
193
194 return;
195 }
196
197 #if defined(__linux__)
uuid_generate_random_linux(char * out,size_t len)198 static char * uuid_generate_random_linux(char * out, size_t len)
199 {
200 FILE * fd = fopen(_("/proc/sys/kernel/random/uuid"), "r");
201
202 if (fd)
203 {
204 if (NULL != fgets(out, len, fd))
205 {
206 size_t ll = strlen(out);
207 if (ll > 0 && out[ll-1] == '\n') {
208 --ll;
209 out[ll] = '\0';
210 }
211 }
212 fclose(fd);
213 }
214 return out;
215 }
216 #endif
217
uuid_generate_random_gen(char * out,size_t len)218 static char * uuid_generate_random_gen(char * out, size_t len)
219 {
220 uuid_t u;
221
222 uuid_generate_random(u);
223 uuid_unparse(u, out, len);
224
225 return out;
226 }
227
sh_uuid_generate_random(char * out,size_t len)228 char * sh_uuid_generate_random(char * out, size_t len)
229 {
230 *out = '\0';
231
232 #if defined(__linux__)
233 uuid_generate_random_linux(out, len);
234 if (UUID_SIZE == strlen(out))
235 return out;
236 #endif
237
238 uuid_generate_random_gen(out, len);
239 return out;
240 }
241
242 #include <ctype.h>
sh_uuid_check(const char * in)243 int sh_uuid_check(const char * in)
244 {
245 int i;
246 const char *cp;
247
248 if (strlen(in) != UUID_SIZE)
249 return -1;
250 for (i=0, cp = in; i <= UUID_SIZE; i++,cp++) {
251 if ((i == 8) || (i == 13) || (i == 18) ||
252 (i == 23)) {
253 if (*cp == '-')
254 continue;
255 else
256 return -1;
257 }
258 if (i== UUID_SIZE)
259 if (*cp == 0)
260 continue;
261 if (!isxdigit(*cp))
262 return -1;
263 }
264 return 0;
265 }
266
267
268 #ifdef SH_CUTEST
269 #include "CuTest.h"
270
271 #include <stdlib.h>
272
uuid_type(const uuid_t uu)273 static int uuid_type(const uuid_t uu)
274 {
275 struct uuid uuid;
276
277 uuid_unpack(uu, &uuid);
278 return ((uuid.time_hi_and_version >> 12) & 0xF);
279 }
280
281 #define UUID_VARIANT_NCS 0
282 #define UUID_VARIANT_DCE 1
283 #define UUID_VARIANT_MICROSOFT 2
284 #define UUID_VARIANT_OTHER 3
285
286 #define UUID_TYPE_DCE_TIME 1
287 #define UUID_TYPE_DCE_RANDOM 4
288
uuid_variant(const uuid_t uu)289 static int uuid_variant(const uuid_t uu)
290 {
291 struct uuid uuid;
292 int var;
293
294 uuid_unpack(uu, &uuid);
295 var = uuid.clock_seq;
296
297 if ((var & 0x8000) == 0)
298 return UUID_VARIANT_NCS;
299 if ((var & 0x4000) == 0)
300 return UUID_VARIANT_DCE;
301 if ((var & 0x2000) == 0)
302 return UUID_VARIANT_MICROSOFT;
303 return UUID_VARIANT_OTHER;
304 }
305
uuid_parse(const char * in,uuid_t uu)306 static int uuid_parse(const char *in, uuid_t uu)
307 {
308 struct uuid uuid;
309 int i;
310 const char *cp;
311 char buf[3];
312
313 if (sh_uuid_check(in) < 0)
314 return -1;
315
316 uuid.time_low = strtoul(in, NULL, 16);
317 uuid.time_mid = strtoul(in+9, NULL, 16);
318 uuid.time_hi_and_version = strtoul(in+14, NULL, 16);
319 uuid.clock_seq = strtoul(in+19, NULL, 16);
320 cp = in+24;
321 buf[2] = 0;
322 for (i=0; i < 6; i++) {
323 buf[0] = *cp++;
324 buf[1] = *cp++;
325 uuid.node[i] = strtoul(buf, NULL, 16);
326 }
327
328 uuid_pack(&uuid, uu);
329 return 0;
330 }
331
Test_uuid(CuTest * tc)332 void Test_uuid (CuTest *tc) {
333
334 char * p; int res;
335 char out[80];
336 size_t len = sizeof(out);
337 uuid_t uu;
338 int type, variant;
339
340 p = uuid_generate_random_gen(out, len);
341 CuAssertPtrNotNull(tc, p);
342 res = strlen(p);
343 CuAssertIntEquals(tc,UUID_SIZE,res);
344 res = uuid_parse(p, uu);
345 CuAssertIntEquals(tc,0,res);
346 type = uuid_type(uu);
347 CuAssertIntEquals(tc,UUID_TYPE_DCE_RANDOM,type);
348 variant = uuid_variant(uu);
349 CuAssertIntEquals(tc,UUID_VARIANT_DCE,variant);
350
351 #if defined(__linux__)
352 p = uuid_generate_random_linux(out, len);
353 CuAssertPtrNotNull(tc, p);
354 res = strlen(p);
355 CuAssertIntEquals(tc,UUID_SIZE,res);
356 res = uuid_parse(p, uu);
357 CuAssertIntEquals(tc,0,res);
358 type = uuid_type(uu);
359 CuAssertIntEquals(tc,UUID_TYPE_DCE_RANDOM,type);
360 variant = uuid_variant(uu);
361 CuAssertIntEquals(tc,UUID_VARIANT_DCE,variant);
362 #endif
363
364 p = sh_uuid_generate_random(out, len);
365 CuAssertPtrNotNull(tc, p);
366 res = strlen(p);
367 CuAssertIntEquals(tc,UUID_SIZE,res);
368 res = uuid_parse(p, uu);
369 CuAssertIntEquals(tc,0,res);
370 type = uuid_type(uu);
371 CuAssertIntEquals(tc,UUID_TYPE_DCE_RANDOM,type);
372 variant = uuid_variant(uu);
373 CuAssertIntEquals(tc,UUID_VARIANT_DCE,variant);
374
375 }
376 #endif
377