Fix for new Kerberos4. Make a fist cut at PAM-ising while I'm here.

This commit is contained in:
Mark Murray 1999-09-19 22:05:32 +00:00
parent ae3b8c19b1
commit 6c9134c067
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=51433
8 changed files with 388 additions and 326 deletions

View File

@ -17,13 +17,11 @@ LSDIR= ../../bin/ls
SRCS+= ls.c cmp.c print.c stat_flags.c util.c
CFLAGS+=-DINTERNAL_LS -Dmain=ls_main -I${.CURDIR}/${LSDIR}
.if exists(${DESTDIR}/usr/lib/libkrb.a) && defined(MAKE_KERBEROS4)
.PATH: ${.CURDIR}/../../lib/libpam/modules/pam_kerberosIV
SRCS+= klogin.c
LDADD+= -lkrb -ldes -lcom_err
DPADD+= ${LIBKRB} ${LIBDES} ${LIBCOM_ERR}
CFLAGS+=-DKERBEROS
DISTRIBUTION= krb
.if defined(NOPAM)
CFLAGS+=-DNOPAM
.else
DPADD+= ${LIBPAM}
LDADD+= ${MINUSLPAM}
.endif
.include <bsd.prog.mk>

View File

@ -94,6 +94,10 @@ static const char rcsid[] =
#include <skey.h>
#endif
#if !defined(NOPAM)
#include <security/pam_appl.h>
#endif
#include "pathnames.h"
#include "extern.h"
@ -168,19 +172,13 @@ char *ident = NULL;
static char ttyline[20];
char *tty = ttyline; /* for klogin */
#ifdef KERBEROS
int klogin __P((struct passwd *, char *, char *, char *));
#if !defined(NOPAM)
static int auth_pam __P((struct passwd**, const char*));
#endif
struct in_addr bind_address;
char *pid_file = NULL;
#if defined(KERBEROS)
int notickets = 1;
int noticketsdontcomplain = 1;
char *krbtkfile_env = NULL;
#endif
/*
* Timeout intervals for retrying connections
* to hosts that don't accept PORT cmds. This
@ -914,6 +912,132 @@ end_login()
dochroot = 0;
}
#if !defined(NOPAM)
/*
* the following code is stolen from imap-uw PAM authentication module and
* login.c
*/
#define COPY_STRING(s) (s ? strdup(s) : NULL)
struct cred_t {
const char *uname; /* user name */
const char *pass; /* password */
};
typedef struct cred_t cred_t;
static int
auth_conv(int num_msg, const struct pam_message **msg,
struct pam_response **resp, void *appdata)
{
int i;
cred_t *cred = (cred_t *) appdata;
struct pam_response *reply =
malloc(sizeof(struct pam_response) * num_msg);
for (i = 0; i < num_msg; i++) {
switch (msg[i]->msg_style) {
case PAM_PROMPT_ECHO_ON: /* assume want user name */
reply[i].resp_retcode = PAM_SUCCESS;
reply[i].resp = COPY_STRING(cred->uname);
/* PAM frees resp. */
break;
case PAM_PROMPT_ECHO_OFF: /* assume want password */
reply[i].resp_retcode = PAM_SUCCESS;
reply[i].resp = COPY_STRING(cred->pass);
/* PAM frees resp. */
break;
case PAM_TEXT_INFO:
case PAM_ERROR_MSG:
reply[i].resp_retcode = PAM_SUCCESS;
reply[i].resp = NULL;
break;
default: /* unknown message style */
free(reply);
return PAM_CONV_ERR;
}
}
*resp = reply;
return PAM_SUCCESS;
}
/*
* Attempt to authenticate the user using PAM. Returns 0 if the user is
* authenticated, or 1 if not authenticated. If some sort of PAM system
* error occurs (e.g., the "/etc/pam.conf" file is missing) then this
* function returns -1. This can be used as an indication that we should
* fall back to a different authentication mechanism.
*/
static int
auth_pam(struct passwd **ppw, const char *pass)
{
pam_handle_t *pamh = NULL;
const char *tmpl_user;
const void *item;
int rval;
int e;
cred_t auth_cred = { (*ppw)->pw_name, pass };
struct pam_conv conv = { &auth_conv, &auth_cred };
e = pam_start("ftpd", (*ppw)->pw_name, &conv, &pamh);
if (e != PAM_SUCCESS) {
syslog(LOG_ERR, "pam_start: %s", pam_strerror(pamh, e));
return -1;
}
e = pam_authenticate(pamh, 0);
switch (e) {
case PAM_SUCCESS:
/*
* With PAM we support the concept of a "template"
* user. The user enters a login name which is
* authenticated by PAM, usually via a remote service
* such as RADIUS or TACACS+. If authentication
* succeeds, a different but related "template" name
* is used for setting the credentials, shell, and
* home directory. The name the user enters need only
* exist on the remote authentication server, but the
* template name must be present in the local password
* database.
*
* This is supported by two various mechanisms in the
* individual modules. However, from the application's
* point of view, the template user is always passed
* back as a changed value of the PAM_USER item.
*/
if ((e = pam_get_item(pamh, PAM_USER, &item)) ==
PAM_SUCCESS) {
tmpl_user = (const char *) item;
if (strcmp((*ppw)->pw_name, tmpl_user) != 0)
*ppw = getpwnam(tmpl_user);
} else
syslog(LOG_ERR, "Couldn't get PAM_USER: %s",
pam_strerror(pamh, e));
rval = 0;
break;
case PAM_AUTH_ERR:
case PAM_USER_UNKNOWN:
case PAM_MAXTRIES:
rval = 1;
break;
default:
syslog(LOG_ERR, "auth_pam: %s", pam_strerror(pamh, e));
rval = -1;
break;
}
if ((e = pam_end(pamh, e)) != PAM_SUCCESS) {
syslog(LOG_ERR, "pam_end: %s", pam_strerror(pamh, e));
rval = -1;
}
return rval;
}
#endif /* !defined(NOPAM) */
void
pass(passwd)
char *passwd;
@ -934,9 +1058,9 @@ pass(passwd)
rval = 1; /* failure below */
goto skip;
}
#if defined(KERBEROS)
rval = klogin(pw, "", hostname, passwd);
if (rval == 0)
#if !defined(NOPAM)
rval = auth_pam(&pw, passwd);
if (rval >= 0)
goto skip;
#endif
#ifdef SKEY
@ -953,7 +1077,7 @@ pass(passwd)
skip:
/*
* If rval == 1, the user failed the authentication check
* above. If rval == 0, either Kerberos or local authentication
* above. If rval == 0, either PAM or local authentication
* succeeded.
*/
if (rval) {
@ -1085,14 +1209,14 @@ pass(passwd)
if (thishost != firsthost)
snprintf(proctitle, sizeof(proctitle),
"%s: anonymous(%s)/%.*s", remotehost, hostname,
sizeof(proctitle) - sizeof(remotehost) -
sizeof(": anonymous/"), passwd);
(int)(sizeof(proctitle) - sizeof(remotehost) -
sizeof(": anonymous/")), passwd);
else
#endif
snprintf(proctitle, sizeof(proctitle),
"%s: anonymous/%.*s", remotehost,
sizeof(proctitle) - sizeof(remotehost) -
sizeof(": anonymous/"), passwd);
(int)(sizeof(proctitle) - sizeof(remotehost) -
sizeof(": anonymous/")), passwd);
setproctitle("%s", proctitle);
#endif /* SETPROCTITLE */
if (logging)
@ -1937,10 +2061,6 @@ dologout(status)
if (logged_in) {
(void) seteuid((uid_t)0);
ftpd_logwtmp(ttyline, "", "");
#if defined(KERBEROS)
if (!notickets && krbtkfile_env)
unlink(krbtkfile_env);
#endif
}
/* beware of flushing buffers after a SIGPIPE */
_exit(status);

View File

@ -8,17 +8,12 @@ DPADD= ${LIBUTIL}
LDADD= -lutil
CFLAGS+= -Wall
.if exists(${DESTDIR}${LIBDIR}/libkrb.a) && defined(MAKE_KERBEROS4)
SRCS+= encrypt.c
CFLAGS+=-DKERBEROS -DCRYPT -DHAVE_CONFIG_H \
-I${.CURDIR}/../../kerberosIV/include \
-I${.CURDIR}/../../crypto/kerberosIV/include \
-I${.CURDIR}/../../crypto/kerberosIV/lib/roken \
-I${.CURDIR}/../../crypto/kerberosIV/appl/bsd
DPADD= ${LIBKRB} ${LIBDES} ${LIBCRYPT} ${LIBCOM_ERR)
LDADD+= -lkrb -ldes -lcrypt -lcom_err
DISTRIBUTION= krb
.PATH: ${.CURDIR}/../../crypto/kerberosIV/appl/bsd
.if defined(NOPAM)
CFLAGS+= -DNO_PAM
.else
SRCS+= auth_pam.c
DPADD+= ${LIBPAM}
LDADD+= ${MINUSLPAM}
.endif
.include <bsd.prog.mk>

142
libexec/rlogind/auth_pam.c Normal file
View File

@ -0,0 +1,142 @@
/*-
* Copyright (c) 1999 John Polstra
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $FreeBSD$
*/
#include <sys/param.h>
#include <sys/types.h>
#include <security/pam_appl.h>
#include <security/pam_misc.h>
#include <paths.h>
#include <pwd.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
/*
* Attempt to authenticate the user using PAM. Returns 0 if the user is
* authenticated, or 1 if not authenticated. If some sort of PAM system
* error occurs (e.g., the "/etc/pam.conf" file is missing) then this
* function returns -1. This can be used as an indication that we should
* fall back to a different authentication mechanism.
*/
int
auth_pam(char *username)
{
struct passwd *pawd;
pam_handle_t *pamh = NULL;
const char *tmpl_user;
const void *item;
int rval;
char *tty, *ttyn;
char hostname[MAXHOSTNAMELEN];
char tname[sizeof(_PATH_TTY) + 10];
int e;
static struct pam_conv conv = { misc_conv, NULL };
ttyn = ttyname(STDIN_FILENO);
if (ttyn == NULL || *ttyn == '\0') {
(void)snprintf(tname, sizeof(tname), "%s??", _PATH_TTY);
ttyn = tname;
}
if ((tty = strrchr(ttyn, '/')) != NULL)
++tty;
else
tty = ttyn;
rval = gethostname(hostname, sizeof(hostname));
if (rval < 0) {
syslog(LOG_ERR, "auth_pam: Failed to resolve local hostname");
return -1;
}
if ((e = pam_start("rshd", username, &conv, &pamh)) != PAM_SUCCESS) {
syslog(LOG_ERR, "pam_start: %s", pam_strerror(pamh, e));
return -1;
}
if ((e = pam_set_item(pamh, PAM_TTY, tty)) != PAM_SUCCESS) {
syslog(LOG_ERR, "pam_set_item(PAM_TTY): %s",
pam_strerror(pamh, e));
return -1;
}
if (hostname != NULL &&
(e = pam_set_item(pamh,PAM_RHOST, hostname)) != PAM_SUCCESS) {
syslog(LOG_ERR, "pam_set_item(PAM_RHOST): %s",
pam_strerror(pamh, e));
return -1;
}
e = pam_authenticate(pamh, 0);
switch (e) {
case PAM_SUCCESS:
/*
* With PAM we support the concept of a "template"
* user. The user enters a login name which is
* authenticated by PAM, usually via a remote service
* such as RADIUS or TACACS+. If authentication
* succeeds, a different but related "template" name
* is used for setting the credentials, shell, and
* home directory. The name the user enters need only
* exist on the remote authentication server, but the
* template name must be present in the local password
* database.
*
* This is supported by two various mechanisms in the
* individual modules. However, from the application's
* point of view, the template user is always passed
* back as a changed value of the PAM_USER item.
*/
if ((e = pam_get_item(pamh, PAM_USER, &item)) ==
PAM_SUCCESS) {
tmpl_user = (const char *) item;
if (strcmp(username, tmpl_user) != 0)
pawd = getpwnam(tmpl_user);
} else
syslog(LOG_ERR, "Couldn't get PAM_USER: %s", pam_strerror(pamh, e));
rval = 0;
break;
case PAM_AUTH_ERR:
case PAM_USER_UNKNOWN:
case PAM_MAXTRIES:
rval = 1;
break;
default:
syslog(LOG_ERR, "auth_pam: %s", pam_strerror(pamh, e));
rval = -1;
break;
}
if ((e = pam_end(pamh, e)) != PAM_SUCCESS) {
syslog(LOG_ERR, "pam_end: %s", pam_strerror(pamh, e));
rval = -1;
}
return rval;
}

View File

@ -31,8 +31,10 @@
* SUCH DAMAGE.
*
* @(#)pathnames.h 8.1 (Berkeley) 6/4/93
* $FreeBSD$
*/
#include <paths.h>
#define _PATH_LOGIN "/usr/bin/login"
#define _PATH_RLOGIN "/usr/bin/rlogin"

View File

@ -80,26 +80,16 @@ static const char rcsid[] =
#include <unistd.h>
#include "pathnames.h"
#ifndef NO_PAM
#include <security/pam_appl.h>
#include <security/pam_misc.h>
#endif
#ifndef TIOCPKT_WINDOW
#define TIOCPKT_WINDOW 0x80
#endif
#ifdef KERBEROS
#include <des.h>
#include <krb.h>
#define SECURE_MESSAGE "This rlogin session is using DES encryption for all transmissions.\r\n"
AUTH_DAT *kdata;
KTEXT ticket;
u_char auth_buf[sizeof(AUTH_DAT)];
u_char tick_buf[sizeof(KTEXT_ST)];
Key_schedule schedule;
int doencrypt, retval, use_kerberos, vacuous;
#define ARGSTR "Dalnkvx"
#else
#define ARGSTR "Daln"
#endif /* KERBEROS */
#define ARGSTR "Dalnx"
char *env[2];
#define NMAX 30
@ -123,6 +113,10 @@ void setup_term __P((int));
int do_krb_login __P((struct sockaddr_in *));
void usage __P((void));
#ifndef NO_PAM
extern int auth_pam __P((char *));
#endif
int
main(argc, argv)
int argc;
@ -149,18 +143,10 @@ main(argc, argv)
case 'n':
keepalive = 0;
break;
#ifdef KERBEROS
case 'k':
use_kerberos = 1;
break;
case 'v':
vacuous = 1;
break;
#ifdef CRYPT
case 'x':
doencrypt = 1;
break;
#endif
#endif
case '?':
default:
@ -170,12 +156,6 @@ main(argc, argv)
argc -= optind;
argv += optind;
#ifdef KERBEROS
if (use_kerberos && vacuous) {
usage();
fatal(STDERR_FILENO, "only one of -k and -v allowed", 0);
}
#endif
fromlen = sizeof (from);
if (getpeername(0, (struct sockaddr *)&from, &fromlen) < 0) {
syslog(LOG_ERR,"Can't get peer name of remote host: %m");
@ -219,27 +199,12 @@ doit(f, fromp)
if (c != 0)
exit(1);
#ifdef KERBEROS
if (vacuous)
fatal(f, "Remote host requires Kerberos authentication", 0);
#endif
alarm(0);
fromp->sin_port = ntohs((u_short)fromp->sin_port);
realhostname(hostname, sizeof(hostname) - 1, &fromp->sin_addr);
hostname[sizeof(hostname) - 1] = '\0';
#ifdef KERBEROS
if (use_kerberos) {
retval = do_krb_login(fromp);
if (retval == 0)
authenticated++;
else if (retval > 0)
fatal(f, krb_err_txt[retval], 0);
write(f, &c, 1);
confirmed = 1; /* we sent the null! */
} else
#endif
{
if (fromp->sin_family != AF_INET ||
fromp->sin_port >= IPPORT_RESERVED ||
@ -283,14 +248,12 @@ doit(f, fromp)
write(f, "", 1);
confirmed = 1; /* we sent the null! */
}
#ifdef KERBEROS
#ifdef CRYPT
if (doencrypt)
(void) des_enc_write(f,
SECURE_MESSAGE,
strlen(SECURE_MESSAGE),
schedule, &kdata->session);
#endif
#endif
netf = f;
@ -311,14 +274,6 @@ doit(f, fromp)
fatal(STDERR_FILENO, "invalid user", 0);
}
if (authenticated) {
#ifdef KERBEROS
if (use_kerberos && (pwd->pw_uid == 0))
syslog(LOG_INFO|LOG_AUTH,
"ROOT Kerberos login from %s.%s@%s on %s\n",
kdata->pname, kdata->pinst, kdata->prealm,
hostname);
#endif
execl(_PATH_LOGIN, "login", "-p",
"-h", hostname, "-f", lusername, (char *)NULL);
} else
@ -328,14 +283,12 @@ doit(f, fromp)
/*NOTREACHED*/
}
#ifdef CRYPT
#ifdef KERBEROS
/*
* If encrypted, don't turn on NBIO or the des read/write
* routines will croak.
*/
if (!doencrypt)
#endif
#endif
ioctl(f, FIONBIO, &on);
ioctl(master, FIONBIO, &on);
@ -445,12 +398,10 @@ protocol(f, p)
}
if (FD_ISSET(f, &ibits)) {
#ifdef CRYPT
#ifdef KERBEROS
if (doencrypt)
fcc = des_enc_read(f, fibuf, sizeof(fibuf),
schedule, &kdata->session);
else
#endif
#endif
fcc = read(f, fibuf, sizeof(fibuf));
if (fcc < 0 && errno == EWOULDBLOCK)
@ -499,9 +450,7 @@ protocol(f, p)
else if (pibuf[0] == 0) {
pbp++, pcc--;
#ifdef CRYPT
#ifdef KERBEROS
if (!doencrypt)
#endif
#endif
FD_SET(f, &obits); /* try write */
} else {
@ -514,12 +463,10 @@ protocol(f, p)
}
if ((FD_ISSET(f, &obits)) && pcc > 0) {
#ifdef CRYPT
#ifdef KERBEROS
if (doencrypt)
cc = des_enc_write(f, pbp, pcc,
schedule, &kdata->session);
else
#endif
#endif
cc = write(f, pbp, pcc);
if (cc < 0 && errno == EWOULDBLOCK) {
@ -588,10 +535,26 @@ int
do_rlogin(dest)
struct sockaddr_in *dest;
{
int retval;
getstr(rusername, sizeof(rusername), "remuser too long");
getstr(lusername, sizeof(lusername), "locuser too long");
getstr(term+ENVSIZE, sizeof(term)-ENVSIZE, "Terminal type too long");
#ifndef NO_PAM
retval = auth_pam(lusername);
if (retval) {
if (retval == -1) {
syslog(LOG_ERR, "PAM authentication failed");
}
else {
syslog(LOG_ERR,
"User %s failed PAM authentication", lusername);
exit(1);
}
}
#endif
pwd = getpwnam(lusername);
if (pwd == NULL)
return (-1);
@ -660,79 +623,8 @@ setup_term(fd)
environ = env;
}
#ifdef KERBEROS
#define VERSION_SIZE 9
/*
* Do the remote kerberos login to the named host with the
* given inet address
*
* Return 0 on valid authorization
* Return -1 on valid authentication, no authorization
* Return >0 for error conditions
*/
int
do_krb_login(dest)
struct sockaddr_in *dest;
{
int rc;
char instance[INST_SZ], version[VERSION_SIZE];
long authopts = 0L; /* !mutual */
struct sockaddr_in faddr;
kdata = (AUTH_DAT *) auth_buf;
ticket = (KTEXT) tick_buf;
instance[0] = '*';
instance[1] = '\0';
#ifdef CRYPT
if (doencrypt) {
rc = sizeof(faddr);
if (getsockname(0, (struct sockaddr *)&faddr, &rc))
return (-1);
authopts = KOPT_DO_MUTUAL;
rc = krb_recvauth(
authopts, 0,
ticket, "rcmd",
instance, dest, &faddr,
kdata, "", schedule, version);
des_set_key(&kdata->session, schedule);
} else
#endif
rc = krb_recvauth(
authopts, 0,
ticket, "rcmd",
instance, dest, (struct sockaddr_in *) 0,
kdata, "", NULL, version);
if (rc != KSUCCESS)
return (rc);
getstr(lusername, sizeof(lusername), "locuser");
/* get the "cmd" in the rcmd protocol */
getstr(term+ENVSIZE, sizeof(term)-ENVSIZE, "Terminal type");
pwd = getpwnam(lusername);
if (pwd == NULL)
return (-1);
/* returns nonzero for no access */
if (kuserok(kdata, lusername) != 0)
return (-1);
return (0);
}
#endif /* KERBEROS */
void
usage()
{
#ifdef KERBEROS
syslog(LOG_ERR, "usage: rlogind [-Daln] [-k | -v]");
#else
syslog(LOG_ERR, "usage: rlogind [-Daln]");
#endif
syslog(LOG_ERR, "usage: rlogind [-" ARGSTR "]");
}

View File

@ -5,11 +5,13 @@ PROG= rshd
SRCS= rshd.c
MAN8= rshd.8
.if exists(${DESTDIR}${LIBDIR}/libkrb.a) && defined(MAKE_KERBEROS4)
CFLAGS+=-DKERBEROS -DCRYPT
DPADD= ${LIBKRB} ${LIBDES} ${LIBCRYPT} ${LIBCOM_ERR}
LDADD= -lkrb -ldes -lcrypt -lcom_err
DISTRIBUTION= krb
.if defined(NOPAM)
CFLAGS+= -DNO_PAM
.else
#CFLAGS+= -DCRYPT
SRCS+= auth_pam.c
DPADD+= ${LIBPAM}
LDADD+= ${MINUSLPAM}
.endif
# For login_cap handling
@ -18,3 +20,5 @@ DPADD+= ${LIBUTIL}
LDADD+= -lutil
.include <bsd.prog.mk>
.PATH: ${.CURDIR}/../rlogind

View File

@ -84,6 +84,9 @@ int keepalive = 1;
int log_success; /* If TRUE, log all successful accesses */
int sent_null;
int no_delay;
#ifdef CRYPT
int doencrypt = 0;
#endif
void doit __P((struct sockaddr_in *));
void error __P((const char *, ...));
@ -92,20 +95,12 @@ int local_domain __P((char *));
char *topdomain __P((char *));
void usage __P((void));
#ifdef KERBEROS
#include <des.h>
#include <krb.h>
#define VERSION_SIZE 9
#define SECURE_MESSAGE "This rsh session is using DES encryption for all transmissions.\r\n"
#define OPTIONS "alnkvxDL"
char authbuf[sizeof(AUTH_DAT)];
char tickbuf[sizeof(KTEXT_ST)];
int doencrypt, use_kerberos, vacuous;
Key_schedule schedule;
#else
#define OPTIONS "alnDL"
#ifndef NO_PAM
extern int auth_pam __P((char *));
#endif
#define OPTIONS "alnDL"
int
main(argc, argv)
int argc;
@ -130,20 +125,10 @@ main(argc, argv)
case 'n':
keepalive = 0;
break;
#ifdef KERBEROS
case 'k':
use_kerberos = 1;
break;
case 'v':
vacuous = 1;
break;
#ifdef CRYPT
case 'x':
doencrypt = 1;
break;
#endif
#endif
case 'D':
no_delay = 1;
@ -160,17 +145,11 @@ main(argc, argv)
argc -= optind;
argv += optind;
#ifdef KERBEROS
if (use_kerberos && vacuous) {
syslog(LOG_ERR, "only one of -k and -v allowed");
exit(2);
}
#ifdef CRYPT
if (doencrypt && !use_kerberos) {
if (doencrypt) {
syslog(LOG_ERR, "-k is required for -x");
exit(2);
}
#endif
#endif
fromlen = sizeof (from);
@ -217,23 +196,15 @@ doit(fromp)
char *cp, sig, buf[BUFSIZ];
char cmdbuf[NCARGS+1], locuser[16], remuser[16];
char fromhost[MAXHOSTNAMELEN];
int retval;
#ifdef CRYPT
int rc;
int pv1[2], pv2[2];
#endif
#ifdef LOGIN_CAP
login_cap_t *lc;
#endif
#ifdef KERBEROS
AUTH_DAT *kdata = (AUTH_DAT *) NULL;
KTEXT ticket = (KTEXT) NULL;
char instance[INST_SZ], version[VERSION_SIZE];
struct sockaddr_in fromaddr;
int rc;
long authopts;
int pv1[2], pv2[2];
fd_set wready, writeto;
fromaddr = *fromp;
#endif
(void) signal(SIGINT, SIG_DFL);
(void) signal(SIGQUIT, SIG_DFL);
(void) signal(SIGTERM, SIG_DFL);
@ -280,17 +251,14 @@ doit(fromp)
}
#endif
#ifdef KERBEROS
if (!use_kerberos)
#endif
if (fromp->sin_port >= IPPORT_RESERVED ||
fromp->sin_port < IPPORT_RESERVED/2) {
syslog(LOG_NOTICE|LOG_AUTH,
"connection from %s on illegal port %u",
inet_ntoa(fromp->sin_addr),
fromp->sin_port);
exit(1);
}
if (fromp->sin_port >= IPPORT_RESERVED ||
fromp->sin_port < IPPORT_RESERVED/2) {
syslog(LOG_NOTICE|LOG_AUTH,
"connection from %s on illegal port %u",
inet_ntoa(fromp->sin_addr),
fromp->sin_port);
exit(1);
}
(void) alarm(60);
port = 0;
@ -316,17 +284,14 @@ doit(fromp)
syslog(LOG_ERR, "can't get stderr port: %m");
exit(1);
}
#ifdef KERBEROS
if (!use_kerberos)
#endif
if (port >= IPPORT_RESERVED ||
port < IPPORT_RESERVED/2) {
syslog(LOG_NOTICE|LOG_AUTH,
"2nd socket from %s on unreserved port %u",
inet_ntoa(fromp->sin_addr),
port);
exit(1);
}
if (port >= IPPORT_RESERVED ||
port < IPPORT_RESERVED/2) {
syslog(LOG_NOTICE|LOG_AUTH,
"2nd socket from %s on unreserved port %u",
inet_ntoa(fromp->sin_addr),
port);
exit(1);
}
fromp->sin_port = htons(port);
if (connect(s, (struct sockaddr *)fromp, sizeof (*fromp)) < 0) {
syslog(LOG_INFO, "connect second port %d: %m", port);
@ -334,60 +299,29 @@ doit(fromp)
}
}
#ifdef KERBEROS
if (vacuous) {
error("rshd: remote host requires Kerberos authentication\n");
exit(1);
}
#endif
#ifdef notdef
/* from inetd, socket is already on 0, 1, 2 */
dup2(f, 0);
dup2(f, 1);
dup2(f, 2);
#endif
errorstr = NULL;
realhostname(fromhost, sizeof(fromhost) - 1, &fromp->sin_addr);
fromhost[sizeof(fromhost) - 1] = '\0';
#ifdef KERBEROS
if (use_kerberos) {
kdata = (AUTH_DAT *) authbuf;
ticket = (KTEXT) tickbuf;
authopts = 0L;
strcpy(instance, "*");
version[VERSION_SIZE - 1] = '\0';
#ifdef CRYPT
if (doencrypt) {
struct sockaddr_in local_addr;
rc = sizeof(local_addr);
if (getsockname(0, (struct sockaddr *)&local_addr,
&rc) < 0) {
syslog(LOG_ERR, "getsockname: %m");
error("rlogind: getsockname: %m");
exit(1);
}
authopts = KOPT_DO_MUTUAL;
rc = krb_recvauth(authopts, 0, ticket,
"rcmd", instance, &fromaddr,
&local_addr, kdata, "", schedule,
version);
des_set_key(&kdata->session, schedule);
} else
#endif
rc = krb_recvauth(authopts, 0, ticket, "rcmd",
instance, &fromaddr,
(struct sockaddr_in *) 0,
kdata, "", NULL, version);
if (rc != KSUCCESS) {
error("Kerberos authentication failure: %s\n",
krb_err_txt[rc]);
if (doencrypt) {
struct sockaddr_in local_addr;
rc = sizeof(local_addr);
if (getsockname(0, (struct sockaddr *)&local_addr,
&rc) < 0) {
syslog(LOG_ERR, "getsockname: %m");
error("rlogind: getsockname: %m");
exit(1);
}
} else
authopts = KOPT_DO_MUTUAL;
rc = krb_recvauth(authopts, 0, ticket,
"rcmd", instance, &fromaddr,
&local_addr, kdata, "", schedule,
version);
des_set_key(&kdata->session, schedule);
}
#endif
getstr(remuser, sizeof(remuser), "remuser");
getstr(remuser, sizeof(remuser), "remuser");
getstr(locuser, sizeof(locuser), "locuser");
getstr(cmdbuf, sizeof(cmdbuf), "command");
@ -427,19 +361,20 @@ doit(fromp)
pwd->pw_dir = "/";
}
#ifdef KERBEROS
if (use_kerberos) {
if (pwd->pw_passwd != 0 && *pwd->pw_passwd != '\0') {
if (kuserok(kdata, locuser) != 0) {
syslog(LOG_INFO|LOG_AUTH,
"Kerberos rsh denied to %s.%s@%s",
kdata->pname, kdata->pinst, kdata->prealm);
error("Login incorrect.\n");
exit(1);
}
#ifndef NO_PAM
retval = auth_pam(locuser);
if (retval) {
if (retval == -1) {
syslog(LOG_ERR,"PAM authentication failed");
}
} else
#endif
else {
syslog(LOG_ERR,
"User %s failed PAM authentication", locuser);
exit(1);
}
}
#endif
if (errorstr ||
(pwd->pw_expire && time(NULL) >= pwd->pw_expire) ||
@ -502,7 +437,6 @@ doit(fromp)
exit(1);
}
#ifdef CRYPT
#ifdef KERBEROS
if (doencrypt) {
if (pipe(pv1) < 0) {
error("Can't make 2nd pipe.\n");
@ -513,7 +447,6 @@ doit(fromp)
exit(1);
}
}
#endif
#endif
pid = fork();
if (pid == -1) {
@ -522,7 +455,6 @@ doit(fromp)
}
if (pid) {
#ifdef CRYPT
#ifdef KERBEROS
if (doencrypt) {
static char msg[] = SECURE_MESSAGE;
(void) close(pv1[1]);
@ -531,7 +463,6 @@ doit(fromp)
schedule, &kdata->session);
} else
#endif
#endif
{
(void) close(0);
@ -548,7 +479,6 @@ doit(fromp)
else
nfd = s;
#ifdef CRYPT
#ifdef KERBEROS
if (doencrypt) {
FD_ZERO(&writeto);
FD_SET(pv2[0], &writeto);
@ -557,7 +487,6 @@ doit(fromp)
nfd = MAX(nfd, pv2[0]);
nfd = MAX(nfd, pv1[0]);
} else
#endif
#endif
ioctl(pv[0], FIONBIO, (char *)&one);
@ -566,7 +495,6 @@ doit(fromp)
do {
ready = readfrom;
#ifdef CRYPT
#ifdef KERBEROS
if (doencrypt) {
wready = writeto;
if (select(nfd, &ready,
@ -574,7 +502,6 @@ doit(fromp)
(struct timeval *) 0) < 0)
break;
} else
#endif
#endif
if (select(nfd, &ready, (fd_set *)0,
(fd_set *)0, (struct timeval *)0) < 0)
@ -582,12 +509,10 @@ doit(fromp)
if (FD_ISSET(s, &ready)) {
int ret;
#ifdef CRYPT
#ifdef KERBEROS
if (doencrypt)
ret = des_enc_read(s, &sig, 1,
schedule, &kdata->session);
else
#endif
#endif
ret = read(s, &sig, 1);
if (ret <= 0)
@ -603,20 +528,17 @@ doit(fromp)
FD_CLR(pv[0], &readfrom);
} else {
#ifdef CRYPT
#ifdef KERBEROS
if (doencrypt)
(void)
des_enc_write(s, buf, cc,
schedule, &kdata->session);
else
#endif
#endif
(void)
write(s, buf, cc);
}
}
#ifdef CRYPT
#ifdef KERBEROS
if (doencrypt && FD_ISSET(pv1[0], &ready)) {
errno = 0;
cc = read(pv1[0], buf, sizeof(buf));
@ -640,14 +562,11 @@ doit(fromp)
} else
(void) write(pv2[0], buf, cc);
}
#endif
#endif
} while (FD_ISSET(s, &readfrom) ||
#ifdef CRYPT
#ifdef KERBEROS
(doencrypt && FD_ISSET(pv1[0], &readfrom)) ||
#endif
#endif
FD_ISSET(pv[0], &readfrom));
exit(0);
@ -656,7 +575,6 @@ doit(fromp)
(void) close(s);
(void) close(pv[0]);
#ifdef CRYPT
#ifdef KERBEROS
if (doencrypt) {
close(pv1[0]); close(pv2[0]);
dup2(pv1[1], 1);
@ -664,7 +582,6 @@ doit(fromp)
close(pv1[1]);
close(pv2[1]);
}
#endif
#endif
dup2(pv[1], 2);
close(pv[1]);
@ -694,14 +611,6 @@ doit(fromp)
#endif
endpwent();
if (log_success || pwd->pw_uid == 0) {
#ifdef KERBEROS
if (use_kerberos)
syslog(LOG_INFO|LOG_AUTH,
"Kerberos shell from %s.%s@%s on %s as %s, cmd='%.80s'",
kdata->pname, kdata->pinst, kdata->prealm,
fromhost, locuser, cmdbuf);
else
#endif
syslog(LOG_INFO|LOG_AUTH, "%s@%s as %s: cmd='%.80s'",
remuser, fromhost, locuser, cmdbuf);
}