summaryrefslogtreecommitdiff
path: root/net-libs/rest/files/rest-0.10.2-CVE-2026-16615.patch
blob: 749c97b16b484a138650ad4fc1fceeb7abd61b16 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
From fe1e7672efdf22eeb5cbe30d6adc485bc55fa021 Mon Sep 17 00:00:00 2001
From: Milan Crha <mcrha@redhat.com>
Date: Thu, 23 Jul 2026 09:44:31 +0200
Subject: [PATCH] utils: Replace GRand with cryptographically secure random
 generator (CVE-2026-16615)

The GRand is not supposed to be used for cryptography, replace it
with a cryptographically secure random generator and require it
to be available during the setup phase. The library will abort
in case the runtime cannot create a random number (only for
rare cases where the very last fallback to /dev/urandom fails
to read from the device, which is used on some old platforms).

Fixes https://gitlab.gnome.org/GNOME/librest/-/issues/25
---
 meson.build       | 29 ++++++++++++++++++++
 rest/meson.build  |  2 +-
 rest/rest-utils.c | 70 +++++++++++++++++++++++++++++++++++++++++++----
 3 files changed, 95 insertions(+), 6 deletions(-)

diff --git a/meson.build b/meson.build
index 4e2a272..2919fb6 100644
--- a/meson.build
+++ b/meson.build
@@ -60,6 +60,8 @@ libsoup_dep = dependency(libsoup_name, version: libsoup_req_version)
 libjson_glib_dep = dependency('json-glib-1.0')
 libxml_dep = dependency('libxml-2.0')
 
+cc = meson.get_compiler('c')
+
 # config.h
 conf = configuration_data()
 conf.set_quoted('PACKAGE_NAME', meson.project_name())
@@ -68,6 +70,33 @@ conf.set_quoted('PACKAGE_VERSION', meson.project_version())
 if get_option('ca_certificates')
   conf.set_quoted('REST_SYSTEM_CA_FILE', ca_certificates_path)
 endif
+
+# CSPRNG detection for secure random string generation (required)
+have_csprng = false
+if cc.has_function('arc4random_buf', prefix: '#include <stdlib.h>')
+  conf.set('HAVE_ARC4RANDOM_BUF', 1)
+  have_csprng = true
+endif
+if cc.has_function('getrandom', prefix: '#include <sys/random.h>')
+  conf.set('HAVE_GETRANDOM', 1)
+  have_csprng = true
+endif
+
+csprng_deps = []
+if host_machine.system() == 'windows'
+  bcrypt_lib = cc.find_library('bcrypt', required: false)
+  if bcrypt_lib.found()
+    csprng_deps += bcrypt_lib
+    conf.set('HAVE_BCRYPTGENRANDOM', 1)
+    have_csprng = true
+  endif
+endif
+
+if not have_csprng
+  error('No cryptographically secure random source found. ' +
+        'librest requires arc4random_buf(), getrandom(), or BCryptGenRandom().')
+endif
+
 config_h = configure_file(output: 'config.h', configuration: conf)
 root_inc = include_directories('.')
 config_dep = declare_dependency(
diff --git a/rest/meson.build b/rest/meson.build
index bfecb9f..1c1cbd5 100644
--- a/rest/meson.build
+++ b/rest/meson.build
@@ -62,7 +62,7 @@ librest_deps = [
   libjson_glib_dep,
   libxml_dep,
   config_dep,
-]
+] + csprng_deps
 
 librest_c_args = [
   '-DG_LOG_DOMAIN="Rest"',
diff --git a/rest/rest-utils.c b/rest/rest-utils.c
index df283e0..346c83b 100644
--- a/rest/rest-utils.c
+++ b/rest/rest-utils.c
@@ -16,29 +16,89 @@
  * Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
  */
 
+#include "config.h"
 #include "rest-utils.h"
 
+#ifdef HAVE_ARC4RANDOM_BUF
+#include <stdlib.h>
+#endif
+
+#ifdef HAVE_GETRANDOM
+#include <errno.h>
+#include <sys/random.h>
+#endif
+
+#ifdef HAVE_BCRYPTGENRANDOM
+#define WIN32_LEAN_AND_MEAN
+#include <windows.h>
+#include <bcrypt.h>
+#endif
+
+#if defined(HAVE_ARC4RANDOM_BUF)
+
+static void
+crypto_random_bytes (guchar *buffer,
+                     gsize   length)
+{
+  arc4random_buf (buffer, length);
+}
+
+#elif defined(HAVE_BCRYPTGENRANDOM)
+
+static void
+crypto_random_bytes (guchar *buffer,
+                     gsize   length)
+{
+  BCryptGenRandom (NULL, buffer, (ULONG) length,
+                   BCRYPT_USE_SYSTEM_PREFERRED_RNG);
+}
+
+#elif defined(HAVE_GETRANDOM)
+
+static void
+crypto_random_bytes (guchar *buffer,
+                     gsize   length)
+{
+  gsize pos = 0;
+
+  while (pos < length)
+    {
+      gssize ret = getrandom (buffer + pos, length - pos, 0);
+      if (ret < 0)
+        {
+          if (errno == EINTR)
+            continue;
+          g_error ("getrandom() failed: %s", g_strerror (errno));
+        }
+      pos += (gsize) ret;
+    }
+}
+
+#endif /* platform selection */
+
 /**
  * random_string:
  * @length: the length of the random string
  *
- * Creates a random string from a given alphabeth with length @length
+ * Creates a random string from a given alphabet with length @length.
  *
  * Returns: (transfer full): a random string
  */
 gchar *
 random_string (guint length)
 {
-  g_autoptr(GRand) rand = g_rand_new ();
   gchar *buffer = g_malloc0 (sizeof (gchar) * length + 1);
-  gchar alphabeth[] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-._~";
+  gchar alphabet[] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-._~";
+  guint alphabet_len = sizeof (alphabet) - 1;
+  g_autofree guchar *rand_bytes = g_malloc (length);
+
+  crypto_random_bytes (rand_bytes, length);
 
   for (guint i = 0; i < length; i++)
     {
-      buffer[i] = alphabeth[g_rand_int (rand) % (sizeof (alphabeth) - 1)];
+      buffer[i] = alphabet[rand_bytes[i] % alphabet_len];
     }
   buffer[length] = '\0';
 
   return buffer;
 }
-
-- 
GitLab