The FreeRADIUS server  $Id: 15bac2a4c627c01d1aa2047687b3418955ac7f00 $
encode.c
Go to the documentation of this file.
1 /*
2  * This library is free software; you can redistribute it and/or
3  * modify it under the terms of the GNU Lesser General Public
4  * License as published by the Free Software Foundation; either
5  * version 2.1 of the License, or (at your option) any later version.
6  *
7  * This library 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 GNU
10  * Lesser General Public License for more details.
11  *
12  * You should have received a copy of the GNU Lesser General Public
13  * License along with this library; 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: cb75f7569be13742e2a7b31f9c06603f4d516703 $
19  *
20  * @file protocols/radius/encode.c
21  * @brief Functions to encode RADIUS attributes
22  *
23  * @copyright 2000-2003,2006-2015 The FreeRADIUS server project
24  */
25 RCSID("$Id: cb75f7569be13742e2a7b31f9c06603f4d516703 $")
26 
27 #include <freeradius-devel/util/dbuff.h>
28 #include <freeradius-devel/util/md5.h>
29 #include <freeradius-devel/util/struct.h>
30 #include <freeradius-devel/io/test_point.h>
31 #include <freeradius-devel/protocol/radius/freeradius.internal.h>
32 #include "attrs.h"
33 
34 #define TAG_VALID(x) ((x) > 0 && (x) < 0x20)
35 
36 static ssize_t encode_value(fr_dbuff_t *dbuff,
37  fr_da_stack_t *da_stack, unsigned int depth,
38  fr_dcursor_t *cursor, void *encode_ctx);
39 
40 static ssize_t encode_child(fr_dbuff_t *dbuff,
41  fr_da_stack_t *da_stack, unsigned int depth,
42  fr_dcursor_t *cursor, void *encode_ctx);
43 
44 /** "encrypt" a password RADIUS style
45  *
46  * Input and output buffers can be identical if in-place encryption is needed.
47  */
49 {
50  fr_md5_ctx_t *md5_ctx, *md5_ctx_old;
52  uint8_t passwd[RADIUS_MAX_PASS_LENGTH] = {0};
53  size_t i, n;
54  size_t len;
55 
56  /*
57  * If the length is zero, round it up.
58  */
59  len = inlen;
60 
62 
63  (void) fr_dbuff_out_memcpy(passwd, input, len);
64  if (len < sizeof(passwd)) memset(passwd + len, 0, sizeof(passwd) - len);
65 
66  if (len == 0) len = AUTH_PASS_LEN;
67  else if ((len & 0x0f) != 0) {
68  len += 0x0f;
69  len &= ~0x0f;
70  }
71 
72  md5_ctx = fr_md5_ctx_alloc_from_list();
73  md5_ctx_old = fr_md5_ctx_alloc_from_list();
74 
75  fr_md5_update(md5_ctx, (uint8_t const *) packet_ctx->common->secret, packet_ctx->common->secret_length);
76  fr_md5_ctx_copy(md5_ctx_old, md5_ctx);
77 
78  /*
79  * Do first pass.
80  */
81  fr_md5_update(md5_ctx, packet_ctx->request_authenticator, AUTH_PASS_LEN);
82 
83  for (n = 0; n < len; n += AUTH_PASS_LEN) {
84  if (n > 0) {
85  fr_md5_ctx_copy(md5_ctx, md5_ctx_old);
86  fr_md5_update(md5_ctx, passwd + n - AUTH_PASS_LEN, AUTH_PASS_LEN);
87  }
88 
89  fr_md5_final(digest, md5_ctx);
90  for (i = 0; i < AUTH_PASS_LEN; i++) passwd[i + n] ^= digest[i];
91  }
92 
93  fr_md5_ctx_free_from_list(&md5_ctx);
94  fr_md5_ctx_free_from_list(&md5_ctx_old);
95 
96  return fr_dbuff_in_memcpy(dbuff, passwd, len);
97 }
98 
99 
101 {
102  fr_md5_ctx_t *md5_ctx, *md5_ctx_old;
105  size_t i, n;
106  uint32_t r;
107  size_t output_len, encrypted_len, padding;
108  ssize_t slen;
109  fr_dbuff_t work_dbuff = FR_DBUFF_MAX(dbuff, RADIUS_MAX_STRING_LENGTH);
110 
111  /*
112  * Limit the maximum size of the input password. 2 bytes
113  * are taken up by the salt, and one by the encoded
114  * "length" field.
115  */
116  if (inlen > (RADIUS_MAX_STRING_LENGTH - 3)) {
117  fail:
118  fr_strerror_const("Input password is too large for tunnel password encoding");
119  return -(inlen + 3);
120  }
121 
122  /*
123  * Length of the encrypted data is the clear-text
124  * password length plus one byte which encodes the length
125  * of the password. We round up to the nearest encoding
126  * block, and bound it by the size of the output buffer,
127  * while accounting for 2 bytes of salt.
128  *
129  * And also ensuring that we don't truncate the input
130  * password.
131  */
132  encrypted_len = ROUND_UP(inlen + 1, 16);
133  if (encrypted_len > (RADIUS_MAX_STRING_LENGTH - 2)) encrypted_len = (RADIUS_MAX_STRING_LENGTH - 2);
134 
135  /*
136  * Get the number of padding bytes in the last block.
137  */
138  padding = encrypted_len - (inlen + 1);
139 
140  output_len = encrypted_len + 2; /* account for the salt */
141 
142  /*
143  * We will have up to 253 octets of data in the output
144  * buffer, some of which are padding.
145  *
146  * If we over-run the output buffer, see if we can drop
147  * some of the padding bytes. If not, we return an error
148  * instead of truncating the password.
149  *
150  * Otherwise we lower the amount of data we copy into the
151  * output buffer, because the last bit is just padding,
152  * and can be safely discarded.
153  */
154  slen = fr_dbuff_set(&work_dbuff, output_len);
155  if (slen < 0) {
156  if (((size_t) -slen) > padding) goto fail;
157 
158  output_len += slen;
159  }
160  fr_dbuff_set_to_start(&work_dbuff);
161 
162  /*
163  * Copy the password over, and fill the remainder with random data.
164  */
165  (void) fr_dbuff_out_memcpy(tpasswd + 3, in, inlen);
166 
167  for (i = 3 + inlen; i < sizeof(tpasswd); i++) {
168  tpasswd[i] = fr_fast_rand(&packet_ctx->rand_ctx);
169  }
170 
171  /*
172  * Generate salt. The RFCs say:
173  *
174  * The high bit of salt[0] must be set, each salt in a
175  * packet should be unique, and they should be random
176  *
177  * So, we set the high bit, add in a counter, and then
178  * add in some PRNG data. should be OK..
179  */
180  r = fr_fast_rand(&packet_ctx->rand_ctx);
181  tpasswd[0] = (0x80 | (((packet_ctx->salt_offset++) & 0x07) << 4) | ((r >> 8) & 0x0f));
182  tpasswd[1] = r & 0xff;
183  tpasswd[2] = inlen; /* length of the password string */
184 
185  md5_ctx = fr_md5_ctx_alloc_from_list();
186  md5_ctx_old = fr_md5_ctx_alloc_from_list();
187 
188  fr_md5_update(md5_ctx, (uint8_t const *) packet_ctx->common->secret, packet_ctx->common->secret_length);
189  fr_md5_ctx_copy(md5_ctx_old, md5_ctx);
190 
192  fr_md5_update(md5_ctx, &tpasswd[0], 2);
193 
194  /*
195  * Do various hashing, and XOR the length+password with
196  * the output of the hash blocks.
197  */
198  for (n = 0; n < encrypted_len; n += AUTH_PASS_LEN) {
199  size_t block_len;
200 
201  if (n > 0) {
202  fr_md5_ctx_copy(md5_ctx, md5_ctx_old);
203  fr_md5_update(md5_ctx, tpasswd + 2 + n - AUTH_PASS_LEN, AUTH_PASS_LEN);
204  }
205  fr_md5_final(digest, md5_ctx);
206 
207  block_len = encrypted_len - n;
208  if (block_len > AUTH_PASS_LEN) block_len = AUTH_PASS_LEN;
209 
210  for (i = 0; i < block_len; i++) tpasswd[i + 2 + n] ^= digest[i];
211  }
212 
213  fr_md5_ctx_free_from_list(&md5_ctx);
214  fr_md5_ctx_free_from_list(&md5_ctx_old);
215 
216  FR_DBUFF_IN_MEMCPY_RETURN(&work_dbuff, tpasswd, output_len);
217 
218  return fr_dbuff_set(dbuff, &work_dbuff);
219 }
220 
221 /*
222  * Encode the contents of an attribute of type TLV.
223  */
225  fr_da_stack_t *da_stack, unsigned int depth,
226  fr_dcursor_t *cursor, void *encode_ctx)
227 {
228  ssize_t slen;
229  fr_pair_t const *vp = fr_dcursor_current(cursor);
230  fr_dict_attr_t const *da = da_stack->da[depth];
231  fr_dbuff_t work_dbuff = FR_DBUFF_MAX(dbuff, RADIUS_MAX_STRING_LENGTH);
232 
233  for (;;) {
234  FR_PROTO_STACK_PRINT(da_stack, depth);
235 
236  /*
237  * This attribute carries sub-TLVs. The sub-TLVs
238  * can only carry a total of 253 bytes of data.
239  */
240 
241  /*
242  * Determine the nested type and call the appropriate encoder
243  */
244  if (!da_stack->da[depth + 1]) {
245  fr_dcursor_t child_cursor;
246 
247  if (vp->da != da_stack->da[depth]) {
248  fr_strerror_printf("%s: Can't encode empty TLV", __FUNCTION__);
249  return 0;
250  }
251 
252  fr_pair_dcursor_child_iter_init(&child_cursor, &vp->vp_group, cursor);
253  vp = fr_dcursor_current(&child_cursor);
254  fr_proto_da_stack_build(da_stack, vp->da);
255 
256  /*
257  * Call ourselves recursively to encode children.
258  */
259  slen = encode_tlv(&work_dbuff, da_stack, depth, &child_cursor, encode_ctx);
260  if (slen < 0) return slen;
261 
262  vp = fr_dcursor_next(cursor);
263  fr_proto_da_stack_build(da_stack, vp ? vp->da : NULL);
264 
265  } else {
266  slen = encode_child(&work_dbuff, da_stack, depth + 1, cursor, encode_ctx);
267  }
268  if (slen < 0) return slen;
269 
270  /*
271  * If nothing updated the attribute, stop
272  */
273  if (!fr_dcursor_current(cursor) || (vp == fr_dcursor_current(cursor))) break;
274 
275  /*
276  * We can encode multiple sub TLVs, if after
277  * rebuilding the TLV Stack, the attribute
278  * at this depth is the same.
279  */
280  if ((da != da_stack->da[depth]) || (da_stack->depth < da->depth)) break;
281  vp = fr_dcursor_current(cursor);
282  }
283 
284  return fr_dbuff_set(dbuff, &work_dbuff);
285 }
286 
287 static ssize_t encode_pairs(fr_dbuff_t *dbuff, fr_pair_list_t const *vps, void *encode_ctx)
288 {
289  ssize_t slen;
290  fr_pair_t const *vp;
291  fr_dcursor_t cursor;
292 
293  /*
294  * Note that we skip tags inside of tags!
295  */
297  while ((vp = fr_dcursor_current(&cursor))) {
298  PAIR_VERIFY(vp);
299 
300  /*
301  * Encode an individual VP
302  */
303  slen = fr_radius_encode_pair(dbuff, &cursor, encode_ctx);
304  if (slen < 0) return slen;
305  }
306 
307  return fr_dbuff_used(dbuff);
308 }
309 
310 
311 /** Encodes the data portion of an attribute
312  *
313  * @return
314  * > 0, Length of the data portion.
315  * = 0, we could not encode anything, skip this attribute (and don't encode the header)
316  * unless it's one of a list of exceptions.
317  * < 0, How many additional bytes we'd need as a negative integer.
318  * PAIR_ENCODE_FATAL_ERROR - Abort encoding the packet.
319  */
321  fr_da_stack_t *da_stack, unsigned int depth,
322  fr_dcursor_t *cursor, void *encode_ctx)
323 {
324  ssize_t slen;
325  size_t len;
326  fr_pair_t const *vp = fr_dcursor_current(cursor);
327  fr_dict_attr_t const *da = da_stack->da[depth];
328  fr_radius_encode_ctx_t *packet_ctx = encode_ctx;
329  fr_dbuff_t work_dbuff = FR_DBUFF(dbuff);
330  fr_dbuff_t value_dbuff;
331  fr_dbuff_marker_t value_start, src, dest;
332  bool encrypted = false;
333 
334  PAIR_VERIFY(vp);
335  FR_PROTO_STACK_PRINT(da_stack, depth);
336 
337  /*
338  * TLVs are just another type of value.
339  */
340  if (da->type == FR_TYPE_TLV) return encode_tlv(dbuff, da_stack, depth, cursor, encode_ctx);
341 
342  if (da->type == FR_TYPE_GROUP) return fr_pair_ref_to_network(dbuff, da_stack, depth, cursor);
343 
344  /*
345  * Catch errors early on.
346  */
347  if (flag_encrypted(&vp->da->flags) && !packet_ctx) {
348  fr_strerror_const("Asked to encrypt attribute, but no packet context provided");
350  }
351 
352  /*
353  * This has special requirements.
354  */
355  if ((vp->vp_type == FR_TYPE_STRUCT) || (da->type == FR_TYPE_STRUCT)) {
356  slen = fr_struct_to_network(&work_dbuff, da_stack, depth, cursor, encode_ctx, encode_value, encode_child);
357  if (slen <= 0) return slen;
358 
359  vp = fr_dcursor_current(cursor);
360  fr_proto_da_stack_build(da_stack, vp ? vp->da : NULL);
361  return fr_dbuff_set(dbuff, &work_dbuff);
362  }
363 
364  /*
365  * If it's not a TLV, it should be a value type RFC
366  * attribute make sure that it is.
367  */
368  if (da_stack->da[depth + 1] != NULL) {
369  fr_strerror_printf("%s: Encoding value but not at top of stack", __FUNCTION__);
371  }
372 
373  if (vp->da != da) {
374  fr_strerror_printf("%s: Top of stack does not match vp->da", __FUNCTION__);
376  }
377 
378  if (fr_type_is_structural(da->type)) {
379  fr_strerror_printf("%s: Called with structural type %s", __FUNCTION__,
380  fr_type_to_str(da_stack->da[depth]->type));
382  }
383 
384  /*
385  * Write tag byte
386  *
387  * The Tag field is one octet in length and is intended to provide a
388  * means of grouping attributes in the same packet which refer to the
389  * same tunnel. If the value of the Tag field is greater than 0x00
390  * and less than or equal to 0x1F, it SHOULD be interpreted as
391  * indicating which tunnel (of several alternatives) this attribute
392  * pertains. If the Tag field is greater than 0x1F, it SHOULD be
393  * interpreted as the first byte of the following String field.
394  *
395  * If the first byte of the string value looks like a
396  * tag, then we always encode a tag byte, even one that
397  * is zero.
398  */
399  if ((vp->vp_type == FR_TYPE_STRING) && flag_has_tag(&vp->da->flags)) {
400  if (packet_ctx->tag) {
401  FR_DBUFF_IN_RETURN(&work_dbuff, (uint8_t)packet_ctx->tag);
402  } else if (TAG_VALID(vp->vp_strvalue[0])) {
403  FR_DBUFF_IN_RETURN(&work_dbuff, (uint8_t)0x00);
404  }
405  }
406 
407  /*
408  * Starting here is a value that may require encryption.
409  */
410  value_dbuff = FR_DBUFF(&work_dbuff);
411  fr_dbuff_marker(&value_start, &value_dbuff);
412  fr_dbuff_marker(&src, &value_dbuff);
413  fr_dbuff_marker(&dest, &value_dbuff);
414 
415  switch (vp->vp_type) {
416  /*
417  * IPv4 addresses are normal, but IPv6 addresses are special to RADIUS.
418  */
420  if (vp->vp_ip.af == AF_INET) goto encode;
421  FALL_THROUGH;
422 
423  /*
424  * Common encoder might add scope byte, which we don't want.
425  */
426  case FR_TYPE_IPV6_ADDR:
427  FR_DBUFF_IN_MEMCPY_RETURN(&value_dbuff, vp->vp_ipv6addr, sizeof(vp->vp_ipv6addr));
428  break;
429 
431  if (vp->vp_ip.af == AF_INET) goto ipv4_prefix;
432  FALL_THROUGH;
433 
434  /*
435  * Common encoder doesn't add reserved byte
436  */
437  case FR_TYPE_IPV6_PREFIX:
438  len = fr_bytes_from_bits(vp->vp_ip.prefix);
439  FR_DBUFF_IN_BYTES_RETURN(&value_dbuff, 0x00, vp->vp_ip.prefix);
440  /* Only copy the minimum number of address bytes required */
441  FR_DBUFF_IN_MEMCPY_RETURN(&value_dbuff, (uint8_t const *)vp->vp_ipv6addr, len);
442  break;
443 
444  /*
445  * Common encoder doesn't add reserved byte
446  */
447  case FR_TYPE_IPV4_PREFIX:
448  ipv4_prefix:
449  FR_DBUFF_IN_BYTES_RETURN(&value_dbuff, 0x00, vp->vp_ip.prefix);
450  FR_DBUFF_IN_MEMCPY_RETURN(&value_dbuff, (uint8_t const *)&vp->vp_ipv4addr, sizeof(vp->vp_ipv4addr));
451  break;
452 
453  /*
454  * Special handling for "abinary". Otherwise, fall
455  * through to using the common encoder.
456  */
457  case FR_TYPE_STRING:
458  if (flag_abinary(&da->flags)) {
459  slen = fr_radius_encode_abinary(vp, &value_dbuff);
460  if (slen <= 0) return slen;
461  break;
462  }
463  FALL_THROUGH;
464 
465  case FR_TYPE_OCTETS:
466 
467  /*
468  * Simple data types use the common encoder.
469  */
470  default:
471  encode:
472  slen = fr_value_box_to_network(&value_dbuff, &vp->data);
473  if (slen < 0) return slen;
474  break;
475  }
476 
477  /*
478  * No data: don't encode the value. The type and length should still
479  * be written.
480  */
481  if (fr_dbuff_used(&value_dbuff) == 0) {
482  vp = fr_dcursor_next(cursor);
483  fr_proto_da_stack_build(da_stack, vp ? vp->da : NULL);
484  return 0;
485  }
486 
487  /*
488  * Encrypt the various password styles
489  *
490  * Attributes with encrypted values MUST be less than
491  * 128 bytes long.
492  */
493  if (flag_encrypted(&da->flags)) switch (vp->da->flags.subtype) {
495  /*
496  * Encode the password in place
497  */
498  slen = encode_password(&work_dbuff, &value_start, fr_dbuff_used(&value_dbuff), packet_ctx);
499  if (slen < 0) return slen;
500  encrypted = true;
501  break;
502 
505  if (packet_ctx->disallow_tunnel_passwords) {
506  fr_strerror_const("Attributes with 'encrypt=2' set cannot go into this packet.");
507  return 0;
508  }
509 
510  /*
511  * Always encode the tag even if it's zero.
512  *
513  * The Tunnel-Password uses 2 salt fields which
514  * MAY have any value. As a result, we always
515  * encode a tag. If we would omit the tag, then
516  * perhaps one of the salt fields could be
517  * mistaken for the tag.
518  */
519  if (flag_has_tag(&vp->da->flags)) fr_dbuff_advance(&work_dbuff, 1);
520 
521  slen = encode_tunnel_password(&work_dbuff, &value_start, fr_dbuff_used(&value_dbuff), packet_ctx);
522  if (slen < 0) {
523  fr_strerror_printf("%s too long", vp->da->name);
524  return slen - flag_has_tag(&vp->da->flags);
525  }
526 
527  /*
528  * Do this after so we don't mess up the input
529  * value.
530  */
531  if (flag_has_tag(&vp->da->flags)) {
532  fr_dbuff_set_to_start(&value_start);
533  fr_dbuff_in(&value_start, (uint8_t) 0x00);
534  }
535  encrypted = true;
536  break;
537 
538  /*
539  * The code above ensures that this attribute
540  * always fits.
541  */
543  /*
544  * @todo radius decoding also uses fr_radius_ascend_secret() (Vernam cipher
545  * is its own inverse). As part of converting decode, make sure the caller
546  * there can pass a marker so we can use it here, too.
547  */
548  slen = fr_radius_ascend_secret(&work_dbuff, fr_dbuff_current(&value_start), fr_dbuff_used(&value_dbuff),
549  packet_ctx->common->secret, packet_ctx->request_authenticator);
550  if (slen < 0) return slen;
551  encrypted = true;
552  break;
553  }
554 
555  if (!encrypted) {
556  fr_dbuff_set(&work_dbuff, &value_dbuff);
557  fr_dbuff_set(&value_start, fr_dbuff_start(&value_dbuff));
558  }
559 
560  /*
561  * High byte of 32bit integers gets set to the tag
562  * value.
563  *
564  * The Tag field is one octet in length and is intended to provide a
565  * means of grouping attributes in the same packet which refer to the
566  * same tunnel. Valid values for this field are 0x01 through 0x1F,
567  * inclusive. If the Tag field is unused, it MUST be zero (0x00).
568  */
569  if ((vp->vp_type == FR_TYPE_UINT32) && flag_has_tag(&vp->da->flags)) {
570  uint8_t msb = 0;
571  /*
572  * Only 24bit integers are allowed here
573  */
574  fr_dbuff_set(&src, &value_start);
575  (void) fr_dbuff_out(&msb, &src);
576  if (msb != 0) {
577  fr_strerror_const("Integer overflow for tagged uint32 attribute");
578  return 0;
579  }
580  fr_dbuff_set(&dest, &value_start);
581  fr_dbuff_in(&dest, packet_ctx->tag);
582  }
583 
584  FR_PROTO_HEX_DUMP(fr_dbuff_start(&work_dbuff), fr_dbuff_used(&work_dbuff), "value %s",
585  fr_type_to_str(vp->vp_type));
586 
587  /*
588  * Rebuilds the TLV stack for encoding the next attribute
589  */
590  vp = fr_dcursor_next(cursor);
591  fr_proto_da_stack_build(da_stack, vp ? vp->da : NULL);
592 
593  return fr_dbuff_set(dbuff, &work_dbuff);
594 }
595 
596 /** Breaks down large data into pieces, each with a header
597  *
598  * @param[out] data we're fragmenting.
599  * @param[in] data_len the amount of data in the dbuff that makes up the value we're
600  * splitting.
601  * @param[in,out] hdr marker that points at said header
602  * @param[in] hdr_len length of the headers that will be added
603  * @param[in] flag_offset offset within header of a flag byte whose MSB is set for all
604  * but the last piece.
605  * @param[in] vsa_offset if non-zero, the offset of a length field in a (sub?)-header
606  * of size 3 that also needs to be adjusted to include the number
607  * of bytes of data in the piece
608  * @return
609  * - <0 the number of bytes we would have needed to create
610  * space for another attribute header in the buffer.
611  * - 0 data was not modified.
612  * - >0 the number additional bytes we used inserting extra
613  * headers.
614  */
615 static ssize_t attr_fragment(fr_dbuff_t *data, size_t data_len, fr_dbuff_marker_t *hdr, size_t hdr_len,
616  int flag_offset, int vsa_offset)
617 {
618  unsigned int num_fragments, i = 0;
619  size_t max_frag_data = UINT8_MAX - hdr_len;
620  fr_dbuff_t frag_data = FR_DBUFF_ABS(hdr);
621  fr_dbuff_marker_t frag_hdr, frag_hdr_p;
622 
623  if (unlikely(!data_len)) return 0; /* Shouldn't have been called */
624 
625  num_fragments = ROUND_UP_DIV(data_len, max_frag_data);
626  if (num_fragments == 1) return 0; /* Nothing to do */
627 
628  fr_dbuff_marker(&frag_hdr, &frag_data);
629  fr_dbuff_marker(&frag_hdr_p, &frag_data);
630 
631  fr_dbuff_advance(&frag_data, hdr_len);
632 
633  FR_PROTO_HEX_DUMP(fr_dbuff_current(hdr), hdr_len + data_len, "attr_fragment in");
634  for (;;) {
635  bool last = (i + 1) == num_fragments;
636  uint8_t frag_len;
637 
638  /*
639  * How long is this fragment?
640  */
641  if (last) {
642  frag_len = (data_len - (max_frag_data * (num_fragments - 1)));
643  } else {
644  frag_len = max_frag_data;
645  }
646 
647  /*
648  * Update the "outer" header to reflect the actual
649  * length of the fragment
650  */
651  fr_dbuff_set(&frag_hdr_p, &frag_hdr);
652  fr_dbuff_advance(&frag_hdr_p, 1);
653  fr_dbuff_in(&frag_hdr_p, (uint8_t)(hdr_len + frag_len));
654 
655  /*
656  * Update the "inner" header. The length here is
657  * the inner VSA header length (3) + the fragment
658  * length.
659  */
660  if (vsa_offset) {
661  fr_dbuff_set(&frag_hdr_p, fr_dbuff_current(&frag_hdr) + vsa_offset);
662  fr_dbuff_in(&frag_hdr_p, (uint8_t)(3 + frag_len));
663  }
664 
665  /*
666  * Just over-ride the flag field. Nothing else
667  * uses it.
668  */
669  if (flag_offset) {
670  fr_dbuff_set(&frag_hdr_p, fr_dbuff_current(&frag_hdr) + flag_offset);
671  fr_dbuff_in(&frag_hdr_p, (uint8_t)(!last << 7));
672  }
673 
674  FR_PROTO_HEX_DUMP(fr_dbuff_current(hdr), frag_len + hdr_len,
675  "attr_fragment fragment %u/%u", i + 1, num_fragments);
676 
677  fr_dbuff_advance(&frag_data, frag_len); /* Go to the start of the next fragment */
678  if (last) break;
679 
680  /*
681  * There's still trailing data after this
682  * fragment. Move the trailing data to *past*
683  * the next header. And after there's room, copy
684  * the header over.
685  *
686  * This process leaves the next header in place,
687  * ready for the next iteration of the loop.
688  *
689  * Yes, moving things multiple times is less than
690  * efficient. Oh well. it's ~1K memmoved()
691  * maybe 4 times. We are nowhere near the CPU /
692  * electrical requirements of Bitcoin.
693  */
694  i++;
695 
696  fr_dbuff_set(&frag_hdr, &frag_data); /* Remember where the header should be */
697  fr_dbuff_advance(&frag_data, hdr_len); /* Advance past the header */
698 
699  /*
700  * Shift remaining data by hdr_len.
701  */
702  FR_DBUFF_IN_MEMCPY_RETURN(&FR_DBUFF(&frag_data), &frag_hdr, data_len - (i * max_frag_data));
703  fr_dbuff_in_memcpy(&FR_DBUFF(&frag_hdr), hdr, hdr_len); /* Copy the old header over */
704  }
705 
706  return fr_dbuff_set(data, &frag_data);
707 }
708 
709 /** Encode an "extended" attribute
710  *
711  */
713  fr_da_stack_t *da_stack, NDEBUG_UNUSED unsigned int depth,
714  fr_dcursor_t *cursor, void *encode_ctx)
715 {
716  ssize_t slen;
717  uint8_t hlen;
718  size_t vendor_hdr;
719  bool extra;
720  int my_depth;
721  fr_dict_attr_t const *da;
722  fr_dbuff_marker_t hdr, length_field;
723  fr_pair_t const *vp = fr_dcursor_current(cursor);
724  fr_dbuff_t work_dbuff;
725 
726  PAIR_VERIFY(vp);
727  FR_PROTO_STACK_PRINT(da_stack, depth);
728 
729  extra = flag_long_extended(&da_stack->da[0]->flags);
730 
731  /*
732  * The data used here can be more than 255 bytes, but only for the
733  * "long" extended type.
734  */
735  if (extra) {
736  work_dbuff = FR_DBUFF_BIND_CURRENT(dbuff);
737  } else {
738  work_dbuff = FR_DBUFF_MAX_BIND_CURRENT(dbuff, UINT8_MAX);
739  }
740  fr_dbuff_marker(&hdr, &work_dbuff);
741 
742  /*
743  * Encode the header for "short" or "long" attributes
744  */
745  hlen = 3 + extra;
746  FR_DBUFF_IN_BYTES_RETURN(&work_dbuff, (uint8_t)da_stack->da[0]->attr);
747  fr_dbuff_marker(&length_field, &work_dbuff);
748  FR_DBUFF_IN_BYTES_RETURN(&work_dbuff, hlen); /* this gets overwritten later*/
749 
750  /*
751  * Encode which extended attribute it is.
752  */
753  FR_DBUFF_IN_BYTES_RETURN(&work_dbuff, (uint8_t)da_stack->da[1]->attr);
754 
755  if (extra) FR_DBUFF_IN_BYTES_RETURN(&work_dbuff, 0x00); /* flags start off at zero */
756 
757  FR_PROTO_STACK_PRINT(da_stack, depth);
758 
759  /*
760  * Handle VSA as "VENDOR + attr"
761  */
762  if (da_stack->da[1]->type == FR_TYPE_VSA) {
763  fr_assert(da_stack->da[2]);
764  fr_assert(da_stack->da[2]->type == FR_TYPE_VENDOR);
765 
766  FR_DBUFF_IN_RETURN(&work_dbuff, (uint32_t) da_stack->da[2]->attr);
767 
768  fr_assert(da_stack->da[3]);
769 
770  FR_DBUFF_IN_BYTES_RETURN(&work_dbuff, (uint8_t)da_stack->da[3]->attr);
771 
772  hlen += 5;
773  vendor_hdr = 5;
774 
775  FR_PROTO_STACK_PRINT(da_stack, depth);
776  FR_PROTO_HEX_DUMP(fr_dbuff_current(&hdr), hlen, "header extended vendor specific");
777 
778  my_depth = 3;
779  } else {
780  vendor_hdr = 0;
781  FR_PROTO_HEX_DUMP(fr_dbuff_current(&hdr), hlen, "header extended");
782 
783  my_depth = 1;
784  }
785 
786  /*
787  * We're at the point where we need to encode something.
788  */
789  da = da_stack->da[my_depth];
790  fr_assert(vp->da == da);
791 
792  if (da->type != FR_TYPE_STRUCT) {
793  slen = encode_value(&work_dbuff, da_stack, my_depth, cursor, encode_ctx);
794 
795  } else {
796  slen = fr_struct_to_network(&work_dbuff, da_stack, my_depth, cursor, encode_ctx, encode_value, encode_child);
797  }
798  if (slen <= 0) return slen;
799 
800  /*
801  * There may be more than 255 octets of data encoded in
802  * the attribute. If so, move the data up in the packet,
803  * and copy the existing header over. Set the "M" flag ONLY
804  * after copying the rest of the data.
805  *
806  * Note that we add "vendor_hdr" to the length of the
807  * encoded data. That 5 octet field is logically part of
808  * the data, and not part of the header.
809  */
810  if (slen > (UINT8_MAX - hlen)) {
811  slen = attr_fragment(&work_dbuff, (size_t)vendor_hdr + slen, &hdr, 4, 3, 0);
812  if (slen <= 0) return slen;
813 
814  return fr_dbuff_set(dbuff, &work_dbuff);
815  }
816 
817  fr_dbuff_in_bytes(&length_field, (uint8_t) fr_dbuff_used(&work_dbuff));
818  FR_PROTO_HEX_DUMP(fr_dbuff_current(&hdr), hlen, "header extended");
819 
820  return fr_dbuff_set(dbuff, &work_dbuff);
821 }
822 
823 /*
824  * The encode_extended() function expects to see the TLV or
825  * STRUCT inside of the extended attribute, in which case it
826  * creates the attribute header and calls encode_value() for the
827  * leaf type, or child TLV / struct.
828  *
829  * If we see VSA or VENDOR, then we recurse past that to a child
830  * which is either a leaf, or a TLV, or a STRUCT.
831  */
833  fr_da_stack_t *da_stack, unsigned int depth,
834  fr_dcursor_t *cursor, void *encode_ctx)
835 {
836  ssize_t slen;
837  fr_pair_t *parent, *vp;
838  fr_dcursor_t child_cursor;
839  fr_dbuff_t work_dbuff = FR_DBUFF(dbuff);
840 
841  parent = fr_dcursor_current(cursor);
843 
844  (void) fr_pair_dcursor_child_iter_init(&child_cursor, &parent->vp_group, cursor);
845 
846  FR_PROTO_STACK_PRINT(da_stack, depth);
847 
848  while ((vp = fr_dcursor_current(&child_cursor)) != NULL) {
849  if ((vp->vp_type == FR_TYPE_VSA) || (vp->vp_type == FR_TYPE_VENDOR)) {
850  slen = encode_extended_nested(&work_dbuff, da_stack, depth + 1, &child_cursor, encode_ctx);
851 
852  } else {
853  fr_proto_da_stack_build(da_stack, vp->da);
854  slen = encode_extended(&work_dbuff, da_stack, depth, &child_cursor, encode_ctx);
855  if (slen < 0) return slen;
856  }
857 
858  if (slen < 0) return slen;
859  }
860 
861  vp = fr_dcursor_next(cursor);
862 
863  fr_proto_da_stack_build(da_stack, vp ? vp->da : NULL);
864 
865  return fr_dbuff_set(dbuff, &work_dbuff);
866 }
867 
868 
869 /** Encode an RFC format attribute, with the "concat" flag set
870  *
871  * If there isn't enough freespace in the packet, the data is
872  * truncated to fit.
873  *
874  * The attribute is split on 253 byte boundaries, with a header
875  * prepended to each chunk.
876  */
878  fr_da_stack_t *da_stack, unsigned int depth,
879  fr_dcursor_t *cursor, UNUSED void *encode_ctx)
880 {
881  uint8_t const *p;
882  size_t data_len;
883  fr_pair_t const *vp = fr_dcursor_current(cursor);
884  fr_dbuff_t work_dbuff = FR_DBUFF(dbuff);
885  fr_dbuff_marker_t hdr;
886 
887  FR_PROTO_STACK_PRINT(da_stack, depth);
888 
889  p = vp->vp_octets;
890  data_len = vp->vp_length;
891  fr_dbuff_marker(&hdr, &work_dbuff);
892 
893  while (data_len > 0) {
894  size_t frag_len = (data_len > RADIUS_MAX_STRING_LENGTH) ? RADIUS_MAX_STRING_LENGTH : data_len;
895 
896  fr_dbuff_set(&hdr, &work_dbuff);
897  FR_DBUFF_IN_BYTES_RETURN(&work_dbuff, (uint8_t) da_stack->da[depth]->attr, 0x00);
898 
899  FR_DBUFF_IN_MEMCPY_RETURN(&work_dbuff, p, frag_len);
900 
901  fr_dbuff_advance(&hdr, 1);
902  fr_dbuff_in(&hdr, (uint8_t) (2 + frag_len));
903 
904  FR_PROTO_HEX_DUMP(fr_dbuff_current(&hdr) - 1, 2 + frag_len, "encode_concat fragment");
905 
906  p += frag_len;
907  data_len -= frag_len;
908  }
909 
910  vp = fr_dcursor_next(cursor);
911 
912  /*
913  * @fixme: attributes with 'concat' MUST of type
914  * 'octets', and therefore CANNOT have any TLV data in them.
915  */
916  fr_proto_da_stack_build(da_stack, vp ? vp->da : NULL);
917 
918  return fr_dbuff_set(dbuff, &work_dbuff);
919 }
920 
921 /** Encode an RFC format attribute.
922  *
923  * This could be a standard attribute, or a TLV data type.
924  * If it's a standard attribute, then vp->da->attr == attribute.
925  * Otherwise, attribute may be something else.
926  */
928  fr_da_stack_t *da_stack, unsigned int depth,
929  fr_dcursor_t *cursor, void *encode_ctx)
930 {
931  ssize_t slen;
932  uint8_t hlen;
933  fr_dbuff_marker_t hdr;
934  fr_dbuff_t work_dbuff = FR_DBUFF_MAX(dbuff, UINT8_MAX);
935 
936  FR_PROTO_STACK_PRINT(da_stack, depth);
937 
938  fr_assert(da_stack->da[depth] != NULL);
939 
940  fr_dbuff_marker(&hdr, &work_dbuff);
941 
942  hlen = 2;
943  FR_DBUFF_IN_BYTES_RETURN(&work_dbuff, (uint8_t)da_stack->da[depth]->attr, hlen);
944 
945  slen = encode_value(&work_dbuff, da_stack, depth, cursor, encode_ctx);
946  if (slen <= 0) return slen;
947 
948  fr_dbuff_advance(&hdr, 1);
949  fr_dbuff_in_bytes(&hdr, (uint8_t)(hlen + slen));
950 
951  FR_PROTO_HEX_DUMP(fr_dbuff_start(&work_dbuff), 2, "header rfc");
952 
953  return fr_dbuff_set(dbuff, &work_dbuff);
954 }
955 
956 
957 /** Encode one full Vendor-Specific + Vendor-ID + Vendor-Attr + Vendor-Length + ...
958  */
960  fr_da_stack_t *da_stack, unsigned int depth,
961  fr_dcursor_t *cursor, void *encode_ctx)
962 {
963  ssize_t slen;
964  size_t hdr_len;
965  fr_dbuff_marker_t hdr, length_field, vsa_length_field;
966  fr_dict_attr_t const *da, *dv;
967  fr_dbuff_t work_dbuff;
968 
969  FR_PROTO_STACK_PRINT(da_stack, depth);
970 
971  dv = da_stack->da[depth++];
972 
973  if (dv->type != FR_TYPE_VENDOR) {
974  fr_strerror_const("Expected Vendor");
976  }
977 
978  /*
979  * Now we encode one vendor attribute.
980  */
981  da = da_stack->da[depth];
982  fr_assert(da != NULL);
983 
984  /*
985  * Most VSAs get limited to the one attribute. Only refs
986  * (e.g. DHCPv4, DHCpv6) can get fragmented.
987  */
988  if (da->type != FR_TYPE_GROUP) {
989  work_dbuff = FR_DBUFF_MAX(dbuff, UINT8_MAX);
990  } else {
991  work_dbuff = FR_DBUFF(dbuff);
992  }
993 
994  fr_dbuff_marker(&hdr, &work_dbuff);
995 
996  /*
997  * Build the Vendor-Specific header
998  */
999  FR_DBUFF_IN_BYTES_RETURN(&work_dbuff, FR_VENDOR_SPECIFIC);
1000 
1001  fr_dbuff_marker(&length_field, &work_dbuff);
1002  FR_DBUFF_IN_BYTES_RETURN(&work_dbuff, 0);
1003 
1004  FR_DBUFF_IN_RETURN(&work_dbuff, (uint32_t)dv->attr); /* Copy in the 32bit vendor ID */
1005 
1006 
1007  hdr_len = dv->flags.type_size + dv->flags.length;
1008 
1009  /*
1010  * Vendors use different widths for their
1011  * attribute number fields.
1012  */
1013  switch (dv->flags.type_size) {
1014  default:
1015  fr_strerror_printf("%s: Internal sanity check failed, type %u", __FUNCTION__, (unsigned) dv->flags.type_size);
1016  return PAIR_ENCODE_FATAL_ERROR;
1017 
1018  case 4:
1019  fr_dbuff_in(&work_dbuff, (uint32_t)da->attr);
1020  break;
1021 
1022  case 2:
1023  fr_dbuff_in(&work_dbuff, (uint16_t)da->attr);
1024  break;
1025 
1026  case 1:
1027  fr_dbuff_in(&work_dbuff, (uint8_t)da->attr);
1028  break;
1029  }
1030 
1031  /*
1032  * The length fields will get over-written later.
1033  */
1034  switch (dv->flags.length) {
1035  default:
1036  fr_strerror_printf("%s: Internal sanity check failed, length %u", __FUNCTION__, (unsigned) dv->flags.length);
1037  return PAIR_ENCODE_FATAL_ERROR;
1038 
1039  case 0:
1040  break;
1041 
1042  case 2:
1043  fr_dbuff_in_bytes(&work_dbuff, 0);
1044  FALL_THROUGH;
1045 
1046  case 1:
1047  /*
1048  * Length fields are set to zero, because they
1049  * will get over-ridden later.
1050  */
1051  fr_dbuff_marker(&vsa_length_field, &work_dbuff);
1052  fr_dbuff_in_bytes(&work_dbuff, 0);
1053  break;
1054  }
1055 
1056  slen = encode_value(&work_dbuff, da_stack, depth, cursor, encode_ctx);
1057  if (slen <= 0) return slen;
1058 
1059  /*
1060  * There may be more than 253 octets of data encoded in
1061  * the attribute. If so, move the data up in the packet,
1062  * and copy the existing header over. Set the "C" flag
1063  * ONLY after copying the rest of the data.
1064  *
1065  * Note that we do NOT check 'slen' here, as it's only
1066  * the size of the sub-sub attribute, and doesn't include
1067  * the RADIUS attribute header, or Vendor-ID.
1068  */
1069  if (fr_dbuff_used(&work_dbuff) > UINT8_MAX) {
1070  size_t length_offset = 0;
1071 
1072  if (dv->flags.length) length_offset = 6 + hdr_len - 1;
1073 
1074  slen = attr_fragment(&work_dbuff, (size_t)slen, &hdr, 6 + hdr_len, 0, length_offset);
1075  if (slen <= 0) return slen;
1076  } else {
1077  if (dv->flags.length) {
1078  fr_dbuff_in(&vsa_length_field, (uint8_t)(hdr_len + slen));
1079  }
1080 
1081  fr_dbuff_in(&length_field, (uint8_t) fr_dbuff_used(&work_dbuff));
1082  }
1083 
1084  FR_PROTO_HEX_DUMP(fr_dbuff_current(&hdr), 6 + hdr_len, "header vsa");
1085 
1086  return fr_dbuff_set(dbuff, &work_dbuff);
1087 }
1088 
1089 /** Encode a WiMAX attribute
1090  *
1091  */
1093  fr_da_stack_t *da_stack, unsigned int depth,
1094  fr_dcursor_t *cursor, void *encode_ctx)
1095 {
1096  ssize_t slen;
1097  fr_dbuff_t work_dbuff = FR_DBUFF(dbuff);
1098  fr_dbuff_marker_t hdr, length_field, vsa_length_field;
1099  fr_dict_attr_t const *dv;
1100  fr_pair_t const *vp = fr_dcursor_current(cursor);
1101 
1102  fr_dbuff_marker(&hdr, &work_dbuff);
1103 
1104  PAIR_VERIFY(vp);
1105  FR_PROTO_STACK_PRINT(da_stack, depth);
1106 
1107  dv = da_stack->da[depth++];
1108 
1109  if (dv->type != FR_TYPE_VENDOR) {
1110  fr_strerror_const("Expected Vendor");
1111  return PAIR_ENCODE_FATAL_ERROR;
1112  }
1113 
1114  FR_PROTO_STACK_PRINT(da_stack, depth);
1115 
1116  /*
1117  * Build the Vendor-Specific header
1118  */
1119  FR_DBUFF_IN_BYTES_RETURN(&work_dbuff, FR_VENDOR_SPECIFIC);
1120  fr_dbuff_marker(&length_field, &work_dbuff);
1121  FR_DBUFF_IN_BYTES_RETURN(&work_dbuff, 0x09);
1122 
1123  FR_DBUFF_IN_RETURN(&work_dbuff, (uint32_t) dv->attr);
1124 
1125  /*
1126  * Encode the first attribute
1127  */
1128  FR_DBUFF_IN_BYTES_RETURN(&work_dbuff, (uint8_t)da_stack->da[depth]->attr);
1129 
1130  fr_dbuff_marker(&vsa_length_field, &work_dbuff);
1131  FR_DBUFF_IN_BYTES_RETURN(&work_dbuff, 0x03, 0x00); /* length + continuation, both may be overwritten later */
1132 
1133  /*
1134  * We don't bound the size of work_dbuff; it can use more than UINT8_MAX bytes
1135  * because of the "continuation" byte.
1136  */
1137  slen = encode_value(&work_dbuff, da_stack, depth, cursor, encode_ctx);
1138  if (slen <= 0) return slen;
1139 
1140  /*
1141  * There may be more than 253 octets of data encoded in
1142  * the attribute. If so, move the data up in the packet,
1143  * and copy the existing header over. Set the "C" flag
1144  * ONLY after copying the rest of the data.
1145  *
1146  * Note that we do NOT check 'slen' here, as it's only
1147  * the size of the sub-sub attribute, and doesn't include
1148  * the RADIUS attribute header, or Vendor-ID.
1149  */
1150  if (fr_dbuff_used(&work_dbuff) > UINT8_MAX) {
1151  slen = attr_fragment(&work_dbuff, (size_t)slen, &hdr, 9, 8, 7);
1152  if (slen <= 0) return slen;
1153 
1154  return fr_dbuff_set(dbuff, &work_dbuff);
1155  }
1156 
1157  fr_dbuff_in_bytes(&vsa_length_field, (uint8_t) (fr_dbuff_used(&work_dbuff) - 6));
1158  fr_dbuff_in_bytes(&length_field, (uint8_t) fr_dbuff_used(&work_dbuff));
1159 
1160  FR_PROTO_HEX_DUMP(fr_dbuff_current(&hdr), 9, "header wimax");
1161 
1162  return fr_dbuff_set(dbuff, &work_dbuff);
1163 }
1164 
1166  fr_da_stack_t *da_stack, unsigned int depth,
1167  fr_dcursor_t *cursor, void *encode_ctx)
1168 {
1169  fr_dict_attr_t const *da = da_stack->da[depth];
1170  ssize_t slen;
1171  fr_pair_t *vp;
1172  fr_dict_vendor_t const *dv;
1173  fr_dcursor_t child_cursor;
1174  fr_dbuff_t work_dbuff;
1175 
1176  FR_PROTO_STACK_PRINT(da_stack, depth);
1177 
1178  if (da->type != FR_TYPE_VENDOR) {
1179  fr_strerror_printf("%s: Expected type \"vendor\" got \"%s\"", __FUNCTION__,
1180  fr_type_to_str(da->type));
1181  return PAIR_ENCODE_FATAL_ERROR;
1182  }
1183 
1184  dv = fr_dict_vendor_by_da(da_stack->da[depth]);
1185 
1186  /*
1187  * Flat hierarchy, encode one attribute at a time.
1188  *
1189  * Note that there's no attempt to encode multiple VSAs
1190  * into one attribute. We can add that back as a flag,
1191  * once all of the nested attribute conversion has been
1192  * done.
1193  */
1194  if (da_stack->da[depth + 1]) {
1195  if (dv && dv->continuation) {
1196  return encode_wimax(dbuff, da_stack, depth, cursor, encode_ctx);
1197  }
1198 
1199  return encode_vendor_attr(dbuff, da_stack, depth, cursor, encode_ctx);
1200  }
1201 
1202  /*
1203  * Loop over the children of this attribute of type Vendor.
1204  */
1205  vp = fr_dcursor_current(cursor);
1206  fr_assert(vp->da == da);
1207  work_dbuff = FR_DBUFF(dbuff);
1208 
1209  fr_pair_dcursor_child_iter_init(&child_cursor, &vp->vp_group, cursor);
1210  while ((vp = fr_dcursor_current(&child_cursor)) != NULL) {
1211  fr_proto_da_stack_build(da_stack, vp->da);
1212 
1213  if (dv && dv->continuation) {
1214  slen = encode_wimax(&work_dbuff, da_stack, depth, &child_cursor, encode_ctx);
1215  } else {
1216  slen = encode_vendor_attr(&work_dbuff, da_stack, depth, &child_cursor, encode_ctx);
1217  }
1218  if (slen < 0) return slen;
1219  }
1220 
1221  vp = fr_dcursor_next(cursor);
1222  fr_proto_da_stack_build(da_stack, vp ? vp->da : NULL);
1223 
1224  return fr_dbuff_set(dbuff, &work_dbuff);
1225 }
1226 
1227 /** Encode a Vendor-Specific attribute
1228  *
1229  */
1231  fr_da_stack_t *da_stack, unsigned int depth,
1232  fr_dcursor_t *cursor, void *encode_ctx)
1233 {
1234  ssize_t slen;
1235  fr_pair_t *vp;
1236  fr_dcursor_t child_cursor;
1237  fr_dict_attr_t const *da = da_stack->da[depth];
1238  fr_dbuff_t work_dbuff;
1239 
1240  FR_PROTO_STACK_PRINT(da_stack, depth);
1241 
1242  if (da->type != FR_TYPE_VSA) {
1243  fr_strerror_printf("%s: Expected type \"vsa\" got \"%s\"", __FUNCTION__,
1244  fr_type_to_str(da->type));
1245  return PAIR_ENCODE_FATAL_ERROR;
1246  }
1247 
1248  /*
1249  * Loop over the contents of Vendor-Specific, each of
1250  * which MUST be of type FR_TYPE_VENDOR.
1251  */
1252  if (da_stack->da[depth + 1]) {
1253  return encode_vendor(dbuff, da_stack, depth + 1, cursor, encode_ctx);
1254  }
1255 
1256  work_dbuff = FR_DBUFF(dbuff);
1257 
1258  vp = fr_dcursor_current(cursor);
1259  if (vp->da != da_stack->da[depth]) {
1260  fr_strerror_printf("%s: Can't encode empty Vendor-Specific", __FUNCTION__);
1261  return 0;
1262  }
1263 
1264  /*
1265  * Loop over the children of this Vendor-Specific
1266  * attribute.
1267  */
1268  fr_pair_dcursor_child_iter_init(&child_cursor, &vp->vp_group, cursor);
1269  while ((vp = fr_dcursor_current(&child_cursor)) != NULL) {
1270  fr_proto_da_stack_build(da_stack, vp->da);
1271 
1272  fr_assert(da_stack->da[depth + 1]->type == FR_TYPE_VENDOR);
1273 
1274  slen = encode_vendor(&work_dbuff, da_stack, depth + 1, &child_cursor, encode_ctx);
1275  if (slen < 0) return slen;
1276  }
1277 
1278  /*
1279  * Fix up the da stack, and return the data we've encoded.
1280  */
1281  vp = fr_dcursor_next(cursor);
1282  fr_proto_da_stack_build(da_stack, vp ? vp->da : NULL);
1283 
1284  FR_PROTO_HEX_DUMP(fr_dbuff_start(&work_dbuff), 6, "header vsa");
1285 
1286  return fr_dbuff_set(dbuff, &work_dbuff);
1287 }
1288 
1289 /** Encode NAS-Filter-Rule
1290  *
1291  * Concatenating the string attributes together, separated by a 0x00 byte,
1292  */
1294  fr_da_stack_t *da_stack, NDEBUG_UNUSED unsigned int depth,
1295  fr_dcursor_t *cursor, UNUSED void *encode_ctx)
1296 {
1297  fr_dbuff_t work_dbuff = FR_DBUFF(dbuff);
1298  fr_dbuff_marker_t hdr, frag_hdr;
1299  fr_pair_t *vp = fr_dcursor_current(cursor);
1300  size_t attr_len = 2;
1301 
1302  FR_PROTO_STACK_PRINT(da_stack, depth);
1303 
1304  fr_assert(vp);
1305  fr_assert(vp->da);
1306 
1307  fr_dbuff_marker(&hdr, &work_dbuff);
1308  fr_dbuff_marker(&frag_hdr, &work_dbuff);
1309  fr_dbuff_advance(&hdr, 1);
1310  FR_DBUFF_IN_BYTES_RETURN(&work_dbuff, (uint8_t)vp->da->attr, 0x00);
1311 
1313 
1314  while (true) {
1315  size_t data_len = vp->vp_length;
1316  size_t frag_len;
1317  char const *p = vp->vp_strvalue;
1318 
1319  /*
1320  * Keep encoding this attribute until it's done.
1321  */
1322  while (data_len > 0) {
1323  frag_len = data_len;
1324 
1325  /*
1326  * This fragment doesn't overflow the
1327  * attribute. Copy it over, update the
1328  * length, but leave the marker at the
1329  * current header.
1330  */
1331  if ((attr_len + frag_len) <= UINT8_MAX) {
1332  FR_DBUFF_IN_MEMCPY_RETURN(&work_dbuff, p, frag_len);
1333  attr_len += frag_len;
1334 
1335  fr_dbuff_set(&frag_hdr, &hdr);
1336  fr_dbuff_in(&frag_hdr, (uint8_t) attr_len); /* there's no fr_dbuff_in_no_advance() */
1337  break;
1338  }
1339 
1340  /*
1341  * This fragment overflows the attribute.
1342  * Copy the fragment in, and create a new
1343  * attribute header.
1344  */
1345  frag_len = UINT8_MAX - attr_len;
1346  FR_DBUFF_IN_MEMCPY_RETURN(&work_dbuff, p, frag_len);
1347  fr_dbuff_in(&hdr, (uint8_t) UINT8_MAX);
1348 
1349  fr_dbuff_marker(&hdr, &work_dbuff);
1350  fr_dbuff_advance(&hdr, 1);
1351  FR_DBUFF_IN_BYTES_RETURN(&work_dbuff, (uint8_t)vp->da->attr, 0x02);
1352  attr_len = 2;
1353 
1354  p += frag_len;
1355  data_len -= frag_len;
1356  }
1357 
1358  /*
1359  * If we have nothing more to do here, then stop.
1360  */
1361  vp = fr_dcursor_next(cursor);
1362  if (!vp || (vp->da != attr_nas_filter_rule)) {
1363  break;
1364  }
1365 
1366  /*
1367  * We have to add a zero byte. If it doesn't
1368  * overflow the current attribute, then just add
1369  * it in.
1370  */
1371  if (attr_len < UINT8_MAX) {
1372  attr_len++;
1373  FR_DBUFF_IN_BYTES_RETURN(&work_dbuff, 0x00);
1374 
1375  fr_dbuff_set(&frag_hdr, &hdr);
1376  fr_dbuff_in(&frag_hdr, (uint8_t) attr_len); /* there's no fr_dbuff_in_no_advance() */
1377  continue;
1378  }
1379 
1380  /*
1381  * The zero byte causes the current attribute to
1382  * overflow. Create a new header with the zero
1383  * byte already populated, and keep going.
1384  */
1385  fr_dbuff_marker(&hdr, &work_dbuff);
1386  fr_dbuff_advance(&hdr, 1);
1387  FR_DBUFF_IN_BYTES_RETURN(&work_dbuff, (uint8_t)vp->da->attr, 0x00, 0x00);
1388  attr_len = 3;
1389  }
1390 
1391  vp = fr_dcursor_current(cursor);
1392  fr_proto_da_stack_build(da_stack, vp ? vp->da : NULL);
1393 
1394  return fr_dbuff_set(dbuff, &work_dbuff);
1395 }
1396 
1397 /** Encode an RFC standard attribute 1..255
1398  *
1399  * This function is not the same as encode_child(), because this
1400  * one treats some "top level" attributes as special. e.g.
1401  * Message-Authenticator.
1402  */
1403 static ssize_t encode_rfc(fr_dbuff_t *dbuff, fr_da_stack_t *da_stack, unsigned int depth,
1404  fr_dcursor_t *cursor, void *encode_ctx)
1405 {
1406  fr_pair_t const *vp = fr_dcursor_current(cursor);
1407  fr_dbuff_t work_dbuff = FR_DBUFF(dbuff);
1408  fr_dbuff_marker_t start;
1409 
1410  fr_dbuff_marker(&start, &work_dbuff);
1411 
1412  /*
1413  * Sanity checks
1414  */
1415  PAIR_VERIFY(vp);
1416  FR_PROTO_STACK_PRINT(da_stack, depth);
1417 
1418  switch (da_stack->da[depth]->type) {
1419  case FR_TYPE_TLV:
1420  case FR_TYPE_VSA:
1421  case FR_TYPE_VENDOR:
1422  /* FR_TYPE_STRUCT is actually allowed... */
1423  fr_strerror_printf("%s: Expected leaf type got \"%s\"", __FUNCTION__,
1424  fr_type_to_str(da_stack->da[depth]->type));
1425  return PAIR_ENCODE_FATAL_ERROR;
1426 
1427  default:
1428  /*
1429  * Attribute 0 is fine as a TLV leaf, or VSA, but not
1430  * in the original standards space.
1431  */
1432  if (((fr_dict_vendor_num_by_da(da_stack->da[depth]) == 0) && (da_stack->da[depth]->attr == 0)) ||
1433  (da_stack->da[depth]->attr > UINT8_MAX)) {
1434  fr_strerror_printf("%s: Called with non-standard attribute %u", __FUNCTION__, vp->da->attr);
1435  return 0;
1436  }
1437  break;
1438  }
1439 
1440  /*
1441  * Only CUI is allowed to have zero length.
1442  * Thank you, WiMAX!
1443  */
1444  if ((vp->da == attr_chargeable_user_identity) && (vp->vp_length == 0)) {
1445  fr_dbuff_in_bytes(&work_dbuff, (uint8_t)vp->da->attr, 0x02);
1446 
1447  FR_PROTO_HEX_DUMP(fr_dbuff_current(&start), 2, "header rfc");
1448 
1449  vp = fr_dcursor_next(cursor);
1450  fr_proto_da_stack_build(da_stack, vp ? vp->da : NULL);
1451  return fr_dbuff_set(dbuff, &work_dbuff);
1452  }
1453 
1454  /*
1455  * Message-Authenticator is hard-coded.
1456  */
1457  if (vp->da == attr_message_authenticator) {
1458  FR_DBUFF_IN_BYTES_RETURN(&work_dbuff, (uint8_t)vp->da->attr, 18);
1460 
1462  "message-authenticator");
1463  FR_PROTO_HEX_DUMP(fr_dbuff_current(&start), 2, "header rfc");
1464 
1465  vp = fr_dcursor_next(cursor);
1466  fr_proto_da_stack_build(da_stack, vp ? vp->da : NULL);
1467  return fr_dbuff_set(dbuff, &work_dbuff);
1468  }
1469 
1470  /*
1471  * NAS-Filter-Rule has a stupid format in order to save
1472  * one byte per attribute.
1473  */
1474  if (vp->da == attr_nas_filter_rule) {
1475  return encode_nas_filter_rule(dbuff, da_stack, depth, cursor, encode_ctx);
1476  }
1477 
1478  /*
1479  * Once we've checked for various top-level magic, RFC attributes are just TLVs.
1480  */
1481  return encode_child(dbuff, da_stack, depth, cursor, encode_ctx);
1482 }
1483 
1484 /** Encode a data structure into a RADIUS attribute
1485  *
1486  * This is the main entry point into the encoder. It sets up the encoder array
1487  * we use for tracking our TLV/VSA nesting and then calls the appropriate
1488  * dispatch function.
1489  *
1490  * @param[out] dbuff Where to write encoded data.
1491  * @param[in] cursor Specifying attribute to encode.
1492  * @param[in] encode_ctx Additional data such as the shared secret to use.
1493  * @return
1494  * - >0 The number of bytes written to out.
1495  * - 0 Nothing to encode (or attribute skipped).
1496  * - <0 an error occurred.
1497  */
1499 {
1500  fr_pair_t const *vp;
1501  ssize_t slen;
1502  fr_dbuff_t work_dbuff = FR_DBUFF(dbuff);
1503 
1504  fr_da_stack_t da_stack;
1505  fr_dict_attr_t const *da = NULL;
1506 
1507  if (!cursor) return PAIR_ENCODE_FATAL_ERROR;
1508 
1509  vp = fr_dcursor_current(cursor);
1510  if (!vp) return 0;
1511 
1512  PAIR_VERIFY(vp);
1513 
1514  if (vp->da->depth > FR_DICT_MAX_TLV_STACK) {
1515  fr_strerror_printf("%s: Attribute depth %i exceeds maximum nesting depth %i",
1516  __FUNCTION__, vp->da->depth, FR_DICT_MAX_TLV_STACK);
1517  return PAIR_ENCODE_FATAL_ERROR;
1518  }
1519 
1520  /*
1521  * Tags are *top-level*, and are never nested.
1522  */
1523  if ((vp->vp_type == FR_TYPE_GROUP) && vp->da->flags.internal &&
1524  (vp->da->attr > FR_TAG_BASE) && (vp->da->attr < (FR_TAG_BASE + 0x20))) {
1525  fr_radius_encode_ctx_t *packet_ctx = encode_ctx;
1526 
1527  packet_ctx->tag = vp->da->attr - FR_TAG_BASE;
1528  fr_assert(packet_ctx->tag > 0);
1529  fr_assert(packet_ctx->tag < 0x20);
1530 
1531  // recurse to encode the children of this attribute
1532  slen = encode_pairs(&work_dbuff, &vp->vp_group, encode_ctx);
1533  packet_ctx->tag = 0;
1534  if (slen < 0) return slen;
1535 
1536  fr_dcursor_next(cursor); /* skip the tag attribute */
1537  return fr_dbuff_set(dbuff, &work_dbuff);
1538  }
1539 
1540  /*
1541  * Check for zero-length attributes.
1542  */
1543  switch (vp->vp_type) {
1544  default:
1545  break;
1546 
1547  /*
1548  * Only variable length data types can be
1549  * variable sized. All others have fixed size.
1550  */
1551  case FR_TYPE_STRING:
1552  case FR_TYPE_OCTETS:
1553  /*
1554  * Zero-length strings are allowed for CUI
1555  * (thanks WiMAX!), and for
1556  * Message-Authenticator, because we will
1557  * automagically generate that one ourselves.
1558  */
1559  if ((vp->vp_length == 0) &&
1562  fr_dcursor_next(cursor);
1563  fr_strerror_const("Zero length string attributes not allowed");
1564  return 0;
1565  }
1566  break;
1567  }
1568 
1569  /*
1570  * Nested structures of attributes can't be longer than
1571  * 255 bytes, so each call to an encode function can
1572  * only use 255 bytes of buffer space at a time.
1573  */
1574 
1575  /*
1576  * Fast path for the common case.
1577  */
1578  if (vp->da->parent->flags.is_root && !vp->da->flags.subtype) {
1579  switch (vp->vp_type) {
1580  case FR_TYPE_LEAF:
1581  da_stack.da[0] = vp->da;
1582  da_stack.da[1] = NULL;
1583  da_stack.depth = 1;
1584  FR_PROTO_STACK_PRINT(&da_stack, 0);
1585  slen = encode_rfc(&work_dbuff, &da_stack, 0, cursor, encode_ctx);
1586  if (slen < 0) return slen;
1587  return fr_dbuff_set(dbuff, &work_dbuff);
1588 
1589  default:
1590  break;
1591  }
1592  }
1593 
1594  /*
1595  * Do more work to set up the stack for the complex case.
1596  */
1597  fr_proto_da_stack_build(&da_stack, vp->da);
1598  FR_PROTO_STACK_PRINT(&da_stack, 0);
1599 
1600  /*
1601  * Top-level attributes get treated specially. Things
1602  * like VSAs inside of extended attributes are handled
1603  * inside of type-specific encoders.
1604  */
1605  da = da_stack.da[0];
1606  switch (da->type) {
1607  case FR_TYPE_OCTETS:
1608  if (flag_concat(&da->flags)) {
1609  /*
1610  * Attributes like EAP-Message are marked as
1611  * "concat", which means that they are fragmented
1612  * using a different scheme than the "long
1613  * extended" one.
1614  */
1615  slen = encode_concat(&work_dbuff, &da_stack, 0, cursor, encode_ctx);
1616  if (slen < 0) return slen;
1617  break;
1618  }
1619  FALL_THROUGH;
1620 
1621  default:
1622  slen = encode_rfc(&work_dbuff, &da_stack, 0, cursor, encode_ctx);
1623  if (slen < 0) return slen;
1624  break;
1625 
1626  case FR_TYPE_VSA:
1627  slen = encode_vsa(&work_dbuff, &da_stack, 0, cursor, encode_ctx);
1628  if (slen < 0) return slen;
1629  break;
1630 
1631  case FR_TYPE_TLV:
1632  if (!flag_extended(&da->flags)) {
1633  slen = encode_child(&work_dbuff, &da_stack, 0, cursor, encode_ctx);
1634 
1635  } else if (vp->da != da) {
1636  fr_strerror_printf("extended attributes must be nested");
1637  return PAIR_ENCODE_FATAL_ERROR;
1638 
1639  } else {
1640  slen = encode_extended_nested(&work_dbuff, &da_stack, 0, cursor, encode_ctx);
1641  }
1642  if (slen < 0) return slen;
1643  break;
1644 
1645  case FR_TYPE_NULL:
1646  case FR_TYPE_VENDOR:
1647  case FR_TYPE_MAX:
1648  fr_strerror_printf("%s: Cannot encode attribute %s", __FUNCTION__, vp->da->name);
1649  return PAIR_ENCODE_FATAL_ERROR;
1650  }
1651 
1652  /*
1653  * We couldn't do it, so we didn't do anything.
1654  */
1655  if (fr_dcursor_current(cursor) == vp) {
1656  fr_strerror_printf("%s: Nested attribute structure too large to encode", __FUNCTION__);
1657  return PAIR_ENCODE_FATAL_ERROR;
1658  }
1659 
1660  return fr_dbuff_set(dbuff, &work_dbuff);
1661 }
1662 
1664 {
1665  fr_radius_ctx_t common_ctx = {};
1667  .common = &common_ctx,
1668  };
1669 
1670  /*
1671  * Just in case we need random numbers.
1672  */
1673  encode_ctx.rand_ctx.a = fr_rand();
1674  encode_ctx.rand_ctx.b = fr_rand();
1675 
1676  /*
1677  * Encode the pairs.
1678  */
1679  return encode_pairs(dbuff, list, &encode_ctx);
1680 }
1681 
1682 
1683 static int encode_test_ctx(void **out, TALLOC_CTX *ctx)
1684 {
1685  static uint8_t vector[RADIUS_AUTH_VECTOR_LENGTH] = {
1686  0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
1687  0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f };
1688 
1689  fr_radius_encode_ctx_t *test_ctx;
1690 
1691  test_ctx = talloc_zero(ctx, fr_radius_encode_ctx_t);
1692  if (!test_ctx) return -1;
1693 
1694  test_ctx->common = talloc_zero(test_ctx, fr_radius_ctx_t);
1695 
1696  test_ctx->common->secret = talloc_strdup(test_ctx->common, "testing123");
1697  test_ctx->common->secret_length = talloc_array_length(test_ctx->common->secret) - 1;
1698 
1699  test_ctx->request_authenticator = vector;
1700  test_ctx->rand_ctx.a = 6809;
1701  test_ctx->rand_ctx.b = 2112;
1702 
1703  *out = test_ctx;
1704 
1705  return 0;
1706 }
1707 
1708 static ssize_t fr_radius_encode_proto(UNUSED TALLOC_CTX *ctx, fr_pair_list_t *vps, uint8_t *data, size_t data_len, void *proto_ctx)
1709 {
1710  fr_radius_encode_ctx_t *packet_ctx = talloc_get_type_abort(proto_ctx, fr_radius_encode_ctx_t);
1711  int packet_type = FR_RADIUS_CODE_ACCESS_REQUEST;
1712  fr_pair_t *vp;
1713  ssize_t slen;
1714 
1715  vp = fr_pair_find_by_da(vps, NULL, attr_packet_type);
1716  if (vp) packet_type = vp->vp_uint32;
1717 
1718  if ((packet_type == FR_RADIUS_CODE_ACCESS_REQUEST) || (packet_type == FR_RADIUS_CODE_STATUS_SERVER)) {
1720  if (vp && (vp->vp_length == RADIUS_AUTH_VECTOR_LENGTH)) {
1721  memcpy(data + 4, vp->vp_octets, RADIUS_AUTH_VECTOR_LENGTH);
1722  } else {
1723  int i;
1724 
1725  for (i = 0; i < RADIUS_AUTH_VECTOR_LENGTH; i++) {
1726  data[4 + i] = fr_fast_rand(&packet_ctx->rand_ctx);
1727  }
1728  }
1729  }
1730 
1731  /*
1732  * @todo - pass in packet_ctx to this function, so that we
1733  * can leverage a consistent random number generator.
1734  */
1735  slen = fr_radius_encode(data, data_len, NULL, packet_ctx->common->secret, talloc_array_length(packet_ctx->common->secret) - 1,
1736  packet_type, 0, vps);
1737  if (slen <= 0) return slen;
1738 
1739  if (fr_radius_sign(data, NULL, (uint8_t const *) packet_ctx->common->secret, talloc_array_length(packet_ctx->common->secret) - 1) < 0) {
1740  return -1;
1741  }
1742 
1743  return slen;
1744 }
1745 
1746 /*
1747  * No one else should be using this.
1748  */
1749 extern void *fr_radius_next_encodable(fr_dlist_head_t *list, void *to_eval, void *uctx);
1750 
1751 /*
1752  * Test points
1753  */
1757  .func = fr_radius_encode_pair,
1758  .next_encodable = fr_radius_next_encodable,
1759 };
1760 
1761 
1765  .func = fr_radius_encode_proto
1766 };
ssize_t fr_radius_encode_abinary(fr_pair_t const *vp, fr_dbuff_t *dbuff)
Encode a string to abinary.
Definition: abinary.c:1198
int n
Definition: acutest.h:577
#define RCSID(id)
Definition: build.h:444
#define NDEBUG_UNUSED
Definition: build.h:324
#define FALL_THROUGH
clang 10 doesn't recognised the FALL-THROUGH comment anymore
Definition: build.h:320
#define unlikely(_x)
Definition: build.h:378
#define UNUSED
Definition: build.h:313
#define fr_dbuff_advance(_dbuff_or_marker, _len)
Advance 'current' position in dbuff or marker by _len bytes.
Definition: dbuff.h:1067
#define fr_dbuff_used(_dbuff_or_marker)
Return the number of bytes remaining between the start of the dbuff or marker and the current positio...
Definition: dbuff.h:762
#define FR_DBUFF_ABS(_dbuff_or_marker)
Create a new dbuff pointing to the same underlying buffer.
Definition: dbuff.h:231
struct fr_dbuff_marker_s fr_dbuff_marker_t
A position marker associated with a dbuff.
Definition: dbuff.h:81
#define fr_dbuff_current(_dbuff_or_marker)
Return the 'current' position of a dbuff or marker.
Definition: dbuff.h:906
#define fr_dbuff_start(_dbuff_or_marker)
Return the 'start' position of a dbuff or marker.
Definition: dbuff.h:893
#define fr_dbuff_set_to_start(_dbuff_or_marker)
Reset the 'current' position of the dbuff or marker to the 'start' of the buffer.
Definition: dbuff.h:1150
#define fr_dbuff_out_memcpy(_out, _dbuff_or_marker, _outlen)
Copy exactly _outlen bytes from the dbuff.
Definition: dbuff.h:1724
#define FR_DBUFF_BIND_CURRENT(_dbuff_or_marker)
Create a new dbuff pointing to the same underlying buffer.
Definition: dbuff.h:240
#define FR_DBUFF_MEMSET_RETURN(_dbuff_or_marker, _c, _inlen)
Set _inlen bytes of a dbuff or marker to _c returning if there is insufficient space.
Definition: dbuff.h:1503
#define fr_dbuff_in_bytes(_dbuff_or_marker,...)
Copy a byte sequence into a dbuff or marker.
Definition: dbuff.h:1460
#define FR_DBUFF_IN_MEMCPY_RETURN(_dbuff_or_marker, _in, _inlen)
Copy exactly _inlen bytes into dbuff or marker returning if there's insufficient space.
Definition: dbuff.h:1377
#define fr_dbuff_in_memcpy(_dbuff_or_marker, _in, _inlen)
Copy exactly _inlen bytes into a dbuff or marker.
Definition: dbuff.h:1345
#define fr_dbuff_in(_dbuff_or_marker, _in)
Copy data from a fixed sized C type into a dbuff or marker.
Definition: dbuff.h:1562
#define FR_DBUFF_IN_RETURN(_dbuff_or_marker, _in)
Copy data from a fixed sized C type into a dbuff returning if there is insufficient space.
Definition: dbuff.h:1580
#define FR_DBUFF(_dbuff_or_marker)
Create a new dbuff pointing to the same underlying buffer.
Definition: dbuff.h:222
#define FR_DBUFF_MAX(_dbuff_or_marker, _max)
Limit the maximum number of bytes available in the dbuff when passing it to another function.
Definition: dbuff.h:301
static uint8_t * fr_dbuff_marker(fr_dbuff_marker_t *m, fr_dbuff_t *dbuff)
Initialises a new marker pointing to the 'current' position of the dbuff.
Definition: dbuff.h:1187
#define FR_DBUFF_MAX_BIND_CURRENT(_dbuff_or_marker, _max)
Limit the maximum number of bytes available in the dbuff when passing it to another function.
Definition: dbuff.h:318
#define fr_dbuff_out(_out, _dbuff_or_marker)
Copy data from a dbuff or marker to a fixed sized C type.
Definition: dbuff.h:1779
#define FR_DBUFF_IN_BYTES_RETURN(_dbuff_or_marker,...)
Copy a byte sequence into a dbuff or marker returning if there's insufficient space.
Definition: dbuff.h:1467
static void * fr_dcursor_next(fr_dcursor_t *cursor)
Advanced the cursor to the next item.
Definition: dcursor.h:287
static void * fr_dcursor_current(fr_dcursor_t *cursor)
Return the item the cursor current points to.
Definition: dcursor.h:336
@ FR_RADIUS_CODE_ACCESS_REQUEST
RFC2865 - Access-Request.
Definition: defs.h:33
@ FR_RADIUS_CODE_STATUS_SERVER
RFC2865/RFC5997 - Status Server (request)
Definition: defs.h:44
static fr_dict_attr_t const * attr_packet_type
Definition: dhcpclient.c:89
bool continuation
we only have one flag for now, for WiMAX
Definition: dict.h:229
#define FR_DICT_MAX_TLV_STACK
Maximum TLV stack size.
Definition: dict.h:384
fr_dict_vendor_t const * fr_dict_vendor_by_da(fr_dict_attr_t const *da)
Look up a vendor by one of its child attributes.
Definition: dict_util.c:2232
static fr_slen_t in
Definition: dict.h:645
Private enterprise.
Definition: dict.h:227
static uint32_t fr_dict_vendor_num_by_da(fr_dict_attr_t const *da)
Return the vendor number for an attribute.
Definition: dict_ext.h:182
Head of a doubly linked list.
Definition: dlist.h:51
#define PAIR_ENCODE_FATAL_ERROR
Fatal encoding error.
Definition: pair.h:37
ssize_t fr_pair_ref_to_network(fr_dbuff_t *dbuff, fr_da_stack_t *da_stack, unsigned int depth, fr_dcursor_t *cursor)
Encode a foreign reference to the network.
Definition: encode.c:123
#define ROUND_UP_DIV(_x, _y)
Get the ceiling value of integer division.
Definition: math.h:153
#define ROUND_UP(_num, _mul)
Round up - Works in all cases, but is slower.
Definition: math.h:148
fr_md5_update_t fr_md5_update
Definition: md5.c:450
fr_md5_final_t fr_md5_final
Definition: md5.c:451
void fr_md5_ctx_free_from_list(fr_md5_ctx_t **ctx)
Definition: md5.c:530
fr_md5_ctx_t * fr_md5_ctx_alloc_from_list(void)
Definition: md5.c:485
fr_md5_ctx_copy_t fr_md5_ctx_copy
Definition: md5.c:447
void fr_md5_ctx_t
Definition: md5.h:28
unsigned short uint16_t
Definition: merged_model.c:31
@ FR_TYPE_TLV
Contains nested attributes.
Definition: merged_model.c:118
@ FR_TYPE_IPV6_PREFIX
IPv6 Prefix.
Definition: merged_model.c:89
@ FR_TYPE_STRING
String of printable characters.
Definition: merged_model.c:83
@ FR_TYPE_MAX
Number of defined data types.
Definition: merged_model.c:130
@ FR_TYPE_NULL
Invalid (uninitialised) attribute type.
Definition: merged_model.c:81
@ FR_TYPE_COMBO_IP_PREFIX
IPv4 or IPv6 address prefix depending on length.
Definition: merged_model.c:92
@ FR_TYPE_UINT32
32 Bit unsigned integer.
Definition: merged_model.c:99
@ FR_TYPE_STRUCT
like TLV, but without T or L, and fixed-width children
Definition: merged_model.c:119
@ FR_TYPE_VENDOR
Attribute that represents a vendor in the attribute tree.
Definition: merged_model.c:122
@ FR_TYPE_IPV6_ADDR
128 Bit IPv6 Address.
Definition: merged_model.c:88
@ FR_TYPE_IPV4_PREFIX
IPv4 Prefix.
Definition: merged_model.c:87
@ FR_TYPE_VSA
Vendor-Specific, for RADIUS attribute 26.
Definition: merged_model.c:121
@ FR_TYPE_COMBO_IP_ADDR
IPv4 or IPv6 address depending on length.
Definition: merged_model.c:91
@ FR_TYPE_OCTETS
Raw octets.
Definition: merged_model.c:84
@ FR_TYPE_GROUP
A grouping of other attributes.
Definition: merged_model.c:124
unsigned int uint32_t
Definition: merged_model.c:33
long int ssize_t
Definition: merged_model.c:24
unsigned char uint8_t
Definition: merged_model.c:30
#define UINT8_MAX
Definition: merged_model.c:32
static uint8_t depth(fr_minmax_heap_index_t i)
Definition: minmax_heap.c:83
static unsigned int fr_bytes_from_bits(unsigned int bits)
Convert bits (as in prefix length) to bytes, rounding up.
Definition: nbo.h:228
#define RADIUS_AUTH_VECTOR_LENGTH
Definition: net.h:89
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
void fr_proto_da_stack_build(fr_da_stack_t *stack, fr_dict_attr_t const *da)
Build a complete DA stack from the da back to the root.
Definition: proto.c:118
void * fr_proto_next_encodable(fr_dlist_head_t *list, void *current, void *uctx)
Implements the default iterator to encode pairs belonging to a specific dictionary that are not inter...
Definition: proto.c:100
static fr_internal_encode_ctx_t encode_ctx
HIDDEN fr_dict_attr_t const * attr_packet_authentication_vector
Definition: base.c:53
HIDDEN fr_dict_attr_t const * attr_chargeable_user_identity
Definition: base.c:56
HIDDEN fr_dict_attr_t const * attr_nas_filter_rule
Definition: base.c:61
ssize_t fr_radius_ascend_secret(fr_dbuff_t *dbuff, uint8_t const *in, size_t inlen, char const *secret, uint8_t const *vector)
Do Ascend-Send / Recv-Secret calculation.
Definition: base.c:190
int fr_radius_sign(uint8_t *packet, uint8_t const *vector, uint8_t const *secret, size_t secret_len)
Sign a previously encoded packet.
Definition: base.c:301
ssize_t fr_radius_encode(uint8_t *packet, size_t packet_len, uint8_t const *original, char const *secret, size_t secret_len, int code, int id, fr_pair_list_t *vps)
Encode VPS into a raw RADIUS packet.
Definition: base.c:860
static ssize_t encode_vsa(fr_dbuff_t *dbuff, fr_da_stack_t *da_stack, unsigned int depth, fr_dcursor_t *cursor, void *encode_ctx)
Encode a Vendor-Specific attribute.
Definition: encode.c:1230
static ssize_t encode_wimax(fr_dbuff_t *dbuff, fr_da_stack_t *da_stack, unsigned int depth, fr_dcursor_t *cursor, void *encode_ctx)
Encode a WiMAX attribute.
Definition: encode.c:1092
static ssize_t encode_pairs(fr_dbuff_t *dbuff, fr_pair_list_t const *vps, void *encode_ctx)
Definition: encode.c:287
static ssize_t encode_tunnel_password(fr_dbuff_t *dbuff, fr_dbuff_marker_t *in, size_t inlen, fr_radius_encode_ctx_t *packet_ctx)
Definition: encode.c:100
void * fr_radius_next_encodable(fr_dlist_head_t *list, void *to_eval, void *uctx)
Definition: base.c:840
#define TAG_VALID(x)
Definition: encode.c:34
static ssize_t fr_radius_encode_proto(UNUSED TALLOC_CTX *ctx, fr_pair_list_t *vps, uint8_t *data, size_t data_len, void *proto_ctx)
Definition: encode.c:1708
static ssize_t encode_value(fr_dbuff_t *dbuff, fr_da_stack_t *da_stack, unsigned int depth, fr_dcursor_t *cursor, void *encode_ctx)
Encodes the data portion of an attribute.
Definition: encode.c:320
static ssize_t encode_concat(fr_dbuff_t *dbuff, fr_da_stack_t *da_stack, unsigned int depth, fr_dcursor_t *cursor, UNUSED void *encode_ctx)
Encode an RFC format attribute, with the "concat" flag set.
Definition: encode.c:877
static ssize_t encode_extended(fr_dbuff_t *dbuff, fr_da_stack_t *da_stack, NDEBUG_UNUSED unsigned int depth, fr_dcursor_t *cursor, void *encode_ctx)
Encode an "extended" attribute.
Definition: encode.c:712
static ssize_t encode_extended_nested(fr_dbuff_t *dbuff, fr_da_stack_t *da_stack, unsigned int depth, fr_dcursor_t *cursor, void *encode_ctx)
Definition: encode.c:832
static ssize_t encode_child(fr_dbuff_t *dbuff, fr_da_stack_t *da_stack, unsigned int depth, fr_dcursor_t *cursor, void *encode_ctx)
Encode an RFC format attribute.
Definition: encode.c:927
ssize_t fr_radius_encode_pair(fr_dbuff_t *dbuff, fr_dcursor_t *cursor, void *encode_ctx)
Encode a data structure into a RADIUS attribute.
Definition: encode.c:1498
fr_test_point_pair_encode_t radius_tp_encode_pair
Definition: encode.c:1755
fr_test_point_proto_encode_t radius_tp_encode_proto
Definition: encode.c:1763
static ssize_t encode_tlv(fr_dbuff_t *dbuff, fr_da_stack_t *da_stack, unsigned int depth, fr_dcursor_t *cursor, void *encode_ctx)
Definition: encode.c:224
ssize_t fr_radius_encode_foreign(fr_dbuff_t *dbuff, fr_pair_list_t const *list)
Definition: encode.c:1663
static int encode_test_ctx(void **out, TALLOC_CTX *ctx)
Definition: encode.c:1683
static ssize_t encode_password(fr_dbuff_t *dbuff, fr_dbuff_marker_t *input, size_t inlen, fr_radius_encode_ctx_t *packet_ctx)
"encrypt" a password RADIUS style
Definition: encode.c:48
static ssize_t attr_fragment(fr_dbuff_t *data, size_t data_len, fr_dbuff_marker_t *hdr, size_t hdr_len, int flag_offset, int vsa_offset)
Breaks down large data into pieces, each with a header.
Definition: encode.c:615
static ssize_t encode_nas_filter_rule(fr_dbuff_t *dbuff, fr_da_stack_t *da_stack, NDEBUG_UNUSED unsigned int depth, fr_dcursor_t *cursor, UNUSED void *encode_ctx)
Encode NAS-Filter-Rule.
Definition: encode.c:1293
static ssize_t encode_rfc(fr_dbuff_t *dbuff, fr_da_stack_t *da_stack, unsigned int depth, fr_dcursor_t *cursor, void *encode_ctx)
Encode an RFC standard attribute 1..255.
Definition: encode.c:1403
static ssize_t encode_vendor(fr_dbuff_t *dbuff, fr_da_stack_t *da_stack, unsigned int depth, fr_dcursor_t *cursor, void *encode_ctx)
Definition: encode.c:1165
static ssize_t encode_vendor_attr(fr_dbuff_t *dbuff, fr_da_stack_t *da_stack, unsigned int depth, fr_dcursor_t *cursor, void *encode_ctx)
Encode one full Vendor-Specific + Vendor-ID + Vendor-Attr + Vendor-Length + ...
Definition: encode.c:959
VQP attributes.
static fr_dict_t const * dict_radius
Definition: radclient-ng.c:102
@ FLAG_ENCRYPT_ASCEND_SECRET
Encrypt attribute ascend style.
Definition: radius.h:93
@ FLAG_ENCRYPT_TUNNEL_PASSWORD
Encrypt attribute RFC 2868 style.
Definition: radius.h:92
@ FLAG_ENCRYPT_USER_PASSWORD
Encrypt attribute RFC 2865 style.
Definition: radius.h:91
@ FLAG_TAGGED_TUNNEL_PASSWORD
the attribute has a tag and is encrypted
Definition: radius.h:89
fr_fast_rand_t rand_ctx
for tunnel passwords
Definition: radius.h:127
#define flag_has_tag(_flags)
Definition: radius.h:97
#define AUTH_PASS_LEN
Definition: radius.h:53
bool disallow_tunnel_passwords
not all packets can have tunnel passwords
Definition: radius.h:132
char const * secret
Definition: radius.h:111
#define flag_extended(_flags)
Definition: radius.h:101
#define RADIUS_MAX_STRING_LENGTH
Definition: radius.h:34
#define flag_encrypted(_flags)
Definition: radius.h:100
uint8_t const * request_authenticator
Definition: radius.h:125
uint8_t tag
current tag for encoding
Definition: radius.h:130
#define RADIUS_MESSAGE_AUTHENTICATOR_LENGTH
Definition: radius.h:37
size_t secret_length
Definition: radius.h:112
#define RADIUS_MAX_PASS_LENGTH
Definition: radius.h:38
#define flag_abinary(_flags)
Definition: radius.h:99
#define flag_concat(_flags)
Definition: radius.h:98
fr_radius_ctx_t * common
Definition: radius.h:123
int salt_offset
for tunnel passwords
Definition: radius.h:128
#define flag_long_extended(_flags)
Definition: radius.h:102
static fr_dict_attr_t const * attr_message_authenticator
Definition: radsnmp.c:112
uint32_t fr_fast_rand(fr_fast_rand_t *ctx)
Definition: rand.c:280
uint32_t fr_rand(void)
Return a 32-bit random number.
Definition: rand.c:106
uint32_t b
Definition: rand.h:55
uint32_t a
Definition: rand.h:55
static int encode(rlm_radius_udp_t const *inst, request_t *request, udp_request_t *u, uint8_t id)
fr_assert(0)
fr_pair_t * vp
ssize_t fr_struct_to_network(fr_dbuff_t *dbuff, fr_da_stack_t *da_stack, unsigned int depth, fr_dcursor_t *parent_cursor, void *encode_ctx, fr_encode_dbuff_t encode_value, fr_encode_dbuff_t encode_pair)
Definition: struct.c:478
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
fr_test_point_ctx_alloc_t test_ctx
Allocate a test ctx for the encoder.
Definition: test_point.h:92
fr_test_point_ctx_alloc_t test_ctx
Allocate a test ctx for the encoder.
Definition: test_point.h:74
Entry point for pair encoders.
Definition: test_point.h:91
Entry point for protocol encoders.
Definition: test_point.h:73
#define fr_pair_dcursor_iter_init(_cursor, _list, _iter, _uctx)
Initialises a special dcursor with callbacks that will maintain the attr sublists correctly.
Definition: pair.h:568
static fr_pair_t * fr_pair_dcursor_child_iter_init(fr_dcursor_t *cursor, fr_pair_list_t const *list, fr_dcursor_t const *parent)
Initializes a child dcursor from a parent cursor, with an iteration function.
Definition: pair.h:610
#define PAIR_VERIFY(_x)
Definition: pair.h:190
static fr_slen_t parent
Definition: pair.h:844
#define FR_PROTO_HEX_DUMP(_data, _data_len, _fmt,...)
Definition: proto.h:41
#define FR_PROTO_STACK_PRINT(_stack, _depth)
Definition: proto.h:43
uint8_t depth
Deepest attribute in the stack.
Definition: proto.h:55
fr_dict_attr_t const * da[FR_DICT_MAX_TLV_STACK+1]
The stack.
Definition: proto.h:56
Structure for holding the stack of dictionary attributes being encoded.
Definition: proto.h:54
#define fr_strerror_printf(_fmt,...)
Log to thread local error buffer.
Definition: strerror.h:64
#define fr_strerror_const(_msg)
Definition: strerror.h:223
static char const * fr_type_to_str(fr_type_t type)
Return a static string containing the type name.
Definition: types.h:433
#define fr_type_is_structural(_x)
Definition: types.h:371
#define FR_TYPE_LEAF
Definition: types.h:297
return fr_dbuff_set(dbuff, &our_dbuff)
ssize_t fr_value_box_to_network(fr_dbuff_t *dbuff, fr_value_box_t const *value)
Encode a single value box, serializing its contents in generic network format.
Definition: value.c:1359
static fr_slen_t data
Definition: value.h:1259
static size_t char fr_sbuff_t size_t inlen
Definition: value.h:984
static size_t char ** out
Definition: value.h:984