summaryrefslogtreecommitdiffstats
path: root/src/appl/bsd/krshd.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/appl/bsd/krshd.c')
-rw-r--r--src/appl/bsd/krshd.c2047
1 files changed, 0 insertions, 2047 deletions
diff --git a/src/appl/bsd/krshd.c b/src/appl/bsd/krshd.c
deleted file mode 100644
index d491e6e35a..0000000000
--- a/src/appl/bsd/krshd.c
+++ /dev/null
@@ -1,2047 +0,0 @@
-/*
- * appl/bsd/krshd.c
- */
-
-/*
- * Copyright (c) 1983 The Regents of the University of California.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms are permitted
- * provided that the above copyright notice and this paragraph are
- * duplicated in all such forms and that any documentation,
- * advertising materials, and other materials related to such
- * distribution and use acknowledge that the software was developed
- * by the University of California, Berkeley. The name of the
- * University may not be used to endorse or promote products derived
- * from this software without specific prior written permission.
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
- * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
- */
-
-#ifndef lint
-char copyright[] =
- "@(#) Copyright (c) 1983 The Regents of the University of California.\n\
- All rights reserved.\n";
-#endif /* not lint */
-
-/* based on @(#)rshd.c 5.12 (Berkeley) 9/12/88 */
-
- /*
- * remote shell server:
- * remuser\0
- * locuser\0
- * command\0
- * data
- */
-
-/*
- * This is the rshell daemon. The very basic protocol for checking
- * authentication and authorization is:
- * 1) Check authentication.
- * 2) Check authorization via the access-control files:
- * ~/.k5login (using krb5_kuserok)
- * Execute command if configured authoriztion checks pass, else deny
- * permission.
- */
-
-/* DEFINES:
- * KERBEROS - Define this if application is to be kerberised.
- * LOG_ALL_LOGINS - Define this if you want to log all logins.
- * LOG_OTHER_USERS - Define this if you want to log all principals that do
- * not map onto the local user.
- * LOG_REMOTE_REALM - Define this if you want to log all principals from
- * remote realms.
- * LOG_CMD - Define this if you want to log not only the user but also the
- * command executed. This only decides the type of information
- * logged. Whether or not to log is still decided by the above
- * three DEFINES.
- * Note: Root account access is always logged.
- */
-
-#define SERVE_NON_KRB
-#define LOG_REMOTE_REALM
-#define LOG_CMD
-
-#ifdef HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-#ifdef HAVE_STDLIB_H
-#include <stdlib.h>
-#endif
-#ifdef __SCO__
-#include <sys/unistd.h>
-#endif
-
-#include <sys/types.h>
-#include <sys/ioctl.h>
-#include <sys/param.h>
-#include <sys/socket.h>
-#include <sys/file.h>
-#include <sys/stat.h>
-#include <sys/time.h>
-
-#include <fcntl.h>
-
-#ifdef HAVE_SYS_SELECT_H
-#include <sys/select.h>
-#endif
-
-#include <netinet/in.h>
-#include <arpa/inet.h>
-
-#include <stdio.h>
-#include <grp.h>
-#include <errno.h>
-#include <pwd.h>
-#include <ctype.h>
-#include <string.h>
-#include <libpty.h>
-#include <sys/wait.h>
-
-#ifdef HAVE_SYS_LABEL_H
-/* only SunOS 4? */
-#include <sys/label.h>
-#include <sys/audit.h>
-#include <pwdadj.h>
-#endif
-#include <stdarg.h>
-
-#include <signal.h>
-#include <netdb.h>
-
-#ifdef CRAY
-#ifndef NO_UDB
-#include <udb.h>
-#endif /* !NO_UDB */
-#include <sys/category.h>
-#include <netinet/ip.h>
-#include <sys/tfm.h>
-#include <sys/nal.h>
-#include <sys/secparm.h>
-#include <sys/usrv.h>
-#include <sys/utsname.h>
-#include <sys/sysv.h>
-#include <sys/slrec.h>
-#include <sys/unistd.h>
-#include <path.h>
-#endif /* CRAY */
-
-#include <syslog.h>
-
-#ifdef POSIX_TERMIOS
-#include <termios.h>
-#endif
-
-#ifdef HAVE_SYS_FILIO_H
-/* get FIONBIO from sys/filio.h, so what if it is a compatibility feature */
-#include <sys/filio.h>
-#endif
-
-#ifdef KERBEROS
-#include "k5-int.h"
-#include <com_err.h>
-#include "loginpaths.h"
-#include <k5-util.h>
-#include <k5-platform.h>
-
-#ifdef HAVE_PATHS_H
-#include <paths.h>
-#endif
-
-#if defined(_PATH_NOLOGIN)
-#define NOLOGIN _PATH_NOLOGIN
-#else
-#define NOLOGIN "/etc/nologin"
-#endif
-
-#include "defines.h"
-
-#if HAVE_ARPA_NAMESER_H
-#include <arpa/nameser.h>
-#endif
-
-#ifndef MAXDNAME
-#define MAXDNAME 256 /*per the rfc*/
-#endif
-
-#define ARGSTR "ek5ciD:S:M:AP:?L:w:"
-
-
-
-
-#define MAXRETRIES 4
-
-krb5_context bsd_context;
-char *srvtab = NULL;
-krb5_keytab keytab = NULL;
-krb5_ccache ccache = NULL;
-
-void fatal(int, const char *);
-
-int require_encrypt = 0;
-int do_encrypt = 0;
-int anyport = 0;
-char *kprogdir = KPROGDIR;
-int netf;
-int maxhostlen = 0;
-int stripdomain = 1;
-int always_ip = 0;
-
-static krb5_error_code recvauth(int netfd, struct sockaddr *peersin,
- int *valid_checksum);
-
-#else /* !KERBEROS */
-
-#define ARGSTR "RD:?"
-
-#endif /* KERBEROS */
-
-static int accept_a_connection (int debug_port, struct sockaddr *from,
- socklen_t *fromlenp);
-
-#ifndef HAVE_KILLPG
-#define killpg(pid, sig) kill(-(pid), (sig))
-#endif
-
-int checksum_required = 0, checksum_ignored = 0;
-char *progname;
-
-#define MAX_PROG_NAME 10
-
-/* Leave room for 4 environment variables to be passed */
-#define MAXENV 4
-#define SAVEENVPAD 0,0,0,0 /* padding for envinit slots */
-char *save_env[MAXENV];
-int num_env = 0;
-
-#ifdef CRAY
-int secflag;
-extern
-#endif /* CRAY */
-
-void error (char *fmt, ...)
-#if !defined (__cplusplus) && (__GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 7))
- __attribute__ ((__format__ (__printf__, 1, 2)))
-#endif
- ;
-
-void usage(void), getstr(int, char *, int, char *),
- doit(int, struct sockaddr *);
-
-#ifndef HAVE_INITGROUPS
-int initgroups(char* name, gid_t basegid) {
- gid_t others[NGROUPS_MAX+1];
- int ngrps;
-
- others[0] = basegid;
- ngrps = getgroups(NGROUPS_MAX, others+1);
- return setgroups(ngrps+1, others);
-}
-#endif
-
-
-int main(argc, argv)
- int argc;
- char **argv;
-{
-#if defined(BSD) && BSD+0 >= 43
- struct linger linger;
-#endif
- int on = 1;
- socklen_t fromlen;
- struct sockaddr_storage from;
- extern int opterr, optind;
- extern char *optarg;
- int ch;
- int fd;
- int debug_port = 0;
-#ifdef KERBEROS
- krb5_error_code status;
-#endif
-
-#ifdef CRAY
- secflag = sysconf(_SC_CRAY_SECURE_SYS);
-#endif
-
- progname = strrchr (*argv, '/');
- progname = progname ? progname + 1 : *argv;
-
-#ifndef LOG_ODELAY /* 4.2 syslog */
- openlog(progname, LOG_PID);
-#else
-#ifndef LOG_AUTH
-#define LOG_AUTH 0
-#endif
- openlog(progname, LOG_PID | LOG_ODELAY, LOG_AUTH);
-#endif /* 4.2 syslog */
-
-#ifdef KERBEROS
- status = krb5_init_context(&bsd_context);
- if (status) {
- syslog(LOG_ERR, "Error initializing krb5: %s",
- error_message(status));
- exit(1);
- }
-#endif
-
- /* Analyze parameters. */
- opterr = 0;
- while ((ch = getopt(argc, argv, ARGSTR)) != -1)
- switch (ch) {
-#ifdef KERBEROS
- case 'k':
- break;
-
- case '5':
- break;
- case 'c':
- checksum_required = 1;
- break;
- case 'i':
- checksum_ignored = 1;
- break;
-
- case 'e':
- require_encrypt = 1;
- break;
-
- case 'S':
- if ((status = krb5_kt_resolve(bsd_context, optarg, &keytab))) {
- com_err(progname, status, "while resolving srvtab file %s",
- optarg);
- exit(2);
- }
- break;
-
- case 'M':
- krb5_set_default_realm(bsd_context, optarg);
- break;
-
- case 'A':
- anyport = 1;
- break;
-
- case 'P':
- kprogdir = optarg;
- break;
-
- case 'L':
- if (num_env < MAXENV) {
- save_env[num_env] = strdup(optarg);
- if(!save_env[num_env++]) {
- com_err(progname, ENOMEM, "in saving environment");
- exit(2);
- }
- } else {
- fprintf(stderr, "%s: Only %d -L arguments allowed\n",
- progname, MAXENV);
- exit(2);
- }
- break;
-#endif
- case 'D':
- debug_port = atoi(optarg);
- break;
- case 'w':
- if (!strcmp(optarg, "ip"))
- always_ip = 1;
- else {
- char *cp;
- cp = strchr(optarg, ',');
- if (cp == NULL)
- maxhostlen = atoi(optarg);
- else if (*(++cp)) {
- if (!strcmp(cp, "striplocal"))
- stripdomain = 1;
- else if (!strcmp(cp, "nostriplocal"))
- stripdomain = 0;
- else {
- usage();
- exit(1);
- }
- *(--cp) = '\0';
- maxhostlen = atoi(optarg);
- }
- }
- break;
- case '?':
- default:
- usage();
- exit(1);
- break;
- }
-
- if (optind == 0) {
- usage();
- exit(1);
- }
-
- argc -= optind;
- argv += optind;
-
- fromlen = sizeof (from);
-
- if (debug_port)
- fd = accept_a_connection(debug_port, (struct sockaddr *)&from,
- &fromlen);
- else {
- if (getpeername(0, (struct sockaddr *)&from, &fromlen) < 0) {
- fprintf(stderr, "%s: ", progname);
- perror("getpeername");
- _exit(1);
- }
-
- fd = 0;
- }
-
-/*
- * AIX passes an IPv4-mapped IPv6 address back from getpeername, but if
- * that address is later used in connect(), it returns an error. Convert
- * IPv4-mapped IPv6 addresses to simple IPv4 addresses on AIX (but don't
- * do this everywhere since it isn't always the right thing to do, just
- * the least wrong on AIX).
- */
-#if defined(_AIX) && defined(KRB5_USE_INET6)
- if (((struct sockaddr*)&from)->sa_family == AF_INET6 && IN6_IS_ADDR_V4MAPPED(&sa2sin6(&from)->sin6_addr)) {
- sa2sin(&from)->sin_len = sizeof(struct sockaddr_in);
- sa2sin(&from)->sin_family = AF_INET;
- sa2sin(&from)->sin_port = sa2sin6(&from)->sin6_port;
- memmove(&(sa2sin(&from)->sin_addr.s_addr), &(sa2sin6(&from)->sin6_addr.u6_addr.u6_addr8[12]), 4);
- }
-#endif
-
- if (setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, (char *)&on,
- sizeof (on)) < 0)
- syslog(LOG_WARNING, "setsockopt (SO_KEEPALIVE): %m");
-#if defined(BSD) && BSD+0 >= 43
- linger.l_onoff = 1;
- linger.l_linger = 60; /* XXX */
- if (setsockopt(fd, SOL_SOCKET, SO_LINGER, (char *)&linger,
- sizeof (linger)) < 0)
- syslog(LOG_WARNING , "setsockopt (SO_LINGER): %m");
-#endif
-
- if (checksum_required&&checksum_ignored) {
- syslog(LOG_CRIT, "Checksums are required and ignored; these options are mutually exclusive--check the documentation.");
- fatal(fd, "Configuration error: mutually exclusive options specified");
- }
-
- doit(dup(fd), (struct sockaddr *) &from);
- return 0;
-}
-
-#ifdef CRAY
-char username[32] = "LOGNAME=";
-#include <tmpdir.h>
-char tmpdir[64] = "TMPDIR=";
-#else
-char username[20] = "USER=";
-#endif
-
-char homedir[64] = "HOME=";
-char shell[64] = "SHELL=";
-char term[64] = "TERM=network";
-char path_rest[] = RPATH;
-
-char remote_addr[64+NI_MAXHOST]; /* = "KRB5REMOTEADDR=" */
-char remote_port[64+NI_MAXSERV]; /* = "KRB5REMOTEPORT=" */
-char local_addr[64+NI_MAXHOST]; /* = "KRB5LOCALADDR=" */
-char local_port[64+NI_MAXSERV]; /* = "KRB5LOCALPORT=" */
-#define ADDRPAD 0,0,0,0
-#define KRBPAD 0 /* KRB5CCNAME, optional */
-
-/* The following include extra space for TZ and MAXENV pointers... */
-#define COMMONVARS homedir, shell, 0/*path*/, username, term
-#ifdef CRAY
-char *envinit[] =
-{COMMONVARS, "TZ=GMT0", tmpdir, SAVEENVPAD, KRBPAD, ADDRPAD, 0};
-#define TMPDIRENV 6
-char *getenv();
-#else /* CRAY */
-#ifdef KERBEROS
-char *envinit[] =
-{COMMONVARS, 0/*tz*/, SAVEENVPAD, KRBPAD, ADDRPAD, 0};
-#else /* KERBEROS */
-char *envinit[] =
-{COMMONVARS, 0/*tz*/, SAVEENVPAD, ADDRPAD, 0};
-#endif /* KERBEROS */
-#endif /* CRAY */
-
-#define TZENV 5
-#define PATHENV 2
-
-extern char **environ;
-char ttyn[12]; /* Line string for wtmp entries */
-
-#ifdef CRAY
-#define SIZEOF_INADDR SIZEOF_in_addr
-int maxlogs;
-#else
-#define SIZEOF_INADDR sizeof(struct in_addr)
-#endif
-
-#ifndef NCARGS
-/* linux doesn't seem to have it... */
-#define NCARGS 1024
-#endif
-
-#define NMAX 16
-
-int pid;
-char locuser[NMAX+1];
-char remuser[NMAX +1];
-char cmdbuf[NCARGS+1];
-char *kremuser;
-krb5_principal client;
-krb5_authenticator *kdata;
-
-static void
-ignore_signals()
-{
-#ifdef POSIX_SIGNALS
- struct sigaction sa;
-
- (void)sigemptyset(&sa.sa_mask);
- sa.sa_flags = 0;
- sa.sa_handler = SIG_IGN;
- (void)sigaction(SIGINT, &sa, (struct sigaction *)0);
- (void)sigaction(SIGQUIT, &sa, (struct sigaction *)0);
- (void)sigaction(SIGTERM, &sa, (struct sigaction *)0);
- (void)sigaction(SIGPIPE, &sa, (struct sigaction *)0);
- (void)sigaction(SIGHUP, &sa, (struct sigaction *)0);
-
- (void)kill(-pid, SIGTERM);
-#else
- signal(SIGINT, SIG_IGN);
- signal(SIGQUIT, SIG_IGN);
- signal(SIGTERM, SIG_IGN);
- signal(SIGPIPE, SIG_IGN);
- signal(SIGHUP, SIG_IGN);
-
- killpg(pid, SIGTERM);
-#endif
-}
-
-static krb5_sigtype
-cleanup(signumber)
- int signumber;
-{
- ignore_signals();
- wait(0);
-
- pty_logwtmp(ttyn,"","");
- syslog(LOG_INFO ,"Daemon terminated via signal %d.", signumber);
- if (ccache)
- krb5_cc_destroy(bsd_context, ccache);
- exit(0);
-}
-
-
-void doit(f, fromp)
- int f;
- struct sockaddr *fromp;
-{
- char *cp;
-#ifdef KERBEROS
- krb5_error_code status;
-#endif
- int valid_checksum;
- int cnt;
- char *crypt();
- struct passwd *pwd;
- char *path;
-#ifdef CRAY
-#ifndef NO_UDB
- struct udb *ue;
- struct udb ue_static;
- extern struct udb *getudbnam();
-#endif
- extern struct passwd *getpwnam(), *getpwuid();
- static int jid;
- int error();
- int paddr;
- struct nal nal;
- int nal_error;
- struct usrv usrv;
- struct sysv sysv;
- char *makejtmp(), *jtmpnam = 0;
- int packet_level; /* Packet classification level */
- long packet_compart; /* Packet compartments */
-#endif /* CRAY */
-
- int s = -1;
- char hostname[NI_MAXHOST];
- char *sane_host;
- char hostaddra[NI_MAXHOST];
- int aierr;
- short port;
- int pv[2], pw[2], px[2], cc;
- fd_set ready, readfrom;
- char buf[RCMD_BUFSIZ], sig;
- struct sockaddr_storage localaddr;
-#ifdef POSIX_SIGNALS
- struct sigaction sa;
-#endif
-
-#ifdef IP_TOS
-/* solaris has IP_TOS, but only IPTOS_* values */
-#ifdef HAVE_GETTOSBYNAME
- struct tosent *tp;
-
-
- if ((tp = gettosbyname("interactive", "tcp")) &&
- (setsockopt(f, IPPROTO_IP, IP_TOS, &tp->t_tos, sizeof(int)) < 0))
-#ifdef TOS_WARN
- syslog(LOG_NOTICE, "setsockopt (IP_TOS): %m");
-#else
- ; /* silently ignore TOS errors in 6E */
-#endif
-#endif
-#endif /* IP_TOS */
-
- {
- socklen_t sin_len = sizeof (localaddr);
- if (getsockname(f, (struct sockaddr*)&localaddr, &sin_len) < 0) {
- perror("getsockname");
- exit(1);
- }
- }
-
-#ifdef POSIX_SIGNALS
- (void)sigemptyset(&sa.sa_mask);
- sa.sa_flags = 0;
- sa.sa_handler = SIG_DFL;
- (void)sigaction(SIGINT, &sa, (struct sigaction *)0);
- (void)sigaction(SIGQUIT, &sa, (struct sigaction *)0);
- (void)sigaction(SIGTERM, &sa, (struct sigaction *)0);
-#else
- signal(SIGINT, SIG_DFL);
- signal(SIGQUIT, SIG_DFL);
- signal(SIGTERM, SIG_DFL);
-#endif
-#ifdef DEBUG
- { int t = open("/dev/tty", 2);
- if (t >= 0) {
- ioctl(t, TIOCNOTTY, (char *)0);
- (void) close(t);
- }
- }
-#endif
- if (fromp->sa_family != AF_INET
-#if defined(KRB5_USE_INET6) && defined(KERBEROS)
- && fromp->sa_family != AF_INET6
-#endif
- ) {
- syslog(LOG_ERR , "malformed from address\n");
- exit(1);
- }
-#ifdef KERBEROS
- netf = f;
-#else
- {
- struct sockaddr_in *frompin = sa2sin(fromp);
- frompin->sin_port = ntohs((u_short)frompin->sin_port);
- if (frompin->sin_port >= IPPORT_RESERVED ||
- frompin->sin_port < IPPORT_RESERVED/2) {
- syslog(LOG_ERR , "connection from bad port\n");
- exit(1);
- }
- }
-#endif /* KERBEROS */
-
-#ifdef CRAY
-
- /* If this is a secure system then get the packet classification
- of f. ( Note IP_SECURITY is checked in get_packet_classification:
- if it's not set then the user's (root) default
- classification level and compartments are returned. )
- Then set this process to that level/compart so that the stderr
- connection will be labeled appropriately.
- */
- if (secflag) {
- if (get_packet_classification(f,getuid(),
- &packet_level,&packet_compart) < 0) {
- syslog(LOG_ERR, "cannot get ip packet level\n");
- exit(1);
- }
- if(secflag == TFM_UDB_5) {
- if(setucmp(packet_compart, C_PROC) != 0) {
- error("Unable to setucmp.\n");
- exit(1);
- }
- } else if(secflag == TFM_UDB_6) {
- if(setulvl(packet_level,C_PROC) != 0) {
- error("Unable to setulvl.\n");
- exit(1);
- }
- if(setucmp(packet_compart, C_PROC) != 0) {
- error("Unable to setucmp.\n");
- exit(1);
- }
- }
-
- }
-#endif /* CRAY */
-
- (void) alarm(60);
- port = 0;
- for (;;) {
- char c;
- if ((cc = read(f, &c, 1)) != 1) {
- if (cc < 0)
- syslog(LOG_NOTICE , "read: %m");
- shutdown(f, 1+1);
- exit(1);
- }
- if (c == 0)
- break;
- port = port * 10 + c - '0';
- }
- (void) alarm(0);
- if (port != 0) {
- if (anyport) {
- int addrfamily = fromp->sa_family;
- s = getport(0, &addrfamily);
- } else {
- int lport = IPPORT_RESERVED - 1;
-#ifdef HAVE_RRESVPORT_AF
- s = rresvport_af(&lport, fromp->sa_family);
-#else
- s = rresvport(&lport);
-#endif
- }
- if (s < 0) {
- syslog(LOG_ERR ,
- "can't get stderr port: %m");
- exit(1);
- }
-#ifndef KERBEROS
- if (port >= IPPORT_RESERVED) {
- syslog(LOG_ERR , "2nd port not reserved\n");
- exit(1);
- }
-#endif /* KERBEROS */
- switch (fromp->sa_family) {
- case AF_INET:
- sa2sin(fromp)->sin_port = htons((u_short)port);
- break;
-#ifdef KRB5_USE_INET6
- case AF_INET6:
- sa2sin6(fromp)->sin6_port = htons((u_short)port);
- break;
-#endif
- }
- if (connect(s, (struct sockaddr *)fromp, socklen(fromp)) < 0) {
- syslog(LOG_INFO ,
- "connect second port: %m");
- exit(1);
- }
- }
- dup2(f, 0);
- dup2(f, 1);
- dup2(f, 2);
- aierr = getnameinfo(fromp, socklen(fromp), hostname, sizeof(hostname),
- 0, 0, 0);
- if (aierr) {
- error("failed to get remote host address: %s", gai_strerror(aierr));
- exit(1);
- }
- aierr = getnameinfo(fromp, socklen(fromp), hostaddra, sizeof(hostaddra),
- 0, 0, NI_NUMERICHOST);
- if (aierr) {
- error("failed to get remote host address: %s", gai_strerror(aierr));
- exit(1);
- }
-
-#ifdef KERBEROS
- status = pty_make_sane_hostname((struct sockaddr *) fromp, maxhostlen,
- stripdomain, always_ip, &sane_host);
- if (status) {
- error("failed make_sane_hostname: %s\n", error_message(status));
- exit(1);
- }
-
- if ((status = recvauth(f, fromp, &valid_checksum))) {
- error("Authentication failed: %s\n", error_message(status));
- exit(1);
- }
-#else
- getstr(f, remuser, sizeof(remuser), "remuser");
- getstr(f, locuser, sizeof(locuser), "locuser");
- getstr(f, cmdbuf, sizeof(cmdbuf), "command");
- rcmd_stream_init_normal();
-#endif /* KERBEROS */
-
-#ifdef CRAY
- paddr = inet_addr(inet_ntoa(fromp->sin_addr));
- if(secflag){
- /*
- * check network authorization list
- */
- if (fetchnal(paddr,&nal) < 0) {
- /*
- * NAL file inaccessible, abort connection.
- */
- error("Permission denied.\n");
- exit(1);
- }
- }
-#endif /* CRAY */
-
- pwd = getpwnam(locuser);
- if (pwd == (struct passwd *) 0 ) {
- syslog(LOG_ERR ,
- "Principal %s (%s@%s (%s)) for local user %s has no account.\n",
- kremuser, remuser, hostaddra, hostname,
- locuser); /* xxx sprintf buffer in syslog*/
- error("Login incorrect.\n");
- exit(1);
- }
-
-#ifdef CRAY
- /* Setup job entry, and validate udb entry.
- ( against packet level also ) */
- if ((jid = setjob(pwd->pw_uid, 0)) < 0) {
- error("Unable to create new job.\n");
- exit(1);
- }
- if ((jtmpnam = makejtmp(pwd->pw_uid, pwd->pw_gid, jid))) {
- register int pid, tpid;
- int status;
- switch(pid = fork()) {
- case -1:
- cleanjtmp(locuser, jtmpnam);
- envinit[TMPDIRENV] = 0;
- break;
- case 0:
- break;
- default:
- close(0);
- close(1);
- close(2);
- close(f);
- if (port)
- close(s);
- while ((tpid = wait(&status)) != pid) {
- if (tpid < 0)
- break;
- }
- cleanjtmp(locuser, jtmpnam);
- exit(status>>8);
- /* NOTREACHED */
- }
- } else {
- envinit[TMPDIRENV] = 0;
- }
-#ifndef NO_UDB
- (void)getsysudb();
-
- if ((ue = getudbnam(pwd->pw_name)) == (struct udb *)NULL) {
- error("Unable to fetch account id.\n");
- exit(1);
- }
- ue_static = *ue; /* save from setlimits call */
- endudb();
- if (secflag) {
- if(getsysv(&sysv, sizeof(struct sysv)) != 0) {
- loglogin(sane_host, SLG_LLERR, 0, ue);
- error("Permission denied.\n");
- exit(1);
- }
- if ((packet_level != ue->ue_deflvl) ||
- ((packet_compart & ue->ue_comparts) != packet_compart )){
- loglogin(sane_host, SLG_LLERR, 0, ue);
- error("Permission denied.\n");
- exit(1);
- }
- if (ue->ue_disabled != 0) {
- loglogin(sane_host,SLG_LOCK,ue->ue_logfails,ue);
- error("Permission denied.\n");
- exit(1);
- }
- maxlogs = sysv.sy_maxlogs;
- }
- if (acctid(getpid(), ue->ue_acids[0]) == -1) {
- error("Unable to set account id.\n");
- exit(1);
- }
- if (setshares(pwd->pw_uid, acctid(0, -1), error, 1, 0)) {
- error("Unable to set shares.\n");
- exit(1);
- }
- if (setlimits(pwd->pw_name, C_PROC, getpid(), UDBRC_INTER)) {
- error("Unable to set limits.\n");
- exit(1);
- }
- if (setlimits(pwd->pw_name, C_JOB, jid, UDBRC_INTER)) {
- error("Unable to set limits.\n");
- exit(1);
- }
- ue = &ue_static; /* restore after setlimits call */
- endudb(); /* setlimits opens udb and leaves it
- open so close it here. */
-#endif /* !NO_UDB */
-#endif /*CRAY*/
-
- /* Setup wtmp entry : we do it here so that if this is a CRAY
- the Process Id is correct and we have not lost our trusted
- privileges. */
- if (port) {
- /* Place entry into wtmp */
- snprintf(ttyn,sizeof(ttyn),"krsh%ld",(long) (getpid() % 9999999));
- pty_logwtmp(ttyn,locuser,sane_host);
- }
- /* We are simply execing a program over rshd : log entry into wtmp,
- as kexe(pid), then finish out the session right after that.
- Syslog should have the information as to what was exec'd */
- else {
- pty_logwtmp(ttyn,locuser,sane_host);
- }
-
-#ifdef CRAY
-
- /* If we are a secure system then we need to get rid of our
- trusted facility, so that MAC on the chdir we work. Before we
- do this make an entry into wtmp, and any other audit recording. */
-
- if (secflag) {
- if (getusrv(&usrv)){
- syslog(LOG_ERR,"Cannot getusrv");
- error("Permission denied.\n");
- loglogin(sane_host, SLG_LVERR, ue->ue_logfails,ue);
- goto signout_please;
- }
- /*
- * 6.0 no longer allows any form ofTRUSTED_PROCESS logins.
- */
- if((ue->ue_valcat & TFM_TRUSTED) ||
- (sysv.sy_oldtfm &&
- ((ue->ue_comparts & TRUSTED_SUBJECT) == TRUSTED_SUBJECT))) {
- loglogin(sane_host, SLG_TRSUB, ue->ue_logfails,ue);
- error("Permission denied.\n");
- goto signout_please;
- }
-
- loglogin(sane_host, SLG_OKLOG, ue->ue_logfails,ue);
-
- /* Setup usrv structure with user udb info and
- packet_level and packet_compart. */
- usrv.sv_actlvl = packet_level;
- usrv.sv_actcmp = packet_compart; /*Note get_packet_level sets
- compartment to users default
- compartments....*/
- usrv.sv_permit = ue->ue_permits;
- usrv.sv_intcls = ue->ue_intcls;
- usrv.sv_maxcls = ue->ue_maxcls;
- usrv.sv_intcat = ue->ue_intcat;
- usrv.sv_valcat = ue->ue_valcat;
- usrv.sv_savcmp = 0;
- usrv.sv_savlvl = 0;
-
- /*
- * Set user values to workstation boundaries
- */
-#ifdef MIN
-#undef MIN
-#endif
-#ifdef MAX
-#undef MAX
-#endif
-
-#define MIN(a,b) ((a) < (b) ? (a) : (b))
-#define MAX(a,b) ((a) > (b) ? (a) : (b))
-
- nal_error = 0;
-
- if (nal.na_sort) {
- if ((ue->ue_minlvl > nal.na_smax) ||
- (ue->ue_maxlvl < nal.na_smin))
- nal_error++;
- else {
- usrv.sv_minlvl=MAX(ue->ue_minlvl, nal.na_smin);
- usrv.sv_maxlvl=MIN(ue->ue_maxlvl, nal.na_smax);
-
-#ifndef IP_SECURITY
-
- if (usrv.sv_actlvl < usrv.sv_minlvl)
- usrv.sv_actlvl = usrv.sv_minlvl;
- if (usrv.sv_actlvl > usrv.sv_maxlvl)
- usrv.sv_actlvl = usrv.sv_maxlvl;
-
-#else /*IP_SECURITY*/
- if (usrv.sv_actlvl < usrv.sv_minlvl)
- nal_error++;
- if (usrv.sv_actlvl > usrv.sv_maxlvl)
- nal_error++;
- if (usrv.sv_actlvl != ue->ue_deflvl)
- nal_error++;
-
- usrv.sv_valcmp = ue->ue_comparts & nal.na_scmp;
- usrv.sv_actcmp &= nal.na_scmp;
-#endif /*IP_SECURITY*/
- usrv.sv_valcmp = ue->ue_comparts & nal.na_scmp;
- usrv.sv_actcmp = (usrv.sv_valcmp &
- ue->ue_defcomps);
- }
- } else {
- /*
- * If the user's minimum level is greater than
- * zero, they cannot log on from this (ie. an
- * unclassified) host.
- */
- if (ue->ue_minlvl > 0)
- nal_error++;
- /*
- * Address not in NAL, if EXEMPT_NAL is not
- * true, then even an unclassified user is
- * not allowed.
- */
- if (!EXEMPT_NAL)
- nal_error++;
- else {
- usrv.sv_minlvl = 0;
- usrv.sv_maxlvl = 0;
- usrv.sv_valcmp = 0;
- usrv.sv_actcmp = 0;
- usrv.sv_actlvl = 0;
- }
- }
- if (nal_error) {
- loglogin(sane_host, SLG_LVERR, ue->ue_logfails,ue);
- error("Permission denied.\n");
- goto signout_please;
- }
-#undef MIN
-#undef MAX
- /* Before the setusrv is done then do a sethost for paddr */
- sethost(paddr);
-
- if (setusrv(&usrv) == -1) {
- loglogin(sane_host, SLG_LVERR, ue->ue_logfails,ue);
- error("Permission denied.\n");
- goto signout_please;
- }
- if (getusrv(&usrv) == -1) {
- error("Getusrv Permission denied.\n");
- goto signout_please;
- }
-
- }
-#endif /*CRAY*/
-
- if (chdir(pwd->pw_dir) < 0) {
- if(chdir("/") < 0) {
- error("No remote directory.\n");
- goto signout_please;
- }
- pwd->pw_dir = "/";
- }
-
-#ifdef KERBEROS
- /* krb5_kuserok returns 1 if OK */
- if (!krb5_kuserok(bsd_context, client, locuser)){
- syslog(LOG_ERR ,
- "Principal %s (%s@%s (%s)) for local user %s failed krb5_kuserok.\n",
- kremuser, remuser, hostaddra, hostname, locuser);
- error("Permission denied.\n");
- goto signout_please;
- }
-#else
- if (pwd->pw_passwd != 0 && *pwd->pw_passwd != '\0' &&
- ruserok(hostname[0] ? hostname : hostaddra,
- pwd->pw_uid == 0, remuser, locuser) < 0) {
- error("Permission denied.\n");
- goto signout_please;
- }
-#endif /* KERBEROS */
-
-
- if (checksum_required && !valid_checksum) {
- syslog(LOG_WARNING, "Client did not supply required checksum--connection rejected.");
- error( "You are using an old Kerberos5 client without checksum support; only newer clients are authorized.\n");
- goto signout_please;
- }
- if (require_encrypt&&(!do_encrypt)) {
- error("You must use encryption.\n");
- goto signout_please;
- }
-
- if (pwd->pw_uid && !access(NOLOGIN, F_OK)) {
- error("Logins currently disabled.\n");
- goto signout_please;
- }
-
- /* Log access to account */
- pwd = (struct passwd *) getpwnam(locuser);
- if (pwd && (pwd->pw_uid == 0)) {
-#ifdef LOG_CMD
- syslog(LOG_NOTICE, "Executing %s for principal %s (%s@%s (%s)) as ROOT",
- cmdbuf, kremuser, remuser, hostaddra, hostname);
-#else
- syslog(LOG_NOTICE ,"Access as ROOT by principal %s (%s@%s (%s))",
- kremuser, remuser, hostaddra, hostname);
-#endif
- }
-#if defined(KERBEROS) && defined(LOG_REMOTE_REALM) && !defined(LOG_OTHER_USERS) && !defined(LOG_ALL_LOGINS)
- /* Log if principal is from a remote realm */
- else if (client && !default_realm(client))
-#endif
-
-#if defined(KERBEROS) && defined(LOG_OTHER_USERS) && !defined(LOG_ALL_LOGINS)
- /* Log if principal name does not map to local username */
- else if (client && !princ_maps_to_lname(client, locuser))
-#endif /* LOG_OTHER_USERS */
-
-#ifdef LOG_ALL_LOGINS /* Log everything */
- else
-#endif
-
-#if defined(LOG_REMOTE_REALM) || defined(LOG_OTHER_USERS) || defined(LOG_ALL_LOGINS)
- {
-#ifdef LOG_CMD
- syslog(LOG_NOTICE, "Executing %s for principal %s (%s@%s (%s)) as local user %s",
- cmdbuf, kremuser, remuser, hostaddra, hostname, locuser);
-#else
- syslog(LOG_NOTICE ,"Access as %s by principal %s (%s@%s (%s))",
- locuser, kremuser, remuser, hostaddra, hostname);
-#endif
- }
-#endif
-
- (void) write(2, "", 1);
-
- if (port||do_encrypt) {
- if (port&&(pipe(pv) < 0)) {
- error("Can't make pipe.\n");
- goto signout_please;
- }
- if (pipe(pw) < 0) {
- error("Can't make pipe 2.\n");
- goto signout_please;
- }
- if (pipe(px) < 0) {
- error("Can't make pipe 3.\n");
- goto signout_please;
- }
- pid = fork();
- if (pid == -1) {
- error("Fork failed.\n");
- goto signout_please;
- }
- if (pid) {
- int maxfd;
-#ifdef POSIX_SIGNALS
- sa.sa_handler = cleanup;
- (void)sigaction(SIGINT, &sa, (struct sigaction *)0);
- (void)sigaction(SIGQUIT, &sa, (struct sigaction *)0);
- (void)sigaction(SIGTERM, &sa, (struct sigaction *)0);
- (void)sigaction(SIGHUP, &sa, (struct sigaction *)0);
-
- sa.sa_handler = SIG_IGN;
- /* SIGPIPE is a crutch that we don't need if we check
- the exit status of write. */
- (void)sigaction(SIGPIPE, &sa, (struct sigaction *)0);
- (void)sigaction(SIGCHLD, &sa, (struct sigaction *)0);
-#else
- signal(SIGINT, cleanup);
- signal(SIGQUIT, cleanup);
- signal(SIGTERM, cleanup);
- signal(SIGHUP, cleanup);
- /* SIGPIPE is a crutch that we don't need if we check
- the exit status of write. */
- signal(SIGPIPE, SIG_IGN);
- signal(SIGCHLD,SIG_IGN);
-#endif
-
- (void) close(0); (void) close(1); (void) close(2);
- if(port)
- (void) close(pv[1]);
- (void) close(pw[1]);
- (void) close(px[0]);
-
-
-
- FD_ZERO(&readfrom);
- FD_SET(f, &readfrom);
- maxfd = f;
- if(port) {
- FD_SET(s, &readfrom);
- if (s > maxfd)
- maxfd = s;
- FD_SET(pv[0], &readfrom);
- if (pv[0] > maxfd)
- maxfd = pv[0];
- }
- FD_SET(pw[0], &readfrom);
- if (pw[0] > maxfd)
- maxfd = pw[0];
-
- /* read from f, write to px[1] -- child stdin */
- /* read from s, signal child */
- /* read from pv[0], write to s -- child stderr */
- /* read from pw[0], write to f -- child stdout */
-
- do {
- ready = readfrom;
- if (select(maxfd + 1, &ready, (fd_set *)0,
- (fd_set *)0, (struct timeval *)0) < 0) {
- if (errno == EINTR) {
- continue;
- } else {
- break;
- }
- }
-
- if (port&&FD_ISSET(pv[0], &ready)) {
- /* read from the child stderr, write to the net */
- errno = 0;
- cc = read(pv[0], buf, sizeof (buf));
- if (cc <= 0) {
- shutdown(s, 1+1);
- FD_CLR(pv[0], &readfrom);
- } else {
- (void) rcmd_stream_write(s, buf, (unsigned) cc, 1);
- }
- }
- if (FD_ISSET(pw[0], &ready)) {
- /* read from the child stdout, write to the net */
- errno = 0;
- cc = read(pw[0], buf, sizeof (buf));
- if (cc <= 0) {
- shutdown(f, 1+1);
- FD_CLR(pw[0], &readfrom);
- } else {
- (void) rcmd_stream_write(f, buf, (unsigned) cc, 0);
- }
- }
- if (port&&FD_ISSET(s, &ready)) {
- /* read from the alternate channel, signal the child */
- if (rcmd_stream_read(s, &sig, 1, 1) <= 0) {
- FD_CLR(s, &readfrom);
- } else {
-#ifdef POSIX_SIGNALS
- sa.sa_handler = cleanup;
- (void)sigaction(sig, &sa, (struct sigaction *)0);
- kill(-pid, sig);
-#else
- signal(sig, cleanup);
- killpg(pid, sig);
-#endif
- }
- }
- if (FD_ISSET(f, &ready)) {
- /* read from the net, write to child stdin */
- errno = 0;
- cc = rcmd_stream_read(f, buf, sizeof(buf), 0);
- if (cc <= 0) {
- (void) close(px[1]);
- FD_CLR(f, &readfrom);
- } else {
- int wcc;
- wcc = write(px[1], buf, (unsigned) cc);
- if (wcc == -1) {
- /* pipe closed, don't read any more */
- /* might check for EPIPE */
- (void) close(px[1]);
- FD_CLR(f, &readfrom);
- } else if (wcc != cc) {
- syslog(LOG_INFO, "only wrote %d/%d to child",
- wcc, cc);
- }
- }
- }
- } while ((port&&FD_ISSET(s, &readfrom)) ||
- FD_ISSET(f, &readfrom) ||
- (port&&FD_ISSET(pv[0], &readfrom) )||
- FD_ISSET(pw[0], &readfrom));
- ignore_signals();
-#ifdef KERBEROS
- syslog(LOG_INFO ,
- "Shell process completed.");
-#endif
- /* Finish session in wmtp */
- pty_logwtmp(ttyn,"","");
- if (ccache)
- krb5_cc_destroy(bsd_context, ccache);
- exit(0);
- }
-#if defined(HAVE_SETSID)&&(!defined(ULTRIX))
- setsid();
-#else
-#ifdef SETPGRP_TWOARG
- setpgrp(0, getpid());
-#else
- setpgrp();
-#endif /*setpgrp_twoarg*/
-#endif /*HAVE_SETSID*/
- (void) close(s);
- (void) close(f);
- (void) close(pw[0]);
- if (port)
- (void) close(pv[0]);
- (void) close(px[1]);
-
- (void) dup2(px[0], 0);
- (void) dup2(pw[1], 1);
- if(port)
- (void) dup2(pv[1], 2);
- else dup2(pw[1], 2);
-
- (void) close(px[0]);
- (void) close(pw[1]);
- if(port)
- (void) close(pv[1]);
- }
-
- /* We are simply execing a program over rshd : log entry into wtmp,
- as kexe(pid), then finish out the session right after that.
- Syslog should have the information as to what was exec'd */
- else {
- pty_logwtmp(ttyn,"","");
- }
-
- if (*pwd->pw_shell == '\0')
- pwd->pw_shell = "/bin/sh";
- (void) close(f);
- (void) setgid((gid_t)pwd->pw_gid);
-#ifndef sgi
- if (getuid() == 0 || getuid() != pwd->pw_uid) {
- /* For testing purposes, we don't call initgroups if we
- already have the right uid, and it is not root. This is
- because on some systems initgroups outputs an error message
- if not called by root. */
- initgroups(pwd->pw_name, pwd->pw_gid);
- }
-#endif
-#ifdef HAVE_SETLUID
- /*
- * If we're on a system which keeps track of login uids, then
- * set the login uid.
- */
- if (setluid((uid_t) pwd->pw_uid) < 0) {
- perror("setluid");
- _exit(1);
- }
-#endif /* HAVE_SETLUID */
- if (setuid((uid_t)pwd->pw_uid) < 0) {
- perror("setuid");
- _exit(1);
- }
- /* if TZ is set in the parent, drag it in */
- {
- char **findtz = environ;
- while(*findtz) {
- if(!strncmp(*findtz,"TZ=",3)) {
- envinit[TZENV] = *findtz;
- break;
- }
- findtz++;
- }
- }
- strncat(homedir, pwd->pw_dir, sizeof(homedir)-6);
- strncat(shell, pwd->pw_shell, sizeof(shell)-7);
- strncat(username, pwd->pw_name, sizeof(username)-6);
- if (asprintf(&path, "PATH=%s:%s", kprogdir, path_rest) < 0) {
- perror("malloc");
- _exit(1);
- }
- envinit[PATHENV] = path;
-
- /* If we have KRB5CCNAME set, then copy into the
- * child's environment. This can't really have
- * a fixed position because tz may or may not be set.
- */
- if (getenv("KRB5CCNAME")) {
- int i;
- char *buf2;
- if (asprintf(&buf2, "KRB5CCNAME=%s",getenv("KRB5CCNAME")) >= 0) {
-
- for (i = 0; envinit[i]; i++);
- envinit[i] = buf2;
- }
- }
-
- {
- char hbuf[NI_MAXHOST], sbuf[NI_MAXSERV];
- int i;
- /* these four are covered by ADDRPAD */
-
- for (i = 0; envinit[i]; i++);
-
- aierr = getnameinfo((struct sockaddr *)&localaddr,
- socklen((struct sockaddr *)&localaddr),
- hbuf, sizeof(hbuf), sbuf, sizeof(sbuf),
- NI_NUMERICHOST | NI_NUMERICSERV);
- if (aierr)
- goto skip_localaddr_env;
- snprintf(local_addr, sizeof(local_addr), "KRB5LOCALADDR=%s", hbuf);
- envinit[i++] =local_addr;
-
- snprintf(local_port, sizeof(local_port), "KRB5LOCALPORT=%s", sbuf);
- envinit[i++] =local_port;
- skip_localaddr_env:
-
- aierr = getnameinfo(fromp, socklen(fromp),
- hbuf, sizeof(hbuf), sbuf, sizeof(sbuf),
- NI_NUMERICHOST | NI_NUMERICSERV);
- if (aierr)
- goto skip_remoteaddr_env;
- snprintf(remote_addr, sizeof(remote_addr), "KRB5REMOTEADDR=%s", hbuf);
- envinit[i++] =remote_addr;
-
- snprintf(remote_port, sizeof(remote_port), "KRB5REMOTEPORT=%s", sbuf);
- envinit[i++] =remote_port;
-
- skip_remoteaddr_env:
- ;
- }
-
- /* If we do anything else, make sure there is space in the array. */
-
- for(cnt=0; cnt < num_env; cnt++) {
- int i;
- char *buf2;
-
- if(getenv(save_env[cnt])) {
- if (asprintf(&buf2, "%s=%s", save_env[cnt],
- getenv(save_env[cnt])) >= 0) {
- for (i = 0; envinit[i]; i++);
- envinit[i] = buf2;
- }
- }
- }
-
- /* XXX - If we do anything else, make sure there is space in the array. */
-
- environ = envinit;
-
-#ifdef KERBEROS
- /* To make Kerberos rcp work correctly, we must ensure that we
- invoke Kerberos rcp on this end, not normal rcp, even if the
- shell startup files change PATH. */
- if (!strncmp(cmdbuf, "rcp ", 4) ||
- (do_encrypt && !strncmp(cmdbuf, "-x rcp ", 7))) {
- char *copy;
- struct stat s2;
- int offst = 0;
-
- copy = strdup(cmdbuf);
- if (copy == NULL) {
- perror("malloc");
- _exit(1);
- }
- if (do_encrypt && !strncmp(cmdbuf, "-x ", 3)) {
- offst = 3;
- }
-
- strlcpy(cmdbuf + offst, kprogdir, sizeof(cmdbuf) - offst);
- cp = copy + 3 + offst;
-
- strlcat(cmdbuf, "/rcp", sizeof(cmdbuf));
-
- if (stat((char *)cmdbuf + offst, &s2) >= 0)
- strlcat(cmdbuf, cp, sizeof(cmdbuf));
- else
- strlcpy(cmdbuf, copy, sizeof(cmdbuf));
- free(copy);
- }
-#endif
-
- cp = strrchr(pwd->pw_shell, '/');
- if (cp)
- cp++;
- else
- cp = pwd->pw_shell;
-
- if (do_encrypt && !strncmp(cmdbuf, "-x ", 3)) {
- execl(pwd->pw_shell, cp, "-c", (char *)cmdbuf + 3, (char *)NULL);
- }
- else {
- execl(pwd->pw_shell, cp, "-c", cmdbuf, (char *)NULL);
- }
- perror(pwd->pw_shell);
- perror(cp);
- exit(1);
-
- signout_please:
- if (ccache)
- krb5_cc_destroy(bsd_context, ccache);
- ccache = NULL;
- pty_logwtmp(ttyn,"","");
- exit(1);
-}
-
-
-void
-#ifdef HAVE_STDARG_H
-error(char *fmt, ...)
-#else
-/*VARARGS1*/
-error(fmt, va_alist)
- char *fmt;
- va_dcl
-#endif
-{
- va_list ap;
- char buf[RCMD_BUFSIZ], *cp = buf;
-
-#ifdef HAVE_STDARG_H
- va_start(ap, fmt);
-#else
- va_start(ap);
-#endif
-
- *cp++ = 1;
- (void) snprintf(cp, sizeof(buf) - (cp - buf), "%s: ", progname);
- (void) vsnprintf(buf+strlen(buf), sizeof(buf) - strlen(buf), fmt, ap);
- va_end(ap);
- (void) write(2, buf, strlen(buf));
- syslog(LOG_ERR ,"%s",buf+1);
-}
-
-
-void getstr(fd, buf, cnt, err)
- int fd;
- char *buf;
- int cnt;
- char *err;
-{
- char c;
-
- do {
- if (read(fd, &c, 1) != 1)
- exit(1);
- *buf++ = c;
- if (--cnt == 0) {
- error("%s too long\n", err);
- exit(1);
- }
- } while (c != 0);
-}
-
-#ifdef CRAY
-char *makejtmp(uid, gid, jid)
- register int uid, gid, jid;
-{
- register char *endc, *tdp = &tmpdir[strlen(tmpdir)];
- register int i;
-
- snprintf(tdp, sizeof(tmpdir) - (tdp - tmpdir), "%s/jtmp.%06d",
- JTMPDIR, jid);
- endc = &tmpdir[strlen(tmpdir)];
-
- endc[1] = '\0';
- for (i = 0; i < 26; i++) {
- endc[0] = 'a' + i;
- if (mkdir(tdp, JTMPMODE) != -1) {
- chown(tdp, uid, gid);
- return (tdp);
- } else if (errno != EEXIST)
- break;
- }
- return(NULL);
-}
-
-
-
-cleanjtmp(user, tpath)
- register char *user, *tpath;
-{
- switch(fork()) {
- case -1:
- break;
- case 0:
- if (secflag) {
- execl("/bin/rm", "rm", "-rf", tpath, 0);
- error("exec of %s failed; errno = %d\n",
- "/bin/rm", errno);
- } else {
- execl(CLEANTMPCMD, CLEANTMPCMD, user, tpath, 0);
- error("exec of %s failed; errno = %d\n",
- CLEANTMPCMD, errno);
- }
- exit(1);
- break;
- default:
- /*
- * Just forget about the child, let init will pick it
- * up after we exit.
- */
- break;
- }
-}
-
-
-
-/***get_packet_classification
- *
- *
- * int get_packet_classification():
- * Obtain packet level and compartments from passed fd...
- *
- * Returns:
- * -1: If could not get user defaults.
- * 0: success
- */
-#ifdef IP_SECURITY
-static int get_packet_classification(fd,useruid,level,comp)
- int fd;
- uid_t useruid;
- int *level;
- long *comp;
-{
- struct socket_security pkt_sec;
- struct udb *udb;
- int retval;
- int sockoptlen;
-
- retval = 0;
- getsysudb ();
- udb = getudbuid ((int) useruid);
- endudb ();
- if (udb == (struct udb *) 0) return(-1);
- /* Get packet IP packet label */
- sockoptlen = SIZEOF_sec;
- if ( getsockopt(fd,SOL_SOCKET,SO_SECURITY,
- (char *) &pkt_sec,&sockoptlen)){ /* Failed */
- return(-2);
- }
- *level = pkt_sec.sec_level;
- *comp = udb->ue_defcomps;
- return(0);
-}
-
-#else /* If no IP_SECURITY set level to users default */
-
-static int get_packet_classification(fd,useruid,level,comp)
- int fd;
- uid_t useruid;
- int *level;
- long *comp;
-{
- struct udb *udb;
- getsysudb ();
- udb = getudbuid ((int) useruid);
- endudb ();
- if (udb == (struct udb *) 0) return(-1);
- *level = udb->ue_deflvl;
- *comp = udb->ue_defcomps;
- return(0);
-}
-
-#endif /* IP_SECURITY */
-
-
-
-/*
- * Make a security log entry for the login attempt.
- * host = pointer to host id
- * flag = status of login
- * failures = current losing streak in login attempts
- */
-/* Make a security log entry for the login attempt.
- * host = pointer to host id
- * flag = status of login
- * failures = current losing streak in login attempts
- */
-
-loglogin(host, flag, failures, ue)
- char *host;
- int flag;
- int failures;
- struct udb * ue;
-{
- char urec[sizeof(struct slghdr) + sizeof(struct slglogin)];
- struct slghdr *uhdr = (struct slghdr *)urec;
- struct slglogin *ulogin=(struct slglogin *)&urec[sizeof(struct slghdr)];
-
- strncpy(ulogin->sl_line, ttyn, sizeof(ulogin->sl_line));
- strncpy(ulogin->sl_host, host, sizeof(ulogin->sl_host));
- ulogin->sl_failures = failures;
- if ( maxlogs && (failures >= maxlogs))
- flag |= SLG_DSABL;
- ulogin->sl_result = flag;
- uhdr->sl_uid = ue->ue_uid;
- uhdr->sl_ruid = ue->ue_uid;
- uhdr->sl_juid = ue->ue_uid;
- uhdr->sl_gid = ue->ue_gids[0];
- uhdr->sl_rgid = ue->ue_gids[0];
- uhdr->sl_slvl = ue->ue_deflvl;
- /* uhdr->sl_scls = ue->ue_defcls; enable for integrity policy */
- uhdr->sl_olvl = 0;
- uhdr->sl_len = sizeof(urec);
-
-#ifdef CRAY2
- slgentry(SLG_LOGN, (word *)urec);
-#else /* ! CRAY2 */
- slgentry(SLG_LOGN, (waddr_t)urec);
-#endif
- return;
-}
-
-#endif /* CRAY */
-
-
-
-void usage()
-{
-#ifdef KERBEROS
- syslog(LOG_ERR, "usage: kshd [-eciK] ");
-#else
- syslog(LOG_ERR, "usage: rshd");
-#endif
-}
-
-
-#ifdef KERBEROS
-
-#ifndef KRB_SENDAUTH_VLEN
-#define KRB_SENDAUTH_VLEN 8 /* length for version strings */
-#endif
-
-#define KRB_SENDAUTH_VERS "AUTHV0.1" /* MUST be KRB_SENDAUTH_VLEN
- chars */
-
-static krb5_error_code
-recvauth(netfd, peersin, valid_checksum)
- int netfd;
- struct sockaddr *peersin;
- int *valid_checksum;
-{
- krb5_auth_context auth_context = NULL;
- krb5_error_code status;
- struct sockaddr_in laddr;
- socklen_t len;
- krb5_data inbuf;
- krb5_authenticator *authenticator;
- krb5_ticket *ticket;
- krb5_rcache rcache;
- struct passwd *pwd;
- uid_t uid;
- gid_t gid;
- enum kcmd_proto kcmd_proto;
- krb5_data version;
-
- *valid_checksum = 0;
- len = sizeof(laddr);
- if (getsockname(netfd, (struct sockaddr *)&laddr, &len)) {
- exit(1);
- }
-
-#ifdef unicos61
-#define SIZEOF_INADDR SIZEOF_in_addr
-#else
-#define SIZEOF_INADDR sizeof(struct in_addr)
-#endif
-
- status = krb5_auth_con_init(bsd_context, &auth_context);
- if (status)
- return status;
-
- status = krb5_auth_con_genaddrs(bsd_context, auth_context, netfd,
- KRB5_AUTH_CONTEXT_GENERATE_REMOTE_FULL_ADDR);
- if (status)
- return status;
-
- status = krb5_auth_con_getrcache(bsd_context, auth_context, &rcache);
- if (status) return status;
-
- if (! rcache) {
- krb5_principal server;
-
- status = krb5_sname_to_principal(bsd_context, 0, 0,
- KRB5_NT_SRV_HST, &server);
- if (status) return status;
-
- status = krb5_get_server_rcache(bsd_context,
- krb5_princ_component(bsd_context, server, 0),
- &rcache);
- krb5_free_principal(bsd_context, server);
- if (status) return status;
-
- status = krb5_auth_con_setrcache(bsd_context, auth_context, rcache);
- if (status) return status;
- }
-
- status = krb5_recvauth_version(bsd_context, &auth_context, &netfd,
- NULL, /* daemon principal */
- 0, /* no flags */
- keytab, /* normally NULL to use v5srvtab */
- &ticket, /* return ticket */
- &version); /* application version string */
- if (status) {
- /*
- * clean up before exiting
- */
- getstr(netfd, locuser, sizeof(locuser), "locuser");
- getstr(netfd, cmdbuf, sizeof(cmdbuf), "command");
- getstr(netfd, remuser, sizeof(locuser), "remuser");
- return status;
- }
-
- getstr(netfd, locuser, sizeof(locuser), "locuser");
- getstr(netfd, cmdbuf, sizeof(cmdbuf), "command");
-
- /* Must be V5 */
-
- kcmd_proto = KCMD_UNKNOWN_PROTOCOL;
- if (version.length != 9)
- fatal (netfd, "bad application version length");
- if (!memcmp (version.data, "KCMDV0.1", 9))
- kcmd_proto = KCMD_OLD_PROTOCOL;
- if (!memcmp (version.data, "KCMDV0.2", 9))
- kcmd_proto = KCMD_NEW_PROTOCOL;
-
- getstr(netfd, remuser, sizeof(locuser), "remuser");
-
- if ((status = krb5_unparse_name(bsd_context, ticket->enc_part2->client,
- &kremuser)))
- return status;
-
- if ((status = krb5_copy_principal(bsd_context, ticket->enc_part2->client,
- &client)))
- return status;
- if ((status = krb5_auth_con_getauthenticator(bsd_context, auth_context,
- &authenticator)))
- return status;
-
- if (authenticator->checksum && !checksum_ignored) {
- struct sockaddr_storage adr;
- unsigned int adr_length = sizeof(adr);
- int e;
- char namebuf[32];
- krb5_boolean valid = 0;
- krb5_data chksumbuf;
-
- chksumbuf.data = NULL;
- if (getsockname(netfd, (struct sockaddr *) &adr, &adr_length) != 0)
- goto error_cleanup;
-
- e = getnameinfo((struct sockaddr *)&adr, adr_length, 0, 0,
- namebuf, sizeof(namebuf), NI_NUMERICSERV);
- if (e)
- fatal(netfd, "local error: can't examine port number");
- if (asprintf(&chksumbuf.data, "%s:%s%s", namebuf, cmdbuf, locuser) < 0)
- goto error_cleanup;
-
- chksumbuf.length = strlen(chksumbuf.data);
- status = krb5_c_verify_checksum(bsd_context,
- ticket->enc_part2->session,
- KRB5_KEYUSAGE_AP_REQ_AUTH_CKSUM,
- &chksumbuf, authenticator->checksum,
- &valid);
- if (status == 0 && !valid) status = KRB5KRB_AP_ERR_BAD_INTEGRITY;
-
- error_cleanup:
- if (chksumbuf.data)
- free(chksumbuf.data);
- if (status) {
- krb5_free_authenticator(bsd_context, authenticator);
- return status;
- }
- *valid_checksum = 1;
- }
- krb5_free_authenticator(bsd_context, authenticator);
-
-
- if (!strncmp(cmdbuf, "-x ", 3))
- do_encrypt = 1;
-
- {
- krb5_keyblock *key;
- status = krb5_auth_con_getrecvsubkey (bsd_context, auth_context,
- &key);
- if (status)
- fatal (netfd, "Server can't get session subkey");
- if (!key && do_encrypt && kcmd_proto == KCMD_NEW_PROTOCOL)
- fatal (netfd, "No session subkey sent");
- if (key && kcmd_proto == KCMD_OLD_PROTOCOL) {
-#ifdef HEIMDAL_FRIENDLY
- key = 0;
-#else
- fatal (netfd, "Session subkey not allowed in old kcmd protocol");
-#endif
- }
- if (key == 0)
- key = ticket->enc_part2->session;
- rcmd_stream_init_krb5 (key, do_encrypt, 0, 0, kcmd_proto);
- }
-
- /* Null out the "session" because kcmd.c references the session
- * key here, and we do not want krb5_free_ticket() to destroy it. */
- ticket->enc_part2->session = 0;
-
- if ((status = krb5_read_message(bsd_context, (krb5_pointer)&netfd,
- &inbuf))) {
- error("Error reading message: %s\n", error_message(status));
- exit(1);
- }
-
- if (inbuf.length) { /* Forwarding being done, read creds */
- pwd = getpwnam(locuser);
- if (!pwd) {
- error("Login incorrect.\n");
- exit(1);
- }
- uid = pwd->pw_uid;
- gid = pwd->pw_gid;
- if ((status = rd_and_store_for_creds(bsd_context, auth_context, &inbuf,
- ticket, &ccache))) {
- error("Can't get forwarded credentials: %s\n",
- error_message(status));
- exit(1);
- }
- if (chown(krb5_cc_get_name(bsd_context, ccache), uid, gid) == -1) {
- error("Can't chown forwarded credentials: %s\n",
- error_message(errno));
- exit(1);
- }
- }
- krb5_free_ticket(bsd_context, ticket);
- return 0;
-}
-#endif /* KERBEROS */
-
-
-
-void fatal(f, msg)
- int f;
- const char *msg;
-{
- char buf[512];
-#ifndef POSIX_TERMIOS
- int out = 1 ; /* Output queue of f */
-#endif
-
- buf[0] = '\01'; /* error indicator */
- (void) snprintf(buf + 1, sizeof(buf) - 1, "%s: %s.\r\n",progname, msg);
- if ((f == netf) && (pid > 0))
- (void) rcmd_stream_write(f, buf, strlen(buf), 0);
- else
- (void) write(f, buf, strlen(buf));
- syslog(LOG_ERR,"%s\n",msg);
- if (pid > 0) {
- signal(SIGCHLD,SIG_IGN);
- kill(pid,SIGKILL);
-#ifdef POSIX_TERMIOS
- (void) tcflush(1, TCOFLUSH);
-#else
- (void) ioctl(f, TIOCFLUSH, (char *)&out);
-#endif
- cleanup(-1);
- }
- exit(1);
-}
-
-static int
-accept_a_connection (int debug_port, struct sockaddr *from,
- socklen_t *fromlenp)
-{
- int n, s, fd, s4 = -1, s6 = -1, on = 1;
- fd_set sockets;
-
- FD_ZERO(&sockets);
-
-#ifdef KRB5_USE_INET6
- {
- struct sockaddr_in6 sock_in6;
-
- if ((s = socket(AF_INET6, SOCK_STREAM, PF_UNSPEC)) < 0) {
- if ((errno == EPROTONOSUPPORT) || (errno == EAFNOSUPPORT))
- goto skip_ipv6;
- fprintf(stderr, "Error in socket(INET6): %s\n", strerror(errno));
- exit(2);
- }
-
- memset(&sock_in6, 0,sizeof(sock_in6));
- sock_in6.sin6_family = AF_INET6;
- sock_in6.sin6_port = htons(debug_port);
- sock_in6.sin6_addr = in6addr_any;
-
- (void) setsockopt(s, SOL_SOCKET, SO_REUSEADDR,
- (char *)&on, sizeof(on));
-
- if ((bind(s, (struct sockaddr *) &sock_in6, sizeof(sock_in6))) < 0) {
- fprintf(stderr, "Error in bind(INET6): %s\n", strerror(errno));
- exit(2);
- }
-
- if ((listen(s, 5)) < 0) {
- fprintf(stderr, "Error in listen(INET6): %s\n", strerror(errno));
- exit(2);
- }
- s6 = s;
- FD_SET(s, &sockets);
- skip_ipv6:
- ;
- }
-#endif
-
- {
- struct sockaddr_in sock_in;
-
- if ((s = socket(AF_INET, SOCK_STREAM, PF_UNSPEC)) < 0) {
- fprintf(stderr, "Error in socket: %s\n", strerror(errno));
- exit(2);
- }
-
- memset(&sock_in, 0,sizeof(sock_in));
- sock_in.sin_family = AF_INET;
- sock_in.sin_port = htons(debug_port);
- sock_in.sin_addr.s_addr = INADDR_ANY;
-
- (void) setsockopt(s, SOL_SOCKET, SO_REUSEADDR,
- (char *)&on, sizeof(on));
-
- if ((bind(s, (struct sockaddr *) &sock_in, sizeof(sock_in))) < 0) {
- if (s6 >= 0 && errno == EADDRINUSE)
- goto try_ipv6_only;
- fprintf(stderr, "Error in bind: %s\n", strerror(errno));
- exit(2);
- }
-
- if ((listen(s, 5)) < 0) {
- fprintf(stderr, "Error in listen: %s\n", strerror(errno));
- exit(2);
- }
- s4 = s;
- FD_SET(s, &sockets);
- try_ipv6_only:
- ;
- }
- if (s4 == -1 && s6 == -1) {
- fprintf(stderr, "No valid sockets established, exiting\n");
- exit(2);
- }
- n = select(((s4 < s6) ? s6 : s4) + 1, &sockets, 0, 0, 0);
- if (n < 0) {
- fprintf(stderr, "select error: %s\n", strerror(errno));
- exit(2);
- } else if (n == 0) {
- fprintf(stderr, "internal error? select returns 0\n");
- exit(2);
- }
- if (s6 != -1 && FD_ISSET(s6, &sockets)) {
- if (s4 != -1)
- close(s4);
- s = s6;
- } else if (FD_ISSET(s4, &sockets)) {
- if (s6 != -1)
- close(s6);
- s = s4;
- } else {
- fprintf(stderr,
- "internal error? select returns positive, "
- "but neither fd available\n");
- exit(2);
- }
-
- if ((fd = accept(s, from, fromlenp)) < 0) {
- fprintf(stderr, "Error in accept: %s\n", strerror(errno));
- exit(2);
- }
-
- close(s);
- return fd;
-}