aboutsummaryrefslogtreecommitdiff
path: root/src/appl/bsd/krshd.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/appl/bsd/krshd.c')
-rw-r--r--src/appl/bsd/krshd.c292
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;
+}