Greenbone Vulnerability Management Libraries 22.18.1
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
10
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 rh = rc_new ();
122 if (rh == NULL)
123 {
124 g_warning ("radius_init: Couldn't allocate memory");
125 return NULL;
126 }
127 if (!rc_config_init (rh))
128 {
129 g_warning ("radius_init: Couldn't initialize the config");
130 return NULL;
131 }
132
133 /* Set the basic configuration options. */
134 if (rc_add_config (rh, "auth_order", "radius", "config", 0))
135 {
136 g_warning ("radius_init: Couldn't set auth_order");
137 goto radius_init_fail;
138 }
139 if (rc_add_config (rh, "login_tries", "4", "config", 0))
140 {
141 g_warning ("radius_init: Couldn't set login_tries");
142 goto radius_init_fail;
143 }
144 if (rc_add_config (rh, "dictionary", RC_DICTIONARY_FILE, "config", 0))
145 {
146 g_warning ("radius_init: Couldn't set dictionary");
147 goto radius_init_fail;
148 }
149 if (rc_add_config (rh, "seqfile", "/var/run/radius.seq", "config", 0))
150 {
151 g_warning ("radius_init: Couldn't set seqfile");
152 goto radius_init_fail;
153 }
154 if (rc_add_config (rh, "radius_retries", "3", "config", 0))
155 {
156 g_warning ("radius_init: Couldn't set radius_retries");
157 goto radius_init_fail;
158 }
159 if (rc_add_config (rh, "radius_timeout", "5", "config", 0))
160 {
161 g_warning ("radius_init: Couldn't set radius_timeout");
162 goto radius_init_fail;
163 }
164 if (rc_add_config (rh, "radius_deadtime", "0", "config", 0))
165 {
166 g_warning ("radius_init: Couldn't set radius_deadtime");
167 goto radius_init_fail;
168 }
169 if (rc_add_config (rh, "authserver", authserver, "config", 0) != 0)
170 {
171 g_warning ("radius_init: Couldn't set authserver %s", authserver);
172 goto radius_init_fail;
173 }
174 if (rc_read_dictionary (rh, RC_DICTIONARY_FILE) != 0)
175 {
176 g_warning ("radius_init: Couldn't read the dictionary file %s",
177 RC_DICTIONARY_FILE);
178 goto radius_init_fail;
179 }
180#endif // defined(RADIUS_AUTH_RADCLI)
181
182 return rh;
183
184radius_init_fail:
185 rc_destroy (rh);
186 return NULL;
187}
188
199int
200radius_authenticate (const char *hostname, const char *secret,
201 const char *username, const char *password)
202{
203 uint32_t service = PW_AUTHENTICATE_ONLY;
204 char msg[PW_MAX_MSG_SIZE];
205 VALUE_PAIR *send = NULL, *received = NULL;
206 rc_handle *rh;
207 int rc = -1;
208 struct sockaddr_in ip4;
209 struct sockaddr_in6 ip6;
210
211 rh = radius_init (hostname, secret);
212 if (!rh)
213 return -1;
214 if (rc_avpair_add (rh, &send, PW_USER_NAME, (char *) username, -1, 0) == NULL)
215 {
216 g_warning ("radius_authenticate: Couldn't set the username");
217 goto authenticate_leave;
218 }
219 if (rc_avpair_add (rh, &send, PW_USER_PASSWORD, (char *) password, -1, 0)
220 == NULL)
221 {
222 g_warning ("radius_authenticate: Couldn't set the password");
223 goto authenticate_leave;
224 }
225 if (rc_avpair_add (rh, &send, PW_SERVICE_TYPE, &service, -1, 0) == NULL)
226 {
227 g_warning ("radius_authenticate: Couldn't set the service type");
228 goto authenticate_leave;
229 }
230 if (gvm_resolve (hostname, &ip4, AF_INET)
231 && gvm_resolve (hostname, &ip6, AF_INET6))
232 {
233 g_warning ("radius_authenticate: Couldn't resolve %s", hostname);
234 goto authenticate_leave;
235 }
236
237 rc = 1;
238 if (rc_auth (rh, 0, send, &received, msg) == OK_RC)
239 rc = 0;
240
241authenticate_leave:
242 rc_destroy (rh);
243 if (send)
244 rc_avpair_free (send);
245 if (received)
246 rc_avpair_free (received);
247 return rc;
248}
249
250#else /* ENABLE_RADIUS_AUTH */
251
262int
263radius_authenticate (const char *hostname, const char *secret,
264 const char *username, const char *password)
265{
266 (void) hostname;
267 (void) secret;
268 (void) username;
269 (void) password;
270
271 return -1;
272}
273
274#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
GVM Networking related API.
int radius_authenticate(const char *hostname, const char *secret, const char *username, const char *password)
Dummy function for manager.
Definition radiusutils.c:263
Headers of an API for Radius authentication.