Greenbone Vulnerability Management Libraries  11.0.0
authutils.c
Go to the documentation of this file.
1 /* Copyright (C) 2009-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 #include "authutils.h"
26 
27 #include <gcrypt.h> /* for gcry_md_get_algo_dlen, gcry_control, gcry_md_alg... */
28 #include <string.h> /* for strcmp */
29 
30 #undef G_LOG_DOMAIN
31 
34 #define G_LOG_DOMAIN "lib auth"
35 
41 static const gchar *authentication_methods[] = {"file", "ldap_connect",
42  "radius_connect", NULL};
43 
47 static gboolean initialized = FALSE;
48 
54 int
56 {
57 #ifdef ENABLE_LDAP_AUTH
58  return 1;
59 #else
60  return 0;
61 #endif /* ENABLE_LDAP_AUTH */
62 }
63 
69 int
71 {
72 #ifdef ENABLE_RADIUS_AUTH
73  return 1;
74 #else
75  return 0;
76 #endif /* ENABLE_RADIUS_AUTH */
77 }
78 
89 const gchar *
91 {
92  if (method >= AUTHENTICATION_METHOD_LAST)
93  return "ERROR";
94  return authentication_methods[method];
95 }
96 
102 int
104 {
105  if (initialized == TRUE)
106  {
107  g_warning ("gvm_auth_init called a second time.");
108  return -1;
109  }
110 
111  /* Init Libgcrypt. */
112 
113  /* Check if libgcrypt is already initialized */
114  if (gcry_control (GCRYCTL_ANY_INITIALIZATION_P))
115  {
116  initialized = TRUE;
117  return 0;
118  }
119 
120  /* Version check should be the very first call because it makes sure that
121  * important subsystems are initialized.
122  * We pass NULL to gcry_check_version to disable the internal version mismatch
123  * test. */
124  if (!gcry_check_version (NULL))
125  {
126  g_critical ("%s: libgcrypt version check failed\n", __FUNCTION__);
127  return -1;
128  }
129 
130  /* We don't want to see any warnings, e.g. because we have not yet parsed
131  * program options which might be used to suppress such warnings. */
132  gcry_control (GCRYCTL_SUSPEND_SECMEM_WARN);
133 
134  /* ... If required, other initialization goes here. Note that the process
135  * might still be running with increased privileges and that the secure
136  * memory has not been initialized. */
137 
138  /* Allocate a pool of 16k secure memory. This make the secure memory
139  * available and also drops privileges where needed. */
140  gcry_control (GCRYCTL_INIT_SECMEM, 16384, 0);
141 
142  /* It is now okay to let Libgcrypt complain when there was/is a problem with
143  * the secure memory. */
144  gcry_control (GCRYCTL_RESUME_SECMEM_WARN);
145 
146  /* ... If required, other initialization goes here. */
147 
148  /* Tell Libgcrypt that initialization has completed. */
149  gcry_control (GCRYCTL_INITIALIZATION_FINISHED, 0);
150 
151  initialized = TRUE;
152 
153  return 0;
154 }
155 
167 gchar *
168 digest_hex (int gcrypt_algorithm, const guchar *digest)
169 {
170  unsigned int i;
171  gchar *hex;
172 
173  gcry_error_t err = gcry_md_test_algo (gcrypt_algorithm);
174  if (err != 0)
175  {
176  g_warning ("Could not select gcrypt algorithm: %s", gcry_strerror (err));
177  return NULL;
178  }
179 
180  hex = g_malloc0 (gcry_md_get_algo_dlen (gcrypt_algorithm) * 2 + 1);
181  for (i = 0; i < gcry_md_get_algo_dlen (gcrypt_algorithm); i++)
182  {
183  g_snprintf (hex + i * 2, 3, "%02x", digest[i]);
184  }
185 
186  return hex;
187 }
188 
202 gchar *
203 get_password_hashes (const gchar *password)
204 {
205  g_assert (password);
206 
207  unsigned char *nonce_buffer[256];
208  guchar *seed = g_malloc0 (gcry_md_get_algo_dlen (GCRY_MD_MD5));
209  gchar *seed_hex = NULL;
210  gchar *seed_pass = NULL;
211  guchar *hash = g_malloc0 (gcry_md_get_algo_dlen (GCRY_MD_MD5));
212  gchar *hash_hex = NULL;
213  gchar *hashes_out = NULL;
214 
215  gcry_create_nonce (nonce_buffer, 256);
216  gcry_md_hash_buffer (GCRY_MD_MD5, seed, nonce_buffer, 256);
217  seed_hex = digest_hex (GCRY_MD_MD5, seed);
218  seed_pass = g_strconcat (seed_hex, password, NULL);
219  gcry_md_hash_buffer (GCRY_MD_MD5, hash, seed_pass, strlen (seed_pass));
220  hash_hex = digest_hex (GCRY_MD_MD5, hash);
221 
222  hashes_out = g_strjoin (" ", hash_hex, seed_hex, NULL);
223 
224  g_free (seed);
225  g_free (seed_hex);
226  g_free (seed_pass);
227  g_free (hash);
228  g_free (hash_hex);
229 
230  return hashes_out;
231 }
232 
242 int
243 gvm_authenticate_classic (const gchar *username, const gchar *password,
244  const gchar *hash_arg)
245 {
246  int gcrypt_algorithm = GCRY_MD_MD5; // FIX whatever configure used
247  int ret;
248  gchar *actual, *expect, *seed_pass;
249  guchar *hash;
250  gchar *hash_hex, **seed_hex, **split;
251 
252  (void) username;
253  if (hash_arg == NULL)
254  return 1;
255  actual = g_strdup (hash_arg);
256 
257  split = g_strsplit_set (g_strchomp (actual), " ", 2);
258  seed_hex = split + 1;
259  if (*split == NULL || *seed_hex == NULL)
260  {
261  g_warning ("Failed to split auth contents.");
262  g_strfreev (split);
263  g_free (actual);
264  return -1;
265  }
266 
267  seed_pass = g_strconcat (*seed_hex, password, NULL);
268  hash = g_malloc0 (gcry_md_get_algo_dlen (gcrypt_algorithm));
269  gcry_md_hash_buffer (GCRY_MD_MD5, hash, seed_pass, strlen (seed_pass));
270  hash_hex = digest_hex (GCRY_MD_MD5, hash);
271 
272  expect = g_strjoin (" ", hash_hex, *seed_hex, NULL);
273 
274  g_strfreev (split);
275  g_free (seed_pass);
276  g_free (hash);
277  g_free (hash_hex);
278 
279  ret = strcmp (expect, actual) ? 1 : 0;
280  g_free (expect);
281  g_free (actual);
282  return ret;
283 }
gvm_auth_ldap_enabled
int gvm_auth_ldap_enabled()
Return whether libraries has been compiled with LDAP support.
Definition: authutils.c:55
auth_method_t
enum authentication_method auth_method_t
Type for the numerical representation of the supported authentication methods.
Definition: authutils.h:45
get_password_hashes
gchar * get_password_hashes(const gchar *password)
Generate a pair of md5 hashes to be used in the "auth/hash" file for the user.
Definition: authutils.c:203
gvm_auth_init
int gvm_auth_init()
Initializes Gcrypt.
Definition: authutils.c:103
authutils.h
Authentication mechanism(s).
gvm_auth_radius_enabled
int gvm_auth_radius_enabled()
Return whether libraries has been compiled with RADIUS support.
Definition: authutils.c:70
gvm_authenticate_classic
int gvm_authenticate_classic(const gchar *username, const gchar *password, const gchar *hash_arg)
Authenticate a credential pair against user file contents.
Definition: authutils.c:243
auth_method_name
const gchar * auth_method_name(auth_method_t method)
Return name of auth_method_t.
Definition: authutils.c:90
AUTHENTICATION_METHOD_LAST
@ AUTHENTICATION_METHOD_LAST
Definition: authutils.h:40
authentication_methods
static const gchar * authentication_methods[]
Array of string representations of the supported authentication methods.
Definition: authutils.c:41
initialized
static gboolean initialized
Flag whether the config file was read.
Definition: authutils.c:47
digest_hex
gchar * digest_hex(int gcrypt_algorithm, const guchar *digest)
Generate a hexadecimal representation of a message digest.
Definition: authutils.c:168