summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorAleksey Demakov <a.demakov@pengutronix.de>2008-05-15 11:13:19 +0000
committerAleksey Demakov <a.demakov@pengutronix.de>2008-05-15 11:13:19 +0000
commit0e5569e8683e6e1b0fe171241aad59fd3ec8caab (patch)
tree040fb633311648de252b654e4bebb7e1ae9599ac /src
parent03d1af8187610aa3fd4726b5222594c3f6c26fba (diff)
downloadurshd-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.c347
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;
}
-
-
-
-