23 RCSID(
"$Id: bb0f560ed6b8ca9011bb654f7732a3569302e653 $")
25 #include <freeradius-devel/libradius.h>
29 #include <freeradius-devel/tmpl.h>
30 #include <freeradius-devel/map.h>
32 #include <freeradius-devel/parser.h>
33 #include <freeradius-devel/xlat.h>
34 #include <freeradius-devel/conf.h>
35 #include <freeradius-devel/radpaths.h>
36 #include <freeradius-devel/dhcp.h>
46 #include <freeradius-devel/log.h>
60 return waitpid(pid, status, 0);
64 UNUSED void const *mod_inst,
UNUSED void const *xlat_inst,
74 .vector = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f },
82 .vector = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f },
93 static int encode_tlv(
char *buffer, uint8_t *output,
size_t outlen);
95 static char const hextab[] =
"0123456789abcdef";
98 uint8_t *output,
size_t outlen)
105 while (*p && (outlen > 0)) {
111 *(output++) = *(p++);
139 fprintf(stderr,
"String is not terminated\n");
144 uint8_t *output,
size_t outlen)
150 for (p = buffer; *p !=
'\0'; p++) {
151 if (*p ==
'{') depth++;
154 if (depth == 0)
break;
159 fprintf(stderr,
"No trailing '}' in string starting "
169 while (isspace((
int) *p)) p++;
172 if (length == 0)
return 0;
177 static int encode_hex(
char *p, uint8_t *output,
size_t outlen)
183 while (isspace((
int) *p)) p++;
187 if(!(c1 = memchr(hextab, tolower((
int) p[0]), 16)) ||
188 !(c2 = memchr(hextab, tolower((
int) p[1]), 16))) {
189 fprintf(stderr,
"Invalid data starting at "
201 fprintf(stderr,
"Too much data\n");
214 if (!isspace((
int) *p)) {
215 fprintf(stderr,
"Invalid character following attribute "
220 while (isspace((
int) *p)) p++;
229 while (isspace((
int) *p)) p++;
232 fprintf(stderr,
"No data\n");
240 if (sublen == 0)
return 0;
259 fprintf(stderr,
"Empty string\n");
270 attr = strtol(buffer, endptr, 10);
271 if (*endptr == buffer) {
272 fprintf(stderr,
"No valid number found in string "
273 "starting with \"%s\"\n", buffer);
278 fprintf(stderr,
"Nothing follows attribute number\n");
282 if ((attr <= 0) || (attr > 256)) {
283 fprintf(stderr,
"Attribute number is out of valid "
295 if (*buffer !=
'.') {
296 fprintf(stderr,
"Invalid separator before vendor id\n");
300 vendor = strtol(buffer + 1, endptr, 10);
301 if (*endptr == (buffer + 1)) {
302 fprintf(stderr,
"No valid vendor number found\n");
307 fprintf(stderr,
"Nothing follows vendor number\n");
311 if ((vendor <= 0) || (vendor > (1 << 24))) {
312 fprintf(stderr,
"Vendor number is out of valid range\n");
316 if (**endptr !=
'.') {
317 fprintf(stderr,
"Invalid data following vendor number\n");
325 static int encode_tlv(
char *buffer, uint8_t *output,
size_t outlen)
332 if (attr == 0)
return 0;
339 length =
encode_tlv(p, output + 2, outlen - 2);
345 if (length == 0)
return 0;
346 if (length > (255 - 2)) {
347 fprintf(stderr,
"TLV data is too long\n");
356 static int encode_vsa(
char *buffer, uint8_t *output,
size_t outlen)
363 if (vendor == 0)
return 0;
366 output[1] = (vendor >> 16) & 0xff;
367 output[2] = (vendor >> 8) & 0xff;
368 output[3] = vendor & 0xff;
370 length =
encode_tlv(p, output + 4, outlen - 4);
371 if (length == 0)
return 0;
372 if (length > (255 - 6)) {
373 fprintf(stderr,
"VSA data is too long\n");
381 static int encode_evs(
char *buffer, uint8_t *output,
size_t outlen)
389 if (vendor == 0)
return 0;
392 if (attr == 0)
return 0;
395 output[1] = (vendor >> 16) & 0xff;
396 output[2] = (vendor >> 8) & 0xff;
397 output[3] = vendor & 0xff;
401 if (length == 0)
return 0;
407 uint8_t *output,
size_t outlen)
414 if (attr == 0)
return 0;
419 length =
encode_evs(p, output + 1, outlen - 1);
423 if (length == 0)
return 0;
424 if (length > (255 - 3)) {
425 fprintf(stderr,
"Extended Attr data is too long\n");
433 uint8_t *output,
size_t outlen)
440 if (attr == 0)
return 0;
448 length =
encode_evs(p, output + 4, outlen - 4);
449 if (length == 0)
return 0;
456 if (length == 0)
return 0;
460 int sublen = 255 - output[1];
462 if (length <= sublen) {
470 memmove(output + 255 + 4, output + 255, length);
471 memcpy(output + 255, output, 4);
484 static int encode_rfc(
char *buffer, uint8_t *output,
size_t outlen)
491 if (attr == 0)
return 0;
498 sublen =
encode_vsa(p, output + 2, outlen - 2);
500 }
else if ((attr < 241) || (attr > 246)) {
505 fprintf(stderr,
"Invalid data following "
506 "attribute number\n");
512 output + 2, outlen - 2);
521 if (sublen == 0)
return 0;
522 if (sublen > (255 -2)) {
523 fprintf(stderr,
"RFC Data is too long\n");
528 return length + sublen;
534 char const *error = NULL;
539 snprintf(output, outlen,
"ERROR offset %d %s", (
int) -slen, error);
544 if (*input !=
'\0') {
546 snprintf(output, outlen,
"ERROR offset %d 'Too much text'", (
int) slen);
555 static void parse_xlat(
char const *input,
char *output,
size_t outlen)
558 char const *error = NULL;
564 snprintf(output, outlen,
"ERROR offset %d '%s'", (
int) -slen, error);
568 if (input[slen] !=
'\0') {
569 snprintf(output, outlen,
"ERROR offset %d 'Too much text'", (
int) slen);
581 ssize_t len, data_len;
583 char input[8192], buffer[8192];
585 char directory[8192];
586 uint8_t *attr,
data[2048];
588 if (strcmp(filename,
"-") == 0) {
590 filename =
"<stdin>";
594 if (root_dir && *root_dir) {
595 snprintf(directory,
sizeof(directory),
"%s/%s", root_dir, filename);
597 strlcpy(directory, filename,
sizeof(directory));
600 fp = fopen(directory,
"r");
602 fprintf(stderr,
"Error opening %s: %s\n",
607 filename = directory;
614 while (fgets(buffer,
sizeof(buffer), fp) != NULL) {
615 char *p = strchr(buffer,
'\n');
622 fprintf(stderr,
"Line %d too long in %s\n",
633 p = strchr(buffer,
'#');
634 if (p && ((p == buffer) ||
635 ((p > buffer) && (p[-1] !=
'[')))) *p =
'\0';
638 while (isspace((
int) *p)) p++;
641 DEBUG2(
"%s[%d]: %s\n", filename, lineno, buffer);
643 strlcpy(input, p,
sizeof(input));
645 if (strncmp(p,
"raw ", 4) == 0) {
646 outlen =
encode_rfc(p + 4, data,
sizeof(data));
648 fprintf(stderr,
"Parse error in line %d of %s\n",
659 if (outlen >= (
sizeof(output) / 2)) {
660 outlen = (
sizeof(output) / 2) - 1;
664 for (i = 0; i < outlen; i++) {
665 if (
sizeof(output) < (3*i))
break;
667 snprintf(output + 3*i,
sizeof(output) - (3*i) - 1,
670 outlen = strlen(output);
671 output[outlen - 1] =
'\0';
675 if (strncmp(p,
"data ", 5) == 0) {
676 if (strcmp(p + 5, output) != 0) {
677 fprintf(stderr,
"Mismatch at line %d of %s\n\tgot : %s\n\texpected : %s\n",
678 lineno, directory, output, p + 5);
684 if (strncmp(p,
"encode ", 7) == 0) {
688 .secret = my_secret };
690 if (strcmp(p + 7,
"-") == 0) {
706 fprintf(stderr,
"Failed encoding %s: %s\n",
716 outlen = attr -
data;
720 if (strncmp(p,
"decode ", 7) == 0) {
725 .secret = my_secret };
726 if (strcmp(p + 7,
"-") == 0) {
733 fprintf(stderr,
"Failed decoding hex string at line %d of %s\n", lineno, directory);
749 fprintf(stderr,
"Internal sanity check failed at %d\n", __LINE__);
769 if (vp->
next) {strcpy(p,
", ");
775 }
else if (my_len < 0) {
787 if (strncmp(p,
"encode-dhcp ", 12) == 0) {
790 if (strcmp(p + 12,
"-") == 0) {
808 fprintf(stderr,
"Failed encoding %s: %s\n",
816 outlen = attr -
data;
820 if (strncmp(p,
"decode-dhcp ", 12) == 0) {
824 if (strcmp(p + 12,
"-") == 0) {
831 fprintf(stderr,
"Failed decoding hex string at line %d of %s\n", lineno, directory);
837 uint8_t
const *end, *option_p;
840 end = option_p + len;
847 while (option_p < end) {
851 end - option_p, NULL);
872 if (vp->
next) {strcpy(p,
", ");
878 }
else if (my_len < 0) {
887 if (strncmp(p,
"attribute ", 10) == 0) {
899 if (strncmp(p,
"dictionary ", 11) == 0) {
907 strlcpy(output,
"ok",
sizeof(output));
911 if (strncmp(p,
"$INCLUDE ", 9) == 0) {
915 while (isspace((
int) *p)) p++;
917 q = strrchr(directory,
'/');
928 if (strncmp(p,
"condition ", 10) == 0) {
934 if (strncmp(p,
"xlat ", 5) == 0) {
940 fprintf(stderr,
"Unknown input at line %d of %s\n",
945 if (fp != stdin) fclose(fp);
950 fprintf(stderr,
"usage: radattr [OPTS] filename\n");
951 fprintf(stderr,
" -d <raddb> Set user dictionary directory (defaults to " RADDBDIR
").\n");
952 fprintf(stderr,
" -D <dictdir> Set main dictionary directory (defaults to " DICTDIR
").\n");
953 fprintf(stderr,
" -x Debugging mode.\n");
954 fprintf(stderr,
" -M Show talloc memory report.\n");
959 int main(
int argc,
char *argv[])
976 while ((c = getopt(argc, argv,
"d:D:xMh")) != EOF)
switch (c) {
997 argc -= (optind - 1);
998 argv += (optind - 1);
1019 fprintf(stderr,
"Failed registering xlat");
void fr_pair_list_free(VALUE_PAIR **)
Free memory used by a valuepair list.
static int encode_vsa(char *buffer, uint8_t *output, size_t outlen)
static char const * dict_dir
int sockfd
Socket this packet was read from.
static void NEVER_RETURNS usage(void)
VALUE_PAIR * fr_cursor_first(vp_cursor_t *cursor)
Rewind cursor to the start of the list.
static char const * radius_dir
Path to raddb directory.
int xlat_register(void *mod_inst, char const *name, xlat_func_t func, xlat_escape_t escape, xlat_instantiate_t instantiate, size_t inst_size, size_t buf_len)
Register an xlat function.
int fr_radius_encode_pair(uint8_t *out, size_t outlen, vp_cursor_t *cursor, void *encoder_ctx)
Encode a data structure into a RADIUS attribute.
static void process_file(fr_dict_t *dict, const char *root_dir, char const *filename)
int fr_dict_read(fr_dict_t *dict, char const *dir, char const *filename)
static RADIUS_PACKET my_original
ssize_t fr_dhcp_encode_option(uint8_t *out, size_t outlen, vp_cursor_t *cursor, void *encoder_ctx)
ssize_t fr_dhcp_decode_option(TALLOC_CTX *ctx, vp_cursor_t *cursor, fr_dict_attr_t const *parent, uint8_t const *data, size_t len, void *decoder_ctx)
VALUE_PAIR * fr_cursor_init(vp_cursor_t *cursor, VALUE_PAIR *const *node)
Setup a cursor to iterate over attribute pairs.
PUBLIC int snprintf(char *string, size_t length, char *format, va_alist)
int fr_log_talloc_report(TALLOC_CTX *ctx)
Generate a talloc memory report for a context and print to stderr/stdout.
#define XLAT_DEFAULT_BUF_LEN
static int encode_data_string(char *buffer, uint8_t *output, size_t outlen)
static int encode_long_extended(char *buffer, uint8_t *output, size_t outlen)
Abstraction to allow iterating over different configurations of VALUE_PAIRs.
int fr_fault_setup(char const *cmd, char const *program)
Registers signal handlers to execute panic_action on fatal signal.
Vendors and attribute names.
RFC2865 - Access-Request.
char const * fr_syserror(int num)
Guaranteed to be thread-safe version of strerror.
int fr_check_lib_magic(uint64_t magic)
Check if the application linking to the library has the correct magic number.
static int decode_attr(char *buffer, char **endptr)
static int encode_data_tlv(char *buffer, char **endptr, uint8_t *output, size_t outlen)
static void parse_condition(char const *input, char *output, size_t outlen)
static char const hextab[]
static int encode_evs(char *buffer, uint8_t *output, size_t outlen)
void void fr_perror(char const *,...) CC_HINT(format(printf
static int encode_hex(char *p, uint8_t *output, size_t outlen)
static RADIUS_PACKET my_packet
#define RADIUS_DICTIONARY
static int encode_data(char *p, uint8_t *output, size_t outlen)
Stores an attribute, a value and various bits of other data.
VALUE_PAIR * fr_cursor_current(vp_cursor_t *cursor)
Return the VALUE_PAIR the cursor current points to.
char const * fr_strerror(void)
Get the last library error.
static char const * my_secret
static ssize_t xlat_test(UNUSED char **out, UNUSED size_t outlen, UNUSED void const *mod_inst, UNUSED void const *xlat_inst, UNUSED REQUEST *request, UNUSED char const *fmt)
char name[1]
Attribute name.
static int encode_tlv(char *buffer, uint8_t *output, size_t outlen)
ssize_t fr_radius_decode_pair(TALLOC_CTX *ctx, vp_cursor_t *cursor, fr_dict_attr_t const *parent, uint8_t const *data, size_t data_len, void *decoder_ctx)
Create a "normal" VALUE_PAIR from the given data.
size_t fr_cond_snprint(char *buffer, size_t bufsize, fr_cond_t const *c)
VALUE_PAIR * fr_cursor_next(vp_cursor_t *cursor)
Advanced the cursor to the next VALUE_PAIR.
log_lvl_t rad_debug_lvl
Global debugging level.
static int encode_extended(char *buffer, uint8_t *output, size_t outlen)
static void parse_xlat(char const *input, char *output, size_t outlen)
static void print_hex(RADIUS_PACKET *packet)
ssize_t ssize_t ssize_t ssize_t ssize_t xlat_tokenize(TALLOC_CTX *ctx, char *fmt, xlat_exp_t **head, char const **error)
ssize_t fr_condition_tokenize(TALLOC_CTX *ctx, CONF_ITEM *ci, char const *start, fr_cond_t **head, char const **error, int flag)
Tokenize a conditional check.
size_t fr_pair_snprint(char *out, size_t outlen, VALUE_PAIR const *vp)
Print one attribute and value to a string.
pid_t rad_waitpid(pid_t pid, int *status)
int main(int argc, char *argv[])
static int encode_rfc(char *buffer, uint8_t *output, size_t outlen)
size_t strlcpy(char *dst, char const *src, size_t siz)
int fr_dict_parse_str(fr_dict_t *dict, char *buf, fr_dict_attr_t const *parent, unsigned int vendor)
fr_dict_attr_t const * da
Dictionary attribute defines the attribute.
RADIUS_PACKET const * packet
log_dst_t dst
Log destination.
FR_TOKEN fr_pair_list_afrom_str(TALLOC_CTX *ctx, char const *buffer, VALUE_PAIR **head)
Read one line of attribute/value pairs into a list.
char * talloc_typed_strdup(void const *t, char const *p)
Call talloc strdup, setting the type on the new chunk correctly.
fr_dict_t * fr_dict_internal
Internal server dictionary.
fr_dict_attr_t const * fr_dict_root(fr_dict_t const *dict)
Return the root attribute of a dictionary.
int fd
File descriptor to write messages to.
static int decode_vendor(char *buffer, char **endptr)
int fr_dict_init(TALLOC_CTX *ctx, fr_dict_t **out, char const *dir, char const *fn, char const *name)
(re)initialize a protocol dictionary
#define RADIUSD_MAGIC_NUMBER
size_t xlat_snprint(char *buffer, size_t bufsize, xlat_exp_t const *node)