From 0b2fe68756570c146bda89ff69a3d209aac9f8be Mon Sep 17 00:00:00 2001 From: markm Date: Sun, 19 Sep 1999 22:05:32 +0000 Subject: Fix for new Kerberos4. Make a fist cut at PAM-ising while I'm here. --- libexec/rlogind/Makefile | 17 ++--- libexec/rlogind/auth_pam.c | 142 ++++++++++++++++++++++++++++++++++++++ libexec/rlogind/pathnames.h | 2 + libexec/rlogind/rlogind.c | 162 ++++++++------------------------------------ 4 files changed, 177 insertions(+), 146 deletions(-) create mode 100644 libexec/rlogind/auth_pam.c (limited to 'libexec/rlogind') diff --git a/libexec/rlogind/Makefile b/libexec/rlogind/Makefile index ae34f30..bae4a4b 100644 --- a/libexec/rlogind/Makefile +++ b/libexec/rlogind/Makefile @@ -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 diff --git a/libexec/rlogind/auth_pam.c b/libexec/rlogind/auth_pam.c new file mode 100644 index 0000000..e452107 --- /dev/null +++ b/libexec/rlogind/auth_pam.c @@ -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 +#include +#include +#include +#include +#include +#include +#include +#include + +/* + * 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; +} diff --git a/libexec/rlogind/pathnames.h b/libexec/rlogind/pathnames.h index 5240f19..17a8f5c 100644 --- a/libexec/rlogind/pathnames.h +++ b/libexec/rlogind/pathnames.h @@ -31,8 +31,10 @@ * SUCH DAMAGE. * * @(#)pathnames.h 8.1 (Berkeley) 6/4/93 + * $FreeBSD$ */ #include #define _PATH_LOGIN "/usr/bin/login" +#define _PATH_RLOGIN "/usr/bin/rlogin" diff --git a/libexec/rlogind/rlogind.c b/libexec/rlogind/rlogind.c index a99ac7e..111a56b 100644 --- a/libexec/rlogind/rlogind.c +++ b/libexec/rlogind/rlogind.c @@ -80,26 +80,16 @@ static const char rcsid[] = #include #include "pathnames.h" +#ifndef NO_PAM +#include +#include +#endif + #ifndef TIOCPKT_WINDOW #define TIOCPKT_WINDOW 0x80 #endif -#ifdef KERBEROS -#include -#include -#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,19 +143,11 @@ 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: usage(); @@ -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,7 +248,6 @@ doit(f, fromp) write(f, "", 1); confirmed = 1; /* we sent the null! */ } -#ifdef KERBEROS #ifdef CRYPT if (doencrypt) (void) des_enc_write(f, @@ -291,7 +255,6 @@ doit(f, fromp) strlen(SECURE_MESSAGE), schedule, &kdata->session); #endif -#endif netf = f; pid = forkpty(&master, line, NULL, &win); @@ -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,7 +283,6 @@ doit(f, fromp) /*NOTREACHED*/ } #ifdef CRYPT -#ifdef KERBEROS /* * If encrypted, don't turn on NBIO or the des read/write * routines will croak. @@ -336,7 +290,6 @@ doit(f, fromp) if (!doencrypt) #endif -#endif ioctl(f, FIONBIO, &on); ioctl(master, FIONBIO, &on); ioctl(master, TIOCPKT, &on); @@ -445,13 +398,11 @@ 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) fcc = 0; @@ -499,10 +450,8 @@ 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 { if (pkcontrol(pibuf[0])) { @@ -514,13 +463,11 @@ 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 "]"); } -- cgit v1.1