Changeset View
Changeset View
Standalone View
Standalone View
head/libexec/rshd/rshd.c
Show First 20 Lines • Show All 82 Lines • ▼ Show 20 Lines | |||||
#include <syslog.h> | #include <syslog.h> | ||||
#include <unistd.h> | #include <unistd.h> | ||||
#include <login_cap.h> | #include <login_cap.h> | ||||
#include <security/pam_appl.h> | #include <security/pam_appl.h> | ||||
#include <security/openpam.h> | #include <security/openpam.h> | ||||
#include <sys/wait.h> | #include <sys/wait.h> | ||||
#ifdef USE_BLACKLIST | |||||
#include <blacklist.h> | |||||
#endif | |||||
static struct pam_conv pamc = { openpam_nullconv, NULL }; | static struct pam_conv pamc = { openpam_nullconv, NULL }; | ||||
static pam_handle_t *pamh; | static pam_handle_t *pamh; | ||||
static int pam_err; | static int pam_err; | ||||
#define PAM_END { \ | #define PAM_END { \ | ||||
if ((pam_err = pam_setcred(pamh, PAM_DELETE_CRED)) != PAM_SUCCESS) \ | if ((pam_err = pam_setcred(pamh, PAM_DELETE_CRED)) != PAM_SUCCESS) \ | ||||
syslog(LOG_ERR|LOG_AUTH, "pam_setcred(): %s", pam_strerror(pamh, pam_err)); \ | syslog(LOG_ERR|LOG_AUTH, "pam_setcred(): %s", pam_strerror(pamh, pam_err)); \ | ||||
if ((pam_err = pam_close_session(pamh,0)) != PAM_SUCCESS) \ | if ((pam_err = pam_close_session(pamh,0)) != PAM_SUCCESS) \ | ||||
▲ Show 20 Lines • Show All 148 Lines • ▼ Show 20 Lines | |||||
#endif | #endif | ||||
if (srcport >= IPPORT_RESERVED || | if (srcport >= IPPORT_RESERVED || | ||||
srcport < IPPORT_RESERVED/2) { | srcport < IPPORT_RESERVED/2) { | ||||
syslog(LOG_NOTICE|LOG_AUTH, | syslog(LOG_NOTICE|LOG_AUTH, | ||||
"connection from %s on illegal port %u", | "connection from %s on illegal port %u", | ||||
numericname, | numericname, | ||||
srcport); | srcport); | ||||
#ifdef USE_BLACKLIST | |||||
blacklist(1, STDIN_FILENO, "illegal port"); | |||||
#endif | |||||
exit(1); | exit(1); | ||||
} | } | ||||
(void) alarm(60); | (void) alarm(60); | ||||
port = 0; | port = 0; | ||||
s = 0; /* not set or used if port == 0 */ | s = 0; /* not set or used if port == 0 */ | ||||
for (;;) { | for (;;) { | ||||
char c; | char c; | ||||
Show All 17 Lines | if (s < 0) { | ||||
exit(1); | exit(1); | ||||
} | } | ||||
if (port >= IPPORT_RESERVED || | if (port >= IPPORT_RESERVED || | ||||
port < IPPORT_RESERVED/2) { | port < IPPORT_RESERVED/2) { | ||||
syslog(LOG_NOTICE|LOG_AUTH, | syslog(LOG_NOTICE|LOG_AUTH, | ||||
"2nd socket from %s on unreserved port %u", | "2nd socket from %s on unreserved port %u", | ||||
numericname, | numericname, | ||||
port); | port); | ||||
#ifdef USE_BLACKLIST | |||||
blacklist(1, STDIN_FILENO, "unreserved port"); | |||||
#endif | |||||
exit(1); | exit(1); | ||||
} | } | ||||
*((in_port_t *)&fromp->sa_data) = htons(port); | *((in_port_t *)&fromp->sa_data) = htons(port); | ||||
if (connect(s, fromp, fromp->sa_len) < 0) { | if (connect(s, fromp, fromp->sa_len) < 0) { | ||||
syslog(LOG_INFO, "connect second port %d: %m", port); | syslog(LOG_INFO, "connect second port %d: %m", port); | ||||
exit(1); | exit(1); | ||||
} | } | ||||
} | } | ||||
errorstr = NULL; | errorstr = NULL; | ||||
realhostname_sa(rhost, sizeof(rhost) - 1, fromp, fromp->sa_len); | realhostname_sa(rhost, sizeof(rhost) - 1, fromp, fromp->sa_len); | ||||
rhost[sizeof(rhost) - 1] = '\0'; | rhost[sizeof(rhost) - 1] = '\0'; | ||||
/* XXX truncation! */ | /* XXX truncation! */ | ||||
(void) alarm(60); | (void) alarm(60); | ||||
getstr(ruser, sizeof(ruser), "ruser"); | getstr(ruser, sizeof(ruser), "ruser"); | ||||
getstr(luser, sizeof(luser), "luser"); | getstr(luser, sizeof(luser), "luser"); | ||||
getstr(cmdbuf, maxcmdlen, "command"); | getstr(cmdbuf, maxcmdlen, "command"); | ||||
(void) alarm(0); | (void) alarm(0); | ||||
pam_err = pam_start("rsh", luser, &pamc, &pamh); | pam_err = pam_start("rsh", luser, &pamc, &pamh); | ||||
if (pam_err != PAM_SUCCESS) { | if (pam_err != PAM_SUCCESS) { | ||||
syslog(LOG_ERR|LOG_AUTH, "pam_start(): %s", | syslog(LOG_ERR|LOG_AUTH, "pam_start(): %s", | ||||
pam_strerror(pamh, pam_err)); | pam_strerror(pamh, pam_err)); | ||||
#ifdef USE_BLACKLIST | |||||
blacklist(1, STDIN_FILENO, "login incorrect"); | |||||
#endif | |||||
rshd_errx(1, "Login incorrect."); | rshd_errx(1, "Login incorrect."); | ||||
} | } | ||||
if ((pam_err = pam_set_item(pamh, PAM_RUSER, ruser)) != PAM_SUCCESS || | if ((pam_err = pam_set_item(pamh, PAM_RUSER, ruser)) != PAM_SUCCESS || | ||||
(pam_err = pam_set_item(pamh, PAM_RHOST, rhost)) != PAM_SUCCESS) { | (pam_err = pam_set_item(pamh, PAM_RHOST, rhost)) != PAM_SUCCESS) { | ||||
syslog(LOG_ERR|LOG_AUTH, "pam_set_item(): %s", | syslog(LOG_ERR|LOG_AUTH, "pam_set_item(): %s", | ||||
pam_strerror(pamh, pam_err)); | pam_strerror(pamh, pam_err)); | ||||
#ifdef USE_BLACKLIST | |||||
blacklist(1, STDIN_FILENO, "login incorrect"); | |||||
#endif | |||||
rshd_errx(1, "Login incorrect."); | rshd_errx(1, "Login incorrect."); | ||||
} | } | ||||
pam_err = pam_authenticate(pamh, 0); | pam_err = pam_authenticate(pamh, 0); | ||||
if (pam_err == PAM_SUCCESS) { | if (pam_err == PAM_SUCCESS) { | ||||
if ((pam_err = pam_get_user(pamh, &cp, NULL)) == PAM_SUCCESS) { | if ((pam_err = pam_get_user(pamh, &cp, NULL)) == PAM_SUCCESS) { | ||||
strncpy(luser, cp, sizeof(luser)); | strncpy(luser, cp, sizeof(luser)); | ||||
luser[sizeof(luser) - 1] = '\0'; | luser[sizeof(luser) - 1] = '\0'; | ||||
/* XXX truncation! */ | /* XXX truncation! */ | ||||
} | } | ||||
pam_err = pam_acct_mgmt(pamh, 0); | pam_err = pam_acct_mgmt(pamh, 0); | ||||
} | } | ||||
if (pam_err != PAM_SUCCESS) { | if (pam_err != PAM_SUCCESS) { | ||||
syslog(LOG_INFO|LOG_AUTH, | syslog(LOG_INFO|LOG_AUTH, | ||||
"%s@%s as %s: permission denied (%s). cmd='%.80s'", | "%s@%s as %s: permission denied (%s). cmd='%.80s'", | ||||
ruser, rhost, luser, pam_strerror(pamh, pam_err), cmdbuf); | ruser, rhost, luser, pam_strerror(pamh, pam_err), cmdbuf); | ||||
#ifdef USE_BLACKLIST | |||||
blacklist(1, STDIN_FILENO, "permission denied"); | |||||
#endif | |||||
rshd_errx(1, "Login incorrect."); | rshd_errx(1, "Login incorrect."); | ||||
} | } | ||||
setpwent(); | setpwent(); | ||||
pwd = getpwnam(luser); | pwd = getpwnam(luser); | ||||
if (pwd == NULL) { | if (pwd == NULL) { | ||||
syslog(LOG_INFO|LOG_AUTH, | syslog(LOG_INFO|LOG_AUTH, | ||||
"%s@%s as %s: unknown login. cmd='%.80s'", | "%s@%s as %s: unknown login. cmd='%.80s'", | ||||
ruser, rhost, luser, cmdbuf); | ruser, rhost, luser, cmdbuf); | ||||
#ifdef USE_BLACKLIST | |||||
blacklist(1, STDIN_FILENO, "unknown login"); | |||||
#endif | |||||
if (errorstr == NULL) | if (errorstr == NULL) | ||||
errorstr = "Login incorrect."; | errorstr = "Login incorrect."; | ||||
rshd_errx(1, errorstr, rhost); | rshd_errx(1, errorstr, rhost); | ||||
} | } | ||||
lc = login_getpwclass(pwd); | lc = login_getpwclass(pwd); | ||||
if (pwd->pw_uid) | if (pwd->pw_uid) | ||||
auth_checknologin(lc); | auth_checknologin(lc); | ||||
Show All 16 Lines | strncpy(remote_ip, numericname, | ||||
sizeof(remote_ip) - 1); | sizeof(remote_ip) - 1); | ||||
remote_ip[sizeof(remote_ip) - 1] = 0; | remote_ip[sizeof(remote_ip) - 1] = 0; | ||||
/* XXX truncation! */ | /* XXX truncation! */ | ||||
if (!auth_hostok(lc, rhost, remote_ip)) { | if (!auth_hostok(lc, rhost, remote_ip)) { | ||||
syslog(LOG_INFO|LOG_AUTH, | syslog(LOG_INFO|LOG_AUTH, | ||||
"%s@%s as %s: permission denied (%s). cmd='%.80s'", | "%s@%s as %s: permission denied (%s). cmd='%.80s'", | ||||
ruser, rhost, luser, __rcmd_errstr, | ruser, rhost, luser, __rcmd_errstr, | ||||
cmdbuf); | cmdbuf); | ||||
#ifdef USE_BLACKLIST | |||||
blacklist(1, STDIN_FILENO, "permission denied"); | |||||
#endif | |||||
rshd_errx(1, "Login incorrect."); | rshd_errx(1, "Login incorrect."); | ||||
} | } | ||||
if (!auth_timeok(lc, time(NULL))) | if (!auth_timeok(lc, time(NULL))) | ||||
rshd_errx(1, "Logins not available right now"); | rshd_errx(1, "Logins not available right now"); | ||||
} | } | ||||
/* | /* | ||||
* PAM modules might add supplementary groups in | * PAM modules might add supplementary groups in | ||||
▲ Show 20 Lines • Show All 79 Lines • ▼ Show 20 Lines | if (pid) { | ||||
/* Parent. */ | /* Parent. */ | ||||
while (wait(NULL) > 0 || errno == EINTR) | while (wait(NULL) > 0 || errno == EINTR) | ||||
/* nothing */ ; | /* nothing */ ; | ||||
PAM_END; | PAM_END; | ||||
exit(0); | exit(0); | ||||
} | } | ||||
} | } | ||||
#ifdef USE_BLACKLIST | |||||
blacklist(0, STDIN_FILENO, "success"); | |||||
#endif | |||||
for (fd = getdtablesize(); fd > 2; fd--) | for (fd = getdtablesize(); fd > 2; fd--) | ||||
(void) close(fd); | (void) close(fd); | ||||
if (setsid() == -1) | if (setsid() == -1) | ||||
syslog(LOG_ERR, "setsid() failed: %m"); | syslog(LOG_ERR, "setsid() failed: %m"); | ||||
if (setlogin(pwd->pw_name) < 0) | if (setlogin(pwd->pw_name) < 0) | ||||
syslog(LOG_ERR, "setlogin() failed: %m"); | syslog(LOG_ERR, "setlogin() failed: %m"); | ||||
if (*pwd->pw_shell == '\0') | if (*pwd->pw_shell == '\0') | ||||
▲ Show 20 Lines • Show All 50 Lines • ▼ Show 20 Lines | |||||
getstr(char *buf, int cnt, const char *error) | getstr(char *buf, int cnt, const char *error) | ||||
{ | { | ||||
char c; | char c; | ||||
do { | do { | ||||
if (read(STDIN_FILENO, &c, 1) != 1) | if (read(STDIN_FILENO, &c, 1) != 1) | ||||
exit(1); | exit(1); | ||||
*buf++ = c; | *buf++ = c; | ||||
if (--cnt == 0) | if (--cnt == 0) { | ||||
#ifdef USE_BLACKLIST | |||||
blacklist(1, STDIN_FILENO, "buffer overflow"); | |||||
#endif | |||||
rshd_errx(1, "%s too long", error); | rshd_errx(1, "%s too long", error); | ||||
} | |||||
} while (c != 0); | } while (c != 0); | ||||
} | } | ||||
/* | /* | ||||
* Check whether host h is in our local domain, | * Check whether host h is in our local domain, | ||||
* defined as sharing the last two components of the domain part, | * defined as sharing the last two components of the domain part, | ||||
* or the entire domain part if the local domain has only one component. | * or the entire domain part if the local domain has only one component. | ||||
* If either name is unqualified (contains no '.'), | * If either name is unqualified (contains no '.'), | ||||
▲ Show 20 Lines • Show All 43 Lines • Show Last 20 Lines |