Greenbone Vulnerability Management Libraries 22.8.0
passwordbasedauthentication.c File Reference
#include "passwordbasedauthentication.h"
#include "authutils.c"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <crypt.h>
Include dependency graph for passwordbasedauthentication.c:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Macros

#define __USE_GNU
 
#define INVALID_HASH   "1234567890$"
 
#define CRYPT_GENSALT_OUTPUT_SIZE   192
 
#define CRYPT_OUTPUT_SIZE   384
 

Functions

static int is_prefix_supported (const char *id)
 
static int get_random (char *buf, size_t buflen)
 
char * crypt_gensalt_r (const char *prefix, unsigned long count, const char *rbytes, int nrbytes, char *output, int output_size)
 
struct PBASettingspba_init (const char *pepper, unsigned int pepper_size, unsigned int count, char *prefix)
 
void pba_finalize (struct PBASettings *settings)
 
static int pba_is_phc_compliant (const char *setting)
 
char * pba_hash (struct PBASettings *setting, const char *password)
 
enum pba_rc pba_verify_hash (const struct PBASettings *setting, const char *hash, const char *password)
 

Variables

const char ascii64 [64]
 

Macro Definition Documentation

◆ __USE_GNU

#define __USE_GNU

Definition at line 16 of file passwordbasedauthentication.c.

◆ CRYPT_GENSALT_OUTPUT_SIZE

#define CRYPT_GENSALT_OUTPUT_SIZE   192

Definition at line 24 of file passwordbasedauthentication.c.

◆ CRYPT_OUTPUT_SIZE

#define CRYPT_OUTPUT_SIZE   384

Definition at line 28 of file passwordbasedauthentication.c.

◆ INVALID_HASH

#define INVALID_HASH   "1234567890$"

Definition at line 22 of file passwordbasedauthentication.c.

Function Documentation

◆ crypt_gensalt_r()

char * crypt_gensalt_r ( const char *  prefix,
unsigned long  count,
const char *  rbytes,
int  nrbytes,
char *  output,
int  output_size 
)

Definition at line 85 of file passwordbasedauthentication.c.

87{
88 char *internal_rbytes = NULL;
89 unsigned int written = 0, used = 0;
90 unsigned long value = 0;
91 if ((rbytes != NULL && nrbytes < 3) || output_size < 16
92 || !is_prefix_supported (prefix))
93 {
94 output[0] = '*';
95 goto exit;
96 }
97 if (rbytes == NULL)
98 {
99 internal_rbytes = malloc (16);
100 if (get_random (internal_rbytes, 16) != 0)
101 {
102 output[0] = '*';
103 goto exit;
104 }
105 nrbytes = 16;
106 rbytes = internal_rbytes;
107 }
108 written = snprintf (output, output_size, "%srounds=%lu$",
109 prefix == NULL ? PREFIX_DEFAULT : prefix, count);
110 while (written + 5 < (unsigned int) output_size
111 && used + 3 < (unsigned int) nrbytes && (used * 4 / 3) < 16)
112 {
113 value = ((unsigned long) rbytes[used + 0] << 0)
114 | ((unsigned long) rbytes[used + 1] << 8)
115 | ((unsigned long) rbytes[used + 2] << 16);
116 output[written] = ascii64[value & 0x3f];
117 output[written + 1] = ascii64[(value >> 6) & 0x3f];
118 output[written + 2] = ascii64[(value >> 12) & 0x3f];
119 output[written + 3] = ascii64[(value >> 18) & 0x3f];
120 written += 4;
121 used += 3;
122 }
123 output[written] = '\0';
124exit:
125 if (internal_rbytes != NULL)
126 free (internal_rbytes);
127 return output[0] == '*' ? 0 : output;
128}
static int get_random(char *buf, size_t buflen)
const char ascii64[64]
static int is_prefix_supported(const char *id)
#define PREFIX_DEFAULT

References ascii64, get_random(), is_prefix_supported(), and PREFIX_DEFAULT.

Referenced by pba_hash().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ get_random()

static int get_random ( char *  buf,
size_t  buflen 
)
static

Definition at line 49 of file passwordbasedauthentication.c.

50{
51 FILE *fp = fopen ("/dev/urandom", "r");
52 int result = 0;
53 if (fp == NULL)
54 {
55 result = -1;
56 goto exit;
57 }
58 size_t nread = fread (buf, 1, buflen, fp);
59 fclose (fp);
60 if (nread < buflen)
61 {
62 result = -2;
63 }
64
65exit:
66 return result;
67}

Referenced by crypt_gensalt_r().

Here is the caller graph for this function:

◆ is_prefix_supported()

static int is_prefix_supported ( const char *  id)
static

Definition at line 32 of file passwordbasedauthentication.c.

33{
34 return strcmp (PREFIX_DEFAULT, id) == 0;
35}

References PREFIX_DEFAULT.

Referenced by crypt_gensalt_r(), pba_hash(), pba_init(), and pba_verify_hash().

Here is the caller graph for this function:

◆ pba_finalize()

void pba_finalize ( struct PBASettings settings)

Definition at line 152 of file passwordbasedauthentication.c.

153{
154 free (settings);
155}

Referenced by Ensure().

Here is the caller graph for this function:

◆ pba_hash()

char * pba_hash ( struct PBASettings setting,
const char *  password 
)

pba_hash tries to create a hash based SETTING and PASSWORD. Returns a hash on success or a NULL pointer on failure

Definition at line 168 of file passwordbasedauthentication.c.

169{
170 char *result = NULL, *settings = NULL, *tmp, *rslt;
171 int i;
172 struct crypt_data *data = NULL;
173
174 if (!setting || !password)
175 goto exit;
176 if (!is_prefix_supported (setting->prefix))
177 goto exit;
178 settings = malloc (CRYPT_GENSALT_OUTPUT_SIZE);
179 if (crypt_gensalt_r (setting->prefix, setting->count, NULL, 0, settings,
181 == NULL)
182 goto exit;
183 tmp = settings + strlen (settings) - 1;
184 for (i = MAX_PEPPER_SIZE - 1; i > -1; i--)
185 {
186 if (setting->pepper[i] != 0)
187 tmp[0] = setting->pepper[i];
188 tmp--;
189 }
190
191 data = calloc (1, sizeof (struct crypt_data));
192 rslt = crypt_r (password, settings, data);
193 if (rslt == NULL)
194 goto exit;
195 result = calloc (1, CRYPT_OUTPUT_SIZE);
196 memcpy (result, rslt, CRYPT_OUTPUT_SIZE);
197 // remove pepper, by jumping to begin of applied pepper within result
198 // and overriding it.
199 tmp = result + (tmp - settings);
200 for (i = 0; i < MAX_PEPPER_SIZE; i++)
201 {
202 tmp++;
203 if (setting->pepper[i] != 0)
204 tmp[0] = '0';
205 }
206exit:
207 if (data != NULL)
208 free (data);
209 if (settings != NULL)
210 free (settings);
211 return result;
212}
char * crypt_gensalt_r(const char *prefix, unsigned long count, const char *rbytes, int nrbytes, char *output, int output_size)
#define CRYPT_OUTPUT_SIZE
#define CRYPT_GENSALT_OUTPUT_SIZE
#define MAX_PEPPER_SIZE
char pepper[MAX_PEPPER_SIZE]

References PBASettings::count, CRYPT_GENSALT_OUTPUT_SIZE, crypt_gensalt_r(), CRYPT_OUTPUT_SIZE, is_prefix_supported(), MAX_PEPPER_SIZE, PBASettings::pepper, and PBASettings::prefix.

Referenced by Ensure().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ pba_init()

struct PBASettings * pba_init ( const char *  pepper,
unsigned int  pepper_size,
unsigned int  count,
char *  prefix 
)

Intitializes PBASettings with given PEPPER, PREFIX, COUNT.

PEPPER_SIZE must be lower or equal MAX_PEPPER_SIZE when PEPPER is set, when PEPPER is a NULL pointer, no pepper will be used and PEPPER_SIZE is ignored.

COUNT is set to COUNT_DEFAULT when it is 0, PREFIX is set to PREFIX_DEFAULT when prefix is a nullpointer.

Returns a pointer to PBASettings on success or NULL on failure.

Definition at line 133 of file passwordbasedauthentication.c.

135{
136 unsigned int i = 0;
137 struct PBASettings *result = NULL;
138 if (pepper_size > MAX_PEPPER_SIZE)
139 goto exit;
140 if (prefix != NULL && !is_prefix_supported (prefix))
141 goto exit;
142 result = malloc (sizeof (struct PBASettings));
143 for (i = 0; i < MAX_PEPPER_SIZE; i++)
144 result->pepper[i] = pepper != NULL && i < pepper_size ? pepper[i] : 0;
145 result->count = count == 0 ? COUNT_DEFAULT : count;
146 result->prefix = prefix == NULL ? PREFIX_DEFAULT : prefix;
147exit:
148 return result;
149}
#define COUNT_DEFAULT

References PBASettings::count, COUNT_DEFAULT, is_prefix_supported(), MAX_PEPPER_SIZE, PBASettings::pepper, PBASettings::prefix, and PREFIX_DEFAULT.

Referenced by Ensure().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ pba_is_phc_compliant()

static int pba_is_phc_compliant ( const char *  setting)
static

Definition at line 158 of file passwordbasedauthentication.c.

159{
160 if (setting == NULL)
161 {
162 return 1;
163 }
164 return strlen (setting) > 1 && setting[0] == '$';
165}

Referenced by Ensure(), and pba_verify_hash().

Here is the caller graph for this function:

◆ pba_verify_hash()

enum pba_rc pba_verify_hash ( const struct PBASettings settings,
const char *  hash,
const char *  password 
)

pba_verify_hash tries to create hash based on PASSWORD and settings found via HASH and compares that with HASH.

Returns VALID if HASH and PASSWORD are correct; UPDATE_RECOMMENDED when the HASH and PASSWORD are correct but based on a deprecated algorithm; IVALID if HASH does not match PASSWORD; ERR if an unexpected error occurs.

Definition at line 215 of file passwordbasedauthentication.c.

217{
218 char *cmp, *tmp = NULL;
219 struct crypt_data *data = NULL;
220 int i = 0;
221 enum pba_rc result = ERR;
222
223 char *invalid_hash = calloc (1, CRYPT_OUTPUT_SIZE);
224 memset (invalid_hash, 0, CRYPT_OUTPUT_SIZE);
225 memcpy (invalid_hash, INVALID_HASH, strlen (INVALID_HASH));
226
227 if (!setting)
228 goto exit;
229 if (!is_prefix_supported (setting->prefix))
230 goto exit;
231 if (pba_is_phc_compliant (hash) != 0)
232 {
233 int hash_size;
234 hash_size = hash ? strlen (hash) : strlen (invalid_hash);
235
236 data = calloc (1, sizeof (struct crypt_data));
237 // manipulate hash to reapply pepper
238 tmp = calloc (1, CRYPT_OUTPUT_SIZE);
239
240 memset (tmp, 0, CRYPT_OUTPUT_SIZE);
241 memcpy (tmp, hash ? hash : invalid_hash,
242 (hash_size < CRYPT_OUTPUT_SIZE) ? hash_size
243 : CRYPT_OUTPUT_SIZE - 1);
244 cmp = strrchr (tmp, '$');
245 for (i = MAX_PEPPER_SIZE - 1; i > -1; i--)
246 {
247 cmp--;
248 if (setting->pepper[i] != 0)
249 cmp[0] = setting->pepper[i];
250 }
251 // some crypt_r implementations cannot handle if password is a
252 // NULL pointer and run into SEGMENTATION faults.
253 // Therefore we set it to ""
254 cmp = crypt_r (password ? password : "", tmp, data);
255 if (strcmp (tmp, cmp) == 0)
256 result = VALID;
257 else
258 result = INVALID;
259 }
260 else
261 {
262 // assume authutils hash handling
263 // initialize gvm_auth utils if not already initialized
264 if (initialized == FALSE && gvm_auth_init () != 0)
265 {
266 goto exit;
267 }
268 // verify result of gvm_authenticate_classic
269 i = gvm_authenticate_classic (NULL, password, hash);
270 if (i == 0)
271 result = UPDATE_RECOMMENDED;
272 else if (i == 1)
273 result = INVALID;
274 }
275exit:
276 free (invalid_hash);
277 if (data != NULL)
278 free (data);
279 if (tmp != NULL)
280 free (tmp);
281 return result;
282}
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:253
int gvm_auth_init(void)
Initializes Gcrypt.
Definition: authutils.c:89
static gboolean initialized
Flag whether the config file was read.
Definition: authutils.c:33
static int pba_is_phc_compliant(const char *setting)
#define INVALID_HASH

References CRYPT_OUTPUT_SIZE, ERR, gvm_auth_init(), gvm_authenticate_classic(), initialized, INVALID, INVALID_HASH, is_prefix_supported(), MAX_PEPPER_SIZE, pba_is_phc_compliant(), PBASettings::pepper, PBASettings::prefix, UPDATE_RECOMMENDED, and VALID.

Referenced by Ensure().

Here is the call graph for this function:
Here is the caller graph for this function:

Variable Documentation

◆ ascii64

const char ascii64[64]
Initial value:
=
"./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"

Definition at line 44 of file passwordbasedauthentication.c.

Referenced by crypt_gensalt_r().