Branch data Line data Source code
1 : : /* guuid.c - UUID functions
2 : : *
3 : : * Copyright (C) 2013-2015, 2017 Red Hat, Inc.
4 : : *
5 : : * This library is free software; you can redistribute it and/or modify
6 : : * it under the terms of the GNU Lesser General Public License as
7 : : * published by the Free Software Foundation; either version 2.1 of the
8 : : * licence, or (at your option) any later version.
9 : : *
10 : : * This is distributed in the hope that it will be useful, but WITHOUT
11 : : * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12 : : * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
13 : : * License for more details.
14 : : *
15 : : * You should have received a copy of the GNU Lesser General Public
16 : : * License along with this library; if not, write to the Free Software
17 : : * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
18 : : * USA.
19 : : *
20 : : * Authors: Marc-André Lureau <marcandre.lureau@redhat.com>
21 : : */
22 : :
23 : : #include "config.h"
24 : : #include <string.h>
25 : :
26 : : #include "gi18n.h"
27 : : #include "gstrfuncs.h"
28 : : #include "grand.h"
29 : : #include "gmessages.h"
30 : : #include "gchecksum.h"
31 : :
32 : : #include "guuid.h"
33 : :
34 : : typedef struct {
35 : : guint8 bytes[16];
36 : : } GUuid;
37 : :
38 : : /*
39 : : * g_uuid_to_string:
40 : : * @uuid: a #GUuid
41 : : *
42 : : * Creates a string representation of @uuid, of the form
43 : : * 06e023d5-86d8-420e-8103-383e4566087a (no braces nor urn:uuid:
44 : : * prefix).
45 : : *
46 : : * Returns: (transfer full): A string that should be freed with g_free().
47 : : * Since: STATIC
48 : : */
49 : : static gchar *
50 : 2 : g_uuid_to_string (const GUuid *uuid)
51 : : {
52 : : const guint8 *bytes;
53 : :
54 : 2 : g_return_val_if_fail (uuid != NULL, NULL);
55 : :
56 : 2 : bytes = uuid->bytes;
57 : :
58 : 2 : return g_strdup_printf ("%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x"
59 : : "-%02x%02x%02x%02x%02x%02x",
60 : 2 : bytes[0], bytes[1], bytes[2], bytes[3],
61 : 2 : bytes[4], bytes[5], bytes[6], bytes[7],
62 : 2 : bytes[8], bytes[9], bytes[10], bytes[11],
63 : 2 : bytes[12], bytes[13], bytes[14], bytes[15]);
64 : : }
65 : :
66 : : static gboolean
67 : 12 : uuid_parse_string (const gchar *str,
68 : : GUuid *uuid)
69 : : {
70 : : GUuid tmp;
71 : 12 : guint8 *bytes = tmp.bytes;
72 : : gint i, j, hi, lo;
73 : 12 : guint expected_len = 36;
74 : :
75 [ + + ]: 12 : if (strlen (str) != expected_len)
76 : 5 : return FALSE;
77 : :
78 [ + + ]: 127 : for (i = 0, j = 0; i < 16;)
79 : : {
80 [ + + + + : 121 : if (j == 8 || j == 13 || j == 18 || j == 23)
+ + + + ]
81 : : {
82 [ - + ]: 24 : if (str[j++] != '-')
83 : 0 : return FALSE;
84 : :
85 : 24 : continue;
86 : : }
87 : :
88 : 97 : hi = g_ascii_xdigit_value (str[j++]);
89 : 97 : lo = g_ascii_xdigit_value (str[j++]);
90 : :
91 [ + + - + ]: 97 : if (hi == -1 || lo == -1)
92 : 1 : return FALSE;
93 : :
94 : 96 : bytes[i++] = hi << 4 | lo;
95 : : }
96 : :
97 [ - + ]: 6 : if (uuid != NULL)
98 : 0 : *uuid = tmp;
99 : :
100 : 6 : return TRUE;
101 : : }
102 : :
103 : : /**
104 : : * g_uuid_string_is_valid:
105 : : * @str: a string representing a UUID
106 : : *
107 : : * Parses the string @str and verify if it is a UUID.
108 : : *
109 : : * The function accepts the following syntax:
110 : : *
111 : : * - simple forms (e.g. `f81d4fae-7dec-11d0-a765-00a0c91e6bf6`)
112 : : *
113 : : * Note that hyphens are required within the UUID string itself,
114 : : * as per the aforementioned RFC.
115 : : *
116 : : * Returns: %TRUE if @str is a valid UUID, %FALSE otherwise.
117 : : * Since: 2.52
118 : : */
119 : : gboolean
120 : 12 : g_uuid_string_is_valid (const gchar *str)
121 : : {
122 : 12 : g_return_val_if_fail (str != NULL, FALSE);
123 : :
124 : 12 : return uuid_parse_string (str, NULL);
125 : : }
126 : :
127 : : static void
128 : 2 : uuid_set_version (GUuid *uuid, guint version)
129 : : {
130 : 2 : guint8 *bytes = uuid->bytes;
131 : :
132 : : /*
133 : : * Set the four most significant bits (bits 12 through 15) of the
134 : : * time_hi_and_version field to the 4-bit version number from
135 : : * Section 4.1.3.
136 : : */
137 : 2 : bytes[6] &= 0x0f;
138 : 2 : bytes[6] |= version << 4;
139 : : /*
140 : : * Set the two most significant bits (bits 6 and 7) of the
141 : : * clock_seq_hi_and_reserved to zero and one, respectively.
142 : : */
143 : 2 : bytes[8] &= 0x3f;
144 : 2 : bytes[8] |= 0x80;
145 : 2 : }
146 : :
147 : : /*
148 : : * g_uuid_generate_v4:
149 : : * @uuid: a #GUuid
150 : : *
151 : : * Generates a random UUID (RFC 4122 version 4).
152 : : * Since: STATIC
153 : : */
154 : : static void
155 : 2 : g_uuid_generate_v4 (GUuid *uuid)
156 : : {
157 : : int i;
158 : : guint8 *bytes;
159 : : guint32 *ints;
160 : :
161 : 2 : g_return_if_fail (uuid != NULL);
162 : :
163 : 2 : bytes = uuid->bytes;
164 : 2 : ints = (guint32 *) bytes;
165 [ + + ]: 10 : for (i = 0; i < 4; i++)
166 : 8 : ints[i] = g_random_int ();
167 : :
168 : 2 : uuid_set_version (uuid, 4);
169 : : }
170 : :
171 : : /**
172 : : * g_uuid_string_random:
173 : : *
174 : : * Generates a random UUID (RFC 4122 version 4) as a string. It has the same
175 : : * randomness guarantees as #GRand, so must not be used for cryptographic
176 : : * purposes such as key generation, nonces, salts or one-time pads.
177 : : *
178 : : * Returns: (transfer full): A string that should be freed with g_free().
179 : : * Since: 2.52
180 : : */
181 : : gchar *
182 : 2 : g_uuid_string_random (void)
183 : : {
184 : : GUuid uuid;
185 : :
186 : 2 : g_uuid_generate_v4 (&uuid);
187 : :
188 : 2 : return g_uuid_to_string (&uuid);
189 : : }
|