The FreeRADIUS server  $Id: 15bac2a4c627c01d1aa2047687b3418955ac7f00 $
rlm_digest.c
Go to the documentation of this file.
1 /*
2  * This program is is free software; you can redistribute it and/or modify
3  * it under the terms of the GNU General Public License as published by
4  * the Free Software Foundation; either version 2 of the License, or (at
5  * your option) any later version.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * along with this program; if not, write to the Free Software
14  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
15  */
16 
17 /**
18  * $Id: f6548a1d77f41333bbfccef135ecb9c99b80948d $
19  * @file rlm_digest.c
20  * @brief Handles SIP digest authentication requests from Cisco SIP servers.
21  *
22  * @copyright 2002,2006 The FreeRADIUS server project
23  * @copyright 2002 Alan DeKok (aland@freeradius.org)
24  */
25 RCSID("$Id: f6548a1d77f41333bbfccef135ecb9c99b80948d $")
26 
27 #include <freeradius-devel/server/base.h>
28 #include <freeradius-devel/server/module_rlm.h>
29 
30 #include <freeradius-devel/util/base16.h>
31 #include <freeradius-devel/util/md5.h>
32 
33 typedef struct {
35 } rlm_digest_t;
36 
37 static fr_dict_t const *dict_freeradius;
38 static fr_dict_t const *dict_radius;
39 
42  { .out = &dict_freeradius, .proto = "freeradius" },
43  { .out = &dict_radius, .proto = "radius" },
44  { NULL }
45 };
46 
49 
63 
66  { .out = &attr_auth_type, .name = "Auth-Type", .type = FR_TYPE_UINT32, .dict = &dict_freeradius },
67  { .out = &attr_cleartext_password, .name = "Password.Cleartext", .type = FR_TYPE_STRING, .dict = &dict_freeradius },
68 
69  { .out = &attr_digest_response, .name = "Digest-Response", .type = FR_TYPE_STRING, .dict = &dict_radius },
70  { .out = &attr_digest_attributes, .name = "Digest-Attributes", .type = FR_TYPE_TLV, .dict = &dict_radius },
71  { .out = &attr_digest_algorithm, .name = "Digest-Attributes.Algorithm", .type = FR_TYPE_STRING, .dict = &dict_radius },
72  { .out = &attr_digest_body_digest, .name = "Digest-Attributes.Body-Digest", .type = FR_TYPE_STRING, .dict = &dict_radius },
73  { .out = &attr_digest_cnonce, .name = "Digest-Attributes.Cnonce", .type = FR_TYPE_STRING, .dict = &dict_radius },
74  { .out = &attr_digest_ha1, .name = "Digest-Attributes.HA1", .type = FR_TYPE_STRING, .dict = &dict_radius },
75  { .out = &attr_digest_method, .name = "Digest-Attributes.Method", .type = FR_TYPE_STRING, .dict = &dict_radius },
76  { .out = &attr_digest_nonce, .name = "Digest-Attributes.Nonce", .type = FR_TYPE_STRING, .dict = &dict_radius },
77  { .out = &attr_digest_nonce_count, .name = "Digest-Attributes.Nonce-Count", .type = FR_TYPE_STRING, .dict = &dict_radius },
78  { .out = &attr_digest_qop, .name = "Digest-Attributes.Qop", .type = FR_TYPE_STRING, .dict = &dict_radius },
79  { .out = &attr_digest_realm, .name = "Digest-Attributes.Realm", .type = FR_TYPE_STRING, .dict = &dict_radius },
80  { .out = &attr_digest_uri, .name = "Digest-Attributes.Uri", .type = FR_TYPE_STRING, .dict = &dict_radius },
81  { .out = &attr_digest_user_name, .name = "Digest-Attributes.User-Name", .type = FR_TYPE_STRING, .dict = &dict_radius },
82 
83  { NULL }
84 };
85 
86 static unlang_action_t CC_HINT(nonnull) mod_authorize(rlm_rcode_t *p_result, module_ctx_t const *mctx, request_t *request)
87 {
88  rlm_digest_t const *inst = talloc_get_type_abort(mctx->inst->data, rlm_digest_t);
89  fr_pair_t *vp;
90 
91  /*
92  * Find the first attribute which is parented by Digest-Attributes.
93  */
94  vp = fr_pair_find_by_da(&request->request_pairs, NULL, attr_digest_attributes);
95  if (!vp) RETURN_MODULE_NOOP;
96 
97  if (!inst->auth_type) {
98  WARN("No 'authenticate %s {...}' section or 'Auth-Type = %s' set. Cannot setup Digest authentication",
99  mctx->inst->name, mctx->inst->name);
101  }
102 
103  /*
104  * Everything's OK, add a digest authentication type.
105  */
107 
109 }
110 
111 /*
112  * Perform all of the wondrous variants of digest authentication.
113  */
114 static unlang_action_t CC_HINT(nonnull) mod_authenticate(rlm_rcode_t *p_result, UNUSED module_ctx_t const *mctx, request_t *request)
115 {
116  size_t a1_len, a2_len, kd_len;
117  uint8_t a1[(FR_MAX_STRING_LEN + 1) * 5]; /* can be 5 attributes */
118  uint8_t a2[(FR_MAX_STRING_LEN + 1) * 3]; /* can be 3 attributes */
119  uint8_t kd[(FR_MAX_STRING_LEN + 1) * 5];
120  uint8_t hash[16]; /* MD5 output */
121  fr_pair_t *vp, *passwd, *algo;
122  fr_pair_t *qop, *nonce;
123  fr_pair_list_t *list;
124 
125  /*
126  * We require access to the plain-text password, or to the
127  * Digest-Attributes.HA1 parameter.
128  */
129  passwd = fr_pair_find_by_da_nested(&request->control_pairs, NULL, attr_digest_ha1);
130  if (passwd) {
131  if (passwd->vp_length != 32) {
132  REDEBUG("Digest-Attributes.HA1 has invalid length, authentication failed");
134  }
135  } else {
136  passwd = fr_pair_find_by_da_nested(&request->control_pairs, NULL, attr_cleartext_password);
137  }
138  if (!passwd) {
139  REDEBUG("Password.Cleartext or Digest-Attributes.HA1 is required for authentication");
141  }
142 
143  vp = fr_pair_find_by_da(&request->request_pairs, NULL, attr_digest_attributes);
144  if (!vp) {
145  REDEBUG("Digest-Attributes is required for authentication");
147  }
148  list = &vp->vp_group;
149 
150  /*
151  * We require access to the Digest-Attributes.Nonce
152  */
153  nonce = fr_pair_find_by_da_nested(list, NULL, attr_digest_nonce);
154  if (!nonce) {
155  REDEBUG("No Digest-Attributes.Nonce: Cannot perform Digest authentication");
157  }
158 
159  /*
160  * A1 = Digest-Attributes.User-Name ":" Realm ":" Password
161  */
163  if (!vp) {
164  REDEBUG("No Digest-Attributes.User-Name: Cannot perform Digest authentication");
166  }
167  memcpy(&a1[0], vp->vp_octets, vp->vp_length);
168  a1_len = vp->vp_length;
169 
170  a1[a1_len] = ':';
171  a1_len++;
172 
174  if (!vp) {
175  REDEBUG("No Digest-Attributes.Attributes.Realm: Cannot perform Digest authentication");
177  }
178  memcpy(&a1[a1_len], vp->vp_octets, vp->vp_length);
179  a1_len += vp->vp_length;
180 
181  a1[a1_len] = ':';
182  a1_len++;
183 
184  if (passwd->da == attr_cleartext_password) {
185  memcpy(&a1[a1_len], passwd->vp_octets, passwd->vp_length);
186  a1_len += passwd->vp_length;
187  a1[a1_len] = '\0';
188  RDEBUG2("A1 = %s", a1);
189  } else {
190  a1[a1_len] = '\0';
191  RDEBUG2("A1 = %s (using Digest-Attributes.HA1)", a1);
192  a1_len = 16;
193  }
194 
195  /*
196  * See which variant we calculate.
197  * Assume MD5 if no Digest-Algorithm attribute received
198  */
200  if ((!algo) ||
201  (strcasecmp(algo->vp_strvalue, "MD5") == 0)) {
202  /*
203  * Set A1 to Digest-Attributes.HA1 if no User-Password found
204  */
205  if (passwd->da == attr_digest_ha1) {
206  if (fr_base16_decode(NULL, &FR_DBUFF_TMP(&a1[0], sizeof(a1)),
207  &FR_SBUFF_IN(passwd->vp_strvalue, passwd->vp_length), false) != 16) {
208  RDEBUG2("Invalid text in Digest-Attributes.HA1");
210  }
211  }
212 
213  } else if (strcasecmp(algo->vp_strvalue, "MD5-sess") == 0) {
214  /*
215  * K1 = H(A1) : Digest-Attributes.Nonce ... : H(A2)
216  *
217  * If we find Digest-Attributes.HA1, we assume it contains
218  * H(A1).
219  */
220  if (passwd->da == attr_cleartext_password) {
221  fr_md5_calc(hash, &a1[0], a1_len);
222  fr_base16_encode(&FR_SBUFF_OUT((char *) &a1[0], 32 + 1), &FR_DBUFF_TMP(hash, 16));
223  } else { /* MUST be Digest-Attributes.HA1 */
224  memcpy(&a1[0], passwd->vp_strvalue, 32);
225  }
226  a1_len = 32;
227 
228  a1[a1_len] = ':';
229  a1_len++;
230 
231  /*
232  * Tack on the Digest-Attributes.Nonce. Length must be even
233  */
234  if ((nonce->vp_length & 1) != 0) {
235  REDEBUG("Received Digest-Attributes.Nonce hex string with invalid length: Cannot perform Digest authentication");
237  }
238  memcpy(&a1[a1_len], nonce->vp_octets, nonce->vp_length);
239  a1_len += nonce->vp_length;
240 
241  a1[a1_len] = ':';
242  a1_len++;
243 
245  if (!vp) {
246  REDEBUG("No Digest-Attributes.CNonce: Cannot perform Digest authentication");
248  }
249 
250  /*
251  * Digest-Attributes.CNonce length must be even
252  */
253  if ((vp->vp_length & 1) != 0) {
254  REDEBUG("Received Digest-Attributes.CNonce hex string with invalid length: Cannot perform Digest authentication");
256  }
257  memcpy(&a1[a1_len], vp->vp_octets, vp->vp_length);
258  a1_len += vp->vp_length;
259 
260  } else if (strcasecmp(algo->vp_strvalue, "MD5") != 0) {
261  /*
262  * We check for "MD5-sess" and "MD5".
263  * Anything else is an error.
264  */
265  REDEBUG("%pP - Unknown Digest-Attributes.Algorithm: Cannot perform Digest authentication", vp);
267  }
268 
269  /*
270  * A2 = Digest-Attributes.Method ":" Digest-Attributes.URI
271  */
273  if (!vp) {
274  REDEBUG("No Digest-Attributes.Method: Cannot perform Digest authentication");
276  }
277  memcpy(&a2[0], vp->vp_octets, vp->vp_length);
278  a2_len = vp->vp_length;
279 
280  a2[a2_len] = ':';
281  a2_len++;
282 
284  if (!vp) {
285  REDEBUG("No Digest-Attributes.URI: Cannot perform Digest authentication");
287  }
288  memcpy(&a2[a2_len], vp->vp_octets, vp->vp_length);
289  a2_len += vp->vp_length;
290 
291  /*
292  * QOP is "auth-int", tack on ": Digest-Attributes.Body-Digest"
293  */
294  qop = fr_pair_find_by_da_nested(list, NULL, attr_digest_qop);
295  if (qop) {
296  if (strcasecmp(qop->vp_strvalue, "auth-int") == 0) {
297  fr_pair_t *body;
298 
299  /*
300  * Add in Digest-Attributes.Body-Digest
301  */
302  a2[a2_len] = ':';
303  a2_len++;
304 
305  /*
306  * Must be a hex representation of an MD5 digest.
307  */
309  if (!body) {
310  REDEBUG("No Digest-Attributes.Body-Digest: Cannot perform Digest authentication");
312  }
313 
314  if ((a2_len + body->vp_length) > sizeof(a2)) {
315  REDEBUG("Digest-Attributes.Body-Digest is too long");
317  }
318 
319  memcpy(a2 + a2_len, body->vp_octets, body->vp_length);
320  a2_len += body->vp_length;
321 
322  } else if (strcasecmp(qop->vp_strvalue, "auth") != 0) {
323  REDEBUG("%pP - Unknown value: Cannot perform Digest authentication", qop);
325  }
326  }
327 
328  a2[a2_len] = '\0';
329  RDEBUG2("A2 = %s", a2);
330 
331  /*
332  * KD = H(A1) : Digest-Attributes.Nonce ... : H(A2).
333  * Compute MD5 if Digest-Attributes.Algorithm == "MD5-Sess",
334  * or if we found a User-Password.
335  */
336  if (((algo != NULL) && (strcasecmp(algo->vp_strvalue, "MD5-Sess") == 0)) ||
337  (passwd->da == attr_cleartext_password)) {
338  a1[a1_len] = '\0';
339  fr_md5_calc(&hash[0], &a1[0], a1_len);
340  } else {
341  memcpy(&hash[0], &a1[0], a1_len);
342  }
343  fr_base16_encode(&FR_SBUFF_OUT((char *) kd, (sizeof(hash) * 2) + 1), &FR_DBUFF_TMP(hash, sizeof(hash)));
344 
345  RHEXDUMP_INLINE3(hash, sizeof(hash), "H(A1)");
346 
347  kd_len = 32;
348 
349  kd[kd_len] = ':';
350  kd_len++;
351 
352  memcpy(&kd[kd_len], nonce->vp_octets, nonce->vp_length);
353  kd_len += nonce->vp_length;
354 
355  /*
356  * No QOP defined. Do RFC 2069 compatibility.
357  */
358  if (!qop) {
359  /*
360  * Do nothing here.
361  */
362 
363  } else { /* Digest-Attributes.QOP MUST be "auth" or "auth-int" */
364  /*
365  * Tack on ":" Digest-Attributes.Nonce-Count ":" Digest-Attributes.CNonce
366  * ":" Digest-Attributes.QOP
367  */
368  kd[kd_len] = ':';
369  kd_len++;
370 
372  if (!vp) {
373  REDEBUG("No Digest-Attributes.Nonce-Count: Cannot perform Digest authentication");
375  }
376  memcpy(&kd[kd_len], vp->vp_octets, vp->vp_length);
377  kd_len += vp->vp_length;
378 
379  kd[kd_len] = ':';
380  kd_len++;
381 
383  if (!vp) {
384  REDEBUG("No Digest-Attributes.CNonce: Cannot perform Digest authentication");
386  }
387  memcpy(&kd[kd_len], vp->vp_octets, vp->vp_length);
388  kd_len += vp->vp_length;
389 
390  kd[kd_len] = ':';
391  kd_len++;
392 
393  memcpy(&kd[kd_len], qop->vp_octets, qop->vp_length);
394  kd_len += qop->vp_length;
395  }
396 
397  /*
398  * Tack on ":" H(A2)
399  */
400  kd[kd_len] = ':';
401  kd_len++;
402 
403  fr_md5_calc(&hash[0], &a2[0], a2_len);
404 
405  fr_base16_encode(&FR_SBUFF_OUT((char *) kd + kd_len, (sizeof(hash) * 2) + 1), &FR_DBUFF_TMP(hash, sizeof(hash)));
406 
407  RHEXDUMP_INLINE3(hash, sizeof(hash), "H(A2)");
408 
409  kd_len += 32;
410 
411  kd[kd_len] = 0;
412 
413  RDEBUG2("KD = %s\n", &kd[0]);
414 
415  /*
416  * Take the hash of KD.
417  */
418  fr_md5_calc(&hash[0], &kd[0], kd_len);
419  memcpy(&kd[0], &hash[0], 16);
420 
421  /*
422  * Get the binary value of Digest-Response. This isn't
423  * inside of the Digest-Attributes group.
424  */
425  vp = fr_pair_find_by_da(&request->request_pairs, NULL, attr_digest_response);
426  if (!vp) {
427  REDEBUG("No Digest-Response attribute in the request. Cannot perform digest authentication");
429  }
430 
431  if (fr_base16_decode(NULL, &FR_DBUFF_TMP(&hash[0], sizeof(hash)),
432  &FR_SBUFF_IN(vp->vp_strvalue, vp->vp_length), false) != (ssize_t)(vp->vp_length >> 1)) {
433  RDEBUG2("Invalid text in Digest-Response");
435  }
436 
437  RDEBUG3("Comparing hashes, received: %pV, calculated: %pH", &vp->data, fr_box_octets(kd, 16));
438 
439  /*
440  * And finally, compare the digest in the packet with KD.
441  */
442  if (memcmp(&kd[0], &hash[0], 16) == 0) RETURN_MODULE_OK;
443 
444  REDEBUG("FAILED authentication");
446 }
447 
448 
449 /*
450  * Create instance for our module. Allocate space for
451  * instance structure and read configuration parameters
452  */
453 static int mod_instantiate(module_inst_ctx_t const *mctx)
454 {
455  rlm_digest_t *inst = talloc_get_type_abort(mctx->inst->data, rlm_digest_t);
456 
457  inst->auth_type = fr_dict_enum_by_name(attr_auth_type, mctx->inst->name, -1);
458  if (!inst->auth_type) {
459  WARN("Failed to find 'authenticate %s {...}' section. Digest authentication will likely not work",
460  mctx->inst->name);
461  }
462 
463  return 0;
464 }
465 
466 /*
467  * The module name should be the only globally exported symbol.
468  * That is, everything else should be 'static'.
469  *
470  * If the module needs to temporarily modify it's instantiation
471  * data, the type should be changed to MODULE_TYPE_THREAD_UNSAFE.
472  * The server will then take care of ensuring that the module
473  * is single-threaded.
474  */
475 extern module_rlm_t rlm_digest;
477  .common = {
478  .magic = MODULE_MAGIC_INIT,
479  .name = "digest",
480  .inst_size = sizeof(rlm_digest_t),
482  },
483  .dict = &dict_radius,
484  .method_names = (module_method_name_t[]){
485  { .name1 = "recv", .name2 = "access-request", .method = mod_authorize },
486  { .name1 = "authenticate", .name2 = CF_IDENT_ANY, .method = mod_authenticate },
488  },
489 };
unlang_action_t
Returned by unlang_op_t calls, determine the next action of the interpreter.
Definition: action.h:35
#define fr_base16_encode(_out, _in)
Definition: base16.h:57
#define fr_base16_decode(_err, _out, _in, _no_trailing)
Definition: base16.h:95
#define RCSID(id)
Definition: build.h:444
#define UNUSED
Definition: build.h:313
#define CF_IDENT_ANY
Definition: cf_util.h:78
#define FR_DBUFF_TMP(_start, _len_or_end)
Creates a compound literal to pass into functions which accept a dbuff.
Definition: dbuff.h:509
fr_dict_attr_t const ** out
Where to write a pointer to the resolved fr_dict_attr_t.
Definition: dict.h:250
fr_dict_t const ** out
Where to write a pointer to the loaded/resolved fr_dict_t.
Definition: dict.h:263
fr_dict_enum_value_t * fr_dict_enum_by_name(fr_dict_attr_t const *da, char const *name, ssize_t len)
Definition: dict_util.c:2992
Specifies an attribute which must be present for the module to function.
Definition: dict.h:249
Specifies a dictionary which must be loaded/loadable for the module to function.
Definition: dict.h:262
Value of an enumerated attribute.
Definition: dict.h:209
char const *_CONST name
Instance name.
Definition: dl_module.h:163
void *_CONST data
Module instance's parsed configuration.
Definition: dl_module.h:165
#define MODULE_MAGIC_INIT
Stop people using different module/library/server versions together.
Definition: dl_module.h:65
#define RDEBUG3(fmt,...)
Definition: log.h:343
#define RHEXDUMP_INLINE3(_data, _len, _fmt,...)
Definition: log.h:686
@ FR_TYPE_TLV
Contains nested attributes.
Definition: merged_model.c:118
@ FR_TYPE_STRING
String of printable characters.
Definition: merged_model.c:83
@ FR_TYPE_UINT32
32 Bit unsigned integer.
Definition: merged_model.c:99
long int ssize_t
Definition: merged_model.c:24
void fr_md5_calc(uint8_t out[static MD5_DIGEST_LENGTH], uint8_t const *in, size_t inlen)
Perform a single digest operation on a single input buffer.
Definition: merged_model.c:251
unsigned char uint8_t
Definition: merged_model.c:30
int strcasecmp(char *s1, char *s2)
Definition: missing.c:66
dl_module_inst_t const * inst
Dynamic loader API handle for the module.
Definition: module_ctx.h:52
dl_module_inst_t const * inst
Dynamic loader API handle for the module.
Definition: module_ctx.h:42
Temporary structure to hold arguments for module calls.
Definition: module_ctx.h:41
Temporary structure to hold arguments for instantiation calls.
Definition: module_ctx.h:51
Specifies a module method identifier.
Definition: module_method.c:36
bool module_rlm_section_type_set(request_t *request, fr_dict_attr_t const *type_da, fr_dict_enum_value_t const *enumv)
Set the next section type if it's not already set.
Definition: module_rlm.c:397
module_t common
Common fields presented by all modules.
Definition: module_rlm.h:37
fr_pair_t * fr_pair_find_by_da(fr_pair_list_t const *list, fr_pair_t const *prev, fr_dict_attr_t const *da)
Find the first pair with a matching da.
Definition: pair.c:688
fr_pair_t * fr_pair_find_by_da_nested(fr_pair_list_t const *list, fr_pair_t const *prev, fr_dict_attr_t const *da)
Find a pair with a matching fr_dict_attr_t, by walking the nested fr_dict_attr_t tree.
Definition: pair.c:765
#define REDEBUG(fmt,...)
Definition: radclient.h:52
#define RDEBUG2(fmt,...)
Definition: radclient.h:54
#define WARN(fmt,...)
Definition: radclient.h:47
#define RETURN_MODULE_REJECT
Definition: rcode.h:55
#define RETURN_MODULE_NOOP
Definition: rcode.h:62
#define RETURN_MODULE_INVALID
Definition: rcode.h:59
#define RETURN_MODULE_OK
Definition: rcode.h:57
rlm_rcode_t
Return codes indicating the result of the module call.
Definition: rcode.h:40
static const fr_dict_attr_t * attr_digest_user_name
Definition: rlm_digest.c:62
static const fr_dict_attr_t * attr_digest_body_digest
Definition: rlm_digest.c:53
static const fr_dict_attr_t * attr_digest_ha1
Definition: rlm_digest.c:55
static const fr_dict_attr_t * attr_digest_method
Definition: rlm_digest.c:56
static const fr_dict_attr_t * attr_digest_qop
Definition: rlm_digest.c:59
static const fr_dict_attr_t * attr_cleartext_password
Definition: rlm_digest.c:48
static const fr_dict_attr_t * attr_digest_attributes
Definition: rlm_digest.c:51
static fr_dict_t const * dict_freeradius
Definition: rlm_digest.c:37
static unlang_action_t mod_authenticate(rlm_rcode_t *p_result, UNUSED module_ctx_t const *mctx, request_t *request)
Definition: rlm_digest.c:114
module_rlm_t rlm_digest
Definition: rlm_digest.c:476
static const fr_dict_attr_t * attr_digest_cnonce
Definition: rlm_digest.c:54
static fr_dict_t const * dict_radius
Definition: rlm_digest.c:38
static const fr_dict_attr_t * attr_digest_algorithm
Definition: rlm_digest.c:52
static const fr_dict_attr_t * attr_digest_response
Definition: rlm_digest.c:50
static const fr_dict_attr_t * attr_digest_uri
Definition: rlm_digest.c:61
static const fr_dict_attr_t * attr_digest_realm
Definition: rlm_digest.c:60
static const fr_dict_attr_t * attr_digest_nonce_count
Definition: rlm_digest.c:58
static unlang_action_t mod_authorize(rlm_rcode_t *p_result, module_ctx_t const *mctx, request_t *request)
Definition: rlm_digest.c:86
static const fr_dict_attr_t * attr_auth_type
Definition: rlm_digest.c:47
fr_dict_attr_autoload_t rlm_digest_dict_attr[]
Definition: rlm_digest.c:65
fr_dict_enum_value_t * auth_type
Definition: rlm_digest.c:34
static const fr_dict_attr_t * attr_digest_nonce
Definition: rlm_digest.c:57
static int mod_instantiate(module_inst_ctx_t const *mctx)
Definition: rlm_digest.c:453
fr_dict_autoload_t rlm_digest_dict[]
Definition: rlm_digest.c:41
static unsigned int hash(char const *username, unsigned int tablesize)
Definition: rlm_passwd.c:132
static int instantiate(module_inst_ctx_t const *mctx)
Definition: rlm_rest.c:1312
#define FR_SBUFF_IN(_start, _len_or_end)
#define FR_SBUFF_OUT(_start, _len_or_end)
#define MODULE_NAME_TERMINATOR
Definition: module.h:135
eap_aka_sim_process_conf_t * inst
fr_pair_t * vp
Stores an attribute, a value and various bits of other data.
Definition: pair.h:68
fr_dict_attr_t const *_CONST da
Dictionary attribute defines the attribute number, vendor and type of the pair.
Definition: pair.h:69
#define FR_MAX_STRING_LEN
Definition: value.h:30
int nonnull(2, 5))
#define fr_box_octets(_val, _len)
Definition: value.h:281