diff -u openafs-1.4.12+dfsg/debian/changelog openafs-1.4.12+dfsg/debian/changelog --- openafs-1.4.12+dfsg/debian/changelog +++ openafs-1.4.12+dfsg/debian/changelog @@ -1,3 +1,66 @@ +openafs (1.4.12+dfsg-3+ubuntu0.3) lucid-security; urgency=high + + * SECURITY UPDATE: Brute force DES attack permits compromise of AFS cell. + vos -encrypt doesn't encrypt connection data. + Buffer overflows which could cause a serverside denial of service. + - Files changed: + src/aklog/aklog_main.c + src/aklog/klog.c + src/auth/akimpersonate.c + src/auth/akimpersonate.h + src/auth/akimpersonate_v5gen.c + src/auth/akimpersonate_v5gen.h + src/auth/authcon.c + src/auth/Makefile.in + src/bozo/bosserver.c + src/bozo/Makefile.in + src/bucoord/Makefile.in + src/budb/Makefile.in + src/budb/server.c + src/butc/Makefile.in + src/cf/kerberos.m4 + src/config/Makefile.config.in + src/fsprobe/Makefile.in + src/kauth/Makefile.in + src/libafsauthent/Makefile.in + src/ptserver/Makefile.in + src/ptserver/ptserver.c + src/rxkad/Makefile.in + src/rxkad/private_data.h + src/rxkad/rxkad.p.h + src/rxkad/rxkad_prototypes.h + src/rxkad/rxkad_server.c + src/rxkad/ticket5.c + src/rxkad/ticket5_keytab.c + src/scout/Makefile.in + src/shlibafsauthent/Makefile.in + src/shlibafsrpc/mapfile + src/tbutc/Makefile.in + src/tsm41/Makefile.in + src/tviced/Makefile.in + src/tvolser/Makefile.in + src/update/Makefile.in + src/update/server.c + src/uss/Makefile.in + src/util/dirpath.c + src/util/dirpath.hin + src/venus/Makefile.in + src/viced/Makefile.in + src/viced/viced.c + src/vlserver/Makefile.in + src/vlserver/vlserver.c + src/volser/Makefile.in + src/volser/volmain.c + - Thanks to Chaskiel Grundman, Alexander Chernyakhovsky, and Ben Kaduk for + the above fixes + - OPENAFS-SA-2013-003 + - OPENAFS-SA-2013-004 + - CVE-2013-4134 + - CVE-2013-4135 + - LP: #1204195 + + -- Luke Faraone Wed, 24 Jul 2013 18:07:21 -0400 + openafs (1.4.12+dfsg-3+ubuntu0.2) lucid-security; urgency=low * SECURITY UPDATE: Fix fileserver buffer overflow when parsing diff -u openafs-1.4.12+dfsg/src/tviced/Makefile.in openafs-1.4.12+dfsg/src/tviced/Makefile.in --- openafs-1.4.12+dfsg/src/tviced/Makefile.in +++ openafs-1.4.12+dfsg/src/tviced/Makefile.in @@ -185,7 +185,7 @@ ${CCRULE} fileserver: ${objects} ${LIBS} - ${CC} ${LDFLAGS} -o fileserver ${objects} ${LIBS} ${MT_LIBS} ${XLIBS} + ${CC} ${LDFLAGS} -o fileserver ${objects} ${LIBS} ${MT_LIBS} ${XLIBS} ${KRB5_LIBS} ${DEST}/root.server/usr/afs/bin/fileserver: fileserver ${INSTALL} -ns $? $@ diff -u openafs-1.4.12+dfsg/src/shlibafsauthent/Makefile.in openafs-1.4.12+dfsg/src/shlibafsauthent/Makefile.in --- openafs-1.4.12+dfsg/src/shlibafsauthent/Makefile.in +++ openafs-1.4.12+dfsg/src/shlibafsauthent/Makefile.in @@ -37,7 +37,7 @@ writeconfig.o \ authcon.o \ ktc_errors.o \ - acfg_errors.o + acfg_errors.o @MAKE_KRB5@ akimpersonate.o akimpersonate_v5gen.o KAUTHOBJS = \ kauth.xdr.o \ @@ -68,7 +68,7 @@ fileutil.o RXKADOBJS = \ - rxkad_errs.o + rxkad_errs.o @MAKE_KRB5@ ticket5_keytab.o SYSOBJS = \ rmtsysc.o \ @@ -150,7 +150,13 @@ ${CCRULE} authcon.o: ${AUTH}/authcon.c - ${CCRULE} + ${CCRULE} @KRB5CFLAGS@ + +akimpersonate.o: ${AUTH}/akimpersonate.c + ${CCRULE} @KRB5CFLAGS@ + +akimpersonate_v5gen.o: ${AUTH}/akimpersonate_v5gen.c + ${CCRULE} @KRB5CFLAGS@ -I../rxkad ktc_errors.o: ${AUTH}/ktc_errors.c ${CCRULE} @@ -227,6 +233,9 @@ rxkad_errs.o: ${RXKAD}/rxkad_errs.c ${CCRULE} +ticket5_keytab.o: ${RXKAD}/ticket5_keytab.c + ${CCRULE} @KRB5CFLAGS@ + ptclient.o: ${PTSERVER}/ptclient.c ${CCRULE} only in patch2: unchanged: --- openafs-1.4.12+dfsg.orig/src/fsprobe/Makefile.in +++ openafs-1.4.12+dfsg/src/fsprobe/Makefile.in @@ -41,7 +41,7 @@ fsprobe_test: fsprobe_test.o libfsprobe.a ${LIBS} ${CC} ${CFLAGS} -o fsprobe_test fsprobe_test.o libfsprobe.a \ - ${LIBS} ${XLIBS} + ${LIBS} ${XLIBS} ${KRB5_LIBS} # # Install targets only in patch2: unchanged: --- openafs-1.4.12+dfsg.orig/src/ptserver/ptserver.c +++ openafs-1.4.12+dfsg/src/ptserver/ptserver.c @@ -523,6 +523,10 @@ sc[1] = 0; if (kerberosKeys) { sc[2] = rxkad_NewServerSecurityObject(0, prdir, afsconf_GetKey, NULL); +#ifdef USE_RXKAD_KEYTAB + if (rxkad_InitKeytabDecrypt(AFSDIR_SERVER_RXKAD_KEYTAB_FILEPATH) == 0) + rxkad_BindKeytabDecrypt(sc[2]); +#endif } else sc[2] = sc[0]; only in patch2: unchanged: --- openafs-1.4.12+dfsg.orig/src/ptserver/Makefile.in +++ openafs-1.4.12+dfsg/src/ptserver/Makefile.in @@ -57,7 +57,7 @@ # Build targets # ptserver: ptserver.o ptutils.o ptprocs.o ptint.ss.o ptint.xdr.o utils.o $(LIBS) ${TOP_LIBDIR}/libaudit.a map.o - $(CC) ${CFLAGS} -o ptserver ptserver.o ptutils.o ptprocs.o ptint.ss.o ptint.xdr.o utils.o map.o $(LIBS) ${XLIBS} ${TOP_LIBDIR}/libaudit.a + $(CC) ${CFLAGS} -o ptserver ptserver.o ptutils.o ptprocs.o ptint.ss.o ptint.xdr.o utils.o map.o $(LIBS) ${XLIBS} ${TOP_LIBDIR}/libaudit.a ${KRB5_LIBS} ptserver.o: ptserver.c ${INCLS} AFS_component_version_number.c @@ -103,10 +103,10 @@ db_verify.o: db_verify.c ${INCLS} AFS_component_version_number.c db_verify: db_verify.o pterror.o display.o $(LIBS) - $(CC) ${CFLAGS} -o db_verify db_verify.o display.o pterror.o $(LIBS) ${XLIBS} + $(CC) ${CFLAGS} -o db_verify db_verify.o display.o pterror.o $(LIBS) ${XLIBS} ${KRB5_LIBS} ptclient: ptclient.o display.o libprot.a $(LIBS) - $(CC) ${CFLAGS} -o ptclient ptclient.o display.o libprot.a $(LIBS) ${XLIBS} + $(CC) ${CFLAGS} -o ptclient ptclient.o display.o libprot.a $(LIBS) ${XLIBS} ${KRB5_LIBS} ptclient.o: ptclient.c ${INCLS} AFS_component_version_number.c @@ -122,32 +122,32 @@ $(RANLIB) $@ pts: pts.o libprot.a ${TOP_LIBDIR}/libcmd.a $(LIBS) - $(CC) ${CFLAGS} -o pts pts.o ${TOP_LIBDIR}/libcmd.a libprot.a ${LIBS} ${XLIBS} + $(CC) ${CFLAGS} -o pts pts.o ${TOP_LIBDIR}/libcmd.a libprot.a ${LIBS} ${XLIBS} ${KRB5_LIBS} pts.o: pts.c ${LINCLS} ${TOP_INCDIR}/afs/cmd.h AFS_component_version_number.c readgroup: readgroup.o libprot.a $(LIBS) - $(CC) ${CFLAGS} -o readgroup readgroup.o libprot.a ${LIBS} ${XLIBS} + $(CC) ${CFLAGS} -o readgroup readgroup.o libprot.a ${LIBS} ${XLIBS} ${KRB5_LIBS} readgroup.o: readgroup.c ${LINCLS} AFS_component_version_number.c readpwd: readpwd.o libprot.a $(LIBS) - $(CC) ${CFLAGS} -o readpwd readpwd.o libprot.a ${LIBS} ${XLIBS} + $(CC) ${CFLAGS} -o readpwd readpwd.o libprot.a ${LIBS} ${XLIBS} ${KRB5_LIBS} readpwd.o: readpwd.c ${LINCLS} AFS_component_version_number.c testpt: testpt.o libprot.a ${TOP_LIBDIR}/libcmd.a $(LIBS) case "$(SYS_NAME)" in \ *_darwin_12 ) \ - $(CC) ${CFLAGS} -o testpt testpt.o ${TOP_LIBDIR}/libcmd.a libprot.a $(LIBS) ;; \ + $(CC) ${CFLAGS} -o testpt testpt.o ${TOP_LIBDIR}/libcmd.a libprot.a $(LIBS) ${KRB5_LIBS} ;; \ * ) \ - $(CC) ${CFLAGS} -o testpt testpt.o -lm ${TOP_LIBDIR}/libcmd.a libprot.a $(LIBS) ${XLIBS} ;; \ + $(CC) ${CFLAGS} -o testpt testpt.o -lm ${TOP_LIBDIR}/libcmd.a libprot.a $(LIBS) ${XLIBS} ${KRB5_LIBS} ;; \ esac testpt.o: testpt.c ${INCLS} ${TOP_INCDIR}/afs/cmd.h AFS_component_version_number.c pt_util: pt_util.o ptutils.o ubik.o utils.o map.o libprot.a $(LIBS) - $(CC) ${CFLAGS} -o pt_util pt_util.o ptutils.o ubik.o utils.o map.o libprot.a ${TOP_LIBDIR}/libcmd.a $(LIBS) ${XLIBS} + $(CC) ${CFLAGS} -o pt_util pt_util.o ptutils.o ubik.o utils.o map.o libprot.a ${TOP_LIBDIR}/libcmd.a $(LIBS) ${XLIBS} ${KRB5_LIBS} ubik.o: ubik.c ${INCLS} only in patch2: unchanged: --- openafs-1.4.12+dfsg.orig/src/cf/kerberos.m4 +++ openafs-1.4.12+dfsg/src/cf/kerberos.m4 @@ -56,11 +56,13 @@ AC_MSG_RESULT([Configuring support for Kerberos 5 utilities]) BUILD_KRB5=yes MAKE_KRB5= + AC_DEFINE([USE_RXKAD_KEYTAB], 1, + [Define to 1 if krb5 libraries are available and rxkad can use keytabs]) save_CPPFLAGS="$CPPFLAGS" CPPFLAGS="$CPPFLAGS $KRB5CFLAGS" save_LIBS="$LIBS" LIBS="$LIBS $KRB5LIBS" - AC_CHECK_FUNCS([add_to_error_table add_error_table krb5_princ_size krb5_principal_get_comp_string encode_krb5_enc_tkt_part encode_krb5_ticket krb5_c_encrypt krb5_c_encrypt_length krb5_cc_register krb5_decode_ticket krb5_get_prompt_types krb5_allow_weak_crypto krb5_enctype_enable]) + AC_CHECK_FUNCS([add_to_error_table add_error_table krb5_princ_size krb5_principal_get_comp_string encode_krb5_enc_tkt_part encode_krb5_ticket krb5_c_encrypt krb5_c_encrypt_length krb5_c_decrypt krb5_cc_register krb5_decode_ticket krb5_get_prompt_types krb5_allow_weak_crypto krb5_enctype_enable krb5_crypto_init krb5_encrypt_tkt_part krb5_decrypt_tkt_part]) AC_CHECK_FUNCS([krb5_524_convert_creds], , [AC_CHECK_FUNCS([krb524_convert_creds_kdc], , [AC_CHECK_LIB([krb524], [krb524_convert_creds_kdc], @@ -71,54 +73,17 @@ AC_CHECK_HEADERS([kerberosIV/krb.h]) AC_CHECK_HEADERS([kerberosV/heim_err.h]) -AC_MSG_CHECKING(for krb5_creds.keyblock existence) -AC_CACHE_VAL(ac_cv_krb5_creds_keyblock_exists, -[ -AC_TRY_COMPILE( -[#include ], -[krb5_creds _c; -printf("%x\n", _c.keyblock);], -ac_cv_krb5_creds_keyblock_exists=yes, -ac_cv_krb5_creds_keyblock_exists=no)]) -AC_MSG_RESULT($ac_cv_krb5_creds_keyblock_exists) - -AC_MSG_CHECKING(for krb5_creds.session existence) -AC_CACHE_VAL(ac_cv_krb5_creds_session_exists, -[ -AC_TRY_COMPILE( -[#include ], -[krb5_creds _c; -printf("%x\n", _c.session);], -ac_cv_krb5_creds_session_exists=yes, -ac_cv_krb5_creds_session_exists=no)]) -AC_MSG_RESULT($ac_cv_krb5_creds_session_exists) -AC_MSG_CHECKING(for krb5_prompt.type existence) -AC_CACHE_VAL(ac_cv_krb5_prompt_type_exists, -[ -AC_TRY_COMPILE( -[#include ], -[krb5_prompt _p; -printf("%x\n", _p.type);], -ac_cv_krb5_prompt_type_exists=yes, -ac_cv_krb5_prompt_type_exists=no)]) -AC_MSG_RESULT($ac_cv_krb5_prompt_type_exists) - -if test "x$ac_cv_krb5_creds_keyblock_exists" = "xyes"; then - AC_DEFINE(HAVE_KRB5_CREDS_KEYBLOCK, 1, [define if krb5_creds has keyblock]) -fi -if test "x$ac_cv_krb5_creds_session_exists" = "xyes"; then - AC_DEFINE(HAVE_KRB5_CREDS_SESSION, 1, [define if krb5_creds has session]) -fi -if test "x$ac_cv_krb5_prompt_type_exists" = "xyes"; then - AC_DEFINE(HAVE_KRB5_PROMPT_TYPE, 1, [define if krb5_prompt has type]) -fi - -dnl AC_CHECK_MEMBERS([krb5_creds.keyblock, krb5_creds.session],,, [#include ]) + AC_CHECK_MEMBERS([krb5_creds.keyblock, krb5_creds.keyblock.enctype, + krb5_creds.session, krb5_keytab_entry.key, + krb5_keytab_entry.keyblock, krb5_keyblock.enctype, + krb5_keyblock.keytype, krb5_prompt.type], , , + [#include ]) + AC_CHECK_DECLS([krb5_free_keytab_entry_contents, krb5_kt_free_entry, + KRB5_KU_TICKET], [], [], [#include ]) CPPFLAGS="$save_CPPFLAGS" LIBS="$save_LIBS" fi - if test "x$ac_cv_krb5_cc_register_exists" = "xyes"; then AC_DEFINE(HAVE_KRB5_CC_REGISTER, 1, [define if krb5_cc_register exists]) fi only in patch2: unchanged: --- openafs-1.4.12+dfsg.orig/src/kauth/Makefile.in +++ openafs-1.4.12+dfsg/src/kauth/Makefile.in @@ -67,7 +67,7 @@ cd test; $(MAKE) kaserver: kautils.o kalocalcell.o kadatabase.o kaprocs.o kalog.o kauth.ss.o kauth.xdr.o kaserver.o kaaux.o krb_udp.o kaauxdb.o $(LIBS) - ${CC} ${LDFLAGS} -o kaserver kaserver.o kautils.o kalocalcell.o kadatabase.o krb_udp.o kaprocs.o kalog.o kauth.ss.o kauth.xdr.o kaaux.o kaauxdb.o $(LIBS) ${XLIBS} ${TOP_LIBDIR}/libaudit.a + ${CC} ${LDFLAGS} -o kaserver kaserver.o kautils.o kalocalcell.o kadatabase.o krb_udp.o kaprocs.o kalog.o kauth.ss.o kauth.xdr.o kaaux.o kaauxdb.o $(LIBS) ${XLIBS} ${TOP_LIBDIR}/libaudit.a ${KRB5_LIBS} kaserver.o: kaserver.c ${INCLS} AFS_component_version_number.o @@ -147,19 +147,19 @@ kas: kauth.h kautils.h admin_tools.o libkauth.a $(LIBS) kas.o kkids.o ${CC} ${LDFLAGS} -o kas kas.o admin_tools.o kkids.o libkauth.a \ - ${LIBS} ${XLIBS} + ${LIBS} ${XLIBS} ${KRB5_LIBS} klog: AFS_component_version_number.o kauth.h kautils.h libkauth.a $(LIBS) \ klog.o - ${CC} ${LDFLAGS} -o klog klog.o libkauth.a ${LIBS} ${XLIBS} + ${CC} ${LDFLAGS} -o klog klog.o libkauth.a ${LIBS} ${XLIBS} ${KRB5_LIBS} klog.o: klog.c kauth.h kautils.h AFS_component_version_number.o klog.krb: kauth.h kautils.h libkauth.krb.a $(KLIBS) klog.o - ${CC} ${LDFLAGS} -o klog.krb klog.o libkauth.krb.a ${KLIBS} ${XLIBS} + ${CC} ${LDFLAGS} -o klog.krb klog.o libkauth.krb.a ${KLIBS} ${XLIBS} ${KRB5_LIBS} knfs: kauth.h kautils.h libkauth.a $(LIBS) knfs.o - ${CC} ${LDFLAGS} -o knfs knfs.o libkauth.a ${LIBS} ${XLIBS} + ${CC} ${LDFLAGS} -o knfs knfs.o libkauth.a ${LIBS} ${XLIBS} ${KRB5_LIBS} knfs.o: knfs.c AFS_component_version_number.o @@ -167,22 +167,22 @@ ${CC} ${CFLAGS} -c ${srcdir}/klogin.c -DKAUTH klogin: libkauth.a $(LIBS) klogin.o - ${CC} ${LDFLAGS} -o klogin klogin.o libkauth.a ${LIBS} ${XLIBS} + ${CC} ${LDFLAGS} -o klogin klogin.o libkauth.a ${LIBS} ${XLIBS} ${KRB5_LIBS} klogin.krb: libkauth.a $(KLIBS) klogin.o - ${CC} ${LDFLAGS} -o klogin.krb klogin.o libkauth.krb.a ${KLIBS} ${XLIBS} + ${CC} ${LDFLAGS} -o klogin.krb klogin.o libkauth.krb.a ${KLIBS} ${XLIBS} ${KRB5_LIBS} kpasswd.o: kauth.h kautils.h ${INCLS} kpasswd.c AFS_component_version_number.o ${CC} ${CFLAGS} -c ${srcdir}/kpasswd.c kpasswd: kauth.h kautils.h libkauth.a $(LIBS) kpasswd.o kkids.o - ${CC} ${LDFLAGS} -o kpasswd kpasswd.o kkids.o libkauth.a ${LIBS} ${XLIBS} + ${CC} ${LDFLAGS} -o kpasswd kpasswd.o kkids.o libkauth.a ${LIBS} ${XLIBS} ${KRB5_LIBS} kpwvalid.o: kpwvalid.c AFS_component_version_number.o ${CC} ${CFLAGS} -c ${srcdir}/kpwvalid.c kpwvalid: kpwvalid.o $(LIBS) - ${CC} ${LDFLAGS} -o kpwvalid kpwvalid.o ${LIBS} ${XLIBS} + ${CC} ${LDFLAGS} -o kpwvalid kpwvalid.o ${LIBS} ${XLIBS} ${KRB5_LIBS} user.krb.o: user.c ${INCLS} ${TOP_INCDIR}/afs/vice.h ${CCOBJ} ${CFLAGS} -DAFS_KERBEROS_ENV -c ${srcdir}/user.c -o user.krb.o @@ -191,7 +191,7 @@ ${CCOBJ} ${CFLAGS} -c ${srcdir}/user.c kdb: kdb.o ${INCLS} ${LIBS} libkauth.a - ${CC} ${LDFLAGS} -o kdb kdb.o libkauth.a ${LIBS} ${XLIBS} + ${CC} ${LDFLAGS} -o kdb kdb.o libkauth.a ${LIBS} ${XLIBS} ${KRB5_LIBS} kdb.o: kdb.c AFS_component_version_number.o @@ -201,12 +201,12 @@ ${CC} ${LDFLAGS} -o krb_udp krb_udp.o libkauth.a $(KLIBS) ka-forwarder: ka-forwarder.o - ${CC} -o $@ ${CFLAGS} ka-forwarder.o ${LIBS} ${XLIBS} + ${CC} -o $@ ${CFLAGS} ka-forwarder.o ${LIBS} ${XLIBS} ${KRB5_LIBS} rebuild.o: rebuild.c $(INCLS) AFS_component_version_number.o rebuild: rebuild.o kautils.o $(LIBS) - ${CC} ${LDFLAGS} -o rebuild rebuild.o kautils.o $(LIBS) + ${CC} ${LDFLAGS} -o rebuild rebuild.o kautils.o $(LIBS) ${KRB5_LIBS} # # Install targets only in patch2: unchanged: --- openafs-1.4.12+dfsg.orig/src/rxkad/ticket5.c +++ openafs-1.4.12+dfsg/src/rxkad/ticket5.c @@ -83,6 +83,7 @@ #include #include #include +#include #include "lifetimes.h" #include "rxkad.h" #endif /* defined(UKERNEL) */ @@ -184,8 +185,11 @@ static int krb5_des_decrypt(struct ktc_encryptionKey *, int, void *, size_t, void *, size_t *); - - +static int rxkad_derive_des_key(const void *, size_t, + struct ktc_encryptionKey *); +static int compress_parity_bits(void *, size_t *); +static void hmac_md5_iov(const void *, size_t, const struct iovec *, + unsigned int, void *); int @@ -193,7 +197,8 @@ int (*get_key) (char *, int, struct ktc_encryptionKey *), char *get_key_rock, int serv_kvno, char *name, char *inst, char *cell, char *session_key, afs_int32 * host, - afs_int32 * start, afs_int32 * end, afs_int32 disableCheckdot) + afs_int32 * start, afs_int32 * end, afs_int32 disableCheckdot, + rxkad_alt_decrypt_func alt_decrypt) { char plain[MAXKRB5TICKETLEN]; struct ktc_encryptionKey serv_key; @@ -234,33 +239,41 @@ v5_serv_kvno = *t5.enc_part.kvno; } - /* Check that the key type really fit into 8 bytes */ + /* check ticket */ + if (t5.enc_part.cipher.length > sizeof(plain)) + goto bad_ticket; switch (t5.enc_part.etype) { case ETYPE_DES_CBC_CRC: case ETYPE_DES_CBC_MD4: case ETYPE_DES_CBC_MD5: + /* Check that the key type really fit into 8 bytes */ + if (t5.enc_part.cipher.length % 8 != 0) + goto bad_ticket; + + code = (*get_key) (get_key_rock, v5_serv_kvno, &serv_key); + if (code) + goto unknown_key; + + /* Decrypt data here, save in plain, assume it will shrink */ + code = + krb5_des_decrypt(&serv_key, t5.enc_part.etype, + t5.enc_part.cipher.data, + t5.enc_part.cipher.length, plain, &plainsiz); + if (code != 0) + goto bad_ticket; break; default: - goto unknown_key; + if (alt_decrypt != NULL) { + plainsiz = sizeof(plain); + code = alt_decrypt(v5_serv_kvno, t5.enc_part.etype, + t5.enc_part.cipher.data, + t5.enc_part.cipher.length, plain, &plainsiz); + if (code != 0) + goto cleanup; + } else + goto unknown_key; } - /* check ticket */ - if (t5.enc_part.cipher.length > sizeof(plain) - || t5.enc_part.cipher.length % 8 != 0) - goto bad_ticket; - - code = (*get_key) (get_key_rock, v5_serv_kvno, &serv_key); - if (code) - goto unknown_key; - - /* Decrypt data here, save in plain, assume it will shrink */ - code = - krb5_des_decrypt(&serv_key, t5.enc_part.etype, - t5.enc_part.cipher.data, t5.enc_part.cipher.length, - plain, &plainsiz); - if (code != 0) - goto bad_ticket; - /* Decode ticket */ code = decode_EncTicketPart(plain, plainsiz, &decr_part, &siz); if (code != 0) @@ -321,21 +334,9 @@ } /* Verify that decr_part.key is of right type */ - switch (decr_part.key.keytype) { - case ETYPE_DES_CBC_CRC: - case ETYPE_DES_CBC_MD4: - case ETYPE_DES_CBC_MD5: - break; - default: + if (tkt_DeriveDesKey(decr_part.key.keytype, decr_part.key.keyvalue.data, + decr_part.key.keyvalue.length, session_key) != 0) goto bad_ticket; - } - - if (decr_part.key.keyvalue.length != 8) - goto bad_ticket; - - /* Extract session key */ - memcpy(session_key, decr_part.key.keyvalue.data, 8); - /* Check lifetimes and host addresses, flags etc */ { time_t now = time(0); /* Use fast time package instead??? */ @@ -483,3 +484,176 @@ return ret; } + +/* + * Use NIST SP800-108 with HMAC(MD5) in counter mode as the PRF to derive a + * des key from another type of key. + * + * L is 64, as we take 64 random bits and turn them into a 56-bit des key. + * The output of hmac_md5 is 128 bits; we take the first 64 only, so n + * properly should be 1. However, we apply a slight variation due to the + * possibility of producing a weak des key. If the output key is weak, do NOT + * simply correct it, instead, the counter is advanced and the next output + * used. As such, we code so as to have n be the full 255 permitted by our + * encoding of the counter i in an 8-bit field. L itself is encoded as a + * 32-bit field, big-endian. We use the constant string "rxkad" as a label + * for this key derivation, the standard NUL byte separator, and omit a + * key-derivation context. The input key is unique to the krb5 service ticket, + * which is unlikely to be used in an other location. If it is used in such + * a fashion, both locations will derive the same des key from the PRF, but + * this is no different from if a krb5 des key had been used in the same way, + * as traditional krb5 rxkad uses the ticket session key directly as the token + * key. + */ +static int +rxkad_derive_des_key(const void *in, size_t insize, + struct ktc_encryptionKey *out) +{ + unsigned char i; + char Lbuf[4]; /* bits of output, as 32 bit word, MSB first */ + char tmp[16]; + struct iovec iov[3]; + des_cblock ktmp; + + Lbuf[0] = 0; + Lbuf[1] = 0; + Lbuf[2] = 0; + Lbuf[3] = 64; + + iov[0].iov_base = &i; + iov[0].iov_len = 1; + iov[1].iov_base = "rxkad"; + iov[1].iov_len = strlen("rxkad") + 1; /* includes label and separator */ + iov[2].iov_base = Lbuf; + iov[2].iov_len = 4; + + /* stop when 8 bit counter wraps to 0 */ + for (i = 1; i ; i++) { + hmac_md5_iov(in, insize, iov, 3, tmp); + memcpy(ktmp, tmp, 8); + des_fixup_key_parity(ktmp); + if (!des_is_weak_key(ktmp)) { + memcpy(out->data, ktmp, 8); + return 0; + } + } + return -1; +} + +/* + * This is the inverse of the random-to-key for 3des specified in + * rfc3961, converting blocks of 8 bytes to blocks of 7 bytes by distributing + * the bits of each 8th byte as the lsb of the previous 7 bytes. + */ +static int +compress_parity_bits(void *buffer, size_t *bufsiz) +{ + unsigned char *cb, tmp; + int i, j, nk; + + if (*bufsiz % 8 != 0) + return 1; + cb = (unsigned char *)buffer; + nk = *bufsiz / 8; + for (i = 0; i < nk; i++) { + tmp = cb[8 * i + 7] >> 1; + for (j = 0; j < 7; j++) { + cb[8 * i + j] &= 0xfe; + cb[8 * i + j] |= tmp & 0x1; + tmp >>= 1; + } + } + for (i = 1; i < nk; i++) + memmove(cb + 7 * i, cb + 8 * i, 7); + *bufsiz = 7 * nk; + return 0; +} + +/* HMAC: Keyed-Hashing for Message Authentication, using MD5 as the hash. + * See RFC 2104. + * + * The constants 64 and 16 are the input block size and output length, + * respectively, of md5. + */ +static void +hmac_md5_iov(const void *key, size_t ks, + const struct iovec *data, unsigned int niov, void *output) +{ + MD5_CTX md5; + const unsigned char *kp; + unsigned int i; + unsigned char tmp[16], tmpk[16], i_pad[64], o_pad[64]; + if (ks > 64) { + MD5_Init(&md5); + MD5_Update(&md5, key, ks); + MD5_Final(tmpk, &md5); + key = tmpk; + ks = 16; + } + kp = key; + for (i = 0; i < ks; i++) + i_pad[i] = kp[i] ^ 0x36; + memset(i_pad + ks, 0x36, 64 - ks); + MD5_Init(&md5); + MD5_Update(&md5, i_pad, 64); + for (i = 0; i < niov; i++) + MD5_Update(&md5, data[i].iov_base, data[i].iov_len); + MD5_Final(tmp, &md5); + for (i = 0; i < ks; i++) + o_pad[i] = kp[i] ^ 0x5c; + memset(o_pad + ks, 0x5c, 64 - ks); + MD5_Init(&md5); + MD5_Update(&md5, o_pad, 64); + MD5_Update(&md5, tmp, 16); + MD5_Final(output, &md5); +} + +/* + * Enctype-specific knowledge about how to derive a des key from a given + * key. If given a des key, use it directly; otherwise, perform any + * parity fixup that may be needed and pass through to the hmad-md5 bits. + */ +int +tkt_DeriveDesKey(int enctype, void *keydata, size_t keylen, + struct ktc_encryptionKey *output) +{ + switch (enctype) { + case ETYPE_DES_CBC_CRC: + case ETYPE_DES_CBC_MD4: + case ETYPE_DES_CBC_MD5: + if (keylen != 8) + return 1; + + /* Extract session key */ + memcpy(output, keydata, 8); + break; + case ETYPE_NULL: + case 4: + case 6: + case 8: + case 9: + case 10: + case 11: + case 12: + case 13: + case 14: + case 15: + return 1; + /*In order to become a "Cryptographic Key" as specified in + * SP800-108, it must be indistinguishable from a random bitstring. */ + case ETYPE_DES3_CBC_MD5: + case ETYPE_OLD_DES3_CBC_SHA1: + case ETYPE_DES3_CBC_SHA1: + if (compress_parity_bits(keydata, &keylen)) + return 1; + /* FALLTHROUGH */ + default: + if (enctype < 0) + return 1; + if (keylen < 7) + return 1; + if (rxkad_derive_des_key(keydata, keylen, output) != 0) + return 1; + } + return 0; +} only in patch2: unchanged: --- openafs-1.4.12+dfsg.orig/src/rxkad/ticket5_keytab.c +++ openafs-1.4.12+dfsg/src/rxkad/ticket5_keytab.c @@ -0,0 +1,333 @@ +/* + * Copyright (c) 2013 Chaskiel Grundman + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR `AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include +#include +#include + +#include + +#include + +#ifdef RX_ENABLE_LOCKS +static afs_kmutex_t krb5_lock; +#endif + +/* these globals are expected to be set only once, so locking is not needed */ +static char *keytab_name; +static int have_keytab_keys; + +/* + * krb5_lock must be held to use/set these globals, including any + * krb5 api use with k5ctx + */ +static krb5_context k5ctx; +static int nkeys; +static krb5_keytab_entry *ktent; +static time_t last_reload; + +#ifdef HAVE_KRB5_KEYBLOCK_ENCTYPE +# define kb_enctype(keyblock) ((keyblock)->enctype) +#elif defined(HAVE_KRB5_KEYBLOCK_KEYTYPE) +# define kb_enctype(keyblock) ((keyblock)->keytype) +#else +# error Cannot figure out how keyblocks work +#endif +#ifdef HAVE_KRB5_KEYTAB_ENTRY_KEYBLOCK +# define kte_keyblock(kte) (&(kte).keyblock) +#elif defined(HAVE_KRB5_KEYTAB_ENTRY_KEY) +# define kte_keyblock(kte) (&(kte).key) +#else +# error Cannot figure out how keytab entries work +#endif +#if HAVE_DECL_KRB5_FREE_KEYTAB_ENTRY_CONTENTS +/* nothing */ +#elif HAVE_DECL_KRB5_KT_FREE_ENTRY +# define krb5_free_keytab_entry_contents krb5_kt_free_entry +#else +static_inline int +krb5_free_keytab_entry_contents(krb5_context ctx, krb5_keytab_entry *ent) +{ + krb5_free_principal(ctx, ent->principal); + krb5_free_keyblock_contents(ctx, kte_keyblock(ent)); + return 0; +} +#endif +#ifndef KRB5_KEYUSAGE_KDC_REP_TICKET +# ifdef HAVE_DECL_KRB5_KU_TICKET +# define KRB5_KEYUSAGE_KDC_REP_TICKET KRB5_KU_TICKET +# else +# define KRB5_KEYUSAGE_KDC_REP_TICKET 2 +# endif +#endif + +static krb5_error_code +reload_keys(void) +{ + krb5_error_code ret; + krb5_keytab fkeytab = NULL; + krb5_kt_cursor c; + krb5_keytab_entry kte; + int i, n_nkeys, o_nkeys; + krb5_keytab_entry *n_ktent = NULL, *o_ktent; + + time(&last_reload); + if (keytab_name != NULL) + ret = krb5_kt_resolve(k5ctx, keytab_name, &fkeytab); + else + ret = krb5_kt_default(k5ctx, &fkeytab); + if (ret != 0) + goto cleanup; + ret = krb5_kt_start_seq_get(k5ctx, fkeytab, &c); + if (ret != 0) + goto cleanup; + n_nkeys = 0; + while (krb5_kt_next_entry(k5ctx, fkeytab, &kte, &c) == 0) { + krb5_free_keytab_entry_contents(k5ctx, &kte); + n_nkeys++; + } + krb5_kt_end_seq_get(k5ctx, fkeytab, &c); + if (n_nkeys == 0) { + ret = KRB5_KT_NOTFOUND; + goto cleanup; + } + n_ktent = calloc(n_nkeys, sizeof(krb5_keytab_entry)); + if (n_ktent == NULL) { + ret = KRB5_KT_NOTFOUND; + goto cleanup; + } + ret = krb5_kt_start_seq_get(k5ctx, fkeytab, &c); + if (ret != 0) + goto cleanup; + for (i = 0; i < n_nkeys; i++) + if (krb5_kt_next_entry(k5ctx, fkeytab, &n_ktent[i], &c) != 0) + break; + krb5_kt_end_seq_get(k5ctx, fkeytab, &c); + if (i < n_nkeys) + goto cleanup; + have_keytab_keys = 1; + o_ktent = ktent; + ktent = n_ktent; + + o_nkeys = nkeys; + nkeys = n_nkeys; + + /* for cleanup */ + n_ktent = o_ktent; + n_nkeys = o_nkeys; +cleanup: + if (n_ktent != NULL) { + for (i = 0; i < n_nkeys; i++) + krb5_free_keytab_entry_contents(k5ctx, &n_ktent[i]); + free(n_ktent); + } + if (fkeytab != NULL) { + krb5_kt_close(k5ctx, fkeytab); + } + return ret; +} + +#if defined(HAVE_KRB5_DECRYPT_TKT_PART) && !defined(HAVE_KRB5_C_DECRYPT) +extern krb5_error_code +encode_krb5_enc_tkt_part(krb5_enc_tkt_part *encpart, krb5_data **a_out); +/* + * AIX krb5 has krb5_decrypt_tkt_part, but no krb5_c_decrypt. So, implement our + * own krb5_c_decrypt. Note that this krb5_c_decrypt is only suitable for + * decrypting an encrypted krb5_enc_tkt_part. But since that's all we ever use + * it for, that should be fine. + */ +static krb5_error_code +krb5_c_decrypt(krb5_context context, const krb5_keyblock *key, + krb5_keyusage usage, const krb5_data *cipher_state, + const krb5_enc_data *input, krb5_data *output) +{ + krb5_ticket tkt; + krb5_error_code code; + krb5_data *tout; + + osi_Assert(cipher_state == NULL); + osi_Assert(usage == KRB5_KEYUSAGE_KDC_REP_TICKET); + + memset(&tkt, 0, sizeof(tkt)); + + tkt.enc_part = *input; + + code = krb5_decrypt_tkt_part(context, key, &tkt); + if (code != 0) + return code; + + code = encode_krb5_enc_tkt_part(tkt.enc_part2, &tout); + if (code != 0) + return code; + + osi_Assert(tout->length <= output->length); + + memcpy(output->data, tout->data, tout->length); + output->length = tout->length; + + krb5_free_data(context, tout); + return 0; +} +#endif /* HAVE_KRB5_DECRYPT_TKT_PART && !HAVE_KRB5_C_DECRYPT */ + +static int +rxkad_keytab_decrypt(int kvno, int et, void *in, size_t inlen, + void *out, size_t *outlen) +{ + krb5_error_code code; + /* use heimdal api if available, since heimdal's interface to + krb5_c_decrypt is non-standard and annoying to use */ +#ifdef HAVE_KRB5_CRYPTO_INIT + krb5_crypto kcrypto; +#else + krb5_enc_data ind; +#endif + krb5_data outd; + int retried, i, foundkey; + MUTEX_ENTER(&krb5_lock); + if (have_keytab_keys == 0) { + if (time(NULL) - last_reload > 600) { + reload_keys(); + } + if (have_keytab_keys == 0) { + MUTEX_EXIT(&krb5_lock); + return RXKADUNKNOWNKEY; + } + } + foundkey = 0; + code = -1; + retried = 0; +retry: + for (i = 0; i < nkeys; i++) { + /* foundkey determines what error code we return for failure */ + if (ktent[i].vno == kvno) + foundkey = 1; + /* but check against all keys if the enctype matches, for robustness */ + if (kb_enctype(kte_keyblock(ktent[i])) == et) { +#ifdef HAVE_KRB5_CRYPTO_INIT + code = krb5_crypto_init(k5ctx, kte_keyblock(ktent[i]), et, + &kcrypto); + if (code == 0) { + code = krb5_decrypt(k5ctx, kcrypto, + KRB5_KEYUSAGE_KDC_REP_TICKET, in, inlen, + &outd); + krb5_crypto_destroy(k5ctx, kcrypto); + } + if (code == 0) { + /* heimdal allocates new memory for the decrypted data; put + * the data back into the requested 'out' buffer */ + osi_Assert(outd.length <= *outlen); + *outlen = outd.length; + memcpy(out, outd.data, outd.length); + krb5_data_free(&outd); + break; + } +#else + outd.length = *outlen; + outd.data = out; + ind.ciphertext.length = inlen; + ind.ciphertext.data = in; + ind.enctype = et; + ind.kvno = kvno; + code = krb5_c_decrypt(k5ctx, kte_keyblock(ktent[i]), + KRB5_KEYUSAGE_KDC_REP_TICKET, NULL, &ind, + &outd); + if (code == 0) { + *outlen = outd.length; + break; + } +#endif + } + } + if (code != 0 && time(NULL) - last_reload > 600 && !retried) { + reload_keys(); + retried = 1; + goto retry; + } + MUTEX_EXIT(&krb5_lock); + if (code == 0) + return 0; + if (foundkey != 0) + return RXKADBADTICKET; + return RXKADUNKNOWNKEY; +} + +#ifdef RX_ENABLE_LOCKS +static int +init_krb5_lock(void) +{ + MUTEX_INIT(&krb5_lock, "krb5 api", MUTEX_DEFAULT, 0); +} + +static pthread_once_t rxkad_keytab_once_init = PTHREAD_ONCE_INIT; +#define INIT_PTHREAD_LOCKS osi_Assert(pthread_once(&rxkad_keytab_once_init, init_krb5_lock)==0) +#else +#define INIT_PTHREAD_LOCKS +#endif +int +rxkad_InitKeytabDecrypt(const char *ktname) +{ + int code; + static int keytab_init; + INIT_PTHREAD_LOCKS; + MUTEX_ENTER(&krb5_lock); + if (keytab_init) { + MUTEX_EXIT(&krb5_lock); + return 0; + } + k5ctx = NULL; + keytab_name = NULL; + code = krb5_init_context(&k5ctx); + if (code != 0) + goto cleanup; + if (ktname != NULL) { + keytab_name = strdup(ktname); + if (keytab_name == NULL) { + code = KRB5_KT_BADNAME; + goto cleanup; + } + } + keytab_init=1; + reload_keys(); + MUTEX_EXIT(&krb5_lock); + return 0; +cleanup: + if (keytab_name != NULL) { + free(keytab_name); + } + if (k5ctx != NULL) { + krb5_free_context(k5ctx); + } + MUTEX_EXIT(&krb5_lock); + return code; +} + +int +rxkad_BindKeytabDecrypt(struct rx_securityClass *aclass) +{ + return rxkad_SetAltDecryptProc(aclass, rxkad_keytab_decrypt); +} only in patch2: unchanged: --- openafs-1.4.12+dfsg.orig/src/rxkad/rxkad.p.h +++ openafs-1.4.12+dfsg/src/rxkad/rxkad.p.h @@ -93,6 +93,11 @@ extern int rxkad_EpochWasSet; /* TRUE => we called rx_SetEpoch */ +/* An alternate decryption function for rxkad. Using the given kvno and + * enctype, decrypt the input data + length to output data + length. */ +typedef int (*rxkad_alt_decrypt_func)(int, int, void *, size_t, void *, + size_t *); + #include "rxkad_prototypes.h" #endif /* OPENAFS_RXKAD_RXKAD_H */ only in patch2: unchanged: --- openafs-1.4.12+dfsg.orig/src/rxkad/rxkad_prototypes.h +++ openafs-1.4.12+dfsg/src/rxkad/rxkad_prototypes.h @@ -124,6 +124,8 @@ struct rx_connection *aconn, rx_securityConfigVariables atype, void * avalue, void **aresult); +extern int rxkad_SetAltDecryptProc(struct rx_securityClass *aobj, + rxkad_alt_decrypt_func alt_decrypt); /* ticket.c */ extern int tkt_DecodeTicket(char *asecret, afs_int32 ticketLen, @@ -149,6 +151,16 @@ char *get_key_rock, int serv_kvno, char *name, char *inst, char *cell, char *session_key, afs_int32 * host, afs_int32 * start, - afs_int32 * end, afs_int32 disableDotCheck); + afs_int32 * end, afs_int32 disableDotCheck, + rxkad_alt_decrypt_func alt_decrypt); +/* + * Compute a des key from a key of a semi-arbitrary kerberos 5 enctype. + * Modifies keydata if enctype is 3des. + */ +extern int tkt_DeriveDesKey(int enctype, void *keydata, size_t keylen, struct ktc_encryptionKey + *output); +/* ticket5_keytab.c */ +extern int rxkad_InitKeytabDecrypt(const char *); +extern int rxkad_BindKeytabDecrypt(struct rx_securityClass *); #endif only in patch2: unchanged: --- openafs-1.4.12+dfsg.orig/src/rxkad/Makefile.in +++ openafs-1.4.12+dfsg/src/rxkad/Makefile.in @@ -17,7 +17,7 @@ OBJS=rxkad_client.o rxkad_server.o rxkad_common.o rxkad_errs.o \ fcrypt.o crypt_conn.o ticket.o ticket5.o crc.o \ - md4.o md5.o + md4.o md5.o @MAKE_KRB5@ ticket5_keytab.o fc_test_OBJS=fc_test.o @@ -94,6 +94,9 @@ crypt_conn.o: ${srcdir}/domestic/crypt_conn.c fcrypt.h private_data.h ${INCLS} ${CCOBJ} ${CFLAGS} -c ${srcdir}/domestic/crypt_conn.c +ticket5_keytab.o: ticket5_keytab.c ${INCLS} + ${CCOBJ} ${CFLAGS} -c ${srcdir}/ticket5_keytab.c @KRB5CFLAGS@ + tcrypt.o: ${srcdir}/domestic/tcrypt.c AFS_component_version_number.o ${CCOBJ} ${CFLAGS} -c ${srcdir}/domestic/fcrypt.c only in patch2: unchanged: --- openafs-1.4.12+dfsg.orig/src/rxkad/rxkad_server.c +++ openafs-1.4.12+dfsg/src/rxkad/rxkad_server.c @@ -326,7 +326,8 @@ tkt_DecodeTicket5(tix, tlen, tsp->get_key, tsp->get_key_rock, kvno, client.name, client.instance, client.cell, &sessionkey, &host, &start, &end, - tsp->flags & RXS_CONFIG_FLAGS_DISABLE_DOTCHECK); + tsp->flags & RXS_CONFIG_FLAGS_DISABLE_DOTCHECK, + tsp->alt_decrypt); if (code) return code; } @@ -474,3 +475,13 @@ } return 0; } + +int rxkad_SetAltDecryptProc(struct rx_securityClass *aobj, + rxkad_alt_decrypt_func alt_decrypt) +{ + struct rxkad_sprivate *private = + (struct rxkad_sprivate *)aobj->privateData; + + private->alt_decrypt = alt_decrypt; + return 0; +} only in patch2: unchanged: --- openafs-1.4.12+dfsg.orig/src/rxkad/private_data.h +++ openafs-1.4.12+dfsg/src/rxkad/private_data.h @@ -78,6 +78,7 @@ int (*get_key) (); /* func. of kvno and server key ptr */ int (*user_ok) (); /* func called with new client name */ afs_uint32 flags; /* configuration flags */ + rxkad_alt_decrypt_func alt_decrypt; }; /* private data in server-side connection */ only in patch2: unchanged: --- openafs-1.4.12+dfsg.orig/src/tvolser/Makefile.in +++ openafs-1.4.12+dfsg/src/tvolser/Makefile.in @@ -189,7 +189,7 @@ ${COMPILE} volserver: ${objects} ${LIBS} - ${CC} ${LDFLAGS} -o volserver ${objects} ${LIBS} ${MT_LIBS} ${XLIBS} + ${CC} ${LDFLAGS} -o volserver ${objects} ${LIBS} ${MT_LIBS} ${XLIBS} ${KRB5_LIBS} ${DEST}/root.server/usr/afs/bin/volserver: volserver ${INSTALL} -ns $? $@ only in patch2: unchanged: --- openafs-1.4.12+dfsg.orig/src/butc/Makefile.in +++ openafs-1.4.12+dfsg/src/butc/Makefile.in @@ -52,15 +52,15 @@ all: butc read_tape butc_test: ${TESTOBJS} ${LIBS} ${INCLS} ${HACKS} - ${CC} ${CFLAGS} ${TESTOBJS} ${LIBS} ${XLIBS} -o butc_test + ${CC} ${CFLAGS} ${TESTOBJS} ${LIBS} ${XLIBS} ${KRB5_LIBS} -o butc_test tdump: tdump.c AFS_component_version_number.c ${CC} ${CFLAGS} ${srcdir}/tdump.c -o tdump butc: ${SOBJS} ${LIBS} ${INCLS} ${HACKS} @case ${SYS_NAME} in \ - rs_aix*) ${CC} ${CFLAGS} ${SOBJS} ${LIBS} ${XLIBS} /usr/lib/libc_r.a -o butc;; \ - *) ${CC} ${CFLAGS} ${SOBJS} ${LIBS} ${XLIBS} -o butc;; \ + rs_aix*) ${CC} ${CFLAGS} ${SOBJS} ${LIBS} ${XLIBS} ${KRB5_LIBS} /usr/lib/libc_r.a -o butc;; \ + *) ${CC} ${CFLAGS} ${SOBJS} ${LIBS} ${XLIBS} ${KRB5_LIBS} -o butc;; \ esac tcmain.o: tcmain.c ${INCLS} AFS_component_version_number.c only in patch2: unchanged: --- openafs-1.4.12+dfsg.orig/src/bucoord/Makefile.in +++ openafs-1.4.12+dfsg/src/bucoord/Makefile.in @@ -52,7 +52,7 @@ $(BACKOBJS): bc.h ${TOP_INCDIR}/afs/butc.h backup: $(BACKOBJS) ${LIBS} - ${CC} ${CFLAGS} -o backup $(BACKOBJS) ${LIBS} ${XLIBS} + ${CC} ${CFLAGS} -o backup $(BACKOBJS) ${LIBS} ${XLIBS} ${KRB5_LIBS} bucoord_errs.c bc.h: bucoord_errs.et bc.p.h $(RM) -f bc.h bucoord_errs.c only in patch2: unchanged: --- openafs-1.4.12+dfsg.orig/src/util/dirpath.c +++ openafs-1.4.12+dfsg/src/util/dirpath.c @@ -366,6 +366,9 @@ pathp = dirPathArray[AFSDIR_SERVER_KRB_EXCL_FILEPATH_ID]; AFSDIR_SERVER_FILEPATH(pathp, AFSDIR_SERVER_ETC_DIR, AFSDIR_KRB_EXCL_FILE); + pathp = dirPathArray[AFSDIR_SERVER_RXKAD_KEYTAB_FILEPATH_ID]; + AFSDIR_SERVER_FILEPATH(pathp, AFSDIR_SERVER_ETC_DIR, AFSDIR_RXKAD_KEYTAB_FILE); + /* client file paths */ #ifdef AFS_NT40_ENV strcpy(dirPathArray[AFSDIR_CLIENT_THISCELL_FILEPATH_ID], only in patch2: unchanged: --- openafs-1.4.12+dfsg.orig/src/util/dirpath.hin +++ openafs-1.4.12+dfsg/src/util/dirpath.hin @@ -145,6 +145,7 @@ #define AFSDIR_VOLSERLOG_FILE "VolserLog" #define AFSDIR_AUDIT_FILE "Audit" #define AFSDIR_KRB_EXCL_FILE "krb.excl" +#define AFSDIR_RXKAD_KEYTAB_FILE "rxkad.keytab" #define AFSDIR_ROOTVOL_FILE "RootVolume" #define AFSDIR_HOSTDUMP_FILE "hosts.dump" @@ -264,6 +265,7 @@ AFSDIR_SERVER_BIN_FILE_DIRPATH_ID, AFSDIR_CLIENT_CELLALIAS_FILEPATH_ID, AFSDIR_SERVER_KRB_EXCL_FILEPATH_ID, + AFSDIR_SERVER_RXKAD_KEYTAB_FILEPATH_ID, AFSDIR_PATHSTRING_MAX } afsdir_id_t; /* getDirPath() returns a pointer to a string from an internal array of path strings @@ -332,6 +334,7 @@ #define AFSDIR_SERVER_THRESHOLD_CONSTANTS_FILEPATH getDirPath(AFSDIR_SERVER_THRESHOLD_CONSTANTS_FILEPATH_ID) #define AFSDIR_SERVER_MIGRATELOG_FILEPATH getDirPath(AFSDIR_SERVER_MIGRATELOG_FILEPATH_ID) #define AFSDIR_SERVER_KRB_EXCL_FILEPATH getDirPath(AFSDIR_SERVER_KRB_EXCL_FILEPATH_ID) +#define AFSDIR_SERVER_RXKAD_KEYTAB_FILEPATH getDirPath(AFSDIR_SERVER_RXKAD_KEYTAB_FILEPATH_ID) /* client file paths */ #define AFSDIR_CLIENT_THISCELL_FILEPATH getDirPath(AFSDIR_CLIENT_THISCELL_FILEPATH_ID) only in patch2: unchanged: --- openafs-1.4.12+dfsg.orig/src/bozo/bosserver.c +++ openafs-1.4.12+dfsg/src/bozo/bosserver.c @@ -1005,6 +1005,10 @@ bozo_rxsc[1] = (struct rx_securityClass *)0; bozo_rxsc[2] = rxkad_NewServerSecurityObject(0, tdir, afsconf_GetKey, NULL); +#ifdef USE_RXKAD_KEYTAB + if (rxkad_InitKeytabDecrypt(AFSDIR_SERVER_RXKAD_KEYTAB_FILEPATH) == 0) + rxkad_BindKeytabDecrypt(bozo_rxsc[2]); +#endif /* Disable jumbograms */ rx_SetNoJumbo(); only in patch2: unchanged: --- openafs-1.4.12+dfsg.orig/src/bozo/Makefile.in +++ openafs-1.4.12+dfsg/src/bozo/Makefile.in @@ -78,12 +78,12 @@ bos.o: bos.c ${INCLS} AFS_component_version_number.o bos: bos.o $(LIBS) libbos.a - ${CC} ${CFLAGS} -o bos bos.o libbos.a $(LIBS) ${XLIBS} + ${CC} ${CFLAGS} -o bos bos.o libbos.a $(LIBS) ${XLIBS} ${KRB5_LIBS} bos_util.o: bos_util.c ${INCLS} AFS_component_version_number.o bos_util: bos_util.o $(LIBS) - ${CC} ${CFLAGS} -o bos_util bos_util.o $(LIBS) ${XLIBS} + ${CC} ${CFLAGS} -o bos_util bos_util.o $(LIBS) ${XLIBS} ${KRB5_LIBS} ezbnodeops.o: ezbnodeops.c ${INCLS} @@ -95,7 +95,7 @@ $(RANLIB) $@ bosserver: $(OBJS) $(LIBS) - ${CC} $(CFLAGS) -o bosserver $(OBJS) ${TOP_LIBDIR}/libaudit.a $(LIBS) ${XLIBS} + ${CC} $(CFLAGS) -o bosserver $(OBJS) ${TOP_LIBDIR}/libaudit.a $(LIBS) ${XLIBS} ${KRB5_LIBS} # # Install targets only in patch2: unchanged: --- openafs-1.4.12+dfsg.orig/src/auth/authcon.c +++ openafs-1.4.12+dfsg/src/auth/authcon.c @@ -45,10 +45,18 @@ #include #include #include +#if defined(USE_RXKAD_KEYTAB) && !defined(UKERNEL) +#include +#include +#endif #include +#include #include "cellconfig.h" #include "keys.h" #include "auth.h" +#if defined(USE_RXKAD_KEYTAB) && !defined(UKERNEL) +#include "akimpersonate.h" +#endif #endif /* defined(UKERNEL) */ /* return a null security object if nothing else can be done */ @@ -71,12 +79,30 @@ { register struct rx_securityClass *tclass; +#ifdef USE_RXKAD_KEYTAB + int keytab_enable = 0; + char *keytab_name; + size_t ktlen; + ktlen = 5 + strlen(adir->name) + 1 + strlen(AFSDIR_RXKAD_KEYTAB_FILE) + 1; + keytab_name = malloc(ktlen); + if (keytab_name != NULL) { + strcompose(keytab_name, ktlen, "FILE:", adir->name, "/", + AFSDIR_RXKAD_KEYTAB_FILE, (char *)NULL); + if (rxkad_InitKeytabDecrypt(keytab_name) == 0) + keytab_enable = 1; + free(keytab_name); + } +#endif LOCK_GLOBAL_MUTEX; tclass = (struct rx_securityClass *) rxkad_NewServerSecurityObject(0, adir, afsconf_GetKey, NULL); if (tclass) { *astr = tclass; *aindex = 2; /* kerberos security index */ +#ifdef USE_RXKAD_KEYTAB + if (keytab_enable) + rxkad_BindKeytabDecrypt(tclass); +#endif UNLOCK_GLOBAL_MUTEX; return 0; } else { @@ -86,6 +112,77 @@ } #endif /* !defined(UKERNEL) */ +#if defined(USE_RXKAD_KEYTAB) && !defined(UKERNEL) +static afs_int32 +K5Auth(struct afsconf_dir *adir, + struct rx_securityClass **astr, + afs_int32 *aindex, + rxkad_level enclevel) +{ + struct rx_securityClass *tclass; + krb5_context context = NULL; + krb5_creds* fake_princ = NULL; + krb5_principal service_princ = NULL; + krb5_principal client_princ = NULL; + krb5_error_code r = 0; + struct ktc_encryptionKey session; + char *keytab_name = NULL; + size_t ktlen; + + ktlen = 5 + strlen(adir->name) + 1 + strlen(AFSDIR_RXKAD_KEYTAB_FILE) + 1; + keytab_name = malloc(ktlen); + if (!keytab_name) { + return errno; + } + strcompose(keytab_name, ktlen, "FILE:", adir->name, "/", + AFSDIR_RXKAD_KEYTAB_FILE, (char *)NULL); + + r = krb5_init_context(&context); + if (r) + goto cleanup; + + r = krb5_build_principal(context, &client_princ, 1, "\0", "afs", NULL); + if (r) + goto cleanup; + + r = get_credv5_akimpersonate(context, keytab_name, + NULL, client_princ, + 0, 0x7fffffff, + NULL, + &fake_princ); + + if (r == 0) { + if (tkt_DeriveDesKey(get_creds_enctype(fake_princ), + get_cred_keydata(fake_princ), + get_cred_keylen(fake_princ), + &session) != 0) { + r = RXKADBADKEY; + goto cleanup; + } + tclass = (struct rx_securityClass *) + rxkad_NewClientSecurityObject(enclevel, &session, + RXKAD_TKT_TYPE_KERBEROS_V5, + fake_princ->ticket.length, + fake_princ->ticket.data); + if (tclass != NULL) { + *astr = tclass; + *aindex = 2; + r = 0; + goto cleanup; + } + r = 1; + } + +cleanup: + free(keytab_name); + if (fake_princ != NULL) + krb5_free_creds(context, fake_princ); + if (context != NULL) + krb5_free_context(context); + return r; +} +#endif + static afs_int32 GenericAuth(struct afsconf_dir *adir, struct rx_securityClass **astr, @@ -99,6 +196,13 @@ afs_int32 ticketLen; register afs_int32 code; +#if defined(USE_RXKAD_KEYTAB) && !defined(UKERNEL) + /* Try to do things the v5 way, before switching down to v4 */ + code = K5Auth(adir, astr, aindex, enclevel); + if (code == 0) + return 0; +#endif + /* first, find the right key and kvno to use */ code = afsconf_GetLatestKey(adir, &kvno, &key); if (code) { only in patch2: unchanged: --- openafs-1.4.12+dfsg.orig/src/auth/akimpersonate.h +++ openafs-1.4.12+dfsg/src/auth/akimpersonate.h @@ -0,0 +1,21 @@ +#ifndef __AKIMPERSONATE_H__ +#define __AKIMPERSONATE_H__ + +#if defined(HAVE_KRB5_CREDS_KEYBLOCK) +#define get_cred_keydata(c) ((c)->keyblock.contents) +#define get_cred_keylen(c) ((c)->keyblock.length) +#define get_creds_enctype(c) ((c)->keyblock.enctype) +#elif defined(HAVE_KRB5_CREDS_SESSION) +#define get_cred_keydata(c) ((c)->session.keyvalue.data) +#define get_cred_keylen(c) ((c)->session.keyvalue.length) +#define get_creds_enctype(c) ((c)->session.keytype) +#else +#error "Must have either keyblock or session member of krb5_creds" +#endif + +/* The caller must include krb5.h to get prototypes for the types used. */ +krb5_error_code +get_credv5_akimpersonate(krb5_context, char*, krb5_principal, krb5_principal, + time_t, time_t, const int *, krb5_creds**); + +#endif only in patch2: unchanged: --- openafs-1.4.12+dfsg.orig/src/auth/akimpersonate.c +++ openafs-1.4.12+dfsg/src/auth/akimpersonate.c @@ -0,0 +1,765 @@ +/* + * Copyright (c) 2005, 2006 + * The Linux Box Corporation + * ALL RIGHTS RESERVED + * + * Permission is granted to use, copy, create derivative works + * and redistribute this software and such derivative works + * for any purpose, so long as the name of the Linux Box + * Corporation is not used in any advertising or publicity + * pertaining to the use or distribution of this software + * without specific, written prior authorization. If the + * above copyright notice or any other identification of the + * Linux Box Corporation is included in any copy of any + * portion of this software, then the disclaimer below must + * also be included. + * + * This software is provided as is, without representation + * from the Linux Box Corporation as to its fitness for any + * purpose, and without warranty by the Linux Box Corporation + * of any kind, either express or implied, including + * without limitation the implied warranties of + * merchantability and fitness for a particular purpose. The + * regents of the Linux Box Corporation shall not be liable + * for any damages, including special, indirect, incidental, or + * consequential damages, with respect to any claim arising + * out of or in connection with the use of the software, even + * if it has been or is hereafter advised of the possibility of + * such damages. + */ +/* + * Copyright (C) 2013 by Alexander Chernyakhovsky and the + * Massachusetts Institute of Technology. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include + +#include +#include +#include +#include + +#include "akimpersonate.h" +#include "akimpersonate_v5gen.h" + +#ifdef HAVE_KRB5_CREDS_KEYBLOCK +#define USING_MIT 1 +#endif +#ifdef HAVE_KRB5_CREDS_SESSION +#define USING_HEIMDAL 1 +#endif + +#if USING_HEIMDAL +#define deref_keyblock_enctype(kb) ((kb)->keytype) +#define deref_entry_keyblock(entry) ((entry)->keyblock) +#define deref_session_key(creds) ((creds)->session) +#define deref_enc_tkt_addrs(tkt) ((tkt)->caddr) +#define deref_enc_data(enc) ((enc)->cipher.data) +#else +#define deref_keyblock_enctype(kb) ((kb)->enctype) +#define deref_entry_keyblock(entry) ((entry)->key) +#define deref_session_key(creds) ((creds)->keyblock) +#define deref_enc_tkt_addrs(tkt) ((tkt)->caddrs) +#define deref_enc_data(enc) ((enc)->ciphertext.data) +#endif +#if HAVE_DECL_KRB5_FREE_KEYTAB_ENTRY_CONTENTS +/* nothing */ +#elif HAVE_DECL_KRB5_KT_FREE_ENTRY +#define krb5_free_keytab_entry_contents krb5_kt_free_entry +#else +static inline int +krb5_free_keytab_entry_contents(krb5_context ctx, krb5_keytab_entry * ent) +{ + krb5_free_principal(ctx, ent->principal); + krb5_free_keyblock_contents(ctx, kte_keyblock(ent)); + return 0; +} +#endif + +#define deref_entry_enctype(entry) \ + deref_keyblock_enctype(&deref_entry_keyblock(entry)) + +#ifdef USING_MIT +# if !defined(HAVE_ENCODE_KRB5_TICKET) +/* + * Solaris doesn't have encode_krb5_ticket and encode_krb5_enc_tkt_part, so we + * need to implement our own. The akv5gen_* functions below are implemented + * using v5gen code; so, they need to have no krb5 structures in their + * arguments, since using system krb5 headers at the same time as v5gen + * headers is problematic. That's why the ticket contents are exploded. + */ +static krb5_error_code +encode_krb5_ticket(krb5_ticket *rep, krb5_data **a_out) +{ + krb5_error_code code = 0; + int i; + char **names = NULL; + krb5_data *out = NULL; + size_t out_len = 0; + char *out_data = NULL; + + *a_out = NULL; + + out = calloc(1, sizeof(*out)); + if (!out) { + code = ENOMEM; + goto cleanup; + } + + names = calloc(rep->server->length, sizeof(names[0])); + if (names == NULL) { + code = ENOMEM; + goto cleanup; + } + + for (i = 0; i < rep->server->length; i++) { + names[i] = rep->server->data[i].data; + } + + code = akv5gen_encode_krb5_ticket(rep->enc_part.kvno, + rep->server->realm.data, + rep->server->type, + rep->server->length, + names, + rep->enc_part.enctype, + rep->enc_part.ciphertext.length, + rep->enc_part.ciphertext.data, + &out_len, + &out_data); + if (code != 0) { + goto cleanup; + } + + out->length = out_len; + out->data = out_data; + *a_out = out; + out = NULL; + + cleanup: + free(names); + free(out); + return code; +} +# endif /* !HAVE_ENCODE_KRB5_TICKET */ + +# if !defined(HAVE_ENCODE_KRB5_ENC_TKT_PART) +static krb5_error_code +encode_krb5_enc_tkt_part(krb5_enc_tkt_part *encpart, krb5_data **a_out) +{ + krb5_error_code code = 0; + int i; + char **names = NULL; + krb5_data *out = NULL; + size_t out_len = 0; + char *out_data = NULL; + + *a_out = NULL; + + out = calloc(1, sizeof(*out)); + if (out == NULL) { + code = ENOMEM; + goto cleanup; + } + + names = calloc(encpart->client->length, sizeof(names[0])); + if (names == NULL) { + code = ENOMEM; + goto cleanup; + } + + for (i = 0; i < encpart->client->length; i++) + names[i] = encpart->client->data[i].data; + + if (encpart->flags != TKT_FLG_INITIAL) { + /* We assume the ticket has the flag _INITIAL set, and only that flag. + * passing each individual flag to akv5gen would be really ugly, and + * should be unnecessary. */ + goto invalid; + } + if (encpart->caddrs != NULL && encpart->caddrs[0] != NULL) + goto invalid; + if (encpart->authorization_data && encpart->authorization_data[0]) + goto invalid; + + code = akv5gen_encode_krb5_enc_tkt_part(encpart->session->enctype, + encpart->session->length, + encpart->session->contents, + encpart->client->realm.data, + encpart->client->type, + encpart->client->length, + names, + encpart->transited.tr_type, + encpart->transited.tr_contents.length, + encpart->transited.tr_contents.data, + encpart->times.authtime, + encpart->times.starttime, + encpart->times.endtime, + encpart->times.renew_till, + &out_len, + &out_data); + if (code != 0) + goto cleanup; + + out->length = out_len; + out->data = out_data; + *a_out = out; + out = NULL; + + cleanup: + free(names); + free(out); + return code; + + invalid: + /* XXX or assert, or ...? */ + code = EINVAL; + goto cleanup; +} +# endif /* !HAVE_ENCODE_KRB5_ENC_TKT_PART */ + +# if !defined(HAVE_KRB5_ENCRYPT_TKT_PART) +krb5_error_code +krb5_encrypt_tkt_part(krb5_context context, + const krb5_keyblock *key, + krb5_ticket *ticket) +{ + krb5_data *data = 0; + int code; + size_t enclen; + + if ((code = encode_krb5_enc_tkt_part(ticket->enc_part2, &data))) + goto Done; + if ((code = krb5_c_encrypt_length(context, key->enctype, + data->length, &enclen))) + goto Done; + ticket->enc_part.ciphertext.length = enclen; + if (!(ticket->enc_part.ciphertext.data = malloc(enclen))) { + code = ENOMEM; + goto Done; + } + if ((code = krb5_c_encrypt(context, key, KRB5_KEYUSAGE_KDC_REP_TICKET, + 0, data, &ticket->enc_part))) { + free(ticket->enc_part.ciphertext.data); + ticket->enc_part.ciphertext.data = 0; + } +Done: + if (data) { + if (data->data) + free(data->data); + free(data); + } + return code; +} +# endif /* HAVE_KRB5_ENCRYPT_TKT_PART */ +#endif /* USING_MIT */ + +static const int any_enctype[2] = {0, 0}; +static const krb5_data empty_string; + +/* + * Routines to allocate/free the extra storage involved in a ticket structure. + * When changing one, ensure that the other is changed to reflect the + * allocation contract. + */ +static int +alloc_ticket(void **out) +{ +#if USING_HEIMDAL + Ticket *ticket_reply; +#else + krb5_ticket *ticket_reply; +#endif + + /* requisite aliasing for MIT/Heimdal support. */ + ticket_reply = *out = calloc(1, sizeof(*ticket_reply)); + if (ticket_reply == NULL) + return ENOMEM; + +#if USING_HEIMDAL + ticket_reply->enc_part.kvno = malloc(sizeof(*ticket_reply->enc_part.kvno)); + if (ticket_reply->enc_part.kvno == NULL) + return ENOMEM; +#else + /* No allocations needed for MIT's krb5_ticket structure. */ +#endif + return 0; +} + +static void +free_ticket(void *in) +{ +#if USING_HEIMDAL + Ticket *ticket_reply; +#else + krb5_ticket *ticket_reply; +#endif + + /* requisite aliasing for MIT/Heimdal support. */ + ticket_reply = in; + if (ticket_reply == NULL) + return; + +#if USING_HEIMDAL + if (ticket_reply->enc_part.kvno != NULL) + free(ticket_reply->enc_part.kvno); +#else + /* No allocations needed for MIT's krb5_ticket structure. */ +#endif + free(ticket_reply); +} + +/* + * Routines to allocate/free the extra storage involved in an encrypted + * ticket part structure. + * When changing one, ensure that the other is changed to reflect the + * allocation contract. + */ +static int +alloc_enc_tkt_part(void **out) +{ +#if USING_HEIMDAL + EncTicketPart *enc_tkt_reply; +#else + krb5_enc_tkt_part *enc_tkt_reply; +#endif + + /* Aliasing for MIT/Heimdal support. */ + enc_tkt_reply = *out = calloc(1, sizeof(*enc_tkt_reply)); + if (enc_tkt_reply == NULL) + return ENOMEM; + +#if USING_HEIMDAL + enc_tkt_reply->starttime = malloc(sizeof(*enc_tkt_reply->starttime)); + if (enc_tkt_reply->starttime == NULL) + return ENOMEM; +#else + /* No allocations needed for MIT's krb5_enc_tkt_part structure. */ +#endif + return 0; +} +static void +free_enc_tkt_part(void *in) +{ +#if USING_HEIMDAL + EncTicketPart *enc_tkt_reply; +#else + krb5_enc_tkt_part *enc_tkt_reply; +#endif + + /* Aliasing for MIT/Heimdal support. */ + enc_tkt_reply = in; + if (enc_tkt_reply == NULL) + return; + +#if USING_HEIMDAL + if (enc_tkt_reply->starttime != NULL) + free(enc_tkt_reply->starttime); +#else + /* No allocations needed for MIT's krb5_enc_tkt_part structure. */ +#endif + free(enc_tkt_reply); +} + +/* + * Given a keytab, extract the principal name of the (first) entry with + * the highest kvno in the keytab. This provides compatibility with the + * rxkad KeyFile behavior of always using the highest kvno entry when + * printing tickets. We could return the kvno as well, but krb5_kt_get_entry + * can find the highest kvno on its own. + * + * Returns 0 on success, krb5 errors on failure. + */ +static int +pick_principal(krb5_context context, krb5_keytab kt, + krb5_principal *service_principal) +{ + krb5_error_code code; + krb5_kvno vno = 0; + krb5_kt_cursor c; + krb5_keytab_entry n_entry; + + /* Nothing to do */ + if (*service_principal != NULL) + return 0; + + memset(&n_entry, 0, sizeof(n_entry)); + + code = krb5_kt_start_seq_get(context, kt, &c); + if (code != 0) + goto cleanup; + while (code == 0 && krb5_kt_next_entry(context, kt, &n_entry, &c) == 0) { + if (n_entry.vno > vno) { + vno = n_entry.vno; + (void)krb5_free_principal(context, *service_principal); + code = krb5_copy_principal(context, n_entry.principal, + service_principal); + } + (void)krb5_free_keytab_entry_contents(context, &n_entry); + } + if (code != 0) { + (void)krb5_kt_end_seq_get(context, kt, &c); + goto cleanup; + } + code = krb5_kt_end_seq_get(context, kt, &c); + +cleanup: + return code; +} + +/* + * Given a keytab and a list of allowed enctypes, and optionally a known + * service principal, choose an appropriate enctype, and choose a + * service principal if one was not given. Return the keytab entry + * corresponding to this service principal and enctype. + * + * The list of allowed enctypes must be zero-terminated. + */ +static int +pick_enctype_and_principal(krb5_context context, krb5_keytab kt, + const int *allowed_enctypes, krb5_enctype *enctype, + krb5_principal *service_principal, + krb5_keytab_entry *entry) +{ + krb5_error_code code; + int i; + + if (*service_principal == NULL) { + code = pick_principal(context, kt, service_principal); + if (code != 0) { + goto cleanup; + } + } + + /* We always have a service_principal, now. */ + i = 0; + do { + *enctype = allowed_enctypes[i]; + code = krb5_kt_get_entry(context, kt, *service_principal, 0 /* any */, + *enctype, entry); + if (code == 0) { + if (*enctype == 0) + *enctype = deref_entry_enctype(entry); + break; + } + ++i; + } while(allowed_enctypes[i] != 0); + if (code != 0) + goto cleanup; + +cleanup: + return code; +} + +/* + * Populate the encrypted part of the ticket. + */ +static void +populate_enc_tkt(krb5_keyblock *session_key, krb5_principal client_principal, + time_t starttime, time_t endtime, void *out) +{ +#if USING_HEIMDAL + EncTicketPart *enc_tkt_reply; +#else + krb5_enc_tkt_part *enc_tkt_reply; +#endif + int i; + + /* Alias through void* since Heimdal and MIT's types differ. */ + enc_tkt_reply = out; + +#if USING_HEIMDAL + enc_tkt_reply->flags.initial = 1; + enc_tkt_reply->transited.tr_type = DOMAIN_X500_COMPRESS; + enc_tkt_reply->cname = client_principal->name; + enc_tkt_reply->crealm = client_principal->realm; + enc_tkt_reply->key = *session_key; + enc_tkt_reply->transited.contents = empty_string; + enc_tkt_reply->authtime = starttime; + *enc_tkt_reply->starttime = starttime; + enc_tkt_reply->endtime = endtime; +#else + enc_tkt_reply->magic = KV5M_ENC_TKT_PART; + enc_tkt_reply->flags |= TKT_FLG_INITIAL; + enc_tkt_reply->transited.tr_type = KRB5_DOMAIN_X500_COMPRESS; + enc_tkt_reply->session = session_key; + enc_tkt_reply->client = client_principal; + enc_tkt_reply->transited.tr_contents = empty_string; + enc_tkt_reply->times.authtime = starttime; + enc_tkt_reply->times.starttime = starttime; /* krb524init needs this */ + enc_tkt_reply->times.endtime = endtime; +#endif /* USING_HEIMDAL */ +} + +/* + * Encrypt the provided enc_tkt_part structure with the key from the keytab + * entry entry, and place the resulting blob in the ticket_reply structure. + */ +static int +encrypt_enc_tkt(krb5_context context, krb5_principal service_principal, + krb5_keytab_entry *entry, void *tr_out, void *er_in) +{ + krb5_error_code code; +#if USING_HEIMDAL + Ticket *ticket_reply; + EncTicketPart *enc_tkt_reply; + krb5_crypto crypto = 0; + unsigned char *buf = 0; + size_t buf_size, buf_len; +#else + krb5_ticket *ticket_reply; + krb5_enc_tkt_part *enc_tkt_reply; +#endif + + /* Requisite aliasing for Heimdal/MIT support. */ + ticket_reply = tr_out; + enc_tkt_reply = er_in; + +#if USING_HEIMDAL + ticket_reply->sname = service_principal->name; + ticket_reply->realm = service_principal->realm; + + ASN1_MALLOC_ENCODE(EncTicketPart, buf, buf_size, enc_tkt_reply, + &buf_len, code); + if (code != 0) + goto cleanup; + + if (buf_len != buf_size) + goto cleanup; + code = krb5_crypto_init(context, + &deref_entry_keyblock(entry), + deref_entry_enctype(entry), + &crypto); + if (code != 0) + goto cleanup; + code = krb5_encrypt_EncryptedData(context, crypto, KRB5_KU_TICKET, buf, + buf_len, entry->vno, + &(ticket_reply->enc_part)); + if (code != 0) + goto cleanup; + ticket_reply->enc_part.etype = deref_entry_enctype(entry); + *ticket_reply->enc_part.kvno = entry->vno; + ticket_reply->tkt_vno = 5; +#else + ticket_reply->server = service_principal; + ticket_reply->enc_part2 = enc_tkt_reply; + code = krb5_encrypt_tkt_part(context, &deref_entry_keyblock(entry), + ticket_reply); + if (code != 0) + goto cleanup; + ticket_reply->enc_part.kvno = entry->vno; +#endif + +cleanup: +#if USING_HEIMDAL + if (buf != NULL) + free(buf); + if (crypto != NULL) + krb5_crypto_destroy(context, crypto); +#endif + return code; +} + +/* + * Populate the credentials structure corresponding to the ticket we are + * printing. + */ +static int +populate_creds(krb5_context context, krb5_principal service_principal, + krb5_principal client_principal, krb5_keyblock *session_key, + void *tr_in, void *er_in, krb5_creds *creds) +{ + krb5_error_code code; +#if USING_HEIMDAL + Ticket *ticket_reply; + EncTicketPart *enc_tkt_reply; + size_t dummy; +#else + krb5_ticket *ticket_reply; + krb5_enc_tkt_part *enc_tkt_reply; + krb5_data *temp = NULL; +#endif + + /* Requisite aliasing for Heimdal/MIT support. */ + ticket_reply = tr_in; + enc_tkt_reply = er_in; + + code = krb5_copy_principal(context, service_principal, &creds->server); + if (code != 0) + goto cleanup; + code = krb5_copy_principal(context, client_principal, &creds->client); + if (code != 0) + goto cleanup; + code = krb5_copy_keyblock_contents(context, session_key, + &deref_session_key(creds)); + if (code != 0) + goto cleanup; + +#if USING_HEIMDAL + creds->times.authtime = enc_tkt_reply->authtime; + creds->times.starttime = *(enc_tkt_reply->starttime); + creds->times.endtime = enc_tkt_reply->endtime; + creds->times.renew_till = 0; /* *(enc_tkt_reply->renew_till) */ + creds->flags.b = enc_tkt_reply->flags; +#else + creds->times = enc_tkt_reply->times; + creds->ticket_flags = enc_tkt_reply->flags; +#endif + +#if USING_HEIMDAL + ASN1_MALLOC_ENCODE(Ticket, creds->ticket.data, creds->ticket.length, + ticket_reply, &dummy, code); + if (code != 0 || dummy != creds->ticket.length) + goto cleanup; +#else + code = encode_krb5_ticket(ticket_reply, &temp); + if (code != 0) + goto cleanup; + creds->ticket = *temp; +#endif + +cleanup: +#if USING_HEIMDAL + /* nothing */ +#else + free(temp); +#endif + return code; +} + +/* + * Print a krb5 ticket in our service key, for the supplied client principal. + * The path to a keytab is mandatory, but the service principal may be + * guessed from the keytab contents if desired. The keytab entry must be + * one of the allowed_enctypes (a zero-terminated list) if a non-NULL + * parameter is passed. + */ +krb5_error_code +get_credv5_akimpersonate(krb5_context context, char* keytab, + krb5_principal service_principal, + krb5_principal client_principal, time_t starttime, + time_t endtime, const int *allowed_enctypes, + krb5_creds** out_creds /* out */ ) +{ + krb5_error_code code; + krb5_keytab kt = 0; + krb5_keytab_entry entry[1]; + krb5_creds *creds = 0; + krb5_enctype enctype; + krb5_keyblock session_key[1]; +#if USING_HEIMDAL + Ticket *ticket_reply; + EncTicketPart *enc_tkt_reply; +#else + krb5_ticket *ticket_reply; + krb5_enc_tkt_part *enc_tkt_reply; +#endif + int i; + *out_creds = NULL; + enctype = 0; /* AKIMPERSONATE_IGNORE_ENCTYPE */ + memset(entry, 0, sizeof *entry); + memset(session_key, 0, sizeof *session_key); + ticket_reply = NULL; + enc_tkt_reply = NULL; + + creds = calloc(1, sizeof(*creds)); + if (creds == NULL) { + code = ENOMEM; + goto cleanup; + } + code = alloc_ticket(&ticket_reply); + if (code != 0) + goto cleanup; + code = alloc_enc_tkt_part(&enc_tkt_reply); + if (code != 0) + goto cleanup; + /* Empty list of allowed etypes must fail. Do it here to avoid issues. */ + if (allowed_enctypes != NULL && *allowed_enctypes == 0) { + code = KRB5_BAD_ENCTYPE; + goto cleanup; + } + if (allowed_enctypes == NULL) + allowed_enctypes = any_enctype; + + if (keytab != NULL) + code = krb5_kt_resolve(context, keytab, &kt); + else + code = krb5_kt_default(context, &kt); + if (code != 0) + goto cleanup; + + code = pick_enctype_and_principal(context, kt, allowed_enctypes, + &enctype, &service_principal, entry); + if (code != 0) + goto cleanup; + + /* Conjure up a random session key */ + deref_keyblock_enctype(session_key) = enctype; +#if USING_HEIMDAL + code = krb5_generate_random_keyblock(context, enctype, session_key); +#else + code = krb5_c_make_random_key(context, enctype, session_key); +#endif + if (code != 0) + goto cleanup; + + populate_enc_tkt(session_key, client_principal, starttime, endtime, + enc_tkt_reply); + + code = encrypt_enc_tkt(context, service_principal, entry, ticket_reply, + enc_tkt_reply); + if (code != 0) + goto cleanup; + + code = populate_creds(context, service_principal, client_principal, + session_key, ticket_reply, enc_tkt_reply, creds); + if (code != 0) + goto cleanup; + + /* return creds */ + *out_creds = creds; + creds = NULL; +cleanup: + if (deref_enc_data(&ticket_reply->enc_part) != NULL) + free(deref_enc_data(&ticket_reply->enc_part)); + krb5_free_keytab_entry_contents(context, entry); + if (client_principal != NULL) + krb5_free_principal(context, client_principal); + if (service_principal != NULL) + krb5_free_principal(context, service_principal); + if (kt != NULL) + krb5_kt_close(context, kt); + if (creds != NULL) + krb5_free_creds(context, creds); + krb5_free_keyblock_contents(context, session_key); + free_ticket(ticket_reply); + free_enc_tkt_part(enc_tkt_reply); + return code; +} only in patch2: unchanged: --- openafs-1.4.12+dfsg.orig/src/auth/akimpersonate_v5gen.h +++ openafs-1.4.12+dfsg/src/auth/akimpersonate_v5gen.h @@ -0,0 +1,30 @@ +#ifndef __AKIMPERSONATE_V5GEN_H__ +#define __AKIMPERSONATE_V5GEN_H__ +extern int akv5gen_encode_krb5_ticket(int kvno, + char *realm, + int name_type, + int name_len, + char **name_parts, + int enctype, + size_t cipher_len, + char *cipher_data, + size_t *a_out_len, + char **a_out_data); + +extern int akv5gen_encode_krb5_enc_tkt_part(int enctype, + size_t key_len, + char *key_data, + char *realm, + int name_type, + int name_len, + char **name_parts, + int transited_type, + int transited_len, + char *transited_data, + time_t authtime, + time_t starttime, + time_t endtime, + time_t renew_till, + size_t *a_out_len, + char **a_out_data); +#endif only in patch2: unchanged: --- openafs-1.4.12+dfsg.orig/src/auth/akimpersonate_v5gen.c +++ openafs-1.4.12+dfsg/src/auth/akimpersonate_v5gen.c @@ -0,0 +1,176 @@ +/* + * Copyright (c) 2013 Sine Nomine Associates + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include + +/* are we using MIT krb5, and are we missing the functions encode_krb5_ticket + * and encode_krb5_enc_tkt_part? */ +#if defined(HAVE_KRB5_CREDS_KEYBLOCK) && !defined(HAVE_KRB5_CREDS_SESSION) \ + && !defined(HAVE_ENCODE_KRB5_TICKET) && !defined(HAVE_ENCODE_KRB5_ENC_TKT_PART) + +# include + +# include +# include +# include +# include +# include +# include +# include +# include +# include + +# include "lifetimes.h" +# include "rxkad.h" + +# include "v5gen-rewrite.h" +# include "v5gen.h" +# include "der.h" + +# include "akimpersonate_v5gen.h" + +int +akv5gen_encode_krb5_ticket(int kvno, + char *realm, + int name_type, + int name_len, + char **name_parts, + int enctype, + size_t cipher_len, + char *cipher_data, + size_t *a_out_len, + char **a_out_data) +{ + Ticket v5gen_tkt; + int code = 0; + size_t dummy; + char *outdata = NULL; + size_t outlen = 0; + + memset(&v5gen_tkt, 0, sizeof(v5gen_tkt)); + + v5gen_tkt.tkt_vno = 5; + v5gen_tkt.realm = realm; + + v5gen_tkt.sname.name_type = name_type; + v5gen_tkt.sname.name_string.len = name_len; + v5gen_tkt.sname.name_string.val = name_parts; + + v5gen_tkt.enc_part.etype = enctype; + v5gen_tkt.enc_part.kvno = &kvno; + v5gen_tkt.enc_part.cipher.length = cipher_len; + v5gen_tkt.enc_part.cipher.data = cipher_data; + + ASN1_MALLOC_ENCODE(Ticket, outdata, outlen, + &v5gen_tkt, &dummy, code); + if (code == 0 && dummy != outlen) + code = EINVAL; /* XXX what error should this be? */ + if (code) + goto cleanup; + + *a_out_len = outlen; + *a_out_data = outdata; + outdata = NULL; + + cleanup: + free(outdata); + return code; +} + +int +akv5gen_encode_krb5_enc_tkt_part(int enctype, + size_t key_len, + char *key_data, + char *realm, + int name_type, + int name_len, + char **name_parts, + int transited_type, + int transited_len, + char *transited_data, + time_t authtime, + time_t starttime, + time_t endtime, + time_t renew_till, + size_t *a_out_len, + char **a_out_data) +{ + EncTicketPart v5gen_enc; + size_t dummy; + int i; + int code = 0; + char *outdata = NULL; + size_t outlen = 0; + + memset(&v5gen_enc, 0, sizeof(v5gen_enc)); + + /* assume the only flag that should be set is _INITIAL */ + v5gen_enc.flags.initial = 1; + + v5gen_enc.key.keytype = enctype; + v5gen_enc.key.keyvalue.length = key_len; + v5gen_enc.key.keyvalue.data = key_data; + + v5gen_enc.crealm = realm; + + v5gen_enc.cname.name_type = name_type; + v5gen_enc.cname.name_string.len = name_len; + v5gen_enc.cname.name_string.val = name_parts; + + v5gen_enc.transited.tr_type = transited_type; + v5gen_enc.transited.contents.length = transited_len; + v5gen_enc.transited.contents.data = transited_data; + + v5gen_enc.authtime = authtime; + v5gen_enc.starttime = &starttime; + v5gen_enc.endtime = endtime; + v5gen_enc.renew_till = &renew_till; + + /* assume we have no addresses */ + v5gen_enc.caddr = NULL; + + /* assume we have no authz data */ + v5gen_enc.authorization_data = NULL; + + ASN1_MALLOC_ENCODE(EncTicketPart, outdata, outlen, + &v5gen_enc, &dummy, code); + if (code == 0 && dummy != outlen) + code = EINVAL; /* XXX what error should this be? */ + if (code) + goto cleanup; + + *a_out_len = outlen; + *a_out_data = outdata; + outdata = NULL; + + cleanup: + free(outdata); + return code; +} + +#endif only in patch2: unchanged: --- openafs-1.4.12+dfsg.orig/src/auth/Makefile.in +++ openafs-1.4.12+dfsg/src/auth/Makefile.in @@ -9,15 +9,15 @@ include @TOP_OBJDIR@/src/config/Makefile.config OBJS= cellconfig.o ktc.o userok.o writeconfig.o authcon.o \ - acfg_errors.o ktc_errors.o + acfg_errors.o ktc_errors.o @MAKE_KRB5@ akimpersonate.o akimpersonate_v5gen.o KOBJS= cellconfig.o ktc.krb.o userok.o writeconfig.o authcon.o \ - acfg_errors.o ktc_errors.o + acfg_errors.o ktc_errors.o @MAKE_KRB5@ akimpersonate.o akimpersonate_v5gen.o LIBS=libauth.a \ ${TOP_LIBDIR}/librxkad.a ${TOP_LIBDIR}/libdes.a \ ${TOP_LIBDIR}/librx.a ${TOP_LIBDIR}/libsys.a \ ${TOP_LIBDIR}/liblwp.a ${TOP_LIBDIR}/util.a -INCLS=cellconfig.h auth.h keys.h +INCLS=cellconfig.h auth.h keys.h akimpersonate.h akimpersonate_v5gen.h KSRCS=auth.h UKSRCS=${KSRCS} cellconfig.h acfg_errors.c keys.h cellconfig.c \ ktc.c authcon.c ktc_errors.c @@ -30,13 +30,23 @@ depinstall: \ ${TOP_INCDIR}/afs/keys.h \ ${TOP_INCDIR}/afs/cellconfig.h \ + ${TOP_INCDIR}/afs/akimpersonate.h \ ${TOP_INCDIR}/afs/auth.h \ ${TOP_INCDIR}/afs/ktc.h cellconfig.o: cellconfig.c ${INCLS} ktc.o: ktc.c ${INCLS} ${TOP_INCDIR}/afs/vice.h writeconfig.o: writeconfig.c ${INCLS} + authcon.o: authcon.c ${INCLS} + ${CCOBJ} ${CFLAGS} -c ${srcdir}/authcon.c @KRB5CFLAGS@ + +akimpersonate.o: akimpersonate.c ${INCLS} + ${CCOBJ} ${CFLAGS} -c ${srcdir}/akimpersonate.c @KRB5CFLAGS@ + +akimpersonate_v5gen.o: akimpersonate_v5gen.c ${INCLS} + ${CCOBJ} ${CFLAGS} -c ${srcdir}/akimpersonate_v5gen.c @KRB5CFLAGS@ -I${srcdir}/../rxkad + userok.o: userok.c ${INCLS} cellconfig.o: cellconfig.c ${INCLS} copyauth.o: copyauth.c ${INCLS} AFS_component_version_number.o @@ -134,6 +144,9 @@ ${DEST}/include/afs/cellconfig.h: cellconfig.h ${INSTALL} $? $@ +${TOP_INCDIR}/afs/akimpersonate.h: akimpersonate.h + ${INSTALL} $? $@ + ${DESTDIR}${includedir}/afs/auth.h: auth.h ${INSTALL} $? $@ only in patch2: unchanged: --- openafs-1.4.12+dfsg.orig/src/libafsauthent/Makefile.in +++ openafs-1.4.12+dfsg/src/libafsauthent/Makefile.in @@ -32,7 +32,7 @@ writeconfig.o \ authcon.o \ ktc_errors.o \ - acfg_errors.o + acfg_errors.o @MAKE_KRB5@ akimpersonate.o akimpersonate_v5gen.o KAUTHOBJS = \ kauth.xdr.o \ @@ -63,7 +63,7 @@ fileutil.o RXKADOBJS = \ - rxkad_errs.o + rxkad_errs.o @MAKE_KRB5@ ticket5_keytab.o SYSOBJS = \ rmtsysc.o \ @@ -120,7 +120,13 @@ ${CCRULE} authcon.o: ${AUTH}/authcon.c - ${CCRULE} + ${CCRULE} @KRB5CFLAGS@ + +akimpersonate.o: ${AUTH}/akimpersonate.c + ${CCRULE} -I../auth @KRB5CFLAGS@ + +akimpersonate_v5gen.o: ${AUTH}/akimpersonate_v5gen.c + ${CCRULE} -I../auth @KRB5CFLAGS@ -I../rxkad ktc_errors.o: ${AUTH}/ktc_errors.c ${CCRULE} @@ -197,6 +203,9 @@ rxkad_errs.o: ${RXKAD}/rxkad_errs.c ${CCRULE} +ticket5_keytab.o: ${RXKAD}/ticket5_keytab.c + ${CCRULE} @KRB5CFLAGS@ + ptclient.o: ${PTSERVER}/ptclient.c ${CCRULE} only in patch2: unchanged: --- openafs-1.4.12+dfsg.orig/src/budb/Makefile.in +++ openafs-1.4.12+dfsg/src/budb/Makefile.in @@ -71,7 +71,7 @@ server.o: server.c budb_errs.h ${INCLS} AFS_component_version_number.c budb_server: $(SERVER_OBJS) ${LIBS} - ${CC} ${LDFLAGS} -o budb_server $(SERVER_OBJS) ${LIBS} ${XLIBS} + ${CC} ${LDFLAGS} -o budb_server $(SERVER_OBJS) ${LIBS} ${XLIBS} ${KRB5_LIBS} budb.cs.c: budb.rg ${RXGEN} -A -u -C -o $@ ${srcdir}/budb.rg only in patch2: unchanged: --- openafs-1.4.12+dfsg.orig/src/budb/server.c +++ openafs-1.4.12+dfsg/src/budb/server.c @@ -524,6 +524,10 @@ sca[RX_SCINDEX_KAD] = rxkad_NewServerSecurityObject(rxkad_clear, BU_conf, afsconf_GetKey, NULL); +#ifdef USE_RXKAD_KEYTAB + if (rxkad_InitKeytabDecrypt(AFSDIR_SERVER_RXKAD_KEYTAB_FILEPATH) == 0) + rxkad_BindKeytabDecrypt(sca[RX_SCINDEX_KAD]); +#endif /* Disable jumbograms */ rx_SetNoJumbo(); only in patch2: unchanged: --- openafs-1.4.12+dfsg.orig/src/config/Makefile.config.in +++ openafs-1.4.12+dfsg/src/config/Makefile.config.in @@ -43,6 +43,7 @@ FSINCLUDES = @FSINCLUDES@ KERN_DBG = @KERN_DBG@ KERN_OPTMZ = @KERN_OPTMZ@ +KRB5_LIBS = @KRB5LIBS@ LD = @LD@ LEX = @LEX@ LIB_AFSDB = @LIB_AFSDB@ only in patch2: unchanged: --- openafs-1.4.12+dfsg.orig/src/shlibafsrpc/mapfile +++ openafs-1.4.12+dfsg/src/shlibafsrpc/mapfile @@ -45,12 +45,14 @@ rxkad_GetServerInfo; rxkad_NewClientSecurityObject; rxkad_NewServerSecurityObject; + rxkad_SetAltDecryptProc; rxnull_NewClientSecurityObject; rxnull_NewServerSecurityObject; rxs_Release; time_to_life; tkt_CheckTimes; tkt_DecodeTicket; + tkt_DeriveDesKey; tkt_MakeTicket; xdrrx_create; hton_syserr_conv; only in patch2: unchanged: --- openafs-1.4.12+dfsg.orig/src/venus/Makefile.in +++ openafs-1.4.12+dfsg/src/venus/Makefile.in @@ -47,7 +47,7 @@ # Build targets # cacheout: cacheout.o - $(CC) ${CFLAGS} -o cacheout cacheout.o ${LIBS} ${XLIBS} ${CMLIBS} + $(CC) ${CFLAGS} -o cacheout cacheout.o ${LIBS} ${XLIBS} ${CMLIBS} ${KRB5_LIBS} cacheout.o: cacheout.c @@ -76,15 +76,15 @@ fs.o: fs.c ${INCLS} AFS_component_version_number.c fs: fs.o $(LIBS) - ${CC} ${CFLAGS} -o fs fs.o ${TOP_LIBDIR}/libprot.a $(LIBS) ${XLIBS} + ${CC} ${CFLAGS} -o fs fs.o ${TOP_LIBDIR}/libprot.a $(LIBS) ${XLIBS} ${KRB5_LIBS} livesys.o: livesys.c ${INCLS} AFS_component_version_number.c livesys: livesys.c $(LIBS) - ${CC} ${CFLAGS} -o livesys ${srcdir}/livesys.c $(LIBS) ${XLIBS} + ${CC} ${CFLAGS} -o livesys ${srcdir}/livesys.c $(LIBS) ${XLIBS} ${KRB5_LIBS} twiddle: twiddle.c $(LIBS) - ${CC} ${CFLAGS} -o twiddle ${srcdir}/twiddle.c $(LIBS) ${XLIBS} + ${CC} ${CFLAGS} -o twiddle ${srcdir}/twiddle.c $(LIBS) ${XLIBS} ${KRB5_LIBS} gcpags: gcpags.c $(LIBS) ${CC} ${CFLAGS} -o gcpags ${srcdir}/gcpags.c $(LIBS) ${XLIBS} @@ -92,7 +92,7 @@ whatfid.o: whatfid.c ${INCLS} AFS_component_version_number.c whatfid: whatfid.o ${LIBS} - ${CC} ${CFLAGS} -o whatfid whatfid.o ${LIBS} ${XLIBS} + ${CC} ${CFLAGS} -o whatfid whatfid.o ${LIBS} ${XLIBS} ${KRB5_LIBS} fstrace.o: fstrace.c AFS_component_version_number.c case ${SYS_NAME} in \ @@ -121,8 +121,7 @@ cmdebug.o: cmdebug.c ${INCLS} AFS_component_version_number.c cmdebug: cmdebug.o ${CMLIBS} - $(CC) -o cmdebug cmdebug.o ${CFLAGS} ${CMLIBS} ${XLIBS} - + $(CC) -o cmdebug cmdebug.o ${CFLAGS} ${CMLIBS} ${XLIBS} ${KRB5_LIBS} # only in patch2: unchanged: --- openafs-1.4.12+dfsg.orig/src/update/Makefile.in +++ openafs-1.4.12+dfsg/src/update/Makefile.in @@ -23,10 +23,10 @@ # Build targets # upclient: client.o update.cs.o utils.o ${LIBS} - ${CC} ${CFLAGS} -o upclient client.o update.cs.o utils.o ${LIBS} ${XLIBS} + ${CC} ${CFLAGS} -o upclient client.o update.cs.o utils.o ${LIBS} ${XLIBS} ${KRB5_LIBS} upserver: server.o utils.o update.ss.o ${LIBS} - ${CC} ${CFLAGS} -o upserver server.o utils.o update.ss.o ${LIBS} ${XLIBS} + ${CC} ${CFLAGS} -o upserver server.o utils.o update.ss.o ${LIBS} ${XLIBS} ${KRB5_LIBS} utils.o: utils.c update.h global.h only in patch2: unchanged: --- openafs-1.4.12+dfsg.orig/src/update/server.c +++ openafs-1.4.12+dfsg/src/update/server.c @@ -314,7 +314,10 @@ rxkad_NewServerSecurityObject(rxkad_clear, cdir, afsconf_GetKey, 0); if (securityObjects[2] == (struct rx_securityClass *)0) Quit("rxkad_NewServerSecurityObject"); - +#ifdef USE_RXKAD_KEYTAB + if (rxkad_InitKeytabDecrypt(AFSDIR_SERVER_RXKAD_KEYTAB_FILEPATH) == 0) + rxkad_BindKeytabDecrypt(securityObjects[2]); +#endif /* Instantiate a single UPDATE service. The rxgen-generated procedure * which is called to decode requests is passed in here * (UPDATE_ExecuteRequest). */ only in patch2: unchanged: --- openafs-1.4.12+dfsg.orig/src/viced/viced.c +++ openafs-1.4.12+dfsg/src/viced/viced.c @@ -1873,6 +1873,12 @@ sc[1] = 0; /* rxvab_NewServerSecurityObject(key1, 0) */ sc[2] = rxkad_NewServerSecurityObject(rxkad_clear, NULL, get_key, NULL); sc[3] = rxkad_NewServerSecurityObject(rxkad_crypt, NULL, get_key, NULL); +#ifdef USE_RXKAD_KEYTAB + if (rxkad_InitKeytabDecrypt(AFSDIR_SERVER_RXKAD_KEYTAB_FILEPATH) == 0) { + rxkad_BindKeytabDecrypt(sc[2]); + rxkad_BindKeytabDecrypt(sc[3]); + } +#endif tservice = rx_NewServiceHost(rx_bindhost, /* port */ 0, /* service id */ 1, /*service name */ "AFS", only in patch2: unchanged: --- openafs-1.4.12+dfsg.orig/src/viced/Makefile.in +++ openafs-1.4.12+dfsg/src/viced/Makefile.in @@ -72,23 +72,23 @@ case ${SYS_NAME} in \ rs_aix*) \ ${CC} -K ${LDFLAGS} -o fileserver ${objects} \ - ${TOP_LIBDIR}/libaudit.a ${LIBS} ${XLIBS} ;; \ + ${TOP_LIBDIR}/libaudit.a ${LIBS} ${XLIBS} ${KRB5_LIBS} ;; \ *) \ ${CC} ${LDFLAGS} -o fileserver ${objects} \ - ${TOP_LIBDIR}/libaudit.a ${LIBS} ${XLIBS} ;; \ + ${TOP_LIBDIR}/libaudit.a ${LIBS} ${XLIBS} ${KRB5_LIBS} ;; \ esac fsprobe.o: fsprobe.c AFS_component_version_number.c ${CC} ${CFLAGS} -DINTERPRET_DUMP -c ${srcdir}/fsprobe.c fsprobe: fsprobe.o - ${CC} ${CFLAGS} -o fsprobe fsprobe.o ${LIBS} ${XLIBS} + ${CC} ${CFLAGS} -o fsprobe fsprobe.o ${LIBS} ${XLIBS} ${KRB5_LIBS} cbd.o: callback.c AFS_component_version_number.c ${CC} ${CFLAGS} -DINTERPRET_DUMP -c -o cbd.o ${srcdir}/callback.c cbd: cbd.o - ${CC} ${CFLAGS} -DINTERPRET_DUMP -o cbd cbd.o ${LIBS} ${XLIBS} + ${CC} ${CFLAGS} -DINTERPRET_DUMP -o cbd cbd.o ${LIBS} ${XLIBS} ${KRB5_LIBS} ${DEST}/root.server/usr/afs/bin/fileserver: fileserver @case ${SYS_NAME} in \ only in patch2: unchanged: --- openafs-1.4.12+dfsg.orig/src/tbutc/Makefile.in +++ openafs-1.4.12+dfsg/src/tbutc/Makefile.in @@ -66,7 +66,7 @@ all: butc butc: ${BUTCOBJS} ${BUTCLIBS} - ${CC} ${CFLAGS} ${BUTCOBJS} ${BUTCLIBS} ${MT_LIBS} ${XLIBS} -o butc + ${CC} ${CFLAGS} ${BUTCOBJS} ${BUTCLIBS} ${MT_LIBS} ${XLIBS} ${KRB5_LIBS} -o butc libbutm.a: ${BUTMOBJS} AFS_component_version_number.o -$(RM) -f libbutm.a only in patch2: unchanged: --- openafs-1.4.12+dfsg.orig/src/aklog/klog.c +++ openafs-1.4.12+dfsg/src/aklog/klog.c @@ -701,8 +701,15 @@ } atoken->startTime = afscred->times.starttime; atoken->endTime = afscred->times.endtime; - memcpy(&atoken->sessionKey, get_cred_keydata(afscred), - get_cred_keylen(afscred)); + if (tkt_DeriveDesKey(get_creds_enctype(afscred), + get_cred_keydata(afscred), + get_cred_keylen(afscred), &atoken->sessionKey)) { + afs_com_err(rn, 0, + "Cannot derive DES key from enctype %i of length %u", + get_creds_enctype(afscred), + (unsigned)get_cred_keylen(afscred)); + KLOGEXIT(1); + } memcpy(atoken->ticket, enc_part->data, atoken->ticketLen = enc_part->length); memset(aserver, 0, sizeof *aserver); only in patch2: unchanged: --- openafs-1.4.12+dfsg.orig/src/aklog/aklog_main.c +++ openafs-1.4.12+dfsg/src/aklog/aklog_main.c @@ -73,6 +73,7 @@ #ifdef AFS_SUN5_ENV #include #endif +#include #include #include #include @@ -180,108 +181,12 @@ #error "Must have either krb5_princ_size or krb5_principal_get_comp_string" #endif -#if !defined(HAVE_KRB5_ENCRYPT_TKT_PART) && defined(HAVE_ENCODE_KRB5_ENC_TKT_PART) && defined(HAVE_KRB5_C_ENCRYPT) -krb5_error_code -krb5_encrypt_tkt_part(krb5_context context, - const krb5_keyblock *key, - krb5_ticket *ticket) -{ - krb5_data *data = 0; - int code; - size_t enclen; - - if ((code = encode_krb5_enc_tkt_part(ticket->enc_part2, &data))) - goto Done; - if ((code = krb5_c_encrypt_length(context, key->enctype, - data->length, &enclen))) - goto Done; - ticket->enc_part.ciphertext.length = enclen; - if (!(ticket->enc_part.ciphertext.data = malloc(enclen))) { - code = ENOMEM; - goto Done; - } - if ((code = krb5_c_encrypt(context, key, KRB5_KEYUSAGE_KDC_REP_TICKET, - 0, data, &ticket->enc_part))) { - free(ticket->enc_part.ciphertext.data); - ticket->enc_part.ciphertext.data = 0; - } -Done: - if (data) { - if (data->data) - free(data->data); - free(data); - } - return code; -} -#endif - -#if defined(HAVE_KRB5_CREDS_KEYBLOCK) - -#define get_cred_keydata(c) c->keyblock.contents -#define get_cred_keylen(c) c->keyblock.length -#define get_creds_enctype(c) c->keyblock.enctype - -#elif defined(HAVE_KRB5_CREDS_SESSION) - -#define get_cred_keydata(c) c->session.keyvalue.data -#define get_cred_keylen(c) c->session.keyvalue.length -#define get_creds_enctype(c) c->session.keytype - -#else -#error "Must have either keyblock or session member of krb5_creds" -#endif - #if !defined(HAVE_KRB5_524_CONVERT_CREDS) && defined(HAVE_KRB524_CONVERT_CREDS_KDC) #define krb5_524_convert_creds krb524_convert_creds_kdc #elif !defined(HAVE_KRB5_524_CONVERT_CREDS) && !defined(HAVE_KRB524_CONVERT_CREDS_KDC) #define HAVE_NO_KRB5_524 #endif -#if USING_HEIMDAL -#define deref_keyblock_enctype(kb) \ - ((kb)->keytype) - -#define deref_entry_keyblock(entry) \ - entry->keyblock - -#define deref_session_key(creds) \ - creds->session - -#define deref_enc_tkt_addrs(tkt) \ - tkt->caddr - -#define deref_enc_length(enc) \ - ((enc)->cipher.length) - -#define deref_enc_data(enc) \ - ((enc)->cipher.data) - -#define krb5_free_keytab_entry_contents krb5_kt_free_entry - -#else -#define deref_keyblock_enctype(kb) \ - ((kb)->enctype) - -#define deref_entry_keyblock(entry) \ - entry->key - -#define deref_session_key(creds) \ - creds->keyblock - -#define deref_enc_tkt_addrs(tkt) \ - tkt->caddrs - -#define deref_enc_length(enc) \ - ((enc)->ciphertext.length) - -#define deref_enc_data(enc) \ - ((enc)->ciphertext.data) - -#endif - -#define deref_entry_enctype(entry) \ - deref_keyblock_enctype(&deref_entry_keyblock(entry)) - /* * Provide a replacement for strerror if we don't have it */ @@ -638,6 +543,8 @@ char *p; char k4name[ANAME_SZ], k4inst[INST_SZ], k4realm[REALM_SZ]; int len; + void *inkey = get_cred_keydata(v5cred); + size_t inkey_sz = get_cred_keylen(v5cred); if (dflag) printf("Using Kerberos V5 ticket natively\n"); @@ -675,8 +582,9 @@ atoken.kvno = RXKAD_TKT_TYPE_KERBEROS_V5; atoken.startTime = v5cred->times.starttime;; atoken.endTime = v5cred->times.endtime; - memcpy(&atoken.sessionKey, get_cred_keydata(v5cred), - get_cred_keylen(v5cred)); + if (tkt_DeriveDesKey(get_creds_enctype(v5cred), inkey, inkey_sz, + &atoken.sessionKey) != 0) + return RXKADBADKEY; atoken.ticketLen = v5cred->ticket.length; memcpy(atoken.ticket, v5cred->ticket.data, atoken.ticketLen); #ifndef HAVE_NO_KRB5_524 @@ -1549,327 +1457,6 @@ } } -static krb5_error_code get_credv5_akimpersonate(krb5_context context, - char* keytab, - krb5_principal service_principal, - krb5_principal client_principal, - time_t starttime, - time_t endtime, - int *allowed_enctypes, - int *paddress, - krb5_creds** out_creds /* out */ ) -{ -#if defined(USING_HEIMDAL) || (defined(HAVE_ENCODE_KRB5_ENC_TKT) && defined(HAVE_ENCODE_KRB5_TICKET) && defined(HAVE_KRB5_C_ENCRYPT)) - krb5_error_code code; - krb5_keytab kt = 0; - krb5_kt_cursor cursor[1]; - krb5_keytab_entry entry[1]; - krb5_ccache cc = 0; - krb5_creds *creds = 0; - krb5_enctype enctype; - krb5_kvno kvno; - krb5_keyblock session_key[1]; -#if USING_HEIMDAL - Ticket ticket_reply[1]; - EncTicketPart enc_tkt_reply[1]; - krb5_address address[30]; - krb5_addresses faddr[1]; - int temp_vno[1]; - time_t temp_time[2]; -#else - krb5_ticket ticket_reply[1]; - krb5_enc_tkt_part enc_tkt_reply[1]; - krb5_address address[30], *faddr[30]; -#endif - krb5_data * temp; - int i; - static int any_enctype[] = {0}; - *out_creds = 0; - if (!(creds = malloc(sizeof *creds))) { - code = ENOMEM; - goto cleanup; - } - if (!allowed_enctypes) - allowed_enctypes = any_enctype; - - cc = 0; - enctype = 0; /* AKIMPERSONATE_IGNORE_ENCTYPE */ - kvno = 0; /* AKIMPERSONATE_IGNORE_VNO */ - memset((char*)creds, 0, sizeof *creds); - memset((char*)entry, 0, sizeof *entry); - memset((char*)session_key, 0, sizeof *session_key); - memset((char*)ticket_reply, 0, sizeof *ticket_reply); - memset((char*)enc_tkt_reply, 0, sizeof *enc_tkt_reply); - code = krb5_kt_resolve(context, keytab, &kt); - if (code) { - if (keytab) - afs_com_err(progname, code, "while resolving keytab %s", keytab); - else - afs_com_err(progname, code, "while resolving default keytab"); - goto cleanup; - } - - if (service_principal) { - for (i = 0; (enctype = allowed_enctypes[i]) || !i; ++i) { - code = krb5_kt_get_entry(context, - kt, - service_principal, - kvno, - enctype, - entry); - if (!code) { - if (allowed_enctypes[i]) - deref_keyblock_enctype(session_key) = allowed_enctypes[i]; - break; - } - } - if (code) { - afs_com_err(progname, code,"while scanning keytab entries"); - goto cleanup; - } - } else { - krb5_keytab_entry new[1]; - int best = -1; - memset(new, 0, sizeof *new); - if ((code == krb5_kt_start_seq_get(context, kt, cursor))) { - afs_com_err(progname, code, "while starting keytab scan"); - goto cleanup; - } - while (!(code = krb5_kt_next_entry(context, kt, new, cursor))) { - for (i = 0; - allowed_enctypes[i] && allowed_enctypes[i] - != deref_entry_enctype(new); ++i) - ; - if ((!i || allowed_enctypes[i]) && - (best < 0 || best > i)) { - krb5_free_keytab_entry_contents(context, entry); - *entry = *new; - memset(new, 0, sizeof *new); - } else krb5_free_keytab_entry_contents(context, new); - } - if ((i = krb5_kt_end_seq_get(context, kt, cursor))) { - afs_com_err(progname, i, "while ending keytab scan"); - code = i; - goto cleanup; - } - if (best < 0) { - afs_com_err(progname, code, "while scanning keytab"); - goto cleanup; - } - deref_keyblock_enctype(session_key) = deref_entry_enctype(entry); - } - - /* Make Ticket */ - -#if USING_HEIMDAL - if ((code = krb5_generate_random_keyblock(context, - deref_keyblock_enctype(session_key), session_key))) { - afs_com_err(progname, code, "while making session key"); - goto cleanup; - } - enc_tkt_reply->flags.initial = 1; - enc_tkt_reply->transited.tr_type = DOMAIN_X500_COMPRESS; - enc_tkt_reply->cname = client_principal->name; - enc_tkt_reply->crealm = client_principal->realm; - enc_tkt_reply->key = *session_key; - { - static krb5_data empty_string; - enc_tkt_reply->transited.contents = empty_string; - } - enc_tkt_reply->authtime = starttime; - enc_tkt_reply->starttime = temp_time; - *enc_tkt_reply->starttime = starttime; -#if 0 - enc_tkt_reply->renew_till = temp_time + 1; - *enc_tkt_reply->renew_till = endtime; -#endif - enc_tkt_reply->endtime = endtime; -#else - if ((code = krb5_c_make_random_key(context, - deref_keyblock_enctype(session_key), session_key))) { - afs_com_err(progname, code, "while making session key"); - goto cleanup; - } - enc_tkt_reply->magic = KV5M_ENC_TKT_PART; -#define DATACAST (unsigned char *) - enc_tkt_reply->flags |= TKT_FLG_INITIAL; - enc_tkt_reply->transited.tr_type = KRB5_DOMAIN_X500_COMPRESS; - enc_tkt_reply->session = session_key; - enc_tkt_reply->client = client_principal; - { - static krb5_data empty_string; - enc_tkt_reply->transited.tr_contents = empty_string; - } - enc_tkt_reply->times.authtime = starttime; - enc_tkt_reply->times.starttime = starttime; /* krb524init needs this */ - enc_tkt_reply->times.endtime = endtime; -#endif /* USING_HEIMDAL */ - /* NB: We will discard address for now--ignoring caddr field - in any case. MIT branch does what it always did. */ - - if (paddress && *paddress) { - deref_enc_tkt_addrs(enc_tkt_reply) = faddr; -#if USING_HEIMDAL - faddr->len = 0; - faddr->val = address; -#endif - for (i = 0; paddress[i]; ++i) { -#if USING_HEIMDAL - address[i].addr_type = KRB5_ADDRESS_INET; - address[i].address.data = (void*)(paddress+i); - address[i].address.length = sizeof(paddress[i]); -#else -#if !USING_SSL - address[i].magic = KV5M_ADDRESS; - address[i].addrtype = ADDRTYPE_INET; -#else - address[i].addrtype = AF_INET; -#endif - address[i].contents = (void*)(paddress+i); - address[i].length = sizeof(int); - faddr[i] = address+i; -#endif - } -#if USING_HEIMDAL - faddr->len = i; -#else - faddr[i] = 0; -#endif - } - -#if USING_HEIMDAL - ticket_reply->sname = service_principal->name; - ticket_reply->realm = service_principal->realm; - - { /* crypto block */ - krb5_crypto crypto = 0; - unsigned char *buf = 0; - size_t buf_size, buf_len; - char *what; - - ASN1_MALLOC_ENCODE(EncTicketPart, buf, buf_size, - enc_tkt_reply, &buf_len, code); - if(code) { - afs_com_err(progname, code, "while encoding ticket"); - goto cleanup; - } - - if(buf_len != buf_size) { - afs_com_err(progname, code, - "%d != %d while encoding ticket (internal ASN.1 encoder error", - buf_len, buf_size); - goto cleanup; - } - what = "krb5_crypto_init"; - code = krb5_crypto_init(context, - &deref_entry_keyblock(entry), - deref_entry_enctype(entry), - &crypto); - if(!code) { - what = "krb5_encrypt"; - code = krb5_encrypt_EncryptedData(context, crypto, KRB5_KU_TICKET, - buf, buf_len, entry->vno, &(ticket_reply->enc_part)); - } - if (buf) free(buf); - if (crypto) krb5_crypto_destroy(context, crypto); - if(code) { - afs_com_err(progname, code, "while %s", what); - goto cleanup; - } - } /* crypto block */ - ticket_reply->enc_part.etype = deref_entry_enctype(entry); - ticket_reply->enc_part.kvno = temp_vno; - *ticket_reply->enc_part.kvno = entry->vno; - ticket_reply->tkt_vno = 5; -#else - ticket_reply->server = service_principal; - ticket_reply->enc_part2 = enc_tkt_reply; - if ((code = krb5_encrypt_tkt_part(context, &deref_entry_keyblock(entry), ticket_reply))) { - afs_com_err(progname, code, "while making ticket"); - goto cleanup; - } - ticket_reply->enc_part.kvno = entry->vno; -#endif - - /* Construct Creds */ - - if ((code = krb5_copy_principal(context, service_principal, - &creds->server))) { - afs_com_err(progname, code, "while copying service principal"); - goto cleanup; - } - if ((code = krb5_copy_principal(context, client_principal, - &creds->client))) { - afs_com_err(progname, code, "while copying client principal"); - goto cleanup; - } - if ((code = krb5_copy_keyblock_contents(context, session_key, - &deref_session_key(creds)))) { - afs_com_err(progname, code, "while copying session key"); - goto cleanup; - } - -#if USING_HEIMDAL - creds->times.authtime = enc_tkt_reply->authtime; - creds->times.starttime = *(enc_tkt_reply->starttime); - creds->times.endtime = enc_tkt_reply->endtime; - creds->times.renew_till = 0; /* *(enc_tkt_reply->renew_till) */ - creds->flags.b = enc_tkt_reply->flags; -#else - creds->times = enc_tkt_reply->times; - creds->ticket_flags = enc_tkt_reply->flags; -#endif - if (!deref_enc_tkt_addrs(enc_tkt_reply)) - ; - else if ((code = krb5_copy_addresses(context, - deref_enc_tkt_addrs(enc_tkt_reply), &creds->addresses))) { - afs_com_err(progname, code, "while copying addresses"); - goto cleanup; - } - -#if USING_HEIMDAL - { - size_t creds_tkt_len; - ASN1_MALLOC_ENCODE(Ticket, creds->ticket.data, creds->ticket.length, - ticket_reply, &creds_tkt_len, code); - if(code) { - afs_com_err(progname, code, "while encoding ticket"); - goto cleanup; - } - } -#else - if ((code = encode_krb5_ticket(ticket_reply, &temp))) { - afs_com_err(progname, code, "while encoding ticket"); - goto cleanup; - } - creds->ticket = *temp; - free(temp); -#endif - /* return creds */ - *out_creds = creds; - creds = 0; -cleanup: - if (deref_enc_data(&ticket_reply->enc_part)) - free(deref_enc_data(&ticket_reply->enc_part)); - krb5_free_keytab_entry_contents(context, entry); - if (client_principal) - krb5_free_principal(context, client_principal); - if (service_principal) - krb5_free_principal(context, service_principal); - if (cc) - krb5_cc_close(context, cc); - if (kt) - krb5_kt_close(context, kt); - if (creds) krb5_free_creds(context, creds); - krb5_free_keyblock_contents(context, session_key); -out: - return code; -#else - return -1; -#endif -} - - static krb5_error_code get_credv5(krb5_context context, char *name, char *inst, char *realm, krb5_creds **creds) @@ -1911,21 +1498,17 @@ increds.client = client_principal; increds.times.endtime = 0; - /* Ask for DES since that is what V4 understands */ - get_creds_enctype((&increds)) = ENCTYPE_DES_CBC_CRC; + if (do524) + /* Ask for DES since that is what V4 understands */ + get_creds_enctype((&increds)) = ENCTYPE_DES_CBC_CRC; if (keytab) { - int allowed_enctypes[] = { - ENCTYPE_DES_CBC_CRC, 0 - }; - r = get_credv5_akimpersonate(context, keytab, increds.server, increds.client, - 300, ((~0U)>>1), - allowed_enctypes, - 0 /* paddress */, + 0, 0x7fffffff, + NULL, creds /* out */); } else { r = krb5_get_credentials(context, 0, _krb425_ccache, &increds, creds); only in patch2: unchanged: --- openafs-1.4.12+dfsg.orig/src/uss/Makefile.in +++ openafs-1.4.12+dfsg/src/uss/Makefile.in @@ -46,7 +46,7 @@ y.tab.o uss: uss.o ${OBJS} - ${CC} ${CFLAGS} -o uss uss.o ${OBJS} ${LIBS} + ${CC} ${CFLAGS} -o uss uss.o ${OBJS} ${LIBS} ${KRB5_LIBS} uss.o: uss.c AFS_component_version_number.c ${CC} -c ${CFLAGS} ${srcdir}/uss.c only in patch2: unchanged: --- openafs-1.4.12+dfsg.orig/src/vlserver/vlserver.c +++ openafs-1.4.12+dfsg/src/vlserver/vlserver.c @@ -355,7 +355,10 @@ sc[0] = rxnull_NewServerSecurityObject(); sc[1] = (struct rx_securityClass *)0; sc[2] = rxkad_NewServerSecurityObject(0, tdir, afsconf_GetKey, NULL); - +#ifdef USE_RXKAD_KEYTAB + if (rxkad_InitKeytabDecrypt(AFSDIR_SERVER_RXKAD_KEYTAB_FILEPATH) == 0) + rxkad_BindKeytabDecrypt(sc[2]); +#endif tservice = rx_NewServiceHost(host, 0, USER_SERVICE_ID, "Vldb server", sc, 3, VL_ExecuteRequest); only in patch2: unchanged: --- openafs-1.4.12+dfsg.orig/src/vlserver/Makefile.in +++ openafs-1.4.12+dfsg/src/vlserver/Makefile.in @@ -46,23 +46,23 @@ ${TOP_INCDIR}/afs/cnvldb.h vldb_check: vldb_check.o ${LIBS} - $(CC) ${CFLAGS} -o vldb_check vldb_check.o ${LIBS} ${XLIBS} + $(CC) ${CFLAGS} -o vldb_check vldb_check.o ${LIBS} ${XLIBS} ${KRB5_LIBS} vldb_check.o: vldb_check.c AFS_component_version_number.o cnvldb: cnvldb.o ${LIBS} - $(CC) ${CFLAGS} -o cnvldb cnvldb.o ${LIBS} ${XLIBS} + $(CC) ${CFLAGS} -o cnvldb cnvldb.o ${LIBS} ${XLIBS} ${KRB5_LIBS} cnvldb.o: cnvldb.c cnvldb.h AFS_component_version_number.o sascnvldb: sascnvldb.o ${LIBS} - $(CC) ${CFLAGS} -o sascnvldb sascnvldb.o ${LIBS} ${XLIBS} + $(CC) ${CFLAGS} -o sascnvldb sascnvldb.o ${LIBS} ${XLIBS} ${KRB5_LIBS} sascnvldb.o: sascnvldb.c cnvldb.h AFS_component_version_number.o vlserver: vlserver.o vlutils.o vlprocs.o vldbint.ss.o vldbint.xdr.o $(LIBS) $(CC) ${CFLAGS} -o vlserver vlserver.o vlutils.o vlprocs.o vldbint.ss.o \ - vldbint.xdr.o $(LIBS) ${XLIBS} ${TOP_LIBDIR}/libaudit.a + vldbint.xdr.o $(LIBS) ${XLIBS} ${TOP_LIBDIR}/libaudit.a ${KRB5_LIBS} vlserver.o: vlserver.c ${INCLS} AFS_component_version_number.o vlutils.o: vlutils.c ${INCLS} @@ -99,7 +99,7 @@ $(RANLIB) $@ vlclient: vlclient.o libvldb.a $(LIBS) - $(CC) ${CFLAGS} -o vlclient vlclient.o libvldb.a $(LIBS) ${XLIBS} ${TOP_LIBDIR}/libcmd.a + $(CC) ${CFLAGS} -o vlclient vlclient.o libvldb.a $(LIBS) ${XLIBS} ${TOP_LIBDIR}/libcmd.a ${KRB5_LIBS} vlclient.o: vlclient.c ${INCLS} AFS_component_version_number.o only in patch2: unchanged: --- openafs-1.4.12+dfsg.orig/src/volser/volmain.c +++ openafs-1.4.12+dfsg/src/volser/volmain.c @@ -494,6 +494,10 @@ rxkad_NewServerSecurityObject(0, tdir, afsconf_GetKey, NULL); if (securityObjects[0] == (struct rx_securityClass *)0) Abort("rxnull_NewServerSecurityObject"); +#ifdef USE_RXKAD_KEYTAB + if (securityObjects[2] != NULL && rxkad_InitKeytabDecrypt(AFSDIR_SERVER_RXKAD_KEYTAB_FILEPATH) == 0) + rxkad_BindKeytabDecrypt(securityObjects[2]); +#endif service = rx_NewServiceHost(host, 0, VOLSERVICE_ID, "VOLSER", securityObjects, 3, AFSVolExecuteRequest); only in patch2: unchanged: --- openafs-1.4.12+dfsg.orig/src/volser/Makefile.in +++ openafs-1.4.12+dfsg/src/volser/Makefile.in @@ -65,11 +65,11 @@ ${TOP_LIBDIR}/libcmd.a ${TOP_LIBDIR}/util.a ${XLIBS} vos: vos.o ${VSOBJS} libvolser.a ${LIBS} - ${CC} ${LDFLAGS} -o vos vos.o $(VSOBJS) libvolser.a ${LIBS} ${XLIBS} + ${CC} ${LDFLAGS} -o vos vos.o $(VSOBJS) libvolser.a ${LIBS} ${XLIBS} ${KRB5_LIBS} volserver: $(SOBJS) $(LIBS) ${TOP_LIBDIR}/libdir.a ${CC} ${DBUG} -o volserver $(SOBJS) ${TOP_LIBDIR}/libdir.a \ - ${LDFLAGS} $(LIBS) ${XLIBS} + ${LDFLAGS} $(LIBS) ${XLIBS} ${KRB5_LIBS} voldump: vol-dump.o ${VOLDUMP_LIBS} ${CC} ${CFLAGS} -o voldump vol-dump.o ${VOLDUMP_LIBS} ${XLIBS} only in patch2: unchanged: --- openafs-1.4.12+dfsg.orig/src/tsm41/Makefile.in +++ openafs-1.4.12+dfsg/src/tsm41/Makefile.in @@ -72,13 +72,13 @@ $(RM) -f *.o $(AUTHLIBS) $(AUTHFILES) so_locations afs_dynamic_auth: ${AUTH_OBJS} ${AFSLIBS} ${AUTHFILES} - $(LD) -o $@ ${AUTH_OBJS} $(AFSLIBS) ${AUTHFILES} ${XLIBS} ${LDFLAGS} + $(LD) -o $@ ${AUTH_OBJS} $(AFSLIBS) ${AUTHFILES} @KRB5LIBS@ ${XLIBS} ${LDFLAGS} aklog_dynamic_auth: ${AUTH_KRB5_OBJS} ${AFSLIBS} ${AUTHFILES} $(LD) -o $@ ${AUTH_KRB5_OBJS} $(AFSLIBS) ${AUTHFILES} @KRB5LIBS@ ${XLIBS} ${AKLDFLAGS} afs_dynamic_kerbauth: ${AUTH_KRB_OBJS} ${KAFSLIBS} ${AUTHFILES} - $(LD) -o $@ ${AUTH_KRB_OBJS} $(KAFSLIBS) ${AUTHFILES} ${XLIBS} ${LDFLAGS} + $(LD) -o $@ ${AUTH_KRB_OBJS} $(KAFSLIBS) ${AUTHFILES} @KRB5LIBS@ ${XLIBS} ${LDFLAGS} aix_auth_common.o: ${srcdir}/aix_auth_common.c ${CCRULE} only in patch2: unchanged: --- openafs-1.4.12+dfsg.orig/src/scout/Makefile.in +++ openafs-1.4.12+dfsg/src/scout/Makefile.in @@ -49,7 +49,7 @@ scout.o: scout.c ${INCLS} AFS_component_version_number.c scout: scout.o $(LIBS) - ${CC} ${LDFLAGS} -o scout scout.o $(LIBS) ${TXLIBS} ${TOP_LIBDIR}/libtermlib.a ${XLIBS} + ${CC} ${LDFLAGS} -o scout scout.o $(LIBS) ${TXLIBS} ${TOP_LIBDIR}/libtermlib.a ${XLIBS} ${KRB5_LIBS} # # Installation targets