Check retrieved TGT against local keytab, if it exists.
This commit is contained in:
parent
0bc8e23c3a
commit
b84b9c883a
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: k5login.c,v 1.14 2000/08/09 17:44:18 thorpej Exp $ */
|
||||
/* $NetBSD: k5login.c,v 1.15 2000/09/01 03:12:20 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.14 2000/08/09 17:44:18 thorpej Exp $");
|
||||
__RCSID("$NetBSD: k5login.c,v 1.15 2000/09/01 03:12:20 aidan Exp $");
|
||||
#endif /* not lint */
|
||||
|
||||
#ifdef KERBEROS5
|
||||
|
@ -52,6 +69,7 @@ __RCSID("$NetBSD: k5login.c,v 1.14 2000/08/09 17:44:18 thorpej Exp $");
|
|||
#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 @@ static krb5_principal me, server;
|
|||
|
||||
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));
|
||||
|
||||
|
@ -82,6 +101,125 @@ void k5destroy __P((void));
|
|||
#define krb5_realm_data(r) ((r).data)
|
||||
#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
|
||||
*
|
||||
|
@ -313,6 +451,10 @@ k5login(pw, instance, localhost, password)
|
|||
|
||||
return(1);
|
||||
}
|
||||
if (k5_verify_creds(kcontext, ccache) < 0) {
|
||||
return(1);
|
||||
}
|
||||
|
||||
|
||||
/* Success */
|
||||
notickets = 0;
|
||||
|
|
Loading…
Reference in New Issue