source: trunk/src/sh_guid.c@ 556

Last change on this file since 556 was 481, checked in by katerina, 9 years ago

Enhancements and fixes for tickets #374, #375, #376, #377, #378, and #379.

File size: 9.1 KB
Line 
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
63struct 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
71typedef unsigned char uuid_t[16];
72
73
74static 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
107static 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
134static 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
159static 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
176static const char *fmt_lower = N_("%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x");
177
178static 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__)
198static 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
218static 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
228char * 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>
243int 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
273static 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
289static 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
306static 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
332void 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
Note: See TracBrowser for help on using the repository browser.