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