2 * command.c Command socket processing.
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
20 * Copyright 2008 The FreeRADIUS server project
21 * Copyright 2008 Alan DeKok <aland@deployingradius.com>
24 #ifdef WITH_COMMAND_SOCKET
26 #include <freeradius-devel/parser.h>
27 #include <freeradius-devel/md5.h>
28 #include <freeradius-devel/channel.h>
31 #ifdef HAVE_INTTYPES_H
38 #define SUN_LEN(su) (sizeof(*(su)) - sizeof((su)->sun_path) + strlen((su)->sun_path))
42 #ifdef HAVE_SYS_STAT_H
49 typedef struct fr_command_table_t fr_command_table_t;
51 typedef int (*fr_command_func_t)(rad_listen_t *, int, char *argv[]);
56 #define CMD_FAIL FR_CHANNEL_FAIL
57 #define CMD_OK FR_CHANNEL_SUCCESS
59 struct fr_command_table_t {
61 int mode; /* read/write */
63 fr_command_func_t func;
64 fr_command_table_t *table;
67 #define COMMAND_BUFFER_SIZE (1024)
69 typedef struct fr_cs_buffer_t {
74 char buffer[COMMAND_BUFFER_SIZE];
77 #define COMMAND_SOCKET_MAGIC (0xffdeadee)
78 typedef struct fr_command_socket_t {
81 char *copy; /* <sigh> */
86 char const *mode_name;
91 * The next few entries handle fake packets injected by
94 fr_ipaddr_t src_ipaddr; /* src_port is always 0 */
95 fr_ipaddr_t dst_ipaddr;
97 rad_listen_t *inject_listener;
98 RADCLIENT *inject_client;
101 } fr_command_socket_t;
103 static const CONF_PARSER command_config[] = {
104 { "socket", FR_CONF_OFFSET(PW_TYPE_STRING, fr_command_socket_t, path), "${run_dir}/radiusd.sock" },
105 { "uid", FR_CONF_OFFSET(PW_TYPE_STRING, fr_command_socket_t, uid_name), NULL },
106 { "gid", FR_CONF_OFFSET(PW_TYPE_STRING, fr_command_socket_t, gid_name), NULL },
107 { "mode", FR_CONF_OFFSET(PW_TYPE_STRING, fr_command_socket_t, mode_name), NULL },
108 { "peercred", FR_CONF_OFFSET(PW_TYPE_BOOLEAN, fr_command_socket_t, peercred), "yes" },
109 CONF_PARSER_TERMINATOR
112 static FR_NAME_NUMBER mode_names[] = {
114 { "read-only", FR_READ },
115 { "read-write", FR_READ | FR_WRITE },
116 { "rw", FR_READ | FR_WRITE },
120 #ifndef HAVE_GETPEEREID
121 static int getpeereid(int s, uid_t *euid, gid_t *egid)
127 socklen_t cl = sizeof(cr);
129 if (getsockopt(s, SOL_SOCKET, SO_PEERCRED, &cr, &cl) < 0) {
136 #endif /* SO_PEERCRED */
138 #endif /* HAVE_GETPEEREID */
140 /** Initialise a socket for use with peercred authentication
142 * This function initialises a socket and path in a way suitable for use with
145 * @param path to socket.
146 * @param uid that should own the socket (linux only).
147 * @param gid that should own the socket (linux only).
148 * @return 0 on success -1 on failure.
151 static int fr_server_domain_socket_peercred(char const *path, uid_t uid, gid_t gid)
153 static int fr_server_domain_socket_peercred(char const *path, uid_t UNUSED uid, UNUSED gid_t gid)
159 struct sockaddr_un salocal;
163 fr_strerror_printf("No path provided, was NULL");
168 if (len >= sizeof(salocal.sun_path)) {
169 fr_strerror_printf("Path too long in socket filename");
173 if ((sockfd = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) {
174 fr_strerror_printf("Failed creating socket: %s", fr_syserror(errno));
178 memset(&salocal, 0, sizeof(salocal));
179 salocal.sun_family = AF_UNIX;
180 memcpy(salocal.sun_path, path, len + 1); /* SUN_LEN does strlen */
182 socklen = SUN_LEN(&salocal);
187 if (stat(path, &buf) < 0) {
188 if (errno != ENOENT) {
189 fr_strerror_printf("Failed to stat %s: %s", path, fr_syserror(errno));
195 * FIXME: Check the enclosing directory?
197 } else { /* it exists */
200 if (!S_ISREG(buf.st_mode)
202 && !S_ISSOCK(buf.st_mode)
205 fr_strerror_printf("Cannot turn %s into socket", path);
211 * Refuse to open sockets not owned by us.
213 if (buf.st_uid != geteuid()) {
214 fr_strerror_printf("We do not own %s", path);
220 * Check if a server is already listening on the
223 client_fd = fr_socket_client_unix(path, false);
224 if (client_fd >= 0) {
225 fr_strerror_printf("Control socket '%s' is already in use", path);
231 if (unlink(path) < 0) {
232 fr_strerror_printf("Failed to delete %s: %s", path, fr_syserror(errno));
238 if (bind(sockfd, (struct sockaddr *)&salocal, socklen) < 0) {
239 fr_strerror_printf("Failed binding to %s: %s", path, fr_syserror(errno));
245 * FIXME: There's a race condition here. But Linux
246 * doesn't seem to permit fchmod on domain sockets.
248 if (chmod(path, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP) < 0) {
249 fr_strerror_printf("Failed setting permissions on %s: %s", path, fr_syserror(errno));
254 if (listen(sockfd, 8) < 0) {
255 fr_strerror_printf("Failed listening to %s: %s", path, fr_syserror(errno));
264 if ((flags = fcntl(sockfd, F_GETFL, NULL)) < 0) {
265 fr_strerror_printf("Failure getting socket flags: %s", fr_syserror(errno));
271 if( fcntl(sockfd, F_SETFL, flags) < 0) {
272 fr_strerror_printf("Failure setting socket flags: %s", fr_syserror(errno));
280 * Changing socket permissions only works on linux.
281 * BSDs ignore socket permissions.
285 * Don't chown it from (possibly) non-root to root.
286 * Do chown it from (possibly) root to non-root.
288 if ((uid != (uid_t) -1) || (gid != (gid_t) -1)) {
290 * Don't do chown if it's already owned by us.
292 if (fstat(sockfd, &buf) < 0) {
293 fr_strerror_printf("Failed reading %s: %s", path, fr_syserror(errno));
298 if ((buf.st_uid != uid) || (buf.st_gid != gid)) {
300 if (fchown(sockfd, uid, gid) < 0) {
301 fr_strerror_printf("Failed setting ownership of %s to (%d, %d): %s",
302 path, uid, gid, fr_syserror(errno));
315 #if !defined(HAVE_OPENAT) || !defined(HAVE_MKDIRAT) || !defined(HAVE_UNLINKAT)
316 static int fr_server_domain_socket_perm(UNUSED char const *path, UNUSED uid_t uid, UNUSED gid_t gid)
318 fr_strerror_printf("Unable to initialise control socket. Set peercred = yes or update to "
319 "POSIX-2008 compliant libc");
323 /** Alternative function for creating Unix domain sockets and enforcing permissions
325 * Unlike fr_server_unix_socket which is intended to be used with peercred auth
326 * this function relies on the file system to enforce access.
328 * The way it does this depends on the operating system. On Linux systems permissions
329 * can be set on the socket directly and the system will enforce them.
331 * On most other systems fchown and fchmod fail when called with socket descriptors,
332 * and although permissions can be changed in other ways, they're not enforced.
334 * For these systems we use the permissions on the parent directory to enforce
335 * permissions on the socket. It's not safe to modify these permissions ourselves
336 * due to TOCTOU attacks, so if they don't match what we require, we error out and
337 * get the user to change them (which arguably isn't any safer, but releases us of
338 * the responsibility).
340 * @note must be called without effective root permissions (fr_suid_down).
342 * @param path where domain socket should be created.
343 * @return a file descriptor for the bound socket on success, -1 on failure.
345 static int fr_server_domain_socket_perm(char const *path, uid_t uid, gid_t gid)
347 int dir_fd = -1, path_fd = -1, sock_fd = -1, parent_fd = -1;
349 char *buff = NULL, *dir = NULL, *p;
360 struct sockaddr_un salocal;
368 * Determine the correct permissions for the socket, or its
369 * containing directory.
371 perm |= S_IREAD | S_IWRITE | S_IEXEC;
372 if (gid != (gid_t) -1) perm |= S_IRGRP | S_IWGRP | S_IXGRP;
374 buff = talloc_strdup(NULL, path);
375 if (!buff) return -1;
378 * Some implementations modify it in place others use internal
379 * storage *sigh*. dirname also formats the path else we wouldn't
384 dir = talloc_strdup(NULL, dir);
389 p = strrchr(dir, FR_DIR_SEP);
391 fr_strerror_printf("Failed determining parent directory");
402 * Ensure the parent of the control socket directory exists,
403 * and the euid we're running under has access to it.
405 parent_fd = open(dir, O_DIRECTORY);
410 if (rad_getpwuid(NULL, &user, euid) < 0) goto error;
411 if (rad_getgrgid(NULL, &group, egid) < 0) {
415 fr_strerror_printf("Can't open directory \"%s\": %s. Must be created manually, or modified, "
416 "with permissions that allow writing by user %s or group %s", dir,
417 user->pw_name, group->gr_name, fr_syserror(errno));
425 dir_fd = openat(parent_fd, p + 1, O_NOFOLLOW | O_DIRECTORY);
429 if (errno != ENOENT) {
430 fr_strerror_printf("Failed opening control socket directory: %s", fr_syserror(errno));
435 * This fails if the radius user can't write
436 * to the parent directory.
438 if (mkdirat(parent_fd, p + 1, 0700) < 0) {
439 fr_strerror_printf("Failed creating control socket directory: %s", fr_syserror(errno));
443 dir_fd = openat(parent_fd, p + 1, O_NOFOLLOW | O_DIRECTORY);
445 fr_strerror_printf("Failed opening the control socket directory we created: %s",
449 if (fchmod(dir_fd, perm) < 0) {
450 fr_strerror_printf("Failed setting permissions on control socket directory: %s",
456 if ((uid != (uid_t)-1) || (gid != (gid_t)-1)) ret = fchown(dir_fd, uid, gid);
459 fr_strerror_printf("Failed changing ownership of control socket directory: %s",
464 * Control socket dir already exists, but we still need to
465 * check the permissions are what we expect.
471 ret = fstat(dir_fd, &st);
473 fr_strerror_printf("Failed checking permissions of control socket directory: %s",
478 if ((uid != (uid_t)-1) && (st.st_uid != uid)) {
479 struct passwd *need_user, *have_user;
481 if (rad_getpwuid(NULL, &need_user, uid) < 0) goto error;
482 if (rad_getpwuid(NULL, &have_user, st.st_uid) < 0) {
483 talloc_free(need_user);
486 fr_strerror_printf("Control socket directory must be owned by user %s, "
487 "currently owned by %s", need_user->pw_name, have_user->pw_name);
488 talloc_free(need_user);
489 talloc_free(have_user);
493 if ((gid != (gid_t)-1) && (st.st_gid != gid)) {
494 struct group *need_group, *have_group;
496 if (rad_getgrgid(NULL, &need_group, gid) < 0) goto error;
497 if (rad_getgrgid(NULL, &have_group, st.st_gid) < 0) {
498 talloc_free(need_group);
501 fr_strerror_printf("Control socket directory \"%s\" must be owned by group %s, "
502 "currently owned by %s", dir, need_group->gr_name, have_group->gr_name);
503 talloc_free(need_group);
504 talloc_free(have_group);
508 if ((perm & 0x0c) != (st.st_mode & 0x0c)) {
509 char str_need[10], oct_need[5];
510 char str_have[10], oct_have[5];
512 rad_mode_to_str(str_need, perm);
513 rad_mode_to_oct(oct_need, perm);
514 rad_mode_to_str(str_have, st.st_mode);
515 rad_mode_to_oct(oct_have, st.st_mode);
516 fr_strerror_printf("Control socket directory must have permissions %s (%s), current "
517 "permissions are %s (%s)", str_need, oct_need, str_have, oct_have);
522 * Check if a server is already listening on the
525 client_fd = fr_socket_client_unix(path, false);
526 if (client_fd >= 0) {
527 fr_strerror_printf("Control socket '%s' is already in use", path);
533 name = strrchr(path, FR_DIR_SEP);
535 fr_strerror_printf("Can't determine socket name");
541 * We've checked the containing directory has the permissions
542 * we expect, and as we have the FD, and aren't following
543 * symlinks no one can trick us into changing or creating a
546 * It's possible an attacker may still be able to create hard
547 * links, for the socket file. But they would need write
548 * access to the directory we just created or verified, so
549 * this attack vector is unlikely.
551 if ((uid != (uid_t)-1) && (rad_seuid(uid) < 0)) goto error;
552 if ((gid != (gid_t)-1) && (rad_segid(gid) < 0)) {
558 * The original code, did openat, used fstat to figure out
559 * what type the file was and then used unlinkat to unlink
560 * it. Except on OSX (at least) openat refuses to open
561 * socket files. So we now rely on the fact that unlinkat
562 * has sane and consistent behaviour, and will not unlink
563 * directories. unlinkat should also fail if the socket user
564 * hasn't got permission to modify the socket.
566 if ((unlinkat(dir_fd, name, 0) < 0) && (errno != ENOENT)) {
567 fr_strerror_printf("Failed removing stale socket: %s", fr_syserror(errno));
569 if (uid != (uid_t)-1) rad_seuid(euid);
570 if (gid != (gid_t)-1) rad_segid(egid);
577 * At this point we should have established a secure directory
578 * to house our socket, and cleared out any stale sockets.
580 sock_fd = socket(AF_UNIX, SOCK_STREAM, 0);
582 fr_strerror_printf("Failed creating socket: %s", fr_syserror(errno));
591 if (len >= sizeof(salocal.sun_path)) {
592 fr_strerror_printf("Path too long in socket filename");
596 memset(&salocal, 0, sizeof(salocal));
597 salocal.sun_family = AF_UNIX;
600 memcpy(salocal.sun_path, name, len + 1); /* SUN_LEN does strlen */
602 memcpy(salocal.sun_path, path, len + 1); /* SUN_LEN does strlen */
604 socklen = SUN_LEN(&salocal);
607 * Direct socket permissions are only useful on Linux which
608 * actually enforces them. BSDs don't. They also need to be
609 * set before binding the socket to a file.
612 if (fchmod(sock_fd, perm) < 0) {
613 char str_need[10], oct_need[5];
615 rad_mode_to_str(str_need, perm);
616 rad_mode_to_oct(oct_need, perm);
617 fr_strerror_printf("Failed changing socket permissions to %s (%s)", str_need, oct_need);
622 if (fchown(sock_fd, uid, gid) < 0) {
626 if (rad_getpwuid(NULL, &user, uid) < 0) goto sock_error;
627 if (rad_getgrgid(NULL, &group, gid) < 0) {
632 fr_strerror_printf("Failed changing ownership of socket to %s:%s", user->pw_name, group->gr_name);
639 * The correct function to use here is bindat(), but only
640 * quite recent versions of FreeBSD actually have it, and
641 * it's definitely not POSIX.
644 if (bindat(dir_fd, sock_fd, (struct sockaddr *)&salocal, socklen) < 0) {
646 if (bind(sock_fd, (struct sockaddr *)&salocal, socklen) < 0) {
648 fr_strerror_printf("Failed binding socket: %s", fr_syserror(errno));
652 if (listen(sock_fd, 8) < 0) {
653 fr_strerror_printf("Failed listening on socket: %s", fr_syserror(errno));
661 flags = fcntl(sock_fd, F_GETFL, NULL);
663 fr_strerror_printf("Failed getting socket flags: %s", fr_syserror(errno));
668 if (fcntl(sock_fd, F_SETFL, flags) < 0) {
669 fr_strerror_printf("Failed setting nonblocking socket flag: %s", fr_syserror(errno));
675 if (uid != (uid_t)-1) rad_seuid(euid);
676 if (gid != (gid_t)-1) rad_segid(egid);
685 static void command_close_socket(rad_listen_t *this)
687 this->status = RAD_LISTEN_STATUS_EOL;
690 * This removes the socket from the event fd, so no one
691 * will be calling us any more.
693 radius_update_listener(this);
696 static ssize_t CC_HINT(format (printf, 2, 3)) cprintf(rad_listen_t *listener, char const *fmt, ...)
703 len = vsnprintf(buffer, sizeof(buffer), fmt, ap);
706 if (listener->status == RAD_LISTEN_STATUS_EOL) return 0;
708 r = fr_channel_write(listener->fd, FR_CHANNEL_STDOUT, buffer, len);
709 if (r <= 0) command_close_socket(listener);
712 * FIXME: Keep writing until done?
717 static ssize_t CC_HINT(format (printf, 2, 3)) cprintf_error(rad_listen_t *listener, char const *fmt, ...)
724 len = vsnprintf(buffer, sizeof(buffer), fmt, ap);
727 if (listener->status == RAD_LISTEN_STATUS_EOL) return 0;
729 r = fr_channel_write(listener->fd, FR_CHANNEL_STDERR, buffer, len);
730 if (r <= 0) command_close_socket(listener);
733 * FIXME: Keep writing until done?
738 static int command_hup(rad_listen_t *listener, int argc, char *argv[])
741 module_instance_t *mi;
745 radius_signal_self(RADIUS_SIGNAL_SELF_HUP);
750 * Hack a "main" HUP thingy
752 if (strcmp(argv[0], "main.log") == 0) {
757 cs = cf_section_find("modules");
758 if (!cs) return CMD_FAIL;
760 mi = module_find(cs, argv[0]);
762 cprintf_error(listener, "No such module \"%s\"\n", argv[0]);
766 if ((mi->entry->module->type & RLM_TYPE_HUP_SAFE) == 0) {
767 cprintf_error(listener, "Module %s cannot be hup'd\n",
772 if (!module_hup_module(mi->cs, mi, time(NULL))) {
773 cprintf_error(listener, "Failed to reload module\n");
777 snprintf(buffer, sizeof(buffer), "modules.%s.hup",
778 cf_section_name1(mi->cs));
779 exec_trigger(NULL, mi->cs, buffer, true);
784 static int command_terminate(UNUSED rad_listen_t *listener,
785 UNUSED int argc, UNUSED char *argv[])
787 radius_signal_self(RADIUS_SIGNAL_SELF_TERM);
792 static int command_uptime(rad_listen_t *listener,
793 UNUSED int argc, UNUSED char *argv[])
797 CTIME_R(&fr_start_time, buffer, sizeof(buffer));
798 cprintf(listener, "Up since %s", buffer); /* no \r\n */
803 static int command_show_config(rad_listen_t *listener, int argc, char *argv[])
810 cprintf_error(listener, "No path was given\n");
814 ci = cf_reference_item(main_config.config, main_config.config, argv[0]);
815 if (!ci) return CMD_FAIL;
817 if (!cf_item_is_pair(ci)) return CMD_FAIL;
819 cp = cf_item_to_pair(ci);
820 value = cf_pair_value(cp);
821 if (!value) return CMD_FAIL;
823 cprintf(listener, "%s\n", value);
828 static char const tabs[] = "\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t";
831 * FIXME: Recurse && indent?
833 static void cprint_conf_parser(rad_listen_t *listener, int indent, CONF_SECTION *cs,
838 char const *name1 = cf_section_name1(cs);
839 char const *name2 = cf_section_name2(cs);
840 CONF_PARSER const *variables = cf_section_parse_table(cs);
843 cprintf(listener, "%.*s%s %s {\n", indent, tabs, name1, name2);
845 cprintf(listener, "%.*s%s {\n", indent, tabs, name1);
853 if (variables) for (i = 0; variables[i].name != NULL; i++) {
858 * No base struct offset, data must be the pointer.
859 * If data doesn't exist, ignore the entry, there
860 * must be something wrong.
863 if (!variables[i].data) {
867 data = variables[i].data;
869 } else if (variables[i].data) {
870 data = variables[i].data;
873 data = (((char const *)base) + variables[i].offset);
877 * Ignore the various flags
879 switch (variables[i].type & 0xff) {
881 cprintf(listener, "%.*s%s = ?\n", indent, tabs,
885 case PW_TYPE_INTEGER:
886 cprintf(listener, "%.*s%s = %u\n", indent, tabs,
887 variables[i].name, *(int const *) data);
890 case PW_TYPE_IPV4_ADDR:
891 inet_ntop(AF_INET, data, buffer, sizeof(buffer));
894 case PW_TYPE_IPV6_ADDR:
895 inet_ntop(AF_INET6, data, buffer, sizeof(buffer));
898 case PW_TYPE_BOOLEAN:
899 cprintf(listener, "%.*s%s = %s\n", indent, tabs,
901 ((*(bool const *) data) == false) ? "no" : "yes");
905 case PW_TYPE_FILE_INPUT:
906 case PW_TYPE_FILE_OUTPUT:
908 * FIXME: Escape things in the string!
910 if (*(char const * const *) data) {
911 cprintf(listener, "%.*s%s = \"%s\"\n", indent, tabs,
912 variables[i].name, *(char const * const *) data);
914 cprintf(listener, "%.*s%s = \n", indent, tabs,
924 cprintf(listener, "%.*s}\n", indent, tabs);
927 static int command_show_module_config(rad_listen_t *listener, int argc, char *argv[])
930 module_instance_t *mi;
933 cprintf_error(listener, "No module name was given\n");
937 cs = cf_section_find("modules");
938 if (!cs) return CMD_FAIL;
940 mi = module_find(cs, argv[0]);
942 cprintf_error(listener, "No such module \"%s\"\n", argv[0]);
946 cprint_conf_parser(listener, 0, mi->cs, mi->insthandle);
951 static char const *method_names[MOD_COUNT] = {
963 static int command_show_module_methods(rad_listen_t *listener, int argc, char *argv[])
967 module_instance_t const *mi;
971 cprintf_error(listener, "No module name was given\n");
975 cs = cf_section_find("modules");
976 if (!cs) return CMD_FAIL;
978 mi = module_find(cs, argv[0]);
980 cprintf_error(listener, "No such module \"%s\"\n", argv[0]);
984 mod = mi->entry->module;
986 for (i = 0; i < MOD_COUNT; i++) {
987 if (mod->methods[i]) cprintf(listener, "%s\n", method_names[i]);
994 static int command_show_module_flags(rad_listen_t *listener, int argc, char *argv[])
997 module_instance_t const *mi;
1001 cprintf_error(listener, "No module name was given\n");
1005 cs = cf_section_find("modules");
1006 if (!cs) return CMD_FAIL;
1008 mi = module_find(cs, argv[0]);
1010 cprintf_error(listener, "No such module \"%s\"\n", argv[0]);
1014 mod = mi->entry->module;
1016 if ((mod->type & RLM_TYPE_THREAD_UNSAFE) != 0)
1017 cprintf(listener, "thread-unsafe\n");
1019 if ((mod->type & RLM_TYPE_HUP_SAFE) != 0)
1020 cprintf(listener, "reload-on-hup\n");
1025 static int command_show_module_status(rad_listen_t *listener, int argc, char *argv[])
1028 const module_instance_t *mi;
1031 cprintf_error(listener, "No module name was given\n");
1035 cs = cf_section_find("modules");
1036 if (!cs) return CMD_FAIL;
1038 mi = module_find(cs, argv[0]);
1040 cprintf_error(listener, "No such module \"%s\"\n", argv[0]);
1045 cprintf(listener, "alive\n");
1047 cprintf(listener, "%s\n", fr_int2str(mod_rcode_table, mi->code, "<invalid>"));
1056 * Show all loaded modules
1058 static int command_show_modules(rad_listen_t *listener, UNUSED int argc, UNUSED char *argv[])
1060 CONF_SECTION *cs, *subcs;
1062 cs = cf_section_find("modules");
1063 if (!cs) return CMD_FAIL;
1066 while ((subcs = cf_subsection_find_next(cs, subcs, NULL)) != NULL) {
1067 char const *name1 = cf_section_name1(subcs);
1068 char const *name2 = cf_section_name2(subcs);
1070 module_instance_t *mi;
1073 mi = module_find(cs, name2);
1076 cprintf(listener, "%s (%s)\n", name2, name1);
1078 mi = module_find(cs, name1);
1081 cprintf(listener, "%s\n", name1);
1089 static int command_show_home_servers(rad_listen_t *listener, UNUSED int argc, UNUSED char *argv[])
1092 home_server_t *home;
1093 char const *type, *state, *proto;
1097 for (i = 0; i < 256; i++) {
1098 home = home_server_bynumber(i);
1102 * Internal "virtual" home server.
1104 if (home->ipaddr.af == AF_UNSPEC) continue;
1106 if (home->type == HOME_TYPE_AUTH) {
1109 } else if (home->type == HOME_TYPE_ACCT) {
1112 } else if (home->type == HOME_TYPE_AUTH_ACCT) {
1116 } else if (home->type == HOME_TYPE_COA) {
1122 if (home->proto == IPPROTO_UDP) {
1126 else if (home->proto == IPPROTO_TCP) {
1132 if (home->state == HOME_STATE_ALIVE) {
1135 } else if (home->state == HOME_STATE_ZOMBIE) {
1138 } else if (home->state == HOME_STATE_IS_DEAD) {
1141 } else if (home->state == HOME_STATE_UNKNOWN) {
1142 time_t now = time(NULL);
1145 * We've recently received a packet, so
1146 * the home server seems to be alive.
1148 * The *reported* state changes because
1149 * the internal state machine NEEDS THE
1150 * RIGHT STATE. However, reporting that
1151 * to the admin will confuse them.
1152 * So... we lie. No, that dress doesn't
1153 * make you look fat...
1155 if ((home->last_packet_recv + (int)home->ping_interval) >= now) {
1163 cprintf(listener, "%s\t%d\t%s\t%s\t%s\t%d\n",
1164 ip_ntoh(&home->ipaddr, buffer, sizeof(buffer)),
1165 home->port, proto, type, state,
1166 home->currently_outstanding);
1173 static int command_show_clients(rad_listen_t *listener, UNUSED int argc, UNUSED char *argv[])
1179 for (i = 0; i < 256; i++) {
1180 client = client_findbynumber(NULL, i);
1183 ip_ntoh(&client->ipaddr, buffer, sizeof(buffer));
1185 if (((client->ipaddr.af == AF_INET) &&
1186 (client->ipaddr.prefix != 32)) ||
1187 ((client->ipaddr.af == AF_INET6) &&
1188 (client->ipaddr.prefix != 128))) {
1189 cprintf(listener, "%s/%d\n", buffer, client->ipaddr.prefix);
1191 cprintf(listener, "%s\n", buffer);
1199 static int command_show_version(rad_listen_t *listener, UNUSED int argc, UNUSED char *argv[])
1201 cprintf(listener, "%s\n", radiusd_version);
1205 static int command_debug_level(rad_listen_t *listener, int argc, char *argv[])
1210 cprintf_error(listener, "Must specify <number>\n");
1214 number = atoi(argv[0]);
1215 if ((number < 0) || (number > 4)) {
1216 cprintf_error(listener, "<number> must be between 0 and 4\n");
1220 fr_debug_lvl = rad_debug_lvl = number;
1225 static char debug_log_file_buffer[1024];
1227 static int command_debug_file(rad_listen_t *listener, int argc, char *argv[])
1229 if (rad_debug_lvl && default_log.dst == L_DST_STDOUT) {
1230 cprintf_error(listener, "Cannot redirect debug logs to a file when already in debugging mode.\n");
1234 if ((argc > 0) && (strchr(argv[0], FR_DIR_SEP) != NULL)) {
1235 cprintf_error(listener, "Cannot direct debug logs to absolute path.\n");
1238 default_log.debug_file = NULL;
1240 if (argc == 0) return CMD_OK;
1243 * This looks weird, but it's here to avoid locking
1244 * a mutex for every log message.
1246 memset(debug_log_file_buffer, 0, sizeof(debug_log_file_buffer));
1249 * Debug files always go to the logging directory.
1251 snprintf(debug_log_file_buffer, sizeof(debug_log_file_buffer),
1252 "%s/%s", radlog_dir, argv[0]);
1254 default_log.debug_file = &debug_log_file_buffer[0];
1259 extern fr_cond_t *debug_condition;
1260 static int command_debug_condition(rad_listen_t *listener, int argc, char *argv[])
1265 fr_cond_t *new_condition = NULL;
1266 char *p, buffer[1024];
1272 TALLOC_FREE(debug_condition);
1273 debug_condition = NULL;
1277 if (!((argc == 1) &&
1278 ((argv[0][0] == '"') || (argv[0][0] == '\'')))) {
1281 for (i = 0; i < argc; i++) {
1284 len = strlcpy(p, argv[i], buffer + sizeof(buffer) - p);
1292 * Backwards compatibility. De-escape the string.
1304 error = "Unexpected end of string";
1305 slen = -strlen(argv[0]);
1313 error = "Unexpected text after end of string";
1314 slen = -(p - argv[0]);
1335 slen = fr_condition_tokenize(NULL, NULL, p, &new_condition, &error, FR_COND_ONE_PASS);
1337 char *spaces, *text;
1340 fr_canonicalize_error(NULL, &spaces, &text, slen, p);
1342 ERROR("Parse error in condition");
1344 ERROR("%s^ %s", spaces, error);
1346 cprintf_error(listener, "Parse error in condition \"%s\": %s\n", p, error);
1348 talloc_free(spaces);
1354 * Delete old condition.
1356 * This is thread-safe because the condition is evaluated
1357 * in the main server thread, along with this code.
1359 TALLOC_FREE(debug_condition);
1360 debug_condition = new_condition;
1365 static int command_show_debug_condition(rad_listen_t *listener,
1366 UNUSED int argc, UNUSED char *argv[])
1370 if (!debug_condition) {
1371 cprintf(listener, "\n");
1375 fr_cond_sprint(buffer, sizeof(buffer), debug_condition);
1377 cprintf(listener, "%s\n", buffer);
1382 static int command_show_debug_file(rad_listen_t *listener,
1383 UNUSED int argc, UNUSED char *argv[])
1385 if (!default_log.debug_file) return CMD_FAIL;
1387 cprintf(listener, "%s\n", default_log.debug_file);
1392 static int command_show_debug_level(rad_listen_t *listener,
1393 UNUSED int argc, UNUSED char *argv[])
1395 cprintf(listener, "%d\n", rad_debug_lvl);
1400 static RADCLIENT *get_client(rad_listen_t *listener, int argc, char *argv[])
1405 int proto = IPPROTO_UDP;
1406 RADCLIENT_LIST *list = NULL;
1409 cprintf_error(listener, "Must specify <ipaddr>\n");
1414 * First arg is IP address.
1416 if (ip_hton(&ipaddr, AF_UNSPEC, argv[0], false) < 0) {
1417 cprintf_error(listener, "Failed parsing IP address; %s\n",
1423 while (myarg < argc) {
1424 if (strcmp(argv[myarg], "udp") == 0) {
1425 proto = IPPROTO_UDP;
1431 if (strcmp(argv[myarg], "tcp") == 0) {
1432 proto = IPPROTO_TCP;
1438 if (strcmp(argv[myarg], "listen") == 0) {
1439 uint16_t server_port;
1440 fr_ipaddr_t server_ipaddr;
1442 if ((argc - myarg) < 2) {
1443 cprintf_error(listener, "Must specify listen <ipaddr> <port>\n");
1447 if (ip_hton(&server_ipaddr, ipaddr.af, argv[myarg + 1], false) < 0) {
1448 cprintf_error(listener, "Failed parsing IP address; %s\n",
1453 server_port = atoi(argv[myarg + 2]);
1455 list = listener_find_client_list(&server_ipaddr, server_port, proto);
1457 cprintf_error(listener, "No such listener %s %s\n", argv[myarg + 1], argv[myarg + 2]);
1464 cprintf_error(listener, "Unknown argument %s.\n", argv[myarg]);
1468 client = client_find(list, &ipaddr, proto);
1470 cprintf_error(listener, "No such client\n");
1478 static home_server_t *get_home_server(rad_listen_t *listener, int argc,
1479 char *argv[], int *last)
1482 home_server_t *home;
1484 int proto = IPPROTO_UDP;
1488 cprintf_error(listener, "Must specify <ipaddr> <port> [udp|tcp]\n");
1492 if (ip_hton(&ipaddr, AF_UNSPEC, argv[0], false) < 0) {
1493 cprintf_error(listener, "Failed parsing IP address; %s\n",
1498 port = atoi(argv[1]);
1502 while (myarg < argc) {
1503 if (strcmp(argv[myarg], "udp") == 0) {
1504 proto = IPPROTO_UDP;
1510 if (strcmp(argv[myarg], "tcp") == 0) {
1511 proto = IPPROTO_TCP;
1518 * Unknown argument. Leave it for the caller.
1523 home = home_server_find(&ipaddr, port, proto);
1525 cprintf_error(listener, "No such home server\n");
1529 if (last) *last = myarg;
1534 static int command_set_home_server_state(rad_listen_t *listener, int argc, char *argv[])
1537 home_server_t *home;
1540 cprintf_error(listener, "Must specify <ipaddr> <port> [udp|tcp] <state>\n");
1544 home = get_home_server(listener, argc, argv, &last);
1549 if (strcmp(argv[last], "alive") == 0) {
1550 revive_home_server(home);
1552 } else if (strcmp(argv[last], "dead") == 0) {
1555 gettimeofday(&now, NULL); /* we do this WAY too ofetn */
1556 mark_home_server_dead(home, &now);
1559 cprintf_error(listener, "Unknown state \"%s\"\n", argv[last]);
1566 static int command_show_home_server_state(rad_listen_t *listener, int argc, char *argv[])
1568 home_server_t *home;
1570 home = get_home_server(listener, argc, argv, NULL);
1571 if (!home) return CMD_FAIL;
1573 switch (home->state) {
1574 case HOME_STATE_ALIVE:
1575 cprintf(listener, "alive\n");
1578 case HOME_STATE_IS_DEAD:
1579 cprintf(listener, "dead\n");
1582 case HOME_STATE_ZOMBIE:
1583 cprintf(listener, "zombie\n");
1586 case HOME_STATE_UNKNOWN:
1587 cprintf(listener, "unknown\n");
1591 cprintf(listener, "invalid\n");
1600 * For encode/decode stuff
1602 static int null_socket_dencode(UNUSED rad_listen_t *listener, UNUSED REQUEST *request)
1607 static int null_socket_send(UNUSED rad_listen_t *listener, REQUEST *request)
1613 output_file = request_data_reference(request, (void *)null_socket_send, 0);
1615 ERROR("No output file for injected packet %d", request->number);
1619 fp = fopen(output_file, "w");
1621 ERROR("Failed to send injected file to %s: %s", output_file, fr_syserror(errno));
1625 if (request->reply->code != 0) {
1626 char const *what = "reply";
1630 if (request->reply->code < FR_MAX_PACKET_CODE) {
1631 what = fr_packet_codes[request->reply->code];
1634 fprintf(fp, "%s\n", what);
1636 if (rad_debug_lvl) {
1637 RDEBUG("Injected %s packet to host %s port 0 code=%d, id=%d", what,
1638 inet_ntop(request->reply->src_ipaddr.af,
1639 &request->reply->src_ipaddr.ipaddr,
1640 buffer, sizeof(buffer)),
1641 request->reply->code, request->reply->id);
1645 for (vp = fr_cursor_init(&cursor, &request->reply->vps);
1647 vp = fr_cursor_next(&cursor)) {
1648 vp_prints(buffer, sizeof(buffer), vp);
1649 fprintf(fp, "%s\n", buffer);
1650 RDEBUG("%s", buffer);
1659 static rad_listen_t *get_socket(rad_listen_t *listener, int argc,
1660 char *argv[], int *last)
1664 int proto = IPPROTO_UDP;
1668 cprintf_error(listener, "Must specify <ipaddr> <port> [udp|tcp]\n");
1672 if (ip_hton(&ipaddr, AF_UNSPEC, argv[0], false) < 0) {
1673 cprintf_error(listener, "Failed parsing IP address; %s\n",
1678 port = atoi(argv[1]);
1680 if (last) *last = 2;
1682 if (strcmp(argv[2], "udp") == 0) {
1683 proto = IPPROTO_UDP;
1684 if (last) *last = 3;
1687 if (strcmp(argv[2], "tcp") == 0) {
1688 proto = IPPROTO_TCP;
1689 if (last) *last = 3;
1694 sock = listener_find_byipaddr(&ipaddr, port, proto);
1696 cprintf_error(listener, "No such listen section\n");
1704 static int command_inject_to(rad_listen_t *listener, int argc, char *argv[])
1706 fr_command_socket_t *sock = listener->data;
1707 listen_socket_t *data;
1708 rad_listen_t *found;
1710 found = get_socket(listener, argc, argv, NULL);
1716 sock->inject_listener = found;
1717 sock->dst_ipaddr = data->my_ipaddr;
1718 sock->dst_port = data->my_port;
1723 static int command_inject_from(rad_listen_t *listener, int argc, char *argv[])
1726 fr_command_socket_t *sock = listener->data;
1729 cprintf_error(listener, "No <ipaddr> was given\n");
1733 if (!sock->inject_listener) {
1734 cprintf_error(listener, "You must specify \"inject to\" before using \"inject from\"\n");
1738 sock->src_ipaddr.af = AF_UNSPEC;
1739 if (ip_hton(&sock->src_ipaddr, AF_UNSPEC, argv[0], false) < 0) {
1740 cprintf_error(listener, "Failed parsing IP address; %s\n",
1745 client = client_listener_find(sock->inject_listener, &sock->src_ipaddr,
1748 cprintf_error(listener, "No such client %s\n", argv[0]);
1751 sock->inject_client = client;
1756 static int command_inject_file(rad_listen_t *listener, int argc, char *argv[])
1758 static int inject_id = 0;
1761 fr_command_socket_t *sock = listener->data;
1763 RADIUS_PACKET *packet;
1767 RAD_REQUEST_FUNP fun = NULL;
1771 cprintf_error(listener, "You must specify <input-file> <output-file>\n");
1775 if (!sock->inject_listener) {
1776 cprintf_error(listener, "You must specify \"inject to\" before using \"inject file\"\n");
1780 if (!sock->inject_client) {
1781 cprintf_error(listener, "You must specify \"inject from\" before using \"inject file\"\n");
1786 * Output files always go to the logging directory.
1788 snprintf(buffer, sizeof(buffer), "%s/%s", radlog_dir, argv[1]);
1790 fp = fopen(argv[0], "r");
1792 cprintf_error(listener, "Failed opening %s: %s\n",
1793 argv[0], fr_syserror(errno));
1797 ret = fr_pair_list_afrom_file(NULL, &vp, fp, &filedone);
1800 cprintf_error(listener, "Failed reading attributes from %s: %s\n",
1801 argv[0], fr_strerror());
1805 fake = talloc(NULL, rad_listen_t);
1806 memcpy(fake, sock->inject_listener, sizeof(*fake));
1809 * Re-write the IO for the listener.
1811 fake->encode = null_socket_dencode;
1812 fake->decode = null_socket_dencode;
1813 fake->send = null_socket_send;
1815 packet = rad_alloc(NULL, false);
1816 packet->src_ipaddr = sock->src_ipaddr;
1817 packet->src_port = 0;
1819 packet->dst_ipaddr = sock->dst_ipaddr;
1820 packet->dst_port = sock->dst_port;
1822 packet->id = inject_id++;
1824 if (fake->type == RAD_LISTEN_AUTH) {
1825 packet->code = PW_CODE_ACCESS_REQUEST;
1826 fun = rad_authenticate;
1829 #ifdef WITH_ACCOUNTING
1830 packet->code = PW_CODE_ACCOUNTING_REQUEST;
1831 fun = rad_accounting;
1833 cprintf_error(listener, "This server was built without accounting support.\n");
1840 if (rad_debug_lvl) {
1841 DEBUG("Injecting %s packet from host %s port 0 code=%d, id=%d",
1842 fr_packet_codes[packet->code],
1843 inet_ntop(packet->src_ipaddr.af,
1844 &packet->src_ipaddr.ipaddr,
1845 buffer, sizeof(buffer)),
1846 packet->code, packet->id);
1848 for (vp = fr_cursor_init(&cursor, &packet->vps);
1850 vp = fr_cursor_next(&cursor)) {
1851 vp_prints(buffer, sizeof(buffer), vp);
1852 DEBUG("\t%s", buffer);
1855 WARN("INJECTION IS LEAKING MEMORY!");
1858 if (!request_receive(NULL, fake, packet, sock->inject_client, fun)) {
1859 cprintf_error(listener, "Failed to inject request. See log file for details\n");
1867 * Remember what the output file is, and remember to
1868 * delete the fake listener when done.
1870 request_data_add(request, null_socket_send, 0, talloc_typed_strdup(NULL, buffer), true);
1871 request_data_add(request, null_socket_send, 1, fake, true);
1879 static fr_command_table_t command_table_inject[] = {
1881 "inject to <ipaddr> <port> - Inject packets to the destination IP and port.",
1882 command_inject_to, NULL },
1885 "inject from <ipaddr> - Inject packets as if they came from <ipaddr>",
1886 command_inject_from, NULL },
1889 "inject file <input-file> <output-file> - Inject packet from <input-file>, with results sent to <output-file>",
1890 command_inject_file, NULL },
1892 { NULL, 0, NULL, NULL, NULL }
1895 static fr_command_table_t command_table_debug[] = {
1896 { "condition", FR_WRITE,
1897 "debug condition [condition] - Enable debugging for requests matching [condition]",
1898 command_debug_condition, NULL },
1900 { "level", FR_WRITE,
1901 "debug level <number> - Set debug level to <number>. Higher is more debugging.",
1902 command_debug_level, NULL },
1905 "debug file [filename] - Send all debugging output to [filename]",
1906 command_debug_file, NULL },
1908 { NULL, 0, NULL, NULL, NULL }
1911 static fr_command_table_t command_table_show_debug[] = {
1912 { "condition", FR_READ,
1913 "show debug condition - Shows current debugging condition.",
1914 command_show_debug_condition, NULL },
1917 "show debug level - Shows current debugging level.",
1918 command_show_debug_level, NULL },
1921 "show debug file - Shows current debugging file.",
1922 command_show_debug_file, NULL },
1924 { NULL, 0, NULL, NULL, NULL }
1927 static fr_command_table_t command_table_show_module[] = {
1928 { "config", FR_READ,
1929 "show module config <module> - show configuration for given module",
1930 command_show_module_config, NULL },
1932 "show module flags <module> - show other module properties",
1933 command_show_module_flags, NULL },
1935 "show module list - shows list of loaded modules",
1936 command_show_modules, NULL },
1937 { "methods", FR_READ,
1938 "show module methods <module> - show sections where <module> may be used",
1939 command_show_module_methods, NULL },
1940 { "status", FR_READ,
1941 "show module status <module> - show the module status",
1942 command_show_module_status, NULL },
1944 { NULL, 0, NULL, NULL, NULL }
1947 static fr_command_table_t command_table_show_client[] = {
1949 "show client list - shows list of global clients",
1950 command_show_clients, NULL },
1952 { NULL, 0, NULL, NULL, NULL }
1956 static fr_command_table_t command_table_show_home[] = {
1958 "show home_server list - shows list of home servers",
1959 command_show_home_servers, NULL },
1961 "show home_server state <ipaddr> <port> [udp|tcp] - shows state of given home server",
1962 command_show_home_server_state, NULL },
1964 { NULL, 0, NULL, NULL, NULL }
1969 static fr_command_table_t command_table_show[] = {
1970 { "client", FR_READ,
1971 "show client <command> - do sub-command of client",
1972 NULL, command_table_show_client },
1973 { "config", FR_READ,
1974 "show config <path> - shows the value of configuration option <path>",
1975 command_show_config, NULL },
1977 "show debug <command> - show debug properties",
1978 NULL, command_table_show_debug },
1980 { "home_server", FR_READ,
1981 "show home_server <command> - do sub-command of home_server",
1982 NULL, command_table_show_home },
1984 { "module", FR_READ,
1985 "show module <command> - do sub-command of module",
1986 NULL, command_table_show_module },
1987 { "uptime", FR_READ,
1988 "show uptime - shows time at which server started",
1989 command_uptime, NULL },
1990 { "version", FR_READ,
1991 "show version - Prints version of the running server",
1992 command_show_version, NULL },
1993 { NULL, 0, NULL, NULL, NULL }
1997 static int command_set_module_config(rad_listen_t *listener, int argc, char *argv[])
2002 module_instance_t *mi;
2003 CONF_PARSER const *variables;
2007 cprintf_error(listener, "No module name or variable was given\n");
2011 cs = cf_section_find("modules");
2014 mi = module_find(cs, argv[0]);
2016 cprintf_error(listener, "No such module \"%s\"\n", argv[0]);
2020 if ((mi->entry->module->type & RLM_TYPE_HUP_SAFE) == 0) {
2021 cprintf_error(listener, "Cannot change configuration of module as it is cannot be HUP'd.\n");
2025 variables = cf_section_parse_table(mi->cs);
2027 cprintf_error(listener, "Cannot find configuration for module\n");
2032 for (i = 0; variables[i].name != NULL; i++) {
2034 * FIXME: Recurse into sub-types somehow...
2036 if (variables[i].type == PW_TYPE_SUBSECTION) continue;
2038 if (strcmp(variables[i].name, argv[1]) == 0) {
2045 cprintf_error(listener, "No such variable \"%s\"\n", argv[1]);
2049 i = rcode; /* just to be safe */
2052 * It's not part of the dynamic configuration. The module
2053 * needs to re-parse && validate things.
2055 if (variables[i].data) {
2056 cprintf_error(listener, "Variable cannot be dynamically updated\n");
2060 data = ((char *) mi->insthandle) + variables[i].offset;
2062 cp = cf_pair_find(mi->cs, argv[1]);
2066 * Replace the OLD value in the configuration file with
2069 * FIXME: Parse argv[2] depending on it's data type!
2070 * If it's a string, look for leading single/double quotes,
2071 * end then call tokenize functions???
2073 cf_pair_replace(mi->cs, cp, argv[2]);
2075 rcode = cf_item_parse(mi->cs, argv[1], variables[i].type, data, argv[2]);
2077 cprintf_error(listener, "Failed to parse value\n");
2084 static int command_set_module_status(rad_listen_t *listener, int argc, char *argv[])
2087 module_instance_t *mi;
2090 cprintf_error(listener, "No module name or status was given\n");
2094 cs = cf_section_find("modules");
2097 mi = module_find(cs, argv[0]);
2099 cprintf_error(listener, "No such module \"%s\"\n", argv[0]);
2104 if (strcmp(argv[1], "alive") == 0) {
2107 } else if (strcmp(argv[1], "dead") == 0) {
2108 mi->code = RLM_MODULE_FAIL;
2114 rcode = fr_str2int(mod_rcode_table, argv[1], -1);
2116 cprintf_error(listener, "Unknown status \"%s\"\n", argv[1]);
2128 static char const *elapsed_names[8] = {
2129 "1us", "10us", "100us", "1ms", "10ms", "100ms", "1s", "10s"
2133 #ifdef WITH_STATS_64BIT
2135 #define PU "%" PRIu64
2141 #define PU "%" PRIu32
2147 static int command_print_stats(rad_listen_t *listener, fr_stats_t *stats,
2148 int auth, int server)
2152 cprintf(listener, "requests\t" PU "\n", stats->total_requests);
2153 cprintf(listener, "responses\t" PU "\n", stats->total_responses);
2156 cprintf(listener, "accepts\t\t" PU "\n",
2157 stats->total_access_accepts);
2158 cprintf(listener, "rejects\t\t" PU "\n",
2159 stats->total_access_rejects);
2160 cprintf(listener, "challenges\t" PU "\n",
2161 stats->total_access_challenges);
2164 cprintf(listener, "dup\t\t" PU "\n", stats->total_dup_requests);
2165 cprintf(listener, "invalid\t\t" PU "\n", stats->total_invalid_requests);
2166 cprintf(listener, "malformed\t" PU "\n", stats->total_malformed_requests);
2167 cprintf(listener, "bad_authenticator\t" PU "\n", stats->total_bad_authenticators);
2168 cprintf(listener, "dropped\t\t" PU "\n", stats->total_packets_dropped);
2169 cprintf(listener, "unknown_types\t" PU "\n", stats->total_unknown_types);
2172 cprintf(listener, "timeouts\t" PU "\n", stats->total_timeouts);
2175 cprintf(listener, "last_packet\t%" PRId64 "\n", (int64_t) stats->last_packet);
2176 for (i = 0; i < 8; i++) {
2177 cprintf(listener, "elapsed.%s\t%u\n",
2178 elapsed_names[i], stats->elapsed[i]);
2185 #ifdef HAVE_PTHREAD_H
2186 static int command_stats_queue(rad_listen_t *listener, UNUSED int argc, UNUSED char *argv[])
2188 int array[RAD_LISTEN_MAX], pps[2];
2190 thread_pool_queue_stats(array, pps);
2192 cprintf(listener, "queue_len_internal\t" PU "\n", array[0]);
2193 cprintf(listener, "queue_len_proxy\t\t" PU "\n", array[1]);
2194 cprintf(listener, "queue_len_auth\t\t" PU "\n", array[2]);
2195 cprintf(listener, "queue_len_acct\t\t" PU "\n", array[3]);
2196 cprintf(listener, "queue_len_detail\t" PU "\n", array[4]);
2198 cprintf(listener, "queue_pps_in\t\t" PU "\n", pps[0]);
2199 cprintf(listener, "queue_pps_out\t\t" PU "\n", pps[1]);
2206 static int command_stats_memory(rad_listen_t *listener, int argc, char *argv[])
2209 if (!main_config.debug_memory || !main_config.memory_report) {
2210 cprintf(listener, "No memory debugging was enabled.\n");
2214 if (argc == 0) goto fail;
2216 if (strcmp(argv[0], "total") == 0) {
2217 cprintf(listener, "%zd\n", talloc_total_size(NULL));
2221 if (strcmp(argv[0], "blocks") == 0) {
2222 cprintf(listener, "%zd\n", talloc_total_blocks(NULL));
2226 if (strcmp(argv[0], "full") == 0) {
2227 cprintf(listener, "see stdout of the server for the full report.\n");
2228 fr_log_talloc_report(NULL);
2233 cprintf_error(listener, "Must use 'stats memory [blocks|full|total]'\n");
2239 static FR_NAME_NUMBER state_names[] = {
2240 { "unopened", STATE_UNOPENED },
2241 { "unlocked", STATE_UNLOCKED },
2242 { "header", STATE_HEADER },
2243 { "reading", STATE_READING },
2244 { "queued", STATE_QUEUED },
2245 { "running", STATE_RUNNING },
2246 { "no-reply", STATE_NO_REPLY },
2247 { "replied", STATE_REPLIED },
2252 static int command_stats_detail(rad_listen_t *listener, int argc, char *argv[])
2255 listen_detail_t *data;
2259 cprintf_error(listener, "Must specify <filename>\n");
2264 for (this = main_config.listen; this != NULL; this = this->next) {
2265 if (this->type != RAD_LISTEN_DETAIL) continue;
2268 if (strcmp(argv[1], data->filename) != 0) continue;
2274 cprintf_error(listener, "No detail file listener\n");
2278 cprintf(listener, "state\t%s\n",
2279 fr_int2str(state_names, data->state, "?"));
2281 if ((data->state == STATE_UNOPENED) ||
2282 (data->state == STATE_UNLOCKED)) {
2287 * Race conditions: file might not exist.
2289 if (stat(data->filename_work, &buf) < 0) {
2290 cprintf(listener, "packets\t0\n");
2291 cprintf(listener, "tries\t0\n");
2292 cprintf(listener, "offset\t0\n");
2293 cprintf(listener, "size\t0\n");
2297 cprintf(listener, "packets\t%d\n", data->packets);
2298 cprintf(listener, "tries\t%d\n", data->tries);
2299 cprintf(listener, "offset\t%u\n", (unsigned int) data->offset);
2300 cprintf(listener, "size\t%u\n", (unsigned int) buf.st_size);
2307 static int command_stats_home_server(rad_listen_t *listener, int argc, char *argv[])
2309 home_server_t *home;
2312 cprintf_error(listener, "Must specify [auth/acct] OR <ipaddr> <port>\n");
2317 #ifdef WITH_ACCOUNTING
2318 if (strcmp(argv[0], "acct") == 0) {
2319 return command_print_stats(listener,
2320 &proxy_acct_stats, 0, 1);
2323 if (strcmp(argv[0], "auth") == 0) {
2324 return command_print_stats(listener,
2325 &proxy_auth_stats, 1, 1);
2328 cprintf_error(listener, "Should specify [auth/acct]\n");
2332 home = get_home_server(listener, argc, argv, NULL);
2333 if (!home) return 0;
2335 command_print_stats(listener, &home->stats,
2336 (home->type == HOME_TYPE_AUTH), 1);
2337 cprintf(listener, "outstanding\t%d\n", home->currently_outstanding);
2342 static int command_stats_client(rad_listen_t *listener, int argc, char *argv[])
2346 RADCLIENT *client, fake;
2349 cprintf_error(listener, "Must specify [auth/acct]\n");
2355 * Global statistics.
2357 fake.auth = radius_auth_stats;
2358 #ifdef WITH_ACCOUNTING
2359 fake.auth = radius_acct_stats;
2362 fake.coa = radius_coa_stats;
2363 fake.dsc = radius_dsc_stats;
2369 * Per-client statistics.
2371 client = get_client(listener, argc - 1, argv + 1);
2372 if (!client) return 0;
2375 if (strcmp(argv[0], "auth") == 0) {
2377 stats = &client->auth;
2379 } else if (strcmp(argv[0], "acct") == 0) {
2380 #ifdef WITH_ACCOUNTING
2382 stats = &client->acct;
2384 cprintf_error(listener, "This server was built without accounting support.\n");
2388 } else if (strcmp(argv[0], "coa") == 0) {
2391 stats = &client->coa;
2393 cprintf_error(listener, "This server was built without CoA support.\n");
2397 } else if (strcmp(argv[0], "disconnect") == 0) {
2400 stats = &client->dsc;
2402 cprintf_error(listener, "This server was built without CoA support.\n");
2407 cprintf_error(listener, "Unknown statistics type\n");
2412 * Global results for all client.
2415 #ifdef WITH_ACCOUNTING
2417 return command_print_stats(listener,
2418 &radius_acct_stats, auth, 0);
2421 return command_print_stats(listener, &radius_auth_stats, auth, 0);
2424 return command_print_stats(listener, stats, auth, 0);
2428 static int command_stats_socket(rad_listen_t *listener, int argc, char *argv[])
2433 sock = get_socket(listener, argc, argv, NULL);
2434 if (!sock) return 0;
2436 if (sock->type != RAD_LISTEN_AUTH) auth = false;
2438 return command_print_stats(listener, &sock->stats, auth, 0);
2440 #endif /* WITH_STATS */
2443 #ifdef WITH_DYNAMIC_CLIENTS
2444 static int command_add_client_file(rad_listen_t *listener, int argc, char *argv[])
2449 cprintf_error(listener, "<file> is required\n");
2454 * Read the file and generate the client.
2456 c = client_read(argv[0], false, false);
2458 cprintf_error(listener, "Unknown error reading client file.\n");
2462 if (!client_add(NULL, c)) {
2463 cprintf_error(listener, "Unknown error inserting new client.\n");
2472 static int command_del_client(rad_listen_t *listener, int argc, char *argv[])
2476 client = get_client(listener, argc, argv);
2477 if (!client) return 0;
2479 if (!client->dynamic) {
2480 cprintf_error(listener, "Client %s was not dynamically defined.\n", argv[0]);
2485 * DON'T delete it. Instead, mark it as "dead now". The
2486 * next time we receive a packet for the client, it will
2489 * If we don't receive a packet from it, the client
2490 * structure will stick around for a while. Oh well...
2492 client->lifetime = 1;
2498 static fr_command_table_t command_table_del_client[] = {
2499 { "ipaddr", FR_WRITE,
2500 "del client ipaddr <ipaddr> [udp|tcp] [listen <ipaddr> <port>] - Delete a dynamically created client",
2501 command_del_client, NULL },
2503 { NULL, 0, NULL, NULL, NULL }
2507 static fr_command_table_t command_table_del[] = {
2508 { "client", FR_WRITE,
2509 "del client <command> - Delete client configuration commands",
2510 NULL, command_table_del_client },
2512 { NULL, 0, NULL, NULL, NULL }
2516 static fr_command_table_t command_table_add_client[] = {
2518 "add client file <filename> - Add new client definition from <filename>",
2519 command_add_client_file, NULL },
2521 { NULL, 0, NULL, NULL, NULL }
2525 static fr_command_table_t command_table_add[] = {
2526 { "client", FR_WRITE,
2527 "add client <command> - Add client configuration commands",
2528 NULL, command_table_add_client },
2530 { NULL, 0, NULL, NULL, NULL }
2535 static fr_command_table_t command_table_set_home[] = {
2536 { "state", FR_WRITE,
2537 "set home_server state <ipaddr> <port> [udp|tcp] [alive|dead] - set state for given home server",
2538 command_set_home_server_state, NULL },
2540 { NULL, 0, NULL, NULL, NULL }
2544 static fr_command_table_t command_table_set_module[] = {
2545 { "config", FR_WRITE,
2546 "set module config <module> variable value - set configuration for <module>",
2547 command_set_module_config, NULL },
2549 { "status", FR_WRITE,
2550 "set module status <module> [alive|...] - set the module status to be alive (operating normally), or force a particular code (ok,fail, etc.)",
2551 command_set_module_status, NULL },
2553 { NULL, 0, NULL, NULL, NULL }
2557 static fr_command_table_t command_table_set[] = {
2558 { "module", FR_WRITE,
2559 "set module <command> - set module commands",
2560 NULL, command_table_set_module },
2562 { "home_server", FR_WRITE,
2563 "set home_server <command> - set home server commands",
2564 NULL, command_table_set_home },
2567 { NULL, 0, NULL, NULL, NULL }
2572 static fr_command_table_t command_table_stats[] = {
2573 { "client", FR_READ,
2574 "stats client [auth/acct] <ipaddr> [udp|tcp] [listen <ipaddr> <port>] "
2575 "- show statistics for given client, or for all clients (auth or acct)",
2576 command_stats_client, NULL },
2579 { "detail", FR_READ,
2580 "stats detail <filename> - show statistics for the given detail file",
2581 command_stats_detail, NULL },
2585 { "home_server", FR_READ,
2586 "stats home_server [<ipaddr>/auth/acct] <port> [udp|tcp] - show statistics for given home server (ipaddr and port), or for all home servers (auth or acct)",
2587 command_stats_home_server, NULL },
2590 #ifdef HAVE_PTHREAD_H
2592 "stats queue - show statistics for packet queues",
2593 command_stats_queue, NULL },
2596 { "socket", FR_READ,
2597 "stats socket <ipaddr> <port> [udp|tcp] "
2598 "- show statistics for given socket",
2599 command_stats_socket, NULL },
2602 { "memory", FR_READ,
2603 "stats memory [blocks|full|total] - show statistics on used memory",
2604 command_stats_memory, NULL },
2607 { NULL, 0, NULL, NULL, NULL }
2611 static fr_command_table_t command_table[] = {
2612 #ifdef WITH_DYNAMIC_CLIENTS
2613 { "add", FR_WRITE, NULL, NULL, command_table_add },
2615 { "debug", FR_WRITE,
2616 "debug <command> - debugging commands",
2617 NULL, command_table_debug },
2618 #ifdef WITH_DYNAMIC_CLIENTS
2619 { "del", FR_WRITE, NULL, NULL, command_table_del },
2622 "hup [module] - sends a HUP signal to the server, or optionally to one module",
2623 command_hup, NULL },
2624 { "inject", FR_WRITE,
2625 "inject <command> - commands to inject packets into a running server",
2626 NULL, command_table_inject },
2627 { "reconnect", FR_READ,
2628 "reconnect - reconnect to a running server",
2629 NULL, NULL }, /* just here for "help" */
2630 { "terminate", FR_WRITE,
2631 "terminate - terminates the server, and cause it to exit",
2632 command_terminate, NULL },
2633 { "set", FR_WRITE, NULL, NULL, command_table_set },
2634 { "show", FR_READ, NULL, NULL, command_table_show },
2636 { "stats", FR_READ, NULL, NULL, command_table_stats },
2639 { NULL, 0, NULL, NULL, NULL }
2643 static void command_socket_free(rad_listen_t *this)
2645 fr_command_socket_t *cmd = this->data;
2648 * If it's a TCP socket, don't do anything.
2650 if (cmd->magic != COMMAND_SOCKET_MAGIC) {
2654 if (!cmd->copy) return;
2660 * Parse the unix domain sockets.
2662 * FIXME: TCP + SSL, after RadSec is in.
2664 static int command_socket_parse_unix(CONF_SECTION *cs, rad_listen_t *this)
2666 fr_command_socket_t *sock;
2668 if (check_config) return 0;
2672 if (cf_section_parse(cs, sock, command_config) < 0) return -1;
2675 * Can't get uid or gid of connecting user, so can't do
2676 * peercred authentication.
2678 #if !defined(HAVE_GETPEEREID) && !defined(SO_PEERCRED)
2679 if (sock->peercred && (sock->uid_name || sock->gid_name)) {
2680 ERROR("System does not support uid or gid authentication for sockets");
2685 sock->magic = COMMAND_SOCKET_MAGIC;
2687 if (sock->path) sock->copy = talloc_typed_strdup(sock, sock->path);
2689 if (sock->uid_name) {
2692 if (rad_getpwnam(cs, &pwd, sock->uid_name) < 0) {
2693 ERROR("Failed getting uid for %s: %s", sock->uid_name, fr_strerror());
2696 sock->uid = pwd->pw_uid;
2702 if (sock->gid_name) {
2703 if (rad_getgid(cs, &sock->gid, sock->gid_name) < 0) {
2704 ERROR("Failed getting gid for %s: %s", sock->gid_name, fr_strerror());
2711 if (!sock->mode_name) {
2712 sock->co.mode = FR_READ;
2714 sock->co.mode = fr_str2int(mode_names, sock->mode_name, 0);
2715 if (!sock->co.mode) {
2716 ERROR("Invalid mode name \"%s\"",
2722 if (sock->peercred) {
2723 this->fd = fr_server_domain_socket_peercred(sock->path, sock->uid, sock->gid);
2725 uid_t uid = sock->uid;
2726 gid_t gid = sock->gid;
2728 if (uid == ((uid_t)-1)) uid = 0;
2729 if (gid == ((gid_t)-1)) gid = 0;
2731 this->fd = fr_server_domain_socket_perm(sock->path, uid, gid);
2735 ERROR("Failed creating control socket \"%s\": %s", sock->path, fr_strerror());
2736 if (sock->copy) talloc_free(sock->copy);
2744 static int command_socket_parse(CONF_SECTION *cs, rad_listen_t *this)
2747 CONF_PAIR const *cp;
2748 listen_socket_t *sock;
2750 cp = cf_pair_find(cs, "socket");
2751 if (cp) return command_socket_parse_unix(cs, this);
2753 rcode = common_socket_parse(cs, this);
2754 if (rcode < 0) return -1;
2759 "TLS is not supported for control sockets");
2765 if (sock->proto != IPPROTO_TCP) {
2767 "UDP is not supported for control sockets");
2774 static int command_socket_print(rad_listen_t const *this, char *buffer, size_t bufsize)
2776 fr_command_socket_t *sock = this->data;
2778 if (sock->magic != COMMAND_SOCKET_MAGIC) {
2779 return common_socket_print(this, buffer, bufsize);
2782 snprintf(buffer, bufsize, "command file %s", sock->path);
2788 * String split routine. Splits an input string IN PLACE
2789 * into pieces, based on spaces.
2791 static int str2argvX(char *str, char **argv, int max_argc)
2796 if (argc >= max_argc) return argc;
2799 * Chop out comments early.
2806 while ((*str == ' ') ||
2809 (*str == '\n')) *(str++) = '\0';
2811 if (!*str) return argc;
2815 if ((*str == '\'') || (*str == '"')) {
2828 * Handle \" and nothing else.
2843 (*str != '\n')) str++;
2849 static void print_help(rad_listen_t *listener, int argc, char *argv[],
2850 fr_command_table_t *table, int recursive)
2854 /* this should never happen, but if it does then just return gracefully */
2857 for (i = 0; table[i].command != NULL; i++) {
2859 if (strcmp(table[i].command, argv[0]) == 0) {
2860 if (table[i].table) {
2861 print_help(listener, argc - 1, argv + 1, table[i].table, recursive);
2863 if (table[i].help) {
2864 cprintf(listener, "%s\n", table[i].help);
2873 if (table[i].help) {
2874 cprintf(listener, "%s\n",
2877 cprintf(listener, "%s <command> - do sub-command of %s\n",
2878 table[i].command, table[i].command);
2881 if (recursive && table[i].table) {
2882 print_help(listener, 0, NULL, table[i].table, recursive);
2887 #define MAX_ARGV (16)
2890 * Check if an incoming request is "ok"
2892 * It takes packets, not requests. It sees if the packet looks
2893 * OK. If so, it does a number of sanity checks on it.
2895 static int command_domain_recv_co(rad_listen_t *listener, fr_cs_buffer_t *co)
2901 fr_channel_type_t channel;
2902 char *my_argv[MAX_ARGV], **argv;
2903 fr_command_table_t *table;
2906 r = fr_channel_drain(listener->fd, &channel, co->buffer, sizeof(co->buffer) - 1, &command, co->offset);
2910 command_close_socket(listener);
2915 * We need more data. Go read it.
2917 if (channel == FR_CHANNEL_WANT_MORE) {
2924 DEBUG("radmin> %s", command);
2926 argc = str2argvX((char *) command, my_argv, MAX_ARGV);
2927 if (argc == 0) goto do_next; /* empty strings are OK */
2930 cprintf_error(listener, "Failed parsing command.\n");
2936 for (len = 0; len <= co->offset; len++) {
2937 if (command[len] < 0x20) {
2938 command[len] = '\0';
2944 * Hard-code exit && quit.
2946 if ((strcmp(argv[0], "exit") == 0) ||
2947 (strcmp(argv[0], "quit") == 0)) goto do_close;
2949 table = command_table;
2952 for (i = 0; table[i].command != NULL; i++) {
2953 if (strcmp(table[i].command, argv[0]) == 0) {
2955 * Check permissions.
2957 if (((co->mode & FR_WRITE) == 0) &&
2958 ((table[i].mode & FR_WRITE) != 0)) {
2959 cprintf_error(listener, "You do not have write permission. See \"mode = rw\" in the \"listen\" section for this socket.\n");
2963 if (table[i].table) {
2965 * This is the last argument, but
2966 * there's a sub-table. Print help.
2970 table = table[i].table;
2976 table = table[i].table;
2980 if ((argc == 2) && (strcmp(argv[1], "?") == 0)) goto do_help;
2982 if (!table[i].func) {
2983 cprintf_error(listener, "Invalid command\n");
2987 status = table[i].func(listener, argc - 1, argv + 1);
2996 if ((strcmp(argv[0], "help") == 0) ||
2997 (strcmp(argv[0], "?") == 0)) {
3001 if ((argc > 1) && (strcmp(argv[1], "-r") == 0)) {
3009 print_help(listener, argc - 1, argv + 1, table, recursive);
3013 cprintf_error(listener, "Unknown command \"%s\"\n",
3018 r = fr_channel_write(listener->fd, FR_CHANNEL_CMD_STATUS, &status, sizeof(status));
3019 if (r <= 0) goto do_close;
3026 * Write 32-bit magic number && version information.
3028 static int command_write_magic(int newfd, listen_socket_t *sock)
3032 fr_channel_type_t channel;
3035 r = fr_channel_read(newfd, &channel, buffer, 8);
3038 ERROR("Cannot talk to socket: %s",
3039 fr_syserror(errno));
3043 magic = htonl(0xf7eead16);
3044 if ((r != 8) || (channel != FR_CHANNEL_INIT_ACK) ||
3045 (memcmp(&magic, &buffer, sizeof(magic)) != 0)) {
3046 ERROR("Incompatible versions");
3050 r = fr_channel_write(newfd, FR_CHANNEL_INIT_ACK, buffer, 8);
3051 if (r <= 0) goto do_close;
3054 * Write an initial challenge
3060 co = talloc_zero(sock, fr_cs_buffer_t);
3061 sock->packet = (void *) co;
3063 for (i = 0; i < 16; i++) {
3064 co->buffer[i] = fr_rand();
3067 r = fr_channel_write(newfd, FR_CHANNEL_AUTH_CHALLENGE, co->buffer, 16);
3068 if (r <= 0) goto do_close;
3075 static int command_tcp_recv(rad_listen_t *this)
3078 listen_socket_t *sock = this->data;
3079 fr_cs_buffer_t *co = (void *) sock->packet;
3080 fr_channel_type_t channel;
3082 rad_assert(co != NULL);
3085 uint8_t expected[16];
3087 r = fr_channel_read(this->fd, &channel, co->buffer, 16);
3088 if ((r != 16) || (channel != FR_CHANNEL_AUTH_RESPONSE)) {
3090 command_close_socket(this);
3094 fr_hmac_md5(expected, (void const *) sock->client->secret,
3095 strlen(sock->client->secret),
3096 (uint8_t *) co->buffer, 16);
3098 if (rad_digest_cmp(expected,
3099 (uint8_t *) co->buffer + 16, 16 != 0)) {
3100 ERROR("radmin failed challenge: Closing socket");
3108 return command_domain_recv_co(this, co);
3112 * Should never be called. The functions should just call write().
3114 static int command_tcp_send(UNUSED rad_listen_t *listener, UNUSED REQUEST *request)
3119 static int command_domain_recv(rad_listen_t *listener)
3121 fr_command_socket_t *sock = listener->data;
3123 return command_domain_recv_co(listener, &sock->co);
3126 static int command_domain_accept(rad_listen_t *listener)
3131 struct sockaddr_storage src;
3132 fr_command_socket_t *sock = listener->data;
3134 salen = sizeof(src);
3136 DEBUG2(" ... new connection request on command socket");
3138 newfd = accept(listener->fd, (struct sockaddr *) &src, &salen);
3141 * Non-blocking sockets must handle this.
3143 if (errno == EWOULDBLOCK) {
3147 DEBUG2(" ... failed to accept connection");
3151 #if defined(HAVE_GETPEEREID) || defined (SO_PEERCRED)
3153 * Perform user authentication.
3155 if (sock->peercred && (sock->uid_name || sock->gid_name)) {
3159 if (getpeereid(newfd, &uid, &gid) < 0) {
3160 ERROR("Failed getting peer credentials for %s: %s",
3161 sock->path, fr_syserror(errno));
3167 * Only do UID checking if the caller is
3168 * non-root. The superuser can do anything, so
3169 * we might as well let them.
3173 * Allow entry if UID or GID matches.
3175 if (sock->uid_name && (sock->uid == uid)) break;
3176 if (sock->gid_name && (sock->gid == gid)) break;
3178 if (sock->uid_name && (sock->uid != uid)) {
3179 ERROR("Unauthorized connection to %s from uid %ld",
3181 sock->path, (long int) uid);
3186 if (sock->gid_name && (sock->gid != gid)) {
3187 ERROR("Unauthorized connection to %s from gid %ld",
3188 sock->path, (long int) gid);
3197 if (command_write_magic(newfd, NULL) < 0) {
3203 * Add the new listener.
3205 this = listen_alloc(listener, listener->type);
3206 if (!this) return 0;
3209 * Copy everything, including the pointer to the socket
3213 memcpy(this, listener, sizeof(*this));
3214 this->status = RAD_LISTEN_STATUS_INIT;
3216 this->data = sock; /* fix it back */
3218 sock->magic = COMMAND_SOCKET_MAGIC;
3219 sock->user[0] = '\0';
3220 sock->path = ((fr_command_socket_t *) listener->data)->path;
3221 sock->co.offset = 0;
3222 sock->co.mode = ((fr_command_socket_t *) listener->data)->co.mode;
3225 this->recv = command_domain_recv;
3228 * Tell the event loop that we have a new FD
3230 radius_update_listener(this);
3237 * Send an authentication response packet
3239 static int command_domain_send(UNUSED rad_listen_t *listener,
3240 UNUSED REQUEST *request)
3246 static int command_socket_encode(UNUSED rad_listen_t *listener,
3247 UNUSED REQUEST *request)
3253 static int command_socket_decode(UNUSED rad_listen_t *listener,
3254 UNUSED REQUEST *request)
3259 #endif /* WITH_COMMAND_SOCKET */