Greenbone Vulnerability Management Libraries  10.0.0
radiusutils.c
Go to the documentation of this file.
1 /* Copyright (C) 2015-2019 Greenbone Networks GmbH
2  *
3  * SPDX-License-Identifier: GPL-2.0-or-later
4  *
5  * This program is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU General Public License
7  * as published by the Free Software Foundation; either version 2
8  * of the License, or (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18  */
19 
25 #ifdef ENABLE_RADIUS_AUTH
26 
27 #include <arpa/inet.h> /* for inet_pton */
28 
29 #if defined(RADIUS_AUTH_FREERADIUS)
30 #include <freeradius-client.h>
31 #ifndef RC_CONFIG_FILE
32 #define RC_DICTIONARY_FILE "/etc/radiusclient/dictionary"
33 #endif
34 #elif defined(RADIUS_AUTH_RADCLI)
35 #include <errno.h>
36 #include <radcli/radcli.h>
37 #include <stdlib.h> /* for mkstemp */
38 #include <string.h> /* for strerror */
39 #include <unistd.h>
40 #ifndef RC_CONFIG_FILE
41 #define RC_DICTIONARY_FILE "/etc/radcli/dictionary"
42 #endif
43 #endif
44 
45 #include "../base/networking.h" /* for gvm_resolve */
46 
47 #include <glib.h> /* for g_warning */
48 
49 #ifndef PW_MAX_MSG_SIZE
50 #define PW_MAX_MSG_SIZE 4096
51 #endif
52 
61 static rc_handle *
62 radius_init (const char *hostname, const char *secret)
63 {
64  rc_handle *rh;
65  char authserver[4096];
66  struct sockaddr_in6 ip6;
67 
68  rh = NULL;
69 
70  if (inet_pton (AF_INET6, hostname, &(ip6.sin6_addr)) == 1)
71  snprintf (authserver, sizeof (authserver), "[%s]::%s", hostname, secret);
72  else
73  snprintf (authserver, sizeof (authserver), "%s::%s", hostname, secret);
74 
75 #if defined(RADIUS_AUTH_RADCLI)
76  // Create config from file for older radcli versions
77  FILE *config_file = NULL;
78  char config_filename[35] = "/tmp/gvm_radius_conf_XXXXXX";
79  int config_fd = mkstemp (config_filename);
80 
81  if (config_fd == -1)
82  {
83  g_warning ("%s: Couldn't create temp radius config file: %s\n",
84  __FUNCTION__, strerror (errno));
85  goto radius_init_fail;
86  }
87 
88  config_file = fdopen (config_fd, "w");
89  if (config_file == NULL)
90  {
91  close (config_fd);
92  g_warning ("%s: Couldn't open temp radius config file %s: %s\n",
93  __FUNCTION__, config_filename, strerror (errno));
94  goto radius_init_fail;
95  }
96 
97  if (fprintf (config_file,
98  "auth_order radius\n"
99  "login_tries 4\n"
100  "dictionary %s\n"
101  "seqfile /var/run/radius.seq\n"
102  "radius_retries 3\n"
103  "radius_timeout 5\n"
104  "radius_deadtime 0\n"
105  "authserver %s\n"
106  "acctserver %s\n",
107  RC_DICTIONARY_FILE, authserver, authserver)
108  < 0)
109  {
110  fclose (config_file);
111  g_warning ("%s: Couldn't write to temp radius config file %s:%s\n",
112  __FUNCTION__, config_filename, strerror (errno));
113  unlink (config_filename);
114  goto radius_init_fail;
115  }
116  fclose (config_file);
117 
118  rh = rc_read_config (config_filename);
119  if (rh == NULL)
120  {
121  g_warning ("%s: Couldn't read temp radius config file %s\n", __FUNCTION__,
122  config_filename);
123  unlink (config_filename);
124  goto radius_init_fail;
125  }
126  unlink (config_filename);
127 #else // defined(RADIUS_AUTH_RADCLI)
128  if ((rh = rc_new ()) == NULL)
129  {
130  g_warning ("radius_init: Couldn't allocate memory");
131  return NULL;
132  }
133  if (!rc_config_init (rh))
134  {
135  g_warning ("radius_init: Couldn't initialize the config");
136  return NULL;
137  }
138 
139  /* Set the basic configuration options. */
140  if (rc_add_config (rh, "auth_order", "radius", "config", 0))
141  {
142  g_warning ("radius_init: Couldn't set auth_order");
143  goto radius_init_fail;
144  }
145  if (rc_add_config (rh, "login_tries", "4", "config", 0))
146  {
147  g_warning ("radius_init: Couldn't set login_tries");
148  goto radius_init_fail;
149  }
150  if (rc_add_config (rh, "dictionary", RC_DICTIONARY_FILE, "config", 0))
151  {
152  g_warning ("radius_init: Couldn't set dictionary");
153  goto radius_init_fail;
154  }
155  if (rc_add_config (rh, "seqfile", "/var/run/radius.seq", "config", 0))
156  {
157  g_warning ("radius_init: Couldn't set seqfile");
158  goto radius_init_fail;
159  }
160  if (rc_add_config (rh, "radius_retries", "3", "config", 0))
161  {
162  g_warning ("radius_init: Couldn't set radius_retries");
163  goto radius_init_fail;
164  }
165  if (rc_add_config (rh, "radius_timeout", "5", "config", 0))
166  {
167  g_warning ("radius_init: Couldn't set radius_timeout");
168  goto radius_init_fail;
169  }
170  if (rc_add_config (rh, "radius_deadtime", "0", "config", 0))
171  {
172  g_warning ("radius_init: Couldn't set radius_deadtime");
173  goto radius_init_fail;
174  }
175  if (rc_add_config (rh, "authserver", authserver, "config", 0) != 0)
176  {
177  g_warning ("radius_init: Couldn't set authserver %s", authserver);
178  goto radius_init_fail;
179  }
180  if (rc_read_dictionary (rh, RC_DICTIONARY_FILE) != 0)
181  {
182  g_warning ("radius_init: Couldn't read the dictionary file %s",
183  RC_DICTIONARY_FILE);
184  goto radius_init_fail;
185  }
186 #endif // defined(RADIUS_AUTH_RADCLI)
187 
188  return rh;
189 
190 radius_init_fail:
191  rc_destroy (rh);
192  return NULL;
193 }
194 
205 int
206 radius_authenticate (const char *hostname, const char *secret,
207  const char *username, const char *password)
208 {
209  uint32_t service = PW_AUTHENTICATE_ONLY;
210  char msg[PW_MAX_MSG_SIZE];
211  VALUE_PAIR *send = NULL, *received = NULL;
212  rc_handle *rh;
213  int rc = -1;
214  struct sockaddr_in ip4;
215  struct sockaddr_in6 ip6;
216 
217  rh = radius_init (hostname, secret);
218  if (!rh)
219  return -1;
220  if (rc_avpair_add (rh, &send, PW_USER_NAME, (char *) username, -1, 0) == NULL)
221  {
222  g_warning ("radius_authenticate: Couldn't set the username");
223  goto authenticate_leave;
224  }
225  if (rc_avpair_add (rh, &send, PW_USER_PASSWORD, (char *) password, -1, 0)
226  == NULL)
227  {
228  g_warning ("radius_authenticate: Couldn't set the password");
229  goto authenticate_leave;
230  }
231  if (rc_avpair_add (rh, &send, PW_SERVICE_TYPE, &service, -1, 0) == NULL)
232  {
233  g_warning ("radius_authenticate: Couldn't set the service type");
234  goto authenticate_leave;
235  }
236  if (gvm_resolve (hostname, &ip4, AF_INET)
237  && gvm_resolve (hostname, &ip6, AF_INET6))
238  {
239  g_warning ("radius_authenticate: Couldn't resolve %s", hostname);
240  goto authenticate_leave;
241  }
242 
243  rc = 1;
244  if (rc_auth (rh, 0, send, &received, msg) == OK_RC)
245  rc = 0;
246 
247 authenticate_leave:
248  rc_destroy (rh);
249  if (send)
250  rc_avpair_free (send);
251  if (received)
252  rc_avpair_free (received);
253  return rc;
254 }
255 
256 #else /* ENABLE_RADIUS_AUTH */
257 
268 int
269 radius_authenticate (const char *hostname, const char *secret,
270  const char *username, const char *password)
271 {
272  (void) hostname;
273  (void) secret;
274  (void) username;
275  (void) password;
276 
277  return -1;
278 }
279 
280 #endif /* ENABLE_RADIUS_AUTH */
int radius_authenticate(const char *hostname, const char *secret, const char *username, const char *password)
Dummy function for manager.
Definition: radiusutils.c:269
int gvm_resolve(const char *name, void *dst, int family)
Resolves a hostname to an IPv4 or IPv6 address.
Definition: networking.c:388