From: Sam Hartman Date: Wed, 24 Jan 1996 08:56:24 +0000 (+0000) Subject: * Add checksum support to klogind making sure encrypted authenticators X-Git-Tag: krb5-1.0-beta6~577 X-Git-Url: http://git.tremily.us/?a=commitdiff_plain;h=d06a3264274e8aa817fb4e3271762b407928c438;p=krb5.git * Add checksum support to klogind making sure encrypted authenticators cannot be replayed against unencrypted connections. * Updated checksumming in kshd to be compatible with klogind so they use the same client code. CVS: * Fixed Makefile to install kshd and klogind not kr*d * Updated option process in krlogind and kshd per messages to c.p.k. ---------------------------------------------------------------------- automatically CVS: CVS: Committing in . CVS: CVS: Modified Files: ---------------------------------------------------------------------- git-svn-id: svn://anonsvn.mit.edu/krb5/trunk@7372 dc483132-0cff-0310-8789-dd5450dbe970 --- diff --git a/src/appl/bsd/ChangeLog b/src/appl/bsd/ChangeLog index 564e33de8..2ed5556de 100644 --- a/src/appl/bsd/ChangeLog +++ b/src/appl/bsd/ChangeLog @@ -1,9 +1,36 @@ +Wed Jan 24 00:34:42 1996 Sam Hartman + + * Makefile.in (install): Install as kshd and klogind not krshd and + krlogind. + + * krshd.c (main): Use krlogind-style options (-54kce) + + * krlogind.c (main): Change option parsing to support new format. + (do_krb_login): Use auth_ok and auth_sent masks instead of passed_* + +Tue Jan 23 18:10:55 1996 Sam Hartman + + * krshd.c (recvauth): Use the correct username in strlen call for + allocating chksumbuf. + + * krlogind.c (recvauth): Code to copy checksum verification code. + + +Mon Jan 22 15:14:11 1996 Sam Hartman + + * krshd.c (recvauth): Update to expect port in checksum. + + * kcmd.c (kcmd): Include port in string of checksumed data to + distinguish between encrypted and unencrypted rlogin. + + Mon Jan 22 18:14:05 1996 Ezra Peisach * krcp.c: Use KRB5_STDARG_P. * configure.in: Add KRB5_CHECK_PROTOS for prototyps definitions. + Fri Jan 19 10:45:29 1996 Sam Hartman * krshd.c (recvauth): Verify checksum against command line and remote user. diff --git a/src/appl/bsd/Makefile.in b/src/appl/bsd/Makefile.in index 9bbdd56d2..7ae3e0b29 100644 --- a/src/appl/bsd/Makefile.in +++ b/src/appl/bsd/Makefile.in @@ -25,10 +25,10 @@ BSD= -DUCB_RLOGIN=\"$(UCB_RLOGIN)\" \ DEFINES= $(RSH) $(BSD) $(RPROGS) \ -DLOGIN_PROGRAM=\"$(SERVER_BINDIR)/login.krb5\" -DKPROGDIR=\"$(CLIENT_BINDIR)\" -all:: rsh rcp rlogin krshd krlogind login.krb5 +all:: rsh rcp rlogin kshd klogind login.krb5 clean:: - $(RM) rsh rcp rlogin krshd krlogind login.krb5 + $(RM) rsh rcp rlogin kshd klogind login.krb5 rsh: krsh.o kcmd.o forward.o $(SETENVOBJ) $(LIBOBJS) $(DEPLIBS) $(LD) $(LDFLAGS) $(LDARGS) -o rsh krsh.o kcmd.o forward.o $(SETENVOBJ) $(LIBOBJS) $(LIBS) @@ -51,19 +51,19 @@ install:: $(INSTALL_PROGRAM) rlogin $(DESTDIR)$(CLIENT_BINDIR)/rlogin $(INSTALL_DATA) $(srcdir)/rlogin.M ${DESTDIR}$(CLIENT_MANDIR)/rlogin.1 -krshd: krshd.o kcmd.o forward.o $(SETENVOBJ) $(LIBOBJS) $(DEPLIBS) - $(LD) $(LDFLAGS) $(LDARGS) -o krshd krshd.o kcmd.o forward.o $(SETENVOBJ) $(LIBOBJS) $(LIBS) +kshd: krshd.o kcmd.o forward.o $(SETENVOBJ) $(LIBOBJS) $(DEPLIBS) + $(LD) $(LDFLAGS) $(LDARGS) -o kshd krshd.o kcmd.o forward.o $(SETENVOBJ) $(LIBOBJS) $(LIBS) install:: - $(INSTALL_PROGRAM) krshd $(DESTDIR)$(SERVER_BINDIR)/krshd - $(INSTALL_DATA) $(srcdir)/krshd.M ${DESTDIR}$(SERVER_MANDIR)/krshd.8 + $(INSTALL_PROGRAM) kshd $(DESTDIR)$(SERVER_BINDIR)/kshd + $(INSTALL_DATA) $(srcdir)/krshd.M ${DESTDIR}$(SERVER_MANDIR)/kshd.8 -krlogind: krlogind.o kcmd.o forward.o $(SETENVOBJ) $(LIBOBJS) $(DEPLIBS) - $(LD) $(LDFLAGS) $(LDARGS) -o krlogind krlogind.o kcmd.o forward.o $(SETENVOBJ) $(LIBOBJS) $(LIBS) +klogind: krlogind.o kcmd.o forward.o $(SETENVOBJ) $(LIBOBJS) $(DEPLIBS) + $(LD) $(LDFLAGS) $(LDARGS) -o klogind krlogind.o kcmd.o forward.o $(SETENVOBJ) $(LIBOBJS) $(LIBS) install:: - $(INSTALL_PROGRAM) krlogind $(DESTDIR)$(SERVER_BINDIR)/krlogind - $(INSTALL_DATA) $(srcdir)/krlogind.M ${DESTDIR}$(SERVER_MANDIR)/krlogind.8 + $(INSTALL_PROGRAM) klogind $(DESTDIR)$(SERVER_BINDIR)/klogind + $(INSTALL_DATA) $(srcdir)/krlogind.M ${DESTDIR}$(SERVER_MANDIR)/klogind.8 # # We load the libraries twice here since des425 has a dependency on diff --git a/src/appl/bsd/kcmd.c b/src/appl/bsd/kcmd.c index 28944b6a1..35ecde534 100644 --- a/src/appl/bsd/kcmd.c +++ b/src/appl/bsd/kcmd.c @@ -109,11 +109,12 @@ kcmd(sock, ahost, rport, locuser, remuser, cmd, fd2p, service, realm, krb5_auth_context auth_context = NULL; char *cksumbuf; krb5_data cksumdat; - if ((cksumbuf = malloc(strlen(cmd)+strlen(remuser))) == 0 ) { + if ((cksumbuf = malloc(strlen(cmd)+strlen(remuser)+64)) == 0 ) { fprintf(stderr, "Unable to allocate memory for checksum buffer.\n"); return(-1); } - strcpy(cksumbuf, cmd); +sprintf(cksumbuf, "%u:", ntohs(rport)); + strcat(cksumbuf, cmd); strcat(cksumbuf, remuser); cksumdat.data = cksumbuf; cksumdat.length = strlen(cksumbuf); diff --git a/src/appl/bsd/krlogind.c b/src/appl/bsd/krlogind.c index 33867b180..7b3848ead 100644 --- a/src/appl/bsd/krlogind.c +++ b/src/appl/bsd/krlogind.c @@ -50,20 +50,15 @@ char copyright[] = * 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 and -K means check .k5login (using krb5_kuserok). - * -r and -R means check .rhosts (using ruserok). + * -k means trust krb4 or krb5 +* -5 means trust krb5 +* -4 means trust krb4 + * -r means trust .rhosts (using ruserok). * -p and -P means prompt for password. - * The difference between upper and lower case is as follows: - * If lower case -r or -k, then as long as one of krb5_kuserok or - * ruserok passes, allow login without password. If the -p option is - * passed with -r or -k, then if both checks fail, allow login but - * only after password verification. - * If uppercase -R or -K, then those checks must be passed, - * regardless of other checks, else no login with or without password. * If the -P option is passed, then the password is verified in * addition to all other checks. If -p is not passed with -k or -r, * and both checks fail, then login permission is denied. - * -x and -e means use encryption. + * - -e means use encryption. * * If no command-line arguments are present, then the presence of the * letters kKrRexpP in the program-name before "logind" determine the @@ -246,9 +241,9 @@ krb5_context bsd_context; krb5_keytab keytab = NULL; -#define ARGSTR "rRkKeExXpPD:S:M:L:?" +#define ARGSTR "rk54cepPD:S:M:L:?" #else /* !KERBEROS */ -#define ARGSTR "rRpPD:?" +#define ARGSTR "rpPD:?" #define (*des_read) read #define (*des_write) write #endif /* KERBEROS */ @@ -298,8 +293,20 @@ void fatal(), fatalperror(), doit(), usage(), do_krb_login(); int princ_maps_to_lname(), default_realm(); krb5_sigtype cleanup(); -int must_pass_rhosts = 0, must_pass_k5 = 0, must_pass_one = 0; +/* 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) +#define AUTH_RHOSTS (0x4) +int auth_ok = 0, auth_sent = 0; int do_encrypt = 0, passwd_if_fail = 0, passwd_req = 0; +int checksum_required = 0; main(argc, argv) int argc; @@ -313,6 +320,7 @@ main(argc, argv) int debug_port = 0; int fd; #ifdef KERBEROS +int valid_checksum; krb5_error_code status; #endif @@ -371,22 +379,28 @@ pty_init(); while ((ch = getopt(argc, argv, ARGSTR)) != EOF) switch (ch) { case 'r': - must_pass_one = 1; /* If just 'r', any one check must succeed */ - break; - case 'R': /* If 'R', must pass .rhosts check*/ - must_pass_rhosts = 1; - if (must_pass_one) - must_pass_one = 0; + auth_ok |= AUTH_RHOSTS; break; #ifdef KERBEROS case 'k': - must_pass_one = 1; /* If just 'k', any one check must succeed */ - break; - case 'K': /* If 'K', must pass .k5login check*/ - must_pass_k5 = 1; - if (must_pass_one) - must_pass_one = 0; - break; +#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; + break; +#ifdef KRB5_KRB4_COMPAT + case '4': + auth_ok |= AUTH_KRB4; + break; +#endif #ifdef CRYPT case 'x': /* Use encryption. */ case 'X': @@ -471,7 +485,7 @@ pty_init(); #ifdef STDERR_FILENO fatal(STDERR_FILENO, "Can't get peer name of remote host", 1); #else - fatal(3, "Can't get peer name of remote host", 1); + fatal(2, "Can't get peer name of remote host", 1); #endif } fd = 0; @@ -480,6 +494,10 @@ pty_init(); if (setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, (const char *) &on, sizeof (on)) < 0) syslog(LOG_WARNING, "setsockopt (SO_KEEPALIVE): %m"); + if (auth_ok == 0) { + syslog(LOG_CRIT, "No authentication systems were enabled; all connections will be refused."); + fatal(fd, "All authentication systems disabled; connection refused."); + } doit(fd, &from); } @@ -552,13 +570,13 @@ int syncpipe[2]; fatal(f, "Permission denied - Malformed from address\n"); #ifdef KERBEROS - if (must_pass_k5 || must_pass_one) { + /* setup des buffers */ - desinbuf.data = des_inbuf; - desoutbuf.data = des_outbuf; /* Set up des buffers */ - } + desinbuf.data = des_inbuf; + desoutbuf.data = des_outbuf; /* Set up des buffers */ + /* Must come from privileged port when .rhosts is being looked into */ - if ((must_pass_rhosts || must_pass_one) + if ((auth_ok&AUTH_RHOSTS) && (fromp->sin_port >= IPPORT_RESERVED || fromp->sin_port < IPPORT_RESERVED/2)) non_privileged = 1; @@ -1043,10 +1061,10 @@ do_krb_login(host) { krb5_error_code status; struct passwd *pwd; - int passed_krb, passed_rhosts; char *msg_fail; +int valid_checksum; + - passed_krb = passed_rhosts = 0; if (getuid()) { exit(1); @@ -1054,7 +1072,7 @@ do_krb_login(host) /* Check authentication. This can be either Kerberos V5, */ /* Kerberos V4, or host-based. */ - if (status = recvauth()) { + if (status = recvauth(&valid_checksum)) { if (ticket) krb5_free_ticket(bsd_context, ticket); if (status != 255) @@ -1074,50 +1092,55 @@ do_krb_login(host) } #endif - if (must_pass_k5 || must_pass_one) { + #if (defined(ALWAYS_V5_KUSEROK) || !defined(KRB5_KRB4_COMPAT)) /* krb5_kuserok returns 1 if OK */ if (client && krb5_kuserok(bsd_context, client, lusername)) - passed_krb++; + auth_sent |= ((auth_sys == KRB5_RECVAUTH_V4)?AUTH_KRB4:AUTH_KRB5); #else if (auth_sys == KRB5_RECVAUTH_V4) { /* kuserok returns 0 if OK */ if (!kuserok(v4_kdata, lusername)) - passed_krb++; + auth_sent |= AUTH_KRB4; } else { /* krb5_kuserok returns 1 if OK */ if (client && krb5_kuserok(bsd_context, client, lusername)) - passed_krb++; + auth_sent |= AUTH_KRB5; } #endif - } - - /* The kerberos authenticated request must pass ruserok also - if asked for. */ + - if (!must_pass_k5 && - (must_pass_rhosts || (!passed_krb && must_pass_one))) { +/* See if we pass .rhosts.*/ + if (auth_ok&AUTH_RHOSTS) { /* Cannot check .rhosts unless connection from a privileged port. */ - if (non_privileged) - fatal(netf, "Permission denied - Connection from bad port"); - - pwd = (struct passwd *) getpwnam(lusername); - if (pwd && - !ruserok(rhost_name, pwd->pw_uid == 0, rusername, lusername)) - passed_rhosts++; + if (!non_privileged) { + pwd = (struct passwd *) getpwnam(lusername); + if (pwd && + !ruserok(rhost_name, pwd->pw_uid == 0, rusername, lusername)) + auth_sent |= AUTH_RHOSTS; + } } - if ((must_pass_k5 && passed_krb) || - (must_pass_rhosts && passed_rhosts) || - (must_pass_one && (passed_krb || passed_rhosts))) - return; + if (checksum_required) { + if ((auth_sent&AUTH_KRB5)&&(!valid_checksum)) { + syslog(LOG_WARNING, "Client did not supply required checksum."); + + fatal(netf, "You are using an old Kerberos5 without initial connection support; only newer clients are authorized."); + } + else { + syslog(LOG_WARNING, "Checksums are only required for v5 clients; other clients cannot produce initial authenticator checksums."); + } + } + if +(auth_ok&auth_sent) /* This should be bitwise.*/ + return; if (ticket) krb5_free_ticket(bsd_context, ticket); msg_fail = (char *) malloc( strlen(krusername) + strlen(lusername) + 80 ); if (!msg_fail) - fatal(netf, "User is not authorized to login to specified account"); + fatal(netf, "User is not authorized to login to specified account"); sprintf(msg_fail, "User %s is not authorized to login to account %s", krusername, lusername); fatal(netf, msg_fail); @@ -1386,10 +1409,10 @@ void usage() { #ifdef KERBEROS syslog(LOG_ERR, - "usage: klogind [-rRkKxpP] [-D port] or [r/R][k/K][x/e][p/P]logind"); + "usage: klogind [-rke45pP] [-D port] or [r/R][k/K][x/e][p/P]logind"); #else syslog(LOG_ERR, - "usage: rlogind [-rRpP] [-D port] or [r/R][p/P]logind"); + "usage: rlogind [-rpP] [-D port] or [r/R][p/P]logind"); #endif } @@ -1440,7 +1463,8 @@ int default_realm(principal) chars */ krb5_error_code -recvauth() +recvauth(valid_checksum) +int *valid_checksum; { krb5_auth_context auth_context = NULL; krb5_error_code status; @@ -1451,7 +1475,8 @@ recvauth() krb5_data inbuf; char v4_instance[INST_SZ]; /* V4 Instance */ char v4_version[9]; - + krb5_authenticator *authenticator; +*valid_checksum = 0; len = sizeof(laddr); if (getsockname(netf, (struct sockaddr *)&laddr, &len)) { exit(1); @@ -1510,6 +1535,41 @@ recvauth() getstr(netf, lusername, sizeof (lusername), "locuser"); getstr(netf, term, sizeof(term), "Terminal type"); + if (status = krb5_auth_con_getauthenticator(bsd_context, auth_context, &authenticator)) + return status; + + if (authenticator->checksum) { + struct sockaddr_in adr; + int adr_length = sizeof(adr); + char * chksumbuf = (char *) malloc(strlen(term)+strlen(lusername)+32); + if (getsockname(netf, (struct sockaddr *) &adr, &adr_length) != 0) + return errno; + if (chksumbuf == 0) + goto error_cleanup; + + sprintf(chksumbuf,"%u:", ntohs(adr.sin_port)); + strcat(chksumbuf,term); + strcat(chksumbuf,lusername); + + if ( status = krb5_verify_checksum(bsd_context, + authenticator->checksum->checksum_type, + authenticator->checksum, + chksumbuf, strlen(chksumbuf), + ticket->enc_part2->session->contents, + ticket->enc_part2->session->length)) + goto error_cleanup; + + error_cleanup: +krb5_xfree(chksumbuf); + if (status) { + krb5_free_authenticator(bsd_context, authenticator); + return status; + } + *valid_checksum = 1; +} + krb5_free_authenticator(bsd_context, authenticator); + + #ifdef KRB5_KRB4_COMPAT if (auth_sys == KRB5_RECVAUTH_V4) { diff --git a/src/appl/bsd/krshd.c b/src/appl/bsd/krshd.c index 77d5fa452..f5f324ee0 100644 --- a/src/appl/bsd/krshd.c +++ b/src/appl/bsd/krshd.c @@ -48,14 +48,10 @@ char copyright[] = * 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 and -K means check .k5login (using krb5_kuserok). - * -r and -R means check .rhosts (using ruserok). - * The difference between upper and lower case is as follows: - * If lower case -r or -k, then as long as one of krb5_kuserok or ruserok - * passes, allow access. If both fail, no access. The program does not fall - * back on password verification. - * If uppercase -R or -K, then those checks must be passed, regardless of - * other checks, else no access. + * -k means trust krb4 or krb5 +* -5 means trust krb5 +* -4 means trust krb4 + * -r means trust .rhosts (using ruserok). * * If no command-line arguments are present, then the presence of the * letters kKrR in the program-name before "shd" determine the @@ -159,7 +155,7 @@ char copyright[] = #include "com_err.h" #include "loginpaths.h" -#define ARGSTR "rRxXeEkKD:S:M:AP:?" +#define ARGSTR "rek54cD:S:M:AP:?" #define SECURE_MESSAGE "This rsh session is using DES encryption for all data transmissions.\r\n" @@ -181,7 +177,7 @@ int v5_des_write(); int (*des_read)() = v5_des_read; int (*des_write)() = v5_des_write; - +int require_encrypt = 0; int do_encrypt = 0; int anyport = 0; char *kprogdir = KPROGDIR; @@ -199,8 +195,19 @@ int netf; #define killpg(pid, sig) kill(-(pid), (sig)) #endif -int must_pass_rhosts = 0, must_pass_k5 = 0, must_pass_one = 0; -int failed_k5 = 0; +/* 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) +#define AUTH_RHOSTS (0x4) +int auth_ok = 0, auth_sent = 0; +int checksum_required = 0; char *progname; #define MAX_PROG_NAME 10 @@ -299,28 +306,31 @@ main(argc, argv) while ((ch = getopt(argc, argv, ARGSTR)) != EOF) switch (ch) { case 'r': - must_pass_one = 1; /* If just 'r', any one check must succeed */ - break; - case 'R': /* If 'R', must pass .rhosts check*/ - must_pass_rhosts = 1; - if (must_pass_one) - must_pass_one = 0; + auth_ok |= AUTH_RHOSTS; break; #ifdef KERBEROS case 'k': - must_pass_one = 1; /* If just 'k', any one check must succeed */ - break; - case 'K': /* If 'K', must pass .k5login check*/ - must_pass_k5 = 1; - if (must_pass_one) - must_pass_one = 0; - break; +#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; + break; +#ifdef KRB5_KRB4_COMPAT + case '4': + auth_ok |= AUTH_KRB4; + break; +#endif - case 'x': - case 'X': case 'e': - case 'E': - do_encrypt = 1; + require_encrypt = 1; break; case 'S': @@ -497,6 +507,7 @@ doit(f, fromp) krb5_error_code status; #endif +int valid_checksum; int tmpint; int ioctlval, cnt; @@ -587,8 +598,7 @@ doit(f, fromp) netf = f; desinbuf.data = des_inbuf; desoutbuf.data = des_outbuf; - if ((must_pass_rhosts || must_pass_one) - && (fromp->sin_port >= IPPORT_RESERVED || + if ( (fromp->sin_port >= IPPORT_RESERVED || fromp->sin_port < IPPORT_RESERVED/2)) non_privileged = 1; #else @@ -663,8 +673,7 @@ doit(f, fromp) exit(1); } #ifdef KERBEROS - if ((must_pass_rhosts || must_pass_one) - && port >= IPPORT_RESERVED) + if ( port >= IPPORT_RESERVED) non_privileged = 1; #else if (port >= IPPORT_RESERVED) { @@ -694,7 +703,7 @@ doit(f, fromp) } #ifdef KERBEROS - if (status = recvauth(f, fromaddr)) { + if (status = recvauth(f, fromaddr,&valid_checksum)) { error("Authentication failed: %s\n", error_message(status)); exit(1); } @@ -726,7 +735,7 @@ doit(f, fromp) if (pwd == (struct passwd *) 0 ) { syslog(LOG_ERR , "Principal %s (%s@%s) for local user %s has no account.\n", - kremuser, remuser, hostname, locuser); + kremuser, remuser, hostname, locuser); /* xxx sprintf buffer in syslog*/ error("Login incorrect.\n"); exit(1); } @@ -972,7 +981,7 @@ doit(f, fromp) } #ifdef KERBEROS - if (must_pass_k5 || must_pass_one) { + #if defined(KRB5_KRB4_COMPAT) && !defined(ALWAYS_V5_KUSEROK) if (auth_sys == KRB5_RECVAUTH_V4) { /* kuserok returns 0 if OK */ @@ -980,45 +989,35 @@ doit(f, fromp) syslog(LOG_ERR , "Principal %s (%s@%s) for local user %s failed kuserok.\n", kremuser, remuser, hostname, locuser); - if (must_pass_k5) { - error("Permission denied.\n"); - goto signout_please; } - failed_k5 = 1; - } - } else + 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) for local user %s failed krb5_kuserok.\n", kremuser, remuser, hostname, locuser); - if (must_pass_k5) { - error("Permission denied.\n"); - goto signout_please; - } - failed_k5 = 1; } +else auth_sent |= AUTH_KRB5; } - } + - if (must_pass_rhosts || (failed_k5 && must_pass_one)) { + if (auth_ok&AUTH_RHOSTS) { /* Cannot check .rhosts unless connection from privileged port */ - if (non_privileged) { - syslog(LOG_ERR , "connection from bad port\n"); - exit(1); - } - - if (ruserok(hostname, pwd->pw_uid == 0, + if (!non_privileged) { + if (ruserok(hostname, pwd->pw_uid == 0, remuser, locuser) < 0) { syslog(LOG_ERR , "Principal %s (%s@%s) for local user %s failed ruserok.\n", kremuser, remuser, hostname, locuser); - error("Permission denied.\n"); - goto signout_please; + + } - } + else auth_sent |=AUTH_RHOSTS; + } +} #else if (pwd->pw_passwd != 0 && *pwd->pw_passwd != '\0' && ruserok(hostname, pwd->pw_uid == 0, remuser, locuser) < 0) { @@ -1026,6 +1025,27 @@ doit(f, fromp) goto signout_please; } #endif /* KERBEROS */ + + +if (checksum_required) { + if ((auth_sent&AUTH_KRB5)&&(!valid_checksum)) { + syslog(LOG_WARNING, "Client did not supply required checksum."); + + error( "You are using an old Kerberos5 without initial connection support; only newer clients are authorized."); +goto signout_please; + } +else { + syslog(LOG_WARNING, "Checksums are only required for v5 clients; other clients cannot produce initial authenticator checksums."); + } + } +if (require_encrypt&&(!do_encrypt)) { + error("You must use encryption."); + goto signout_please; +} + if (!(auth_ok&auth_sent)) { + error("Permission denied."); + goto signout_please; + } if (pwd->pw_uid && !access("/etc/nologin", F_OK)) { error("Logins currently disabled.\n"); @@ -1598,9 +1618,10 @@ int default_realm(principal) chars */ krb5_error_code -recvauth(netf, peersin) +recvauth(netf, peersin, valid_checksum) int netf; struct sockaddr_in peersin; +int *valid_checksum; { krb5_auth_context auth_context = NULL; krb5_error_code status; @@ -1614,6 +1635,7 @@ recvauth(netf, peersin) krb5_authenticator *authenticator; krb5_ticket *ticket; + *valid_checksum = 0; len = sizeof(laddr); if (getsockname(netf, (struct sockaddr *)&laddr, &len)) { exit(1); @@ -1704,11 +1726,16 @@ krb5_authenticator *authenticator; return status; if (authenticator->checksum) { - char * chksumbuf = (char *) malloc(strlen(cmdbuf)+strlen(remuser)+1); + struct sockaddr_in adr; + int adr_length = sizeof(adr); + char * chksumbuf = (char *) malloc(strlen(cmdbuf)+strlen(locuser)+32); + if (getsockname(netf, (struct sockaddr *) &adr, &adr_length) != 0) + return errno; if (chksumbuf == 0) goto error_cleanup; - strcpy(chksumbuf,cmdbuf); + sprintf(chksumbuf,"%u:", ntohs(adr.sin_port)); + strcat(chksumbuf,cmdbuf); strcat(chksumbuf,locuser); if ( status = krb5_verify_checksum(bsd_context, @@ -1725,6 +1752,7 @@ krb5_xfree(chksumbuf); krb5_free_authenticator(bsd_context, authenticator); return status; } + *valid_checksum = 1; } krb5_free_authenticator(bsd_context, authenticator);