pax_global_header00006660000000000000000000000064134526472140014522gustar00rootroot0000000000000052 comment=a203411222fdf089065aef09464ac6cda171114d jd-sysrqd-9510edc/000077500000000000000000000000001345264721400140565ustar00rootroot00000000000000jd-sysrqd-9510edc/.gitignore000066400000000000000000000000201345264721400160360ustar00rootroot00000000000000sysrqd.o sysrqd jd-sysrqd-9510edc/AUTHORS000066400000000000000000000000431345264721400151230ustar00rootroot00000000000000Julien Danjou jd-sysrqd-9510edc/ChangeLog000066400000000000000000000037031345264721400156330ustar00rootroot00000000000000Version 17 -- 8 Apr 2019 * Fix check of inet_aton() returned value Version 16 -- Thu, 24 Mar 2016 14:43:33 CET * Update README * Add missing changelog entry Version 15 -- Thu, 24 Mar 2016 14:36:33 CET * Allow to store password encrypted using crypt(3) Version 14 -- Tue, 16 Mar 2010 16:54:22 +0100 * Fix authentification with clients not sending \r\n Version 13 -- Mon, 30 Nov 2009 09:51:24 +0100 * No code change, but version 12 was badly released with no changelog and bad tarball. Version 12 -- Mon, 19 Oct 2009 14:03:01 +0200 * Ignore SIGPIPE Version 11 -- Mon, 19 Oct 2009 11:30:52 +0200 * Do not try to write anything if read() has failed while reading password. Fix a crash using e.g. nmap. Version 10 -- Thu, 12 Feb 2009 12:05:54 +0100 * memset() our pwd/bindip * Merge read password and bindfile functions * Add more things to syslog * Fix authentification Version 9 -- Fri, 19 Jan 2007 15:32:00 +0100 * Add a warning about TERM and KILL in README * Merge a patch from Neil McGovern: - don't go in swap, always stay in memory - if /etc/sysrqd.bind exists, bind to a specific ip instead of any. Version 8 -- Tue, 11 Jul 2006 11:41:05 +0200 * Use official ports registered by IANA: sysrqd 4094/tcp sysrq daemon sysrqd 4094/udp sysrq daemon Version 7 -- Tue, 16 May 2006 15:55:55 +0200 * Call daemon() instead of simply forking Version 6 -- Tue, 16 May 2006 15:00:44 +0200 * Fix bug with pid file (Thanks to Norbert Kiesel ) * Change default port to 880 Version 5 -- Mon, 1 May 2006 11:58:21 +0200 * Fix little bug with open() Version 4 -- Sun, 30 Apr 2006 21:50:51 +0200 * Add support of syslog * Fork and run in background * Write a pid file Version 3 -- Sat, 11 Mar 2006 11:48:00 +0100 * Fix little bug if password file does not have \n Version 2 -- Mon, 29 Aug 2005 17:06:00 +0200 * Remove init.d script Version 1 -- Mon, 29 Aug 2005 11:02:26 +0200 * Initial release jd-sysrqd-9510edc/INSTALL000066400000000000000000000010051345264721400151030ustar00rootroot00000000000000Symple type: % make % make install - Read the README file. - Create a password file: echo "mypassword" > /etc/sysrqd.secret chmod 0600 /etc/sysrqd.secret - Optionnaly, create a bind file to bind to a specific IP echo 192.168.2.13 > /etc/sysrqd.bind - Add it to your local daemons startup. If you need to tweak some paramaters, take a look on define at the beginning of sysrqd.c You can add this lines to /etc/services: sysrqd 4094/tcp # sysrq daemon sysrqd 4094/udp # sysrq daemon jd-sysrqd-9510edc/Makefile000066400000000000000000000016341345264721400155220ustar00rootroot00000000000000VERSION=$(shell grep '^Version' ChangeLog | head -n 1 | cut -d' ' -f2 | tr -d ' ') BIN=sysrqd O=sysrqd.o CFLAGS+=-W -Wall -Wextra \ -Wundef -Wshadow -Wcast-align -Wwrite-strings -Wsign-compare \ -Wunused -Winit-self -Wpointer-arith -Wredundant-decls \ -Wmissing-prototypes -Wmissing-format-attribute -Wmissing-noreturn \ -std=gnu99 -pipe -DSYSRQD_VERSION="\"$(VERSION)\"" -O3 LDFLAGS+=-lcrypt SBINDIR=$(DESTDIR)/usr/sbin #MANDIR=$(DESTDIR)/usr/share/man/man1 INSTALL = install #MAN=sysrqd.1 $(BIN): $(O) $(CC) -o $(BIN) $(O) $(LDFLAGS) install: $(BIN) $(INSTALL) -d -m 755 $(SBINDIR) $(INSTALL) -m 755 $(BIN) $(SBINDIR) #$(INSTALL) -d -m 755 $(MANDIR) #$(INSTALL) -m 644 $(MAN) $(MANDIR) clean: rm -f *~ $(O) $(BIN) release: clean mkdir ../$(BIN)-$(VERSION) cp -a * ../$(BIN)-$(VERSION) cd .. && tar czf $(BIN)-$(VERSION).tar.gz $(BIN)-$(VERSION) rm -rf ../$(BIN)-$(VERSION) jd-sysrqd-9510edc/README.md000066400000000000000000000015701345264721400153400ustar00rootroot00000000000000 _ ___ _ _ ___ _ __ __ _ __| | / __| | | / __| '__/ _` |/ _` | \__ \ |_| \__ \ | | (_| | (_| | |___/\__, |___/_| \__, |\__,_| |___/ |_| « Don't let me down. » -- The Beatles sysrqd is a small daemon intended to manage [Linux SysRq](https://en.wikipedia.org/wiki/Magic_SysRq_key) over the network. Its philosophy is to be very responsive under heavy load and to try to be somehow reliable. Authentication is made by clear password. Connection should be made to port 4094. # Demo % telnet localhost 4094 Trying 127.0.0.1... Connected to localhost.localdomain. Escape character is '^]'. sysrqd password: hello sysrq> s sysrq> u sysrq> q # Warning Please, be careful if you use 'e' (tErm) and 'i' (kIll). This will kill all processes, including sysrqd! jd-sysrqd-9510edc/sysrqd.c000066400000000000000000000161331345264721400155530ustar00rootroot00000000000000/* * sysrqd.c - Daemon to control sysrq over network * * © 2005-2009 Julien Danjou * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 dated June, 1991. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #define PASS_MAX_LEN 256 #define BIND_MAX_LEN 16 #define PROMPT "sysrq> " #define SYSRQ_TRIGGER_PATH "/proc/sysrq-trigger" #define AUTH_FILE "/etc/sysrqd.secret" #define BINDIP_FILE "/etc/sysrqd.bind" #define PID_FILE "/var/run/sysrqd.pid" #define SYSRQD_PRIO -19 #define SYSRQD_LISTEN_PORT 4094 char pwd[PASS_MAX_LEN]; int sock_serv; /* Macro used to write a string to the client */ #define write_cli(s) \ write(sock_client, s, sizeof(s) - 1); /* Macro used to write the prompt */ #define write_prompt(s) \ write_cli(PROMPT); #define errmsg(s) \ fprintf(stderr, "%s (%s:%d)\n", s, __FILE__, __LINE__); /* Authenticate the connection */ static int auth (int sock_client) { char buf[PASS_MAX_LEN]; size_t len; char *crypt_result; write_cli("sysrqd password: "); memset(buf, 0, sizeof(buf)); /* Read password */ len = read(sock_client, buf, sizeof(buf) - 1); /* remove \r and \n at end */ while(len > 0 && (buf[len - 1] == '\n' || buf[len - 1] == '\r')) len--; /* If password has been sent */ if(len > 0) { buf[len] = '\0'; /* Check if our stored password is crypted, i.e. starts with $[0-9]$ */ if(strlen(pwd) >= 34 && pwd[0] == '$' && pwd[2] == '$' && pwd[1] >= '0' && pwd[1] <= '9') { crypt_result = crypt(buf, pwd); if(!strcmp(crypt_result, pwd)) return 1; else write_cli("Go away!\r\n"); } else { if(!strcmp(buf, pwd)) return 1; else write_cli("Go away!\r\n"); } } return 0; } /* Read a configuration file */ static int read_conffile (const char *file, char* buf, size_t buflen) { int fd; if((fd = open (file, O_RDONLY)) == -1) { syslog(LOG_ERR, "Unable to open file %s: %s", file, strerror(errno)); return 1; } memset(buf, 0, buflen); read (fd, buf, buflen - 1); close (fd); buf[buflen - 1] = '\0'; /* Strip last \n */ char *tmp; if((tmp = strchr(buf, '\n'))) *tmp = '\0'; return 0; } /* Read commands */ static void read_cmd (int sock_client, int fd_sysrq) { char buf = 0; write_prompt(); do { if(buf == '\n') write_prompt(); if((buf >= 48 && buf <= 57) || (buf >= 97 && buf <= 122 )) write(fd_sysrq, &buf, 1); } while(read (sock_client, &buf, 1) == 1 && buf != 'q'); } /* * Listen to a port, * authenticate connection * and execute commands */ static int start_listen (int fd_sysrq) { int sock_client; socklen_t size_addr; struct sockaddr_in addr; struct sockaddr_in addr_client; int opt; char bindip[BIND_MAX_LEN]; addr.sin_family = AF_INET; addr.sin_port = htons(SYSRQD_LISTEN_PORT); if(read_conffile(BINDIP_FILE, bindip, sizeof(bindip))) addr.sin_addr.s_addr = INADDR_ANY; else if(!inet_aton(bindip, &addr.sin_addr)) { syslog(LOG_ERR, "Unable to convert IP: %s, using INADDR_ANY", strerror(errno)); addr.sin_addr.s_addr = INADDR_ANY; } if(!(sock_serv = socket (PF_INET, SOCK_STREAM, 0))) { syslog(LOG_ERR, "Error while creating server socket: %s", strerror(errno)); return 1; } /* We tries to avoid "socket already in use" errors */ opt = 1; setsockopt(sock_serv, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof (opt)); if(bind (sock_serv, (struct sockaddr *) &addr, sizeof (addr))) { syslog(LOG_ERR, "Unable to bind(): %s", strerror(errno)); return 1; } if(listen(sock_serv, 2)) { syslog(LOG_ERR, "Unable to listen(): %s", strerror(errno)); return 1; } size_addr = sizeof (addr_client); syslog(LOG_INFO, "Listening on port tcp/%d", SYSRQD_LISTEN_PORT); while((sock_client = accept (sock_serv, (struct sockaddr *) &addr_client, &size_addr))) { if(auth (sock_client)) read_cmd (sock_client, fd_sysrq); close(sock_client); } close (sock_serv); return 0; } static void __attribute__ ((noreturn)) signal_handler (void) { close (sock_serv); exit (EXIT_FAILURE); } static int catch_signals (void) { struct sigaction sa; sigset_t mask; sigfillset (&mask); sa.sa_handler = (void *) &signal_handler; sa.sa_mask = mask; sigaction (SIGINT, &sa, NULL); sigaction (SIGTERM, &sa, NULL); /* ignore sigpipe */ sigemptyset(&mask); sigaddset(&mask, SIGPIPE); sigprocmask(SIG_BLOCK, &mask, NULL); return 0; } static int write_pidfile(pid_t pid) { FILE *pidf = fopen(PID_FILE, "w"); if (pidf == NULL) return 1; fprintf(pidf, "%d\n", pid); fclose(pidf); return 0; } static void do_on_exit(void) { syslog(LOG_NOTICE, "Exiting"); } int main (void) { int fd_sysrq; atexit(do_on_exit); /* We test if it is worth the pain to fork if setpriority would fail */ if(getuid() != 0) { errmsg ("Only root can run this program."); return 1; } /* We read our password */ if(read_conffile (AUTH_FILE, pwd, sizeof(pwd))) return EXIT_FAILURE; /* mlock, we want this to always run */ mlockall(MCL_CURRENT | MCL_FUTURE); /* We daemonize */ daemon(0, 0); openlog ("sysrqd", LOG_PID, LOG_DAEMON); syslog(LOG_PID | LOG_DAEMON, "Starting"); if(write_pidfile(getpid())) syslog (LOG_PID | LOG_DAEMON, "Unable to write pidfile"); /* We set our priority */ if(setpriority (PRIO_PROCESS, 0, SYSRQD_PRIO)) { syslog (LOG_PID | LOG_DAEMON, "Unable to set priority: %s", strerror(errno)); return EXIT_FAILURE; } /* Catch some signals */ catch_signals (); /* We keep the sysrq-trigger file opened */ fd_sysrq = open(SYSRQ_TRIGGER_PATH, O_SYNC|O_WRONLY); if(fd_sysrq == -1) { syslog(LOG_ERR, "Error while opening sysrq trigger: %s", strerror(errno)); return EXIT_FAILURE; } /* Now listen */ if(!start_listen (fd_sysrq)) return EXIT_FAILURE; /* If we quit, close the trigger */ close (fd_sysrq); closelog(); return EXIT_SUCCESS; }