Coverage Report

Created: 2024-02-11 06:22

/src/dovecot/src/lib/guid.c
Line
Count
Source (jump to first uncovered line)
1
/* Copyright (c) 2011-2018 Dovecot authors, see the included COPYING file */
2
3
#include "lib.h"
4
#include "ioloop.h"
5
#include "buffer.h"
6
#include "str.h"
7
#include "sha1.h"
8
#include "hash.h"
9
#include "hex-binary.h"
10
#include "hostpid.h"
11
#include "guid.h"
12
#include "randgen.h"
13
14
#include <unistd.h>
15
#include <time.h>
16
17
const char *guid_generate(void)
18
0
{
19
0
  static struct timespec ts = { 0, 0 };
20
0
  static unsigned int pid = 0;
21
22
  /* we'll use the current time in nanoseconds as the initial 64bit
23
     counter. */
24
0
  if (ts.tv_sec == 0) {
25
0
    if (clock_gettime(CLOCK_REALTIME, &ts) < 0)
26
0
      i_fatal("clock_gettime() failed: %m");
27
0
    pid = getpid();
28
0
  } else if ((uint32_t)ts.tv_nsec < (uint32_t)-1) {
29
0
    ts.tv_nsec++;
30
0
  } else {
31
0
    ts.tv_sec++;
32
0
    ts.tv_nsec = 0;
33
0
  }
34
0
  return t_strdup_printf("%08x%08lx.%x.%s",
35
0
             (unsigned int)ts.tv_nsec,
36
0
             (unsigned long)ts.tv_sec,
37
0
             pid, my_hostname);
38
0
}
39
40
void guid_128_host_hash_get(const char *host,
41
          unsigned char hash_r[STATIC_ARRAY GUID_128_HOST_HASH_SIZE])
42
1
{
43
1
  unsigned char full_hash[SHA1_RESULTLEN];
44
45
1
  sha1_get_digest(host, strlen(host), full_hash);
46
1
  memcpy(hash_r, full_hash + sizeof(full_hash)-GUID_128_HOST_HASH_SIZE,
47
1
         GUID_128_HOST_HASH_SIZE);
48
1
}
49
50
void guid_128_generate(guid_128_t guid_r)
51
6.27k
{
52
#if GUID_128_HOST_HASH_SIZE != 4
53
#  error GUID_128_HOST_HASH_SIZE must be 4
54
#endif
55
6.27k
  static struct timespec ts = { 0, 0 };
56
6.27k
  static uint8_t guid_static[8];
57
6.27k
  uint32_t pid;
58
59
  /* we'll use the current time in nanoseconds as the initial 64bit
60
     counter. */
61
6.27k
  if (ts.tv_sec == 0) {
62
1
    if (clock_gettime(CLOCK_REALTIME, &ts) < 0)
63
0
      i_fatal("clock_gettime() failed: %m");
64
1
    pid = getpid();
65
66
1
    guid_static[0] = (pid & 0x000000ff);
67
1
    guid_static[1] = (pid & 0x0000ff00) >> 8;
68
1
    guid_static[2] = (pid & 0x00ff0000) >> 16;
69
1
    guid_static[3] = (pid & 0xff000000) >> 24;
70
1
    guid_128_host_hash_get(my_hostdomain(), guid_static+4);
71
6.27k
  } else if (ioloop_timeval.tv_sec > ts.tv_sec ||
72
6.27k
       (ioloop_timeval.tv_sec == ts.tv_sec &&
73
6.27k
        ioloop_timeval.tv_usec * 1000 > ts.tv_nsec)) {
74
    /* use ioloop's time since we have it. it doesn't provide any
75
       more uniqueness, but it allows finding out more reliably
76
       when a GUID was created. */
77
6.27k
    ts.tv_sec = ioloop_timeval.tv_sec;
78
6.27k
    ts.tv_nsec = ioloop_timeval.tv_usec*1000;
79
6.27k
  } else if (ts.tv_nsec < 999999999L) {
80
0
    ts.tv_nsec++;
81
0
  } else {
82
0
    ts.tv_sec++;
83
0
    ts.tv_nsec = 0;
84
0
  }
85
86
6.27k
  guid_r[0] = (ts.tv_nsec & 0x000000ff);
87
6.27k
  guid_r[1] = (ts.tv_nsec & 0x0000ff00) >> 8;
88
6.27k
  guid_r[2] = (ts.tv_nsec & 0x00ff0000) >> 16;
89
6.27k
  guid_r[3] = (ts.tv_nsec & 0xff000000) >> 24;
90
6.27k
  guid_r[4] = (ts.tv_sec & 0x000000ff);
91
6.27k
  guid_r[5] = (ts.tv_sec & 0x0000ff00) >> 8;
92
6.27k
  guid_r[6] = (ts.tv_sec & 0x00ff0000) >> 16;
93
6.27k
  guid_r[7] = (ts.tv_sec & 0xff000000) >> 24;
94
6.27k
  memcpy(guid_r + 8, guid_static, 8);
95
6.27k
}
96
97
void guid_128_uuid4_generate(guid_128_t uuid)
98
0
{
99
0
  random_fill(uuid, sizeof(guid_128_t));
100
0
  uuid[6] = (uuid[6] & 0x0F) | 0x40; /* Set version 4 */
101
0
  uuid[8] = (uuid[8] & 0xBF) | 0x80; /* Set variant 2 (first 2 bits to 10) */
102
0
}
103
104
bool guid_128_is_empty(const guid_128_t guid)
105
0
{
106
0
  unsigned int i;
107
108
0
  for (i = 0; i < GUID_128_SIZE; i++) {
109
0
    if (guid[i] != 0)
110
0
      return FALSE;
111
0
  }
112
0
  return TRUE;
113
0
}
114
115
bool guid_128_equals(const guid_128_t guid1, const guid_128_t guid2)
116
0
{
117
0
  return memcmp(guid1, guid2, GUID_128_SIZE) == 0;
118
0
}
119
120
int guid_128_from_string(const char *str, guid_128_t guid_r)
121
0
{
122
0
  buffer_t buf;
123
124
0
  buffer_create_from_data(&buf, guid_r, GUID_128_SIZE);
125
0
  return strlen(str) == GUID_128_SIZE*2 &&
126
0
    hex_to_binary(str, &buf) == 0 &&
127
0
    buf.used == GUID_128_SIZE ? 0 : -1;
128
0
}
129
130
const char *guid_128_to_string(const guid_128_t guid)
131
0
{
132
0
  return binary_to_hex(guid, GUID_128_SIZE);
133
0
}
134
135
unsigned int guid_128_hash(const guid_128_t guid)
136
0
{
137
0
  return mem_hash(guid, GUID_128_SIZE);
138
0
}
139
140
int guid_128_cmp(const guid_128_t guid1, const guid_128_t guid2)
141
0
{
142
0
  return memcmp(guid1, guid2, GUID_128_SIZE);
143
0
}
144
145
const char *guid_128_to_uuid_string(const guid_128_t guid, enum uuid_format format)
146
0
{
147
0
  switch(format) {
148
0
  case FORMAT_COMPACT:
149
0
    return guid_128_to_string(guid);
150
0
  case FORMAT_RECORD:
151
0
    return t_strdup_printf("%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x",
152
0
        guid[0], guid[1], guid[2], guid[3], guid[4],
153
0
        guid[5], guid[6], guid[7], guid[8], guid[9],
154
0
        guid[10], guid[11], guid[12], guid[13], guid[14],
155
0
        guid[15]);
156
0
  case FORMAT_MICROSOFT:
157
0
    return t_strdup_printf("{%s}", guid_128_to_uuid_string(guid, FORMAT_RECORD));
158
0
  }
159
0
  i_unreached();
160
0
}
161
162
int guid_128_from_uuid_string(const char *str, guid_128_t guid_r)
163
0
{
164
0
  size_t i,len,m=0;
165
0
  int ret;
166
0
  T_BEGIN {
167
0
    len = strlen(str);
168
0
    string_t *str2 = t_str_new(len);
169
0
    for(i=0; i < len; i++) {
170
      /* Microsoft format */
171
0
      if (i==0 && str[i] == '{') { m=1; continue; }
172
0
      else if (i == len-1 && str[i] == '}') continue;
173
      /* 8-4-4-4-12 */
174
0
      if (((i==8+m) || (i==13+m) || (i==18+m) || (i==23+m)) &&
175
0
          str[i] == '-') continue;
176
0
      str_append_c(str2, str[i]);
177
0
    }
178
0
    ret = guid_128_from_string(str_c(str2), guid_r);
179
0
  } T_END;
180
181
0
  return ret;
182
0
}