source: trunk/src/sh_guid.c @ 481

Last change on this file since 481 was 481, checked in by katerina, 6 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.