From 2cd78ca21e3a4171d8b53d4565ed0a2852d8b747 Mon Sep 17 00:00:00 2001 From: Sam Hartman Date: Tue, 27 Aug 2002 17:50:07 +0000 Subject: [PATCH] Add support for using the encrypted part of a krb5 ticket as an AFS token-- af krb5-encpart-only (kvno 213) and enable this support by default. git-svn-id: svn://anonsvn.mit.edu/krb5/trunk@14777 dc483132-0cff-0310-8789-dd5450dbe970 --- src/krb524/ChangeLog | 21 ++++ src/krb524/README | 33 +++++++ src/krb524/krb524d.c | 229 ++++++++++++++++++++++++++++++++----------- 3 files changed, 227 insertions(+), 56 deletions(-) diff --git a/src/krb524/ChangeLog b/src/krb524/ChangeLog index 9c299aa37..d78c76c96 100644 --- a/src/krb524/ChangeLog +++ b/src/krb524/ChangeLog @@ -3,6 +3,27 @@ * Makefile.in ($(KRB524_HDR), $(KRB524_ERR_HDR)): Quote target of copy on Windows. +2002-08-27 Sam Hartman + + * README: Document new afs_krb5 configuration information + + * krb524d.c (afs_return_v4): New function to determine if we have + been configured to return v4 tickets for afs or use the afs + krb5-encpart proposal + (do_connection): Call afs_return_v4 and use its result + + 2002-08-26 Sam Hartman + + * RELEASE_NOTES: Delete OV release notes now with 100% incorrect + content + +2002-08-22 Sam Hartman + + * krb524d.c (do_connection): Add support for AFS + krb5-encpart-only per discussion with jhutz and lha + (handle_classic_v4): Split out code for handling v4 tickets since + it needs to be called multiple times + 2002-08-23 Ken Raeburn * Makefile.in: Change $(S)=>/ and $(U)=>.. globally. diff --git a/src/krb524/README b/src/krb524/README index 1531de0d9..dd7ca9c23 100644 --- a/src/krb524/README +++ b/src/krb524/README @@ -48,6 +48,16 @@ information in the V5 credential and {C,S}_4. Steps (2) through (4) are encapsulated in a single function call in the krb524 library. +An alternate conversion is provided for AFS servers that support the +encrypted part of a krb5 ticket as an AFS token. If the krb524d is +converting a principal whose first component is afs and if the +encrypted part of the ticket fits in 344 bytes, then it will default +to simply returning the encrypted part of the ticket as a token. If +it turns out that the AFS server does not support the ticket, then +users will get an unknown key version error and the krb524d must be +configured to use v4 tickets for this AFS service. + + Obviously, not all V5 credentials can be completely converted to V4 credentials, since the former is a superset of the latter. The precise semantics of the conversion function are still undecided. @@ -82,6 +92,29 @@ default principal's realm if not specified. The -n argument causes the new ticket to be added to the existing ticket file; otherwise, the ticket file is initialized. +Configuring krb524d AFS Conversion +====================================================================== + +The krb524d looks in the appdefaults section of krb5.conf for an +application called afs_krb5 to determine whether afs principals +support encrypted ticket parts as tokens. The following configuration +fragment says that afs/sipb.mit.edu@ATHENA.MIT.EDU supports the new +token format but afs@ATHENA.MIT.EDU and +afs/athena.mit.edu@ATHENA.MIT.EDU do not. Note that the default is to +assume afs servers support the new format. + +[appdefaults] +afs_krb5 = { + ATHENA.MIT.EDU = { + # This stanza describes principals in the + #ATHENA.MIT.EDU realm + afs = false + afs/athena.mit.edu = false + afs/sipb.mit.edu = true + } +} + + Using libkrb524.a ====================================================================== diff --git a/src/krb524/krb524d.c b/src/krb524/krb524d.c index ad7c43978..4995b515f 100644 --- a/src/krb524/krb524d.c +++ b/src/krb524/krb524d.c @@ -1,4 +1,25 @@ /* + * Copyright (C) 2002 by the Massachusetts Institute of Technology. + * All rights reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. * Copyright 1994 by OpenVision Technologies, Inc. * * Permission to use, copy, modify, distribute, and sell this software @@ -26,6 +47,7 @@ #include #include +#include #include #ifdef HAVE_SYS_SELECT_H #include @@ -68,6 +90,13 @@ krb5_error_code kdc_get_server_key(krb5_context, krb5_principal, krb5_keyblock *, krb5_kvno *, krb5_enctype, krb5_kvno); +static krb5_error_code +handle_classic_v4 (krb5_context context, krb5_ticket *v5tkt, + struct sockaddr_in *saddr, + krb5_data *tktdata, krb5_kvno *v4kvno); +static krb5_error_code +afs_return_v4(krb5_context, const krb5_principal , int *use_v5); + static void usage(context) krb5_context context; { @@ -276,20 +305,16 @@ krb5_error_code do_connection(s, context) { struct sockaddr saddr; krb5_ticket *v5tkt = 0; - KTEXT_ST v4tkt; - krb5_keyblock v5_service_key, v4_service_key; krb5_data msgdata, tktdata; char msgbuf[MSGSIZE], tktbuf[TKT_BUFSIZ], *p; int ret, saddrlen; krb5_int32 n; /* Must be 4 bytes */ krb5_kvno v4kvno; - /* Clear out keyblock contents so we don't accidentally free the stack.*/ - v5_service_key.contents = v4_service_key.contents = 0; - msgdata.data = msgbuf; msgdata.length = MSGSIZE; - + tktdata.data = tktbuf; + tktdata.length = TKT_BUFSIZ; saddrlen = sizeof(struct sockaddr); ret = recvfrom(s, msgdata.data, (int) msgdata.length, 0, &saddr, &saddrlen); if (ret < 0) { @@ -321,51 +346,41 @@ krb5_error_code do_connection(s, context) if (debug) printf("V5 ticket decoded\n"); - if ((ret = lookup_service_key(context, v5tkt->server, - v5tkt->enc_part.enctype, - v5tkt->enc_part.kvno, - &v5_service_key, NULL))) - goto error; - - if ((ret = lookup_service_key(context, v5tkt->server, - ENCTYPE_DES3_CBC_RAW, - 0, /* highest kvno */ - &v4_service_key, &v4kvno)) && - (ret = lookup_service_key(context, v5tkt->server, - ENCTYPE_LOCAL_DES3_HMAC_SHA1, - 0, - &v4_service_key, &v4kvno)) && - (ret = lookup_service_key(context, v5tkt->server, - ENCTYPE_DES3_CBC_SHA1, - 0, - &v4_service_key, &v4kvno)) && - (ret = lookup_service_key(context, v5tkt->server, - ENCTYPE_DES_CBC_CRC, - 0, - &v4_service_key, &v4kvno))) - goto error; - - if (debug) - printf("service key retrieved\n"); - - ret = krb524_convert_tkt_skey(context, v5tkt, &v4tkt, &v5_service_key, - &v4_service_key, - (struct sockaddr_in *)&saddr); - if (ret) - goto error; - - if (debug) - printf("credentials converted\n"); - - tktdata.data = tktbuf; - tktdata.length = TKT_BUFSIZ; - ret = encode_v4tkt(&v4tkt, tktdata.data, &tktdata.length); - if (ret) - goto error; - if (debug) - printf("v4 credentials encoded\n"); - -error: + if( v5tkt->server->length >= 1 + &&krb5_princ_component(context, v5tkt->server, 0)->length == 3 + &&strncmp(krb5_princ_component(context, v5tkt->server, 0)->data, + "afs", 3) == 0) { + krb5_data *enc_part; + int use_v5; + if ((ret = afs_return_v4(context, v5tkt->server, + &use_v5)) != 0) + goto error; + if ((ret = encode_krb5_enc_data( &v5tkt->enc_part, &enc_part)) != 0) + goto error; + if (!(use_v5 )|| enc_part->length >= 344) { + krb5_free_data(context, enc_part); + if ((ret = handle_classic_v4(context, v5tkt, + (struct sockaddr_in *) &saddr, &tktdata, + &v4kvno)) != 0) + goto error; + } else { + KTEXT_ST fake_v4tkt; + fake_v4tkt.mbz = 0; + fake_v4tkt.length = enc_part->length; + memcpy(fake_v4tkt.dat, enc_part->data, enc_part->length); + v4kvno = (0x100-0x2b); /*protocol constant indicating v5 + * enc part only*/ + krb5_free_data(context, enc_part); + ret = encode_v4tkt(&fake_v4tkt, tktdata.data, &tktdata.length); + } + } else { + if ((ret = handle_classic_v4(context, v5tkt, + (struct sockaddr_in *) &saddr, &tktdata, + &v4kvno)) != 0) + goto error; + } + + error: /* create the reply */ p = msgdata.data; msgdata.length = 0; @@ -395,11 +410,6 @@ write_msg: ret = errno; if (debug) printf("reply written\n"); - /* If we have keys to clean up, do so.*/ - if (v5_service_key.contents) - krb5_free_keyblock_contents(context, &v5_service_key); - if (v4_service_key.contents) - krb5_free_keyblock_contents(context, &v4_service_key); if (v5tkt) krb5_free_ticket(context, v5tkt); @@ -488,3 +498,110 @@ krb5_error_code kdc_get_server_key(context, service, key, kvnop, ktype, kvno) kadm5_free_principal_ent(handle, &server); return ret; } + +/* + * We support two kinds of v4 credentials. There are real v4 + * credentials, and a Kerberos v5 enc part masquerading as a krb4 + * credential to be used by modern AFS implementations; this function + * handles the classic v4 case. + */ + +static krb5_error_code +handle_classic_v4 (krb5_context context, krb5_ticket *v5tkt, + struct sockaddr_in *saddr, + krb5_data *tktdata, krb5_kvno *v4kvno) +{ + krb5_error_code ret; + krb5_keyblock v5_service_key, v4_service_key; + KTEXT_ST v4tkt; + + v5_service_key.contents = NULL; + v4_service_key.contents = NULL; + + if ((ret = lookup_service_key(context, v5tkt->server, + v5tkt->enc_part.enctype, + v5tkt->enc_part.kvno, + &v5_service_key, NULL))) + goto error; + + if ((ret = lookup_service_key(context, v5tkt->server, + ENCTYPE_DES3_CBC_RAW, + 0, /* highest kvno */ + &v4_service_key, v4kvno)) && + (ret = lookup_service_key(context, v5tkt->server, + ENCTYPE_LOCAL_DES3_HMAC_SHA1, + 0, + &v4_service_key, v4kvno)) && + (ret = lookup_service_key(context, v5tkt->server, + ENCTYPE_DES3_CBC_SHA1, + 0, + &v4_service_key, v4kvno)) && + (ret = lookup_service_key(context, v5tkt->server, + ENCTYPE_DES_CBC_CRC, + 0, + &v4_service_key, v4kvno))) + goto error; + + if (debug) + printf("service key retrieved\n"); + + ret = krb524_convert_tkt_skey(context, v5tkt, &v4tkt, &v5_service_key, + &v4_service_key, + (struct sockaddr_in *)saddr); + if (ret) + goto error; + + if (debug) + printf("credentials converted\n"); + + ret = encode_v4tkt(&v4tkt, tktdata->data, &tktdata->length); + if (ret) + goto error; + if (debug) + printf("v4 credentials encoded\n"); + + error: + if(v5_service_key.contents) + krb5_free_keyblock_contents(context, &v5_service_key); + if (v4_service_key.contents) + krb5_free_keyblock_contents(context, &v4_service_key); + return ret; +} + +/* + * afs_return_v4: a predicate to determine whether we want to try + * using the afs krb5 encrypted part encoding or whether we just + * return krb4. Takes a principal, and checks the configuration file. + */ +static krb5_error_code +afs_return_v4 (krb5_context context, const krb5_principal princ, + int *use_v5) +{ + krb5_error_code ret; + char *unparsed_name; + char *cp; + krb5_data realm; + assert(use_v5 != NULL); + ret = krb5_unparse_name(context, princ, &unparsed_name); + if (ret != 0) + return ret; +/* Trim out trailing realm component into separate string.*/ + for (cp = unparsed_name; *cp != '\0'; cp++) { + if (*cp == '\\') { + cp++; /* We trust unparse_name not to leave a singleton + * backslash*/ + continue; + } + if (*cp == '@') { + *cp = '\0'; + realm.data = cp+1; + realm.length = strlen((char *) realm.data); + break; + } + } + krb5_appdefault_boolean(context, "afs_krb5", + &realm, unparsed_name, 1, + use_v5); + krb5_free_unparsed_name(context, unparsed_name); + return ret; +} -- 2.26.2