diff options
author | Aleksey Demakov <a.demakov@pengutronix.de> | 2008-05-15 11:13:19 +0000 |
---|---|---|
committer | Aleksey Demakov <a.demakov@pengutronix.de> | 2008-05-15 11:13:19 +0000 |
commit | 0e5569e8683e6e1b0fe171241aad59fd3ec8caab (patch) | |
tree | 040fb633311648de252b654e4bebb7e1ae9599ac /src | |
parent | 03d1af8187610aa3fd4726b5222594c3f6c26fba (diff) | |
download | urshd-0e5569e8683e6e1b0fe171241aad59fd3ec8caab.tar.gz urshd-0e5569e8683e6e1b0fe171241aad59fd3ec8caab.tar.xz |
remove rhosts, PAM, client host and port checks; some code cleanup and cosmetic changes
Diffstat (limited to 'src')
-rw-r--r-- | src/urshd.c | 347 |
1 files changed, 88 insertions, 259 deletions
diff --git a/src/urshd.c b/src/urshd.c index 9aa7234..3c43194 100644 --- a/src/urshd.c +++ b/src/urshd.c @@ -33,10 +33,6 @@ #define PROG "urshd" -/* - * PAM modifications by Michael K. Johnson <johnsonm@redhat.com> - */ - char copyright[] = "@(#) Copyright (c) 1988, 1989 The Regents of the University of California.\n" "All rights reserved.\n"; @@ -82,26 +78,21 @@ char rcsid[] = #include <ctype.h> #include <assert.h> #include <sched.h> +#include <getopt.h> #include <urshd_config.h> -#if defined(__GLIBC__) && (__GLIBC__ >= 2) -#define _check_rhosts_file __check_rhosts_file -#endif +#define OPTIONS "np:P:" -#ifdef USE_PAM -#include <security/pam_appl.h> -#include <security/pam_misc.h> -static pam_handle_t *pamh; -#endif /* USE_PAM */ - -#define OPTIONS "ahlLnp:P:" +static struct option long_options[] = { + {"disable-keepalive", no_argument, 0, 'n' }, + {"priority", required_argument, 0, 'p' }, + {"command-priority", required_argument, 0, 'P' }, + {0, 0, 0, 0} +}; static int keepalive = 1; -static int check_all = 0; -static int paranoid = 0; static int sent_null; -static int allow_root_rhosts=0; static int priority = 0; static int cmd_priority = 0; @@ -117,7 +108,34 @@ static void error(const char *fmt, ...); static void doit(struct sockaddr_in *fromp); static void getstr(char *buf, int cnt, const char *err); -extern int _check_rhosts_file; +static void +set_priority(int sched_priority) +{ + struct sched_param schedp; + + memset(&schedp, 0, sizeof(schedp)); + schedp.sched_priority = sched_priority; + sched_setscheduler(0, SCHED_FIFO, &schedp); +} + +static void +usage(void) +{ + syslog(LOG_ERR, "usage: " PROG " [-%s]", OPTIONS); + exit(2); +} + +static void +fatal(const char *fmt, ...) +{ + va_list ap; + + va_start(ap, fmt); + vsyslog(LOG_ERR, fmt, ap); + va_end(ap); + + exit(1); +} /* * Report error to client. @@ -126,33 +144,25 @@ extern int _check_rhosts_file; * for that connection first. */ static void -error(const char *fmt, ...) { +error(const char *fmt, ...) +{ va_list ap; char buf[BUFSIZ], *bp = buf; - - if (sent_null == 0) *bp++ = 1; + + if (sent_null == 0) { + *bp++ = 1; + } + va_start(ap, fmt); - vsnprintf(bp, sizeof(buf)-1, fmt, ap); + vsnprintf(bp, sizeof(buf) - 1, fmt, ap); va_end(ap); + write(2, buf, strlen(buf)); } -static void fail(const char *errorstr, - const char *remuser, const char *hostname, - const char *locuser, - const char *cmdbuf) +static void +getstr(char *buf, int cnt, const char *err) { - /* log the (failed) rsh request */ - syslog(LOG_INFO|LOG_AUTH, "rsh denied to %s@%s as %s: %s", - remuser, hostname, locuser, errorstr); - if (paranoid) { - syslog(LOG_INFO|LOG_AUTH, "rsh command was '%s'", cmdbuf); - } - error(errorstr, hostname); - exit(1); -} - -static void getstr(char *buf, int cnt, const char *err) { char c; do { if (read(0, &c, 1) != 1) exit(1); @@ -164,7 +174,9 @@ static void getstr(char *buf, int cnt, const char *err) { } while (c != 0); } -static int getint(void) { +static int +getint(void) +{ int port = 0; char c; do { @@ -174,7 +186,9 @@ static int getint(void) { return port; } -static void stderr_parent(int sock, int pype, int pid) { +static void +stderr_parent(int sock, int pype, int pid) +{ fd_set ready, readfrom; char buf[BUFSIZ], sig; int one = 1; @@ -215,126 +229,8 @@ static void stderr_parent(int sock, int pype, int pid) { else write(sock, buf, cc); } } - -#ifdef USE_PAM - /* - * This does not strike me as the right place for this; this is - * in a child process... what does this need to accomplish? - * - * No, it's not the child process, the code is just confusing. - */ - pam_close_session(pamh, 0); - pam_end(pamh, PAM_SUCCESS); -#endif - exit(0); -} - -static struct passwd *doauth(const char *remuser, - const char *hostname, - const char *locuser) -{ -#ifdef USE_PAM - static struct pam_conv conv = { misc_conv, NULL }; - int retcode; -#endif - struct passwd *pwd = getpwnam(locuser); - if (pwd == NULL) return NULL; - if (pwd->pw_uid==0) paranoid = 1; - -#ifdef USE_PAM - retcode = pam_start("rsh", locuser, &conv, &pamh); - if (retcode != PAM_SUCCESS) { - syslog(LOG_ERR, "pam_start: %s\n", pam_strerror(pamh, retcode)); - exit (1); - } - pam_set_item (pamh, PAM_RUSER, remuser); - pam_set_item (pamh, PAM_RHOST, hostname); - pam_set_item (pamh, PAM_TTY, "tty"); - - retcode = pam_authenticate(pamh, 0); - if (retcode == PAM_SUCCESS) { - retcode = pam_acct_mgmt(pamh, 0); - } - if (retcode == PAM_SUCCESS) { - /* - * Why do we need to set groups here? - * Also, this stuff should be moved down near where the setuid() is. - */ - if (setgid(pwd->pw_gid) != 0) { - pam_end(pamh, PAM_SYSTEM_ERR); - return NULL; - } - if (initgroups(locuser, pwd->pw_gid) != 0) { - pam_end(pamh, PAM_SYSTEM_ERR); - return NULL; - } - retcode = pam_setcred(pamh, PAM_ESTABLISH_CRED); - } - - if (retcode == PAM_SUCCESS) { - retcode = pam_open_session(pamh,0); - } - if (retcode != PAM_SUCCESS) { - pam_end(pamh, retcode); - return NULL; - } - return pwd; -#else - if (pwd->pw_uid==0 && !allow_root_rhosts) return NULL; - if (_check_rhosts_file) { - if (ruserok(hostname, pwd->pw_uid==0, remuser, locuser) < 0) { - return NULL; - } - } - return pwd; -#endif -} - -static const char *findhostname(struct sockaddr_in *fromp, - const char *remuser, const char *locuser, - const char *cmdbuf) -{ - struct hostent *hp; - const char *hostname; - - hp = gethostbyaddr((char *)&fromp->sin_addr, sizeof (struct in_addr), - fromp->sin_family); - - errno = ENOMEM; /* malloc (thus strdup) may not set it */ - if (hp) hostname = strdup(hp->h_name); - else hostname = strdup(inet_ntoa(fromp->sin_addr)); - - if (hostname==NULL) { - /* out of memory? */ - error("strdup: %s\n", strerror(errno)); - exit(1); - } - - /* - * Attempt to confirm the DNS. - */ -#ifdef RES_DNSRCH - _res.options &= ~RES_DNSRCH; -#endif - hp = gethostbyname(hostname); - if (hp == NULL) { - syslog(LOG_INFO, "Couldn't look up address for %s", hostname); - fail("Couldn't get address for your host (%s)\n", - remuser, inet_ntoa(fromp->sin_addr), locuser, cmdbuf); - } - while (hp->h_addr_list[0] != NULL) { - if (!memcmp(hp->h_addr_list[0], &fromp->sin_addr, - sizeof(fromp->sin_addr))) { - return hostname; - } - hp->h_addr_list++; - } - syslog(LOG_NOTICE, "Host addr %s not listed for host %s", - inet_ntoa(fromp->sin_addr), hp->h_name); - fail("Host address mismatch for %s\n", - remuser, inet_ntoa(fromp->sin_addr), locuser, cmdbuf); - return NULL; /* not reachable */ + exit(0); } static void @@ -345,7 +241,6 @@ doit(struct sockaddr_in *fromp) char locuser[16], remuser[16]; struct passwd *pwd; int sock = -1; - const char *hostname; u_short port; int pv[2], pid, ifd; @@ -376,25 +271,18 @@ doit(struct sockaddr_in *fromp) } } -#if 0 - /* We're running from inetd; socket is already on 0, 1, 2 */ - dup2(f, 0); - dup2(f, 1); - dup2(f, 2); -#endif - getstr(remuser, sizeof(remuser), "remuser"); getstr(locuser, sizeof(locuser), "locuser"); getstr(cmdbuf, sizeof(cmdbuf), "command"); - if (!strcmp(locuser, "root")) paranoid = 1; - - hostname = findhostname(fromp, remuser, locuser, cmdbuf); setpwent(); - pwd = doauth(remuser, hostname, locuser); + pwd = getpwnam(locuser); if (pwd == NULL) { - fail("Permission denied.\n", - remuser, hostname, locuser, cmdbuf); + syslog(LOG_INFO|LOG_AUTH, PROG " permission denied to %s as %s.", + remuser, locuser); + syslog(LOG_INFO|LOG_AUTH, PROG " command was '%s'", cmdbuf); + error("Permission denied.\n"); + exit(1); } if (chdir(pwd->pw_dir) < 0) { @@ -449,8 +337,6 @@ doit(struct sockaddr_in *fromp) syslog(LOG_ERR, "setlogin() failed: %m"); } #endif -#ifndef USE_PAM - /* if PAM, already done */ if (setgid(pwd->pw_gid)) { syslog(LOG_ERR, "setgid: %m"); exit(1); @@ -459,7 +345,6 @@ doit(struct sockaddr_in *fromp) syslog(LOG_ERR, "initgroups: %m"); exit(1); } -#endif if (setuid(pwd->pw_uid)) { syslog(LOG_ERR, "setuid: %m"); exit(1); @@ -482,9 +367,8 @@ doit(struct sockaddr_in *fromp) else shellname = theshell; endpwent(); - if (paranoid) { - syslog(LOG_INFO|LOG_AUTH, "%s@%s as %s: cmd='%s'", - remuser, hostname, locuser, cmdbuf); + if (0) { + syslog(LOG_INFO|LOG_AUTH, "%s as %s: cmd='%s'", remuser, locuser, cmdbuf); } /* @@ -494,23 +378,20 @@ doit(struct sockaddr_in *fromp) for (ifd = getdtablesize()-1; ifd > 2; ifd--) close(ifd); if (cmd_priority) { - struct sched_param schedp; - - memset(&schedp, 0, sizeof(schedp)); - schedp.sched_priority = cmd_priority; - sched_setscheduler(0, SCHED_FIFO, &schedp); + set_priority(cmd_priority); } + execl(theshell, shellname, "-c", cmdbuf, NULL); perror(theshell); exit(1); } -static void network_init(int fd, struct sockaddr_in *fromp) +static void +network_init(int fd, struct sockaddr_in *fromp) { struct linger linger; socklen_t fromlen; int on=1; - int port; fromlen = sizeof(*fromp); if (getpeername(fd, (struct sockaddr *) fromp, &fromlen) < 0) { @@ -527,11 +408,6 @@ static void network_init(int fd, struct sockaddr_in *fromp) sizeof (linger)) < 0) syslog(LOG_WARNING, "setsockopt (SO_LINGER): %m"); - if (fromp->sin_family != AF_INET) { - syslog(LOG_ERR, "malformed \"from\" address (af %d)\n", - fromp->sin_family); - exit(1); - } #ifdef IP_OPTIONS { u_char optbuf[BUFSIZ/3], *cp; @@ -568,19 +444,10 @@ static void network_init(int fd, struct sockaddr_in *fromp) } } #endif - - /* - * Check originating port for validity. - */ - port = ntohs(fromp->sin_port); - if (port >= IPPORT_RESERVED || port < IPPORT_RESERVED/2) { - syslog(LOG_NOTICE|LOG_AUTH, "Connection from %s on illegal port", - inet_ntoa(fromp->sin_addr)); - exit(1); - } } -int mainloop(char *port) +static int +mainloop(char *port) { int s; struct servent *sp; @@ -591,65 +458,54 @@ int mainloop(char *port) sn.sin_family = AF_INET; if (priority) { - struct sched_param schedp; - - memset(&schedp, 0, sizeof(schedp)); - schedp.sched_priority = priority; - sched_setscheduler(0, SCHED_FIFO, &schedp); + set_priority(priority); } if (port) { - if ((sp = getservbyname(port, "tcp"))!=NULL) { + if ((sp = getservbyname(port, "tcp")) != NULL) { sn.sin_port = sp->s_port; - } - else { + } else { int pt = atoi(port); if (pt <= 0) { - fprintf(stderr, "telnetd: %s: bad port number\n", - port); - exit(1); + fatal("%s: bad port number", port); } sn.sin_port = htons(pt); } } else { sp = getservbyname("shell", "tcp"); if (sp == 0) { - fprintf(stderr, PROG ": tcp/shell: unknown service\n"); - exit(1); + fatal("tcp/shell: unknown service"); } sn.sin_port = sp->s_port; } s = socket(AF_INET, SOCK_STREAM, 0); if (s < 0) { - perror(PROG ": socket");; - exit(1); + fatal("socket: %s", strerror(errno)); } (void) setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)); if (bind(s, (struct sockaddr *)&sn, sizeof(sn)) < 0) { - perror(PROG ": bind"); - exit(1); + fatal("bind: %s", strerror(errno)); } if (listen(s, 1) < 0) { - perror(PROG ": listen"); - exit(1); + fatal("listen: %s", strerror(errno)); } while (1) { socklen_t len; int ns, pid; struct sockaddr_in from; - fprintf(stderr, PROG ": waiting for connections.\n"); + syslog(LOG_INFO, "Waiting for connections."); + len = sizeof(sn); ns = accept(s, (struct sockaddr *)&sn, &len); if (ns < 0) { - perror(PROG ": accept"); - exit(1); + fatal("accept: %s", strerror(errno)); } + if ((pid = fork()) < 0) { - perror(PROG ": fork"); - } - else if (pid == 0) { + fatal("fork: %s", strerror(errno)); + } else if (pid == 0) { close(s); dup2(ns, 0); dup2(ns, 1); @@ -657,8 +513,7 @@ int mainloop(char *port) close(ns); network_init(0, &from); doit(&from); - } - else { + } else { close(ns); } } @@ -668,33 +523,16 @@ int main(int argc, char *argv[]) { int ch; - _check_rhosts_file=1; openlog(PROG, LOG_PID | LOG_ODELAY, LOG_DAEMON); opterr = 0; - while ((ch = getopt(argc, argv, OPTIONS)) != EOF) { + while ((ch = getopt_long(argc, argv, OPTIONS, long_options, NULL)) != EOF) { switch (ch) { - case 'a': - check_all = 1; - break; - - case 'h': - allow_root_rhosts = 1; - break; - - case 'l': - _check_rhosts_file = 0; - break; - case 'n': keepalive = 0; break; - case 'L': - paranoid = 1; - break; - case 'p': priority = atoi(optarg); break; @@ -705,23 +543,14 @@ main(int argc, char *argv[]) case '?': default: - syslog(LOG_ERR, "usage: " PROG " [-%s]", OPTIONS); - exit(2); + usage(); } } - argc -= optind; - argv += optind; -#ifdef USE_PAM - if (_check_rhosts_file == 0 || allow_root_rhosts) - syslog(LOG_ERR, "-l and -h functionality has been moved to " - "pam_rhosts_auth in /etc/pam.conf"); -#endif /* USE_PAM */ + if (optind < argc) { + usage(); + } mainloop(0); return 0; } - - - - |