Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/netbsd-1-5]: src/usr.bin/login Pull up revision 1.15 (requested by aidan):
details: https://anonhg.NetBSD.org/src/rev/62709597080c
branches: netbsd-1-5
changeset: 489435:62709597080c
user: aidan <aidan%NetBSD.org@localhost>
date: Mon Sep 11 23:50:13 2000 +0000
description:
Pull up revision 1.15 (requested by aidan):
Make login check the returned TGT against the local keytab, when using krb5
for authentication. This closes a potential man-in-the-middle attack, where
an intruder can forge a response to login's AS-request, and gain access to
the host.
diffstat:
usr.bin/login/k5login.c | 146 +++++++++++++++++++++++++++++++++++++++++++++++-
1 files changed, 144 insertions(+), 2 deletions(-)
diffs (193 lines):
diff -r 499e0ae59fe4 -r 62709597080c usr.bin/login/k5login.c
--- a/usr.bin/login/k5login.c Mon Sep 11 22:13:12 2000 +0000
+++ b/usr.bin/login/k5login.c Mon Sep 11 23:50:13 2000 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: k5login.c,v 1.12.2.2 2000/08/09 17:49:40 thorpej Exp $ */
+/* $NetBSD: k5login.c,v 1.12.2.3 2000/09/11 23:50:13 aidan Exp $ */
/*-
* Copyright (c) 1990 The Regents of the University of California.
@@ -33,12 +33,29 @@
* SUCH DAMAGE.
*/
+/*
+ * Copyright (c) 1980, 1987, 1988 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are permitted
+ * provided that the above copyright notice and this paragraph are
+ * duplicated in all such forms and that any documentation,
+ * advertising materials, and other materials related to such
+ * distribution and use acknowledge that the software was developed
+ * by the University of California, Berkeley. The name of the
+ * University may not be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
#include <sys/cdefs.h>
#ifndef lint
#if 0
static char sccsid[] = "@(#)klogin.c 5.11 (Berkeley) 7/12/92";
#endif
-__RCSID("$NetBSD: k5login.c,v 1.12.2.2 2000/08/09 17:49:40 thorpej Exp $");
+__RCSID("$NetBSD: k5login.c,v 1.12.2.3 2000/09/11 23:50:13 aidan Exp $");
#endif /* not lint */
#ifdef KERBEROS5
@@ -52,6 +69,7 @@
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
+#include <errno.h>
#define KRB5_DEFAULT_OPTIONS 0
#define KRB5_DEFAULT_LIFE 60*60*10 /* 10 hours */
@@ -72,6 +90,7 @@
int k5_read_creds __P((char *));
int k5_write_creds __P((void));
+int k5_verify_creds __P((krb5_context, krb5_ccache));
int k5login __P((struct passwd *, char *, char *, char *));
void k5destroy __P((void));
@@ -83,6 +102,125 @@
#endif
/*
+ * Verify the Kerberos ticket-granting ticket just retrieved for the
+ * user. If the Kerberos server doesn't respond, assume the user is
+ * trying to fake us out (since we DID just get a TGT from what is
+ * supposedly our KDC). If the host/<host> service is unknown (i.e.,
+ * the local keytab doesn't have it), let her in.
+ *
+ * Returns 1 for confirmation, -1 for failure, 0 for uncertainty.
+ */
+int
+k5_verify_creds(c, ccache)
+ krb5_context c;
+ krb5_ccache ccache;
+{
+ char phost[MAXHOSTNAMELEN];
+ int retval, have_keys;
+ krb5_principal princ;
+ krb5_keyblock *kb = 0;
+ krb5_error_code kerror;
+ krb5_data packet;
+ krb5_auth_context auth_context = NULL;
+ krb5_ticket *ticket = NULL;
+
+ kerror = krb5_sname_to_principal(c, 0, 0, KRB5_NT_SRV_HST, &princ);
+ if (kerror) {
+ com_err("login", kerror, "constructing local service name");
+ return (-1);
+ }
+
+ /* Do we have host/<host> keys? */
+ /* (use default keytab, kvno IGNORE_VNO to get the first match,
+ * and default enctype.) */
+ kerror = krb5_kt_read_service_key(c, NULL, princ, 0, 0, &kb);
+ if (kb)
+ krb5_free_keyblock(c, kb);
+ /* any failure means we don't have keys at all. */
+ have_keys = kerror ? 0 : 1;
+
+ /* XXX there should be a krb5 function like mk_req, but taking a full
+ * principal, instead of a service/hostname. (Did I miss one?) */
+ gethostname(phost, sizeof(phost));
+ phost[sizeof(phost) - 1] = '\0';
+
+ /* talk to the kdc and construct the ticket */
+ kerror = krb5_mk_req(c, &auth_context, 0, "host", phost,
+ 0, ccache, &packet);
+ /* wipe the auth context for rd_req */
+ if (auth_context) {
+ krb5_auth_con_free(c, auth_context);
+ auth_context = NULL;
+ }
+ if (kerror == KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN) {
+ /* we have a service key, so something should be
+ * in the database, therefore this error packet could
+ * have come from an attacker. */
+ if (have_keys) {
+ retval = -1;
+ goto EGRESS;
+ }
+ /* but if it is unknown and we've got no key, we don't
+ * have any security anyhow, so it is ok. */
+ else {
+ retval = 0;
+ goto EGRESS;
+ }
+ }
+ else if (kerror) {
+ com_err("login", kerror,
+ "Unable to verify Kerberos V5 TGT: %s", phost);
+ syslog(LOG_NOTICE|LOG_AUTH, "Kerberos V5 TGT bad: %s",
+ error_message(kerror));
+ retval = -1;
+ goto EGRESS;
+ }
+ /* got ticket, try to use it */
+ kerror = krb5_rd_req(c, &auth_context, &packet,
+ princ, NULL, NULL, &ticket);
+ if (kerror) {
+ if (!have_keys) {
+ /* The krb5 errors aren't specified well, but I think
+ * these values cover the cases we expect. */
+ switch (kerror) {
+ case ENOENT: /* no keytab */
+ case KRB5_KT_NOTFOUND:
+ retval = 0;
+ break;
+ default:
+ /* unexpected error: fail */
+ retval = -1;
+ break;
+ }
+ }
+ else {
+ /* we have keys, so if we got any error, we could be
+ * under attack. */
+ retval = -1;
+ }
+ com_err("login", kerror, "Unable to verify host ticket");
+ syslog(LOG_NOTICE|LOG_AUTH, "can't verify v5 ticket: %s; %s\n",
+ error_message(kerror),
+ retval
+ ? "keytab found, assuming failure"
+ : "no keytab found, assuming success");
+ goto EGRESS;
+ }
+ /*
+ * The host/<host> ticket has been received _and_ verified.
+ */
+ retval = 1;
+
+ /* do cleanup and return */
+EGRESS:
+ if (auth_context)
+ krb5_auth_con_free(c, auth_context);
+ krb5_free_principal(c, princ);
+ /* possibly ticket and packet need freeing here as well */
+ return (retval);
+}
+
+/*
* Attempt to read forwarded kerberos creds
*
* return 0 on success (forwarded creds in memory)
@@ -313,6 +451,10 @@
return(1);
}
+ if (k5_verify_creds(kcontext, ccache) < 0) {
+ return(1);
+ }
+
/* Success */
notickets = 0;
Home |
Main Index |
Thread Index |
Old Index