The FreeRADIUS server  $Id: 15bac2a4c627c01d1aa2047687b3418955ac7f00 $
radmin.c
Go to the documentation of this file.
1 /*
2  * This program 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
5  * (at 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: f5aa08a6b5d642c8cb5e80983f31e851e0cf8b26 $
19  *
20  * @file src/listen/control/radmin.c
21  * @brief Control a running radiusd process.
22  *
23  * @copyright 2012-2016 The FreeRADIUS server project
24  * @copyright 2016 Arran Cudbard-Bell (a.cudbardb@freeradius.org)
25  * @copyright 2012 Alan DeKok (aland@deployingradius.com)
26  */
27 RCSID("$Id: f5aa08a6b5d642c8cb5e80983f31e851e0cf8b26 $")
28 
29 #include <assert.h>
30 
31 #include <pwd.h>
32 #include <grp.h>
33 #include <fcntl.h>
34 
35 #ifdef HAVE_GETOPT_H
36 # include <getopt.h>
37 #endif
38 
39 #ifdef HAVE_SYS_STAT_H
40 # include <sys/stat.h>
41 #endif
42 
43 #ifdef HAVE_LIBREADLINE
44 
45 # include <stdio.h>
46 
47 DIAG_OFF(strict-prototypes)
48 #if defined(HAVE_READLINE_READLINE_H)
49 # include <readline/readline.h>
50 # define USE_READLINE (1)
51 #elif defined(HAVE_READLINE_H)
52 # include <readline.h>
53 # define USE_READLINE (1)
54 #endif /* !defined(HAVE_READLINE_H) */
55 DIAG_ON(strict-prototypes)
56 
57 #ifdef HAVE_READLINE_HISTORY
58 # if defined(HAVE_READLINE_HISTORY_H)
59 # include <readline/history.h>
60 # define USE_READLINE_HISTORY (1)
61 # elif defined(HAVE_HISTORY_H)
62 # include <history.h>
63 # define USE_READLINE_HISTORY (1)
64 #endif /* defined(HAVE_READLINE_HISTORY_H) */
65 #endif /* HAVE_READLINE_HISTORY */
66 #endif /* HAVE_LIBREADLINE */
67 
68 #define LOG_PREFIX "radmin"
69 
70 #include <freeradius-devel/server/cf_parse.h>
71 #include <freeradius-devel/server/cf_file.h>
72 #include <freeradius-devel/server/main_config.h>
73 #include <freeradius-devel/server/radmin.h>
74 
75 #include <freeradius-devel/util/conf.h>
76 #include <freeradius-devel/util/md5.h>
77 #include <freeradius-devel/util/socket.h>
78 #include <freeradius-devel/util/atexit.h>
79 
80 #ifdef USE_READLINE_HISTORY
81 #ifndef READLINE_MAX_HISTORY_LINES
82 # define READLINE_MAX_HISTORY_LINES 1000
83 #endif
84 #endif
85 
86 #include "conduit.h"
87 
88 /*
89  * For configuration file stuff.
90  */
91 static char const *progname = "radmin";
92 static char const *radmin_version = RADIUSD_VERSION_BUILD("radmin");
93 
94 typedef enum {
95  RADMIN_CONN_NONE = 0, //!< Don't know, never connected.
96  RADMIN_CONN_UNIX, //!< Connect via unix socket.
97  RADMIN_CONN_TCP //!< Connect via TCP.
99 
100 /** A connection to a server
101  *
102  */
103 typedef struct {
104  fr_event_list_t *event_list; //!< Event list this fd is serviced by.
105  int fd; //!< Control socket descriptor.
106 
107  char *last_command; //!< Last command we executed on this connection.
108  char *server; //!< Path or FQDN of server we're connected to.
109  char *secret; //!< We use to authenticate ourselves to the server.
110 
111  bool nonblock; //!< Whether this connection should operate in
112  //!< non-blocking mode.
113  bool connected; //!< Whether this connection is currently connected.
115  radmin_conn_type_t type; //!< Type of connection.
116 } radmin_conn_t;
117 
118 /** Radmin state
119  *
120  * Many of the readline functions don't take callbacks, so we need
121  * to use a global structure to communicate radmin state.
122  */
123 typedef struct {
124  fr_event_list_t *event_list; //!< Our main event list.
125 
126  radmin_conn_t *active_conn; //!< Connection to remote entity.
128 
129 /** Main radmin state
130  *
131  */
132 //static radmin_state_t state;
133 
134 static bool echo = false;
135 static char const *secret = "";
136 static bool unbuffered = false;
137 static bool use_readline = true;
138 
140  .dst = L_DST_NULL,
141  .colourise = false,
142  .timestamp = L_TIMESTAMP_ON,
143  .fd = -1,
144  .file = NULL,
145 };
146 static int sockfd = -1;
147 static char io_buffer[65536];
148 
149 #ifdef USE_READLINE
150 #define CMD_MAX_EXPANSIONS (128)
151 static int radmin_num_expansions = 0;
152 static char *radmin_expansions[CMD_MAX_EXPANSIONS] = {0};
153 #endif
154 
155 #define MAX_STACK (64)
156 static int stack_depth;
157 static char cmd_buffer[65536];
158 static char *stack[MAX_STACK];
159 
160 static fr_cmd_t *local_cmds = NULL;
161 
162 static NEVER_RETURNS void usage(int status)
163 {
164  FILE *output = status ? stderr : stdout;
165  fprintf(output, "Usage: %s [ args ]\n", progname);
166  fprintf(output, " -d raddb_dir Configuration files are in \"raddbdir/*\".\n");
167  fprintf(output, " -D <dictdir> Set main dictionary directory (defaults to " DICTDIR ").\n");
168  fprintf(output, " -e command Execute 'command' and then exit.\n");
169  fprintf(output, " -E Echo commands as they are being executed.\n");
170  fprintf(output, " -f socket_file Open socket_file directly, without reading radius.conf\n");
171  fprintf(output, " -h Print usage help information.\n");
172  fprintf(output, " -i input_file Read commands from 'input_file'.\n");
173  fprintf(output, " -l <log_file> Commands which are executed will be written to this file.\n");
174  fprintf(output, " -n name Read raddb/name.conf instead of raddb/radiusd.conf\n");
175  fprintf(output, " -q Reduce output verbosity\n");
176  fprintf(output, " -s <server> Look in named server for name of control socket.\n");
177  fprintf(output, " -S <secret> Use argument as shared secret for authentication to the server.\n");
178  fprintf(output, " -x Increase output verbosity\n");
179  fr_exit_now(status);
180 }
181 
182 static int client_socket(char const *server)
183 {
184  int fd;
185  uint16_t port;
186  fr_ipaddr_t ipaddr;
187  char *p, buffer[1024];
188 
189  strlcpy(buffer, server, sizeof(buffer));
190 
191  p = strchr(buffer, ':');
192  if (!p) {
193  port = FR_RADMIN_PORT;
194  } else {
195  port = atoi(p + 1);
196  *p = '\0';
197  }
198 
199  if (fr_inet_hton(&ipaddr, AF_INET, buffer, false) < 0) {
200  fprintf(stderr, "%s: Failed looking up host %s: %s\n",
201  progname, buffer, fr_syserror(errno));
202  fr_exit_now(EXIT_FAILURE);
203  }
204 
205  fd = fr_socket_client_tcp(NULL, NULL, &ipaddr, port, false);
206  if (fd < 0) {
207  fprintf(stderr, "%s: Failed opening socket %s: %s\n",
208  progname, server, fr_syserror(errno));
209  fr_exit_now(EXIT_FAILURE);
210  }
211 
212  return fd;
213 }
214 
215 static ssize_t do_challenge(int fd)
216 {
217  ssize_t r;
218  fr_conduit_type_t conduit;
219  uint8_t challenge[16];
220 
221  challenge[0] = 0x00;
222 
223  /*
224  * When connecting over a socket, the server challenges us.
225  */
226  r = fr_conduit_read(fd, &conduit, challenge, sizeof(challenge));
227  if (r <= 0) return r;
228 
229  if ((r != 16) || (conduit != FR_CONDUIT_AUTH_CHALLENGE)) {
230  fprintf(stderr, "%s: Failed to read challenge.\n",
231  progname);
232  fr_exit_now(EXIT_FAILURE);
233  }
234 
235  fr_hmac_md5(challenge, (uint8_t const *) secret, strlen(secret),
236  challenge, sizeof(challenge));
237 
238  r = fr_conduit_write(fd, FR_CONDUIT_AUTH_RESPONSE, challenge, sizeof(challenge));
239  if (r <= 0) return r;
240 
241  /*
242  * If the server doesn't like us, it just closes the
243  * socket. So we don't look for an ACK.
244  */
245 
246  return r;
247 }
248 
249 
250 /*
251  * Returns -1 on failure. 0 on connection failed. +1 on OK.
252  */
253 static ssize_t flush_conduits(int fd, char *buffer, size_t bufsize)
254 {
255  ssize_t r;
256 #ifdef USE_READLINE
257  char *p, *str;
258 #endif
259  uint32_t status;
260  fr_conduit_type_t conduit;
261 
262  while (true) {
263  uint32_t notify;
264 
265  r = fr_conduit_read(fd, &conduit, buffer, bufsize - 1);
266  if (r <= 0) return r;
267 
268  buffer[r] = '\0'; /* for C strings */
269 
270  switch (conduit) {
271  case FR_CONDUIT_STDOUT:
272  fprintf(stdout, "%s", buffer);
273  break;
274 
275  case FR_CONDUIT_STDERR:
276  fprintf(stderr, "ERROR: %s", buffer);
277  break;
278 
280  if (r < 4) return 1;
281 
282  memcpy(&status, buffer, sizeof(status));
283  status = ntohl(status);
284  return status;
285 
286  case FR_CONDUIT_NOTIFY:
287  if (r < 4) return -1;
288 
289  memcpy(&notify, buffer, sizeof(notify));
290  notify = ntohl(notify);
291 
292  if (notify == FR_NOTIFY_UNBUFFERED) unbuffered = true;
293  if (notify == FR_NOTIFY_BUFFERED) unbuffered = false;
294 
295  break;
296 
297 #ifdef USE_READLINE
298  case FR_CONDUIT_COMPLETE:
299  str = buffer;
300 
301  for (p = buffer; p < (buffer + r); p++) {
302  if (*p == '\n') {
303  size_t len;
304 
305  len = p - str;
306 
307  MEM(radmin_expansions[radmin_num_expansions] = malloc(len + 1));
308  memcpy(radmin_expansions[radmin_num_expansions], str, len);
309  radmin_expansions[radmin_num_expansions][len] = '\0';
310  radmin_num_expansions++;
311 
312  str = p + 1;
313  }
314 
315  if (radmin_num_expansions >= CMD_MAX_EXPANSIONS) break;
316  }
317  break;
318 #endif
319 
320  default:
321  fprintf(stderr, "Unexpected response %02x\n", conduit);
322  return -1;
323  }
324  }
325 
326  /* never gets here */
327 }
328 
329 
330 /*
331  * Returns -1 on failure. 0 on connection failed. +1 on OK.
332  */
333 static ssize_t run_command(int fd, char const *command,
334  char *buffer, size_t bufsize)
335 {
336  ssize_t r;
337  char const *p = command;
338 
340  if (!*p) return FR_CONDUIT_SUCCESS;
341 
342  if (echo) {
343  fprintf(stdout, "%s\n", command);
344  }
345 
346  /*
347  * Write the text to the socket.
348  */
349  r = fr_conduit_write(fd, FR_CONDUIT_STDIN, p, strlen(p));
350  if (r <= 0) return r;
351 
352  return flush_conduits(fd, buffer, bufsize);
353 }
354 
355 static int do_connect(int *out, char const *file, char const *server)
356 {
357  int fd;
358  ssize_t r;
359  fr_conduit_type_t conduit;
360  char buffer[65536];
361 
362  uint32_t magic;
363 
364  /*
365  * Close stale file descriptors
366  */
367  if (*out != -1) {
368  close(*out);
369  *out = -1;
370  }
371 
372  if (file) {
373  /*
374  * FIXME: Get destination from command line, if possible?
375  */
376  fd = fr_socket_client_unix(file, false);
377  if (fd < 0) {
378  fr_perror("radmin");
379  if (errno == ENOENT) {
380  fprintf(stderr, "Perhaps you need to run the commands:");
381  fprintf(stderr, "\tcd /etc/raddb\n");
382  fprintf(stderr, "\tln -s sites-available/control-socket "
383  "sites-enabled/control-socket\n");
384  fprintf(stderr, "and then re-start the server?\n");
385  }
386  return -1;
387  }
388  } else {
389  fd = client_socket(server);
390  }
391 
392  /*
393  * Only works for BSD, but Linux allows us
394  * to mask SIGPIPE, so that's fine.
395  */
396 #ifdef SO_NOSIGPIPE
397  {
398  int set = 1;
399 
400  setsockopt(fd, SOL_SOCKET, SO_NOSIGPIPE, (void *)&set, sizeof(int));
401  }
402 #endif
403 
404  /*
405  * Set up the initial header data.
406  */
407  magic = FR_CONDUIT_MAGIC;
408  magic = htonl(magic);
409  memcpy(buffer, &magic, sizeof(magic));
410  memset(buffer + sizeof(magic), 0, sizeof(magic));
411 
413  if (r <= 0) {
414  do_close:
415  fprintf(stderr, "%s: Error in socket: %s\n",
416  progname, fr_syserror(errno));
417  close(fd);
418  return -1;
419  }
420 
421  r = fr_conduit_read(fd, &conduit, buffer + 8, 8);
422  if (r <= 0) goto do_close;
423 
424  if ((r != 8) || (conduit != FR_CONDUIT_INIT_ACK) ||
425  (memcmp(buffer, buffer + 8, 8) != 0)) {
426  fprintf(stderr, "%s: Incompatible versions\n", progname);
427  close(fd);
428  return -1;
429  }
430 
431  if (secret) {
432  r = do_challenge(fd);
433  if (r <= 0) goto do_close;
434  }
435 
436  *out = fd;
437 
438  return 0;
439 }
440 
441 
442 static char *readline_buffer[1024];
443 
444 /*
445  * Wrapper around readline which does the "right thing" depending
446  * on whether we're reading from a file or not. It also ignores
447  * blank lines and comments, which the main readline() API
448  * doesn't do.
449  */
450 static char *my_readline(char const *prompt, FILE *fp_in, FILE *fp_out)
451 {
452  char *line, *p;
453 
454 #ifdef USE_READLINE
455  if (use_readline) return readline(prompt);
456 #endif
457 
458  if (prompt && *prompt) puts(prompt);
459  fflush(fp_out);
460 
461  line = fgets((char *) readline_buffer, sizeof(readline_buffer), fp_in);
462  if (!line) return NULL;
463 
464  p = strchr(line, '\n');
465  if (!p) {
466  fprintf(stderr, "Input line too long\n");
467  return NULL;
468  }
469  *p = '\0';
470 
472 
473  /*
474  * Comments: keep going.
475  */
476  if (line[0] == '#') {
477  *line = '\0';
478  return line;
479  }
480 
481  /*
482  * Strip off CR / LF
483  */
484  for (p = line; *p != '\0'; p++) {
485  if ((p[0] == '\r') ||
486  (p[0] == '\n')) {
487  p[0] = '\0';
488  break;
489  }
490  }
491 
492  return line;
493 }
494 
495 #ifdef USE_READLINE
496 static void radmin_free(char *line)
497 {
498  /*
499  * Was read from stdin, so "line" == "readline_buffer"
500  */
501  if (!use_readline) return;
502 
503  free(line);
504 }
505 #else
506 #define radmin_free(_x)
507 #endif
508 
509 /*
510  * Copies the (possible partial) command to the command buffer,
511  * so that we can send the full command over to the server.
512  */
513 static ssize_t cmd_copy(char const *cmd)
514 {
515  size_t len;
516  char *p = stack[stack_depth];
517 
518  if (stack_depth > 0) *(p++) = ' ';
519 
520  /*
521  * No input, allow a trailing space so that tab
522  * completion works.
523  */
524  if (!*cmd) {
525  return p - cmd_buffer;
526  }
527 
528  len = strlcpy(p, cmd, cmd_buffer + sizeof(cmd_buffer) - p);
529  if ((p + len) >= (cmd_buffer + sizeof(cmd_buffer))) {
530  fprintf(stderr, "Command too long\n");
531  return -1;
532  }
533 
534  /*
535  * Trash trailing spaces.
536  */
537  for (p += len;
538  p > cmd_buffer;
539  p--) {
540  if (!isspace((uint8_t) p[-1])) break;
541  p[-1] = '\0';
542  }
543 
544  return p - cmd_buffer;
545 }
546 
547 #ifdef USE_READLINE
548 static int radmin_help(UNUSED int count, UNUSED int key)
549 {
550  ssize_t len;
551 
552  printf("\n");
553 
554  len = cmd_copy(rl_line_buffer);
555  if (len < 0) return 0;
556 
557  /*
558  * Special-case help for local commands.
559  */
560  if ((len >= 5) && strncmp(cmd_buffer, "local", 5) == 0) {
562  rl_on_new_line();
563  return 0;
564  }
565 
566  if (len > 0) {
568  } else {
569  /*
570  * Don't write zero bytes to the other side...
571  */
572  (void) fr_conduit_write(sockfd, FR_CONDUIT_HELP, " ", 1);
573  }
574 
575  (void) flush_conduits(sockfd, io_buffer, sizeof(io_buffer));
576 
577  rl_on_new_line();
578  return 0;
579 }
580 
581 static char *
582 radmin_expansion_walk(UNUSED const char *text, int state)
583 {
584  static int current;
585  char *name;
586 
587  if (!state) {
588  current = 0;
589  }
590 
591  /*
592  * fr_command_completions() takes care of comparing things to
593  * suppress expansions which don't match "text"
594  */
595  if (current >= radmin_num_expansions) return NULL;
596 
597  name = radmin_expansions[current];
598 
599  radmin_expansions[current++] = NULL;
600 
601  return name;
602 }
603 
604 static char **
605 radmin_completion(const char *text, int start, UNUSED int end)
606 {
607  ssize_t len;
608 
609  rl_attempted_completion_over = 1;
610 
611  radmin_num_expansions = 0;
612 
613  len = cmd_copy(rl_line_buffer);
614  if (len < 0) return NULL;
615 
616  /*
617  * Handle local commands specially.
618  */
619  if (strncmp(cmd_buffer, "local", 5) == 0) {
620  int num;
621  char **expansions = &radmin_expansions[0];
622  char const **expansions_const;
623 
624  memcpy(&expansions_const, &expansions, sizeof(expansions)); /* const issues */
626  CMD_MAX_EXPANSIONS, expansions_const);
627  if (num <= 0) return NULL;
628 
629  radmin_num_expansions = num;
630  return rl_completion_matches(text, radmin_expansion_walk);
631  }
632 
633  start += len;
634 
635  if (start > 65535) return NULL;
636 
637  io_buffer[0] = (start >> 8) & 0xff;
638  io_buffer[1] = start & 0xff;
639 
640  /*
641  * Note that "text" is the PARTIAL thing we're trying to complete.
642  * And "start" is the OFFSET from rl_line_buffer where we want to
643  * do the completion. It's all rather idiotic.
644  */
645  memcpy(io_buffer + 2, cmd_buffer, len);
646 
648 
649  (void) flush_conduits(sockfd, io_buffer, sizeof(io_buffer));
650 
651  return rl_completion_matches(text, radmin_expansion_walk);
652 }
653 
654 #endif
655 
656 #ifndef USE_READLINE_HISTORY
657 # define add_history(line)
658 # define write_history(history_file)
659 #endif
660 
661 static int check_server(CONF_SECTION *subcs, uid_t uid, gid_t gid, char const **file_p, char const **server_p)
662 {
663  int rcode;
664  char const *value, *file = NULL;
665  CONF_SECTION *cs;
666  CONF_PAIR *cp;
667  char const *uid_name = NULL;
668  char const *gid_name = NULL;
669  char const *server;
670  struct passwd *pwd;
671  struct group *grp;
672 
673  cp = cf_pair_find(subcs, "namespace");
674  if (!cp) return 0;
675 
676  value = cf_pair_value(cp);
677  if (!value) return 0;
678 
679  if (strcmp(value, "control") != 0) return 0;
680 
681  server = cf_section_name2(subcs);
682  *server_p = server; /* need this for error messages */
683 
684  /* listen {} */
685  cs = cf_section_find(subcs, "listen", NULL);
686  if (!cs) {
687  fprintf(stderr, "%s: Failed parsing 'listen{}' section in 'server %s {...}'\n", progname, server);
688  return -1;
689  }
690 
691  /* transport = <transport> */
692  cp = cf_pair_find(cs, "transport");
693  if (!cp) return 0;
694 
695  value = cf_pair_value(cp);
696  if (!value) return 0;
697 
698  /* <transport> { ... } */
699  subcs = cf_section_find(cs, value, NULL);
700  if (!subcs) {
701  fprintf(stderr, "%s: Failed parsing the '%s {}' section in 'server %s {...}'\n",
702  progname, cf_section_name1(subcs), server);
703  return -1;
704  }
705 
706  /*
707  * Now find the socket name (sigh)
708  */
709  rcode = cf_pair_parse(NULL, subcs, "filename",
711  if (rcode < 0) {
712  fprintf(stderr, "%s: Failed parsing listen section 'socket'\n", progname);
713  return -1;
714  }
715 
716  if (!file) {
717  fprintf(stderr, "%s: No path given for socket\n", progname);
718  return -1;
719  }
720 
721  *file_p = file;
722 
723  /*
724  * If we're root, just use the first one we find
725  */
726  if (uid == 0) return 1;
727 
728  /*
729  * Check UID and GID.
730  */
731  rcode = cf_pair_parse(NULL, subcs, "uid",
733  if (rcode < 0) {
734  fprintf(stderr, "%s: Failed parsing listen section 'uid'\n", progname);
735  return -1;
736  }
737 
738  if (!uid_name || !*uid_name) return 1;
739 
740  pwd = getpwnam(uid_name);
741  if (!pwd) {
742  fprintf(stderr, "%s: Failed getting UID for user %s: %s\n", progname, uid_name,
743  fr_syserror(errno));
744  return -1;
745  }
746 
747  if (uid != pwd->pw_uid) return 0;
748 
749  rcode = cf_pair_parse(NULL, subcs, "gid",
751  if (rcode < 0) {
752  fprintf(stderr, "%s: Failed parsing listen section 'gid'\n", progname);
753  return -1;
754  }
755 
756  if (!gid_name || !*gid_name) return 1;
757 
758  grp = getgrnam(gid_name);
759  if (!grp) {
760  fprintf(stderr, "%s: Failed resolving gid of group %s: %s\n",
761  progname, gid_name, fr_syserror(errno));
762  return -1;
763  }
764 
765  if (gid != grp->gr_gid) return 0;
766 
767  return 1;
768 }
769 
770 static int cmd_test(FILE *fp, UNUSED FILE *fp_err, UNUSED void *ctx, UNUSED fr_cmd_info_t const *info)
771 {
772  fprintf(fp, "We're testing stuff!\n");
773 
774  return 0;
775 }
776 
777 /*
778  * Local radmin commands
779  */
781  {
782  .parent = "local",
783  .name = "test",
784  .func = cmd_test,
785  .help = "Test stuff",
786  .read_only = true
787  },
788 
790 };
791 
793 
794 static int local_command(char *line)
795 {
796  int argc, ret;
797 
799  if (argc < 0) {
800  fr_perror("Failed parsing local command");
801  return -1;
802  }
803 
804  if (!local_info.runnable) {
805  return 0;
806  }
807 
808  ret = fr_command_run(stderr, stdout, &local_info, false);
809  fflush(stdout);
810  fflush(stderr);
811 
812  /*
813  * reset "info" to be a top-level context again.
814  */
815  (void) fr_command_clear(0, &local_info);
816 
817  if (ret < 0) return ret;
818 
819  return 1;
820 
821 }
822 
823 
824 #define MAX_COMMANDS (256)
825 
826 int main(int argc, char **argv)
827 {
828  int c;
829  bool quiet = false;
830  char *line = NULL;
831  ssize_t result;
832  char const *file = NULL;
833  char const *name = "radiusd";
834  char const *input_file = NULL;
835  FILE *inputfp = stdin;
836  char const *server = NULL;
837  fr_dict_t *dict = NULL;
838 
839  char const *raddb_dir = RADIUS_DIR;
840  char const *dict_dir = DICTDIR;
841 #ifdef USE_READLINE_HISTORY
842  char history_file[PATH_MAX];
843 #endif
844 
845  TALLOC_CTX *autofree;
846 
847  char *commands[MAX_COMMANDS];
848  int num_commands = 0;
849 
850  int exit_status = EXIT_SUCCESS;
851 
852  char const *prompt = "radmin> ";
853  char prompt_buffer[1024];
854 
855  /*
856  * Must be called first, so the handler is called last
857  */
859 
861 
862 #ifndef NDEBUG
863  if (fr_fault_setup(autofree, getenv("PANIC_ACTION"), argv[0]) < 0) {
864  fr_perror("radmin");
865  fr_exit_now(EXIT_FAILURE);
866  }
867 #endif
868 
869  talloc_set_log_stderr();
870 
871  if ((progname = strrchr(argv[0], FR_DIR_SEP)) == NULL) {
872  progname = argv[0];
873  } else {
874  progname++;
875  }
876 
878  secret = NULL;
879 
880  while ((c = getopt(argc, argv, "d:D:hi:e:Ef:n:qs:S:x")) != -1) switch (c) {
881  case 'd':
882  if (file) {
883  fprintf(stderr, "%s: -d and -f cannot be used together.\n", progname);
884  fr_exit_now(EXIT_FAILURE);
885  }
886  raddb_dir = optarg;
887  break;
888 
889  case 'D':
890  dict_dir = optarg;
891  break;
892 
893  case 'e':
894  if (num_commands >= MAX_COMMANDS) {
895  fprintf(stderr, "%s: Too many '-e'\n", progname);
896  fr_exit_now(EXIT_FAILURE);
897  }
898 
899  commands[num_commands++] = optarg;
900  break;
901 
902  case 'E':
903  echo = true;
904  break;
905 
906  case 'f':
907  raddb_dir = NULL;
908  file = optarg;
909  break;
910 
911  default:
912  case 'h':
913  usage(0); /* never returns */
914 
915  case 'i':
916  /*
917  * optarg check is to quiet clang scan
918  */
919  if (optarg && (strcmp(optarg, "-") != 0)) input_file = optarg;
920  quiet = true;
921  break;
922 
923  case 'l':
924  radmin_log.file = optarg;
925  break;
926 
927  case 'n':
928  name = optarg;
929  break;
930 
931  case 'q':
932  quiet = true;
933  if (fr_debug_lvl > 0) fr_debug_lvl--;
934  break;
935 
936  case 's':
937  if (file) {
938  fprintf(stderr, "%s: -s and -f cannot be used together.\n", progname);
939  usage(1);
940  }
941  server = optarg;
942  break;
943 
944  case 'S':
945  secret = optarg;
946  break;
947 
948  case 'x':
949  fr_debug_lvl++;
950  break;
951  }
952 
953  /*
954  * Mismatch between the binary and the libraries it depends on
955  */
957  fr_perror("radmin");
958  fr_exit_now(EXIT_FAILURE);
959  }
960 
961  if (raddb_dir) {
962  int rcode;
963  uid_t uid;
964  gid_t gid;
965  CONF_SECTION *cs, *subcs;
966  CONF_PAIR *cp;
967 
968  file = NULL; /* MUST read it from the conf_file now */
969 
970  snprintf(io_buffer, sizeof(io_buffer), "%s/%s.conf", raddb_dir, name);
971 
972  /*
973  * Need to read in the dictionaries, else we may get
974  * validation errors when we try and parse the config.
975  */
976  if (!fr_dict_global_ctx_init(NULL, true, dict_dir)) {
977  fr_perror("radmin");
978  fr_exit_now(64);
979  }
980 
982  fr_perror("radmin");
983  fr_exit_now(64);
984  }
985 
986  if (fr_dict_read(dict, raddb_dir, FR_DICTIONARY_FILE) == -1) {
987  fr_perror("radmin");
988  fr_exit_now(64);
989  }
990 
991  cs = cf_section_alloc(autofree, NULL, "main", NULL);
992  if (!cs) fr_exit_now(EXIT_FAILURE);
993 
994  if ((cf_file_read(cs, io_buffer) < 0) || (cf_section_pass2(cs) < 0)) {
995  fprintf(stderr, "%s: Errors reading or parsing %s\n", progname, io_buffer);
996  error:
997  fr_exit_now(EXIT_FAILURE);
998  }
999 
1000  uid = getuid();
1001  gid = getgid();
1002 
1003  /*
1004  * We are looking for: server whatever { namespace="control" ... }
1005  */
1006  if (server) {
1007  subcs = cf_section_find(cs, "server", server);
1008  if (subcs) {
1009  fprintf(stderr, "%s: Could not find virtual server %s {}\n", progname, server);
1010  goto error;
1011  }
1012 
1013  rcode = check_server(subcs, uid, gid, &file, &server);
1014  if (rcode < 0) goto error;
1015  if (rcode == 0) file = NULL;
1016 
1017  } else {
1018  for (subcs = cf_section_find_next(cs, NULL, "server", CF_IDENT_ANY);
1019  subcs != NULL;
1020  subcs = cf_section_find_next(cs, subcs, "server", CF_IDENT_ANY)) {
1021  rcode = check_server(subcs, uid, gid, &file, &server);
1022  if (rcode < 0) goto error;
1023  if (rcode == 1) break;
1024  }
1025  }
1026 
1027  if (!file) {
1028  fprintf(stderr, "%s: Could not find control socket in %s (server %s {})\n", progname, io_buffer, server);
1029  goto error;
1030  }
1031 
1032  /*
1033  * Log the commands we've run.
1034  */
1035  if (!radmin_log.file) {
1036  subcs = cf_section_find(cs, "log", NULL);
1037  if (subcs) {
1038  cp = cf_pair_find(subcs, "radmin");
1039  if (cp) {
1041 
1042  if (!radmin_log.file) {
1043  fprintf(stderr, "%s: Invalid value for 'radmin' log destination", progname);
1044  goto error;
1045  }
1046  }
1047  }
1048  }
1049 
1050  if (radmin_log.file) {
1051  radmin_log.fd = open(radmin_log.file, O_APPEND | O_CREAT, S_IRUSR | S_IWUSR);
1052  if (radmin_log.fd < 0) {
1053  fprintf(stderr, "%s: Failed opening %s: %s\n", progname, radmin_log.file, fr_syserror(errno));
1054  goto error;
1055  }
1056 
1058  }
1059  }
1060 
1061  if (input_file) {
1062  inputfp = fopen(input_file, "r");
1063  if (!inputfp) {
1064  fprintf(stderr, "%s: Failed opening %s: %s\n", progname, input_file, fr_syserror(errno));
1065  goto error;
1066  }
1067  }
1068 
1069  if (!file) {
1070  fprintf(stderr, "%s: Failed to find socket file name\n",
1071  progname);
1072  goto error;
1073  }
1074 
1075  /*
1076  * Check if stdin is a TTY only if input is from stdin
1077  */
1078  if (input_file || !isatty(STDIN_FILENO)) {
1079  use_readline = false;
1080  quiet = true;
1081  }
1082 
1083  if (use_readline) {
1084 #ifdef USE_READLINE_HISTORY
1085  using_history();
1086  stifle_history(READLINE_MAX_HISTORY_LINES);
1087  snprintf(history_file, sizeof(history_file), "%s/%s", getenv("HOME"), ".radmin_history");
1088  read_history(history_file);
1089 #endif
1090 #ifdef USE_READLINE
1091  rl_attempted_completion_function = radmin_completion;
1092 #endif
1093  } else {
1094  prompt = NULL;
1095  }
1096 
1097  /*
1098  * Prevent SIGPIPEs from terminating the process
1099  */
1100  signal(SIGPIPE, SIG_IGN);
1101 
1102  if (do_connect(&sockfd, file, server) < 0) fr_exit_now(EXIT_FAILURE);
1103 
1104  /*
1105  * Register local commands.
1106  */
1107  if (fr_command_add_multi(autofree, &local_cmds, NULL, NULL, cmd_table) < 0) {
1108  fprintf(stderr, "%s: Failed registering local commands: %s\n",
1109  progname, fr_strerror());
1110  goto error;
1111  }
1112 
1114 
1115  /*
1116  * Run commands from the command-line.
1117  */
1118  if (num_commands > 0) {
1119  int i;
1120 
1121  for (i = 0; i < num_commands; i++) {
1122  result = run_command(sockfd, commands[i], io_buffer, sizeof(io_buffer));
1123  if (result < 0) fr_exit_now(EXIT_FAILURE);
1124 
1125  if (result == FR_CONDUIT_FAIL) {
1126  exit_status = EXIT_FAILURE;
1127  goto exit;
1128  }
1129  }
1130 
1131  if (unbuffered) {
1132  while (true) flush_conduits(sockfd, io_buffer, sizeof(io_buffer));
1133  }
1134 
1135  /*
1136  * We're done all of the commands, exit now.
1137  */
1138  goto exit;
1139  }
1140 
1141  if (!quiet) {
1142  printf("%s - FreeRADIUS Server administration tool.\n", radmin_version);
1143  printf("Copyright 2008-2019 The FreeRADIUS server project and contributors.\n");
1144  printf("There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A\n");
1145  printf("PARTICULAR PURPOSE.\n");
1146  printf("You may redistribute copies of FreeRADIUS under the terms of the\n");
1147  printf("GNU General Public License v2.\n");
1148  }
1149 
1150  /*
1151  * FIXME: Do login?
1152  */
1153 
1154 #ifdef USE_READLINE
1155  (void) rl_bind_key('?', radmin_help);
1156 #endif
1157 
1158  stack_depth = 0;
1159  stack[0] = cmd_buffer;
1160 
1161  while (1) {
1162  int retries;
1163  ssize_t len;
1164 
1165  line = my_readline(prompt, inputfp, stdout);
1166 
1167  if (!line) break;
1168 
1169  if (!*line) goto next;
1170 
1171  /*
1172  * Radmin supports a number of commands which are
1173  * valid in any context.
1174  */
1175  if (strcmp(line, "reconnect") == 0) {
1176  if (do_connect(&sockfd, file, server) < 0) {
1177  radmin_free(line);
1178  fr_exit_now(EXIT_FAILURE);
1179  }
1180  goto next;
1181  }
1182 
1183  if (!secret && !stack_depth && (strncmp(line, "secret ", 7) == 0)) {
1184  secret = line + 7;
1186  goto next;
1187  }
1188 
1189  /*
1190  * Quit the program
1191  */
1192  if (strcmp(line, "quit") == 0) {
1193  radmin_free(line);
1194  break;
1195  }
1196 
1197  /*
1198  * Exit the current context.
1199  */
1200  if (strcmp(line, "exit") == 0) {
1201  if (!stack_depth) {
1202  radmin_free(line);
1203  break;
1204  }
1205 
1206  stack_depth--;
1207  *stack[stack_depth] = '\0';
1208 
1209  if (stack_depth == 0) {
1210  prompt = "radmin> ";
1211  } else {
1212  snprintf(prompt_buffer, sizeof(prompt_buffer), "... %s> ",
1213  stack[stack_depth - 1]);
1214  prompt = prompt_buffer;
1215  }
1216 
1217  goto next;
1218  }
1219 
1220  /*
1221  * Radmin also supports local commands which
1222  * modifies it's behavior. These commands MUST
1223  */
1224  if (!stack_depth && (strncmp(line, "local", 5) == 0)) {
1225  if (!isspace((uint8_t) line[5])) {
1226  fprintf(stderr, "'local' commands MUST be specified all on one line");
1227  goto next;
1228  }
1229 
1230  /*
1231  * Parse and run the local command.
1232  */
1234  goto next;
1235  }
1236 
1237  /*
1238  * Any other input is sent to the server.
1239  */
1240  retries = 0;
1241 
1242  /*
1243  * If required, log commands to a radmin log file.
1244  */
1245  if (radmin_log.dst == L_DST_FILES) {
1246  fr_log(&radmin_log, L_INFO, __FILE__, __LINE__, "%s", line);
1247  }
1248 
1249  len = cmd_copy(line);
1250  if (len < 0) {
1251  exit_status = EXIT_FAILURE;
1252  radmin_free(line);
1253  break;
1254  }
1255 
1256  retry:
1257 
1258  result = run_command(sockfd, cmd_buffer, io_buffer, sizeof(io_buffer));
1259  if (result < 0) {
1260  if (!quiet) fprintf(stderr, "... reconnecting ...\n");
1261 
1262  if (do_connect(&sockfd, file, server) < 0) {
1263  radmin_free(line);
1264  fr_exit_now(EXIT_FAILURE);
1265  }
1266 
1267  retries++;
1268  if (retries < 2) goto retry;
1269 
1270  fprintf(stderr, "Failed to connect to server\n");
1271  radmin_free(line);
1272  fr_exit_now(EXIT_FAILURE);
1273 
1274  } else if (result == FR_CONDUIT_FAIL) {
1275  fprintf(stderr, "Failed running command\n");
1276  exit_status = EXIT_FAILURE;
1277 
1278  } else if (result == FR_CONDUIT_PARTIAL) {
1279  char *p;
1280 
1281  if (stack_depth >= (MAX_STACK - 1)) {
1282  fprintf(stderr, "Too many sub-contexts running command\n");
1283  exit_status = EXIT_FAILURE;
1284  radmin_free(line);
1285  break;
1286  }
1287 
1288  /*
1289  * Point the stack to the last entry.
1290  */
1291  p = stack[stack_depth];
1292  p += strlen(p);
1293  stack_depth++;
1294  stack[stack_depth] = p;
1295 
1296  snprintf(prompt_buffer, sizeof(prompt_buffer), "... %s> ",
1297  stack[stack_depth - 1]);
1298  prompt = prompt_buffer;
1299 
1300  } else {
1301  /*
1302  * Add only successful commands to the history.
1303  *
1304  * Don't add exit / quit / secret / etc.
1305  */
1306  if (use_readline) {
1308  write_history(history_file);
1309  }
1310  }
1311 
1312  /*
1313  * SUCCESS and PARTIAL end up here too.
1314  */
1315  next:
1316  radmin_free(line);
1317  }
1318 
1319 exit:
1320  fr_dict_free(&dict, __FILE__);
1321 
1322  if (inputfp != stdin) fclose(inputfp);
1323 
1325 
1326  if (sockfd >= 0) close(sockfd);
1327 
1328  if (!quiet) fprintf(stdout, "\n");
1329 
1330  /*
1331  * Ensure our atexit handlers run before any other
1332  * atexit handlers registered by third party libraries.
1333  */
1335 
1336  return exit_status;
1337 }
static int const char char buffer[256]
Definition: acutest.h:574
int const char * file
Definition: acutest.h:702
int const char int line
Definition: acutest.h:702
int fr_atexit_global_setup(void)
Setup the atexit handler, should be called at the start of a program's execution.
Definition: atexit.c:160
int fr_atexit_global_trigger_all(void)
Cause all global free triggers to fire.
Definition: atexit.c:286
static fr_dict_t * dict
Definition: fuzzer.c:46
#define CMD_MAX_EXPANSIONS
Definition: radmin.c:151
static char * readline(char const *prompt)
Definition: radmin.c:81
#define RCSID(id)
Definition: build.h:444
#define NEVER_RETURNS
Should be placed before the function return type.
Definition: build.h:311
#define DIAG_ON(_x)
Definition: build.h:419
#define UNUSED
Definition: build.h:313
#define DIAG_OFF(_x)
Definition: build.h:418
int cf_file_read(CONF_SECTION *cs, char const *filename)
Definition: cf_file.c:3010
int cf_section_pass2(CONF_SECTION *cs)
Definition: cf_file.c:757
int cf_pair_parse(TALLOC_CTX *ctx, CONF_SECTION *cs, char const *name, unsigned int type, void *data, char const *dflt, fr_token_t dflt_quote)
Parses a CONF_PAIR into a C data type, with a default value.
Definition: cf_parse.c:700
#define FR_ITEM_POINTER(_type, _res_p)
Definition: cf_parse.h:331
Configuration AVP similar to a fr_pair_t.
Definition: cf_priv.h:70
A section grouping multiple CONF_PAIR.
Definition: cf_priv.h:89
CONF_SECTION * cf_section_find(CONF_SECTION const *cs, char const *name1, char const *name2)
Find a CONF_SECTION with name1 and optionally name2.
Definition: cf_util.c:970
CONF_PAIR * cf_pair_find(CONF_SECTION const *cs, char const *attr)
Search for a CONF_PAIR with a specific name.
Definition: cf_util.c:1356
char const * cf_section_name2(CONF_SECTION const *cs)
Return the second identifier of a CONF_SECTION.
Definition: cf_util.c:1126
char const * cf_pair_value(CONF_PAIR const *pair)
Return the value of a CONF_PAIR.
Definition: cf_util.c:1511
CONF_SECTION * cf_section_find_next(CONF_SECTION const *cs, CONF_SECTION const *prev, char const *name1, char const *name2)
Return the next matching section.
Definition: cf_util.c:991
char const * cf_section_name1(CONF_SECTION const *cs)
Return the second identifier of a CONF_SECTION.
Definition: cf_util.c:1112
#define cf_section_alloc(_ctx, _parent, _name1, _name2)
Definition: cf_util.h:137
#define CF_IDENT_ANY
Definition: cf_util.h:78
int fr_command_clear(int new_argc, fr_cmd_info_t *info)
Clear out any value boxes etc.
Definition: command.c:2369
int fr_command_str_to_argv(fr_cmd_t *head, fr_cmd_info_t *info, char const *text)
Split a string in-place, updating argv[].
Definition: command.c:2141
int fr_command_run(FILE *fp, FILE *fp_err, fr_cmd_info_t *info, bool read_only)
Run a particular command.
Definition: command.c:1473
void fr_command_info_init(TALLOC_CTX *ctx, fr_cmd_info_t *info)
Initialize an fr_cmd_info_t structure.
Definition: command.c:2397
int fr_command_print_help(FILE *fp, fr_cmd_t *head, char const *text)
Do readline-style help completions.
Definition: command.c:2802
int fr_command_complete(fr_cmd_t *head, char const *text, int start, int max_expansions, char const **expansions)
Do readline-style command completions.
Definition: command.c:2659
int fr_command_add_multi(TALLOC_CTX *talloc_ctx, fr_cmd_t **head, char const *name, void *ctx, fr_cmd_table_t const *table)
Add multiple commands to the global command tree.
Definition: command.c:985
char const * parent
e.g. "show module"
Definition: command.h:52
bool runnable
is the command runnable?
Definition: command.h:41
#define CMD_TABLE_END
Definition: command.h:62
ssize_t fr_conduit_write(int fd, fr_conduit_type_t conduit, void const *out, size_t outlen)
Definition: conduit.c:225
ssize_t fr_conduit_read(int fd, fr_conduit_type_t *pconduit, void *out, size_t outlen)
Definition: conduit.c:143
API to provide distinct communication conduits for the radmin protocol.
#define FR_CONDUIT_MAGIC
Definition: conduit.h:32
@ FR_CONDUIT_FAIL
Definition: conduit.h:54
@ FR_CONDUIT_PARTIAL
Definition: conduit.h:55
@ FR_CONDUIT_SUCCESS
Definition: conduit.h:56
@ FR_NOTIFY_BUFFERED
Definition: conduit.h:61
@ FR_NOTIFY_UNBUFFERED
Definition: conduit.h:62
fr_conduit_type_t
Definition: conduit.h:34
@ FR_CONDUIT_STDOUT
Definition: conduit.h:36
@ FR_CONDUIT_AUTH_RESPONSE
Definition: conduit.h:41
@ FR_CONDUIT_HELP
Definition: conduit.h:43
@ FR_CONDUIT_NOTIFY
Definition: conduit.h:42
@ FR_CONDUIT_STDIN
Definition: conduit.h:35
@ FR_CONDUIT_STDERR
Definition: conduit.h:37
@ FR_CONDUIT_CMD_STATUS
Definition: conduit.h:38
@ FR_CONDUIT_INIT_ACK
Definition: conduit.h:39
@ FR_CONDUIT_COMPLETE
Definition: conduit.h:44
@ FR_CONDUIT_AUTH_CHALLENGE
Definition: conduit.h:40
int fr_fault_setup(TALLOC_CTX *ctx, char const *cmd, char const *program)
Registers signal handlers to execute panic_action on fatal signal.
Definition: debug.c:1215
#define fr_exit_now(_x)
Exit without calling atexit() handlers, producing a log message in debug builds.
Definition: debug.h:232
static int retries
Definition: dhcpclient.c:53
int fr_dict_internal_afrom_file(fr_dict_t **out, char const *internal_name, char const *dependent)
(Re-)Initialize the special internal dictionary
int fr_dict_free(fr_dict_t **dict, char const *dependent)
Decrement the reference count on a previously loaded dictionary.
Definition: dict_util.c:3581
int fr_dict_read(fr_dict_t *dict, char const *dict_dir, char const *filename)
Read supplementary attribute definitions into an existing dictionary.
fr_dict_gctx_t * fr_dict_global_ctx_init(TALLOC_CTX *ctx, bool free_at_exit, char const *dict_dir)
Initialise the global protocol hashes.
Definition: dict_util.c:3984
Test enumeration values.
Definition: dict_test.h:92
free(array)
int fr_hmac_md5(uint8_t digest[MD5_DIGEST_LENGTH], uint8_t const *in, size_t inlen, uint8_t const *key, size_t key_len)
Calculate HMAC using internal MD5 implementation.
Definition: hmac_md5.c:119
int fr_inet_hton(fr_ipaddr_t *out, int af, char const *hostname, bool fallback)
Wrappers for IPv4/IPv6 host to IP address lookup.
Definition: inet.c:240
IPv4/6 prefix.
Definition: merged_model.c:272
Stores all information relating to an event list.
Definition: event.c:411
int fr_debug_lvl
Definition: log.c:42
void fr_log(fr_log_t const *log, fr_log_type_t type, char const *file, int line, char const *fmt,...)
Send a server log message to its destination.
Definition: log.c:599
@ L_DST_NULL
Discard log messages.
Definition: log.h:83
@ L_DST_FILES
Log to a file on disk.
Definition: log.h:79
@ L_TIMESTAMP_ON
Always log timestamps.
Definition: log.h:90
@ L_DBG_LVL_1
Highest priority debug messages (-x).
Definition: log.h:70
@ L_INFO
Informational message.
Definition: log.h:55
char * last_command
Last command we executed on this connection.
Definition: radmin.c:107
static char io_buffer[65536]
Definition: radmin.c:147
fr_event_list_t * event_list
Event list this fd is serviced by.
Definition: radmin.c:104
static ssize_t do_challenge(int fd)
Definition: radmin.c:215
static fr_cmd_t * local_cmds
Definition: radmin.c:160
static int stack_depth
Definition: radmin.c:156
static int client_socket(char const *server)
Definition: radmin.c:182
static bool echo
Main radmin state.
Definition: radmin.c:134
int main(int argc, char **argv)
Definition: radmin.c:826
fr_event_list_t * event_list
Our main event list.
Definition: radmin.c:124
static int do_connect(int *out, char const *file, char const *server)
Definition: radmin.c:355
static char const * radmin_version
Definition: radmin.c:92
#define MAX_COMMANDS
Definition: radmin.c:824
static char * my_readline(char const *prompt, FILE *fp_in, FILE *fp_out)
Definition: radmin.c:450
radmin_conn_type_t type
Type of connection.
Definition: radmin.c:115
static int local_command(char *line)
Definition: radmin.c:794
static ssize_t flush_conduits(int fd, char *buffer, size_t bufsize)
Definition: radmin.c:253
static fr_log_t radmin_log
Definition: radmin.c:139
static char const * secret
Definition: radmin.c:135
static fr_cmd_table_t cmd_table[]
Definition: radmin.c:780
bool nonblock
Whether this connection should operate in non-blocking mode.
Definition: radmin.c:111
static bool use_readline
Definition: radmin.c:137
#define write_history(history_file)
Definition: radmin.c:658
radmin_conn_type_t
Definition: radmin.c:94
@ RADMIN_CONN_UNIX
Connect via unix socket.
Definition: radmin.c:96
@ RADMIN_CONN_TCP
Connect via TCP.
Definition: radmin.c:97
@ RADMIN_CONN_NONE
Don't know, never connected.
Definition: radmin.c:95
static ssize_t cmd_copy(char const *cmd)
Definition: radmin.c:513
#define add_history(line)
Definition: radmin.c:657
static char const * progname
Definition: radmin.c:91
#define radmin_free(_x)
Definition: radmin.c:506
static char * readline_buffer[1024]
Definition: radmin.c:442
static fr_cmd_info_t local_info
Definition: radmin.c:792
int fd
Control socket descriptor.
Definition: radmin.c:105
char * secret
We use to authenticate ourselves to the server.
Definition: radmin.c:109
static char * stack[MAX_STACK]
Definition: radmin.c:158
static int cmd_test(FILE *fp, UNUSED FILE *fp_err, UNUSED void *ctx, UNUSED fr_cmd_info_t const *info)
Definition: radmin.c:770
bool connected
Whether this connection is currently connected.
Definition: radmin.c:113
static bool unbuffered
Definition: radmin.c:136
static int sockfd
Definition: radmin.c:146
char * server
Path or FQDN of server we're connected to.
Definition: radmin.c:108
static NEVER_RETURNS void usage(int status)
Definition: radmin.c:162
static char cmd_buffer[65536]
Definition: radmin.c:157
#define MAX_STACK
Definition: radmin.c:155
static ssize_t run_command(int fd, char const *command, char *buffer, size_t bufsize)
Definition: radmin.c:333
static int check_server(CONF_SECTION *subcs, uid_t uid, gid_t gid, char const **file_p, char const **server_p)
Definition: radmin.c:661
fr_cs_buffer_t co
Definition: radmin.c:114
radmin_conn_t * active_conn
Connection to remote entity.
Definition: radmin.c:126
A connection to a server.
Definition: radmin.c:103
Radmin state.
Definition: radmin.c:123
unsigned short uint16_t
Definition: merged_model.c:31
@ FR_TYPE_STRING
String of printable characters.
Definition: merged_model.c:83
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 fr_skip_whitespace(_p)
Skip whitespace ('\t', '\n', '\v', '\f', '\r', ' ')
Definition: misc.h:59
static TALLOC_CTX * autofree
Definition: radclient-ng.c:104
static rc_request_t * current
Definition: radclient-ng.c:97
static bool quiet
Definition: radius1_test.c:71
#define FR_RADMIN_PORT
Definition: radmin.h:38
static char const * name
PUBLIC int snprintf(char *string, size_t length, char *format, va_alist)
Definition: snprintf.c:689
int fr_socket_client_tcp(char const *ifname, fr_ipaddr_t *src_ipaddr, fr_ipaddr_t const *dst_ipaddr, uint16_t dst_port, bool async)
Establish a connected TCP socket.
Definition: socket.c:729
int fr_socket_client_unix(UNUSED char const *path, UNUSED bool async)
Definition: socket.c:564
return count
Definition: module.c:175
MEM(pair_append_request(&vp, attr_eap_aka_sim_identity) >=0)
size_t strlcpy(char *dst, char const *src, size_t siz)
Definition: strlcpy.c:34
Definition: log.h:96
fr_log_dst_t dst
Log destination.
Definition: log.h:97
int fd
File descriptor to write messages to.
Definition: log.h:112
char const * file
Path to log file.
Definition: log.h:113
char const * fr_syserror(int num)
Guaranteed to be thread-safe version of strerror.
Definition: syserror.c:243
#define talloc_autofree_context
The original function is deprecated, so replace it with our version.
Definition: talloc.h:51
@ T_DOUBLE_QUOTED_STRING
Definition: token.h:121
close(uq->fd)
static fr_table_ptr_sorted_t commands[]
#define FR_DICTIONARY_FILE
Definition: conf.h:7
#define FR_DICTIONARY_INTERNAL_DIR
Definition: conf.h:8
#define RADIUS_DIR
Definition: conf.h:3
void fr_perror(char const *fmt,...)
Print the current error to stderr with a prefix.
Definition: strerror.c:733
char const * fr_strerror(void)
Get the last library error.
Definition: strerror.c:554
int fr_check_lib_magic(uint64_t magic)
Check if the application linking to the library has the correct magic number.
Definition: version.c:40
#define RADIUSD_VERSION_BUILD(_x)
Create a version string for a utility in the suite of FreeRADIUS utilities.
Definition: version.h:58
#define RADIUSD_MAGIC_NUMBER
Definition: version.h:81
static size_t char ** out
Definition: value.h:984