Greenbone Vulnerability Management Libraries 22.8.0
radiusutils.c
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2015-2023 Greenbone AG
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later
4 */
5
11#include "radiusutils.h"
12#ifdef ENABLE_RADIUS_AUTH
13
14#include <arpa/inet.h> /* for inet_pton */
15
16#if defined(RADIUS_AUTH_FREERADIUS)
17#include <freeradius-client.h>
18#ifndef RC_CONFIG_FILE
19#define RC_DICTIONARY_FILE "/etc/radiusclient/dictionary"
20#endif
21#elif defined(RADIUS_AUTH_RADCLI)
22#include <errno.h>
23#include <radcli/radcli.h>
24#include <stdlib.h> /* for mkstemp */
25#include <string.h> /* for strerror */
26#include <unistd.h>
27#ifndef RC_CONFIG_FILE
28#define RC_DICTIONARY_FILE "/etc/radcli/dictionary"
29#endif
30#endif
31
32#include "../base/networking.h" /* for gvm_resolve */
33
34#include <glib.h> /* for g_warning */
35
36#undef G_LOG_DOMAIN
40#define G_LOG_DOMAIN "libgvm util"
41
42#ifndef PW_MAX_MSG_SIZE
43#define PW_MAX_MSG_SIZE 4096
44#endif
45
54static rc_handle *
55radius_init (const char *hostname, const char *secret)
56{
57 rc_handle *rh;
58 char authserver[4096];
59 struct sockaddr_in6 ip6;
60
61 rh = NULL;
62
63 if (inet_pton (AF_INET6, hostname, &(ip6.sin6_addr)) == 1)
64 snprintf (authserver, sizeof (authserver), "[%s]::%s", hostname, secret);
65 else
66 snprintf (authserver, sizeof (authserver), "%s::%s", hostname, secret);
67
68#if defined(RADIUS_AUTH_RADCLI)
69 // Create config from file for older radcli versions
70 FILE *config_file = NULL;
71 char config_filename[35] = "/tmp/gvm_radius_conf_XXXXXX";
72 int config_fd = mkstemp (config_filename);
73
74 if (config_fd == -1)
75 {
76 g_warning ("%s: Couldn't create temp radius config file: %s\n", __func__,
77 strerror (errno));
78 goto radius_init_fail;
79 }
80
81 config_file = fdopen (config_fd, "w");
82 if (config_file == NULL)
83 {
84 close (config_fd);
85 g_warning ("%s: Couldn't open temp radius config file %s: %s\n", __func__,
86 config_filename, strerror (errno));
87 goto radius_init_fail;
88 }
89
90 if (fprintf (config_file,
91 "auth_order radius\n"
92 "login_tries 4\n"
93 "dictionary %s\n"
94 "seqfile /var/run/radius.seq\n"
95 "radius_retries 3\n"
96 "radius_timeout 5\n"
97 "radius_deadtime 0\n"
98 "authserver %s\n"
99 "acctserver %s\n",
100 RC_DICTIONARY_FILE, authserver, authserver)
101 < 0)
102 {
103 fclose (config_file);
104 g_warning ("%s: Couldn't write to temp radius config file %s:%s\n",
105 __func__, config_filename, strerror (errno));
106 unlink (config_filename);
107 goto radius_init_fail;
108 }
109 fclose (config_file);
110
111 rh = rc_read_config (config_filename);
112 if (rh == NULL)
113 {
114 g_warning ("%s: Couldn't read temp radius config file %s\n", __func__,
115 config_filename);
116 unlink (config_filename);
117 goto radius_init_fail;
118 }
119 unlink (config_filename);
120#else // defined(RADIUS_AUTH_RADCLI)
121 if ((rh = rc_new ()) == NULL)
122 {
123 g_warning ("radius_init: Couldn't allocate memory");
124 return NULL;
125 }
126 if (!rc_config_init (rh))
127 {
128 g_warning ("radius_init: Couldn't initialize the config");
129 return NULL;
130 }
131
132 /* Set the basic configuration options. */
133 if (rc_add_config (rh, "auth_order", "radius", "config", 0))
134 {
135 g_warning ("radius_init: Couldn't set auth_order");
136 goto radius_init_fail;
137 }
138 if (rc_add_config (rh, "login_tries", "4", "config", 0))
139 {
140 g_warning ("radius_init: Couldn't set login_tries");
141 goto radius_init_fail;
142 }
143 if (rc_add_config (rh, "dictionary", RC_DICTIONARY_FILE, "config", 0))
144 {
145 g_warning ("radius_init: Couldn't set dictionary");
146 goto radius_init_fail;
147 }
148 if (rc_add_config (rh, "seqfile", "/var/run/radius.seq", "config", 0))
149 {
150 g_warning ("radius_init: Couldn't set seqfile");
151 goto radius_init_fail;
152 }
153 if (rc_add_config (rh, "radius_retries", "3", "config", 0))
154 {
155 g_warning ("radius_init: Couldn't set radius_retries");
156 goto radius_init_fail;
157 }
158 if (rc_add_config (rh, "radius_timeout", "5", "config", 0))
159 {
160 g_warning ("radius_init: Couldn't set radius_timeout");
161 goto radius_init_fail;
162 }
163 if (rc_add_config (rh, "radius_deadtime", "0", "config", 0))
164 {
165 g_warning ("radius_init: Couldn't set radius_deadtime");
166 goto radius_init_fail;
167 }
168 if (rc_add_config (rh, "authserver", authserver, "config", 0) != 0)
169 {
170 g_warning ("radius_init: Couldn't set authserver %s", authserver);
171 goto radius_init_fail;
172 }
173 if (rc_read_dictionary (rh, RC_DICTIONARY_FILE) != 0)
174 {
175 g_warning ("radius_init: Couldn't read the dictionary file %s",
176 RC_DICTIONARY_FILE);
177 goto radius_init_fail;
178 }
179#endif // defined(RADIUS_AUTH_RADCLI)
180
181 return rh;
182
183radius_init_fail:
184 rc_destroy (rh);
185 return NULL;
186}
187
198int
199radius_authenticate (const char *hostname, const char *secret,
200 const char *username, const char *password)
201{
202 uint32_t service = PW_AUTHENTICATE_ONLY;
203 char msg[PW_MAX_MSG_SIZE];
204 VALUE_PAIR *send = NULL, *received = NULL;
205 rc_handle *rh;
206 int rc = -1;
207 struct sockaddr_in ip4;
208 struct sockaddr_in6 ip6;
209
210 rh = radius_init (hostname, secret);
211 if (!rh)
212 return -1;
213 if (rc_avpair_add (rh, &send, PW_USER_NAME, (char *) username, -1, 0) == NULL)
214 {
215 g_warning ("radius_authenticate: Couldn't set the username");
216 goto authenticate_leave;
217 }
218 if (rc_avpair_add (rh, &send, PW_USER_PASSWORD, (char *) password, -1, 0)
219 == NULL)
220 {
221 g_warning ("radius_authenticate: Couldn't set the password");
222 goto authenticate_leave;
223 }
224 if (rc_avpair_add (rh, &send, PW_SERVICE_TYPE, &service, -1, 0) == NULL)
225 {
226 g_warning ("radius_authenticate: Couldn't set the service type");
227 goto authenticate_leave;
228 }
229 if (gvm_resolve (hostname, &ip4, AF_INET)
230 && gvm_resolve (hostname, &ip6, AF_INET6))
231 {
232 g_warning ("radius_authenticate: Couldn't resolve %s", hostname);
233 goto authenticate_leave;
234 }
235
236 rc = 1;
237 if (rc_auth (rh, 0, send, &received, msg) == OK_RC)
238 rc = 0;
239
240authenticate_leave:
241 rc_destroy (rh);
242 if (send)
243 rc_avpair_free (send);
244 if (received)
245 rc_avpair_free (received);
246 return rc;
247}
248
249#else /* ENABLE_RADIUS_AUTH */
250
261int
262radius_authenticate (const char *hostname, const char *secret,
263 const char *username, const char *password)
264{
265 (void) hostname;
266 (void) secret;
267 (void) username;
268 (void) password;
269
270 return -1;
271}
272
273#endif /* ENABLE_RADIUS_AUTH */
int gvm_resolve(const char *name, void *dst, int family)
Resolves a hostname to an IPv4 or IPv6 address.
Definition: networking.c:389
int radius_authenticate(const char *hostname, const char *secret, const char *username, const char *password)
Dummy function for manager.
Definition: radiusutils.c:262
Headers of an API for Radius authentication.