Fix for new Kerberos4. Make a fist cut at PAM-ising while I'm here.
This commit is contained in:
parent
ae3b8c19b1
commit
6c9134c067
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=51433
@ -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>
|
||||
|
@ -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);
|
||||
|
@ -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
142
libexec/rlogind/auth_pam.c
Normal 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;
|
||||
}
|
@ -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"
|
||||
|
@ -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 "]");
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user