diff options
Diffstat (limited to 'src/appl/bsd/krshd.c')
-rw-r--r-- | src/appl/bsd/krshd.c | 292 |
1 files changed, 136 insertions, 156 deletions
diff --git a/src/appl/bsd/krshd.c b/src/appl/bsd/krshd.c index 8570b60..aa3f2ed 100644 --- a/src/appl/bsd/krshd.c +++ b/src/appl/bsd/krshd.c @@ -39,25 +39,14 @@ char copyright[] = * This is the rshell daemon. The very basic protocol for checking * authentication and authorization is: * 1) Check authentication. - * 2) Check authorization via the access-control files: - * ~/.k5login (using krb5_kuserok) and/or + * 2) Check authorization via the access-control files: + * ~/.k5login (using krb5_kuserok) * Execute command if configured authoriztion checks pass, else deny * permission. - * - * The configuration is done either by command-line arguments passed by inetd, - * or by the name of the daemon. If command-line arguments are present, they - * take priority. The options are: - * -k means trust krb4 or krb5 - * -5 means trust krb5 - * -4 means trust krb4 (using .klogin) - * */ /* DEFINES: * KERBEROS - Define this if application is to be kerberised. - * KRB5_KRB4_COMPAT - Define this if v4 rlogin clients are also to be served. - * ALWAYS_V5_KUSEROK - Define this if you want .k5login to be - * checked even for v4 clients (instead of .klogin). * LOG_ALL_LOGINS - Define this if you want to log all logins. * LOG_OTHER_USERS - Define this if you want to log all principals that do * not map onto the local user. @@ -87,10 +76,7 @@ char copyright[] = #include <sys/types.h> #include <sys/ioctl.h> #include <sys/param.h> -#if !defined(KERBEROS) || !defined(KRB5_KRB4_COMPAT) -/* Ultrix doesn't protect it vs multiple inclusion, and krb.h includes it */ #include <sys/socket.h> -#endif #include <sys/file.h> #include <sys/stat.h> #include <sys/time.h> @@ -122,10 +108,7 @@ char copyright[] = #include <stdarg.h> #include <signal.h> -#if !defined(KERBEROS) || !defined(KRB5_KRB4_COMPAT) -/* Ultrix doesn't protect it vs multiple inclusion, and krb.h includes it */ #include <netdb.h> -#endif #ifdef CRAY #ifndef NO_UDB @@ -159,10 +142,6 @@ char copyright[] = #include "k5-int.h" #include <com_err.h> #include "loginpaths.h" -#ifdef KRB5_KRB4_COMPAT -#include <kerberosIV/krb.h> -Key_schedule v4_schedule; -#endif #include <k5-util.h> #include <k5-platform.h> @@ -186,7 +165,7 @@ Key_schedule v4_schedule; #define MAXDNAME 256 /*per the rfc*/ #endif -#define ARGSTR "ek54ciD:S:M:AP:?L:w:" +#define ARGSTR "ek5ciD:S:M:AP:?L:w:" @@ -218,22 +197,13 @@ static krb5_error_code recvauth(int netfd, struct sockaddr *peersin, #endif /* KERBEROS */ +static int accept_a_connection (int debug_port, struct sockaddr *from, + socklen_t *fromlenp); #ifndef HAVE_KILLPG #define killpg(pid, sig) kill(-(pid), (sig)) #endif -/* There are two authentication related masks: - * auth_ok and auth_sent. -* The auth_ok mask is the oring of authentication systems any one -* of which can be used. -* The auth_sent mask is the oring of one or more authentication/authorization -* systems that succeeded. If the anding -* of these two masks is true, then authorization is successful. -*/ -#define AUTH_KRB4 (0x1) -#define AUTH_KRB5 (0x2) -int auth_ok = 0, auth_sent = 0; int checksum_required = 0, checksum_ignored = 0; char *progname; @@ -321,15 +291,9 @@ int main(argc, argv) switch (ch) { #ifdef KERBEROS case 'k': -#ifdef KRB5_KRB4_COMPAT - auth_ok |= (AUTH_KRB5|AUTH_KRB4); -#else - auth_ok |= AUTH_KRB5; -#endif /* KRB5_KRB4_COMPAT*/ break; case '5': - auth_ok |= AUTH_KRB5; break; case 'c': checksum_required = 1; @@ -338,12 +302,6 @@ int main(argc, argv) checksum_ignored = 1; break; -#ifdef KRB5_KRB4_COMPAT - case '4': - auth_ok |= AUTH_KRB4; - break; -#endif - case 'e': require_encrypt = 1; break; @@ -538,16 +496,6 @@ char *kremuser; krb5_principal client; krb5_authenticator *kdata; -#ifdef KRB5_KRB4_COMPAT -AUTH_DAT *v4_kdata; -KTEXT v4_ticket; -#endif - -int auth_sys = 0; /* Which version of Kerberos used to authenticate */ - -#define KRB5_RECVAUTH_V4 4 -#define KRB5_RECVAUTH_V5 5 - static void ignore_signals() { @@ -1091,31 +1039,14 @@ void doit(f, fromp) } #ifdef KERBEROS - -#if defined(KRB5_KRB4_COMPAT) && !defined(ALWAYS_V5_KUSEROK) - if (auth_sys == KRB5_RECVAUTH_V4) { - /* kuserok returns 0 if OK */ - if (kuserok(v4_kdata, locuser)){ - syslog(LOG_ERR , - "Principal %s (%s@%s (%s)) for local user %s failed kuserok.\n", - kremuser, remuser, hostaddra, hostname, locuser); - } - else auth_sent |= AUTH_KRB4; - } else -#endif - { - /* krb5_kuserok returns 1 if OK */ - if (!krb5_kuserok(bsd_context, client, locuser)){ - syslog(LOG_ERR , - "Principal %s (%s@%s (%s)) for local user %s failed krb5_kuserok.\n", - kremuser, remuser, hostaddra, hostname, locuser); - } - else - auth_sent |= - ((auth_sys == KRB5_RECVAUTH_V4) ? AUTH_KRB4 : AUTH_KRB5); - } - - + /* krb5_kuserok returns 1 if OK */ + if (!krb5_kuserok(bsd_context, client, locuser)){ + syslog(LOG_ERR , + "Principal %s (%s@%s (%s)) for local user %s failed krb5_kuserok.\n", + kremuser, remuser, hostaddra, hostname, locuser); + error("Permission denied.\n"); + goto signout_please; + } #else if (pwd->pw_passwd != 0 && *pwd->pw_passwd != '\0' && ruserok(hostname[0] ? hostname : hostaddra, @@ -1127,26 +1058,14 @@ void doit(f, fromp) if (checksum_required && !valid_checksum) { - if (auth_sent & AUTH_KRB5) { - syslog(LOG_WARNING, "Client did not supply required checksum--connection rejected."); - error( "You are using an old Kerberos5 client without checksum support; only newer clients are authorized.\n"); - goto signout_please; - } else { - syslog(LOG_WARNING, - "Configuration error: Requiring checksums with -c is inconsistent with allowing Kerberos V4 connections."); - } + syslog(LOG_WARNING, "Client did not supply required checksum--connection rejected."); + error( "You are using an old Kerberos5 client without checksum support; only newer clients are authorized.\n"); + goto signout_please; } if (require_encrypt&&(!do_encrypt)) { error("You must use encryption.\n"); goto signout_please; } - if (!(auth_ok&auth_sent)) { - if (auth_sent) - error("Another authentication mechanism must be used to access this host.\n"); - else - error("Permission denied.\n"); - goto signout_please; - } if (pwd->pw_uid && !access(NOLOGIN, F_OK)) { error("Logins currently disabled.\n"); @@ -1519,10 +1438,7 @@ void doit(f, fromp) strlcpy(cmdbuf + offst, kprogdir, sizeof(cmdbuf) - offst); cp = copy + 3 + offst; - if (auth_sys == KRB5_RECVAUTH_V4) - strlcat(cmdbuf, "/v4rcp", sizeof(cmdbuf)); - else - strlcat(cmdbuf, "/rcp", sizeof(cmdbuf)); + strlcat(cmdbuf, "/rcp", sizeof(cmdbuf)); if (stat((char *)cmdbuf + offst, &s2) >= 0) strlcat(cmdbuf, cp, sizeof(cmdbuf)); @@ -1771,7 +1687,7 @@ loglogin(host, flag, failures, ue) void usage() { #ifdef KERBEROS - syslog(LOG_ERR, "usage: kshd [-54ecikK] "); + syslog(LOG_ERR, "usage: kshd [-eciK] "); #else syslog(LOG_ERR, "usage: rshd"); #endif @@ -1798,9 +1714,6 @@ recvauth(netfd, peersin, valid_checksum) struct sockaddr_in laddr; socklen_t len; krb5_data inbuf; -#ifdef KRB5_KRB4_COMPAT - char v4_instance[INST_SZ]; /* V4 Instance */ -#endif krb5_authenticator *authenticator; krb5_ticket *ticket; krb5_rcache rcache; @@ -1822,10 +1735,6 @@ recvauth(netfd, peersin, valid_checksum) #define SIZEOF_INADDR sizeof(struct in_addr) #endif -#ifdef KRB5_KRB4_COMPAT - strlcpy(v4_instance, "*", sizeof(v4_instance)); -#endif - status = krb5_auth_con_init(bsd_context, &auth_context); if (status) return status; @@ -1855,66 +1764,25 @@ recvauth(netfd, peersin, valid_checksum) if (status) return status; } -#ifdef KRB5_KRB4_COMPAT - status = krb5_compat_recvauth_version(bsd_context, &auth_context, &netfd, - NULL, /* Specify daemon principal */ - 0, /* no flags */ - keytab, /* normally NULL to use v5srvtab */ - 0, /* v4_opts */ - "rcmd", /* v4_service */ - v4_instance, /* v4_instance */ - (struct sockaddr_in *)peersin, /* foreign address */ - &laddr, /* our local address */ - "", /* use default srvtab */ - - &ticket, /* return ticket */ - &auth_sys, /* which authentication system*/ - &v4_kdata, 0, &version); -#else status = krb5_recvauth_version(bsd_context, &auth_context, &netfd, NULL, /* daemon principal */ 0, /* no flags */ keytab, /* normally NULL to use v5srvtab */ &ticket, /* return ticket */ &version); /* application version string */ - auth_sys = KRB5_RECVAUTH_V5; -#endif if (status) { - if (auth_sys == KRB5_RECVAUTH_V5) { - /* - * clean up before exiting - */ - getstr(netfd, locuser, sizeof(locuser), "locuser"); - getstr(netfd, cmdbuf, sizeof(cmdbuf), "command"); - getstr(netfd, remuser, sizeof(locuser), "remuser"); - } + /* + * clean up before exiting + */ + getstr(netfd, locuser, sizeof(locuser), "locuser"); + getstr(netfd, cmdbuf, sizeof(cmdbuf), "command"); + getstr(netfd, remuser, sizeof(locuser), "remuser"); return status; } getstr(netfd, locuser, sizeof(locuser), "locuser"); getstr(netfd, cmdbuf, sizeof(cmdbuf), "command"); -#ifdef KRB5_KRB4_COMPAT - if (auth_sys == KRB5_RECVAUTH_V4) { - rcmd_stream_init_normal(); - - /* We do not really know the remote user's login name. - * Assume it to be the same as the first component of the - * principal's name. - */ - strlcpy(remuser, v4_kdata->pname, sizeof(remuser)); - - status = krb5_425_conv_principal(bsd_context, v4_kdata->pname, - v4_kdata->pinst, v4_kdata->prealm, - &client); - if (status) return status; - - status = krb5_unparse_name(bsd_context, client, &kremuser); - - return status; - } -#endif /* KRB5_KRB4_COMPAT */ - /* Must be V5 */ kcmd_proto = KCMD_UNKNOWN_PROTOCOL; @@ -2061,3 +1929,115 @@ void fatal(f, msg) } exit(1); } + +static int +accept_a_connection (int debug_port, struct sockaddr *from, + socklen_t *fromlenp) +{ + int n, s, fd, s4 = -1, s6 = -1, on = 1; + fd_set sockets; + + FD_ZERO(&sockets); + +#ifdef KRB5_USE_INET6 + { + struct sockaddr_in6 sock_in6; + + if ((s = socket(AF_INET6, SOCK_STREAM, PF_UNSPEC)) < 0) { + if ((errno == EPROTONOSUPPORT) || (errno == EAFNOSUPPORT)) + goto skip_ipv6; + fprintf(stderr, "Error in socket(INET6): %s\n", strerror(errno)); + exit(2); + } + + memset((char *) &sock_in6, 0,sizeof(sock_in6)); + sock_in6.sin6_family = AF_INET6; + sock_in6.sin6_port = htons(debug_port); + sock_in6.sin6_addr = in6addr_any; + + (void) setsockopt(s, SOL_SOCKET, SO_REUSEADDR, + (char *)&on, sizeof(on)); + + if ((bind(s, (struct sockaddr *) &sock_in6, sizeof(sock_in6))) < 0) { + fprintf(stderr, "Error in bind(INET6): %s\n", strerror(errno)); + exit(2); + } + + if ((listen(s, 5)) < 0) { + fprintf(stderr, "Error in listen(INET6): %s\n", strerror(errno)); + exit(2); + } + s6 = s; + FD_SET(s, &sockets); + skip_ipv6: + ; + } +#endif + + { + struct sockaddr_in sock_in; + + if ((s = socket(AF_INET, SOCK_STREAM, PF_UNSPEC)) < 0) { + fprintf(stderr, "Error in socket: %s\n", strerror(errno)); + exit(2); + } + + memset((char *) &sock_in, 0,sizeof(sock_in)); + sock_in.sin_family = AF_INET; + sock_in.sin_port = htons(debug_port); + sock_in.sin_addr.s_addr = INADDR_ANY; + + (void) setsockopt(s, SOL_SOCKET, SO_REUSEADDR, + (char *)&on, sizeof(on)); + + if ((bind(s, (struct sockaddr *) &sock_in, sizeof(sock_in))) < 0) { + if (s6 >= 0 && errno == EADDRINUSE) + goto try_ipv6_only; + fprintf(stderr, "Error in bind: %s\n", strerror(errno)); + exit(2); + } + + if ((listen(s, 5)) < 0) { + fprintf(stderr, "Error in listen: %s\n", strerror(errno)); + exit(2); + } + s4 = s; + FD_SET(s, &sockets); + try_ipv6_only: + ; + } + if (s4 == -1 && s6 == -1) { + fprintf(stderr, "No valid sockets established, exiting\n"); + exit(2); + } + n = select(((s4 < s6) ? s6 : s4) + 1, &sockets, 0, 0, 0); + if (n < 0) { + fprintf(stderr, "select error: %s\n", strerror(errno)); + exit(2); + } else if (n == 0) { + fprintf(stderr, "internal error? select returns 0\n"); + exit(2); + } + if (s6 != -1 && FD_ISSET(s6, &sockets)) { + if (s4 != -1) + close(s4); + s = s6; + } else if (FD_ISSET(s4, &sockets)) { + if (s6 != -1) + close(s6); + s = s4; + } else { + fprintf(stderr, + "internal error? select returns positive, " + "but neither fd available\n"); + exit(2); + } + + if ((fd = accept(s, from, fromlenp)) < 0) { + fprintf(stderr, "Error in accept: %s\n", strerror(errno)); + exit(2); + } + + close(s); + return fd; +} |