From owner-freebsd-bugs Fri Jul 23 8: 1:25 1999 Delivered-To: freebsd-bugs@freebsd.org Received: from freefall.freebsd.org (freefall.FreeBSD.ORG [204.216.27.21]) by hub.freebsd.org (Postfix) with ESMTP id 5D67E15251 for ; Fri, 23 Jul 1999 08:01:18 -0700 (PDT) (envelope-from gnats@FreeBSD.org) Received: (from gnats@localhost) by freefall.freebsd.org (8.9.3/8.9.2) id IAA66197; Fri, 23 Jul 1999 08:00:02 -0700 (PDT) (envelope-from gnats@FreeBSD.org) Received: by hub.freebsd.org (Postfix, from userid 32767) id C34C914C35; Fri, 23 Jul 1999 07:58:36 -0700 (PDT) Message-Id: <19990723145836.C34C914C35@hub.freebsd.org> Date: Fri, 23 Jul 1999 07:58:36 -0700 (PDT) From: dagill@unx.sas.com To: freebsd-gnats-submit@freebsd.org X-Send-Pr-Version: www-1.0 Subject: misc/12776: Add PAM hooks to rlogind and rshd Sender: owner-freebsd-bugs@FreeBSD.ORG Precedence: bulk X-Loop: FreeBSD.org >Number: 12776 >Category: misc >Synopsis: Add PAM hooks to rlogind and rshd >Confidential: no >Severity: non-critical >Priority: medium >Responsible: freebsd-bugs >State: open >Quarter: >Keywords: >Date-Required: >Class: change-request >Submitter-Id: current-users >Arrival-Date: Fri Jul 23 08:00:02 PDT 1999 >Closed-Date: >Last-Modified: >Originator: Dave Gillham >Release: -current (4.0-19990704) >Organization: SAS Institute Inc. >Environment: FreeBSD frink.unx.sas.com 4.0-19990704-SNAP FreeBSD 4.0-19990704-SNAP #0: Tue Jul 6 14:11:50 EDT 1999 root@itchy.unx.sas.com:/usr/src/sys/compile/BBKERN i386 >Description: Attached are patches for rshd and rlogind to add a hook to use PAM modules to handle user authentication. The following code (which originally came from login) gives us the ability to use PAM to deny the user access before attempting to access their .rhosts file. Without these changes, rsh and rlogin authenticate the user by their .rhosts file without giving PAM a chance to validate them. With these changes, we provide the oportunity to callout to PAM before any .rhost checking and thus deny user login based on the policy coded into the PAM module. Please consider these changes for review and integration into the base system. >How-To-Repeat: n/a >Fix: Index: rlogind/Makefile =================================================================== RCS file: /usr/mirror/ncvs/src/libexec/rlogind/Makefile,v retrieving revision 1.10 diff -r1.10 Makefile 23a24,30 > .if defined(NOPAM) > CFLAGS+= -DNO_PAM > .else > DPADD+= ${LIBPAM} > LDADD+= ${MINUSLPAM} > .endif > Index: rlogind/rlogind.c =================================================================== RCS file: /usr/mirror/ncvs/src/libexec/rlogind/rlogind.c,v retrieving revision 1.23 diff -r1.23 rlogind.c 82a83,87 > #ifndef NO_PAM > #include > #include > #endif > 125a131,134 > #ifndef NO_PAM > static int auth_pam __P((char *)); > #endif > 198a208,313 > #ifndef NO_PAM > /* > * 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(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; > } > #endif > 278a394,395 > > 588a706 > int retval; 596a715,727 > > #ifndef NO_PAM > retval = auth_pam(lusername); > > if (retval < 0) { > syslog(LOG_ERR,"PAM authentication failed"); > } > else if (retval == 1) { > syslog(LOG_ERR,"User %s failed PAM authentication",lusername); > exit(1); > } > #endif > Index: rshd/Makefile =================================================================== RCS file: /usr/mirror/ncvs/src/libexec/rshd/Makefile,v retrieving revision 1.10 diff -r1.10 Makefile 19a20,26 > .if defined(NOPAM) > CFLAGS+= -DNO_PAM > .else > DPADD+= ${LIBPAM} > LDADD+= ${MINUSLPAM} > .endif > Index: rshd/rshd.c =================================================================== RCS file: /usr/mirror/ncvs/src/libexec/rshd/rshd.c,v retrieving revision 1.25 diff -r1.25 rshd.c 82a83,87 > #ifndef NO_PAM > #include > #include > #endif > 94a100,103 > #ifndef NO_PAM > static int auth_pam __P((char *)); > #endif > 197a207,314 > #ifndef NO_PAM > /* > * 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(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; > } > #endif > 215a333 > int retval; 428a547,558 > > #ifndef NO_PAM > retval = auth_pam(locuser); > > if (retval < 0) { > syslog(LOG_ERR,"PAM authentication failed"); > } > else if (retval == 1) { > syslog(LOG_ERR,"User %s failed PAM authentication",locuser); > exit(1); > } > #endif >Release-Note: >Audit-Trail: >Unformatted: To Unsubscribe: send mail to majordomo@FreeBSD.org with "unsubscribe freebsd-bugs" in the body of the message