All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
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: ad15c878c29ea530dea899acddbbf0b05959dc27 $
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@ox.org>
24  */
25 RCSID("$Id: ad15c878c29ea530dea899acddbbf0b05959dc27 $")
26 
27 #include <freeradius-devel/radiusd.h>
28 #include <freeradius-devel/modules.h>
29 #include <freeradius-devel/md5.h>
30 
31 static int digest_fix(REQUEST *request)
32 {
33  VALUE_PAIR *first, *i;
34  vp_cursor_t cursor;
35 
36  /*
37  * We need both of these attributes to do the authentication.
38  */
40  if (!first) {
41  return RLM_MODULE_NOOP;
42  }
43 
44  /*
45  * Check the sanity of the attribute.
46  */
47  if (first->vp_length != 32) {
48  return RLM_MODULE_NOOP;
49  }
50 
51  /*
52  * Check for proper format of the Digest-Attributes
53  */
54  RDEBUG("Checking for correctly formatted Digest-Attributes");
55 
57  if (!first) {
58  return RLM_MODULE_NOOP;
59  }
60 
61  fr_cursor_init(&cursor, &first);
62  while ((i = fr_cursor_next_by_num(&cursor, 0, PW_DIGEST_ATTRIBUTES, TAG_ANY))) {
63  int length = i->vp_length;
64  int attrlen;
65  uint8_t const *p = i->vp_octets;
66 
67  /*
68  * Until this stupidly encoded attribute is exhausted.
69  */
70  while (length > 0) {
71  /*
72  * The attribute type must be valid
73  */
74  if ((p[0] == 0) || (p[0] > 10)) {
75  RDEBUG("Not formatted as Digest-Attributes: TLV type (%u) invalid", (unsigned int) p[0]);
76  return RLM_MODULE_NOOP;
77  }
78 
79  attrlen = p[1]; /* stupid VSA format */
80 
81  /*
82  * Too short.
83  */
84  if (attrlen < 3) {
85  RDEBUG("Not formatted as Digest-Attributes: TLV too short");
86  return RLM_MODULE_NOOP;
87  }
88 
89  /*
90  * Too long.
91  */
92  if (attrlen > length) {
93  RDEBUG("Not formatted as Digest-Attributes: TLV too long)");
94  return RLM_MODULE_NOOP;
95  }
96 
97  length -= attrlen;
98  p += attrlen;
99  } /* loop over this one attribute */
100  }
101 
102  /*
103  * Convert them to something sane.
104  */
105  RDEBUG("Digest-Attributes look OK. Converting them to something more useful");
106  fr_cursor_first(&cursor);
107  while ((i = fr_cursor_next_by_num(&cursor, 0, PW_DIGEST_ATTRIBUTES, TAG_ANY))) {
108  int length = i->vp_length;
109  int attrlen;
110  uint8_t const *p = &i->vp_octets[0];
111  VALUE_PAIR *sub;
112 
113  /*
114  * Until this stupidly encoded attribute is exhausted.
115  */
116  while (length > 0) {
117  /*
118  * The attribute type must be valid
119  */
120  if ((p[0] == 0) || (p[0] > 10)) {
121  REDEBUG("Received Digest-Attributes with invalid sub-attribute %d", p[0]);
122  return RLM_MODULE_INVALID;
123  }
124 
125  attrlen = p[1]; /* stupid VSA format */
126 
127  /*
128  * Too short.
129  */
130  if (attrlen < 3) {
131  REDEBUG("Received Digest-Attributes with short sub-attribute %d, of length %d", p[0], attrlen);
132  return RLM_MODULE_INVALID;
133  }
134 
135  /*
136  * Too long.
137  */
138  if (attrlen > length) {
139  REDEBUG("Received Digest-Attributes with long sub-attribute %d, of length %d", p[0], attrlen);
140  return RLM_MODULE_INVALID;
141  }
142 
143  /*
144  * Create a new attribute, broken out of
145  * the stupid sub-attribute crap.
146  *
147  * Didn't they know that VSA's exist?
148  */
149  sub = radius_pair_create(request->packet, &request->packet->vps,
150  PW_DIGEST_REALM - 1 + p[0], 0);
151  fr_pair_value_bstrncpy(sub, p + 2, attrlen - 2);
152 
153  if ((rad_debug_lvl > 1) && fr_log_fp) {
155  }
156 
157  /*
158  * FIXME: Check for the existence
159  * of the necessary attributes!
160  */
161 
162  length -= attrlen;
163  p += attrlen;
164  } /* loop over this one attribute */
165  }
166 
167  return RLM_MODULE_OK;
168 }
169 
170 static rlm_rcode_t CC_HINT(nonnull) mod_authorize(UNUSED void *instance, REQUEST *request)
171 {
172  rlm_rcode_t rcode;
173 
174  /*
175  * Double-check and fix the attributes.
176  */
177  rcode = digest_fix(request);
178  if (rcode != RLM_MODULE_OK) return rcode;
179 
180 
181  if (fr_pair_find_by_num(request->config, 0, PW_AUTH_TYPE, TAG_ANY)) {
182  RWDEBUG2("Auth-Type already set. Not setting to DIGEST");
183  return RLM_MODULE_NOOP;
184  }
185 
186  /*
187  * Everything's OK, add a digest authentication type.
188  */
189  RDEBUG("Adding Auth-Type = DIGEST");
190  pair_make_config("Auth-Type", "DIGEST", T_OP_EQ);
191 
192  return RLM_MODULE_OK;
193 }
194 
195 /*
196  * Perform all of the wondrous variants of digest authentication.
197  */
198 static rlm_rcode_t CC_HINT(nonnull) mod_authenticate(UNUSED void *instance, REQUEST *request)
199 {
200  int i;
201  size_t a1_len, a2_len, kd_len;
202  uint8_t a1[(MAX_STRING_LEN + 1) * 5]; /* can be 5 attributes */
203  uint8_t a2[(MAX_STRING_LEN + 1) * 3]; /* can be 3 attributes */
204  uint8_t kd[(MAX_STRING_LEN + 1) * 5];
205  uint8_t hash[16]; /* MD5 output */
206  VALUE_PAIR *vp, *passwd, *algo;
207  VALUE_PAIR *qop, *nonce;
208 
209  /*
210  * We require access to the plain-text password, or to the
211  * Digest-HA1 parameter.
212  */
213  passwd = fr_pair_find_by_num(request->config, 0, PW_DIGEST_HA1, TAG_ANY);
214  if (passwd) {
215  if (passwd->vp_length != 32) {
216  RAUTH("Digest-HA1 has invalid length, authentication failed");
217  return RLM_MODULE_INVALID;
218  }
219  } else {
220  passwd = fr_pair_find_by_num(request->config, 0, PW_CLEARTEXT_PASSWORD, TAG_ANY);
221  }
222  if (!passwd) {
223  RAUTH("Cleartext-Password or Digest-HA1 is required for authentication");
224  return RLM_MODULE_INVALID;
225  }
226 
227  /*
228  * We need these, too.
229  */
230  vp = fr_pair_find_by_num(request->packet->vps, 0, PW_DIGEST_ATTRIBUTES, TAG_ANY);
231  if (!vp) {
232  error:
233  REDEBUG("You set 'Auth-Type = Digest' for a request that does not contain any digest attributes!");
234  return RLM_MODULE_INVALID;
235  }
236 
237  /*
238  * Look for the "internal" FreeRADIUS Digest attributes.
239  * If they don't exist, it means that someone forced
240  * Auth-Type = digest, without putting "digest" into the
241  * "authorize" section. In that case, try to decode the
242  * attributes here.
243  */
244  if (!fr_pair_find_by_num(request->packet->vps, 0, PW_DIGEST_NONCE, TAG_ANY)) {
245  int rcode;
246 
247  rcode = digest_fix(request);
248 
249  /*
250  * NOOP means "couldn't find the attributes".
251  * That's bad.
252  */
253  if (rcode == RLM_MODULE_NOOP) goto error;
254 
255  if (rcode != RLM_MODULE_OK) return rcode;
256  }
257 
258  /*
259  * We require access to the Digest-Nonce-Value
260  */
261  nonce = fr_pair_find_by_num(request->packet->vps, 0, PW_DIGEST_NONCE, TAG_ANY);
262  if (!nonce) {
263  REDEBUG("No Digest-Nonce: Cannot perform Digest authentication");
264  return RLM_MODULE_INVALID;
265  }
266 
267  /*
268  * A1 = Digest-User-Name ":" Realm ":" Password
269  */
270  vp = fr_pair_find_by_num(request->packet->vps, 0, PW_DIGEST_USER_NAME, TAG_ANY);
271  if (!vp) {
272  REDEBUG("No Digest-User-Name: Cannot perform Digest authentication");
273  return RLM_MODULE_INVALID;
274  }
275  memcpy(&a1[0], vp->vp_octets, vp->vp_length);
276  a1_len = vp->vp_length;
277 
278  a1[a1_len] = ':';
279  a1_len++;
280 
281  vp = fr_pair_find_by_num(request->packet->vps, 0, PW_DIGEST_REALM, TAG_ANY);
282  if (!vp) {
283  REDEBUG("No Digest-Realm: Cannot perform Digest authentication");
284  return RLM_MODULE_INVALID;
285  }
286  memcpy(&a1[a1_len], vp->vp_octets, vp->vp_length);
287  a1_len += vp->vp_length;
288 
289  a1[a1_len] = ':';
290  a1_len++;
291 
292  if (passwd->da->attr == PW_CLEARTEXT_PASSWORD) {
293  memcpy(&a1[a1_len], passwd->vp_octets, passwd->vp_length);
294  a1_len += passwd->vp_length;
295  a1[a1_len] = '\0';
296  RDEBUG2("A1 = %s", a1);
297  } else {
298  a1[a1_len] = '\0';
299  RDEBUG2("A1 = %s (using Digest-HA1)", a1);
300  a1_len = 16;
301  }
302 
303  /*
304  * See which variant we calculate.
305  * Assume MD5 if no Digest-Algorithm attribute received
306  */
307  algo = fr_pair_find_by_num(request->packet->vps, 0, PW_DIGEST_ALGORITHM, TAG_ANY);
308  if ((!algo) ||
309  (strcasecmp(algo->vp_strvalue, "MD5") == 0)) {
310  /*
311  * Set A1 to Digest-HA1 if no User-Password found
312  */
313  if (passwd->da->attr == PW_DIGEST_HA1) {
314  if (fr_hex2bin(&a1[0], sizeof(a1), passwd->vp_strvalue, passwd->vp_length) != 16) {
315  RDEBUG2("Invalid text in Digest-HA1");
316  return RLM_MODULE_INVALID;
317  }
318  }
319 
320  } else if (strcasecmp(algo->vp_strvalue, "MD5-sess") == 0) {
321  /*
322  * K1 = H(A1) : Digest-Nonce ... : H(A2)
323  *
324  * If we find Digest-HA1, we assume it contains
325  * H(A1).
326  */
327  if (passwd->da->attr == PW_CLEARTEXT_PASSWORD) {
328  fr_md5_calc(hash, &a1[0], a1_len);
329  fr_bin2hex((char *) &a1[0], hash, 16);
330  } else { /* MUST be Digest-HA1 */
331  memcpy(&a1[0], passwd->vp_strvalue, 32);
332  }
333  a1_len = 32;
334 
335  a1[a1_len] = ':';
336  a1_len++;
337 
338  /*
339  * Tack on the Digest-Nonce. Length must be even
340  */
341  if ((nonce->vp_length & 1) != 0) {
342  REDEBUG("Received Digest-Nonce hex string with invalid length: Cannot perform Digest authentication");
343  return RLM_MODULE_INVALID;
344  }
345  memcpy(&a1[a1_len], nonce->vp_octets, nonce->vp_length);
346  a1_len += nonce->vp_length;
347 
348  a1[a1_len] = ':';
349  a1_len++;
350 
351  vp = fr_pair_find_by_num(request->packet->vps, 0, PW_DIGEST_CNONCE, TAG_ANY);
352  if (!vp) {
353  REDEBUG("No Digest-CNonce: Cannot perform Digest authentication");
354  return RLM_MODULE_INVALID;
355  }
356 
357  /*
358  * Digest-CNonce length must be even
359  */
360  if ((vp->vp_length & 1) != 0) {
361  REDEBUG("Received Digest-CNonce hex string with invalid length: Cannot perform Digest authentication");
362  return RLM_MODULE_INVALID;
363  }
364  memcpy(&a1[a1_len], vp->vp_octets, vp->vp_length);
365  a1_len += vp->vp_length;
366 
367  } else if (strcasecmp(algo->vp_strvalue, "MD5") != 0) {
368  /*
369  * We check for "MD5-sess" and "MD5".
370  * Anything else is an error.
371  */
372  REDEBUG("Unknown Digest-Algorithm \"%s\": Cannot perform Digest authentication", vp->vp_strvalue);
373  return RLM_MODULE_INVALID;
374  }
375 
376  /*
377  * A2 = Digest-Method ":" Digest-URI
378  */
379  vp = fr_pair_find_by_num(request->packet->vps, 0, PW_DIGEST_METHOD, TAG_ANY);
380  if (!vp) {
381  REDEBUG("No Digest-Method: Cannot perform Digest authentication");
382  return RLM_MODULE_INVALID;
383  }
384  memcpy(&a2[0], vp->vp_octets, vp->vp_length);
385  a2_len = vp->vp_length;
386 
387  a2[a2_len] = ':';
388  a2_len++;
389 
390  vp = fr_pair_find_by_num(request->packet->vps, 0, PW_DIGEST_URI, TAG_ANY);
391  if (!vp) {
392  REDEBUG("No Digest-URI: Cannot perform Digest authentication");
393  return RLM_MODULE_INVALID;
394  }
395  memcpy(&a2[a2_len], vp->vp_octets, vp->vp_length);
396  a2_len += vp->vp_length;
397 
398  /*
399  * QOP is "auth-int", tack on ": Digest-Body-Digest"
400  */
401  qop = fr_pair_find_by_num(request->packet->vps, 0, PW_DIGEST_QOP, TAG_ANY);
402  if (qop) {
403  if (strcasecmp(qop->vp_strvalue, "auth-int") == 0) {
404  VALUE_PAIR *body;
405 
406  /*
407  * Add in Digest-Body-Digest
408  */
409  a2[a2_len] = ':';
410  a2_len++;
411 
412  /*
413  * Must be a hex representation of an MD5 digest.
414  */
415  body = fr_pair_find_by_num(request->packet->vps, 0, PW_DIGEST_BODY_DIGEST, TAG_ANY);
416  if (!body) {
417  REDEBUG("No Digest-Body-Digest: Cannot perform Digest authentication");
418  return RLM_MODULE_INVALID;
419  }
420 
421  if ((a2_len + body->vp_length) > sizeof(a2)) {
422  REDEBUG("Digest-Body-Digest is too long");
423  return RLM_MODULE_INVALID;
424  }
425 
426  memcpy(a2 + a2_len, body->vp_octets, body->vp_length);
427  a2_len += body->vp_length;
428 
429  } else if (strcasecmp(qop->vp_strvalue, "auth") != 0) {
430  REDEBUG("Unknown Digest-QOP \"%s\": Cannot perform Digest authentication", qop->vp_strvalue);
431  return RLM_MODULE_INVALID;
432  }
433  }
434 
435  a2[a2_len] = '\0';
436  RDEBUG2("A2 = %s", a2);
437 
438  /*
439  * KD = H(A1) : Digest-Nonce ... : H(A2).
440  * Compute MD5 if Digest-Algorithm == "MD5-Sess",
441  * or if we found a User-Password.
442  */
443  if (((algo != NULL) &&
444  (strcasecmp(algo->vp_strvalue, "MD5-Sess") == 0)) ||
445  (passwd->da->attr == PW_CLEARTEXT_PASSWORD)) {
446  a1[a1_len] = '\0';
447  fr_md5_calc(&hash[0], &a1[0], a1_len);
448  } else {
449  memcpy(&hash[0], &a1[0], a1_len);
450  }
451  fr_bin2hex((char *) kd, hash, sizeof(hash));
452 
453 #ifndef NRDEBUG
454  if (rad_debug_lvl > 1) {
455  fr_printf_log("H(A1) = ");
456  for (i = 0; i < 16; i++) {
457  fr_printf_log("%02x", hash[i]);
458  }
459  fr_printf_log("\n");
460  }
461 #endif
462  kd_len = 32;
463 
464  kd[kd_len] = ':';
465  kd_len++;
466 
467  memcpy(&kd[kd_len], nonce->vp_octets, nonce->vp_length);
468  kd_len += nonce->vp_length;
469 
470  /*
471  * No QOP defined. Do RFC 2069 compatibility.
472  */
473  if (!qop) {
474  /*
475  * Do nothing here.
476  */
477 
478  } else { /* Digest-QOP MUST be "auth" or "auth-int" */
479  /*
480  * Tack on ":" Digest-Nonce-Count ":" Digest-CNonce
481  * ":" Digest-QOP
482  */
483  kd[kd_len] = ':';
484  kd_len++;
485 
486  vp = fr_pair_find_by_num(request->packet->vps, 0, PW_DIGEST_NONCE_COUNT, TAG_ANY);
487  if (!vp) {
488  REDEBUG("No Digest-Nonce-Count: Cannot perform Digest authentication");
489  return RLM_MODULE_INVALID;
490  }
491  memcpy(&kd[kd_len], vp->vp_octets, vp->vp_length);
492  kd_len += vp->vp_length;
493 
494  kd[kd_len] = ':';
495  kd_len++;
496 
497  vp = fr_pair_find_by_num(request->packet->vps, 0, PW_DIGEST_CNONCE, TAG_ANY);
498  if (!vp) {
499  REDEBUG("No Digest-CNonce: Cannot perform Digest authentication");
500  return RLM_MODULE_INVALID;
501  }
502  memcpy(&kd[kd_len], vp->vp_octets, vp->vp_length);
503  kd_len += vp->vp_length;
504 
505  kd[kd_len] = ':';
506  kd_len++;
507 
508  memcpy(&kd[kd_len], qop->vp_octets, qop->vp_length);
509  kd_len += qop->vp_length;
510  }
511 
512  /*
513  * Tack on ":" H(A2)
514  */
515  kd[kd_len] = ':';
516  kd_len++;
517 
518  fr_md5_calc(&hash[0], &a2[0], a2_len);
519 
520  fr_bin2hex((char *) kd + kd_len, hash, sizeof(hash));
521 
522 #ifndef NRDEBUG
523  if (rad_debug_lvl > 1) {
524  fr_printf_log("H(A2) = ");
525  for (i = 0; i < 16; i++) {
526  fr_printf_log("%02x", hash[i]);
527  }
528  fr_printf_log("\n");
529  }
530 #endif
531  kd_len += 32;
532 
533  kd[kd_len] = 0;
534 
535  RDEBUG2("KD = %s\n", &kd[0]);
536 
537  /*
538  * Take the hash of KD.
539  */
540  fr_md5_calc(&hash[0], &kd[0], kd_len);
541  memcpy(&kd[0], &hash[0], 16);
542 
543  /*
544  * Get the binary value of Digest-Response
545  */
546  vp = fr_pair_find_by_num(request->packet->vps, 0, PW_DIGEST_RESPONSE, TAG_ANY);
547  if (!vp) {
548  REDEBUG("No Digest-Response attribute in the request. Cannot perform digest authentication");
549  return RLM_MODULE_INVALID;
550  }
551 
552  if (fr_hex2bin(&hash[0], sizeof(hash), vp->vp_strvalue, vp->vp_length) != (vp->vp_length >> 1)) {
553  RDEBUG2("Invalid text in Digest-Response");
554  return RLM_MODULE_INVALID;
555  }
556 
557  if (RDEBUG_ENABLED3) {
558  char buffer[33];
559 
560  fr_bin2hex(buffer, kd, 16);
561 
562  RDEBUG3("Comparing hashes, received: %s, calculated: %s", vp->vp_strvalue, buffer);
563  }
564 
565  /*
566  * And finally, compare the digest in the packet with KD.
567  */
568  if (memcmp(&kd[0], &hash[0], 16) == 0) return RLM_MODULE_OK;
569 
570  REDEBUG("FAILED authentication");
571  return RLM_MODULE_REJECT;
572 }
573 
574 /*
575  * The module name should be the only globally exported symbol.
576  * That is, everything else should be 'static'.
577  *
578  * If the module needs to temporarily modify it's instantiation
579  * data, the type should be changed to RLM_TYPE_THREAD_UNSAFE.
580  * The server will then take care of ensuring that the module
581  * is single-threaded.
582  */
583 extern module_t rlm_digest;
584 module_t rlm_digest = {
586  .name = "digest",
587  .methods = {
590  },
591 };
static int digest_fix(REQUEST *request)
Definition: rlm_digest.c:31
void fr_md5_calc(uint8_t *out, uint8_t const *in, size_t inlen)
Calculate the MD5 hash of the contents of a buffer.
Definition: md5.c:28
FILE * fr_log_fp
Definition: radius.c:81
VALUE_PAIR * fr_cursor_first(vp_cursor_t *cursor)
Rewind cursor to the start of the list.
Definition: cursor.c:105
#define RDEBUG_ENABLED3
True if request debug level 1-3 messages are enabled.
Definition: log.h:239
The module is OK, continue.
Definition: radiusd.h:91
Metadata exported by the module.
Definition: modules.h:134
VALUE_PAIR * fr_cursor_next_by_num(vp_cursor_t *cursor, unsigned int vendor, unsigned int attr, int8_t tag)
Iterate over a collection of VALUE_PAIRs of a given type in the pairlist.
Definition: cursor.c:200
VALUE_PAIR * radius_pair_create(TALLOC_CTX *ctx, VALUE_PAIR **vps, unsigned int attribute, unsigned int vendor)
Create a VALUE_PAIR and add it to a list of VALUE_PAIR s.
Definition: pair.c:704
static rlm_rcode_t mod_authorize(void *instance, REQUEST *request)
Handle authorization requests using Couchbase document data.
#define UNUSED
Definition: libradius.h:134
#define RLM_MODULE_INIT
Definition: modules.h:86
VALUE_PAIR * vps
Result of decoding the packet into VALUE_PAIRs.
Definition: libradius.h:162
VALUE_PAIR * fr_cursor_init(vp_cursor_t *cursor, VALUE_PAIR *const *node)
Setup a cursor to iterate over attribute pairs.
Definition: cursor.c:60
#define PW_DIGEST_RESPONSE
Definition: radius.h:164
uint8_t length
Definition: proto_bfd.c:203
Definition: token.h:46
The module considers the request invalid.
Definition: radiusd.h:93
static rlm_rcode_t mod_authenticate(void *instance, REQUEST *request) CC_HINT(nonnull)
void fr_pair_fprint(FILE *, VALUE_PAIR const *vp)
Print one attribute and value to FP.
Definition: pair.c:2232
Abstraction to allow iterating over different configurations of VALUE_PAIRs.
Definition: pair.h:144
static unsigned int hash(char const *username, unsigned int tablesize)
Definition: rlm_passwd.c:124
#define PW_DIGEST_ATTRIBUTES
Definition: radius.h:165
#define pair_make_config(_a, _b, _c)
Definition: radiusd.h:547
size_t fr_hex2bin(uint8_t *bin, size_t outlen, char const *hex, size_t inlen)
Convert hex strings to binary data.
Definition: misc.c:220
unsigned int attr
Attribute number.
Definition: dict.h:79
Immediately reject the request.
Definition: radiusd.h:89
Stores an attribute, a value and various bits of other data.
Definition: pair.h:112
0 methods index for authenticate section.
Definition: modules.h:41
enum rlm_rcodes rlm_rcode_t
Return codes indicating the result of the module call.
#define RWDEBUG2(fmt,...)
Definition: log.h:252
int strcasecmp(char *s1, char *s2)
Definition: missing.c:73
void fr_printf_log(char const *,...) CC_HINT(format(printf
Module succeeded without doing anything.
Definition: radiusd.h:96
#define RDEBUG2(fmt,...)
Definition: log.h:244
uint64_t magic
Used to validate module struct.
Definition: modules.h:135
#define TAG_ANY
Definition: pair.h:191
module_t rlm_digest
Definition: rlm_digest.c:584
log_lvl_t rad_debug_lvl
Global debugging level.
Definition: log.c:49
RADIUS_PACKET * packet
Incoming request.
Definition: radiusd.h:221
#define RAUTH(fmt,...)
Definition: log.h:202
#define REDEBUG(fmt,...)
Definition: log.h:254
VALUE_PAIR * fr_pair_find_by_num(VALUE_PAIR *head, unsigned int vendor, unsigned int attr, int8_t tag)
Find the pair with the matching attribute.
Definition: pair.c:639
fr_dict_attr_t const * da
Dictionary attribute defines the attribute.
Definition: pair.h:113
void fr_pair_value_bstrncpy(VALUE_PAIR *vp, void const *src, size_t len)
Copy data into an "string" data type.
Definition: pair.c:2043
#define MAX_STRING_LEN
Definition: libradius.h:120
1 methods index for authorize section.
Definition: modules.h:42
#define RCSID(id)
Definition: build.h:135
#define RDEBUG(fmt,...)
Definition: log.h:243
size_t fr_bin2hex(char *hex, uint8_t const *bin, size_t inlen)
Convert binary data to a hex string.
Definition: misc.c:254
static rlm_rcode_t CC_HINT(nonnull)
Definition: rlm_digest.c:170
#define RDEBUG3(fmt,...)
Definition: log.h:245