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
37 
40 #define G_LOG_DOMAIN "libgvm util"
41 
42 #ifndef PW_MAX_MSG_SIZE
43 #define PW_MAX_MSG_SIZE 4096
44 #endif
45 
54 static rc_handle *
55 radius_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 
183 radius_init_fail:
184  rc_destroy (rh);
185  return NULL;
186 }
187 
198 int
199 radius_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 
240 authenticate_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 
261 int
262 radius_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 */
gvm_resolve
int gvm_resolve(const char *name, void *dst, int family)
Resolves a hostname to an IPv4 or IPv6 address.
Definition: networking.c:389
radiusutils.h
Headers of an API for Radius authentication.
radius_authenticate
int radius_authenticate(const char *hostname, const char *secret, const char *username, const char *password)
Dummy function for manager.
Definition: radiusutils.c:262