pull up 3des implementation from the marc-3des branch
authorMarc Horowitz <marc@mit.edu>
Fri, 30 Oct 1998 02:56:35 +0000 (02:56 +0000)
committerMarc Horowitz <marc@mit.edu>
Fri, 30 Oct 1998 02:56:35 +0000 (02:56 +0000)
git-svn-id: svn://anonsvn.mit.edu/krb5/trunk@11001 dc483132-0cff-0310-8789-dd5450dbe970

340 files changed:
src/ChangeLog
src/aclocal.m4
src/appl/bsd/ChangeLog
src/appl/bsd/kcmd.c
src/appl/bsd/krlogin.c
src/appl/bsd/krlogind.c
src/appl/bsd/login.c
src/appl/gss-sample/ChangeLog
src/appl/gss-sample/gss-client.c
src/appl/gss-sample/gss-server.c
src/appl/gssftp/ftp/ChangeLog
src/appl/gssftp/ftp/ftp.c
src/appl/telnet/libtelnet/ChangeLog
src/appl/telnet/libtelnet/enc_des.c
src/appl/telnet/libtelnet/kerberos.c
src/appl/telnet/telnet/ChangeLog
src/appl/telnet/telnet/commands.c
src/clients/ChangeLog
src/clients/Makefile.in
src/clients/configure.in
src/clients/kinit/ChangeLog
src/clients/kinit/kinit.c
src/clients/klist/ChangeLog
src/clients/klist/klist.c
src/include/ChangeLog
src/include/k5-int.h
src/include/kerberosIV/ChangeLog
src/include/kerberosIV/krb_db.h
src/include/krb5.hin
src/include/krb5/ChangeLog
src/include/krb5/kdb.h
src/include/krb5/kdb_dbc.h
src/kadmin/cli/ChangeLog
src/kadmin/cli/keytab.c
src/kadmin/dbutil/ChangeLog
src/kadmin/dbutil/dumpv4.c
src/kadmin/dbutil/kadm5_create.c
src/kadmin/dbutil/kdb5_create.c
src/kadmin/dbutil/kdb5_stash.c
src/kadmin/dbutil/kdb5_util.c
src/kadmin/dbutil/loadv4.c
src/kadmin/server/ChangeLog
src/kadmin/server/ovsec_kadmd.c
src/kadmin/v4server/ChangeLog
src/kadmin/v4server/acl_files.c
src/kadmin/v4server/admin_server.c
src/kadmin/v4server/kadm_funcs.c
src/kadmin/v4server/kadm_ser_wrap.c
src/kadmin/v4server/kadm_server.h
src/kdc/ChangeLog
src/kdc/do_as_req.c
src/kdc/do_tgs_req.c
src/kdc/extern.h
src/kdc/kdc_preauth.c
src/kdc/kdc_util.c
src/kdc/kerberos_v4.c
src/kdc/main.c
src/krb524/ChangeLog
src/krb524/cnv_tkt_skey.c
src/krb524/krb524d.c
src/lib/crypto/ChangeLog
src/lib/crypto/Makefile.in
src/lib/crypto/block_size.c [new file with mode: 0644]
src/lib/crypto/checksum_length.c [new file with mode: 0644]
src/lib/crypto/cksumtype_to_string.c [new file with mode: 0644]
src/lib/crypto/cksumtypes.c [new file with mode: 0644]
src/lib/crypto/cksumtypes.h [new file with mode: 0644]
src/lib/crypto/coll_proof_cksum.c [new file with mode: 0644]
src/lib/crypto/configure.in
src/lib/crypto/crc32/ChangeLog
src/lib/crypto/crc32/Makefile.in
src/lib/crypto/crc32/crc-32.h
src/lib/crypto/crc32/crc32.c [new file with mode: 0644]
src/lib/crypto/cryptoconf.c [deleted file]
src/lib/crypto/decrypt.c [new file with mode: 0644]
src/lib/crypto/decrypt_data.c [deleted file]
src/lib/crypto/des/.rconf [deleted file]
src/lib/crypto/des/ChangeLog
src/lib/crypto/des/FUNCTIONS [deleted file]
src/lib/crypto/des/Makefile.in
src/lib/crypto/des/afsstring2key.c
src/lib/crypto/des/cbc_cksum.c [deleted file]
src/lib/crypto/des/d3_ecb.c [deleted file]
src/lib/crypto/des/d3_procky.c [deleted file]
src/lib/crypto/des/d3_str2ky.c [deleted file]
src/lib/crypto/des/des.h [deleted file]
src/lib/crypto/des/des_int.h
src/lib/crypto/des/destest.c
src/lib/crypto/des/f_README [deleted file]
src/lib/crypto/des/f_ecb.c [deleted file]
src/lib/crypto/des/f_pcbc.c [deleted file]
src/lib/crypto/des/fin_rndkey.c [deleted file]
src/lib/crypto/des/finish_key.c [deleted file]
src/lib/crypto/des/init_rkey.c [deleted file]
src/lib/crypto/des/process_ky.c [deleted file]
src/lib/crypto/des/random_key.c [deleted file]
src/lib/crypto/des/string2key.c
src/lib/crypto/des/t_random.c [deleted file]
src/lib/crypto/des/t_verify.c
src/lib/crypto/des/u_nfold.c [deleted file]
src/lib/crypto/des/u_rn_key.c [deleted file]
src/lib/crypto/des3_raw.c [deleted file]
src/lib/crypto/des3_sha.c [deleted file]
src/lib/crypto/des_crc.c [deleted file]
src/lib/crypto/des_md5.c [deleted file]
src/lib/crypto/encrypt.c [new file with mode: 0644]
src/lib/crypto/encrypt_data.c [deleted file]
src/lib/crypto/encrypt_length.c [new file with mode: 0644]
src/lib/crypto/enctype_compare.c [new file with mode: 0644]
src/lib/crypto/enctype_to_string.c [new file with mode: 0644]
src/lib/crypto/etypes.c [new file with mode: 0644]
src/lib/crypto/etypes.h [new file with mode: 0644]
src/lib/crypto/hmac.c [new file with mode: 0644]
src/lib/crypto/keyed_checksum_types.c [new file with mode: 0644]
src/lib/crypto/keyed_cksum.c [new file with mode: 0644]
src/lib/crypto/krb5_glue.c [deleted file]
src/lib/crypto/make_checksum.c [new file with mode: 0644]
src/lib/crypto/make_random_key.c [new file with mode: 0644]
src/lib/crypto/md4/.rconf [deleted file]
src/lib/crypto/md4/ChangeLog
src/lib/crypto/md4/Makefile.in
src/lib/crypto/md4/md4crypto.c [deleted file]
src/lib/crypto/md4/md4driver.c [deleted file]
src/lib/crypto/md4/md4glue.c [deleted file]
src/lib/crypto/md5/ChangeLog
src/lib/crypto/md5/Makefile.in
src/lib/crypto/md5/md5crypto.c [deleted file]
src/lib/crypto/md5/md5glue.c [deleted file]
src/lib/crypto/md5/t_cksum.c [deleted file]
src/lib/crypto/nfold.c [new file with mode: 0644]
src/lib/crypto/old_api_glue.c [new file with mode: 0644]
src/lib/crypto/os/.Sanitize [deleted file]
src/lib/crypto/os/ChangeLog [deleted file]
src/lib/crypto/os/Makefile.in [deleted file]
src/lib/crypto/os/c_localaddr.c [deleted file]
src/lib/crypto/os/rnd_confoun.c [deleted file]
src/lib/crypto/prng.c [new file with mode: 0644]
src/lib/crypto/raw_des.c [deleted file]
src/lib/crypto/sha/.Sanitize [deleted file]
src/lib/crypto/sha/ChangeLog [deleted file]
src/lib/crypto/sha/Makefile.in [deleted file]
src/lib/crypto/sha/hmac_sha.c [deleted file]
src/lib/crypto/sha/sha_crypto.c [deleted file]
src/lib/crypto/sha/sha_glue.c [deleted file]
src/lib/crypto/sha/shs.c [deleted file]
src/lib/crypto/sha/shs.h [deleted file]
src/lib/crypto/sha/t_shs.c [deleted file]
src/lib/crypto/string_to_cksumtype.c [new file with mode: 0644]
src/lib/crypto/string_to_enctype.c [new file with mode: 0644]
src/lib/crypto/string_to_key.c [new file with mode: 0644]
src/lib/crypto/t_nfold.c [new file with mode: 0644]
src/lib/crypto/valid_cksumtype.c [new file with mode: 0644]
src/lib/crypto/valid_enctype.c [new file with mode: 0644]
src/lib/crypto/verify_checksum.c [new file with mode: 0644]
src/lib/des425/ChangeLog
src/lib/des425/Makefile.in
src/lib/des425/new_rnd_key.c
src/lib/des425/random_key.c
src/lib/gssapi/Makefile.in
src/lib/gssapi/generic/ChangeLog
src/lib/gssapi/generic/gssapi.hin
src/lib/gssapi/generic/gssapi_err_generic.et
src/lib/gssapi/generic/util_token.c
src/lib/gssapi/krb5/ChangeLog
src/lib/gssapi/krb5/Makefile.in
src/lib/gssapi/krb5/accept_sec_context.c
src/lib/gssapi/krb5/acquire_cred.c
src/lib/gssapi/krb5/add_cred.c [new file with mode: 0644]
src/lib/gssapi/krb5/canon_name.c
src/lib/gssapi/krb5/delete_sec_context.c
src/lib/gssapi/krb5/disp_status.c
src/lib/gssapi/krb5/gssapiP_krb5.h
src/lib/gssapi/krb5/gssapi_err_krb5.et
src/lib/gssapi/krb5/gssapi_krb5.c
src/lib/gssapi/krb5/gssapi_krb5.h
src/lib/gssapi/krb5/init_sec_context.c
src/lib/gssapi/krb5/inq_cred.c
src/lib/gssapi/krb5/inq_names.c
src/lib/gssapi/krb5/k5seal.c
src/lib/gssapi/krb5/k5unseal.c
src/lib/gssapi/krb5/rel_oid.c
src/lib/gssapi/krb5/ser_sctx.c
src/lib/gssapi/krb5/util_cksum.c
src/lib/gssapi/krb5/util_crypt.c
src/lib/gssapi/krb5/util_ctxsetup.c [new file with mode: 0644]
src/lib/gssapi/krb5/util_seed.c
src/lib/gssapi/krb5/util_seqnum.c
src/lib/gssapi/krb5/wrap_size_limit.c
src/lib/kadm5/ChangeLog
src/lib/kadm5/alt_prof.c
src/lib/kadm5/clnt/ChangeLog
src/lib/kadm5/clnt/Makefile.in
src/lib/kadm5/clnt/client_init.c
src/lib/kadm5/srv/ChangeLog
src/lib/kadm5/srv/Makefile.in
src/lib/kadm5/srv/server_kdb.c
src/lib/kadm5/srv/svr_principal.c
src/lib/kdb/ChangeLog
src/lib/kdb/Makefile.in
src/lib/kdb/decrypt_key.c
src/lib/kdb/encrypt_key.c
src/lib/kdb/fetch_mkey.c
src/lib/kdb/kdb_cpw.c
src/lib/kdb/kdb_db2.c
src/lib/kdb/kdb_db2.h
src/lib/kdb/kdb_dbm.c
src/lib/kdb/kdb_xdr.c
src/lib/kdb/keytab.c
src/lib/kdb/verify_mky.c
src/lib/krb4/ChangeLog
src/lib/krb4/Makefile.in
src/lib/krb4/cr_tkt.c
src/lib/krb4/decomp_tkt.c
src/lib/krb4/rd_req.c
src/lib/krb4/tf_util.c
src/lib/krb5/ChangeLog
src/lib/krb5/Makefile.in
src/lib/krb5/asn.1/ChangeLog
src/lib/krb5/asn.1/asn1buf.c
src/lib/krb5/ccache/ChangeLog
src/lib/krb5/ccache/ccapi/Makefile.in [deleted file]
src/lib/krb5/ccache/ccapi/stdcc.c [deleted file]
src/lib/krb5/ccache/ccapi/stdcc.h [deleted file]
src/lib/krb5/ccache/ccapi/stdcc_util.c [deleted file]
src/lib/krb5/ccache/ccapi/stdcc_util.h [deleted file]
src/lib/krb5/ccache/ccbase.c
src/lib/krb5/configure.in
src/lib/krb5/error_tables/krb5_err.et
src/lib/krb5/keytab/file/ChangeLog
src/lib/krb5/keytab/file/ktf_g_ent.c
src/lib/krb5/krb/ChangeLog
src/lib/krb5/krb/Makefile.in
src/lib/krb5/krb/auth_con.c
src/lib/krb5/krb/auth_con.h
src/lib/krb5/krb/decode_kdc.c
src/lib/krb5/krb/decrypt_tk.c
src/lib/krb5/krb/enc_helper.c [new file with mode: 0644]
src/lib/krb5/krb/encode_kdc.c
src/lib/krb5/krb/encrypt_tk.c
src/lib/krb5/krb/gen_seqnum.c
src/lib/krb5/krb/gen_subkey.c
src/lib/krb5/krb/get_creds.c
src/lib/krb5/krb/gic_pwd.c
src/lib/krb5/krb/in_tkt_pwd.c
src/lib/krb5/krb/init_ctx.c
src/lib/krb5/krb/kdc_rep_dc.c
src/lib/krb5/krb/kfree.c
src/lib/krb5/krb/mk_cred.c
src/lib/krb5/krb/mk_priv.c
src/lib/krb5/krb/mk_rep.c
src/lib/krb5/krb/mk_req_ext.c
src/lib/krb5/krb/mk_safe.c
src/lib/krb5/krb/preauth.c
src/lib/krb5/krb/preauth2.c
src/lib/krb5/krb/rd_cred.c
src/lib/krb5/krb/rd_priv.c
src/lib/krb5/krb/rd_rep.c
src/lib/krb5/krb/rd_req_dec.c
src/lib/krb5/krb/rd_safe.c
src/lib/krb5/krb/send_tgs.c
src/lib/krb5/krb/ser_actx.c
src/lib/krb5/krb/ser_eblk.c
src/lib/krb5/krb/str_conv.c
src/lib/krb5/krb/vfy_increds.c
src/lib/krb5/os/ChangeLog
src/lib/krb5/os/Makefile.in
src/lib/krb5/os/c_ustime.c [moved from src/lib/crypto/os/c_ustime.c with 99% similarity]
src/lib/krb5/os/ktdefname.c
src/lib/krb5/os/localaddr.c
src/lib/krb5/os/locate_kdc.c
src/lib/rpc/ChangeLog
src/lib/rpc/Makefile.in
src/lib/rpc/auth_gssapi.h
src/lib/rpc/svc_auth_gssapi.c
src/mac/TestTrack/ChangeLog [deleted file]
src/mac/TestTrack/MITAthenaLib [deleted file]
src/mac/TestTrack/ShlibTestTrack.c [deleted file]
src/mac/TestTrack/ShlibTestTrack.h [deleted file]
src/mac/TestTrack/TestTrackLib.h [deleted file]
src/mac/TestTrack/testtrack.h [deleted file]
src/mac/libraries/CCache API/bin/CCacheGlobalsLib.68K [deleted file]
src/mac/libraries/CCache API/bin/CCacheGlobalsLib.PPC [deleted file]
src/mac/libraries/CCache API/bin/CCacheLib.68K [deleted file]
src/mac/libraries/CCache API/bin/CCacheLib.68K.debug [deleted file]
src/mac/libraries/CCache API/bin/CCacheLib.PPC [deleted file]
src/mac/libraries/CCache API/bin/CCacheLib.PPC.debug [deleted file]
src/mac/libraries/CCache API/include/CCache.h [deleted file]
src/mac/libraries/CCache API/include/CCacheUtil.h [deleted file]
src/mac/libraries/CodeWarrior Dependencies/Pro2.prj [deleted file]
src/mac/libraries/CodeWarrior Dependencies/Pro4.prj [deleted file]
src/mac/libraries/DES/bin/deslib.68K [deleted file]
src/mac/libraries/DES/bin/deslib.68K.debug [deleted file]
src/mac/libraries/DES/bin/deslib.PPC [deleted file]
src/mac/libraries/DES/bin/deslib.PPC.debug [deleted file]
src/mac/libraries/DES/doc/ChangeLog [deleted file]
src/mac/libraries/DES/doc/READ_ME [deleted file]
src/mac/libraries/DES/doc/f_README [deleted file]
src/mac/libraries/DES/doc/ren.msg [deleted file]
src/mac/libraries/DES/include/des.h [deleted file]
src/mac/libraries/DES/include/deslib.CFMGlue.c [deleted file]
src/mac/libraries/DES/include/deslib.CFMGlue.h [deleted file]
src/mac/libraries/DES/include/mit-copyright.h [deleted file]
src/mac/libraries/Metrowerks/CW Pro 2/MIT C.CFM68K DLL.doc [deleted file]
src/mac/libraries/Metrowerks/CW Pro 2/MIT C.CFM68K DLL.prj [deleted file]
src/mac/libraries/Metrowerks/CW Pro 2/MIT C.PPC DLL.doc [deleted file]
src/mac/libraries/Metrowerks/CW Pro 2/MIT C.PPC DLL.prj [deleted file]
src/mac/libraries/Metrowerks/CW Pro 2/MIT RuntimeCFM68K DLL.doc [deleted file]
src/mac/libraries/Metrowerks/CW Pro 2/MIT RuntimeCFM68K DLL.prj [deleted file]
src/mac/libraries/Metrowerks/CW Pro 2/MIT RuntimePPC DLL.doc [deleted file]
src/mac/libraries/Metrowerks/CW Pro 2/MIT RuntimePPC DLL.prj [deleted file]
src/mac/libraries/Metrowerks/CW Pro 4/MIT C.CFM68K DLL.doc [deleted file]
src/mac/libraries/Metrowerks/CW Pro 4/MIT C.CFM68K DLL.prj [deleted file]
src/mac/libraries/Metrowerks/CW Pro 4/MIT C.PPC DLL.doc [deleted file]
src/mac/libraries/Metrowerks/CW Pro 4/MIT C.PPC DLL.prj [deleted file]
src/mac/libraries/Metrowerks/CW Pro 4/MIT RuntimeCFM68K DLL.doc [deleted file]
src/mac/libraries/Metrowerks/CW Pro 4/MIT RuntimeCFM68K DLL.prj [deleted file]
src/mac/libraries/Metrowerks/CW Pro 4/MIT RuntimePPC DLL.doc [deleted file]
src/mac/libraries/Metrowerks/CW Pro 4/MIT RuntimePPC DLL.prj [deleted file]
src/slave/ChangeLog
src/slave/kpropd.c
src/tests/create/ChangeLog
src/tests/create/kdb5_mkdums.c
src/tests/misc/test_nfold.c [new file with mode: 0644]
src/tests/verify/ChangeLog
src/tests/verify/kdb5_verify.c
src/util/profile/ChangeLog
src/util/profile/Makefile.in
src/util/profile/configure.in
src/util/pty/ChangeLog
src/util/pty/Makefile.in
src/util/pty/configure.in
src/util/ss/execute_cmd.c
src/windows/lib/ChangeLog [deleted file]
src/windows/lib/Makefile.in [deleted file]
src/windows/lib/gic.c [deleted file]
src/windows/lib/gic.h [deleted file]
src/windows/lib/registry.c [deleted file]
src/windows/lib/registry.h [deleted file]
src/windows/lib/vardlg.c [deleted file]
src/windows/lib/vardlg.h [deleted file]

index 2189342e5cc5bea8a901a81f5b11aa2fec9edb15..409a200cbfad6cd4ef71d16f2652c286a90db1b6 100644 (file)
@@ -1,9 +1,26 @@
+Wed Sep 23 15:24:44 1998  Tom Yu  <tlyu@mit.edu>
+
+       * aclocal.m4 (KRB5_LIB_AUX): Do what Sam originally meant to do by
+       moving the explicit resetting of DEPLIB=$SHLIBEXT and forcing
+       SHLIBEXT=.so-nobuild to avoid duplicate rules on AIX and such.
+
 1998-08-24  Theodore Ts'o  <tytso@rsts-11.mit.edu>
 
        * Makefile.in: Add support to build the lib/krb5/ccache api
                directory and include it in the Windows kerbsrc-nt.zip
                file.
 
+Wed Aug 19 20:14:31 1998  Tom Yu  <tlyu@mit.edu>
+
+       * aclocal.m4 (KRB5_LIB_AUX): Back out Sam's change to reorder the
+       "force_static" logic, as it would cause problems where a
+       forced-static library is built in the same directory as a
+       program, due to explicit setting of CC_LINK, etc.
+
+Mon Aug 17 18:10:29 1998  Tom Yu  <tlyu@mit.edu>
+
+       * aclocal.m4: Fix Sam's fixes (variable capitalization).
+
 Wed Jul  8 01:10:44 1998  Matthew D Hancher  <mdh@mit.edu>
 
        * aclocal.m4: Allow shared libraries to build properly under Irix
index af2d8a923870fb3d3a8828b3bbf71aaf8317a651..1bfd92606fe893ee72b169625283739ba9c5563d 100644 (file)
@@ -868,8 +868,8 @@ if test "$enableval" = no && test "$krb5_force_static" != yes; then
        LIBLIST=
        OBJLISTS=
 else
-       LIBLIST="lib\$(LIB)$STLIBEXT"
-       LIBLINKS="\$(TOPLIBD)/lib\$(LIB)$STLIBEXT"
+       LIBLIST='lib$(LIB)$(STLIBEXT)'
+       LIBLINKS='$(TOPLIBD)/lib$(LIB)$(STLIBEXT)'
        OBJLISTS=OBJS.ST
        LIBINSTLIST=install-static
        DEPLIBEXT=$STLIBEXT
@@ -886,8 +886,12 @@ AC_ARG_ENABLE([shared],
                CC_LINK="$CC_LINK_STATIC"
                ;;
        *)
+               # set this now because some logic below may reset SHLIBEXT
+               DEPLIBEXT=$SHLIBEXT
                if test "$krb5_force_static" = "yes"; then
                        AC_MSG_RESULT([Forcing static libraries.])
+                       # avoid duplicate rules generation for AIX and such
+                       SHLIBEXT=.so-nobuild
                else
                        AC_MSG_RESULT([Enabling shared libraries.])
                        LIBLIST="$LIBLIST "'lib$(LIB)$(SHLIBEXT)'
@@ -904,7 +908,6 @@ AC_ARG_ENABLE([shared],
                        esac
                        OBJLISTS="$OBJLISTS OBJS.SH"
                fi
-               DEPLIBEXT=$SHLIBEXT
                CC_LINK="$CC_LINK_SHARED"
                if test "$STLIBEXT" = "$SHLIBEXT" ; then
                  STLIBEXT=".a-no-build"
@@ -1018,7 +1021,7 @@ mips-sgi-irix6.3) # This is a Kludge; see below
        SHLIBEXT=.so
        SHOBJEXT=.o
        # Kludge follows: (gcc makes n32 object files but ld expects o32, so we reeducate ld)
-       if test "$GCC" = yes; then
+       if test "$krb5_cv_prog_gcc" = yes; then
                LDCOMBINE='ld -n32 -shared -ignore_unresolved -update_registry $(BUILDTOP)/so_locations -soname lib$(LIB)$(SHLIBSEXT)'
        else
                LDCOMBINE='ld -shared -ignore_unresolved -update_registry $(BUILDTOP)/so_locations -soname lib$(LIB)$(SHLIBSEXT)'
@@ -1047,7 +1050,7 @@ mips-sgi-irix*)
 
 # untested...
 mips-sni-sysv4)
-       if test "$GCC" = yes; then
+       if test "$krb5_cv_prog_gcc" = yes; then
                PICFLAGS=-fpic
                LDCOMBINE='$(CC) -G -Wl,-h -Wl,lib$(LIB)$(SHLIBSEXT)'
        else
@@ -1114,7 +1117,7 @@ mips-*-netbsd*)
        ;;
 
 *-*-solaris*)
-       if test "$GCC" = yes; then
+       if test "$krb5_cv_prog_gcc" = yes; then
                PICFLAGS=-fpic
                LDCOMBINE='$(CC) -shared -h lib$(LIB)$(SHLIBSEXT)'
        else
@@ -1171,7 +1174,7 @@ mips-*-netbsd*)
        LDCOMBINE='$(BUILDTOP)/util/makeshlib $(LIBMAJOR).$(LIBMINOR)'
        SHLIB_EXPFLAGS='  $(SHLIB_DIRS) $(SHLIB_EXPLIBS)'
        PROFFLAGS=-pg
-       if test "$gcc" = "yes" ; then
+       if test "$krb5_cv_prog_gcc" = "yes" ; then
          CC_LINK_SHARED='$(CC) $(PROG_LIBPATH) -Xlinker -bex4:$(BUILDTOP)/util/aix.bincmds '
        else
          CC_LINK_SHARED='$(CC) $(PROG_LIBPATH) -bex4:$(BUILDTOP)/util/aix.bincmds '
index 6eaa52942e524716fdecd147f0dbc3c7e841b6e2..8f7e9a8fc8d3e5ac824755be8b9c75d3a8303b3f 100644 (file)
@@ -1,3 +1,17 @@
+1998-10-24  Marc Horowitz  <marc@mit.edu>
+
+       * login.c: update to new get_creds API
+       
+       * krlogin.c (main, oob, server_message, control), krlogind.c
+               (sendoob, protocol, recvauth): If the enctype is not
+               similar to DES, use an inband signalling protocol instead
+               of MSG_OOB data to indicate status changes.
+
+       * kcmd.c (rcmd_stream_init_krb5, v5_des_read, v5_des_write):
+               update to new crypto API.  Add ivec chaining to
+               encryption when the enctype is not similar to DES as part
+               of the new protocol.
+
 1998-10-06  Theodore Ts'o  <tytso@rsts-11.mit.edu>
 
        * krshd.c (doit): Apply ghudson's patch so that rshd passes the
@@ -8,6 +22,10 @@
                the foreign and local ports so that encrypted rcp for the
                same machine.  [krb5-appl/638]
 
+Tue Aug 18 16:48:02 1998  Tom Yu  <tlyu@mit.edu>
+
+       * krlogin.c: Add <sys/filio.h> for FIONREAD.
+
 Sat Aug 15 00:01:15 1998  Geoffrey King  <gjking@mit.edu>
 
        * krcp.c (error): Don't call rcmd_stream_write if iamremote is not
@@ -19,6 +37,11 @@ Mon Jul 27 00:06:20 1998  Geoffrey King  <gjking@mit.edu>
        * krlogin.c (main): Apply ghudson's patch so that rlogin -a
        no longer dumps core. [krb5-appl/612]
 
+Sun Jul 26 23:46:36 1998  Sam Hartman  <hartmans@utwig.mesas.com>
+
+       * login.c (main): Allow krb524 conversion for forwarded tickets
+       (try_convert524): Don't check to see if we have tickets here; caller  does that and actually gets it right.
+
 1998-05-26  Theodore Ts'o  <tytso@rsts-11.mit.edu>
 
        * login.c (dolastlog): BSD 4.4 systems don't have lastlog.h, but
index c6f21e02f23a7dfd9b4dc8ebcaf21d16d24b21ac..f775719174dbb2fa6bf3e2ae0516eb1114dac8bf 100644 (file)
  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  */
 
+/*
+ * Copyright (C) 1998 by the FundsXpress, INC.
+ * 
+ * All rights reserved.
+ * 
+ * Export of this software from the United States of America may require
+ * a specific license from the United States Government.  It is the
+ * responsibility of any person or organization contemplating export to
+ * obtain such a license before exporting.
+ * 
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of FundsXpress. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  FundsXpress makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
 /* derived from @(#)rcmd.c     5.17 (Berkeley) 6/27/88 */
      
 #ifdef HAVE_UNISTD_H
@@ -76,6 +102,8 @@ extern Key_schedule v4_schedule;
 #define START_PORT      5120     /* arbitrary */
 char *default_service = "host";
 
+#define KCMD_KEYUSAGE  1026
+
 /*
  * Note that the encrypted rlogin packets take the form of a four-byte
  * length followed by encrypted data.  On writing the data out, a significant
@@ -89,7 +117,8 @@ static char des_inbuf[2*RCMD_BUFSIZ];         /* needs to be > largest read size */
 static char des_outpkt[2*RCMD_BUFSIZ+4]; /* needs to be > largest write size */
 static krb5_data desinbuf;
 static krb5_data desoutbuf;
-static krb5_encrypt_block eblock;       /* eblock for encrypt/decrypt */
+static krb5_data encivec;
+static krb5_keyblock *keyblock;                 /* key for encrypt/decrypt */
 static int (*input)();
 static int (*output)();
 static char storage[2*RCMD_BUFSIZ];     /* storage for the decryption */
@@ -713,12 +742,14 @@ void rcmd_stream_init_normal()
     output = twrite;
 }
 
-void rcmd_stream_init_krb5(keyblock, encrypt_flag, lencheck)
-     krb5_keyblock *keyblock;
+void rcmd_stream_init_krb5(in_keyblock, encrypt_flag, lencheck)
+     krb5_keyblock *in_keyblock;
      int encrypt_flag;
      int lencheck;
 {
     krb5_error_code status;
+    size_t blocksize;
+    krb5_boolean similar;
 
     if (!encrypt_flag) {
        rcmd_stream_init_normal();
@@ -726,15 +757,39 @@ void rcmd_stream_init_krb5(keyblock, encrypt_flag, lencheck)
     }
     desinbuf.data = des_inbuf;
     desoutbuf.data = des_outpkt+4;     /* Set up des buffers */
-    krb5_use_enctype(bsd_context, &eblock, keyblock->enctype);
-    if ( status = krb5_process_key(bsd_context, &eblock, keyblock)) {
-       fprintf(stderr, "rcmd: Cannot process session key: %s\n",
-               error_message(status));
-       exit(1);
-    }
+    keyblock = in_keyblock;
+
     do_lencheck = lencheck;
     input = v5_des_read;
     output = v5_des_write;
+
+    if (status = krb5_c_enctype_compare(bsd_context, ENCTYPE_DES_CBC_CRC,
+                                       keyblock->enctype,
+                                       &similar)) {
+       /* XXX what do I do? */
+       abort();
+    }
+
+    if (similar) {
+       encivec.length = 0;
+       return;
+    }
+
+    if (status = krb5_c_block_size(bsd_context, keyblock->enctype,
+                                  &blocksize)) {
+       /* XXX what do I do? */
+       abort();
+    }
+
+    encivec.length = blocksize;
+
+    if ((encivec.data = malloc(encivec.length)) == NULL) {
+       /* XXX what do I do? */
+       abort();
+    }
+
+    /* is there a better way to initialize this? */
+    memset(encivec.data, '\0', blocksize);
 }
 
 #ifdef KRB5_KRB4_COMPAT
@@ -787,9 +842,12 @@ static int v5_des_read(fd, buf, len)
      int len;
 {
     int nreturned = 0;
-    long net_len,rd_len;
+    size_t net_len,rd_len;
     int cc;
     unsigned char c;
+    krb5_error_code ret;
+    krb5_data plain;
+    krb5_enc_data cipher;
     
     if (nstored >= len) {
        memcpy(buf, store_ptr, len);
@@ -823,7 +881,12 @@ static int v5_des_read(fd, buf, len)
     if ((cc = krb5_net_read(bsd_context, fd, &c, 1)) != 1) return 0;
     rd_len = (rd_len << 8) | c;
 
-    net_len = krb5_encrypt_size(rd_len,eblock.crypto_entry);
+    if (ret = krb5_c_encrypt_length(bsd_context, keyblock->enctype,
+                                 rd_len, &net_len)) {
+       errno = ret;
+       return(-1);
+    }
+
     if ((net_len <= 0) || (net_len > sizeof(des_inbuf))) {
        /* preposterous length, probably out of sync */
        errno = EIO;
@@ -834,11 +897,17 @@ static int v5_des_read(fd, buf, len)
        errno = EIO;
        return(-1);
     }
+
+    cipher.enctype = ENCTYPE_UNKNOWN;
+    cipher.ciphertext.length = net_len;
+    cipher.ciphertext.data = desinbuf.data;
+    plain.length = sizeof(storage);
+    plain.data = storage;
+
     /* decrypt info */
-    if ((krb5_decrypt(bsd_context, desinbuf.data,
-                     (krb5_pointer) storage,
-                     net_len,
-                     &eblock, 0))) {
+    if (krb5_c_decrypt(bsd_context, keyblock, KCMD_KEYUSAGE,
+                      encivec.length?&encivec:0,
+                      &cipher, &plain)) {
        /* probably out of sync */
        errno = EIO;
        return(-1);
@@ -867,21 +936,24 @@ static int v5_des_write(fd, buf, len)
      int len;
 {
     unsigned char *len_buf = (unsigned char *) des_outpkt;
-    
-    desoutbuf.length = krb5_encrypt_size(len,eblock.crypto_entry);
-    if (desoutbuf.length > sizeof(des_outpkt)-4){
-       errno = EIO;
-       return(-1);
-    }
-    if ((krb5_encrypt(bsd_context, (krb5_pointer)buf,
-                     desoutbuf.data,
-                     len,
-                     &eblock,
-                     0))){
+    krb5_data plain;
+    krb5_enc_data cipher;
+
+    plain.data = buf;
+    plain.length = len;
+
+    cipher.ciphertext.length = sizeof(des_outpkt)-4;
+    cipher.ciphertext.data = desoutbuf.data;
+
+    if (krb5_c_encrypt(bsd_context, keyblock, KCMD_KEYUSAGE,
+                      encivec.length?&encivec:0,
+                      &plain, &cipher)) {
        errno = EIO;
        return(-1);
     }
 
+    desoutbuf.length = cipher.ciphertext.length;
+
     len_buf[0] = (len & 0xff000000) >> 24;
     len_buf[1] = (len & 0xff0000) >> 16;
     len_buf[2] = (len & 0xff00) >> 8;
@@ -891,6 +963,7 @@ static int v5_des_write(fd, buf, len)
        errno = EIO;
        return(-1);
     }
+
     else return(len);
 }
 
index 54d048b65a20025b082ee66f6809b6c07a1a286f..0bfb3ef571acbfa90d9e3b34c4d0650faec0b557 100644 (file)
  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  */
 
+/*
+ * Copyright (C) 1998 by the FundsXpress, INC.
+ * 
+ * All rights reserved.
+ * 
+ * Export of this software from the United States of America may require
+ * a specific license from the United States Government.  It is the
+ * responsibility of any person or organization contemplating export to
+ * obtain such a license before exporting.
+ * 
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of FundsXpress. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  FundsXpress makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
 #ifndef lint
 char copyright[] =
   "@(#) Copyright (c) 1983 The Regents of the University of California.\n\
@@ -61,6 +87,11 @@ char copyright[] =
 #include <setjmp.h>
 #include <netdb.h>
      
+#ifdef HAVE_SYS_FILIO_H
+/* Solaris needs <sys/filio.h> for FIONREAD */
+#include <sys/filio.h>
+#endif
+
 #ifdef HAVE_STDLIB_H
 #include <stdlib.h>
 #endif
@@ -175,6 +206,7 @@ char        *getenv();
 
 char   *name;
 int    rem = -1;               /* Remote socket fd */
+int    do_inband = 0;
 char   cmdchar = '~';
 int    eight = 1;              /* Default to 8 bit transmission */
 int    no_local_escape = 0;
@@ -219,6 +251,7 @@ char        *host=0;                        /* external, so it can be
                                           reached from confirm_death() */
 
 krb5_sigtype   sigwinch KRB5_PROTOTYPE((int));
+int server_message KRB5_PROTOTYPE((int));
 void oob KRB5_PROTOTYPE((void));
 krb5_sigtype   lostpeer KRB5_PROTOTYPE((int));
 #if __STDC__
@@ -593,8 +626,22 @@ main(argc, argv)
 #else
        try_normal(orig_argv);
 #endif
-    } else
+    } else {
+       krb5_boolean similar;
+
        rcmd_stream_init_krb5(&cred->keyblock, encrypt_flag, 1);
+
+       if (status = krb5_c_enctype_compare(bsd_context, ENCTYPE_DES_CBC_CRC,
+                                           cred->keyblock.enctype, &similar))
+           try_normal(orig_argv); /* doesn't return */
+
+       if (!similar) {
+           do_inband = 1;
+           if (debug_port)
+               fprintf(stderr, "DEBUG: setting do_inband\n");
+       }
+    }
+       
     rem = sock;
     
 #else
@@ -1185,15 +1232,16 @@ int     rcvcnt;
 int    rcvstate;
 int    ppid;
 
+/* returns 1 if flush, 0 otherwise */
 
-void oob()
+int server_message(mark)
+     int mark;
 {
 #ifndef POSIX_TERMIOS
     int out = FWRITE;
 #endif
-    int atmark, n;
+    int n;
     int rcvd = 0;
-    char waste[RLOGIN_BUFSIZ], mark;
 #ifdef POSIX_TERMIOS
     struct termios tty;
 #else
@@ -1203,9 +1251,7 @@ void oob()
     struct sgttyb sb;
 #endif
 #endif
-    mark = 0;
-    
-    recv(rem, &mark, 1, MSG_OOB);
+
     if (mark & TIOCPKT_WINDOW) {
        /*
         * Let server know about window size changes
@@ -1263,27 +1309,62 @@ void oob()
        (void) ioctl(1, TCFLSH, 1);
 #endif
 #endif
-       for (;;) {
-           if (ioctl(rem, SIOCATMARK, &atmark) < 0) {
-               perror("ioctl");
-               break;
-           }
-           if (atmark)
-             break;
-           n = read(rem, waste, sizeof (waste));
-           if (n <= 0)
-             break;
-return;
-       }
+       return(1);
     }
+
+    return(0);
+}
+
+void oob()
+{
+    char mark;
+    char waste[RLOGIN_BUFSIZ];
+    int atmark;
+
+    mark = 0;
     
-    
+    recv(rem, &mark, 1, MSG_OOB);
+
+    if (server_message(mark)) {
+       if (ioctl(rem, SIOCATMARK, &atmark) < 0) {
+           perror("ioctl");
+           return;
+       }
+       if (!atmark)
+           read(rem, waste, sizeof (waste));
+    }
 }
 
+/* two control messages are defined:
 
+   a double flag byte of 'o' indicates a one-byte message which is
+   identical to what was once carried out of band.  
+
+   a double flag byte of 'q' indicates a zero-byte message.  This
+   message is interpreted as two \377 data bytes.  This is just a
+   quote rule so that binary data from the server does not confuse the
+   client.  */
+
+int control(cp, n)
+     unsigned char *cp;
+     int n;
+{
+    if ((n >= 5) && (cp[2] == 'o') && (cp[3] == 'o')) {
+       if (server_message(cp[4]))
+           return(-5);
+       return(5);
+    } else if ((n >= 4) && (cp[2] == 'q') && (cp[3] == 'q')) {
+       /* this is somewhat of a hack */
+       cp[2] = '\377';
+       cp[3] = '\377';
+       return(2);
+    }
+
+    return(0);
+}
 
 /*
- * reader: read from remote: line -> 1
+ * reader: read from remote: line -> 1 
  */
 reader(oldmask)
 #ifdef POSIX_SIGNALS
@@ -1298,8 +1379,9 @@ reader(oldmask)
     int pid = -getpid();
 #endif
 fd_set readset, excset, writeset;
-    int n, remaining;
+    int n, remaining, left;
     char *bufp = rcvbuf;
+    char *cp;
 
 #ifdef POSIX_SIGNALS
     struct sigaction sa;
@@ -1326,24 +1408,23 @@ fd_set readset, excset, writeset;
 #endif /* POSIX_SIGNALS */
 
     for (;;) {
-       if ((remaining = rcvcnt - (bufp - rcvbuf)) > 0)
-       {
+       if ((remaining = rcvcnt - (bufp - rcvbuf)) > 0) {
            FD_SET(1,&writeset);
            rcvstate = WRITING;
            FD_CLR(rem, &readset);
+       } else {
+           bufp = rcvbuf;
+           rcvcnt = 0;
+           rcvstate = READING;
+           FD_SET(rem,&readset);
+           FD_CLR(1,&writeset);
        }
-       else {
-           
-       bufp = rcvbuf;
-       rcvcnt = 0;
-       rcvstate = READING;
-       FD_SET(rem,&readset);
-       FD_CLR(1,&writeset);
-       }
-       FD_SET(rem,&excset);
+       if (!do_inband)
+           FD_SET(rem,&excset);
        if (select(rem+1, &readset, &writeset, &excset, 0) > 0 ) {
-           if (FD_ISSET(rem, &excset))
-               oob();
+           if (!do_inband)
+               if (FD_ISSET(rem, &excset))
+                   oob();
            if (FD_ISSET(1,&writeset)) {
                n = write(1, bufp, remaining);
                if (n < 0) {
@@ -1359,6 +1440,30 @@ fd_set readset, excset, writeset;
                    return (0);
                if (rcvcnt < 0)
                    goto error;
+
+               if (do_inband) {
+                   for (cp = rcvbuf; cp < rcvbuf+rcvcnt-1; cp++) {
+                       if (cp[0] == '\377' &&
+                           cp[1] == '\377') {
+                           left = (rcvbuf+rcvcnt) - cp;
+                           n = control(cp, left);
+                           if (n < 0) {
+                               left -= (-n);
+                               rcvcnt = 0;
+                               /* flush before, and (-n) bytes */
+                               if (left > 0)
+                                   memmove(rcvbuf, cp+(-n), left);
+                               cp = rcvbuf-1;
+                           } else if (n) {
+                               left -= n;
+                               rcvcnt -= n;
+                               if (left > 0)
+                                   memmove(cp, cp+n, left);
+                               cp--;
+                           }
+                       }
+                   }
+               }
            }
        } else
 error:
index bd376ff098313a567f736e4e6ef41730ee3030e3..f433897190f887077d56adc0ec3a1e68b4277c89 100644 (file)
  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  */
 
+/*
+ * Copyright (C) 1998 by the FundsXpress, INC.
+ * 
+ * All rights reserved.
+ * 
+ * Export of this software from the United States of America may require
+ * a specific license from the United States Government.  It is the
+ * responsibility of any person or organization contemplating export to
+ * obtain such a license before exporting.
+ * 
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of FundsXpress. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  FundsXpress makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
 #ifndef lint
 char copyright[] =
   "@(#) Copyright (c) 1983 The Regents of the University of California.\n\
@@ -266,6 +292,7 @@ char            *krusername = 0;
 char           term[64];
 char            rhost_name[128];
 krb5_principal  client;
+int            do_inband = 0;
 
 int    reapchild();
 char   *progname;
@@ -837,6 +864,31 @@ unsigned char      oobdata[] = {TIOCPKT_WINDOW};
 char    oobdata[] = {0};
 #endif
 
+int sendoob(fd, byte)
+     int fd;
+     char *byte;
+{
+    char message[5];
+    int cc;
+
+    if (do_inband) {
+       message[0] = '\377';
+       message[1] = '\377';
+       message[2] = 'o';
+       message[3] = 'o';
+       message[4] = *byte;
+
+       cc = rcmd_stream_write(fd, message, sizeof(message));
+       while (cc < 0 && ((errno == EWOULDBLOCK) || (errno == EAGAIN))) {
+           /* also shouldn't happen */
+           sleep(5);
+           cc = rcmd_stream_write(fd, message, sizeof(message));
+       }
+    } else {
+       send(fd, byte, 1, MSG_OOB);
+    }
+}
+
 /*
  * Handle a "control" request (signaled by magic being present)
  * in the data stream.  For now, we are only willing to handle
@@ -880,7 +932,7 @@ int control(pty, cp, n)
 void protocol(f, p)
      int f, p;
 {
-    unsigned char pibuf[BUFSIZ], fibuf[BUFSIZ], *pbp, *fbp;
+    unsigned char pibuf[BUFSIZ], qpibuf[BUFSIZ*2], fibuf[BUFSIZ], *pbp, *fbp;
     register pcc = 0, fcc = 0;
     int cc;
     char cntl;
@@ -915,7 +967,7 @@ void protocol(f, p)
     signal(SIGTTOU, SIG_IGN);
 #endif
 #ifdef TIOCSWINSZ
-    send(f, oobdata, 1, MSG_OOB);      /* indicate new rlogin */
+    sendoob(f, oobdata);
 #endif
     for (;;) {
        fd_set ibits, obits, ebits;
@@ -933,7 +985,6 @@ void protocol(f, p)
                FD_SET(f, &obits);
            else
                FD_SET(p, &ibits);
-       FD_SET(p, &ebits);
        
        if (select(8*sizeof(ibits), &ibits, &obits, &ebits, 0) < 0) {
            if (errno == EINTR)
@@ -941,43 +992,32 @@ void protocol(f, p)
            fatalperror(f, "select");
        }
 #define        pkcontrol(c)    ((c)&(TIOCPKT_FLUSHWRITE|TIOCPKT_NOSTOP|TIOCPKT_DOSTOP))
-       if (FD_ISSET(p, &ebits)) {
-           cc = read(p, &cntl, 1);
-           if (cc == 1 && pkcontrol(cntl)) {
-               cntl |= oobdata[0];
-               send(f, &cntl, 1, MSG_OOB);
-               if (cntl & TIOCPKT_FLUSHWRITE) {
-                   pcc = 0;
-                   FD_CLR(p, &ibits);
-               }
-           }
-       }
        if (FD_ISSET(f, &ibits)) {
            fcc = rcmd_stream_read(f, fibuf, sizeof (fibuf));
-           if (fcc < 0 && ((errno == EWOULDBLOCK) || (errno == EAGAIN)))
-             fcc = 0;
-           else {
+           if (fcc < 0 && ((errno == EWOULDBLOCK) || (errno == EAGAIN))) {
+               fcc = 0;
+           else {
                register unsigned char *cp;
                int left, n;
                
                if (fcc <= 0)
-                 break;
+                   break;
                fbp = fibuf;
                
-             top:
-               for (cp = fibuf; cp < fibuf+fcc-1; cp++)
-                 if (cp[0] == magic[0] &&
-                     cp[1] == magic[1]) {
-                     left = fcc - (cp-fibuf);
-                     n = control(p, cp, left);
-                     if (n) {
-                         left -= n;
-                         if (left > 0)
-                           memmove(cp, cp+n, left);
-                         fcc -= n;
-                         goto top; /* n^2 */
-                     }
-                 }
+               for (cp = fibuf; cp < fibuf+fcc-1; cp++) {
+                   if (cp[0] == magic[0] &&
+                       cp[1] == magic[1]) {
+                       left = (fibuf+fcc) - cp;
+                       n = control(p, cp, left);
+                       if (n) {
+                           left -= n;
+                           fcc -= n;
+                           if (left > 0)
+                               memmove(cp, cp+n, left);
+                           cp--;
+                       }
+                   }
+               }
            }
        }
        
@@ -992,24 +1032,54 @@ void protocol(f, p)
        if (FD_ISSET(p, &ibits)) {
            pcc = read(p, pibuf, sizeof (pibuf));
            pbp = pibuf;
-           if (pcc < 0 && ((errno == EWOULDBLOCK) || (errno == EAGAIN)))
-             pcc = 0;
-           else if (pcc <= 0)
-             break;
+           if (pcc < 0 && ((errno == EWOULDBLOCK) || (errno == EAGAIN))) {
+               pcc = 0;
+           } else if (pcc <= 0) {
+               break;
+           }
 #ifdef TIOCPKT
            else if (tiocpkt_on) {
-             if (pibuf[0] == 0)
-               pbp++, pcc--;
-             else {
-                 if (pkcontrol(pibuf[0])) {
-                     pibuf[0] |= oobdata[0];
-                     send(f, &pibuf[0], 1, MSG_OOB);
-                 }
-                 pcc = 0;
-             }
+               if (pibuf[0] == 0) {
+                   pbp++, pcc--;
+               } else {
+                   if (pkcontrol(pibuf[0])) {
+                       pibuf[0] |= oobdata[0];
+                       sendoob(f, pibuf);
+                   }
+                   pcc = 0;
+               }
            }
 #endif
+
+           /* quote any double-\377's if necessary */
+
+           if (do_inband) {
+               unsigned char *qpbp;
+               int qpcc, i;
+
+               qpbp = qpibuf;
+               qpcc = 0;
+
+               for (i=0; i<pcc;) {
+                   if (pbp[i] == 0377u && (i+1)<pcc && pbp[i+1] == 0377u) {
+                       qpbp[qpcc] = '\377';
+                       qpbp[qpcc+1] = '\377';
+                       qpbp[qpcc+2] = 'q';
+                       qpbp[qpcc+3] = 'q';
+                       i += 2;
+                       qpcc += 4;
+                   } else {
+                       qpbp[qpcc] = pbp[i];
+                       i++;
+                       qpcc++;
+                   }
+               }
+
+               pbp = qpbp;
+               pcc = qpcc;
+           }
        }
+
        if (FD_ISSET(f, &obits) && pcc > 0) {
            cc = rcmd_stream_write(f, pbp, pcc);
            if (cc < 0 && ((errno == EWOULDBLOCK) || (errno == EAGAIN))) {
@@ -1411,6 +1481,21 @@ recvauth(valid_checksum)
 
     rcmd_stream_init_krb5(ticket->enc_part2->session, do_encrypt, 1);
 
+    {
+       krb5_boolean similar;
+
+       if (status = krb5_c_enctype_compare(bsd_context, ENCTYPE_DES_CBC_CRC,
+                                          ticket->enc_part2->session->enctype,
+                                          &similar))
+         return(status);
+
+       if (!similar) {
+         do_inband = 1;
+         syslog(LOG_DEBUG, "setting do_inband");
+       }
+    }
+
+
     getstr(netf, rusername, sizeof(rusername), "remuser");
 
     if ((status = krb5_unparse_name(bsd_context, client, &krusername)))
index cb18f4c2c5d886d768d52442c9fe634bf1d21cf2..c8017cc77b4028a905d02ffccfc7e1d99df09b31 100644 (file)
@@ -48,6 +48,7 @@ char copyright[] =
 */
 #define KRB5_GET_TICKETS
 int login_krb5_get_tickets = 1;
+
 #ifdef KRB5_KRB4_COMPAT
 #define KRB4_GET_TICKETS
 int login_krb4_get_tickets = 0;
@@ -56,6 +57,7 @@ int login_krb4_convert = 0;
 #define KRB_RUN_AKLOG
 int login_krb_run_aklog = 0;
 #endif /* KRB5_KRB4_COMPAT */
+
 int login_accept_passwd = 0;
 
 /*
@@ -189,10 +191,10 @@ typedef sigtype (*handler)();
 
 #ifndef HAVE_KRB_GET_ERR_TEXT
 
-static const char * krb_get_err_text(kerror)
-  int kerror;
+static const char *krb_get_err_text(kerror)
+     int kerror;
 {
-  return krb_err_txt[kerror];
+    return krb_err_txt[kerror];
 }
 
 #endif /*HAVE_KRB_GET_ERR_TEXT*/
@@ -326,52 +328,58 @@ typedef krb5_sigtype sigtype;
 
 #ifndef HAVE_INITGROUPS
 static int initgroups(char* name, gid_t basegid) {
-  gid_t others[NGROUPS_MAX+1];
-  int ngrps;
+    gid_t others[NGROUPS_MAX+1];
+    int ngrps;
 
-  others[0] = basegid;
-  ngrps = getgroups(NGROUPS_MAX, others+1);
-  return setgroups(ngrps+1, others);
+    others[0] = basegid;
+    ngrps = getgroups(NGROUPS_MAX, others+1);
+    return setgroups(ngrps+1, others);
 }
 #endif
 
-#ifdef KRB5_GET_TICKETS
 static struct login_confs {
-       char *flagname;
-       int *flag;
+    char *flagname;
+    int *flag;
 } login_conf_set[] = {
-       "krb5_get_tickets", &login_krb5_get_tickets,
+#ifdef KRB5_GET_TICKETS
+    "krb5_get_tickets", &login_krb5_get_tickets,
+#endif
 #ifdef KRB5_KRB4_COMPAT
-       "krb4_get_tickets", &login_krb4_get_tickets,
-       "krb4_convert", &login_krb4_convert,
-       "krb4_run_aklog", &login_krb_run_aklog,
+    "krb4_get_tickets", &login_krb4_get_tickets,
+    "krb4_convert", &login_krb4_convert,
+    "krb4_run_aklog", &login_krb_run_aklog,
 #endif /* KRB5_KRB4_COMPAT */
 };
+
 static char *conf_yes[] = {
-       "y", "yes", "true", "t", "1", "on",
-       0
+    "y", "yes", "true", "t", "1", "on",
+    0
 };
+
 static char *conf_no[] = {
-       "n", "no", "false", "nil", "0", "off",
-       0
+    "n", "no", "false", "nil", "0", "off",
+    0
 };
+
 /* 1 = true, 0 = false, -1 = ambiguous */
 static int conf_affirmative(s)
-       char *s;
+     char *s;
 {
-       char **p;
-       for(p=conf_yes; *p; p++) {
-               if (!strcasecmp(*p,s))
-                       return 1;
-       }
-       for(p=conf_no; *p; p++) {
-               if (!strcasecmp(*p,s))
-                       return 0;
-       }
-       /* ambiguous */
-       return -1;
+    char **p;
+
+    for(p=conf_yes; *p; p++) {
+       if (!strcasecmp(*p,s))
+           return 1;
+    }
+
+    for(p=conf_no; *p; p++) {
+       if (!strcasecmp(*p,s))
+           return 0;
+    }
+
+    /* ambiguous */
+    return -1;
 }
-#endif /* KRB5_GET_TICKETS */
 
 #ifdef KRB5_GET_TICKETS
 krb5_data tgtname = {
@@ -381,46 +389,43 @@ krb5_data tgtname = {
 };
 #endif
 
-#ifdef KRB5_GET_TICKETS
 /* get flags (listed above) from the profile */
 void login_get_kconf(k)
-       krb5_context k;
+     krb5_context k;
 {
-       int i, max_i;
-       const char* kconf_names[3];
-       char **kconf_val;
-       int retval;
-
-       max_i = sizeof(login_conf_set)/sizeof(struct login_confs);
-       for (i = 0; i<max_i; i++) {
-               kconf_names[0] = "login";
-               kconf_names[1] = login_conf_set[i].flagname;
-               kconf_names[2] = 0;
-               retval = profile_get_values(k->profile, 
-                                           kconf_names, &kconf_val);
-               if (retval) {
-                 /* ignore most (all?) errors */
-               } else if (kconf_val) {
-                       switch(conf_affirmative(*kconf_val)) {
-                       case 1:
-                               *login_conf_set[i].flag = 1;
-                               break;
-                       case 0:
-                               *login_conf_set[i].flag = 0;
-                               break;
-                       default:
-                       case -1:
-                               com_err("login/kconf", 0,
-                                       "invalid flag value %s for flag %s",
-                                       *kconf_val, kconf_names[1]);
-                               break;
-                       }
-               }
+    int i, max_i;
+    const char* kconf_names[3];
+    char **kconf_val;
+    int retval;
+
+    max_i = sizeof(login_conf_set)/sizeof(struct login_confs);
+    for (i = 0; i<max_i; i++) {
+       kconf_names[0] = "login";
+       kconf_names[1] = login_conf_set[i].flagname;
+       kconf_names[2] = 0;
+       retval = profile_get_values(k->profile, 
+                                   kconf_names, &kconf_val);
+       if (retval) {
+           /* ignore most (all?) errors */
+       } else if (kconf_val) {
+           switch(conf_affirmative(*kconf_val)) {
+           case 1:
+               *login_conf_set[i].flag = 1;
+               break;
+           case 0:
+               *login_conf_set[i].flag = 0;
+               break;
+           default:
+           case -1:
+               com_err("login/kconf", 0,
+                       "invalid flag value %s for flag %s",
+                       *kconf_val, kconf_names[1]);
+               break;
+           }
        }
+    }
 }
-#endif /* KRB5_GET_TICKETS */
 
-\f
 /* UNIX password support */
 
 struct passwd *pwd;
@@ -475,16 +480,19 @@ int unix_passwd_okay (pass)
 #endif
     return !strcmp (namep, pwd->pw_passwd);
 }
-\f
+
 /* Kerberos support */
 #ifdef KRB5_GET_TICKETS
 krb5_context kcontext;
 krb5_ccache ccache;
-static int got_v5_tickets, got_v4_tickets;
+krb5_creds my_creds;
+static int got_v5_tickets, forwarded_v5_tickets;
 char ccfile[MAXPATHLEN+6];     /* FILE:path+\0 */
 int krbflag;                   /* set if tickets have been obtained */
+#endif /* KRB5_GET_TICKETS */
 
 #ifdef KRB4_GET_TICKETS
+static int got_v4_tickets;
 AUTH_DAT *kdata = (AUTH_DAT *) NULL;
 KTEXT ticket = (KTEXT) NULL;
 char tkfile[MAXPATHLEN];
@@ -494,6 +502,7 @@ char realm[REALM_SZ];
 void k_init (ttyn)
     char *ttyn;
 {
+#ifdef KRB5_GET_TICKETS
     krb5_error_code retval;
     
     retval = krb5_init_context(&kcontext);
@@ -501,6 +510,7 @@ void k_init (ttyn)
        com_err("login", retval, "while initializing krb5");
        exit(1);
     }
+
     krb5_secure_config_files (kcontext);
     login_get_kconf(kcontext);
 
@@ -514,6 +524,7 @@ void k_init (ttyn)
        strncpy(ccfile, getenv(KRB5_ENV_CCNAME), sizeof(ccfile));
        ccfile[sizeof(ccfile) - 1] = '\0';
     }
+#endif
 
 #ifdef KRB4_GET_TICKETS
     if (krb_get_lrealm(realm, 1) != KSUCCESS) {
@@ -539,6 +550,7 @@ void k_init (ttyn)
 #endif /* BIND_HACK */
 }
 
+#ifdef KRB5_GET_TICKETS
 int k5_get_password (user_pwstring, pwsize)
     char *user_pwstring;
 {
@@ -561,76 +573,23 @@ int k5_get_password (user_pwstring, pwsize)
     return 1;
 }
 
-#define KRB5_DEFAULT_LIFE 60*60*10 /* 10 hours */
-int krb5_options = 0;
-krb5_deltat krb5_ticket_lifetime = KRB5_DEFAULT_LIFE;
-
 int try_krb5 (me_p, pass)
     krb5_principal *me_p;
     char *pass;
 {
     krb5_error_code code;
-    krb5_principal server, me;
-    krb5_creds my_creds;
-    krb5_timestamp now;
-    krb5_deltat lifetime = krb5_ticket_lifetime;
-
-    /* set up credential cache -- obeying KRB5_ENV_CCNAME 
-       set earlier */
-    /* (KRB5_ENV_CCNAME == "KRB5CCNAME" via osconf.h) */
-    if ((code = krb5_cc_default(kcontext, &ccache))) {
-       com_err("login", code, "while getting default ccache");
-       return 0;
-    }
-    /* setup code from v5 kinit */
-    memset((char *)&my_creds, 0, sizeof(my_creds));
+    krb5_principal me;
 
-    code = krb5_parse_name (kcontext, username, &me);
-    if (code) {
+    if (code = krb5_parse_name(kcontext, username, &me)) {
        com_err ("login", code, "when parsing name %s",username);
        return 0;
     }
-    *me_p = my_creds.client = me;
 
-    code = krb5_cc_initialize (kcontext, ccache, me);
-    if (code) {
-       com_err ("login", code, 
-                "when initializing cache");
-       return 0;
-    }
+    *me_p = me;
 
-    code = krb5_build_principal_ext(kcontext, &server,
-                                   krb5_princ_realm(kcontext, me)->length,
-                                   krb5_princ_realm(kcontext, me)->data,
-                                   tgtname.length, tgtname.data,
-                                   krb5_princ_realm(kcontext, me)->length,
-                                   krb5_princ_realm(kcontext, me)->data,
-                                   0);
-    if (code) {
-       com_err("login", code,
-               "while building server name");
-       goto nuke_ccache;
-    }
-
-    my_creds.server = server;
-    code = krb5_timeofday(kcontext, &now);
-    if (code) {
-       com_err("login", code,
-               "while getting time of day");
-       goto nuke_ccache;
-    }
-    my_creds.times.starttime = 0; /* start timer when 
-                                    request gets to KDC */
-    my_creds.times.endtime = now + lifetime;
-    my_creds.times.renew_till = 0;
-
-    code = krb5_get_in_tkt_with_password(kcontext, krb5_options,
-                                        0, NULL, 0 /*preauth*/,
-                                        pass,
-                                        ccache,
-                                        &my_creds, 0);
-
-    if (code) {
+    if (code = krb5_get_init_creds_password(kcontext, &my_creds, me, pass,
+                                           krb5_prompter_posix, NULL,
+                                           0, NULL, NULL)) {
        if (code == KRB5KRB_AP_ERR_BAD_INTEGRITY)
            fprintf (stderr,
                     "%s: Kerberos password incorrect\n", 
@@ -638,17 +597,12 @@ int try_krb5 (me_p, pass)
        else
            com_err ("login", code,
                     "while getting initial credentials");
-    nuke_ccache:
-       krb5_cc_destroy (kcontext, ccache);
        return 0;
-    } else {
-       /* get_name pulls out just the name not the
-          type */
-       strncpy(ccfile, krb5_cc_get_name(kcontext, ccache), sizeof(ccfile));
-       ccfile[sizeof(ccfile) - 1] = '\0';
-       krbflag = got_v5_tickets = 1;
-       return 1;
     }
+
+    krbflag = got_v5_tickets = 1;
+
+    return 1;
 }
 
 int have_v5_tickets (me)
@@ -663,6 +617,7 @@ int have_v5_tickets (me)
     krbflag = 1;
     return 1;
 }
+#endif /* KRB5_GET_TICKETS */
 
 #ifdef KRB4_CONVERT
 try_convert524 (kcontext, me)
@@ -675,8 +630,6 @@ try_convert524 (kcontext, me)
     krb5_creds increds, *v5creds;
     CREDENTIALS v4creds;
 
-    if (!got_v5_tickets)
-       return 0;
 
     /* or do this directly with krb524_convert_creds_kdc */
     krb524_init_ets(kcontext);
@@ -886,162 +839,23 @@ EGRESS:
 }
 #endif /* KRB4_GET_TICKETS */
 
-/* call already conditionalized on login_krb5_get_tickets */
-/*
- * Verify the Kerberos ticket-granting ticket just retrieved for the
- * user.  If the Kerberos server doesn't respond, assume the user is
- * trying to fake us out (since we DID just get a TGT from what is
- * supposedly our KDC).  If the host/<host> service is unknown (i.e.,
- * the local keytab doesn't have it), let her in.
- *
- * Returns 1 for confirmation, -1 for failure, 0 for uncertainty.
- */
-int verify_krb_v5_tgt (c)
-    krb5_context c;
+void destroy_tickets()
 {
-    char phost[BUFSIZ];
-    krb5_ccache ccdef;
-    int retval, have_keys;
-    krb5_principal princ;
-    krb5_keyblock *kb = 0;
-    krb5_error_code krbval;
-    krb5_data packet;
-    krb5_auth_context auth_context = NULL;
-    krb5_ticket *ticket = NULL;
-
-    /* XXX This is to work around a library bug.  I'm not sure if it's
-       been fixed for beta-7, so leave this in for now.  Remove it (and
-       fix the bug if necessary) after beta-7 ships.
-
-       Whoever wrote that comment didn't mention what the bug is!  Ted
-       says it is something about the starttime of the ticket and
-       "now" being equal.  He thinks it is fixed, but isn't sure.
-       */
-    sleep(2);
-
-    /* get the server principal for the local host */
-    /* (use defaults of "host" and canonicalized local name) */
-    krbval = krb5_sname_to_principal(c, 0, 0, KRB5_NT_SRV_HST, &princ);
-    if (krbval) {
-           com_err ("login", krbval, "constructing local service name");
-           return -1;
-    }
+#ifdef KRB5_GET_TICKETS
+    krb5_ccache cache;
+    krb5_error_code retval;
 
-    /* since krb5_sname_to_principal has done the work for us, just
-       extract the name directly */
-    strncpy(phost, krb5_princ_component(c, princ, 1)->data, sizeof(phost));
-    phost[sizeof(phost) - 1] = '\0';
-
-    /* Do we have host/<host> keys? */
-    /* (use default keytab, kvno IGNORE_VNO to get the first match,
-       and enctype is currently ignored anyhow.) */
-    krbval = krb5_kt_read_service_key (c, NULL, princ, 0, ENCTYPE_DES_CBC_CRC, &kb);
-    if (kb)
-       krb5_free_keyblock (c, kb);
-    /* any failure means we don't have keys at all. */
-    have_keys = krbval ? 0 : 1;
-
-    /* set up credential cache -- obeying KRB5_ENV_CCNAME set earlier */
-    /* (KRB5_ENV_CCNAME == "KRB5CCNAME" via osconf.h) */
-    if (krbval = krb5_cc_default(c, &ccdef)) {
-       com_err("login", krbval, "while getting default ccache");
-       return -1;
-    }
-    /* talk to the kdc and construct the ticket */
-    krbval = krb5_mk_req(c, &auth_context, 0, "host", phost,
-                        0, ccdef, &packet);
-    /* wipe the auth context for mk_req */
-    if (auth_context) {
-       krb5_auth_con_free(c, auth_context);
-       auth_context = NULL;
-    }
-    if (krbval == KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN) {
-           /* we have a service key, so something should be 
-              in the database, therefore this error packet could
-              have come from an attacker. */
-           if (have_keys) { retval = -1; goto EGRESS; }
-           /* but if it is unknown and we've got no key, we don't
-              have any security anyhow, so it is ok. */
-           else { retval = 0; goto EGRESS; }
-    }
-    else if (krbval) {
-           com_err("login", krbval, 
-                   "Unable to verify Kerberos V5 TGT: %s", phost);
-#ifndef SYSLOG42
-           syslog (LOG_NOTICE|LOG_AUTH, "Kerberos V5 TGT bad: %s", 
-                   error_message(krbval));
-#endif
-           retval = -1;
-           goto EGRESS;
-    }
-    /* got ticket, try to use it */
-    krbval = krb5_rd_req(c, &auth_context, &packet, 
-                        princ, NULL, NULL, &ticket);
-    if (krbval) {
-       if (!have_keys)
-           /* The krb5 errors aren't specified well, but I think
-              these values cover the cases we expect.  */
-           switch (krbval) {
-               /* no keytab */
-           case ENOENT:
-               /* keytab found, missing entry */
-#if 0 /* Don't depend on the nameserver for security.  Assume that if
-        we have a keytab, it must contain the right host/FQDN key.  */
-           case KRB5_KT_NOTFOUND:
-#endif
-               retval = 0;
-               break;
-           default:
-               /* unexpected error: fail */
-               retval = -1;
-               break;
-           }
-       else
-           /* Any error here is bad.  */
-           retval = -1;
-       com_err("login", krbval, "Unable to verify host ticket");
-#ifndef SYSLOG42
-       syslog (LOG_NOTICE|LOG_AUTH, "can't verify v5 ticket: %s; %s\n",
-               error_message(krbval),
-               retval
-               ? "keytab found, assuming failure"
-               : "no keytab found, assuming success");
-#endif
-       goto EGRESS;
+    if (login_krb5_get_tickets) {
+       if(!krb5_cc_default(kcontext, &cache))
+         krb5_cc_destroy (kcontext, cache);
     }
-    /*
-     * The host/<host> ticket has been received _and_ verified.
-     */
-    retval = 1;
-    /* do cleanup and return */
-EGRESS:
-    if (auth_context) krb5_auth_con_free(c, auth_context);
-    krb5_free_principal(c, princ);
-    /* possibly ticket and packet need freeing here as well */
-    /* memset (&ticket, 0, sizeof (ticket)); */
-    return retval;
-}
-
-destroy_tickets()
-{
-       krb5_context c;
-       krb5_ccache cache;
-       krb5_error_code retval;
-
-#ifdef KRB5_GET_TICKETS
-       if (login_krb5_get_tickets) {
-           if(!krb5_cc_default(kcontext, &cache))
-               krb5_cc_destroy (kcontext, cache);
-       }
 #endif
 #ifdef KRB4_GET_TICKETS
-       if (login_krb4_get_tickets||login_krb4_convert)
+    if (login_krb4_get_tickets || login_krb4_convert)
        dest_tkt();
 #endif /* KRB4_GET_TICKETS */
 }
 
-#endif /* KRB5_GET_TICKETS */
-\f
 /* AFS support routines */
 #ifdef SETPAG
 
@@ -1086,15 +900,13 @@ static int try_afscall (scall)
 void
 afs_login ()
 {
-#ifdef KRB4_GET_TICKETS
-#ifdef SETPAG
+#if defined(KRB4_GET_TICKETS) && defined(SETPAG)
     if (login_krb4_get_tickets && pwd->pw_uid) {
        /* Only reset the pag for non-root users. */
        /* This allows root to become anything. */
        pagflag = try_setpag ();
     }
 #endif
-#endif /* KRB4_GET_TICKETS */
 #ifdef KRB_RUN_AKLOG
     if (got_v4_tickets && login_krb_run_aklog) {
        /* KPROGDIR is $(prefix)/bin */
@@ -1120,19 +932,19 @@ afs_cleanup ()
       try_unlog ();
 #endif
 }
-\f
+
 /* Main routines */
 #define EXCL_AUTH_TEST if (rflag || kflag || Kflag || eflag || fflag ) { \
-                               fprintf(stderr, \
-                                   "login: only one of -r, -k, -K, -e, -F, and -f allowed.\n"); \
-                               exit(1);\
-                       }
+    fprintf(stderr, \
+           "login: only one of -r, -k, -K, -e, -F, and -f allowed.\n"); \
+    exit(1); \
+}
 
 #define EXCL_HOST_TEST if (rflag || kflag || Kflag || hflag) { \
-                               fprintf(stderr, \
-                                   "login: only one of -r, -k, -K, and -h allowed.\n"); \
-                               exit(1);\
-                       }
+    fprintf(stderr, \
+           "login: only one of -r, -k, -K, and -h allowed.\n"); \
+    exit(1); \
+}
 
 static void
 read_env_vars_from_file (filename)
@@ -1142,7 +954,7 @@ read_env_vars_from_file (filename)
     char *p, *eq;
     char tbuf[MAXPATHLEN+2];
 
-    if ((fp = fopen("/etc/environment", "r")) != NULL) {
+    if ((fp = fopen(filename, "r")) != NULL) {
        while (fgets(tbuf, sizeof(tbuf), fp)) {
            if (tbuf[0] == '#')
                continue;
@@ -1176,467 +988,480 @@ log_repeated_failures (tty, hostname)
               tty, hostname, UT_NAMESIZE,
               username);
 #endif
-    }
-    else
+    } else {
        syslog(LOG_ERR,
               "REPEATED LOGIN FAILURES ON %s, %.*s",
               tty, UT_NAMESIZE, username);
+    }
 }
 
 int main(argc, argv)
-       int argc;
-       char **argv;
+     int argc;
+     char **argv;
 {
-       extern int optind;
-       extern char *optarg, **environ;
-       struct group *gr;
-       int ch;
-       char *p;
-       int fflag, hflag, pflag, rflag, cnt;
-       int kflag, Kflag, eflag;
-       int quietlog, passwd_req, ioctlval;
-       sigtype timedout();
-       char *domain, **envinit, *ttyn, *tty;
-       char tbuf[MAXPATHLEN + 2];
-       char *ttyname(), *stypeof(), *crypt(), *getpass();
-       time_t login_time;
-       int retval;
-int rewrite_ccache = 1; /*try to write out ccache*/
+    extern int optind;
+    extern char *optarg, **environ;
+    struct group *gr;
+    int ch;
+    char *p;
+    int fflag, hflag, pflag, rflag, cnt;
+    int kflag, Kflag, eflag;
+    int quietlog, passwd_req, ioctlval;
+    sigtype timedout();
+    char *domain, **envinit, *ttyn, *tty;
+    char tbuf[MAXPATHLEN + 2];
+    char *ttyname(), *stypeof(), *crypt(), *getpass();
+    time_t login_time;
+    int retval;
+    int rewrite_ccache = 1; /*try to write out ccache*/
 #ifdef KRB5_GET_TICKETS
-       krb5_principal me;
-       krb5_creds save_v5creds;
+    krb5_principal me;
+    krb5_creds save_v5creds;
+    krb5_ccache xtra_creds = NULL;
 #endif
 #ifdef KRB4_GET_TICKETS
-       CREDENTIALS save_v4creds;
+    CREDENTIALS save_v4creds;
 #endif
-       char *ccname = 0;   /* name of forwarded cache */
-       char *tz = 0;
+    char *ccname = 0;   /* name of forwarded cache */
+    char *tz = 0;
 
-       off_t lseek();
-       handler sa;
+    off_t lseek();
+    handler sa;
 
-       handler_init (sa, timedout);
-       handler_set (SIGALRM, sa);
-       (void)alarm((u_int)timeout);
+    handler_init (sa, timedout);
+    handler_set (SIGALRM, sa);
+    (void)alarm((u_int)timeout);
 
-       handler_init (sa, SIG_IGN);
-       handler_set (SIGQUIT, sa);
-       handler_set (SIGINT, sa);
-       setpriority(PRIO_PROCESS, 0, 0 + PRIO_OFFSET);
+    handler_init (sa, SIG_IGN);
+    handler_set (SIGQUIT, sa);
+    handler_set (SIGINT, sa);
+    setpriority(PRIO_PROCESS, 0, 0 + PRIO_OFFSET);
 #ifdef OQUOTA
-       (void)quota(Q_SETUID, 0, 0, 0);
+    (void)quota(Q_SETUID, 0, 0, 0);
 #endif
 
-       /*
-        * -p is used by getty to tell login not to destroy the environment
-        * -r is used by rlogind to cause the autologin protocol;
-        * -f is used to skip a second login authentication 
-        * -F is used to skip a second login authentication, allows login as root 
-        * -e is used to skip a second login authentication, but allows
-        *      login as root.
-        * -h is used by other servers to pass the name of the
-        * remote host to login so that it may be placed in utmp and wtmp
-        * -k is used by klogind to cause the Kerberos V4 autologin protocol;
-        * -K is used by klogind to cause the Kerberos V4 autologin
-        *    protocol with restricted access.
-        */
-       (void)gethostname(tbuf, sizeof(tbuf));
-       domain = strchr(tbuf, '.');
-
-        fflag = hflag = pflag = rflag = kflag = Kflag = eflag = 0;
-       passwd_req = 1;
-       while ((ch = getopt(argc, argv, "Ffeh:pr:k:K:")) != -1)
-               switch (ch) {
-               case 'f':
-                       EXCL_AUTH_TEST;
-                       fflag = 1;
-                       break;
-               case 'F':
-                       EXCL_AUTH_TEST;
-                       fflag = 1;
-                       break;
-               case 'h':
-                       EXCL_HOST_TEST;
-                       if (getuid()) {
-                               fprintf(stderr,
-                                   "login: -h for super-user only.\n");
-                               exit(1);
-                       }
-                       hflag = 1;
-                       if (domain && (p = strchr(optarg, '.')) &&
-                           strcmp(p, domain) == 0)
-                               *p = 0;
-                       hostname = optarg;
-                       break;
-               case 'p':
-                       pflag = 1;
-                       break;
-               case 'r':
-                       EXCL_AUTH_TEST;
-                       EXCL_HOST_TEST;
-                       if (getuid()) {
-                               fprintf(stderr,
-                                   "login: -r for super-user only.\n");
-                               exit(1);
-                       }
-                       /* "-r hostname" must be last args */
-                       if (optind != argc) {
-                               fprintf(stderr, "Syntax error.\n");
-                               exit(1);
-                       }
-                       rflag = 1;
-                       passwd_req = (doremotelogin(optarg) == -1);
-                       if (domain && (p = strchr(optarg, '.')) &&
-                           !strcmp(p, domain))
-                               *p = '\0';
-                       hostname = optarg;
-                       break;
+    /*
+     * -p is used by getty to tell login not to destroy the environment
+     * -r is used by rlogind to cause the autologin protocol;
+     * -f is used to skip a second login authentication 
+     * -F is used to skip a second login authentication, allows login as root 
+     * -e is used to skip a second login authentication, but allows
+     *         login as root.
+     * -h is used by other servers to pass the name of the
+     * remote host to login so that it may be placed in utmp and wtmp
+     * -k is used by klogind to cause the Kerberos V4 autologin protocol;
+     * -K is used by klogind to cause the Kerberos V4 autologin
+     *    protocol with restricted access.
+     */
+    (void)gethostname(tbuf, sizeof(tbuf));
+    domain = strchr(tbuf, '.');
+
+    fflag = hflag = pflag = rflag = kflag = Kflag = eflag = 0;
+    passwd_req = 1;
+    while ((ch = getopt(argc, argv, "Ffeh:pr:k:K:")) != -1)
+       switch (ch) {
+       case 'f':
+           EXCL_AUTH_TEST;
+           fflag = 1;
+           break;
+       case 'F':
+           EXCL_AUTH_TEST;
+           fflag = 1;
+           break;
+       case 'h':
+           EXCL_HOST_TEST;
+           if (getuid()) {
+               fprintf(stderr,
+                       "login: -h for super-user only.\n");
+               exit(1);
+           }
+           hflag = 1;
+           if (domain && (p = strchr(optarg, '.')) && strcmp(p, domain) == 0)
+               *p = 0;
+           hostname = optarg;
+           break;
+       case 'p':
+           pflag = 1;
+           break;
+       case 'r':
+           EXCL_AUTH_TEST;
+           EXCL_HOST_TEST;
+           if (getuid()) {
+               fprintf(stderr,
+                       "login: -r for super-user only.\n");
+               exit(1);
+           }
+           /* "-r hostname" must be last args */
+           if (optind != argc) {
+               fprintf(stderr, "Syntax error.\n");
+               exit(1);
+           }
+           rflag = 1;
+           passwd_req = (doremotelogin(optarg) == -1);
+           if (domain && (p = strchr(optarg, '.')) && !strcmp(p, domain))
+               *p = '\0';
+           hostname = optarg;
+           break;
 #ifdef KRB4_KLOGIN
-               case 'k':
-               case 'K':
-                       EXCL_AUTH_TEST;
-                       EXCL_HOST_TEST;
-                       if (getuid()) {
-                               fprintf(stderr,
-                                   "login: -%c for super-user only.\n", ch);
-                               exit(1);
-                       }
-                       /* "-k hostname" must be last args */
-                       if (optind != argc) {
-                               fprintf(stderr, "Syntax error.\n");
-                               exit(1);
-                       }
-                       if (ch == 'K')
-                           Kflag = 1;
-                       else
-                           kflag = 1;
-                       passwd_req = (do_krb_login(optarg,
-                                                  Kflag ? 1 : 0) == -1);
-                       if (domain && (p = strchr(optarg, '.')) &&
-                           !strcmp(p, domain))
-                               *p = '\0';
-                       hostname = optarg;
-                       break;
+       case 'k':
+       case 'K':
+           EXCL_AUTH_TEST;
+           EXCL_HOST_TEST;
+           if (getuid()) {
+               fprintf(stderr,
+                       "login: -%c for super-user only.\n", ch);
+               exit(1);
+           }
+           /* "-k hostname" must be last args */
+           if (optind != argc) {
+               fprintf(stderr, "Syntax error.\n");
+               exit(1);
+           }
+           if (ch == 'K')
+               Kflag = 1;
+           else
+               kflag = 1;
+           passwd_req = (do_krb_login(optarg, Kflag ? 1 : 0) == -1);
+           if (domain && 
+               (p = strchr(optarg, '.')) &&
+               (!strcmp(p, domain))) 
+               *p = '\0';
+           hostname = optarg;
+           break;
 #endif /* KRB4_KLOGIN */
-               case 'e':
-                       EXCL_AUTH_TEST;
-                       if (getuid()) {
-                           fprintf(stderr,
-                                   "login: -e for super-user only.\n");
-                           exit(1);
-                       }
-                       eflag = 1;
-                       passwd_req = 0;
-                       break;
-               case '?':
-               default:
-                       fprintf(stderr, "usage: login [-fp] [username]\n");
-                       exit(1);
-               }
-       argc -= optind;
-       argv += optind;
-       if (*argv)
-               username = *argv;
+       case 'e':
+           EXCL_AUTH_TEST;
+           if (getuid()) {
+               fprintf(stderr,
+                       "login: -e for super-user only.\n");
+               exit(1);
+           }
+           eflag = 1;
+           passwd_req = 0;
+           break;
+       case '?':
+       default:
+           fprintf(stderr, "usage: login [-fp] [username]\n");
+           exit(1);
+       }
+    argc -= optind;
+    argv += optind;
+    if (*argv)
+       username = *argv;
 
 #if !defined(POSIX_TERMIOS) && defined(TIOCLSET)
-       ioctlval = 0;
-       /* Only do this we we're not using POSIX_TERMIOS */
-       (void)ioctl(0, TIOCLSET, (char *)&ioctlval);
+    ioctlval = 0;
+    /* Only do this we we're not using POSIX_TERMIOS */
+    (void)ioctl(0, TIOCLSET, (char *)&ioctlval);
 #endif
        
 #ifdef TIOCNXCL
-       (void)ioctl(0, TIOCNXCL, (char *)0);
+    (void)ioctl(0, TIOCNXCL, (char *)0);
 #endif
        
-       ioctlval = fcntl(0, F_GETFL);
+    ioctlval = fcntl(0, F_GETFL);
 #ifdef O_NONBLOCK
-       ioctlval &= ~O_NONBLOCK;
+    ioctlval &= ~O_NONBLOCK;
 #endif
 #ifdef O_NDELAY
-       ioctlval &= ~O_NDELAY;
+    ioctlval &= ~O_NDELAY;
 #endif
-       (void)fcntl(0, F_SETFL, ioctlval);
+    (void)fcntl(0, F_SETFL, ioctlval);
 
        /*
         * If talking to an rlogin process, propagate the terminal type and
         * baud rate across the network.
         */
-       if (eflag)
-               lgetstr(term, sizeof(term), "Terminal type");
-       else if (!(kflag || Kflag ))  /*Preserve terminal if not read over net */
-         {
-           if (getenv("TERM")) {
-             strncpy(term, getenv("TERM"), sizeof(term));
-             term[sizeof(term) - 1] = '\0';
-           }
-         }
+    if (eflag) {
+       lgetstr(term, sizeof(term), "Terminal type");
+    } else if (!(kflag || Kflag)) {/* Preserve terminal if not read over net */
+       if (getenv("TERM")) {
+           strncpy(term, getenv("TERM"), sizeof(term));
+           term[sizeof(term) - 1] = '\0';
+       }
+    }
        
-       term_init (rflag || kflag || Kflag || eflag);
+    term_init (rflag || kflag || Kflag || eflag);
 
-       for (cnt = getdtablesize(); cnt > 2; cnt--)
-               (void) close(cnt);
+    for (cnt = getdtablesize(); cnt > 2; cnt--)
+       (void) close(cnt);
 
-       ttyn = ttyname(0);
-       if (ttyn == NULL || *ttyn == '\0')
-               ttyn = "/dev/tty??";
+    ttyn = ttyname(0);
+    if (ttyn == NULL || *ttyn == '\0')
+       ttyn = "/dev/tty??";
 
-       /* This allows for tty names of the form /dev/pts/4 as well */
-       if ((tty = strchr(ttyn, '/')) && (tty = strchr(tty+1, '/')))
-               ++tty;
-       else
-               tty = ttyn;
+    /* This allows for tty names of the form /dev/pts/4 as well */
+    if ((tty = strchr(ttyn, '/')) && (tty = strchr(tty+1, '/')))
+       ++tty;
+    else
+       tty = ttyn;
 
 #ifndef LOG_ODELAY /* 4.2 syslog ... */                      
-       openlog("login", 0);
+    openlog("login", 0);
 #else
-       openlog("login", LOG_ODELAY, LOG_AUTH);
+    openlog("login", LOG_ODELAY, LOG_AUTH);
 #endif /* 4.2 syslog */
 
 /******* begin askpw *******/
-       /* overall:
-          ask for username if we don't have it already
-          look it up in local pw or shadow file (to get crypt string)
-          ask for password
-          try and get v4, v5 tickets with it
-          try and use the tickets against the local srvtab
-          if the password matches, always let them in
-          if the ticket decrypts, let them in.
-          v5 needs to work, does v4?
-          */
-
+    /* overall:
+       ask for username if we don't have it already
+       look it up in local pw or shadow file (to get crypt string)
+       ask for password
+       try and get v4, v5 tickets with it
+       try and use the tickets against the local srvtab
+       if the password matches, always let them in
+       if the ticket decrypts, let them in.
+       v5 needs to work, does v4?
+    */
+
+    k_init (ttyn);
+
+    for (cnt = 0;; username = NULL) {
 #ifdef KRB5_GET_TICKETS
-       k_init (ttyn);
-#endif
-
-       for (cnt = 0;; username = NULL) {
-#ifdef KRB5_GET_TICKETS
-               int kpass_ok,lpass_ok;
-               char user_pwstring[MAXPWSIZE];
-               /* variables from v5 kinit */
+       int kpass_ok, lpass_ok;
+       char user_pwstring[MAXPWSIZE];
 #endif /* KRB5_GET_TICKETS */
 
-               if (username == NULL) {
-                       fflag = 0;
-                       getloginname();
-               }
-
-               lookup_user (username); /* sets pwd */
-
-               /* if user not super-user, check for disabled logins */
-               if (pwd == NULL || pwd->pw_uid)
-                       checknologin();
+       if (username == NULL) {
+           fflag = 0;
+           getloginname();
+       }
 
-               /*
-                * Allows automatic login by root.
-                * If not invoked by root, disallow if the uid's differ.
-                */
+       lookup_user(username);  /* sets pwd */
 
-               if (fflag && pwd) {
-                       int uid = (int) getuid();
-                       passwd_req = (uid && uid != pwd->pw_uid);
-               }
+       /* if user not super-user, check for disabled logins */
+       if (pwd == NULL || pwd->pw_uid)
+           checknologin();
 
-               /*
-                * If no remote login authentication and a password exists
-                * for this user, prompt for one and verify it.
-                */
-               if (!passwd_req)
-                   break;
+       /*
+        * Allows automatic login by root.
+        * If not invoked by root, disallow if the uid's differ.
+        */
 
-               if (! unix_needs_passwd ())
-                   break;
+       if (fflag && pwd) {
+           int uid = (int) getuid();
+           passwd_req = (uid && uid != pwd->pw_uid);
+       }
 
-               /* we have several sets of code:
-                  1) get v5 tickets alone -DKRB5_GET_TICKETS
-                  2) get v4 tickets alone [** don't! only get them *with* v5 **]
-                  3) get both tickets -DKRB5_GET_TICKETS -DKRB4_GET_TICKETS
-                  3a) use krb524 calls to get the v4 tickets -DKRB4_CONVERT plus (3).
-                  4) get no tickets and use the password file (none of thes defined.)
+       /*
+        * If no remote login authentication and a password exists
+        * for this user, prompt for one and verify it.
+        */
+       if (!passwd_req)
+           break;
+
+       if (!unix_needs_passwd())
+           break;
+
+       /* we have several sets of code:
+          1) get v5 tickets alone -DKRB5_GET_TICKETS
+          2) get v4 tickets alone [** don't! only get them *with* v5 **]
+          3) get both tickets -DKRB5_GET_TICKETS -DKRB4_GET_TICKETS
+          3a) use krb524 calls to get the v4 tickets -DKRB4_CONVERT plus (3).
+          4) get no tickets and use the password file (none of thes defined.)
                   
-                  Likewise we need to (optionally?) test these tickets against local srvtabs.
-                  */
+          Likewise we need to (optionally?) test these tickets against
+          local srvtabs.
+       */
+
 #ifdef KRB5_GET_TICKETS
-               if (login_krb5_get_tickets) {
-               /* rename these to something more verbose */
-               kpass_ok = 0;
-               lpass_ok = 0;
-
-               setpriority(PRIO_PROCESS, 0, -4 + PRIO_OFFSET);
-               if (! k5_get_password (user_pwstring, sizeof (user_pwstring))) {
-                   goto bad_login;
-               }
+       if (login_krb5_get_tickets) {
+           /* rename these to something more verbose */
+           kpass_ok = 0;
+           lpass_ok = 0;
 
-               /* now that we have the password, we've obscured things
-                  sufficiently, and can avoid trying tickets */
-               if (!pwd)
-                       goto bad_login;
+           setpriority(PRIO_PROCESS, 0, -4 + PRIO_OFFSET);
+           if (! k5_get_password(user_pwstring, sizeof (user_pwstring))) {
+               goto bad_login;
+           }
+
+           /* now that we have the password, we've obscured things
+              sufficiently, and can avoid trying tickets */
+           if (!pwd)
+               goto bad_login;
 
-               lpass_ok = unix_passwd_okay (user_pwstring);
+           lpass_ok = unix_passwd_okay(user_pwstring);
 
-               if (pwd->pw_uid != 0) { /* Don't get tickets for root */
-                       try_krb5 (&me, user_pwstring);
+           if (pwd->pw_uid != 0) { /* Don't get tickets for root */
+               try_krb5(&me, user_pwstring);
 
 #ifdef KRB4_GET_TICKETS
-                       if (login_krb4_get_tickets
-                           && (!got_v5_tickets
-                               || !login_krb4_convert))
-                           try_krb4 (me, user_pwstring);
+               if (login_krb4_get_tickets &&
+                   !(got_v5_tickets && login_krb4_convert))
+                   try_krb4(me, user_pwstring);
+#endif
+               krbflag = (got_v5_tickets
+#ifdef KRB4_GET_TICKETS
+                          || got_v4_tickets
 #endif
-                       krbflag = got_v5_tickets || got_v4_tickets;
-                       memset (user_pwstring, 0, sizeof(user_pwstring));
-                       /* password wiped, so we can relax */
-                       setpriority(PRIO_PROCESS, 0, 0 + PRIO_OFFSET);
+                          );
+               memset (user_pwstring, 0, sizeof(user_pwstring));
+               /* password wiped, so we can relax */
+               setpriority(PRIO_PROCESS, 0, 0 + PRIO_OFFSET);
+           } else {
+               memset(user_pwstring, 0, sizeof(user_pwstring));
+               setpriority(PRIO_PROCESS, 0, 0 + PRIO_OFFSET);
+           }
+
+           /* Policy: If local password is good, user is good.
+              We really can't trust the Kerberos password,
+              because somebody on the net could spoof the
+              Kerberos server (not easy, but possible).
+              Some sites might want to use it anyways, in
+              which case they should change this line
+              to:
+              if (kpass_ok)
+           */
+
+           if (lpass_ok)
+               break;
 
+           if (got_v5_tickets) {
+               if (retval = krb5_verify_init_creds(kcontext, &my_creds, NULL,
+                                                   NULL, &xtra_creds,
+                                                   NULL)) {
+                   com_err("login", retval, "while verifying initial ticket");
+#ifndef SYSLOG42
+                   syslog(LOG_NOTICE|LOG_AUTH,
+                          "can't verify v5 ticket: %s\n",
+                          error_message(retval));
+#endif
                } else {
-                       memset (user_pwstring, 0, sizeof(user_pwstring));
-                       setpriority(PRIO_PROCESS, 0, 0 + PRIO_OFFSET);
+                   break;      /* we're ok */
                }
-
-               /* Policy: If local password is good, user is good.
-                  We really can't trust the Kerberos password,
-                  because somebody on the net could spoof the
-                  Kerberos server (not easy, but possible).
-                  Some sites might want to use it anyways, in
-                  which case they should change this line
-                  to:
-                  if (kpass_ok)
-                  */
-               if (lpass_ok)
-                       break;
-               if (got_v5_tickets
-                   && verify_krb_v5_tgt(kcontext) != -1)
-                       break;  /* we're ok */
+           }
 #ifdef KRB4_GET_TICKETS
-               if (login_krb4_get_tickets) {
-                   if (got_v4_tickets
-                       && ! got_v5_tickets
-                       && verify_krb_v4_tgt(realm) != -1)
-                       break;  /* we're ok */
-               }
+           else if (got_v4_tickets) {
+               if (login_krb4_get_tickets &&
+                   (verify_krb_v4_tgt(realm) != -1))
+                   break;      /* we're ok */
+           }
 #endif /* KRB4_GET_TICKETS */
+
        bad_login:
-               setpriority(PRIO_PROCESS, 0, 0 + PRIO_OFFSET);
-               if (krbflag)
-                       destroy_tickets(); /* clean up tickets if login fails */
+           setpriority(PRIO_PROCESS, 0, 0 + PRIO_OFFSET);
 
-               }
+           if (krbflag)
+               destroy_tickets(); /* clean up tickets if login fails */
+       }
 #endif /* KRB5_GET_TICKETS */
+
 #ifdef OLD_PASSWD
-               p = getpass ("Password:");
-               /* conventional password only */
-               if (unix_passwd_okay (p))
-                   break;
+       p = getpass ("Password:");
+       /* conventional password only */
+       if (unix_passwd_okay (p))
+           break;
 #endif /* OLD_PASSWD */
-               printf("Login incorrect\n");
-               if (++cnt >= 5) {
-                       log_repeated_failures (tty, hostname);
-/* irix has no tichpcl */
+       printf("Login incorrect\n");
+       if (++cnt >= 5) {
+           log_repeated_failures (tty, hostname);
+           /* irix has no tichpcl */
 #ifdef TIOCHPCL
-                       (void)ioctl(0, TIOCHPCL, (char *)0);
+           (void)ioctl(0, TIOCHPCL, (char *)0);
 #endif
-                       sleepexit(1);
-               }
-       } /* end of password retry loop */
+           sleepexit(1);
+       }
+    } /* end of password retry loop */
 
-       /* committed to login -- turn off timeout */
-       (void)alarm((u_int)0);
+    /* committed to login -- turn off timeout */
+    (void) alarm((u_int) 0);
 
-       /*
-        * If valid so far and root is logging in, see if root logins on
-        * this terminal are permitted.
-        *
-        * We allow authenticated remote root logins (except -r style)
-        */
-       if (pwd->pw_uid == 0 && !rootterm(tty) && (passwd_req || rflag)) {
-               if (hostname)
+    /*
+     * If valid so far and root is logging in, see if root logins on
+     * this terminal are permitted.
+     *
+     * We allow authenticated remote root logins (except -r style)
+     */
+
+    if (pwd->pw_uid == 0 && !rootterm(tty) && (passwd_req || rflag)) {
+       if (hostname) {
 #ifdef UT_HOSTSIZE
-                       syslog(LOG_ERR, "ROOT LOGIN REFUSED ON %s FROM %.*s",
-                           tty, UT_HOSTSIZE, hostname);
+           syslog(LOG_ERR, "ROOT LOGIN REFUSED ON %s FROM %.*s",
+                  tty, UT_HOSTSIZE, hostname);
 #else
-                       syslog(LOG_ERR, "ROOT LOGIN REFUSED ON %s FROM %s",
-                           tty, hostname);
+           syslog(LOG_ERR, "ROOT LOGIN REFUSED ON %s FROM %s",
+                  tty, hostname);
 #endif
-               else
-                       syslog(LOG_ERR, "ROOT LOGIN REFUSED ON %s", tty);
-               printf("Login incorrect\n");
-               sleepexit(1);
+       } else {
+           syslog(LOG_ERR, "ROOT LOGIN REFUSED ON %s", tty);
        }
+       printf("Login incorrect\n");
+       sleepexit(1);
+    }
 
 #ifdef OQUOTA
-       if (quota(Q_SETUID, pwd->pw_uid, 0, 0) < 0 && errno != EINVAL) {
-               switch(errno) {
-               case EUSERS:
-                       fprintf(stderr,
-               "Too many users logged on already.\nTry again later.\n");
-                       break;
-               case EPROCLIM:
-                       fprintf(stderr,
-                           "You have too many processes running.\n");
-                       break;
-               default:
-                       perror("quota (Q_SETUID)");
-               }
-               sleepexit(0);
+    if (quota(Q_SETUID, pwd->pw_uid, 0, 0) < 0 && errno != EINVAL) {
+       switch(errno) {
+       case EUSERS:
+           fprintf(stderr,
+                   "Too many users logged on already.\nTry again later.\n");
+           break;
+       case EPROCLIM:
+           fprintf(stderr,
+                   "You have too many processes running.\n");
+           break;
+       default:
+           perror("quota (Q_SETUID)");
        }
+       sleepexit(0);
+    }
 #endif
-       if (chdir(pwd->pw_dir) < 0) {
-               printf("No directory %s!\n", pwd->pw_dir);
-               if (chdir("/"))
-                       exit(0);
-               pwd->pw_dir = "/";
-               printf("Logging in with home = \"/\".\n");
-       }
 
-       /* nothing else left to fail -- really log in */
-       {
-               struct utmp utmp;
-
-               login_time = time(&utmp.ut_time);
-               if ( (retval = pty_update_utmp(PTY_USER_PROCESS, getpid(),  username, ttyn, hostname, PTY_TTYSLOT_USABLE)) < 0 )
-                   com_err (argv[0], retval, "while updating utmp");
-       }
+    if (chdir(pwd->pw_dir) < 0) {
+       printf("No directory %s!\n", pwd->pw_dir);
+       if (chdir("/"))
+           exit(0);
+       pwd->pw_dir = "/";
+       printf("Logging in with home = \"/\".\n");
+    }
 
-       quietlog = access(HUSHLOGIN, F_OK) == 0;
-       dolastlog(quietlog, tty);
+    /* nothing else left to fail -- really log in */
+    {
+       struct utmp utmp;
 
-       if (!hflag && !rflag && !kflag && !Kflag && !eflag) {   /* XXX */
-               static struct winsize win = { 0, 0, 0, 0 };
+       login_time = time(&utmp.ut_time);
+       if ((retval = pty_update_utmp(PTY_USER_PROCESS, getpid(), username,
+                                     ttyn, hostname,
+                                     PTY_TTYSLOT_USABLE)) < 0)
+           com_err (argv[0], retval, "while updating utmp");
+    }
 
-               (void)ioctl(0, TIOCSWINSZ, (char *)&win);
-       }
+    quietlog = access(HUSHLOGIN, F_OK) == 0;
+    dolastlog(quietlog, tty);
 
-       (void)chown(ttyn, pwd->pw_uid,
-           (gr = getgrnam(TTYGRPNAME)) ? gr->gr_gid : pwd->pw_gid);
+    if (!hflag && !rflag && !kflag && !Kflag && !eflag) {      /* XXX */
+       static struct winsize win = { 0, 0, 0, 0 };
 
-       (void)chmod(ttyn, 0620);
-#ifdef KRB5_GET_TICKETS
-                   /* Maybe telnetd got tickets for us?  */
-       if (!got_v5_tickets && have_v5_tickets (&me))
-         got_v5_tickets = 1;
-#endif /* GET_KRB_TICKETS */
+       (void)ioctl(0, TIOCSWINSZ, (char *)&win);
+    }
 
-#ifdef KRB4_GET_TICKETS
-       if ( login_krb4_convert && !got_v4_tickets) {
+    (void)chown(ttyn, pwd->pw_uid,
+               (gr = getgrnam(TTYGRPNAME)) ? gr->gr_gid : pwd->pw_gid);
 
+    (void)chmod(ttyn, 0620);
 
-           if (got_v5_tickets)
-               try_convert524 (kcontext, me);
+#ifdef KRB5_GET_TICKETS
+    /* Maybe telnetd got tickets for us?  */
+    if (!got_v5_tickets && have_v5_tickets (&me))
+       forwarded_v5_tickets = 1;
+#endif /* KRB5_GET_TICKETS */
 
-       }
+#if defined(KRB5_GET_TICKETS) && defined(KRB4_CONVERT)
+    if (login_krb4_convert && !got_v4_tickets) {
+       if (got_v5_tickets||forwarded_v5_tickets)
+           try_convert524 (kcontext, me);
+    }
 #endif
 
-#if defined(KRB5_GET_TICKETS) || defined(KRB4_GET_TICKETS)
-#if defined(KRB5_GET_TICKETS) && defined(KRB4_GET_TICKETS)
-       if (login_krb4_get_tickets || login_krb5_get_tickets) {
-#elif defined(KRB4_GET_TICKETS)
-       if (login_krb4_get_tickets) {
-#else
-       if (login_krb5_get_tickets) {
+#ifdef KRB5_GET_TICKETS
+    if (login_krb5_get_tickets)
+       dofork();
+    else
 #endif
-           /* Fork so that we can call kdestroy */
+#ifdef KRB4_GET_TICKETS
+       if (login_krb4_get_tickets)
            dofork();
-       }
-#endif /* KRB4_GET_TICKETS */
+#endif
 
 /* If the user's shell does not do job control we should put it in a
    different process group than than us, and set the tty process group
@@ -1644,335 +1469,364 @@ int rewrite_ccache = 1; /*try to write out ccache*/
    telnetd or rlogind if they don't properly detach from their
    controlling tty, which is the case (under SunOS at least.) */
 
-       {
-          int p = getpid(); 
-          struct sigaction sa, osa;
+    {
+       int p = getpid(); 
+       struct sigaction sa, osa;
 
-          /* this will set the PGID to the PID. */
+       /* this will set the PGID to the PID. */
 #ifdef HAVE_SETPGID
-          if (setpgid(p,p) < 0) perror("login.krb5: setpgid");
+       if (setpgid(p,p) < 0)
+           perror("login.krb5: setpgid");
+#elif defined(SETPGRP_TWOARG)
+       if (setpgrp(p,p) < 0)
+           perror("login.krb5: setpgrp");
 #else
-#ifdef SETPGRP_TWOARG
-          if (setpgrp(p,p) < 0) perror("login.krb5: setpgrp");
-#else
-          if (setpgrp() < 0) perror("login.krb5: setpgrp");
-#endif
+       if (setpgrp() < 0)
+           perror("login.krb5: setpgrp");
 #endif
 
-          /* This will cause SIGTTOU to be ignored for the duration
-             of the TIOCSPGRP.  If this is not done, and the parent's
-             process group is the foreground pgrp of the tty, then
-             this will suspend the child, which is bad. */
+       /* This will cause SIGTTOU to be ignored for the duration
+          of the TIOCSPGRP.  If this is not done, and the parent's
+          process group is the foreground pgrp of the tty, then
+          this will suspend the child, which is bad. */
 
-          sa.sa_flags = 0;
-          sa.sa_handler = SIG_IGN;
-          sigemptyset(&(sa.sa_mask));
+       sa.sa_flags = 0;
+       sa.sa_handler = SIG_IGN;
+       sigemptyset(&(sa.sa_mask));
 
-          if (sigaction(SIGTTOU, &sa, &osa))
-             perror("login.krb5: sigaction(SIGTTOU, SIG_IGN)");
+       if (sigaction(SIGTTOU, &sa, &osa))
+           perror("login.krb5: sigaction(SIGTTOU, SIG_IGN)");
 
-          /* This will set the foreground process group of the
-             controlling terminal to this process group (containing
-             only this process). */
+       /* This will set the foreground process group of the
+          controlling terminal to this process group (containing
+          only this process). */
 #ifdef HAVE_TCSETPGRP
-          if (tcsetpgrp(0, p) < 0) perror("login.krb5: tcsetpgrp");
+       if (tcsetpgrp(0, p) < 0)
+           perror("login.krb5: tcsetpgrp");
 #else
-          if (ioctl(0, TIOCSPGRP, &p) < 0) perror("login.krb5: tiocspgrp");
+       if (ioctl(0, TIOCSPGRP, &p) < 0)
+           perror("login.krb5: tiocspgrp");
 #endif
 
-          /* This will reset the SIGTTOU handler */
+       /* This will reset the SIGTTOU handler */
 
-          if (sigaction(SIGTTOU, &osa, NULL))
-             perror("login.krb5: sigaction(SIGTTOU, [old handler])");
-        }
+       if (sigaction(SIGTTOU, &osa, NULL))
+           perror("login.krb5: sigaction(SIGTTOU, [old handler])");
+    }
 
-       (void)setgid((gid_t) pwd->pw_gid);
-       (void) initgroups(username, pwd->pw_gid);
+    (void) setgid((gid_t) pwd->pw_gid);
+    (void) initgroups(username, pwd->pw_gid);
 
-       /*
-        * The V5 ccache and V4 ticket file are both created as root.
-        * They need to be owned by the user, and chown (a) assumes
-        * they are stored in a file and (b) allows a race condition
-        * in which a user can delete the file (if the directory
-        * sticky bit is not set) and make it a symlink to somewhere
-        * else; on some platforms, chown() on a symlink actually
-        * changes the owner of the pointed-to file.  This is Bad.
-        *
-        * So, we suck the V5 and V4 krbtgts into memory here, destroy
-        * the ccache/ticket file, and recreate them later after the
-        * setuid.
-        */
+    /*
+     * The V5 ccache and V4 ticket file are both created as root.
+     * They need to be owned by the user, and chown (a) assumes
+     * they are stored in a file and (b) allows a race condition
+     * in which a user can delete the file (if the directory
+     * sticky bit is not set) and make it a symlink to somewhere
+     * else; on some platforms, chown() on a symlink actually
+     * changes the owner of the pointed-to file.  This is Bad.
+     *
+     * So, we suck the V5 and V4 krbtgts into memory here, destroy
+     * the ccache/ticket file, and recreate them later after the
+     * setuid.
+     *
+     * With the new v5 api, v5 tickets are kept in memory until written
+     * out after the setuid.  However, forwarded tickets still
+     * need to be read in and recreated later
+     */
 #ifdef KRB5_GET_TICKETS
-       if (got_v5_tickets) {
-            krb5_creds mcreds;
-
-            memset(&mcreds, 0, sizeof(mcreds));
-            memset(&save_v5creds, 0, sizeof(save_v5creds));
-
-            mcreds.client = me;
-            retval = krb5_build_principal_ext(kcontext, &mcreds.server,
-                                   krb5_princ_realm(kcontext, me)->length,
-                                   krb5_princ_realm(kcontext, me)->data,
-                                   tgtname.length, tgtname.data,
-                                   krb5_princ_realm(kcontext, me)->length,
-                                   krb5_princ_realm(kcontext, me)->data,
-                                   0);
-            if (retval) {
-                 syslog(LOG_ERR,
-                        "%s while creating V5 krbtgt principal",
-                        error_message(retval));
-                 goto skip_ccache_rewrite;
-            }
-
-              mcreds.ticket_flags =0;
-            
-            if (retval = krb5_cc_retrieve_cred(kcontext, ccache,
-                                               0,
-                                          &mcreds, &save_v5creds)) {
-                 syslog(LOG_ERR,
-                        "%s while retrieiving V5 initial ticket for copy",
-                        error_message(retval));
-            skip_ccache_rewrite: rewrite_ccache = 0;
-
-            }
-            krb5_free_principal(kcontext, mcreds.server);
+    if (forwarded_v5_tickets) {
+       krb5_creds mcreds;
+
+       memset(&mcreds, 0, sizeof(mcreds));
+       memset(&save_v5creds, 0, sizeof(save_v5creds));
+
+       mcreds.client = me;
+       retval =
+           krb5_build_principal_ext(kcontext, &mcreds.server,
+                                    krb5_princ_realm(kcontext, me)->length,
+                                    krb5_princ_realm(kcontext, me)->data,
+                                    tgtname.length, tgtname.data,
+                                    krb5_princ_realm(kcontext, me)->length,
+                                    krb5_princ_realm(kcontext, me)->data,
+                                    0);
+       if (retval) {
+           syslog(LOG_ERR,
+                  "%s while creating V5 krbtgt principal",
+                  error_message(retval));
+           rewrite_ccache = 0;
+       } else {
+           mcreds.ticket_flags = 0;
+
+           if (retval = krb5_cc_retrieve_cred(kcontext, ccache, 0,
+                                              &mcreds, &save_v5creds)) {
+               syslog(LOG_ERR,
+                      "%s while retrieiving V5 initial ticket for copy",
+                      error_message(retval));
+               rewrite_ccache = 0;
+           }
        }
+
+       krb5_free_principal(kcontext, mcreds.server);
+    }
 #endif /* KRB5_GET_TICKETS */
+
 #ifdef KRB4_GET_TICKETS
-       if (got_v4_tickets) {
-            memset(&save_v4creds, 0, sizeof(save_v4creds));
-            
-            retval = krb_get_cred("krbtgt", realm, realm, &save_v4creds);
-            if (retval != KSUCCESS) {
-                 syslog(LOG_ERR,
-                        "%s while retrieving V4 initial ticket for copy",
-                        error_message(retval));
-             rewrite_ccache = 0;
+    if (got_v4_tickets) {
+       memset(&save_v4creds, 0, sizeof(save_v4creds));
             
-            }
+       retval = krb_get_cred("krbtgt", realm, realm, &save_v4creds);
+       if (retval != KSUCCESS) {
+           syslog(LOG_ERR,
+                  "%s while retrieving V4 initial ticket for copy",
+                  error_message(retval));
+           rewrite_ccache = 0;
        }
+    }
 #endif /* KRB4_GET_TICKETS */
-#if defined(KRB5_GET_TICKETS) || defined(KRB4_GET_TICKETS)
-       if (got_v5_tickets || got_v4_tickets)
-         destroy_tickets();
+
+#ifdef KRB5_GET_TICKETS
+    if (forwarded_v5_tickets)
+       destroy_tickets();
+    else
+#endif
+#ifdef KRB4_GET_TICKETS
+       if (got_v4_tickets)
+           destroy_tickets();
 #endif
 
 #ifdef OQUOTA
-       quota(Q_DOWARN, pwd->pw_uid, (dev_t)-1, 0);
+    quota(Q_DOWARN, pwd->pw_uid, (dev_t)-1, 0);
 #endif
 #ifdef HAVE_SETLOGIN
-       if (setlogin(pwd->pw_name) < 0)
-           syslog(LOG_ERR, "setlogin() failure %d",errno);
+    if (setlogin(pwd->pw_name) < 0)
+       syslog(LOG_ERR, "setlogin() failure %d",errno);
 #endif
 
 #ifdef HAVE_SETLUID
-       /*
-        * If we're on a system which keeps track of login uids, then
-        * attempt to set the login uid, but don't get too unhappy when/if
-        * it doesn't succeed.
-        */
-       if ((uid_t) getluid() < (uid_t) 0) {
-           setluid((uid_t) pwd->pw_uid);
-       }
+    /*
+     * If we're on a system which keeps track of login uids, then
+     * attempt to set the login uid, but don't get too unhappy when/if
+     * it doesn't succeed.
+     */
+    if ((uid_t) getluid() < (uid_t) 0) {
+       setluid((uid_t) pwd->pw_uid);
+    }
 #endif /* HAVE_SETLUID */
 #ifdef _IBMR2
-       setuidx(ID_LOGIN, pwd->pw_uid);
+    setuidx(ID_LOGIN, pwd->pw_uid);
 #endif
 
-       /* This call MUST succeed */
-       if(setuid((uid_t) pwd->pw_uid) < 0) {
-            perror("setuid");
-            sleepexit(1);
-       }
+    /* This call MUST succeed */
+    if (setuid((uid_t) pwd->pw_uid) < 0) {
+       perror("setuid");
+       sleepexit(1);
+    }
+
+    /*
+     * We are the user now.  Re-create the destroyed ccache and
+     * ticket file.
+     */
 
-       /*
-        * We are the user now.  Re-create the destroyed ccache and
-        * ticket file.
-        */
 #ifdef KRB5_GET_TICKETS
-       if (got_v5_tickets && rewrite_ccache) {
-            retval = krb5_cc_initialize (kcontext, ccache, me);
-            if (retval) {
-                 syslog(LOG_ERR,
-                        "%s while re-initializing V5 ccache as user",
-                        error_message(retval));
-                 goto skip_ccache_output;
-            }
-            if (retval = krb5_cc_store_cred(kcontext, ccache, &save_v5creds)) {
-                 syslog(LOG_ERR,
-                        "%s while re-storing V5 credentials as user",
-                        error_message(retval));
-
-            }
-            skip_ccache_output: krb5_free_cred_contents(kcontext, &save_v5creds);
+    if (got_v5_tickets) {
+       /* set up credential cache -- obeying KRB5_ENV_CCNAME 
+          set earlier */
+       /* (KRB5_ENV_CCNAME == "KRB5CCNAME" via osconf.h) */
+       if (retval = krb5_cc_default(kcontext, &ccache)) {
+           com_err(argv[0], retval, "while getting default ccache");
+       } else if (retval = krb5_cc_initialize(kcontext, ccache, me)) {
+           com_err(argv[0], retval, "when initializing cache");
+       } else if (retval = krb5_cc_store_cred(kcontext, ccache, &my_creds)) {
+           com_err(argv[0], retval, "while storing credentials");
+       } else if (xtra_creds &&
+                  (retval = krb5_cc_copy_creds(kcontext, xtra_creds,
+                                               ccache))) {
+           com_err(argv[0], retval, "while storing credentials");
        }
+
+       krb5_cc_destroy(kcontext, xtra_creds);
+    } else if (forwarded_v5_tickets && rewrite_ccache) {
+       if ((retval = krb5_cc_initialize (kcontext, ccache, me))) {
+           syslog(LOG_ERR,
+                  "%s while re-initializing V5 ccache as user",
+                  error_message(retval));
+       } else if (retval = krb5_cc_store_cred(kcontext, ccache,
+                                              &save_v5creds)) {
+           syslog(LOG_ERR,
+                  "%s while re-storing V5 credentials as user",
+                  error_message(retval));
+           
+       }
+       krb5_free_cred_contents(kcontext, &save_v5creds);
+    }
 #endif /* KRB5_GET_TICKETS */
+
 #ifdef KRB4_GET_TICKETS
-       if (got_v4_tickets&&rewrite_ccache) {
-            retval = in_tkt(save_v4creds.pname, save_v4creds.pinst);
-            if (retval != KSUCCESS) {
-                 syslog(LOG_ERR,
-                        "%s while re-initializing V4 ticket cache as user",
-                        error_message((retval == -1)?errno:retval));
-                 goto skip_output_tkfile;
-            }
-            retval = krb_save_credentials(save_v4creds.service,
-                                          save_v4creds.instance,
-                                          save_v4creds.realm, 
-                                          save_v4creds.session,
-                                          save_v4creds.lifetime,
-                                          save_v4creds.kvno,
-                                          &(save_v4creds.ticket_st), 
-                                          save_v4creds.issue_date);
-            if (retval != KSUCCESS) {
-                 syslog(LOG_ERR,
-                        "%s while re-storing V4 tickets as user",
-                        error_message(retval));
-
-            }
+    if (got_v4_tickets && rewrite_ccache) {
+       if ((retval = in_tkt(save_v4creds.pname, save_v4creds.pinst))
+           != KSUCCESS) {
+           syslog(LOG_ERR,
+                  "%s while re-initializing V4 ticket cache as user",
+                  error_message((retval == -1)?errno:retval));
+       } else if ((retval = krb_save_credentials(save_v4creds.service,
+                                                 save_v4creds.instance,
+                                                 save_v4creds.realm, 
+                                                 save_v4creds.session,
+                                                 save_v4creds.lifetime,
+                                                 save_v4creds.kvno,
+                                                 &(save_v4creds.ticket_st), 
+                                                 save_v4creds.issue_date))
+                  != KSUCCESS) {
+           syslog(LOG_ERR,
+                  "%s while re-storing V4 tickets as user",
+                  error_message(retval));
        }
+    }
 #endif /* KRB4_GET_TICKETS */
-       skip_output_tkfile: /*null*/;
 
+    if (*pwd->pw_shell == '\0')
+       pwd->pw_shell = BSHELL;
 
-       if (*pwd->pw_shell == '\0')
-               pwd->pw_shell = BSHELL;
 #if defined(NTTYDISC) && defined(TIOCSETD)
-       /* turn on new line discipline for all shells */
-       ioctlval = NTTYDISC;
-       (void)ioctl(0, TIOCSETD, (char *)&ioctlval);
+    /* turn on new line discipline for all shells */
+    ioctlval = NTTYDISC;
+    (void)ioctl(0, TIOCSETD, (char *)&ioctlval);
 #endif
 
-       ccname = getenv("KRB5CCNAME");  /* save cache */
-       tz = getenv("TZ");      /* and time zone */
+    ccname = getenv("KRB5CCNAME");  /* save cache */
+    tz = getenv("TZ"); /* and time zone */
 
-       /* destroy environment unless user has requested preservation */
-       if (!pflag) {
-           envinit = (char **)malloc(MAXENVIRON * sizeof(char *));
-           if (envinit == 0) {
-               fprintf(stderr, "Can't malloc empty environment.\n");
-               sleepexit(1);
-           }
-           envinit[0] = NULL;
-           environ = envinit;
+    /* destroy environment unless user has requested preservation */
+    if (!pflag) {
+       envinit = (char **) malloc(MAXENVIRON * sizeof(char *));
+       if (envinit == 0) {
+           fprintf(stderr, "Can't malloc empty environment.\n");
+           sleepexit(1);
        }
+       envinit[0] = NULL;
+       environ = envinit;
+    }
 
-       setenv ("LOGNAME", pwd->pw_name, 1);
-       setenv ("LOGIN", pwd->pw_name, 1);
+    setenv ("LOGNAME", pwd->pw_name, 1);
+    setenv ("LOGIN", pwd->pw_name, 1);
 
-       /* read the /etc/environment file on AIX */
+    /* read the /etc/environment file on AIX */
 #ifdef HAVE_ETC_ENVIRONMENT
-       read_env_vars_from_file ("/etc/environment");
+    read_env_vars_from_file ("/etc/environment");
 #endif
 
-       /* Set login timezone for date information (sgi PDG) */
+    /* Set login timezone for date information (sgi PDG) */
 #ifdef HAVE_ETC_TIMEZONE
-       read_env_vars_from_file ("/etc/TIMEZONE");
+    read_env_vars_from_file ("/etc/TIMEZONE");
 #else
-       if (tz)
-           setenv ("TZ", tz, 1);
+    if (tz)
+       setenv ("TZ", tz, 1);
 #endif
 
-       if (ccname)
-               setenv("KRB5CCNAME", ccname, 1);
+    if (ccname)
+       setenv("KRB5CCNAME", ccname, 1);
 
-       setenv("HOME", pwd->pw_dir, 1);
-       setenv("PATH", LPATH, 1);
-       setenv("USER", pwd->pw_name, 1);
-       setenv("SHELL", pwd->pw_shell, 1);
+    setenv("HOME", pwd->pw_dir, 1);
+    setenv("PATH", LPATH, 1);
+    setenv("USER", pwd->pw_name, 1);
+    setenv("SHELL", pwd->pw_shell, 1);
+
+    if (term[0] == '\0') {
+       (void) strncpy(term, stypeof(tty), sizeof(term));
+       term[sizeof(term) - 1] = '\0';
+    }
+    if (term[0])
+       (void)setenv("TERM", term, 0);
 
-       if (term[0] == '\0') {
-               (void) strncpy(term, stypeof(tty), sizeof(term));
-               term[sizeof(term) - 1] = '\0';
-       }
-       if (term[0])
-               (void)setenv("TERM", term, 0);
 #ifdef KRB4_GET_TICKETS
-       /* tkfile[0] is only set if we got tickets above */
-       if (login_krb4_get_tickets && tkfile[0])
-           (void) setenv(KRB_ENVIRON, tkfile, 1);
+    /* tkfile[0] is only set if we got tickets above */
+    if (login_krb4_get_tickets && tkfile[0])
+       (void) setenv(KRB_ENVIRON, tkfile, 1);
 #endif /* KRB4_GET_TICKETS */
+
 #ifdef KRB5_GET_TICKETS
-       /* ccfile[0] is only set if we got tickets above */
-       if (login_krb5_get_tickets && ccfile[0])
-           (void) setenv(KRB5_ENV_CCNAME, ccfile, 1);
+    /* ccfile[0] is only set if we got tickets above */
+    if (login_krb5_get_tickets && ccfile[0])
+       (void) setenv(KRB5_ENV_CCNAME, ccfile, 1);
 #endif /* KRB5_GET_TICKETS */
 
-       if (tty[sizeof("tty")-1] == 'd')
-               syslog(LOG_INFO, "DIALUP %s, %s", tty, pwd->pw_name);
-       if (pwd->pw_uid == 0)
-               if (hostname)
+    if (tty[sizeof("tty")-1] == 'd')
+       syslog(LOG_INFO, "DIALUP %s, %s", tty, pwd->pw_name);
+    if (pwd->pw_uid == 0)
 #ifdef KRB4_KLOGIN
-                       if (kdata) {
-                           /* @*$&@#*($)#@$ syslog doesn't handle very
-                              many arguments */
-                           char buf[BUFSIZ];
+       if (kdata) {
+           if (hostname) {
+               char buf[BUFSIZ];
 #ifdef UT_HOSTSIZE
-                           (void) sprintf(buf,
-                                  "ROOT LOGIN (krb) %s from %.*s, %s.%s@%s",
-                                  tty, UT_HOSTSIZE, hostname,
-                                  kdata->pname, kdata->pinst,
-                                  kdata->prealm);
+               (void) sprintf(buf,
+                              "ROOT LOGIN (krb) %s from %.*s, %s.%s@%s",
+                              tty, UT_HOSTSIZE, hostname,
+                              kdata->pname, kdata->pinst,
+                              kdata->prealm);
 #else
-                           (void) sprintf(buf,
-                                  "ROOT LOGIN (krb) %s from %s, %s.%s@%s",
-                                  tty, hostname,
-                                  kdata->pname, kdata->pinst,
-                                  kdata->prealm);
-#endif
-                           syslog(LOG_NOTICE, "%s", buf);
-                       } else {
+               (void) sprintf(buf,
+                              "ROOT LOGIN (krb) %s from %s, %s.%s@%s",
+                              tty, hostname,
+                              kdata->pname, kdata->pinst,
+                              kdata->prealm);
+#endif
+               syslog(LOG_NOTICE, "%s", buf);
+           } else {
+               syslog(LOG_NOTICE,
+                      "ROOT LOGIN (krb) %s, %s.%s@%s",
+                      tty,
+                      kdata->pname, kdata->pinst,
+                      kdata->prealm);
+           }
+       } else
 #endif /* KRB4_KLOGIN */
+           {
+               if (hostname) {
 #ifdef UT_HOSTSIZE
-                       syslog(LOG_NOTICE, "ROOT LOGIN %s FROM %.*s",
-                           tty, UT_HOSTSIZE, hostname);
+                   syslog(LOG_NOTICE, "ROOT LOGIN %s FROM %.*s",
+                          tty, UT_HOSTSIZE, hostname);
 #else
-                       syslog(LOG_NOTICE, "ROOT LOGIN %s FROM %s",
-                           tty, hostname);
+                   syslog(LOG_NOTICE, "ROOT LOGIN %s FROM %s",
+                          tty, hostname);
 #endif
-#ifdef KRB4_KLOGIN
-                       }
-               else 
-                       if (kdata) {
-                           syslog(LOG_NOTICE,
-                                  "ROOT LOGIN (krb) %s, %s.%s@%s",
-                                  tty,
-                                  kdata->pname, kdata->pinst,
-                                  kdata->prealm);
-                       } 
-#endif /* KRB4_KLOGIN */
-               else
-                       syslog(LOG_NOTICE, "ROOT LOGIN %s", tty);
+               } else {
+                   syslog(LOG_NOTICE, "ROOT LOGIN %s", tty);
+               }
+           }
 
-       afs_login ();
+    afs_login();
 
-       if (!quietlog) {
+    if (!quietlog) {
 #ifdef KRB4_KLOGIN
-               if (!krbflag && !fflag && !eflag )
-                   printf("\nWarning: No Kerberos tickets obtained.\n\n");
+       if (!krbflag && !fflag && !eflag )
+           printf("\nWarning: No Kerberos tickets obtained.\n\n");
 #endif /* KRB4_KLOGIN */
-               motd ();
-               check_mail ();
-       }
+       motd();
+       check_mail();
+    }
 
 #ifndef OQUOTA
-       if (! access( QUOTAWARN, X_OK)) (void) system(QUOTAWARN);
-#endif
-       handler_init (sa, SIG_DFL);
-       handler_set (SIGALRM, sa);
-       handler_set (SIGQUIT, sa);
-       handler_set (SIGINT, sa);
-       handler_init (sa, SIG_IGN);
-       handler_set (SIGTSTP, sa);
-
-       tbuf[0] = '-';
-       (void) strncpy(tbuf + 1, (p = strrchr(pwd->pw_shell, '/')) ?
-           p + 1 : pwd->pw_shell, sizeof(tbuf) - 1);
-       tbuf[sizeof(tbuf) - 1] = '\0';
-       execlp(pwd->pw_shell, tbuf, 0);
-       fprintf(stderr, "login: no shell: ");
-       perror(pwd->pw_shell);
-       exit(0);
+    if (! access( QUOTAWARN, X_OK))
+       (void) system(QUOTAWARN);
+#endif
+
+    handler_init (sa, SIG_DFL);
+    handler_set (SIGALRM, sa);
+    handler_set (SIGQUIT, sa);
+    handler_set (SIGINT, sa);
+    handler_init (sa, SIG_IGN);
+    handler_set (SIGTSTP, sa);
+
+    tbuf[0] = '-';
+    p = strrchr(pwd->pw_shell, '/');
+    (void) strncpy(tbuf+1, p?(p+1):pwd->pw_shell, sizeof(tbuf-1));
+    tbuf[sizeof(tbuf) - 1] = '\0';
+
+    execlp(pwd->pw_shell, tbuf, 0);
+    fprintf(stderr, "login: no shell: ");
+    perror(pwd->pw_shell);
+    exit(0);
 }
 
 char *speeds[] = {
@@ -1991,212 +1845,216 @@ speed_t b_speeds[] = {
 
 term_init (do_rlogin)
 {
-       int line_speed = -1;
+    int line_speed = -1;
 
-       if (do_rlogin) {
-           register char *cp = strchr(term, '/'), **cpp;
-           char *speed;
+    if (do_rlogin) {
+       register char *cp = strchr(term, '/'), **cpp;
+       char *speed;
 
-           if (cp) {
+       if (cp) {
+           *cp++ = '\0';
+           speed = cp;
+           cp = strchr(speed, '/');
+           if (cp)
                *cp++ = '\0';
-               speed = cp;
-               cp = strchr(speed, '/');
-               if (cp)
-                   *cp++ = '\0';
-               for (cpp = speeds; cpp < &speeds[NSPEEDS]; cpp++)
-                   if (strcmp(*cpp, speed) == 0) {
-                       line_speed = cpp-speeds;
-                       break;
-                   }
-           }
+           for (cpp = speeds; cpp < &speeds[NSPEEDS]; cpp++)
+               if (strcmp(*cpp, speed) == 0) {
+                   line_speed = cpp-speeds;
+                   break;
+               }
        }
+    }
 #ifdef POSIX_TERMIOS
-       {
-           struct termios tc;
+    {
+       struct termios tc;
 
-           (void)tcgetattr(0, &tc);
-           if (line_speed != -1) {
-               cfsetispeed(&tc, b_speeds[line_speed]);
-               cfsetospeed(&tc, b_speeds[line_speed]);
-           }
-           tc.c_cc[VMIN] = 1;
-           tc.c_cc[VTIME] = 0;
+       (void)tcgetattr(0, &tc);
+       if (line_speed != -1) {
+           cfsetispeed(&tc, b_speeds[line_speed]);
+           cfsetospeed(&tc, b_speeds[line_speed]);
+       }
+       tc.c_cc[VMIN] = 1;
+       tc.c_cc[VTIME] = 0;
 #ifndef NO_INIT_CC
-           tc.c_cc[VERASE] = CERASE;
-           tc.c_cc[VKILL] = CKILL;
-           tc.c_cc[VEOF] = CEOF;
-           tc.c_cc[VINTR] = CINTR;
-           tc.c_cc[VQUIT] = CQUIT;
-           tc.c_cc[VSTART] = CSTART;
-           tc.c_cc[VSTOP] = CSTOP;
+       tc.c_cc[VERASE] = CERASE;
+       tc.c_cc[VKILL] = CKILL;
+       tc.c_cc[VEOF] = CEOF;
+       tc.c_cc[VINTR] = CINTR;
+       tc.c_cc[VQUIT] = CQUIT;
+       tc.c_cc[VSTART] = CSTART;
+       tc.c_cc[VSTOP] = CSTOP;
 #ifndef CNUL
 #define CNUL CEOL
 #endif
-           tc.c_cc[VEOL] = CNUL;
-           /* The following are common extensions to POSIX */
+       tc.c_cc[VEOL] = CNUL;
+       /* The following are common extensions to POSIX */
 #ifdef VEOL2
-           tc.c_cc[VEOL2] = CNUL;
+       tc.c_cc[VEOL2] = CNUL;
 #endif
 #ifdef VSUSP
 #if !defined(CSUSP) && defined(CSWTCH)
 #define CSUSP CSWTCH
 #endif
-           tc.c_cc[VSUSP] = CSUSP;
+       tc.c_cc[VSUSP] = CSUSP;
 #endif
 #ifdef VDSUSP
-           tc.c_cc[VDSUSP] = CDSUSP;
+       tc.c_cc[VDSUSP] = CDSUSP;
 #endif
 #ifdef VLNEXT
-           tc.c_cc[VLNEXT] = CLNEXT;
+       tc.c_cc[VLNEXT] = CLNEXT;
 #endif
 #ifdef VREPRINT
-           tc.c_cc[VREPRINT] = CRPRNT;
+       tc.c_cc[VREPRINT] = CRPRNT;
 #endif
 #ifdef VDISCRD
-           tc.c_cc[VDISCRD] = CFLUSH;
+       tc.c_cc[VDISCRD] = CFLUSH;
 #endif
 #ifdef VDISCARD
 #ifndef CDISCARD
 #define CDISCARD CFLUSH
 #endif
-           tc.c_cc[VDISCARD] = CDISCARD;
+       tc.c_cc[VDISCARD] = CDISCARD;
 #endif
 #ifdef VWERSE
-           tc.c_cc[VWERSE] = CWERASE;
+       tc.c_cc[VWERSE] = CWERASE;
 #endif
 #ifdef VWERASE
-           tc.c_cc[VWERASE] = CWERASE;
+       tc.c_cc[VWERASE] = CWERASE;
 #endif
 #if defined (VSTATUS) && defined (CSTATUS)
-           tc.c_cc[VSTATUS] = CSTATUS;
+       tc.c_cc[VSTATUS] = CSTATUS;
 #endif /* VSTATUS && CSTATUS */
 #endif /* NO_INIT_CC */
-           /* set all standard echo, edit, and job control options */
-           /* but leave any extensions */
-           tc.c_lflag |= ECHO|ECHOE|ECHOK|ICANON|ISIG|IEXTEN;
-           tc.c_lflag &= ~(NOFLSH|TOSTOP);
+       /* set all standard echo, edit, and job control options */
+       /* but leave any extensions */
+       tc.c_lflag |= ECHO|ECHOE|ECHOK|ICANON|ISIG|IEXTEN;
+       tc.c_lflag &= ~(NOFLSH|TOSTOP);
 #ifdef ECHOCTL
-           /* Not POSIX, but if we have it, we probably want it */
-           tc.c_lflag |= ECHOCTL;
+       /* Not POSIX, but if we have it, we probably want it */
+       tc.c_lflag |= ECHOCTL;
 #endif
 #ifdef ECHOKE
-           /* Not POSIX, but if we have it, we probably want it */
-           tc.c_lflag |= ECHOKE;
+       /* Not POSIX, but if we have it, we probably want it */
+       tc.c_lflag |= ECHOKE;
 #endif
-           tc.c_iflag |= ICRNL|BRKINT;
-           tc.c_oflag |= ONLCR|OPOST|TAB3;
-           tcsetattr(0, TCSANOW, &tc);
-       }
+       tc.c_iflag |= ICRNL|BRKINT;
+       tc.c_oflag |= ONLCR|OPOST|TAB3;
+       tcsetattr(0, TCSANOW, &tc);
+    }
 
 #else /* not POSIX_TERMIOS */
 
-       {
-           struct sgttyb sgttyb;
-           static struct tchars tc = {
-               CINTR, CQUIT, CSTART, CSTOP, CEOT, CBRK
-           };
-           static struct ltchars ltc = {
-               CSUSP, CDSUSP, CRPRNT, CFLUSH, CWERASE, CLNEXT
-           };
-
-           (void) ioctl(0, TIOCGETP, (char *)&sgttyb);
-           if (line_speed != -1)
-               sgttyb.sg_ispeed = sgttyb.sg_ospeed = line_speed;
-           sgttyb.sg_flags = ECHO|CRMOD|ANYP|XTABS;
-           sgttyb.sg_erase = CERASE;
-           sgttyb.sg_kill = CKILL;
-           (void)ioctl(0, TIOCSLTC, (char *)&ltc);
-           (void)ioctl(0, TIOCSETC, (char *)&tc);
-           (void)ioctl(0, TIOCSETP, (char *)&sgttyb);
+    {
+       struct sgttyb sgttyb;
+       static struct tchars tc = {
+           CINTR, CQUIT, CSTART, CSTOP, CEOT, CBRK
+       };
+       static struct ltchars ltc = {
+           CSUSP, CDSUSP, CRPRNT, CFLUSH, CWERASE, CLNEXT
+       };
+
+       (void) ioctl(0, TIOCGETP, (char *)&sgttyb);
+       if (line_speed != -1)
+           sgttyb.sg_ispeed = sgttyb.sg_ospeed = line_speed;
+       sgttyb.sg_flags = ECHO|CRMOD|ANYP|XTABS;
+       sgttyb.sg_erase = CERASE;
+       sgttyb.sg_kill = CKILL;
+       (void)ioctl(0, TIOCSLTC, (char *)&ltc);
+       (void)ioctl(0, TIOCSETC, (char *)&tc);
+       (void)ioctl(0, TIOCSETP, (char *)&sgttyb);
 #if defined(TIOCSETD)
-           {
-               int ioctlval;
-               ioctlval = 0;
-               (void)ioctl(0, TIOCSETD, (char *)&ioctlval);
-           }
-#endif
+       {
+           int ioctlval;
+           ioctlval = 0;
+           (void)ioctl(0, TIOCSETD, (char *)&ioctlval);
        }
+#endif
+    }
 #endif
 }
 
 void getloginname()
 {
-       register int ch;
-       register char *p;
-       static char nbuf[UT_NAMESIZE + 1];
-
-       for (;;) {
-               printf("login: ");
-               for (p = nbuf; (ch = getchar()) != '\n'; ) {
-                       if (ch == EOF)
-                               exit(0);
-                       if (p < nbuf + UT_NAMESIZE)
-                               *p++ = ch;
-               }
-               if (p > nbuf)
-                       if (nbuf[0] == '-')
-                               fprintf(stderr,
-                                   "login names may not start with '-'.\n");
-                       else {
-                               *p = '\0';
-                               username = nbuf;
-                               break;
-                       }
+    register int ch;
+    register char *p;
+    static char nbuf[UT_NAMESIZE + 1];
+
+    for (;;) {
+       printf("login: ");
+       for (p = nbuf; (ch = getchar()) != '\n'; ) {
+           if (ch == EOF)
+               exit(0);
+           if (p < nbuf + UT_NAMESIZE)
+               *p++ = ch;
        }
+       if (p > nbuf)
+           if (nbuf[0] == '-')
+               fprintf(stderr,
+                       "login names may not start with '-'.\n");
+           else {
+               *p = '\0';
+               username = nbuf;
+               break;
+           }
+    }
 }
 
 sigtype
 timedout()
 {
-       fprintf(stderr, "Login timed out after %d seconds\n", timeout);
-       exit(0);
+    fprintf(stderr, "Login timed out after %d seconds\n", timeout);
+    exit(0);
 }
 
 #ifndef HAVE_TTYENT_H
 int root_tty_security = 1;
 #endif
+
 int rootterm(tty)
        char *tty;
 {
 #ifndef HAVE_TTYENT_H
-       return(root_tty_security);
+    return(root_tty_security);
 #else
-       struct ttyent *t;
+    struct ttyent *t;
 
-       return((t = getttynam(tty)) && t->ty_status&TTY_SECURE);
+    return((t = getttynam(tty)) && t->ty_status&TTY_SECURE);
 #endif /* HAVE_TTYENT_H */
 }
 
 #ifndef NO_MOTD
 sigjmp_buf motdinterrupt;
+
 sigtype
 sigint()
 {
-       siglongjmp(motdinterrupt, 1);
+    siglongjmp(motdinterrupt, 1);
 }
 
 void motd()
 {
-       register int fd, nchars;
-       char tbuf[8192];
-       handler sa, osa;
-
-       if ((fd = open(MOTDFILE, O_RDONLY, 0)) < 0)
-               return;
-       handler_init (sa, sigint);
-       handler_swap (SIGINT, sa, osa);
-       if (sigsetjmp(motdinterrupt, 1) == 0)
-               while ((nchars = read(fd, tbuf, sizeof(tbuf))) > 0)
-                       (void)write(fileno(stdout), tbuf, nchars);
-       handler_set (SIGINT, osa);
-       (void)close(fd);
+    register int fd, nchars;
+    char tbuf[8192];
+    handler sa, osa;
+
+    if ((fd = open(MOTDFILE, O_RDONLY, 0)) < 0)
+       return;
+    handler_init (sa, sigint);
+    handler_swap (SIGINT, sa, osa);
+    if (sigsetjmp(motdinterrupt, 1) == 0)
+       while ((nchars = read(fd, tbuf, sizeof(tbuf))) > 0)
+           (void)write(fileno(stdout), tbuf, nchars);
+    handler_set (SIGINT, osa);
+    (void)close(fd);
 }
 #else
-void motd () { }
+void motd()
+{
+}
 #endif
 
 #ifndef NO_MAILCHECK
-void check_mail ()
+void check_mail()
 {
     char tbuf[MAXPATHLEN+2];
     struct stat st;
@@ -2206,56 +2064,61 @@ void check_mail ()
               (st.st_mtime > st.st_atime) ? "new " : "");
 }
 #else
-void check_mail () { }
+void check_mail()
+{
+}
 #endif
 
 void checknologin()
 {
-       register int fd, nchars;
-       char tbuf[8192];
+    register int fd, nchars;
+    char tbuf[8192];
 
-       if ((fd = open(NOLOGIN, O_RDONLY, 0)) >= 0) {
-               while ((nchars = read(fd, tbuf, sizeof(tbuf))) > 0)
-                       (void)write(fileno(stdout), tbuf, nchars);
-               sleepexit(0);
-       }
+    if ((fd = open(NOLOGIN, O_RDONLY, 0)) >= 0) {
+       while ((nchars = read(fd, tbuf, sizeof(tbuf))) > 0)
+           (void)write(fileno(stdout), tbuf, nchars);
+       sleepexit(0);
+    }
 }
 
 void dolastlog(quiet, tty)
-       int quiet;
-       char *tty;
+     int quiet;
+     char *tty;
 {
 #if defined(HAVE_LASTLOG_H) || (defined(BSD) && (BSD >= 199103))
-       struct lastlog ll;
-       int fd;
+    struct lastlog ll;
+    int fd;
 
-       if ((fd = open(LASTLOG, O_RDWR, 0)) >= 0) {
-               (void)lseek(fd, (off_t)pwd->pw_uid * sizeof(ll), SEEK_SET);
-               if (!quiet) {
-                       if (read(fd, (char *)&ll, sizeof(ll)) == sizeof(ll) &&
-                           ll.ll_time != 0) {
-                               printf("Last login: %.*s ",
-                                   24-5, (char *)ctime(&ll.ll_time));
-                               if (*ll.ll_host != '\0')
-                                       printf("from %.*s\n",
-                                           sizeof(ll.ll_host), ll.ll_host);
-                               else
-                                       printf("on %.*s\n",
-                                           sizeof(ll.ll_line), ll.ll_line);
-                       }
-                       (void)lseek(fd, (off_t)pwd->pw_uid * sizeof(ll), SEEK_SET);
-               }
-               (void)time(&ll.ll_time);
-               (void) strncpy(ll.ll_line, tty, sizeof(ll.ll_line));
-               ll.ll_line[sizeof(ll.ll_line) - 1] = '\0';
-               if (hostname) {
-                   (void) strncpy(ll.ll_host, hostname, sizeof(ll.ll_host));
-                   ll.ll_host[sizeof(ll.ll_host) - 1] = '\0';
-               } else
-                   (void) memset(ll.ll_host, 0, sizeof(ll.ll_host));
-               (void)write(fd, (char *)&ll, sizeof(ll));
-               (void)close(fd);
+    if ((fd = open(LASTLOG, O_RDWR, 0)) >= 0) {
+       (void)lseek(fd, (off_t)pwd->pw_uid * sizeof(ll), SEEK_SET);
+       if (!quiet) {
+           if ((read(fd, (char *)&ll, sizeof(ll)) == sizeof(ll)) &&
+               (ll.ll_time != 0)) {
+
+               printf("Last login: %.*s ", 24-5, (char *)ctime(&ll.ll_time));
+
+               if (*ll.ll_host != '\0')
+                   printf("from %.*s\n", sizeof(ll.ll_host), ll.ll_host);
+               else
+                   printf("on %.*s\n", sizeof(ll.ll_line), ll.ll_line);
+           }
+           (void)lseek(fd, (off_t)pwd->pw_uid * sizeof(ll), SEEK_SET);
+       }
+       (void) time(&ll.ll_time);
+
+       (void) strncpy(ll.ll_line, tty, sizeof(ll.ll_line));
+       ll.ll_line[sizeof(ll.ll_line) - 1] = '\0';
+
+       if (hostname) {
+           (void) strncpy(ll.ll_host, hostname, sizeof(ll.ll_host));
+           ll.ll_host[sizeof(ll.ll_host) - 1] = '\0';
+       } else {
+           (void) memset(ll.ll_host, 0, sizeof(ll.ll_host));
        }
+
+       (void)write(fd, (char *)&ll, sizeof(ll));
+       (void)close(fd);
+    }
 #endif
 }
 
@@ -2268,166 +2131,168 @@ void dolastlog(quiet, tty)
 
 char *
 stypeof(ttyid)
-  char *ttyid;
+     char *ttyid;
 {
-char *cp = getenv("term");
+    char *cp = getenv("term");
 
 #ifndef HAVE_TTYENT_H
-if (cp)
-  return cp;
-else return(UNKNOWN);
+    if (cp)
+       return cp;
+    else
+       return(UNKNOWN);
 #else
-       struct ttyent *t;
-       if (cp)
-         return cp;
- else return(ttyid && (t = getttynam(ttyid)) ? t->ty_type : UNKNOWN);
+    struct ttyent *t;
+    if (cp)
+       return cp;
+    else
+       return(ttyid && (t = getttynam(ttyid)) ? t->ty_type : UNKNOWN);
 #endif
 }
 
 int doremotelogin(host)
-       char *host;
+     char *host;
 {
-       static char lusername[UT_NAMESIZE+1];
-       char rusername[UT_NAMESIZE+1];
-
-       lgetstr(rusername, sizeof(rusername), "Remote user");
-       lgetstr(lusername, sizeof(lusername), "Local user");
-       lgetstr(term, sizeof(term), "Terminal type");
-       username = lusername;
-       pwd = getpwnam(username);
-       if (pwd == NULL)
-               return(-1);
-       return(ruserok(host, (pwd->pw_uid == 0), rusername, username));
+    static char lusername[UT_NAMESIZE+1];
+    char rusername[UT_NAMESIZE+1];
+
+    lgetstr(rusername, sizeof(rusername), "Remote user");
+    lgetstr(lusername, sizeof(lusername), "Local user");
+    lgetstr(term, sizeof(term), "Terminal type");
+    username = lusername;
+    pwd = getpwnam(username);
+    if (pwd == NULL)
+       return(-1);
+    return(ruserok(host, (pwd->pw_uid == 0), rusername, username));
 }
 
 #ifdef KRB4_KLOGIN
 int do_krb_login(host, strict)
-       char *host;
-       int strict;
+     char *host;
+     int strict;
 {
-       int rc;
-       struct sockaddr_in sin;
-       char instance[INST_SZ], version[9];
-       long authoptions = 0L;
-        struct hostent *hp = gethostbyname(host);
-       static char lusername[UT_NAMESIZE+1];
+    int rc;
+    struct sockaddr_in sin;
+    char instance[INST_SZ], version[9];
+    long authoptions = 0L;
+    struct hostent *hp = gethostbyname(host);
+    static char lusername[UT_NAMESIZE+1];
+    
+    /*
+     * Kerberos autologin protocol.
+     */
 
+    (void) memset((char *) &sin, 0, (int) sizeof(sin));
+    
+    if (hp)
+       (void) memcpy ((char *)&sin.sin_addr, hp->h_addr,
+                      sizeof(sin.sin_addr));
+    else
+       sin.sin_addr.s_addr = inet_addr(host);
+    
+    if ((hp == NULL) && (sin.sin_addr.s_addr == -1)) {
+       printf("Hostname did not resolve to an address, so Kerberos authentication failed\r\n");
        /*
-        * Kerberos autologin protocol.
+        * No host addr prevents auth, so
+        * punt krb and require password
         */
-
-       (void) memset((char *) &sin, 0, (int) sizeof(sin));
-
-        if (hp)
-                (void) memcpy ((char *)&sin.sin_addr, hp->h_addr,
-                              sizeof(sin.sin_addr));
-       else
-               sin.sin_addr.s_addr = inet_addr(host);
-
-       if ((hp == NULL) && (sin.sin_addr.s_addr == -1)) {
-           printf("Hostname did not resolve to an address, so Kerberos authentication failed\r\n");
-                /*
-                * No host addr prevents auth, so
-                 * punt krb and require password
-                */
-                if (strict) {
-                        goto paranoid;
-                } else {
-                       pwd = NULL;
-                        return(-1);
-               }
+       if (strict) {
+           goto paranoid;
+       } else {
+           pwd = NULL;
+           return(-1);
        }
+    }
 
-       kdata = (AUTH_DAT *)malloc( sizeof(AUTH_DAT) );
-       ticket = (KTEXT) malloc(sizeof(KTEXT_ST));
+    kdata = (AUTH_DAT *)malloc( sizeof(AUTH_DAT) );
+    ticket = (KTEXT) malloc(sizeof(KTEXT_ST));
 
-       (void) strcpy(instance, "*");
-       if ((rc=krb_recvauth(authoptions, 0, ticket, "rcmd",
-                           instance, &sin,
-                           (struct sockaddr_in *)0,
-                           kdata, "", (bit_64 *) 0, version))) {
-               printf("Kerberos rlogin failed: %s\r\n",krb_get_err_text(rc));
-               if (strict) {
+    (void) strcpy(instance, "*");
+    if ((rc=krb_recvauth(authoptions, 0, ticket, "rcmd",
+                        instance, &sin,
+                        (struct sockaddr_in *)0,
+                        kdata, "", (bit_64 *) 0, version))) {
+       printf("Kerberos rlogin failed: %s\r\n",krb_get_err_text(rc));
+       if (strict) {
 paranoid:
-                       /*
-                        * Paranoid hosts, such as a Kerberos server,
-                        * specify the Klogind daemon to disallow
-                        * even password access here.
-                        */
-                       printf("Sorry, you must have Kerberos authentication to access this host.\r\n");
-                       exit(1);
-               }
-       }
-       (void) lgetstr(lusername, sizeof (lusername), "Local user");
-       (void) lgetstr(term, sizeof(term), "Terminal type");
-       username = lusername;
-       if (getuid()) {
-               pwd = NULL;
-               return(-1);
-       }
-       pwd = getpwnam(lusername);
-       if (pwd == NULL) {
-               pwd = NULL;
-               return(-1);
+           /*
+            * Paranoid hosts, such as a Kerberos server,
+            * specify the Klogind daemon to disallow
+            * even password access here.
+            */
+           printf("Sorry, you must have Kerberos authentication to access this host.\r\n");
+           exit(1);
        }
+    }
+    (void) lgetstr(lusername, sizeof (lusername), "Local user");
+    (void) lgetstr(term, sizeof(term), "Terminal type");
+    username = lusername;
+    if (getuid()) {
+       pwd = NULL;
+       return(-1);
+    }
+    pwd = getpwnam(lusername);
+    if (pwd == NULL) {
+       pwd = NULL;
+       return(-1);
+    }
 
-       /*
-        * if Kerberos login failed because of an error in krb_recvauth,
-        * return the indication of a bad attempt.  User will be prompted
-        * for a password.  We CAN'T check the .rhost file, because we need 
-        * the remote username to do that, and the remote username is in the 
-        * Kerberos ticket.  This affects ONLY the case where there is
-        * Kerberos on both ends, but Kerberos fails on the server end. 
-        */
-       if (rc) {
-               return(-1);
-       }
+    /*
+     * if Kerberos login failed because of an error in krb_recvauth,
+     * return the indication of a bad attempt.  User will be prompted
+     * for a password.  We CAN'T check the .rhost file, because we need 
+     * the remote username to do that, and the remote username is in the 
+     * Kerberos ticket.  This affects ONLY the case where there is
+     * Kerberos on both ends, but Kerberos fails on the server end. 
+     */
+    if (rc) {
+       return(-1);
+    }
 
-       if ((rc=kuserok(kdata,lusername))) {
-               printf("login: %s has not given you permission to login without a password.\r\n",lusername);
-               if (strict) {
-                 exit(1);
-               }
-               return(-1);
+    if ((rc=kuserok(kdata,lusername))) {
+       printf("login: %s has not given you permission to login without a password.\r\n",lusername);
+       if (strict) {
+           exit(1);
        }
-       return(0);
+       return(-1);
+    }
+    return(0);
 }
 #endif /* KRB4_KLOGIN */
 
 void lgetstr(buf, cnt, err)
-       char *buf, *err;
-       int cnt;
+     char *buf, *err;
+     int cnt;
 {
-       int ocnt = cnt;
-       char *obuf = buf;
-       char ch;
-
-       do {
-               if (read(0, &ch, sizeof(ch)) != sizeof(ch))
-                       exit(1);
-               if (--cnt < 0) {
-                       fprintf(stderr,"%s '%.*s' too long, %d characters maximum.\r\n",
-                              err, ocnt, obuf, ocnt-1);
-                       sleepexit(1);
-               }
-               *buf++ = ch;
-       } while (ch);
+    int ocnt = cnt;
+    char *obuf = buf;
+    char ch;
+
+    do {
+       if (read(0, &ch, sizeof(ch)) != sizeof(ch))
+           exit(1);
+       if (--cnt < 0) {
+           fprintf(stderr,"%s '%.*s' too long, %d characters maximum.\r\n",
+                   err, ocnt, obuf, ocnt-1);
+           sleepexit(1);
+       }
+       *buf++ = ch;
+    } while (ch);
 }
 
 void sleepexit(eval)
-       int eval;
+     int eval;
 {
 #ifdef KRB4_GET_TICKETS
-       if (login_krb4_get_tickets && krbflag)
-           (void) destroy_tickets();
+    if (login_krb4_get_tickets && krbflag)
+       (void) destroy_tickets();
 #endif /* KRB4_GET_TICKETS */
-       sleep((u_int)5);
-       exit(eval);
+    sleep((u_int)5);
+    exit(eval);
 }
 
 #if defined(KRB4_GET_TICKETS) || defined(KRB5_GET_TICKETS)
-
 static int hungup = 0;
+
 static sigtype
 sighup() {
     hungup = 1;
@@ -2448,34 +2313,38 @@ dofork()
 #ifdef _IBMR2
     update_ref_count(1);
 #endif
-    if(!(child=fork()))
-           return; /* Child process returns */
+    if (!(child=fork()))
+       return; /* Child process returns */
 
     /* The parent continues here */
 
-    { /* Try and get rid of our controlling tty.  On SunOS, this may or may
-       not work depending on if our parent did a setsid before exec-ing us. */
+    /* Try and get rid of our controlling tty.  On SunOS, this may or may
+       not work depending on if our parent did a setsid before exec-ing
+       us. */
 #ifndef __linux__
-      /* On linux, TIOCNOTTY causes us to die on a
-       SIGHUP, so don't even try it. */
+    /* On linux, TIOCNOTTY causes us to die on a
+       SIGHUP, so don't even try it. */
 #ifdef TIOCNOTTY
-      { int fd;
-        if ((fd = open("/dev/tty", O_RDWR)) >= 0) {
-          ioctl(fd, TIOCNOTTY, 0);
-          close(fd);
-        }
-      }
+    { 
+       int fd;
+
+       if ((fd = open("/dev/tty", O_RDWR)) >= 0) {
+           ioctl(fd, TIOCNOTTY, 0);
+           close(fd);
+       }
+    }
 #endif
 #endif /* __linux__ */
+
 #ifdef HAVE_SETSID
-      (void)setsid();
+    (void)setsid();
 #endif
+
 #ifdef SETPGRP_TWOARG
-      (void)setpgrp(0, 0);
+    (void)setpgrp(0, 0);
 #else
-      (void)setpgrp();
+    (void)setpgrp();
 #endif
-    } 
 
     /* Setup stuff?  This would be things we could do in parallel with login */
     (void) chdir("/"); /* Let's not keep the fs busy... */
@@ -2489,21 +2358,22 @@ dofork()
     while (1) {
 #ifdef HAVE_WAITPID
         pid = waitpid(child, 0, 0);
-#else
-#ifdef WAIT_USES_INT
+#elif defined(WAIT_USES_INT)
         pid = wait((int *)0);
 #else
         pid = wait((union wait *)0);
 #endif
-#endif
-       if (hungup)
+
+       if (hungup) {
 #ifdef HAVE_KILLPG
            killpg(child, SIGHUP);
 #else
            kill(-child, SIGHUP);
 #endif
+       }
+
        if (pid == child)
-               break;
+           break;
     }
     
     /* Cleanup stuff */
@@ -2525,20 +2395,18 @@ dofork()
    for compatablilty with version 5 krb library, since kcmd.o is linked
    into all programs. */
 
-char *
-  strsave(sp)
-char *sp;
+char *strsave(sp)
+     char *sp;
 {
     register char *ret;
     
-    if((ret = (char *) malloc((unsigned) strlen(sp)+1)) == NULL) {
+    if ((ret = (char *) malloc((unsigned) strlen(sp)+1)) == NULL) {
        fprintf(stderr, "no memory for saving args\n");
        exit(1);
     }
     (void) strcpy(ret,sp);
     return(ret);
 }
-
 #endif
 
 #ifdef _IBMR2
index 476fb5bce1620e41fda5b9cc91aaa2f9bf5da593..bdf6e8d71a3f006e8d6a3cebd21bf706e2a5374b 100644 (file)
@@ -1,3 +1,15 @@
+1998-10-24  Marc Horowitz  <marc@mit.edu>
+
+       * gss-server.c (sign_server): fix the text heuristic to recognize
+               whitespace as text.
+       (main): clean up file descriptors properly after each
+               connection.
+
+       * gss-client.c (read_file): properly handle empty files
+
+       * gss-client.c: (call_server): NUL-terminate the contents
+               of non-empty files on the wire.
+       
 Wed Feb 18 15:27:32 1998  Tom Yu  <tlyu@mit.edu>
 
        * Makefile.in: Remove trailing slash from BUILDTOP.  Fix up
index e0bca99c46baea8325e7342eb9a4d951a8b2e2f3..33a7e963a38a159f7cd33cb1c58d18a6978f179c 100644 (file)
@@ -239,25 +239,29 @@ void read_file(file_name, in_buf)
        exit(1);
     }
     in_buf->length = stat_buf.st_size;
-    in_buf->value = malloc(in_buf->length);
-    if (in_buf->value == 0) {
+
+    if (in_buf->length == 0) {
+       in_buf->value = NULL;
+       return;
+    }
+
+    if ((in_buf->value = malloc(in_buf->length)) == 0) {
        fprintf(stderr, "Couldn't allocate %d byte buffer for reading file\n",
                in_buf->length);
        exit(1);
     }
-    memset(in_buf->value, 0, in_buf->length);
-    for (bytes_in = 0; bytes_in < in_buf->length; bytes_in += count) {
-       count = read(fd, in_buf->value, in_buf->length);
-       if (count < 0) {
-           perror("read");
-           exit(1);
-       }
-       if (count == 0)
-           break;
+
+    /* this code used to check for incomplete reads, but you can't get
+       an incomplete read on any file for which fstat() is meaningful */
+
+    count = read(fd, in_buf->value, in_buf->length);
+    if (count < 0) {
+       perror("read");
+       exit(1);
     }
-    if (bytes_in != count)
+    if (count < in_buf->length)
        fprintf(stderr, "Warning, only read in %d bytes, expected %d\n",
-               bytes_in, count);
+               count, in_buf->length);
 }
 
 /*
@@ -281,8 +285,7 @@ void read_file(file_name, in_buf)
  * seals msg in a GSS-API token with gss_seal, sends it to the server,
  * reads back a GSS-API signature block for msg from the server, and
  * verifies it with gss_verify.  -1 is returned if any step fails,
- * otherwise 0 is returned.
- */
+ * otherwise 0 is returned.  */
 int call_server(host, port, oid, service_name, deleg_flag, msg, use_file)
      char *host;
      u_short port;
@@ -410,7 +413,7 @@ int call_server(host, port, oid, service_name, deleg_flag, msg, use_file)
      } else {
         /* Seal the message */
         in_buf.value = msg;
-        in_buf.length = strlen(msg) + 1;
+        in_buf.length = strlen(msg);
      }
 
      maj_stat = gss_wrap(&min_stat, context, 1, GSS_C_QOP_DEFAULT,
index ef9d4958201097af86a6ab734a4f4eeb1afc5d9b..3e9ff095926d3bc14b78c01446ed2dcce7045bfa 100644 (file)
@@ -393,9 +393,10 @@ int sign_server(s, server_creds)
 
      fprintf(log, "Received message: ");
      cp = msg_buf.value;
-     if (isprint(cp[0]) && isprint(cp[1]))
-       fprintf(log, "\"%s\"\n", cp);
-     else {
+     if ((isprint(cp[0]) || isspace(cp[0])) &&
+        (isprint(cp[1]) || isspace(cp[1]))) {
+       fprintf(log, "\"%.*s\"\n", msg_buf.length, msg_buf.value);
+     } else {
        printf("\n");
        print_token(&msg_buf);
      }
@@ -488,20 +489,21 @@ main(argc, argv)
      } else {
         int stmp;
 
-        if ((stmp = create_socket(port))) {
+        if ((stmp = create_socket(port)) >= 0) {
             do {
                 /* Accept a TCP connection */
                 if ((s = accept(stmp, NULL, 0)) < 0) {
                     perror("accepting connection");
-                } else {
-                    /* this return value is not checked, because there's
-                       not really anything to do if it fails */
-                    sign_server(s, server_creds);
+                    continue;
                 }
+                /* this return value is not checked, because there's
+                   not really anything to do if it fails */
+                sign_server(s, server_creds);
+                close(s);
             } while (!once);
-        }
 
-        close(stmp);
+            close(stmp);
+        }
      }
 
      (void) gss_release_cred(&min_stat, &server_creds);
index ed4aecb1a9e7a5129c5ebdb4173bf0d7cd59b3e2..b021129b04a2373437972bb8a2be9dccfd0fe83c 100644 (file)
@@ -1,3 +1,10 @@
+1998-10-26  Marc Horowitz  <marc@mit.edu>
+
+       * ftp.c (login): *always* encrypt the password, regardless
+       of the default command mode.
+       (do_auth): Try the new krb5 mech, and if that fails, try the
+       old one.
+
 1998-10-26  Geoffrey King  <gjking@mit.edu>
 
        * ftp.M: Add documentation for new ccc and cprotect commands.
index f6fb15677343f6c20d1316e8c5d43d33c72c4082..d19d62c2066d9b999d6eeb2ae54050abb46db672 100644 (file)
  * SUCH DAMAGE.
  */
 
+/*
+ * Copyright (C) 1998 by the FundsXpress, INC.
+ * 
+ * All rights reserved.
+ * 
+ * Export of this software from the United States of America may require
+ * a specific license from the United States Government.  It is the
+ * responsibility of any person or organization contemplating export to
+ * obtain such a license before exporting.
+ * 
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of FundsXpress. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  FundsXpress makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
 #ifndef lint
 static char sccsid[] = "@(#)ftp.c      5.38 (Berkeley) 4/22/91";
 #endif /* not lint */
@@ -95,11 +121,13 @@ MSG_DAT msg_data;
 #endif /* KRB5_KRB4_COMPAT */
 #ifdef GSSAPI
 #include <gssapi/gssapi.h>
-#include <gssapi/gssapi_generic.h>
+/* need to include the krb5 file, because we're doing manual fallback
+   from the v2 mech to the v2 mech.  Once there's real negotiation,
+   we can be generic again. */
+#include <gssapi/gssapi_krb5.h>
 gss_ctx_id_t gcontext;
 #endif /* GSSAPI */
 
-
 static int kerror;     /* XXX needed for all auth types */
 
 char   *auth_type;     /* Authentication succeeded?  If so, what type? */
@@ -308,7 +336,8 @@ login(host)
                if (pass == NULL)
                        pass = mygetpass("Password:");
 #ifndef NOENCRYPTION
-               if ((oldclevel = clevel) == PROT_S) clevel = PROT_P;
+               oldclevel = clevel;
+               clevel = PROT_P;
 #endif
                n = command("PASS %s", pass);
 #ifndef NOENCRYPTION
@@ -1843,8 +1872,16 @@ char realm[REALM_SZ + 1];
 #endif /* KRB5_KRB4_COMPAT */
 
 #ifdef GSSAPI
-/* for testing, we don't have an ftp key yet */
-char* gss_services[] = { "ftp", "host", 0 };
+struct {
+    const gss_OID_desc * const * mech_type;
+    char *service_name;
+} gss_trials[] = {
+    { &gss_mech_krb5_v2, "ftp" },
+    { &gss_mech_krb5, "ftp" },
+    { &gss_mech_krb5_v2, "host" },
+    { &gss_mech_krb5, "host" },
+};
+int n_gss_trials = sizeof(gss_trials)/sizeof(gss_trials[0]);
 #endif /* GSSAPI */
 
 do_auth()
@@ -1870,8 +1907,7 @@ do_auth()
          gss_name_t target_name;
          gss_buffer_desc send_tok, recv_tok, *token_ptr;
          char stbuf[FTP_BUFSIZ];
-         char **service_name, **end_service_name;
-         int comcode;
+         int comcode, trial;
          struct gss_channel_bindings_struct chan;
          chan.initiator_addrtype = GSS_C_AF_INET; /* OM_uint32  */ 
          chan.initiator_address.length = 4;
@@ -1882,21 +1918,15 @@ do_auth()
          chan.application_data.length = 0;
          chan.application_data.value = 0;
 
-         for (end_service_name = gss_services; *end_service_name; )
-           end_service_name++;
-         end_service_name--;
-
          if (verbose)
-           printf("%s accepted as authentication type\n", "GSSAPI");
+           printf("GSSAPI accepted as authentication type\n");
          
          /* blob from gss-client */
-           
          
-         for (service_name = gss_services; *service_name; service_name++) {
-           
+         for (trial = 0; trial < n_gss_trials; trial++) {
            /* ftp@hostname first, the host@hostname */
            /* the V5 GSSAPI binding canonicalizes this for us... */
-           sprintf(stbuf, "%s@%s", *service_name, hostname);
+           sprintf(stbuf, "%s@%s", gss_trials[trial].service_name, hostname);
            if (debug)
              fprintf(stderr, "Trying to authenticate to <%s>\n", stbuf);
 
@@ -1922,7 +1952,7 @@ do_auth()
                                     GSS_C_NO_CREDENTIAL,
                                     &gcontext,
                                     target_name,
-                                    GSS_C_NULL_OID,
+                                    *gss_trials[trial].mech_type,
                                     GSS_C_MUTUAL_FLAG | GSS_C_REPLAY_FLAG |
                                     (forward ? GSS_C_DELEG_FLAG : 0),
                                     0,
@@ -1935,7 +1965,7 @@ do_auth()
              
 
              if (maj_stat!=GSS_S_COMPLETE && maj_stat!=GSS_S_CONTINUE_NEEDED){
-               if (service_name == end_service_name)
+               if (trial == n_gss_trials-1)
                  user_gss_error(maj_stat, min_stat, "initializing context");
                (void) gss_release_name(&min_stat, &target_name);
                /* could just be that we missed on the service name */
@@ -1946,16 +1976,28 @@ do_auth()
                int len = send_tok.length;
                reply_parse = "ADAT="; /* for command() later */
                oldverbose = verbose;
-               verbose = 0;
+               verbose = (trial == n_gss_trials-1)?0:-1;
                kerror = radix_encode(send_tok.value, out_buf, &len, 0);
                if (kerror)  {
                  fprintf(stderr, "Base 64 encoding failed: %s\n",
                          radix_error(kerror));
                } else if ((comcode = command("ADAT %s", out_buf))!=COMPLETE
                           /* && comcode != 3 (335)*/) {
-                 fprintf(stderr, "GSSAPI ADAT failed\n");
-                 /* force out of loop */
-                 maj_stat = GSS_S_FAILURE;
+                   if (trial == n_gss_trials-1) {
+                       fprintf(stderr, "GSSAPI ADAT failed\n");
+                       /* force out of loop */
+                       maj_stat = GSS_S_FAILURE;
+                   }
+                   /* backoff to the v1 gssapi is still possible.  Send
+                      a new AUTH command.  If that fails, terminate the
+                      loop */
+                   if (command("AUTH %s", "GSSAPI") != CONTINUE) {
+                       fprintf(stderr,
+                               "GSSAPI ADAT failed, AUTH restart failed\n");
+                       /* force out of loop */
+                       maj_stat = GSS_S_FAILURE;
+                   }
+                   goto outer_loop;
                } else if (!reply_parse) {
                  fprintf(stderr,
                          "No authentication data received from server\n");
@@ -1979,7 +2021,7 @@ do_auth()
 
                /* get out of loop clean */
              gss_complete_loop:
-               service_name = end_service_name;
+               trial = n_gss_trials-1;
                gss_release_buffer(&min_stat, &send_tok);
                gss_release_name(&min_stat, &target_name);
                goto outer_loop;
@@ -1991,8 +2033,7 @@ do_auth()
          }
          verbose = oldverbose;
          if (maj_stat == GSS_S_COMPLETE) {
-           if (verbose)
-             printf("GSSAPI authentication succeeded\n");
+           printf("GSSAPI authentication succeeded\n");
            reply_parse = NULL;
            auth_type = "GSSAPI";
            return(1);
index 494050438de94c76b9bcaaead980e4c952407063..55168c36b33e665bdc9996b7933af164de1ef134 100644 (file)
@@ -1,3 +1,10 @@
+1998-10-26  Marc Horowitz  <marc@mit.edu>
+
+       * enc_des.c, kerberos.c: the ECB des functions don't exist
+       anymore, but telnet always encrypted/decrypted one block.  Convert
+       to calls to the new crypto api, with des-cbc-raw, using a single
+       block.
+
 Tue Mar  3 14:43:30 1998  Theodore Ts'o  <tytso@rsts-11.mit.edu>
 
        * configure.in: Change test for cgetent to use HAVE_ instead
index f44700a731b4c902443472e26026f24f94917dea..3912b35e938c26e384da9f4a2bc0dff15d33a726 100644 (file)
  * SUCH DAMAGE.
  */
 
+/*
+ * Copyright (C) 1998 by the FundsXpress, INC.
+ * 
+ * All rights reserved.
+ * 
+ * Export of this software from the United States of America may require
+ * a specific license from the United States Government.  It is the
+ * responsibility of any person or organization contemplating export to
+ * obtain such a license before exporting.
+ * 
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of FundsXpress. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  FundsXpress makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
 /* based on @(#)enc_des.c      8.1 (Berkeley) 6/4/93 */
 
 #ifdef ENCRYPTION
 # ifdef        AUTHENTICATION
 #  ifdef DES_ENCRYPTION
+#include <krb5.h>
 #include <arpa/telnet.h>
 #include <stdio.h>
 #ifdef __STDC__
@@ -53,6 +80,8 @@
 
 extern encrypt_debug_mode;
 
+extern krb5_context telnet_context;
+
 #define        CFB     0
 #define        OFB     1
 
@@ -65,20 +94,19 @@ extern encrypt_debug_mode;
 
 
 struct fb {
-       Block krbdes_key;
-       Schedule krbdes_sched;
        Block temp_feed;
        unsigned char fb_feed[64];
        int need_start;
        int state[2];
        int keyid[2];
        int once;
+       int validkey;
        struct stinfo {
                Block           str_output;
                Block           str_feed;
                Block           str_iv;
-               Block           str_ikey;
-               Schedule        str_sched;
+               unsigned char   str_keybytes[8]; /* yuck */
+               krb5_keyblock   str_key;
                int             str_index;
                int             str_flagshift;
        } streams[2];
@@ -122,6 +150,29 @@ static void fb64_session P((Session_Key *, int, struct fb *));
 void fb64_stream_key P((Block, struct stinfo *));
 int fb64_keyid P((int, unsigned char *, int *, struct fb *));
 
+static void ecb_encrypt(stp, in, out)
+     struct stinfo *stp;
+     Block in;
+     Block out;
+{
+       krb5_error_code code;
+       krb5_data din;
+       krb5_enc_data dout;
+       
+       din.length = 8;
+       din.data = in;
+
+       dout.ciphertext.length = 8;
+       dout.ciphertext.data = out;
+       dout.enctype = ENCTYPE_UNKNOWN;
+
+       code = krb5_c_encrypt(telnet_context, &stp->str_key, 0, 0,
+                             &din, &dout);
+       /* XXX I'm not sure what to do if this fails */
+       if (code)
+               com_err("libtelnet", code, "encrypting stream data");
+}
+
        void
 cfb64_init(server)
        int server;
@@ -207,7 +258,7 @@ fb64_start(fbp, dir, server)
                else if ((state & NO_SEND_IV) == 0)
                        break;
 
-               if (!VALIDKEY(fbp->krbdes_key)) {
+               if (!fbp->validkey) {
                        fbp->need_start = 1;
                        break;
                }
@@ -218,9 +269,18 @@ fb64_start(fbp, dir, server)
                /*
                 * Create a random feed and send it over.
                 */
-               des_new_random_key(fbp->temp_feed);
-               des_ecb_encrypt(fbp->temp_feed, fbp->temp_feed,
-                               fbp->krbdes_sched, 1);
+               {
+                       krb5_data d;
+                       krb5_error_code code;
+
+                       d.data = fbp->temp_feed;
+                       d.length = sizeof(fbp->temp_feed);
+
+                       if (code = krb5_c_random_make_octets(telnet_context,
+                                                            &d))
+                               return(FAILED);
+               }
+
                p = fbp->fb_feed + 3;
                *p++ = ENCRYPT_IS;
                p++;
@@ -418,23 +478,18 @@ fb64_session(key, server, fbp)
        int server;
        struct fb *fbp;
 {
-
        if (!key || key->type != SK_DES) {
                if (encrypt_debug_mode)
                        printf("Can't set krbdes's session key (%d != %d)\r\n",
                                key ? key->type : -1, SK_DES);
                return;
        }
-       memcpy((void *)fbp->krbdes_key, (void *)key->data, sizeof(Block));
 
-       fb64_stream_key(fbp->krbdes_key, &fbp->streams[DIR_ENCRYPT-1]);
-       fb64_stream_key(fbp->krbdes_key, &fbp->streams[DIR_DECRYPT-1]);
+       fbp->validkey = 1;
+
+       fb64_stream_key(key->data, &fbp->streams[DIR_ENCRYPT-1]);
+       fb64_stream_key(key->data, &fbp->streams[DIR_DECRYPT-1]);
 
-       if (fbp->once == 0) {
-               des_set_random_generator_seed(fbp->krbdes_key);
-               fbp->once = 1;
-       }
-       des_key_sched(fbp->krbdes_key, fbp->krbdes_sched);
        /*
         * Now look to see if krbdes_start() was was waiting for
         * the key to show up.  If so, go ahead an call it now
@@ -551,12 +606,9 @@ fb64_stream_iv(seed, stp)
        Block seed;
        register struct stinfo *stp;
 {
-
        memcpy((void *)stp->str_iv,     (void *)seed, sizeof(Block));
        memcpy((void *)stp->str_output, (void *)seed, sizeof(Block));
 
-       des_key_sched(stp->str_ikey, stp->str_sched);
-
        stp->str_index = sizeof(Block);
 }
 
@@ -565,8 +617,13 @@ fb64_stream_key(key, stp)
        Block key;
        register struct stinfo *stp;
 {
-       memcpy((void *)stp->str_ikey, (void *)key, sizeof(Block));
-       des_key_sched(key, stp->str_sched);
+       memcpy((void *)stp->str_keybytes, (void *)key, sizeof(Block));
+       stp->str_key.length = 8;
+       stp->str_key.contents = stp->str_keybytes;
+       /* the original version of this code uses des ecb mode, but
+          it only ever does one block at a time.  cbc with a zero iv
+          is identical */
+       stp->str_key.enctype = ENCTYPE_DES_CBC_RAW;
 
        memcpy((void *)stp->str_output, (void *)stp->str_iv, sizeof(Block));
 
@@ -607,7 +664,7 @@ cfb64_encrypt(s, c)
        while (c-- > 0) {
                if (index == sizeof(Block)) {
                        Block b;
-                       des_ecb_encrypt(stp->str_output, b, stp->str_sched, 1);
+                       ecb_encrypt(stp, stp->str_output, b);
                        memcpy((void *)stp->str_feed,(void *)b,sizeof(Block));
                        index = 0;
                }
@@ -641,7 +698,7 @@ cfb64_decrypt(data)
        index = stp->str_index++;
        if (index == sizeof(Block)) {
                Block b;
-               des_ecb_encrypt(stp->str_output, b, stp->str_sched, 1);
+               ecb_encrypt(stp, stp->str_output, b);
                memcpy((void *)stp->str_feed, (void *)b, sizeof(Block));
                stp->str_index = 1;     /* Next time will be 1 */
                index = 0;              /* But now use 0 */ 
@@ -683,7 +740,7 @@ ofb64_encrypt(s, c)
        while (c-- > 0) {
                if (index == sizeof(Block)) {
                        Block b;
-                       des_ecb_encrypt(stp->str_feed, b, stp->str_sched, 1);
+                       ecb_encrypt(stp, stp->str_feed, b);
                        memcpy((void *)stp->str_feed,(void *)b,sizeof(Block));
                        index = 0;
                }
@@ -714,7 +771,7 @@ ofb64_decrypt(data)
        index = stp->str_index++;
        if (index == sizeof(Block)) {
                Block b;
-               des_ecb_encrypt(stp->str_feed, b, stp->str_sched, 1);
+               ecb_encrypt(stp, stp->str_feed, b);
                memcpy((void *)stp->str_feed, (void *)b, sizeof(Block));
                stp->str_index = 1;     /* Next time will be 1 */
                index = 0;              /* But now use 0 */ 
index 63738b53bf5d0d6ad49fd901f7699ebf48ebdab8..ed32392c9c9d4b3332b3cef9669d9120650bc846 100644 (file)
  * or implied warranty.
  */
 
+/*
+ * Copyright (C) 1998 by the FundsXpress, INC.
+ * 
+ * All rights reserved.
+ * 
+ * Export of this software from the United States of America may require
+ * a specific license from the United States Government.  It is the
+ * responsibility of any person or organization contemplating export to
+ * obtain such a license before exporting.
+ * 
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of FundsXpress. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  FundsXpress makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
 #ifdef KRB4
+/* this code must be compiled in the krb5 tree.  disgustingly, there
+   is code in here which declares structures which happen to mirror
+   the krb4 des structures.  I didn't want to rototill this *completely*
+   so this is how it's going to work. --marc */
+#include <krb5.h>
 #include <sys/types.h>
 #include <arpa/telnet.h>
 #include <stdio.h>
 #include "misc.h"
 
 extern auth_debug_mode;
+extern krb5_context telnet_context;
 
 static unsigned char str_data[1024] = { IAC, SB, TELOPT_AUTHENTICATION, 0,
                                        AUTHTYPE_KERBEROS_V4, };
@@ -93,6 +125,7 @@ static       AUTH_DAT adat = { 0 };
 #ifdef ENCRYPTION
 static Block   session_key     = { 0 };
 static Schedule sched;
+static krb5_keyblock krbkey;
 static Block   challenge       = { 0 };
 #endif /* ENCRYPTION */
 
@@ -146,6 +179,9 @@ kerberos4_init(ap, server)
        } else {
                str_data[3] = TELQUAL_IS;
        }
+
+       kerberos5_init(NULL, server);
+
        return(1);
 }
 
@@ -157,15 +193,18 @@ kerberos4_send(ap)
        Authenticator *ap;
 {
        KTEXT_ST auth;
-#ifdef ENCRYPTION
-       Block enckey;
-#endif /* ENCRYPTION */
        char instance[INST_SZ];
        char *realm;
        char *krb_realmofhost();
        char *krb_get_phost();
        CREDENTIALS cred;
        int r;
+#ifdef ENCRYPTION
+       krb5_data data;
+       krb5_enc_data encdata;
+       krb5_error_code code;
+       krb5_keyblock random_key;
+#endif
 
        printf("[ Trying KERBEROS4 ... ]\r\n"); 
        if (!UserNameRequested) {
@@ -216,11 +255,56 @@ kerberos4_send(ap)
        if ((ap->way & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL) {
                register int i;
 
-               des_key_sched(cred.session, sched);
-               des_init_random_number_generator(cred.session);
-               des_new_random_key(session_key);
-               des_ecb_encrypt(session_key, session_key, sched, 0);
-               des_ecb_encrypt(session_key, challenge, sched, 0);
+               data.data = cred.session;
+               data.length = 8; /* sizeof(cred.session) */;
+
+               if (code = krb5_c_random_seed(telnet_context, &data)) {
+                   com_err("libtelnet", code,
+                           "while seeding random number generator");
+                   return(0);
+               }
+
+               if (code = krb5_c_make_random_key(telnet_context,
+                                                 ENCTYPE_DES_CBC_RAW,
+                                                 &random_key)) {
+                   com_err("libtelnet", code,
+                           "while creating random session key");
+                   return(0);
+               }
+
+               /* the krb4 code uses ecb mode, but on a single block
+                  with a zero ivec, ecb and cbc are the same */
+               krbkey.enctype = ENCTYPE_DES_CBC_RAW;
+               krbkey.length = 8;
+               krbkey.contents = cred.session;
+
+               encdata.ciphertext.data = random_key.contents;
+               encdata.ciphertext.length = random_key.length;
+               encdata.enctype = ENCTYPE_UNKNOWN;
+
+               data.data = session_key;
+               data.length = 8;
+
+               code = krb5_c_decrypt(telnet_context, &krbkey, 0, 0,
+                                     &encdata, &data);
+
+               krb5_free_keyblock_contents(telnet_context, &random_key);
+
+               if (code) {
+                   com_err("libtelnet", code, "while encrypting random key");
+                   return(0);
+               }
+
+               encdata.ciphertext.data = session_key;
+               encdata.ciphertext.length = 8;
+               encdata.enctype = ENCTYPE_UNKNOWN;
+
+               data.data = challenge;
+               data.length = 8;
+
+               code = krb5_c_decrypt(telnet_context, &krbkey, 0, 0,
+                                     &encdata, &data);
+
                /*
                 * Increment the challenge by 1, and encrypt it for
                 * later comparison.
@@ -232,7 +316,19 @@ kerberos4_send(ap)
                        if (x < 256)            /* if no overflow, all done */
                                break;
                }
-               des_ecb_encrypt(challenge, challenge, sched, 1);
+
+               data.data = challenge;
+               data.length = 8;
+
+               encdata.ciphertext.data = challenge;
+               encdata.ciphertext.length = 8;
+               encdata.enctype = ENCTYPE_UNKNOWN;
+
+               if (code = krb5_c_encrypt(telnet_context, &krbkey, 0, 0, &data,
+                                         &encdata)) {
+                   com_err("libtelnet", code, "while encrypting random key");
+                   return(0);
+               }
        }
 #endif /* ENCRYPTION */
        
@@ -253,7 +349,10 @@ kerberos4_is(ap, data, cnt)
 {
 #ifdef ENCRYPTION
        Session_Key skey;
-       Block datablock;
+       Block datablock, tmpkey;
+       krb5_data kdata;
+       krb5_enc_data encdata;
+       krb5_error_code code;
 #endif /* ENCRYPTION */
        char realm[REALM_SZ];
        char instance[INST_SZ];
@@ -317,24 +416,60 @@ kerberos4_is(ap, data, cnt)
                 * Initialize the random number generator since it's
                 * used later on by the encryption routine.
                 */
-               des_init_random_number_generator(session_key);
-               des_key_sched(session_key, sched);
+
+               kdata.data = session_key;
+               kdata.length = 8;
+
+               if (code = krb5_c_random_seed(telnet_context, &kdata)) {
+                   com_err("libtelnet", code,
+                           "while seeding random number generator");
+                   return;
+               }
+
                memcpy((void *)datablock, (void *)data, sizeof(Block));
                /*
                 * Take the received encrypted challenge, and encrypt
                 * it again to get a unique session_key for the
                 * ENCRYPT option.
                 */
-               des_ecb_encrypt(datablock, session_key, sched, 1);
+               krbkey.enctype = ENCTYPE_DES_CBC_RAW;
+               krbkey.length = 8;
+               krbkey.contents = session_key;
+
+               kdata.data = datablock;
+               kdata.length = 8;
+
+               encdata.ciphertext.data = tmpkey;
+               encdata.ciphertext.length = 8;
+               encdata.enctype = ENCTYPE_UNKNOWN;
+
+               if (code = krb5_c_encrypt(telnet_context, &krbkey, 0, 0,
+                                         &kdata, &encdata)) {
+                   com_err("libtelnet", code, "while encrypting random key");
+                   return;
+               }
+
                skey.type = SK_DES;
                skey.length = 8;
-               skey.data = session_key;
+               skey.data = tmpkey;
                encrypt_session_key(&skey, 1);
                /*
                 * Now decrypt the received encrypted challenge,
                 * increment by one, re-encrypt it and send it back.
                 */
-               des_ecb_encrypt(datablock, challenge, sched, 0);
+               encdata.ciphertext.data = datablock;
+               encdata.ciphertext.length = 8;
+               encdata.enctype = ENCTYPE_UNKNOWN;
+
+               kdata.data = challenge;
+               kdata.length = 8;
+
+               if (code = krb5_c_decrypt(telnet_context, &krbkey, 0, 0, 
+                                         &encdata, &kdata)) {
+                   com_err("libtelnet", code, "while decrypting challenge");
+                   return;
+               }
+
                for (r = 7; r >= 0; r--) {
                        register int t;
                        t = (unsigned int)challenge[r] + 1;
@@ -342,7 +477,20 @@ kerberos4_is(ap, data, cnt)
                        if (t < 256)            /* if no overflow, all done */
                                break;
                }
-               des_ecb_encrypt(challenge, challenge, sched, 1);
+
+               kdata.data = challenge;
+               kdata.length = 8;
+
+               encdata.ciphertext.data = challenge;
+               encdata.ciphertext.length = 8;
+               encdata.enctype = ENCTYPE_UNKNOWN;
+
+               if (code = krb5_c_encrypt(telnet_context, &krbkey, 0, 0,
+                                         &kdata, &encdata)) {
+                   com_err("libtelnet", code, "while decrypting challenge");
+                   return;
+               }
+
                Data(ap, KRB_RESPONSE, (void *)challenge, sizeof(challenge));
 #endif /* ENCRYPTION */
                break;
@@ -363,6 +511,10 @@ kerberos4_reply(ap, data, cnt)
 {
 #ifdef ENCRYPTION
        Session_Key skey;
+       krb5_data kdata;
+       krb5_enc_data encdata;
+       krb5_error_code code;
+
 #endif /* ENCRYPTION */
 
        if (cnt-- < 1)
@@ -387,7 +539,21 @@ kerberos4_reply(ap, data, cnt)
 #else  /* ENCRYPTION */
                        Data(ap, KRB_CHALLENGE, (void *)session_key,
                                                sizeof(session_key));
-                       des_ecb_encrypt(session_key, session_key, sched, 1);
+
+                       kdata.data = session_key;
+                       kdata.length = 8;
+
+                       encdata.ciphertext.data = session_key;
+                       encdata.ciphertext.length = 8;
+                       encdata.enctype = ENCTYPE_UNKNOWN;
+
+                       if (code = krb5_c_encrypt(telnet_context, &krbkey,
+                                                 0, 0, &kdata, &encdata)) {
+                               com_err("libtelnet", code,
+                                       "while encrypting session_key");
+                               return;
+                       }
+
                        skey.type = SK_DES;
                        skey.length = 8;
                        skey.data = session_key;
index 6d13e63f2c40c5f3f803043f221bdbaca324def3..7d94d0acf7144237a434381e41fdabc3e5ffb80d 100644 (file)
@@ -1,3 +1,10 @@
+1998-10-26  Marc Horowitz  <marc@mit.edu>
+
+       * commands.c: remove calls to setuid(getuid()).  This looks like
+       it was once an attempt to make it safe to run setuid, but it's not
+       safe for a number of other reasons, so there's no reason to
+       pretend.
+
 Sat Oct 10 06:24:55 1998  Geoffrey King  <gjking@mit.edu>
 
        * telnet.c (telnet): Cosmetic change: Put a newline after "Waiting
index 5c8ae3cb725e95202b61d5cb82fdef70b03bcfbe..c23e199cce1c6749803439004fcfb2ad15944947 100644 (file)
@@ -2378,7 +2378,6 @@ tn(argc, argv)
 
     if (connected) {
        printf("?Already connected to %s\r\n", hostname);
-       setuid(getuid());
        return 0;
     }
     if (argc < 2) {
@@ -2419,7 +2418,6 @@ tn(argc, argv)
        }
     usage:
        printf("usage: %s [-l user] [-a] host-name [port]\r\n", cmd);
-       setuid(getuid());
        return 0;
     }
     if (hostp == 0)
@@ -2434,11 +2432,9 @@ tn(argc, argv)
        temp = sourceroute(hostp, &srp, &srlen);
        if (temp == 0) {
            herror(srp);
-           setuid(getuid());
            return 0;
        } else if (temp == -1) {
            printf("Bad source route option: %s\r\n", hostp);
-           setuid(getuid());
            return 0;
        } else {
            sin.sin_addr.s_addr = temp;
@@ -2468,7 +2464,6 @@ tn(argc, argv)
                hostname = _hostname;
            } else {
                herror(hostp);
-               setuid(getuid());
                return 0;
            }
        }
@@ -2489,7 +2484,6 @@ tn(argc, argv)
                sin.sin_port = sp->s_port;
            else {
                printf("%s: bad port number\r\n", portp);
-               setuid(getuid());
                return 0;
            }
        } else {
@@ -2500,7 +2494,6 @@ tn(argc, argv)
            sp = getservbyname("telnet", "tcp");
            if (sp == 0) {
                fprintf(stderr, "telnet: tcp/telnet: unknown service\n");
-               setuid(getuid());
                return 0;
            }
            sin.sin_port = sp->s_port;
@@ -2510,7 +2503,6 @@ tn(argc, argv)
     printf("Trying %s...\r\n", inet_ntoa(sin.sin_addr));
     do {
        net = socket(AF_INET, SOCK_STREAM, 0);
-       setuid(getuid());
        if (net < 0) {
            perror("telnet: socket");
            return 0;
index 75b04852d135009ef2406a04e48423816294fa3f..e8390d6b21d4bd42fed66d86c15a027cd5318d61 100644 (file)
@@ -1,3 +1,11 @@
+1998-10-26  Marc Horowitz  <marc@mit.edu>
+
+       * configure.in: add kvno
+
+Sat Jul 25 15:00:26 1998  Sam Hartman  <hartmans@utwig.mesas.com>
+
+       * Makefile.in (LOCAL_SUBDIRS): add kvno
+
 Wed Feb 18 15:40:02 1998  Tom Yu  <tlyu@mit.edu>
 
        * Makefile.in: Remove trailing slash from thisconfigdir.
index b793c04303792fc2b8030026da89f20da9ff6528..e772cf6b864727c24c1ab9850887d84fb92e6c3c 100644 (file)
@@ -1,7 +1,7 @@
 thisconfigdir=.
 BUILDTOP=$(REL)$(U)
 
-LOCAL_SUBDIRS= klist kinit kdestroy kpasswd ksu
+LOCAL_SUBDIRS= klist kinit kdestroy kpasswd ksu kvno
 
 ##WIN32##all-windows::
 ##WIN32##      @echo Making all in clients\klist
index 4959bdebfa15fbb5284181e81b2c1b3aeaeaa48c..db30b09c319a679ad14d307a3073770c2b3ef96e 100644 (file)
@@ -8,6 +8,7 @@ AC_CHECK_HEADERS(unistd.h pwd.h)
 K5_GEN_MAKEFILE(.)
 K5_GEN_MAKEFILE(klist)
 K5_GEN_MAKEFILE(kinit)
+K5_GEN_MAKEFILE(kvno)
 K5_GEN_MAKEFILE(kdestroy)
 K5_GEN_MAKEFILE(kpasswd)
 K5_GEN_MAKEFILE(ksu)
index 65bcc031eba8b6b6b694d58cb7dd806fc840551c..5bdf4525768b95054402a2c862e36a17665e9511 100644 (file)
@@ -1,3 +1,7 @@
+1998-10-26  Marc Horowitz  <marc@mit.edu>
+
+       * kinit.c: convert to new init_creds api
+
 1998-05-06  Theodore Ts'o  <tytso@rsts-11.mit.edu>
 
        * kinit.c (main): POSIX states that getopt returns -1 when it
index 6f7b840c98981c3e5cd572c288f5f875e015975e..f02db2e186237283bf8da1eba5d35cec2a0fbbff 100644 (file)
  * Initialize a credentials cache.
  */
 
-#include "k5-int.h"
+#include <krb5.h>
+#include <string.h>
+#include <stdio.h>
+
+#ifdef GETOPT_LONG
+#include "getopt.h"
+#else
+#include <unistd.h>
+#endif
 #include "com_err.h"
-#include "adm_proto.h"
 
-#include <stdio.h>
 #ifdef HAVE_PWD_H
 #include <pwd.h>
-#endif
 
-#define KRB5_DEFAULT_OPTIONS 0
-#define KRB5_DEFAULT_LIFE 60*60*10 /* 10 hours */
-
-extern int optind;
-extern char *optarg;
+void get_name_from_passwd_file(program_name, kcontext, me)
+    char * program_name;
+    krb5_context kcontext;
+    krb5_principal * me;
+{
+    struct passwd *pw;
+    krb5_error_code code;
+    if (pw = getpwuid((int) getuid())) {
+       if ((code = krb5_parse_name(kcontext, pw->pw_name, me))) {
+           com_err (program_name, code, "when parsing name %s", pw->pw_name);
+           exit(1);
+       }
+    } else {
+       fprintf(stderr, "Unable to identify user from password file\n");
+       exit(1);
+    }
+}
+#else /* HAVE_PWD_H */
+void get_name_from_passwd_file(kcontext, me)
+    krb5_context kcontext;
+    krb5_principal * me;
+{
+    fprintf(stderr, "Unable to identify user\n");
+    exit(1);
+}
+#endif /* HAVE_PWD_H */
 
-krb5_data tgtname = {
-    0,
-    KRB5_TGS_NAME_SIZE,
-    KRB5_TGS_NAME
+#ifdef GETOPT_LONG
+/* if struct[2] == NULL, then long_getopt acts as if the short flag
+   struct[3] was specified.  If struct[2] != NULL, then struct[3] is
+   stored in *(struct[2]), the array index which was specified is
+   stored in *index, and long_getopt() returns 0. */
+
+struct option long_options[] = {
+    { "noforwardable", 0, NULL, 'f'+0200 },
+    { "noproxiable", 0, NULL, 'p'+0200 },
+    { "addresses", 0, NULL, 'A'+0200},
+    { "forwardable", 0, NULL, 'f' },
+    { "proxiable", 0, NULL, 'p' },
+    { "noaddresses", 0, NULL, 'A'},
+    { "version", 0, NULL, 0x01 },
+    { NULL, 0, NULL, 0 }
 };
-
-/* Internal prototypes */
-static krb5_error_code krb5_validate_tgt
-        KRB5_PROTOTYPE((krb5_context, krb5_ccache,
-                        krb5_principal, krb5_data *));
-static krb5_error_code krb5_renew_tgt
-        KRB5_PROTOTYPE((krb5_context, krb5_ccache,
-                        krb5_principal, krb5_data *));
-static krb5_error_code krb5_tgt_gen
-        KRB5_PROTOTYPE((krb5_context, krb5_ccache,
-                        krb5_principal, krb5_data *, int opt));
-
-/*
- * Try no preauthentication first; then try the encrypted timestamp
- */
-krb5_preauthtype * preauth = NULL;
-krb5_preauthtype preauth_list[2] = { 0, -1 };
+#endif
 
 int
 main(argc, argv)
@@ -68,114 +89,147 @@ main(argc, argv)
     char **argv;
 {
     krb5_context kcontext;
+    krb5_principal me = NULL;
+    krb5_deltat start_time = 0;
+    krb5_address **addresses = NULL;
+    krb5_get_init_creds_opt opts;
+    char *service_name = NULL;
+    krb5_keytab keytab = NULL;
+    char *cache_name;
     krb5_ccache ccache = NULL;
-    char *cache_name = NULL;           /* -f option */
-    char *keytab_name = NULL;          /* -t option */
-    char *service_name = NULL;         /* -s option */
-    krb5_deltat lifetime = KRB5_DEFAULT_LIFE;  /* -l option */
-    krb5_timestamp starttime = 0;
-    krb5_deltat rlife = 0;
-    int options = KRB5_DEFAULT_OPTIONS;
-    int option;
-    int errflg = 0;
-    krb5_error_code code;
-    krb5_principal me;
-    krb5_principal server;
+    enum { INIT_PW, INIT_KT, RENEW, VALIDATE} action;
+    int errflg = 0, idx, i;
     krb5_creds my_creds;
-    krb5_timestamp now;
-    krb5_address *null_addr = (krb5_address *)0;
-    krb5_address **addrs = (krb5_address **)0;
-    int use_keytab = 0;                        /* -k option */
-    krb5_keytab keytab = NULL;
-    struct passwd *pw = 0;
-    int pwsize;
-    char password[255], *client_name, prompt[1024];
+    krb5_error_code code;
 
-    code = krb5_init_context(&kcontext);
-    if (code) {
-           com_err(argv[0], code, "while initializing krb5");
-           exit(1);
-    }
+    /* Ensure we can be driven from a pipe */
+    if(!isatty(fileno(stdin)))
+        setvbuf(stdin, 0, _IONBF, 0);
+    if(!isatty(fileno(stdout)))
+        setvbuf(stdout, 0, _IONBF, 0);
+    if(!isatty(fileno(stderr)))
+        setvbuf(stderr, 0, _IONBF, 0);
 
-    if ((code = krb5_timeofday(kcontext, &now))) {
-       com_err(argv[0], code, "while getting time of day");
+    if (code = krb5_init_context(&kcontext)) {
+       com_err(argv[0], code, "while initializing kerberos library");
        exit(1);
     }
 
+    krb5_get_init_creds_opt_init(&opts);
+
+    action = INIT_PW;
+
     if (strrchr(argv[0], '/'))
        argv[0] = strrchr(argv[0], '/')+1;
 
-    while ((option = getopt(argc, argv, "r:Rfpl:s:c:kt:vS:")) != -1) {
-       switch (option) {
-       case 'r':
-           options |= KDC_OPT_RENEWABLE;
-           code = krb5_string_to_deltat(optarg, &rlife);
-           if (code != 0 || rlife == 0) {
-               fprintf(stderr, "Bad lifetime value %s\n", optarg);
-               errflg++;
+    while (
+#ifdef GETOPT_LONG
+          (i = getopt_long(argc, argv, "r:fpAl:s:c:kt:RS:v",
+                           long_options, &idx)) != -1
+#else
+          (i = getopt(argc, argv, "r:fpAl:s:c:kt:RS:v")) != -1
+#endif
+          ) {
+       switch (i) {
+#ifdef GETOPT_LONG
+       case 1: /* Print the version */
+           printf("%s\n", krb5_version);
+           exit(0);
+#endif
+        case 'l':
+           {
+               krb5_deltat lifetime;
+               code = krb5_string_to_deltat(optarg, &lifetime);
+               if (code != 0 || lifetime == 0) {
+                   fprintf(stderr, "Bad lifetime value %s\n", optarg);
+                   errflg++;
+               }
+               krb5_get_init_creds_opt_set_tkt_life(&opts, lifetime);
            }
            break;
-       case 'R':
-           /* renew the ticket */
-           options |= KDC_OPT_RENEW;
+       case 'r':
+           {
+               krb5_deltat rlife;
+
+               code = krb5_string_to_deltat(optarg, &rlife);
+               if (code != 0 || rlife == 0) {
+                   fprintf(stderr, "Bad lifetime value %s\n", optarg);
+                   errflg++;
+               }
+               krb5_get_init_creds_opt_set_renew_life(&opts, rlife);
+           }
            break;
-       case 'v':
-           /* validate the ticket */
-           options |= KDC_OPT_VALIDATE;
+       case 'f':
+           krb5_get_init_creds_opt_set_forwardable(&opts, 1);
            break;
-        case 'S':
-           service_name = optarg;
+#ifdef GETOPT_LONG
+       case 'f'+0200:
+           krb5_get_init_creds_opt_set_forwardable(&opts, 0);
            break;
+#endif
        case 'p':
-           options |= KDC_OPT_PROXIABLE;
+           krb5_get_init_creds_opt_set_proxiable(&opts, 1);
            break;
-       case 'f':
-           options |= KDC_OPT_FORWARDABLE;
+#ifdef GETOPT_LONG
+       case 'p'+0200:
+           krb5_get_init_creds_opt_set_proxiable(&opts, 0);
            break;
-#ifndef NO_KEYTAB
-       case 'k':
-           use_keytab = 1;
+#endif
+       case 'A':
+           krb5_get_init_creds_opt_set_address_list(&opts, NULL);
            break;
-       case 't':
-           if (keytab == NULL) {
-                keytab_name = optarg;
+#ifdef GETOPT_LONG
+       case 'A'+0200:
+           krb5_os_localaddr(kcontext, &addresses);
+           krb5_get_init_creds_opt_set_address_list(&opts, addresses);
+           break;
+#endif
+               case 's':
+           code = krb5_string_to_deltat(optarg, &start_time);
+           if (code != 0 || start_time == 0) {
+               krb5_timestamp abs_starttime;
+               krb5_timestamp now;
+
+               code = krb5_string_to_timestamp(optarg, &abs_starttime);
+               if (code != 0 || abs_starttime == 0) {
+                   fprintf(stderr, "Bad start time value %s\n", optarg);
+                   errflg++;
+               } else {
+                   if ((code = krb5_timeofday(kcontext, &now))) {
+                       com_err(argv[0], code,
+                               "while getting time of day");
+                       exit(1);
+                   }
 
-                code = krb5_kt_resolve(kcontext, keytab_name, &keytab);
+                   start_time = abs_starttime - now;
+               }
+           }
+           break;
+        case 'S':
+           service_name = optarg;
+           break;
+        case 'k':
+           action = INIT_KT;
+           break;
+        case 't':
+           if (keytab == NULL) {
+                code = krb5_kt_resolve(kcontext, optarg, &keytab);
                 if (code != 0) {
-                     com_err(argv[0], code, "resolving keytab %s",
-                             keytab_name);
-                errflg++;
+                     com_err(argv[0], code, "resolving keytab %s", optarg);
+                     errflg++;
                 }
            } else {
                 fprintf(stderr, "Only one -t option allowed.\n");
                 errflg++;
            }
            break;
-#endif
-       case 'l':
-           code = krb5_string_to_deltat(optarg, &lifetime);
-           if (code != 0 || lifetime == 0) {
-               fprintf(stderr, "Bad lifetime value %s\n", optarg);
-               errflg++;
-           }
+       case 'R':
+           action = RENEW;
            break;
-       case 's':
-           code = krb5_string_to_timestamp(optarg, &starttime);
-           if (code != 0 || starttime == 0) {
-             krb5_deltat ktmp;
-             code = krb5_string_to_deltat(optarg, &ktmp);
-             if (code == 0 && ktmp != 0) {
-               starttime = now + ktmp;
-               options |= KDC_OPT_POSTDATED;
-             } else {
-               fprintf(stderr, "Bad postdate start time value %s\n", optarg);
-               errflg++;
-             }
-           } else {
-             options |= KDC_OPT_POSTDATED;
-           }
+       case 'v':
+           action = VALIDATE;
            break;
-       case 'c':
+               case 'c':
            if (ccache == NULL) {
                cache_name = optarg;
                
@@ -190,7 +244,6 @@ main(argc, argv)
                errflg++;
            }
            break;
-       case '?':
        default:
            errflg++;
            break;
@@ -204,7 +257,11 @@ main(argc, argv)
     }
 
     if (errflg) {
-       fprintf(stderr, "Usage: %s [-r time] [-R] [-s time] [-v] [-puf] [-l lifetime] [-c cachename] [-k] [-t keytab] [-S target_service] [principal]\n", argv[0]);
+#ifdef GETOPT_LONG
+       fprintf(stderr, "Usage: %s [--version] [-l lifetime] [-r renewable_life] [-f | --forwardable | --noforwardable] [-p | --proxiable | --noproxiable] [-A | --noaddresses | --addresses] [-s start_time] [-S target_service] [-k [-t keytab_file]] [-R] [-v] [-c cachename] [principal]\n", argv[0]);
+#else
+       fprintf(stderr, "Usage: %s [-l lifetime] [-r renewable_life] [-f] [-p] [-A] [-s start_time] [-S target_service] [-k [-t keytab_file]] [-R] [-v] [-c cachename] [principal]\n", argv[0]);
+#endif
        exit(2);
     }
 
@@ -215,147 +272,51 @@ main(argc, argv)
         }
     }
 
-    if (optind != argc-1) {       /* No principal name specified */
-#ifndef NO_KEYTAB
-        if (use_keytab) {
-             /* Use the default host/service name */
-             code = krb5_sname_to_principal(kcontext, NULL, NULL,
-                                            KRB5_NT_SRV_HST, &me);
-             if (code) {
-                  com_err(argv[0], code,
-                          "when creating default server principal name");
-                  exit(1);
-             }
-        } else
-#endif
-        {
-             /* Get default principal from cache if one exists */
-             code = krb5_cc_get_principal(kcontext, ccache, &me);
-             if (code) {
-#ifdef HAVE_PWD_H
-                  /* Else search passwd file for client */
-                  pw = getpwuid((int) getuid());
-                  if (pw) {
-                       if ((code = krb5_parse_name(kcontext,pw->pw_name,
-                                                   &me))) {
-                            com_err (argv[0], code, "when parsing name %s",
-                                     pw->pw_name);
-                            exit(1);
-                       }
-                  } else {
-                       fprintf(stderr, 
-                       "Unable to identify user from password file\n");
-                       exit(1);
-                  }
-#else /* HAVE_PWD_H */
-                  fprintf(stderr, "Unable to identify user\n");
-                  exit(1);
-#endif /* HAVE_PWD_H */
-             }
-        }
-    } /* Use specified name */  
-    else if ((code = krb5_parse_name (kcontext, argv[optind], &me))) {
-        com_err (argv[0], code, "when parsing name %s",argv[optind]);
-        exit(1);
-    }
-    
-    if ((code = krb5_unparse_name(kcontext, me, &client_name))) {
-       com_err (argv[0], code, "when unparsing name");
-       exit(1);
-    }
-
-    memset((char *)&my_creds, 0, sizeof(my_creds));
-    
-    my_creds.client = me;
-
-    if (service_name == NULL) {
-        if((code = krb5_build_principal_ext(kcontext, &server,
-                                            krb5_princ_realm(kcontext, me)->length,
-                                            krb5_princ_realm(kcontext, me)->data,
-                                            tgtname.length, tgtname.data,
-                                            krb5_princ_realm(kcontext, me)->length,
-                                            krb5_princ_realm(kcontext, me)->data,
-                                            0))) {
-             com_err(argv[0], code, "while building server name");
-             exit(1);
-        }
-    } else {
-        if ((code = krb5_parse_name(kcontext, service_name, &server))) {
-             com_err(argv[0], code, "while parsing service name %s",
-                     service_name);
-             exit(1);
-        }
-    }
-       
-    my_creds.server = server;
-
-    if (options & KDC_OPT_POSTDATED) {
-      my_creds.times.starttime = starttime;
-      my_creds.times.endtime = starttime + lifetime;
+    if (optind == argc-1) {
+       /* Use specified name */
+       if ((code = krb5_parse_name (kcontext, argv[optind], &me))) {
+           com_err (argv[0], code, "when parsing name %s",argv[optind]);
+           exit(1);
+       }
     } else {
-      my_creds.times.starttime = 0;    /* start timer when request
-                                          gets to KDC */
-      my_creds.times.endtime = now + lifetime;
-    }
-    if (options & KDC_OPT_RENEWABLE) {
-       my_creds.times.renew_till = now + rlife;
-    } else
-       my_creds.times.renew_till = 0;
-
-    if (options & KDC_OPT_VALIDATE) {
-        /* don't use get_in_tkt, just use mk_req... */
-        krb5_data outbuf;
-
-        code = krb5_validate_tgt(kcontext, ccache, server, &outbuf);
-       if (code) {
-         com_err (argv[0], code, "validating tgt");
-         exit(1);
+       /* No principal name specified */
+       if (action == INIT_KT) {
+           /* Use the default host/service name */
+           if (code = krb5_sname_to_principal(kcontext, NULL, NULL,
+                                              KRB5_NT_SRV_HST, &me)) {
+               com_err(argv[0], code,
+                       "when creating default server principal name");
+               exit(1);
+           }
+       } else {
+           /* Get default principal from cache if one exists */
+           if (code = krb5_cc_get_principal(kcontext, ccache, &me))
+               get_name_from_passwd_file(argv[0], kcontext, &me);
        }
-       /* should be done... */
-       exit(0);
     }
-
-    if (options & KDC_OPT_RENEW) {
-        /* don't use get_in_tkt, just use mk_req... */
-        krb5_data outbuf;
-
-        code = krb5_renew_tgt(kcontext, ccache, server, &outbuf);
-       if (code) {
-         com_err (argv[0], code, "renewing tgt");
-         exit(1);
-       }
-       /* should be done... */
-       exit(0);
+    
+    switch (action) {
+    case INIT_PW:
+       code = krb5_get_init_creds_password(kcontext, &my_creds, me, NULL,
+                                           krb5_prompter_posix, NULL,
+                                           start_time, service_name,
+                                           &opts);
+       break;
+    case INIT_KT:
+       code = krb5_get_init_creds_keytab(kcontext, &my_creds, me, keytab,
+                                           start_time, service_name,
+                                           &opts);
+       break;
+    case VALIDATE:
+       code = krb5_get_validated_creds(kcontext, &my_creds, me, ccache,
+                                       service_name);
+       break;
+    case RENEW:
+       code = krb5_get_renewed_creds(kcontext, &my_creds, me, ccache,
+                                     service_name);
+       break;
     }
-#ifndef NO_KEYTAB
-    if (!use_keytab)
-#endif
-    {
-        (void) sprintf(prompt, "Password for %.*s: ",
-                       sizeof(prompt)-32, (char *) client_name);
-
-        pwsize = sizeof(password);
 
-        code = krb5_read_password(kcontext, prompt, 0, password, &pwsize);
-        if (code || pwsize == 0) {
-             fprintf(stderr, "Error while reading password for '%s'\n",
-                     client_name);
-             memset(password, 0, sizeof(password));
-             exit(1);
-        }
-
-        code = krb5_get_in_tkt_with_password(kcontext, options, addrs,
-                                             NULL, preauth, password, 0,
-                                             &my_creds, 0);
-        memset(password, 0, sizeof(password));
-#ifndef NO_KEYTAB
-    } else {
-        code = krb5_get_in_tkt_with_keytab(kcontext, options, addrs,
-                                           NULL, preauth, keytab, 0,
-                                           &my_creds, 0);
-#endif
-    }
-    
     if (code) {
        if (code == KRB5KRB_AP_ERR_BAD_INTEGRITY)
            fprintf (stderr, "%s: Password incorrect\n", argv[0]);
@@ -364,86 +325,27 @@ main(argc, argv)
        exit(1);
     }
 
-    code = krb5_cc_initialize (kcontext, ccache, me);
-    if (code != 0) {
+    if (code = krb5_cc_initialize(kcontext, ccache, me)) {
        com_err (argv[0], code, "when initializing cache %s",
                 cache_name?cache_name:"");
        exit(1);
     }
 
-    code = krb5_cc_store_cred(kcontext, ccache, &my_creds);
-    if (code) {
+    if (code = krb5_cc_store_cred(kcontext, ccache, &my_creds)) {
        com_err (argv[0], code, "while storing credentials");
        exit(1);
     }
 
-    /* my_creds is pointing at server */
-    krb5_free_principal(kcontext, server);
+    if (me)
+       krb5_free_principal(kcontext, me);
+    if (keytab)
+       krb5_kt_close(kcontext, keytab);
+    if (ccache)
+       krb5_cc_close(kcontext, ccache);
+    if (addresses)
+       krb5_free_addresses(kcontext, addresses);
 
     krb5_free_context(kcontext);
-
+    
     exit(0);
 }
-
-#define VALIDATE 0
-#define RENEW 1
-
-/* stripped down version of krb5_mk_req */
-static krb5_error_code krb5_validate_tgt(context, ccache, server, outbuf)
-     krb5_context context;
-     krb5_ccache ccache;
-     krb5_principal      server; /* tgtname */
-     krb5_data *outbuf;
-{
-       return krb5_tgt_gen(context, ccache, server, outbuf, VALIDATE);
-}
-
-/* stripped down version of krb5_mk_req */
-static krb5_error_code krb5_renew_tgt(context, ccache, server, outbuf)
-     krb5_context context;
-     krb5_ccache ccache;
-     krb5_principal      server; /* tgtname */
-     krb5_data *outbuf;
-{
-       return krb5_tgt_gen(context, ccache, server, outbuf, RENEW);
-}
-
-
-/* stripped down version of krb5_mk_req */
-static krb5_error_code krb5_tgt_gen(context, ccache, server, outbuf, opt)
-     krb5_context context;
-     krb5_ccache ccache;
-     krb5_principal      server; /* tgtname */
-     krb5_data *outbuf;
-     int opt;
-{
-    krb5_error_code      retval;
-    krb5_creds                 * credsp;
-    krb5_creds                   creds;
-
-    /* obtain ticket & session key */
-    memset((char *)&creds, 0, sizeof(creds));
-    if ((retval = krb5_copy_principal(context, server, &creds.server)))
-       goto cleanup;
-
-    if ((retval = krb5_cc_get_principal(context, ccache, &creds.client)))
-       goto cleanup_creds;
-
-    if(opt == VALIDATE) {
-           if ((retval = krb5_get_credentials_validate(context, 0,
-                                                       ccache, &creds, &credsp)))
-                   goto cleanup_creds;
-    } else {
-           if ((retval = krb5_get_credentials_renew(context, 0,
-                                                       ccache, &creds, &credsp)))
-                   goto cleanup_creds;
-    }
-
-    /* we don't actually need to do the mk_req, just get the creds. */
-cleanup_creds:
-    krb5_free_cred_contents(context, &creds);
-
-cleanup:
-
-    return retval;
-}
index 3150210e4cb385e0367bf584061c064463ebe44f..20feffb3554264d5a308f01d5b701cd8823a3ac1 100644 (file)
@@ -1,3 +1,9 @@
+1998-10-26  Marc Horowitz  <marc@mit.edu>
+
+       * klist.c: add -a flag to print the ticket address, and -n flag to
+       do so without attempting resolution.  Make klist use the new api
+       for stringifying enctypes.
+
 Tue Aug 11 23:38:53 1998  Matthew D Hancher  <mdh@mit.edu>
 
        * klist.c (do_ccache): Properly check the return value of
index 6d05f822d644235fc05af5de0c5d909caa095552..deb5f44bc27dc0f0b16e21eb8579ded9f759944a 100644 (file)
 #include <string.h>
 #include <stdio.h>
 #include <time.h>
+#include <sys/socket.h>
+#include <netdb.h>
 
 extern int optind;
 extern char *optarg;
 int show_flags = 0, show_time = 0, status_only = 0, show_keys = 0;
-int show_etype = 0;
+int show_etype = 0, show_addresses = 0, no_resolve = 0;
 char *defname;
 char *progname;
 krb5_int32 now;
@@ -50,6 +52,7 @@ void show_credential KRB5_PROTOTYPE((char *,
 void do_ccache KRB5_PROTOTYPE((char *));
 void do_keytab KRB5_PROTOTYPE((char *));
 void printtime KRB5_PROTOTYPE((time_t));
+void one_addr KRB5_PROTOTYPE((krb5_address *));
 void fillit KRB5_PROTOTYPE((FILE *, int, int));
        
 #define DEFAULT 0
@@ -58,7 +61,7 @@ void fillit KRB5_PROTOTYPE((FILE *, int, int));
 
 void usage()
 {
-     fprintf(stderr, "Usage: %s [[-c] [-f] [-e] [-s]] [-k [-t] [-K]] [name]\n",
+     fprintf(stderr, "Usage: %s [[-c] [-f] [-e] [-s] [-a] [-n]] [-k [-t] [-K]] [name]\n",
             progname); 
      fprintf(stderr, "\t-c specifies credentials cache, -k specifies keytab");
      fprintf(stderr, ", -c is default\n");
@@ -66,6 +69,8 @@ void usage()
      fprintf(stderr, "\t\t-f shows credentials flags\n");
      fprintf(stderr, "\t\t-e shows the encryption type\n");
      fprintf(stderr, "\t\t-s sets exit status based on valid tgt existence\n");
+     fprintf(stderr, "\t\t-a displays the address list\n");
+     fprintf(stderr, "\t\t\t-n do not reverse-resolve\n");
      fprintf(stderr, "\toptions for keytabs:\n");
      fprintf(stderr, "\t\t-t shows keytab entry timestamps\n");
      fprintf(stderr, "\t\t-K shows keytab entry DES keys\n");
@@ -114,6 +119,12 @@ main(argc, argv)
        case 's':
            status_only = 1;
            break;
+       case 'n':
+           no_resolve = 1;
+           break;
+       case 'a':
+           show_addresses = 1;
+           break;
        case 'c':
            if (mode != DEFAULT) usage();
            mode = CCACHE;
@@ -220,8 +231,8 @@ void do_keytab(name)
               printf(" ");
          }
          printf("%s", pname);
-if (show_etype)
-    printf(" (%s) " , etype_string(entry.key.enctype));
+         if (show_etype)
+             printf(" (%s) " , etype_string(entry.key.enctype));
          if (show_keys) {
               printf(" (0x");
               {
@@ -352,26 +363,15 @@ char *
 etype_string(enctype)
     krb5_enctype enctype;
 {
-    static char buf[12];
+    static char buf[100];
+    krb5_error_code retval;
     
-    switch (enctype) {
-    case ENCTYPE_DES_CBC_CRC:
-       return "DES-CBC-CRC";
-       break;
-    case ENCTYPE_DES_CBC_MD4:
-       return "DES-CBC-MD4";
-       break;
-    case ENCTYPE_DES_CBC_MD5:
-       return "DES-CBC-MD5";
-       break;
-    case ENCTYPE_DES3_CBC_SHA:
-       return "DES3-CBC-SHA";
-       break;
-    default:
+    if ((retval = krb5_enctype_to_string(enctype, buf, sizeof(buf)))) {
+       /* XXX if there's an error != EINVAL, I should probably report it */
        sprintf(buf, "etype %d", enctype);
-       return buf;
-       break;
     }
+
+    return buf;
 }
 
 char *
@@ -498,8 +498,9 @@ show_credential(progname, kcontext, cred)
            fputs("\t",stdout);
        else
            fputs(", ",stdout);
-       printf("Etype (skey, tkt): %s, %s ",
-              etype_string(cred->keyblock.enctype), 
+       printf("Etype (skey, tkt): %s, ",
+              etype_string(cred->keyblock.enctype));
+       printf("%s ",
               etype_string(tkt->enc_part.enctype));
        krb5_free_ticket(kcontext, tkt);
        extra_field++;
@@ -508,10 +509,52 @@ show_credential(progname, kcontext, cred)
     /* if any additional info was printed, extra_field is non-zero */
     if (extra_field)
        putchar('\n');
+
+
+    if (show_addresses) {
+       if (!cred->addresses || !cred->addresses[0]) {
+           printf("\tAddresses: (none)\n");
+       } else {
+           int i;
+
+           printf("\tAddresses: ");
+           one_addr(cred->addresses[0]);
+
+           for (i=1; cred->addresses[i]; i++) {
+               printf(", ");
+               one_addr(cred->addresses[1]);
+           }
+
+           printf("\n");
+       }
+    }
+
     free(name);
     free(sname);
 }
 
+void one_addr(a)
+    krb5_address *a;
+{
+    struct hostent *h;
+
+    if ((a->addrtype == ADDRTYPE_INET) &&
+       (a->length == 4)) {
+       if (!no_resolve) {
+           h = gethostbyaddr(a->contents, 4, AF_INET);
+           if (h) {
+               printf("%s", h->h_name);
+           }
+       }
+       if (no_resolve || !h) {
+           printf("%d.%d.%d.%d", a->contents[0], a->contents[1],
+                  a->contents[2], a->contents[3]);
+       }
+    } else {
+       printf("unknown addr type %d", a->addrtype);
+    }
+}
+
 void
 fillit(f, num, c)
     FILE       *f;
index b3c8848e008beb8fb68f3186a435a29ce867786d..d66def009e24503a39c2593e65e305e55536a2ba 100644 (file)
@@ -1,3 +1,21 @@
+1998-10-26  Marc Horowitz  <marc@mit.edu>
+
+       * krb5.hin: add new interfaces for new crypto API and key
+       derivation/key usage.  Add new (krb5_get_permitted_enctypes,
+       krb5_is_permitted_enctype) api for querying permitted etypes from
+       krb5.conf, and new auth_context flag
+       (KRB5_AUTH_CONTEXT_PERMIT_ALL) to override this.  Fix bug in
+       krb5_kt_get_type.
+       
+       * k5-int.h: make changes related to new crypto API and key
+       derivation/key usage
+
+Tue Sep  1 19:32:33 1998  Tom Yu  <tlyu@mit.edu>
+
+       * krb5.hin: Add ENCTYPE_LOCAL_DES3_HMAC_SHA1, in order to deal
+       with marc's current des3 cryptosystem until we figure out what
+       we're actually going to use for a standardized cryptosystem.
+
 Wed Jul  1 19:14:25 1998  Theodore Y. Ts'o  <tytso@mit.edu>
 
        * win-mac.h: Make size_t to be an unsigned long instead of
index db82e0266eb2705fd671f004877bad0a77074947..fa8824c49e60698bfa98679987ba07621f38e9a2 100644 (file)
  * documentation shall at all times remain with M.I.T., and USER agrees to 
  * preserve same.  
  */
+
+/*
+ * Copyright (C) 1998 by the FundsXpress, INC.
+ * 
+ * All rights reserved.
+ * 
+ * Export of this software from the United States of America may require
+ * a specific license from the United States Government.  It is the
+ * responsibility of any person or organization contemplating export to
+ * obtain such a license before exporting.
+ * 
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of FundsXpress. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  FundsXpress makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
 /*
  * This prototype for k5-int.h (Krb5 internals include file)
  * includes the user-visible definitions from krb5.h and then
@@ -152,6 +179,8 @@ typedef unsigned char       u_char;
 #define labs(x) abs(x)
 #endif
 
+/* #define KRB5_OLD_CRYPTO is done in krb5.h */
+
 #endif /* KRB5_CONFIG__ */
 
 /*
@@ -500,11 +529,125 @@ void krb5_os_free_context
 krb5_error_code krb5_find_config_files
         KRB5_PROTOTYPE(());
 
+#endif /* KRB5_LIBOS_PROTO__ */
+
+/* new encryption provider api */
+
+struct krb5_enc_provider {
+    void (*block_size) KRB5_NPROTOTYPE
+    ((size_t *output));
+
+    /* keybytes is the input size to make_key; 
+       keylength is the output size */
+    void (*keysize) KRB5_NPROTOTYPE
+    ((size_t *keybytes, size_t *keylength));
+
+    /* ivec == 0 is an all-zeros ivec */
+    krb5_error_code (*encrypt) KRB5_NPROTOTYPE
+    ((krb5_const krb5_keyblock *key, krb5_const krb5_data *ivec,
+      krb5_const krb5_data *input, krb5_data *output));
+
+    krb5_error_code (*decrypt) KRB5_NPROTOTYPE
+    ((krb5_const krb5_keyblock *key, krb5_const krb5_data *ivec,
+      krb5_const krb5_data *input, krb5_data *output));
+
+    krb5_error_code (*make_key) KRB5_NPROTOTYPE
+    ((krb5_const krb5_data *randombits, krb5_keyblock *key));
+};
+
+struct krb5_hash_provider {
+    void (*hash_size) KRB5_NPROTOTYPE
+    ((size_t *output));
+
+    void (*block_size) KRB5_NPROTOTYPE
+    ((size_t *output));
+
+    /* this takes multiple inputs to avoid lots of copying. */
+    krb5_error_code (*hash) KRB5_NPROTOTYPE
+    ((unsigned int icount, krb5_const krb5_data *input, krb5_data *output));
+};
+
+struct krb5_keyhash_provider {
+    void (*hash_size) KRB5_NPROTOTYPE
+    ((size_t *output));
+
+    krb5_error_code (*hash) KRB5_NPROTOTYPE
+    ((krb5_const krb5_keyblock *key, krb5_const krb5_data *ivec,
+      krb5_const krb5_data *input, krb5_data *output));
+
+    krb5_error_code (*verify) KRB5_NPROTOTYPE
+    ((krb5_const krb5_keyblock *key, krb5_const krb5_data *ivec,
+      krb5_const krb5_data *input, krb5_const krb5_data *hash,
+      krb5_boolean *valid));
+};
+
+typedef void (*krb5_encrypt_length_func) KRB5_NPROTOTYPE
+((krb5_const struct krb5_enc_provider *enc,
+  krb5_const struct krb5_hash_provider *hash,
+  size_t inputlen, size_t *length));
+
+typedef krb5_error_code (*krb5_crypt_func) KRB5_NPROTOTYPE
+((krb5_const struct krb5_enc_provider *enc,
+  krb5_const struct krb5_hash_provider *hash,
+  krb5_const krb5_keyblock *key, krb5_keyusage usage,
+  krb5_const krb5_data *ivec, 
+  krb5_const krb5_data *input, krb5_data *output));
+
+typedef krb5_error_code (*krb5_str2key_func) KRB5_NPROTOTYPE
+((krb5_const struct krb5_enc_provider *enc, krb5_const krb5_data *string,
+  krb5_const krb5_data *salt, krb5_keyblock *key));
+
+struct krb5_keytypes {
+    krb5_enctype etype;
+    char *in_string;
+    char *out_string;
+    struct krb5_enc_provider *enc;
+    struct krb5_hash_provider *hash;
+    krb5_encrypt_length_func encrypt_len;
+    krb5_crypt_func encrypt;
+    krb5_crypt_func decrypt;
+    krb5_str2key_func str2key;
+};
+
+struct krb5_cksumtypes {
+    krb5_cksumtype ctype;
+    unsigned int flags;
+    char *in_string;
+    char *out_string;
+    /* if the hash is keyed, this is the etype it is keyed with.
+       Actually, it can be keyed by any etype which has the same
+       enc_provider as the specified etype.  DERIVE checksums can
+       be keyed with any valid etype. */
+    krb5_enctype keyed_etype;
+    /* I can't statically initialize a union, so I'm just going to use
+       two pointers here.  The keyhash is used if non-NULL.  If NULL,
+       then HMAC/hash with derived keys is used if the relevant flag
+       is set.  Otherwise, a non-keyed hash is computed.  This is all
+       kind of messy, but so is the krb5 api. */
+    struct krb5_keyhash_provider *keyhash;
+    struct krb5_hash_provider *hash;
+};
+
+#define KRB5_CKSUMFLAG_DERIVE          0x0001
+#define KRB5_CKSUMFLAG_NOT_COLL_PROOF  0x0002
 
 /*
- * in here to deal with stuff from lib/crypto/os
+ * in here to deal with stuff from lib/crypto
  */
 
+void krb5_nfold
+KRB5_PROTOTYPE((int inbits, krb5_const unsigned char *in,
+               int outbits, unsigned char *out));
+
+krb5_error_code krb5_hmac
+KRB5_PROTOTYPE((krb5_const struct krb5_hash_provider *hash,
+               krb5_const krb5_keyblock *key, unsigned int icount,
+               krb5_const krb5_data *input, krb5_data *output));
+
+
+#ifdef KRB5_OLD_CRYPTO
+/* old provider api */
+
 typedef struct _krb5_cryptosystem_entry {
     krb5_magic magic;
     krb5_error_code (*encrypt_func) KRB5_NPROTOTYPE(( krb5_const_pointer /* in */,
@@ -573,23 +716,6 @@ typedef struct _krb5_checksum_entry {
     unsigned int uses_key:1;
 } krb5_checksum_entry;
 
-
-/* This array is indexed by encryption type */
-extern krb5_cs_table_entry * NEAR krb5_csarray[];
-extern int krb5_max_cryptosystem;
-
-/* This array is indexed by key type */
-extern krb5_cs_table_entry * NEAR krb5_enctype_array[];
-extern krb5_enctype krb5_max_enctype;
-
-/* This array is indexed by checksum type */
-extern krb5_checksum_entry * NEAR krb5_cksumarray[];
-extern krb5_cksumtype krb5_max_cksum;
-
-KRB5_DLLIMP krb5_error_code KRB5_CALLCONV krb5_random_confounder
-       KRB5_PROTOTYPE((size_t,
-               krb5_pointer ));
-
 krb5_error_code krb5_crypto_os_localaddr
        KRB5_PROTOTYPE((krb5_address ***));
 
@@ -599,7 +725,15 @@ krb5_error_code krb5_crypto_us_timeofday
 
 time_t gmt_mktime KRB5_PROTOTYPE((struct tm *));
 
-#endif /* KRB5_LIBOS_PROTO__ */
+#endif /* KRB5_OLD_CRYPTO */
+
+/* this helper fct is in libkrb5, but it makes sense declared here. */
+
+krb5_error_code krb5_encrypt_helper
+KRB5_PROTOTYPE((krb5_context context, krb5_const krb5_keyblock *key,
+               krb5_keyusage usage, krb5_const krb5_data *plain,
+               krb5_enc_data *cipher));
+
 /*
  * End "los-proto.h"
  */
@@ -1201,6 +1335,7 @@ krb5_error_code krb5_encode_kdc_rep
        KRB5_PROTOTYPE((krb5_context,
                krb5_const krb5_msgtype,
                krb5_const krb5_enc_kdc_rep_part *,
+               int using_subkey,
                krb5_const krb5_keyblock *,
                krb5_kdc_rep *,
                krb5_data ** ));
index 85f624b06619f2744b02c8269dfa6be20583f47c..0ecf2b09e7f6e8a0d501af2ce7bf3dfe9d50305c 100644 (file)
@@ -1,3 +1,9 @@
+Thu Sep 17 18:23:26 1998  Tom Yu  <tlyu@mit.edu>
+
+       * krb_db.h: ifdef out the declarations for kerb_get_* and
+       kerb_db_* to avoid problems with krb4 compat code in the kdc,
+       which declares some of these static.
+
 Wed Feb 18 15:51:41 1998  Tom Yu  <tlyu@mit.edu>
 
        * Makefile.in: Remove trailing slash from thisconfigdir.  Fix up
index 4925137c4389eef0b15110714f8c90245f922c2f..dc2265d96066f0eb2e3ea4b4758970b13a860204 100644 (file)
@@ -104,11 +104,13 @@ typedef struct {
 }
         Dba;
 
+#if 0
 extern int kerb_get_principal();
 extern int kerb_put_principal();
 extern int kerb_db_get_stat();
 extern int kerb_db_put_stat();
 extern int kerb_get_dba();
 extern int kerb_db_get_dba();
+#endif
 
 #endif /* KRB_DB_DEFS */
index 9949524045a35387492042ca83ddc9310fb92123..8b1d42f0d0bffe2f20c68def0aa371d8d8be7e7a 100644 (file)
  * General definitions for Kerberos version 5.
  */
 
+/*
+ * Copyright (C) 1998 by the FundsXpress, INC.
+ * 
+ * All rights reserved.
+ * 
+ * Export of this software from the United States of America may require
+ * a specific license from the United States Government.  It is the
+ * responsibility of any person or organization contemplating export to
+ * obtain such a license before exporting.
+ * 
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of FundsXpress. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  FundsXpress makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
 #ifndef KRB5_GENERAL__
 #define KRB5_GENERAL__
 
@@ -54,6 +80,7 @@
 #define THREEPARAMOPEN(x,y,z) open(x,y,z)
 #endif
 
+#define KRB5_OLD_CRYPTO
 
 #ifdef HAVE_SYS_TYPES_H
 #include <sys/types.h>
@@ -131,10 +158,11 @@ typedef   unsigned int krb5_boolean;
 typedef        unsigned int krb5_msgtype;      
 typedef        unsigned int krb5_kvno; 
 
-typedef        unsigned int krb5_addrtype;
-typedef unsigned int krb5_enctype;
-typedef unsigned int krb5_cksumtype;
-typedef unsigned int krb5_authdatatype;
+typedef        krb5_int32 krb5_addrtype;
+typedef krb5_int32 krb5_enctype;
+typedef krb5_int32 krb5_cksumtype;
+typedef krb5_int32 krb5_authdatatype;
+typedef krb5_int32 krb5_keyusage;
 
 typedef krb5_int32     krb5_preauthtype; /* This may change, later on */
 typedef        krb5_int32      krb5_flags;
@@ -286,6 +314,17 @@ typedef struct _krb5_keyblock {
     krb5_octet FAR *contents;
 } krb5_keyblock;
 
+#ifdef KRB5_OLD_CRYPTO
+typedef struct _krb5_encrypt_block {
+    krb5_magic magic;
+    krb5_enctype crypto_entry;         /* to call krb5_encrypt_size, you need
+                                          this.  it was a pointer, but it
+                                          doesn't have to be.  gross. */
+    krb5_keyblock FAR *key;
+    krb5_int32 priv_size;              /* Size of private data */
+} krb5_encrypt_block;
+#endif
+
 typedef struct _krb5_checksum {
     krb5_magic magic;
     krb5_cksumtype checksum_type;      /* checksum type */
@@ -293,15 +332,6 @@ typedef struct _krb5_checksum {
     krb5_octet FAR *contents;
 } krb5_checksum;
 
-typedef struct _krb5_encrypt_block {
-    krb5_magic magic;
-    struct _krb5_cryptosystem_entry FAR * crypto_entry;
-    krb5_keyblock FAR *key;
-    krb5_pointer priv;                 /* for private use, e.g. DES
-                                          key schedules */
-    krb5_int32 priv_size;              /* Size of private data */
-} krb5_encrypt_block;
-
 typedef struct _krb5_enc_data {
     krb5_magic magic;
     krb5_enctype enctype;
@@ -315,9 +345,15 @@ typedef struct _krb5_enc_data {
 #define        ENCTYPE_DES_CBC_MD4     0x0002  /* DES cbc mode with RSA-MD4 */
 #define        ENCTYPE_DES_CBC_MD5     0x0003  /* DES cbc mode with RSA-MD5 */
 #define        ENCTYPE_DES_CBC_RAW     0x0004  /* DES cbc mode raw */
+/* XXX deprecated? */
 #define        ENCTYPE_DES3_CBC_SHA    0x0005  /* DES-3 cbc mode with NIST-SHA */
 #define        ENCTYPE_DES3_CBC_RAW    0x0006  /* DES-3 cbc mode raw */
+#define ENCTYPE_DES3_HMAC_SHA1 0x0007
+#define ENCTYPE_DES_HMAC_SHA1  0x0008
 #define ENCTYPE_UNKNOWN                0x01ff
+/* local crud */
+/* marc's DES-3 with 32-bit length */
+#define ENCTYPE_LOCAL_DES3_HMAC_SHA1 0x7007
 
 #define        CKSUMTYPE_CRC32         0x0001
 #define        CKSUMTYPE_RSA_MD4       0x0002
@@ -328,7 +364,7 @@ typedef struct _krb5_enc_data {
 #define        CKSUMTYPE_RSA_MD5       0x0007
 #define        CKSUMTYPE_RSA_MD5_DES   0x0008
 #define CKSUMTYPE_NIST_SHA     0x0009
-#define CKSUMTYPE_HMAC_SHA     0x000a
+#define CKSUMTYPE_HMAC_SHA1    0x000a
 
 #ifndef krb5_roundup
 /* round x up to nearest multiple of y */
@@ -349,8 +385,118 @@ typedef struct _krb5_enc_data {
 extern "C" {
 #endif
 
+KRB5_DLLIMP krb5_error_code KRB5_CALLCONV
+    krb5_c_encrypt
+    KRB5_PROTOTYPE((krb5_context context, krb5_const krb5_keyblock *key,
+                   krb5_keyusage usage, krb5_const krb5_data *ivec,
+                   krb5_const krb5_data *input, krb5_enc_data *output));
+
+KRB5_DLLIMP krb5_error_code KRB5_CALLCONV
+    krb5_c_decrypt
+    KRB5_PROTOTYPE((krb5_context context, krb5_const krb5_keyblock *key,
+                   krb5_keyusage usage, krb5_const krb5_data *ivec,
+                   krb5_const krb5_enc_data *input, krb5_data *output));
+
+KRB5_DLLIMP krb5_error_code KRB5_CALLCONV
+    krb5_c_encrypt_length
+    KRB5_PROTOTYPE((krb5_context context, krb5_enctype enctype,
+                   size_t inputlen, size_t *length));
+
+KRB5_DLLIMP krb5_error_code KRB5_CALLCONV
+    krb5_c_block_size
+    KRB5_PROTOTYPE((krb5_context context, krb5_enctype enctype,
+                   size_t *blocksize));
+
+KRB5_DLLIMP krb5_error_code KRB5_CALLCONV
+    krb5_c_make_random_key
+    KRB5_PROTOTYPE((krb5_context context, krb5_enctype enctype,
+                   krb5_keyblock *random_key));
+
+KRB5_DLLIMP krb5_error_code KRB5_CALLCONV
+    krb5_c_random_make_octets
+    KRB5_PROTOTYPE((krb5_context context, krb5_data *data));
+
+KRB5_DLLIMP krb5_error_code KRB5_CALLCONV
+    krb5_c_random_seed
+    KRB5_PROTOTYPE((krb5_context context, krb5_data *data));
+
+KRB5_DLLIMP krb5_error_code KRB5_CALLCONV
+    krb5_c_string_to_key
+    KRB5_PROTOTYPE((krb5_context context, krb5_enctype enctype,
+                   krb5_const krb5_data *string, krb5_const krb5_data *salt,
+                   krb5_keyblock *key));
+
+KRB5_DLLIMP krb5_error_code KRB5_CALLCONV
+    krb5_c_enctype_compare
+    KRB5_PROTOTYPE((krb5_context context, krb5_enctype e1, krb5_enctype e2,
+                   krb5_boolean *similar));
+
+KRB5_DLLIMP krb5_error_code KRB5_CALLCONV
+    krb5_c_make_checksum
+    KRB5_PROTOTYPE((krb5_context context, krb5_cksumtype cksumtype,
+                   krb5_const krb5_keyblock *key, krb5_keyusage usage,
+                   krb5_const krb5_data *input, krb5_checksum *cksum));
+    
+KRB5_DLLIMP krb5_error_code KRB5_CALLCONV
+    krb5_c_verify_checksum
+    KRB5_PROTOTYPE((krb5_context context, 
+                   krb5_const krb5_keyblock *key, krb5_keyusage usage,
+                   krb5_const krb5_data *data,
+                   krb5_const krb5_checksum *cksum,
+                   krb5_boolean *valid));
+    
+KRB5_DLLIMP krb5_error_code KRB5_CALLCONV
+    krb5_c_checksum_length
+    KRB5_PROTOTYPE((krb5_context context, krb5_cksumtype cksumtype,
+                   size_t *length));
+
+KRB5_DLLIMP krb5_error_code KRB5_CALLCONV
+    krb5_c_keyed_checksum_types
+    KRB5_PROTOTYPE((krb5_context context, krb5_enctype enctype, 
+                   unsigned int *count, krb5_cksumtype **cksumtypes));
+
+#define KRB5_KEYUSAGE_AS_REQ_PA_ENC_TS         1
+#define KRB5_KEYUSAGE_KDC_REP_TICKET           2
+#define KRB5_KEYUSAGE_AS_REP_ENCPART           3
+#define KRB5_KEYUSAGE_TGS_REQ_AD_SESSKEY       4
+#define KRB5_KEYUSAGE_TGS_REQ_AD_SUBKEY                5
+#define KRB5_KEYUSAGE_TGS_REQ_AUTH_CKSUM       6
+#define KRB5_KEYUSAGE_TGS_REQ_AUTH             7
+#define KRB5_KEYUSAGE_TGS_REP_ENCPART_SESSKEY  8
+#define KRB5_KEYUSAGE_TGS_REP_ENCPART_SUBKEY   9
+#define KRB5_KEYUSAGE_AP_REQ_AUTH_CKSUM                10
+#define KRB5_KEYUSAGE_AP_REQ_AUTH              11
+#define KRB5_KEYUSAGE_AP_REP_ENCPART           12
+#define KRB5_KEYUSAGE_KRB_PRIV_ENCPART         13
+#define KRB5_KEYUSAGE_KRB_CRED_ENCPART         14
+#define KRB5_KEYUSAGE_KRB_SAFE_CKSUM           15
+#define KRB5_KEYUSAGE_APP_DATA_ENCRYPT         16
+#define KRB5_KEYUSAGE_APP_DATA_CKSUM           17
+#define KRB5_KEYUSAGE_KRB_ERROR_CKSUM          18
+#define KRB5_KEYUSAGE_AD_KDCISSUED_CKSUM       19
+#define KRB5_KEYUSAGE_AD_MTE                   20
+#define KRB5_KEYUSAGE_AD_ITE                   21
+
+/* XXX need to register these */
+
+#define KRB5_KEYUSAGE_GSS_TOK_MIC              22
+#define KRB5_KEYUSAGE_GSS_TOK_WRAP_INTEG       23
+#define KRB5_KEYUSAGE_GSS_TOK_WRAP_PRIV                24
+
+
+krb5_boolean KRB5_CALLCONV valid_enctype
+       KRB5_PROTOTYPE((krb5_const krb5_enctype ktype));
+krb5_boolean KRB5_CALLCONV valid_cksumtype
+       KRB5_PROTOTYPE((krb5_const krb5_cksumtype ctype));
+krb5_boolean KRB5_CALLCONV is_coll_proof_cksum
+       KRB5_PROTOTYPE((krb5_const krb5_cksumtype ctype));
+krb5_boolean KRB5_CALLCONV is_keyed_cksum
+       KRB5_PROTOTYPE((krb5_const krb5_cksumtype ctype));
+
+#ifdef KRB5_OLD_CRYPTO
 /*
- * cryptosystem routine prototypes
+ * old cryptosystem routine prototypes.  These are now layered
+ * on top of the functions above.
  */
 KRB5_DLLIMP krb5_error_code KRB5_CALLCONV krb5_encrypt
        KRB5_PROTOTYPE((krb5_context context,
@@ -402,7 +548,7 @@ KRB5_DLLIMP krb5_error_code KRB5_CALLCONV krb5_use_enctype
                krb5_const krb5_enctype enctype));
 KRB5_DLLIMP size_t KRB5_CALLCONV krb5_encrypt_size
        KRB5_PROTOTYPE((krb5_const size_t length,
-               krb5_const struct _krb5_cryptosystem_entry FAR * crypto));
+               krb5_enctype crypto));
 KRB5_DLLIMP size_t KRB5_CALLCONV krb5_checksum_size
        KRB5_PROTOTYPE((krb5_context context,
                krb5_const krb5_cksumtype ctype));
@@ -422,15 +568,6 @@ KRB5_DLLIMP krb5_error_code KRB5_CALLCONV krb5_verify_checksum
 KRB5_DLLIMP krb5_error_code KRB5_CALLCONV krb5_random_confounder
        KRB5_PROTOTYPE((size_t, krb5_pointer));
 
-krb5_boolean KRB5_CALLCONV valid_enctype
-       KRB5_PROTOTYPE((krb5_const krb5_enctype ktype));
-krb5_boolean KRB5_CALLCONV valid_cksumtype
-       KRB5_PROTOTYPE((krb5_const krb5_cksumtype ctype));
-krb5_boolean KRB5_CALLCONV is_coll_proof_cksum
-       KRB5_PROTOTYPE((krb5_const krb5_cksumtype ctype));
-krb5_boolean KRB5_CALLCONV is_keyed_cksum
-       KRB5_PROTOTYPE((krb5_const krb5_cksumtype ctype));
-
 krb5_error_code krb5_encrypt_data
        KRB5_PROTOTYPE((krb5_context context, krb5_keyblock *key, 
                krb5_pointer ivec, krb5_data *data, 
@@ -440,6 +577,9 @@ krb5_error_code krb5_decrypt_data
        KRB5_PROTOTYPE((krb5_context context, krb5_keyblock *key, 
                krb5_pointer ivec, krb5_enc_data *data, 
                krb5_data *enc_data));
+
+#endif /* KRB5_OLD_CRYPTO */
+
 #ifdef __cplusplus
 }
 #endif
@@ -961,6 +1101,7 @@ typedef struct _krb5_pwd_data {
 #define KRB5_AUTH_CONTEXT_RET_TIME     0x00000002
 #define KRB5_AUTH_CONTEXT_DO_SEQUENCE  0x00000004
 #define KRB5_AUTH_CONTEXT_RET_SEQUENCE 0x00000008
+#define KRB5_AUTH_CONTEXT_PERMIT_ALL   0x00000010
  
 typedef struct krb5_replay_data { 
     krb5_timestamp     timestamp; 
@@ -1222,7 +1363,7 @@ typedef struct _krb5_kt_ops {
     void * serializer;
 } krb5_kt_ops;
 
-#define krb5_kt_get_type(context, keytab) (*(keytab)->ops->prefix)
+#define krb5_kt_get_type(context, keytab) ((keytab)->ops->prefix)
 #define krb5_kt_get_name(context, keytab, name, namelen) krb5_x((keytab)->ops->get_name,(context, keytab,name,namelen))
 #define krb5_kt_close(context, keytab) krb5_x((keytab)->ops->close,(context, keytab))
 #define krb5_kt_get_entry(context, keytab, principal, vno, enctype, entry) krb5_x((keytab)->ops->get,(context, keytab, principal, vno, enctype, entry))
@@ -1267,6 +1408,12 @@ krb5_error_code krb5_get_tgs_ktypes
                krb5_const_principal,
                krb5_enctype **));
 
+krb5_error_code krb5_get_permitted_enctypes
+       KRB5_PROTOTYPE((krb5_context, krb5_enctype **));
+
+krb5_boolean krb5_is_permitted_enctype
+       KRB5_PROTOTYPE((krb5_context, krb5_enctype));
+
 /* libkrb.spec */
 krb5_error_code krb5_kdc_rep_decrypt_proc
        KRB5_PROTOTYPE((krb5_context,
@@ -1616,6 +1763,8 @@ KRB5_DLLIMP void KRB5_CALLCONV krb5_free_cred_enc_part
        KRB5_PROTOTYPE((krb5_context, krb5_cred_enc_part FAR *));
 KRB5_DLLIMP void KRB5_CALLCONV krb5_free_checksum
        KRB5_PROTOTYPE((krb5_context, krb5_checksum FAR *));
+KRB5_DLLIMP void KRB5_CALLCONV krb5_free_checksum_contents
+       KRB5_PROTOTYPE((krb5_context, krb5_checksum FAR *));
 KRB5_DLLIMP void KRB5_CALLCONV krb5_free_keyblock
        KRB5_PROTOTYPE((krb5_context, krb5_keyblock FAR *));
 KRB5_DLLIMP void KRB5_CALLCONV krb5_free_keyblock_contents
@@ -1636,6 +1785,8 @@ KRB5_DLLIMP void KRB5_CALLCONV krb5_free_data_contents
        KRB5_PROTOTYPE((krb5_context, krb5_data FAR *));
 KRB5_DLLIMP void KRB5_CALLCONV krb5_free_unparsed_name
        KRB5_PROTOTYPE((krb5_context, char FAR *));
+KRB5_DLLIMP void KRB5_CALLCONV krb5_free_cksumtypes
+       KRB5_PROTOTYPE((krb5_context, krb5_cksumtype FAR *));
 
 /* From krb5/os but needed but by the outside world */
 KRB5_DLLIMP krb5_error_code KRB5_CALLCONV krb5_us_timeofday
index 202608002e27f64b92ddc45af3e6d86473fcefc7..af894dad1509a2800e028cc1ef7e6f2d3e9b1425 100644 (file)
@@ -1,3 +1,8 @@
+1998-10-26  Marc Horowitz  <marc@mit.edu>
+
+       * kdb_dbc.h, kdb.h: update kdb api to be compatible with the new
+       crypto api.
+
 Wed Jul  8 04:30:22 1998  Geoffrey King  <gjking@mit.edu>
 
        * adm_proto.h: Added prototype for new function krb5_klog_reopen()
index 6a75372d1147eb5bd81f703b23ad978386275f6b..65731279f7e850987d808422e26ec17b7f1b83e9 100644 (file)
  * KDC Database interface definitions.
  */
 
+/*
+ * Copyright (C) 1998 by the FundsXpress, INC.
+ * 
+ * All rights reserved.
+ * 
+ * Export of this software from the United States of America may require
+ * a specific license from the United States Government.  It is the
+ * responsibility of any person or organization contemplating export to
+ * obtain such a license before exporting.
+ * 
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of FundsXpress. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  FundsXpress makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
 
 #ifndef KRB5_KDB5__
 #define KRB5_KDB5__
@@ -208,8 +233,7 @@ krb5_error_code krb5_db_iterate
 krb5_error_code krb5_db_verify_master_key
        KRB5_PROTOTYPE((krb5_context,
                   krb5_principal, 
-                  krb5_keyblock *, 
-                  krb5_encrypt_block *));
+                  krb5_keyblock *));
 krb5_error_code krb5_db_store_mkey 
        KRB5_PROTOTYPE((krb5_context,
                   char *,
@@ -224,10 +248,10 @@ krb5_error_code krb5_db_setup_mkey_name
                   krb5_principal *));
 
 krb5_error_code krb5_db_set_mkey
-        KRB5_PROTOTYPE((krb5_context, krb5_encrypt_block *));
+        KRB5_PROTOTYPE((krb5_context, krb5_keyblock *));
 
 krb5_error_code krb5_db_get_mkey
-        KRB5_PROTOTYPE((krb5_context, krb5_encrypt_block **));
+        KRB5_PROTOTYPE((krb5_context, krb5_keyblock **));
 krb5_error_code krb5_db_destroy 
        KRB5_PROTOTYPE((krb5_context,
                   char * ));
@@ -246,7 +270,7 @@ krb5_boolean krb5_db_set_lockmode
 krb5_error_code        krb5_db_fetch_mkey
        KRB5_PROTOTYPE((krb5_context,
                   krb5_principal, 
-                  krb5_encrypt_block *
+                  krb5_enctype
                   krb5_boolean,
                   krb5_boolean, 
                   char *,
@@ -260,14 +284,14 @@ krb5_error_code krb5_db_close_database
 
 krb5_error_code krb5_dbekd_encrypt_key_data
        KRB5_PROTOTYPE((krb5_context,
-                  krb5_encrypt_block *,
+                  const krb5_keyblock *,
                   const krb5_keyblock *,
                   const krb5_keysalt *,
                   int,
                   krb5_key_data *));
 krb5_error_code krb5_dbekd_decrypt_key_data
        KRB5_PROTOTYPE((krb5_context,
-                  krb5_encrypt_block *,
+                  const krb5_keyblock *,
                   const krb5_key_data *,
                   krb5_keyblock *,
                   krb5_keysalt *));
@@ -343,7 +367,7 @@ struct __krb5_key_salt_tuple;
 
 krb5_error_code krb5_dbe_cpw
         KRB5_PROTOTYPE((krb5_context,
-                       krb5_encrypt_block  *,
+                       krb5_keyblock  *,
                        struct __krb5_key_salt_tuple *,
                        int,
                        char *,
@@ -351,20 +375,20 @@ krb5_error_code krb5_dbe_cpw
                        krb5_db_entry *));
 krb5_error_code krb5_dbe_apw
         KRB5_PROTOTYPE((krb5_context,
-                   krb5_encrypt_block  *,
+                   krb5_keyblock  *,
                    struct __krb5_key_salt_tuple *,
                    int,
                    char *,
                    krb5_db_entry *));
 krb5_error_code krb5_dbe_crk
         KRB5_PROTOTYPE((krb5_context,
-                   krb5_encrypt_block  *,
+                   krb5_keyblock  *,
                    struct __krb5_key_salt_tuple *,
                    int,
                    krb5_db_entry *));
 krb5_error_code krb5_dbe_ark
         KRB5_PROTOTYPE((krb5_context,
-                   krb5_encrypt_block  *,
+                   krb5_keyblock  *,
                    struct __krb5_key_salt_tuple *,
                    int,
                    krb5_db_entry *));
index 3dfd0d8416ead5027f218121356245fab07489a3..e0bbd1b4765a174c5959a5563508263ed1e466e2 100644 (file)
  * KDC Database context definitions.
  */
 
+/*
+ * Copyright (C) 1998 by the FundsXpress, INC.
+ * 
+ * All rights reserved.
+ * 
+ * Export of this software from the United States of America may require
+ * a specific license from the United States Government.  It is the
+ * responsibility of any person or organization contemplating export to
+ * obtain such a license before exporting.
+ * 
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of FundsXpress. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  FundsXpress makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
 
 #ifndef KRB5_KDB5_DBC__
 #define KRB5_KDB5_DBC__
@@ -43,7 +69,7 @@ typedef struct __krb5_db_context {
     int                 db_locks_held;  /* Number of times locked       */
     int                 db_lock_mode;   /* Last lock mode, e.g. greatest*/
     krb5_boolean        db_nb_locks;    /* [Non]Blocking lock modes     */
-    krb5_encrypt_block *db_master_key;  /* Master key of database       */
+    krb5_keyblock      *db_master_key;  /* Master key of database       */
     kdb5_dispatch_table *db_dispatch;   /* Dispatch table               */
 } krb5_db_context;
 
index 9bf1d76f00b9aa811db22fccaad797913e82749d..455733b5f1c5244d66a0b41e7dac7f8265441450 100644 (file)
@@ -1,3 +1,8 @@
+1998-10-26  Marc Horowitz  <marc@mit.edu>
+
+       * keytab.c (etype_string): replace the hardwired table with a call
+       to krb5_enctype_to_string()
+
 Fri Feb 27 23:32:38 1998  Theodore Ts'o  <tytso@rsts-11.mit.edu>
 
        * Makefile.in: Changed thisconfigdir to point at the kadmin
index df4f6ce257cd15f2eb1d22a22613d0303ac51f82..8a474b92c333f77d5a13f5c76c114eca8e40508f 100644 (file)
@@ -5,6 +5,32 @@
  * $Source$
  */
 
+/*
+ * Copyright (C) 1998 by the FundsXpress, INC.
+ * 
+ * All rights reserved.
+ * 
+ * Export of this software from the United States of America may require
+ * a specific license from the United States Government.  It is the
+ * responsibility of any person or organization contemplating export to
+ * obtain such a license before exporting.
+ * 
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of FundsXpress. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  FundsXpress makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
 #if !defined(lint) && !defined(__CODECENTER__)
 static char *rcsid = "$Header$";
 #endif
@@ -399,26 +425,11 @@ int remove_principal(char *keytab_str, krb5_keytab keytab, char
 static char *etype_string(enctype)
     krb5_enctype enctype;
 {
-    static char buf[12];
-    
-    switch (enctype) {
-    case ENCTYPE_DES_CBC_CRC:
-       return "DES-CBC-CRC";
-       break;
-    case ENCTYPE_DES_CBC_MD4:
-       return "DES-CBC-MD4";
-       break;
-    case ENCTYPE_DES_CBC_MD5:
-       return "DES-CBC-MD5";
-       break;
-#if 0
-    case ENCTYPE_DES3_CBC_MD5:
-       return "DES3-CBC-MD5";
-       break;
-#endif
-    default:
+    static char buf[100];
+    krb5_error_code ret;
+
+    if (ret = krb5_enctype_to_string(enctype, buf, sizeof(buf)))
        sprintf(buf, "etype %d", enctype);
-       return buf;
-       break;
-    }
+
+    return buf;
 }
index e6ab156f9624cbd5f44095cbbff65fd16e97f028..2f0c84e73e19058e91280bd8b8857661582386b1 100644 (file)
@@ -1,8 +1,25 @@
+1998-10-27  Marc Horowitz  <marc@mit.edu>
+
+       * dumpv4, loadv4.c, kdb5_create.c, kdb5_stash.c, kdb5_util.c,
+       kadm5_create.c: convert to new crypto api
+
 Wed Sep 30 00:02:01 1998  Theodore Y. Ts'o  <tytso@mit.edu>
 
        * dump.c: Add support for changing the master key for a database
                as part of creating a dump of the database.
 
+Thu Aug 20 16:50:00 1998  Tom Yu  <tlyu@mit.edu>
+
+       * kdb5_util.c (add_random_key): Fixes to deal with absence of "-e"
+       flag.
+
+Wed Aug 19 14:52:40 1998  Tom Yu  <tlyu@mit.edu>
+
+       * kdb5_util.c (add_random_key): New function to create a new
+       random key for a principal while retaining the previous kvno's
+       keys.  This is only temporary until a reasonable kadm5 interface
+       is made.
+
 1998-05-06  Theodore Ts'o  <tytso@rsts-11.mit.edu>
 
        * kdb5_stash.c (argv): 
index fd5d0b2f453bdfab0658a2e094d050c29ff7d899..9eb203c3a494ceb7c2f2e10f0f8bbdc83cb59396 100644 (file)
  * Dump a KDC database into a V4 slave dump.
  */
 
+/*
+ * Copyright (C) 1998 by the FundsXpress, INC.
+ * 
+ * All rights reserved.
+ * 
+ * Export of this software from the United States of America may require
+ * a specific license from the United States Government.  It is the
+ * responsibility of any person or organization contemplating export to
+ * obtain such a license before exporting.
+ * 
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of FundsXpress. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  FundsXpress makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
 #ifdef KRB5_KRB4_COMPAT
 
 #include "k5-int.h"
 struct dump_record {
        char    *comerr_name;
        FILE    *f;
-       krb5_encrypt_block *v5master;
+       krb5_keyblock *v5mkey;
        C_Block         v4_master_key;
        Key_schedule    v4_master_key_schedule;
        long    master_key_version;
        char    *realm;
 };
 
-extern krb5_encrypt_block master_encblock;
 extern krb5_keyblock master_keyblock;
 extern krb5_principal master_princ;
 extern krb5_boolean dbactive;
@@ -226,7 +251,7 @@ found_one:;
            principal->key_version,
            principal->attributes);
 
-    handle_one_key(arg, arg->v5master, &entry->key_data[ok_key], v4key);
+    handle_one_key(arg, arg->v5mkey, &entry->key_data[ok_key], v4key);
 
     for (i = 0; i < 8; i++) {
        fprintf(arg->f, "%02x", ((unsigned char*)v4key)[i]);
@@ -363,26 +388,20 @@ int handle_keys(arg)
        exit(1);
     }
 
-    krb5_use_enctype(util_context, &master_encblock, DEFAULT_KDC_ENCTYPE);
     if (retval = krb5_db_fetch_mkey(util_context, master_princ, 
-                                   &master_encblock, 0,
+                                   master_keyblock.enctype, 0,
                                    0, global_params.stash_file, 0,
                                    &master_keyblock)) { 
        com_err(arg->comerr_name, retval, "while reading master key");
        exit(1);
     }
-    if (retval = krb5_process_key(util_context, &master_encblock, 
-                                   &master_keyblock)) {
-       com_err(arg->comerr_name, retval, "while processing master key");
-       exit(1);
-    }
-    arg->v5master = &master_encblock;
+    arg->v5mkey = &master_keyblock;
     return(0);
 }
 
-handle_one_key(arg, v5master, v5key, v4key)
+handle_one_key(arg, v5mkey, v5key, v4key)
     struct dump_record *arg;
-    krb5_encrypt_block *v5master;
+    krb5_keyblock *v5mkey;
     krb5_key_data *v5key;
     des_cblock v4key;
 {
@@ -392,7 +411,7 @@ handle_one_key(arg, v5master, v5key, v4key)
     krb5_keyblock v5plainkey;
     /* v4key is the actual v4 key from the file. */
 
-    if (retval = krb5_dbekd_decrypt_key_data(util_context, v5master, v5key, 
+    if (retval = krb5_dbekd_decrypt_key_data(util_context, v5mkey, v5key, 
                                             &v5plainkey, NULL)) 
        return retval;
 
index b60ec9759e7a633d06febbfe73ad0dd3817149e0..9cedf30c4b521cb5ccec28bc2ccc81f1e9ca5708 100644 (file)
@@ -5,6 +5,32 @@
  * $Source$
  */
 
+/*
+ * Copyright (C) 1998 by the FundsXpress, INC.
+ * 
+ * All rights reserved.
+ * 
+ * Export of this software from the United States of America may require
+ * a specific license from the United States Government.  It is the
+ * responsibility of any person or organization contemplating export to
+ * obtain such a license before exporting.
+ * 
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of FundsXpress. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  FundsXpress makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
 #if !defined(lint) && !defined(__CODECENTER__)
 static char *rcsid = "$Header$";
 #endif
@@ -31,7 +57,6 @@ int add_admin_princ(void *handle, krb5_context context,
 
 extern char *progname;
 
-extern krb5_encrypt_block master_encblock;
 extern krb5_keyblock master_keyblock;
 extern krb5_db_entry master_db;
 
index 2e2c5f91262f90581ae74146f68b84a960040982..5aa7ae11ed1cf2fbd24aa708089e6a079b7edabc 100644 (file)
  * Generate (from scratch) a Kerberos KDC database.
  */
 
+/*
+ * Copyright (C) 1998 by the FundsXpress, INC.
+ * 
+ * All rights reserved.
+ * 
+ * Export of this software from the United States of America may require
+ * a specific license from the United States Government.  It is the
+ * responsibility of any person or organization contemplating export to
+ * obtain such a license before exporting.
+ * 
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of FundsXpress. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  FundsXpress makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
 #include <stdio.h>
 #include <k5-int.h>
 #include <kadm5/admin.h>
@@ -42,8 +68,7 @@ struct realm_info {
     krb5_deltat max_rlife;
     krb5_timestamp expiration;
     krb5_flags flags;
-    krb5_encrypt_block *eblock;
-    krb5_pointer rseed;
+    krb5_keyblock *key;
     krb5_int32 nkslist;
     krb5_key_salt_tuple *kslist;
 } rblock = { /* XXX */
@@ -51,8 +76,7 @@ struct realm_info {
     KRB5_KDB_MAX_RLIFE,
     KRB5_KDB_EXPIRATION,
     KRB5_KDB_DEF_FLAGS,
-    (krb5_encrypt_block *) NULL,
-    (krb5_pointer) NULL,
+    (krb5_keyblock *) NULL,
     1,
     &def_kslist
 };
@@ -85,7 +109,6 @@ static krb5_error_code add_principal
 
 extern krb5_keyblock master_keyblock;
 extern krb5_principal master_princ;
-extern krb5_encrypt_block master_encblock;
 krb5_data master_salt;
 
 krb5_data tgt_princ_entries[] = {
@@ -133,7 +156,7 @@ void kdb5_create(argc, argv)
     int pw_size = 0;
     int do_stash = 0;
     krb5_int32 crflags = KRB5_KDB_CREATE_BTREE;
-    krb5_data pwd;
+    krb5_data pwd, seed;
           
     if (strrchr(argv[0], '/'))
        argv[0] = strrchr(argv[0], '/')+1;
@@ -159,8 +182,6 @@ void kdb5_create(argc, argv)
     rblock.nkslist = global_params.num_keysalts;
     rblock.kslist = global_params.keysalts;
 
-    krb5_use_enctype(util_context, &master_encblock, master_keyblock.enctype);
-
     retval = krb5_db_set_name(util_context, global_params.dbname);
     if (!retval) retval = EEXIST;
 
@@ -216,50 +237,37 @@ master key name '%s'\n",
        com_err(argv[0], retval, "while calculated master key salt");
        exit_status++; return;
     }
-    if (retval = krb5_string_to_key(util_context, &master_encblock
-                                   &master_keyblock, &pwd, &master_salt)) {
+    if (retval = krb5_c_string_to_key(util_context, master_keyblock.enctype
+                                     &pwd, &master_salt, &master_keyblock)) {
        com_err(argv[0], retval, "while transforming master key from password");
        exit_status++; return;
     }
 
-    if ((retval = krb5_process_key(util_context, &master_encblock,
-                                  &master_keyblock))) {
-       com_err(argv[0], retval, "while processing master key");
-       exit_status++; return;
-    }
+    rblock.key = &master_keyblock;
+
+    seed.length = master_keyblock.length;
+    seed.data = master_keyblock.contents;
 
-    rblock.eblock = &master_encblock;
-    if ((retval = krb5_init_random_key(util_context, &master_encblock, 
-                                      &master_keyblock, &rblock.rseed))) {
+    if ((retval = krb5_c_random_seed(util_context, &seed))) {
        com_err(argv[0], retval, "while initializing random key generator");
-       (void) krb5_finish_key(util_context, &master_encblock);
        exit_status++; return;
     }
     if ((retval = krb5_db_create(util_context,
                                 global_params.dbname, crflags))) {
-       (void) krb5_finish_key(util_context, &master_encblock);
-       (void) krb5_finish_random_key(util_context, &master_encblock, &rblock.rseed);
        com_err(argv[0], retval, "while creating database '%s'",
                global_params.dbname);
        exit_status++; return;
     }
     if (retval = krb5_db_fini(util_context)) {
-       (void) krb5_finish_key(util_context, &master_encblock);
-       (void) krb5_finish_random_key(util_context, &master_encblock,
-                                     &rblock.rseed); 
         com_err(argv[0], retval, "while closing current database");
         exit_status++; return;
     }
     if ((retval = krb5_db_set_name(util_context, global_params.dbname))) {
-       (void) krb5_finish_key(util_context, &master_encblock);
-       (void) krb5_finish_random_key(util_context, &master_encblock, &rblock.rseed);
         com_err(argv[0], retval, "while setting active database to '%s'",
                 global_params.dbname);
         exit_status++; return;
     }
     if ((retval = krb5_db_init(util_context))) {
-       (void) krb5_finish_key(util_context, &master_encblock);
-       (void) krb5_finish_random_key(util_context, &master_encblock, &rblock.rseed);
        com_err(argv[0], retval, "while initializing the database '%s'",
                global_params.dbname);
        exit_status++; return;
@@ -268,8 +276,6 @@ master key name '%s'\n",
     if ((retval = add_principal(util_context, master_princ, MASTER_KEY, &rblock)) ||
        (retval = add_principal(util_context, &tgt_princ, TGT_KEY, &rblock))) {
        (void) krb5_db_fini(util_context);
-       (void) krb5_finish_key(util_context, &master_encblock);
-       (void) krb5_finish_random_key(util_context, &master_encblock, &rblock.rseed);
        com_err(argv[0], retval, "while adding entries to the database");
        exit_status++; return;
     }
@@ -287,8 +293,6 @@ master key name '%s'\n",
     }
     /* clean up */
     (void) krb5_db_fini(util_context);
-    (void) krb5_finish_key(util_context, &master_encblock);
-    (void) krb5_finish_random_key(util_context, &master_encblock, &rblock.rseed);
     memset((char *)master_keyblock.contents, 0, master_keyblock.length);
     free(master_keyblock.contents);
     if (pw_str) {
@@ -315,9 +319,8 @@ tgt_keysalt_iterate(ksent, ptr)
     krb5_context       context;
     krb5_error_code    kret;
     struct iterate_args        *iargs;
-    krb5_keyblock      random_keyblock, *key;
+    krb5_keyblock      key;
     krb5_int32         ind;
-    krb5_encrypt_block  random_encblock;
     krb5_pointer rseed;
     krb5_data  pwd;
 
@@ -330,33 +333,25 @@ tgt_keysalt_iterate(ksent, ptr)
      * Convert the master key password into a key for this particular
      * encryption system.
      */
-    krb5_use_enctype(context, &random_encblock, ksent->ks_enctype);
     pwd.data = mkey_password;
     pwd.length = strlen(mkey_password);
-    if (kret = krb5_string_to_key(context, &random_encblock, &random_keyblock, 
-                             &pwd, &master_salt))
-       return kret;
-    if ((kret = krb5_init_random_key(context, &random_encblock, 
-                                      &random_keyblock, &rseed)))
+    if (kret = krb5_c_random_seed(context, &pwd))
        return kret;
-    
+
     if (!(kret = krb5_dbe_create_key_data(iargs->ctx, iargs->dbentp))) {
        ind = iargs->dbentp->n_key_data-1;
-       if (!(kret = krb5_random_key(context,
-                                    &random_encblock, rseed,
-                                    &key))) {
+       if (!(kret = krb5_c_make_random_key(context, ksent->ks_enctype,
+                                           &key))) {
            kret = krb5_dbekd_encrypt_key_data(context,
-                                              iargs->rblock->eblock,
-                                              key, 
+                                              iargs->rblock->key,
+                                              &key, 
                                               NULL,
                                               1,
                                               &iargs->dbentp->key_data[ind]);
-           krb5_free_keyblock(context, key);
+           krb5_free_keyblock_contents(context, &key);
        }
     }
-    memset((char *)random_keyblock.contents, 0, random_keyblock.length);
-    free(random_keyblock.contents);
-    (void) krb5_finish_random_key(context, &random_encblock, &rseed);
+
     return(kret);
 }
 
@@ -402,7 +397,7 @@ add_principal(context, princ, op, pblock)
        entry.n_key_data = 1;
 
        entry.attributes |= KRB5_KDB_DISALLOW_ALL_TIX;
-       if ((retval = krb5_dbekd_encrypt_key_data(context, pblock->eblock,
+       if ((retval = krb5_dbekd_encrypt_key_data(context, pblock->key,
                                                  &master_keyblock, NULL, 
                                                  1, entry.key_data)))
            return retval;
index 40084e2bb4af2c7be9112e8f37955ec2abea647d..c682f3a5662ad9e7d2bc6588f94c8527d8b54e9c 100644 (file)
  * Store the master database key in a file.
  */
 
+/*
+ * Copyright (C) 1998 by the FundsXpress, INC.
+ * 
+ * All rights reserved.
+ * 
+ * Export of this software from the United States of America may require
+ * a specific license from the United States Government.  It is the
+ * responsibility of any person or organization contemplating export to
+ * obtain such a license before exporting.
+ * 
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of FundsXpress. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  FundsXpress makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
 #include "k5-int.h"
 #include "com_err.h"
 #include <kadm5/admin.h>
@@ -33,7 +59,6 @@ extern int errno;
 
 extern krb5_keyblock master_keyblock;
 extern krb5_principal master_princ;
-extern krb5_encrypt_block master_encblock;
 extern kadm5_config_params global_params;
 
 extern int exit_status;
@@ -93,8 +118,6 @@ char *argv[];
        exit_status++; return; 
     }
 
-    krb5_use_enctype(context, &master_encblock, master_keyblock.enctype);
-
     if (retval = krb5_db_set_name(context, dbname)) {
        com_err(argv[0], retval, "while setting active database to '%s'",
                dbname);
@@ -116,7 +139,8 @@ char *argv[];
     }
 
     /* TRUE here means read the keyboard, but only once */
-    if (retval = krb5_db_fetch_mkey(context, master_princ, &master_encblock,
+    if (retval = krb5_db_fetch_mkey(context, master_princ,
+                                   master_keyblock.enctype,
                                    TRUE, FALSE, (char *) NULL,
                                    0, &master_keyblock)) {
        com_err(argv[0], retval, "while reading master key");
@@ -124,7 +148,7 @@ char *argv[];
        exit_status++; return; 
     }
     if (retval = krb5_db_verify_master_key(context, master_princ, 
-                                          &master_keyblock,&master_encblock)) {
+                                          &master_keyblock)) {
        com_err(argv[0], retval, "while verifying master key");
        (void) krb5_db_fini(context);
        exit_status++; return; 
index ead82aa6342584bdbd30d5428074faad4cd1bf86..0a053c8c8e3241295c8daa70a0c06d60ba6ea87c 100644 (file)
  * Edit a KDC database.
  */
 
+/*
+ * Copyright (C) 1998 by the FundsXpress, INC.
+ * 
+ * All rights reserved.
+ * 
+ * Export of this software from the United States of America may require
+ * a specific license from the United States Government.  It is the
+ * responsibility of any person or organization contemplating export to
+ * obtain such a license before exporting.
+ * 
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of FundsXpress. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  FundsXpress makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
 #include <stdio.h>
 #include <k5-int.h>
 #include <kadm5/admin.h>
@@ -60,15 +86,14 @@ usage()
             "\tdump    [-old] [-ov] [-b6] [-verbose] [filename [princs...]]\n"
             "\tload    [-old] [-ov] [-b6] [-verbose] [-update] filename\n"
             "\tdump_v4 [filename]\n"
-            "\tload_v4 [-t] [-n] [-v] [-K] [-s stashfile] inputfile\n");
+            "\tload_v4 [-t] [-n] [-v] [-K] [-s stashfile] inputfile\n"
+            "\tark     [-e etype_list] principal\n");
      exit(1);
 }
 
 extern krb5_keyblock master_keyblock;
 extern krb5_principal master_princ;
-extern krb5_encrypt_block master_encblock;
 krb5_db_entry master_entry;
-krb5_pointer master_random;
 int    valid_master_key = 0;
 int     close_policy_db = 0;
 
@@ -84,6 +109,7 @@ int load_db(int, char **);
 int dump_v4db(int, char **);
 int load_v4db(int, char **);
 int open_db_and_mkey();
+int add_random_key(int, char **);
    
 typedef int (*cmd_func)(int, char **);
 
@@ -99,6 +125,7 @@ struct _cmd_table {
      "load", load_db, 0,
      "dump_v4", dump_v4db, 1,
      "load_v4", load_v4db, 0,
+     "ark", add_random_key, 1,
      NULL, NULL, 0,
 };
 
@@ -204,19 +231,10 @@ int main(argc, argv)
     (void) umask(077);
 
     master_keyblock.enctype = global_params.enctype;
-    if (master_keyblock.enctype != ENCTYPE_UNKNOWN) {
-       if (!valid_enctype(master_keyblock.enctype)) {
-           char tmp[32];
-           if (krb5_enctype_to_string(master_keyblock.enctype,
-                                      tmp, sizeof(tmp)))
-               com_err(argv[0], KRB5_PROG_KEYTYPE_NOSUPP,
-                       "while setting up enctype %d", master_keyblock.enctype);
-           else
-               com_err(argv[0], KRB5_PROG_KEYTYPE_NOSUPP, tmp);
-           exit(1);
-       }
-       krb5_use_enctype(util_context, &master_encblock,
-                        master_keyblock.enctype);
+    if ((master_keyblock.enctype != ENCTYPE_UNKNOWN) &&
+       (!valid_enctype(master_keyblock.enctype))) {
+       com_err(argv[0], KRB5_PROG_KEYTYPE_NOSUPP,
+               "while setting up enctype %d", master_keyblock.enctype);
     }
 
     cmd = cmd_lookup(cmd_argv[0]);
@@ -257,12 +275,9 @@ void set_dbname(argc, argv)
            return;
        }
        if (valid_master_key) {
-               (void) krb5_finish_key(util_context, &master_encblock);
-               (void) krb5_finish_random_key(util_context, &master_encblock,
-                                             &master_random);
-               krb5_free_keyblock_contents(util_context, &master_keyblock);
-               master_keyblock.contents = NULL;
-               valid_master_key = 0;
+           krb5_free_keyblock_contents(util_context, &master_keyblock);
+           master_keyblock.contents = NULL;
+           valid_master_key = 0;
        }
        krb5_free_principal(util_context, master_princ);
        dbactive = FALSE;
@@ -287,7 +302,7 @@ int open_db_and_mkey()
     krb5_error_code retval;
     int nentries;
     krb5_boolean more;
-    krb5_data scratch, pwd;
+    krb5_data scratch, pwd, seed;
 
     dbactive = FALSE;
     valid_master_key = 0;
@@ -355,23 +370,15 @@ int open_db_and_mkey()
 
        /* If no encryption type is set, use the default */
        if (master_keyblock.enctype == ENCTYPE_UNKNOWN) {
-               master_keyblock.enctype = DEFAULT_KDC_ENCTYPE;
-               if (!valid_enctype(master_keyblock.enctype)) {
-                       char tmp[32];
-                       if (krb5_enctype_to_string(master_keyblock.enctype,
-                                                  tmp, sizeof(tmp)))
-                               com_err(progname, KRB5_PROG_KEYTYPE_NOSUPP,
-                                       "while setting up enctype %d", master_keyblock.enctype);
-                       else
-                               com_err(progname, KRB5_PROG_KEYTYPE_NOSUPP, tmp);
-                       exit(1);
-               }
-               krb5_use_enctype(util_context, &master_encblock,
-                                master_keyblock.enctype);
+           master_keyblock.enctype = DEFAULT_KDC_ENCTYPE;
+           if (!valid_enctype(master_keyblock.enctype))
+               com_err(progname, KRB5_PROG_KEYTYPE_NOSUPP,
+                       "while setting up enctype %d",
+                       master_keyblock.enctype);
        }
 
-       retval = krb5_string_to_key(util_context, &master_encblock
-                                   &master_keyblock, &pwd, &scratch);
+       retval = krb5_c_string_to_key(util_context, master_keyblock.enctype
+                                     &pwd, &scratch, &master_keyblock);
        if (retval) {
            com_err(progname, retval,
                    "while transforming master key from password");
@@ -380,8 +387,9 @@ int open_db_and_mkey()
        free(scratch.data);
        mkey_password = 0;
     } else if ((retval = krb5_db_fetch_mkey(util_context, master_princ, 
-                                           &master_encblock, manual_mkey, 
-                                           FALSE, global_params.stash_file,
+                                           master_keyblock.enctype,
+                                           manual_mkey, FALSE,
+                                           global_params.stash_file,
                                            0, &master_keyblock))) {
        com_err(progname, retval, "while reading master key");
        com_err(progname, 0, "Warning: proceeding without master key");
@@ -389,27 +397,19 @@ int open_db_and_mkey()
        return(0);
     }
     if ((retval = krb5_db_verify_master_key(util_context, master_princ, 
-                                           &master_keyblock,&master_encblock))
-       ) {
+                                           &master_keyblock))) {
        com_err(progname, retval, "while verifying master key");
        exit_status++;
        krb5_free_keyblock_contents(util_context, &master_keyblock);
        return(1);
     }
-    if ((retval = krb5_process_key(util_context, &master_encblock,
-                                  &master_keyblock))) {
-       com_err(progname, retval, "while processing master key");
-       exit_status++;
-       memset((char *)master_keyblock.contents, 0, master_keyblock.length);
-       krb5_free_keyblock_contents(util_context, &master_keyblock);
-       return(1);
-    }
-    if ((retval = krb5_init_random_key(util_context, &master_encblock,
-                                      &master_keyblock,
-                                      &master_random))) {
-       com_err(progname, retval, "while initializing random key generator");
+
+    seed.length = master_keyblock.length;
+    seed.data = master_keyblock.contents;
+
+    if ((retval = krb5_c_random_seed(util_context, &seed))) {
+       com_err(progname, retval, "while seeding random number generator");
        exit_status++;
-       (void) krb5_finish_key(util_context, &master_encblock);
        memset((char *)master_keyblock.contents, 0, master_keyblock.length);
        krb5_free_keyblock_contents(util_context, &master_keyblock);
        return(1);
@@ -432,11 +432,6 @@ quit()
 
     if (finished)
        return 0;
-    if (valid_master_key) {
-           (void) krb5_finish_key(util_context, &master_encblock);
-           (void) krb5_finish_random_key(util_context, &master_encblock, 
-                                         &master_random);
-    }
     retval = krb5_db_fini(util_context);
     memset((char *)master_keyblock.contents, 0, master_keyblock.length);
     finished = TRUE;
@@ -447,3 +442,104 @@ quit()
     }
     return 0;
 }
+
+int
+add_random_key(argc, argv)
+    int argc;
+    char **argv;
+{
+    krb5_error_code ret;
+    krb5_principal princ;
+    krb5_db_entry dbent;
+    int n, i;
+    krb5_boolean more;
+    krb5_timestamp now;
+
+    krb5_key_salt_tuple *keysalts = NULL;
+    krb5_int32 num_keysalts = 0;
+
+    int free_keysalts;
+    char *me = argv[0];
+    char *ks_str = NULL;
+    char *pr_str;
+
+    if (argc < 2)
+       usage();
+    for (argv++, argc--; *argv; argv++, argc--) {
+       if (!strcmp(*argv, "-e")) {
+           argv++; argc--;
+           ks_str = *argv;
+           continue;
+       } else
+           break;
+    }
+    if (argc < 1)
+       usage();
+    pr_str = *argv;
+    ret = krb5_parse_name(util_context, pr_str, &princ);
+    if (ret) {
+       com_err(me, ret, "while parsing principal name %s", pr_str);
+       return 1;
+    }
+    n = 1;
+    ret = krb5_db_get_principal(util_context, princ, &dbent,
+                               &n, &more);
+    if (ret) {
+       com_err(me, ret, "while fetching principal %s", pr_str);
+       return 1;
+    }
+    if (n != 1) {
+       fprintf(stderr, "principal %s not found\n", pr_str);
+       return 1;
+    }
+    if (more) {
+       fprintf(stderr, "principal %s not unique\n", pr_str);
+       krb5_dbe_free_contents(util_context, &dbent);
+       return 1;
+    }
+    ret = krb5_string_to_keysalts(ks_str,
+                                 ", \t", ":.-", 0,
+                                 &keysalts,
+                                 &num_keysalts);
+    if (ret) {
+       com_err(me, ret, "while parsing keysalts %s", ks_str);
+       return 1;
+    }
+    if (!num_keysalts || keysalts == NULL) {
+       num_keysalts = global_params.num_keysalts;
+       keysalts = global_params.keysalts;
+       free_keysalts = 0;
+    } else
+       free_keysalts = 1;
+    ret = krb5_dbe_ark(util_context, &master_keyblock,
+                      keysalts, num_keysalts,
+                      &dbent);
+    if (free_keysalts)
+       free(keysalts);
+    if (ret) {
+       com_err(me, ret, "while randomizing principal %s", pr_str);
+       krb5_dbe_free_contents(util_context, &dbent);
+       return 1;
+    }
+    dbent.attributes &= ~KRB5_KDB_REQUIRES_PWCHANGE;
+    ret = krb5_timeofday(util_context, &now);
+    if (ret) {
+       com_err(me, ret, "while getting time");
+       krb5_dbe_free_contents(util_context, &dbent);
+       return 1;
+    }
+    ret = krb5_dbe_update_last_pwd_change(util_context, &dbent, now);
+    if (ret) {
+       com_err(me, ret, "while setting changetime");
+       krb5_dbe_free_contents(util_context, &dbent);
+       return 1;
+    }
+    ret = krb5_db_put_principal(util_context, &dbent, &n);
+    krb5_dbe_free_contents(util_context, &dbent);
+    if (ret) {
+       com_err(me, ret, "while saving principal %s", pr_str);
+       return 1;
+    }
+    printf("%s changed\n", pr_str);
+    return 0;
+}
index 01a4bf2a6bff3e883a58866c1916b6cbd34a1dde..b7df142bd8eb93cb65261899ba634d5f692cd5d0 100644 (file)
  * entries from a V4 database.
  */
 
+/*
+ * Copyright (C) 1998 by the FundsXpress, INC.
+ * 
+ * All rights reserved.
+ * 
+ * Export of this software from the United States of America may require
+ * a specific license from the United States Government.  It is the
+ * responsibility of any person or organization contemplating export to
+ * obtain such a license before exporting.
+ * 
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of FundsXpress. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  FundsXpress makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
 #ifdef KRB5_KRB4_COMPAT
 
 #include <des.h>
@@ -59,8 +85,7 @@ struct realm_info {
     krb5_deltat max_rlife;
     krb5_timestamp expiration;
     krb5_flags flags;
-    krb5_encrypt_block *eblock;
-    krb5_pointer rseed;
+    krb5_keyblock *key;
 };
 
 static struct realm_info rblock = { /* XXX */
@@ -92,7 +117,6 @@ static int create_local_tgt = 0;
 
 static krb5_keyblock master_keyblock;
 static krb5_principal master_princ;
-static krb5_encrypt_block master_encblock;
 
 static krb5_data tgt_princ_entries[] = {
        {0, KRB5_TGS_NAME_SIZE, KRB5_TGS_NAME},
@@ -146,6 +170,7 @@ char *argv[];
     extern kadm5_config_params global_params;
     long exp_time = 0;
     krb5_int32 crflags = KRB5_KDB_CREATE_BTREE;
+    krb5_data seed;
 
     retval = krb5_init_context(&context);
     if (retval) {
@@ -218,8 +243,6 @@ char *argv[];
        return;
     }
 
-    krb5_use_enctype(context, &master_encblock, master_keyblock.enctype);
-
     /* If the user has not requested locking, don't modify an existing database. */
     if (! tempdb) {
        retval = krb5_db_set_name(context, dbname);
@@ -281,39 +304,32 @@ master key name '%s'\n",
        fflush(stdout);
     }
 
-    if (retval = krb5_db_fetch_mkey(context, master_princ, &master_encblock,
+    if (retval = krb5_db_fetch_mkey(context, master_princ,
+                                   master_keyblock.enctype,
                                    read_mkey, read_mkey, stash_file, 0, 
                                    &master_keyblock)) {
        com_err(PROGNAME, retval, "while reading master key");
        krb5_free_context(context);
        return;
     }
-    if (retval = krb5_process_key(context, &master_encblock, &master_keyblock)) {
-       com_err(PROGNAME, retval, "while processing master key");
-       krb5_free_context(context);
-       return;
-    }
 
-    rblock.eblock = &master_encblock;
-    if (retval = krb5_init_random_key(context, &master_encblock,
-                                     &master_keyblock, &rblock.rseed)) {
+    rblock.key = &master_keyblock;
+
+    seed.length = master_keyblock.length;
+    seed.data = master_keyblock.contents;
+
+    if (retval = krb5_c_random_seed(context, &seed)) {
        com_err(PROGNAME, retval, "while initializing random key generator");
-       (void) krb5_finish_key(context, &master_encblock);
        krb5_free_context(context);
        return;
     }
     if (retval = krb5_db_create(context, tempdbname, crflags)) {
-       (void) krb5_finish_key(context, &master_encblock);
-       (void) krb5_finish_random_key(context, &master_encblock, &rblock.rseed);
-       (void) krb5_db_destroy(context, tempdbname);
        com_err(PROGNAME, retval, "while creating %sdatabase '%s'",
                tempdb ? "temporary " : "", tempdbname);
        krb5_free_context(context);
        return;
     }
     if (retval = krb5_db_set_name(context, tempdbname)) {
-       (void) krb5_finish_key(context, &master_encblock);
-       (void) krb5_finish_random_key(context, &master_encblock, &rblock.rseed);
        (void) krb5_db_destroy(context, tempdbname);
         com_err(PROGNAME, retval, "while setting active database to '%s'",
                 tempdbname);
@@ -321,16 +337,12 @@ master key name '%s'\n",
         return;
     }
     if (v4init(PROGNAME, v4manual, v4dumpfile)) {
-       (void) krb5_finish_key(context, &master_encblock);
-       (void) krb5_finish_random_key(context, &master_encblock, &rblock.rseed);
        (void) krb5_db_destroy(context, tempdbname);
        krb5_free_context(context);
        return;
     }
     if ((retval = krb5_db_init(context)) || 
        (retval = krb5_db_open_database(context))) {
-       (void) krb5_finish_key(context, &master_encblock);
-       (void) krb5_finish_random_key(context, &master_encblock, &rblock.rseed);
        (void) krb5_db_destroy(context, tempdbname);
        com_err(PROGNAME, retval, "while initializing the database '%s'",
                tempdbname);
@@ -340,8 +352,6 @@ master key name '%s'\n",
 
     if (retval = add_principal(context, master_princ, MASTER_KEY, &rblock)) {
        (void) krb5_db_fini(context);
-       (void) krb5_finish_key(context, &master_encblock);
-       (void) krb5_finish_random_key(context, &master_encblock, &rblock.rseed);
        (void) krb5_db_destroy(context, tempdbname);
        com_err(PROGNAME, retval, "while adding K/M to the database");
        krb5_free_context(context);
@@ -351,8 +361,6 @@ master key name '%s'\n",
     if (create_local_tgt &&
        (retval = add_principal(context, &tgt_princ, RANDOM_KEY, &rblock))) {
        (void) krb5_db_fini(context);
-       (void) krb5_finish_key(context, &master_encblock);
-       (void) krb5_finish_random_key(context, &master_encblock, &rblock.rseed);
        (void) krb5_db_destroy(context, tempdbname);
        com_err(PROGNAME, retval, "while adding TGT service to the database");
        krb5_free_context(context);
@@ -384,8 +392,6 @@ master key name '%s'\n",
        if (tempdb)
                (void) krb5_db_destroy (context, tempdbname);
     }
-    (void) krb5_finish_key(context, &master_encblock);
-    (void) krb5_finish_random_key(context, &master_encblock, &rblock.rseed);
     memset((char *)master_keyblock.contents, 0, master_keyblock.length);
 
     /*
@@ -547,7 +553,7 @@ Principal *princ;
     keysalt.type = KRB5_KDB_SALTTYPE_V4;
     keysalt.data.length = 0;
     keysalt.data.data = (char *) NULL;
-    retval = krb5_dbekd_encrypt_key_data(context, rblock.eblock,
+    retval = krb5_dbekd_encrypt_key_data(context, rblock.key,
                                         &v4v5key, &keysalt, 
                                         princ->key_version,
                                         &entry.key_data[0]);
@@ -592,7 +598,7 @@ struct realm_info *pblock;
 {
     krb5_db_entry entry;
     krb5_error_code retval;
-    krb5_keyblock *rkey;
+    krb5_keyblock rkey;
     int nentries = 1;
     krb5_timestamp mod_time;
     krb5_principal mod_princ;
@@ -619,7 +625,7 @@ struct realm_info *pblock;
     switch (op) {
     case MASTER_KEY:
        entry.attributes |= KRB5_KDB_DISALLOW_ALL_TIX;
-       if (retval = krb5_dbekd_encrypt_key_data(context, pblock->eblock,
+       if (retval = krb5_dbekd_encrypt_key_data(context, pblock->key,
                                                 &master_keyblock,
                                                 (krb5_keysalt *) NULL, 1,
                                                 &entry.key_data[0])) {
@@ -628,19 +634,19 @@ struct realm_info *pblock;
        }
        break;
     case RANDOM_KEY:
-       if (retval = krb5_random_key(context, pblock->eblock, pblock->rseed,
-                                    &rkey)) {
+       if (retval = krb5_c_make_random_key(context, pblock->key->enctype,
+                                           &rkey)) {
            krb5_db_free_principal(context, &entry, 1);
            return retval;
        }
-       if (retval = krb5_dbekd_encrypt_key_data(context, pblock->eblock,
-                                                rkey,
+       if (retval = krb5_dbekd_encrypt_key_data(context, pblock->key,
+                                                &rkey,
                                                 (krb5_keysalt *) NULL, 1,
                                                 &entry.key_data[0])) {
            krb5_db_free_principal(context, &entry, 1);
            return(retval);
        }
-       krb5_free_keyblock(context, rkey);
+       krb5_free_keyblock_contents(context, &rkey);
        break;
     case NULL_KEY:
        return EOPNOTSUPP;
index 22f8214bd02a32e511b87b758d0533edfe19ce0c..8131a8695cb7a2ecd1a81e88a851ce9db4e03250 100644 (file)
@@ -1,3 +1,10 @@
+1998-10-27  Marc Horowitz  <marc@mit.edu>
+
+       * ovsec_kadmd.c: add calls to a new function
+       _svcauth_gssapi_unset_names() to clean up memory when shutting
+       down.  Use krb5_overridekeyname instead of krb5_defkeyname, so the
+       command line takes precedence over the environment.
+
 Wed Jul 22 00:28:57 1998  Geoffrey King  <gjking@mit.edu>
 
        * ovsec_kadmd.c (main): Cast gss_nt_krb5_name to
index 6ac8709c76985df9d6552795482bfca10b7fa772..b8a5088d8ec8e95c80a827900d46da13094b3175 100644 (file)
@@ -3,6 +3,32 @@
  *
  */
 
+/*
+ * Copyright (C) 1998 by the FundsXpress, INC.
+ * 
+ * All rights reserved.
+ * 
+ * Export of this software from the United States of America may require
+ * a specific license from the United States Government.  It is the
+ * responsibility of any person or organization contemplating export to
+ * obtain such a license before exporting.
+ * 
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of FundsXpress. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  FundsXpress makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
 #include    <stdio.h>
 #include    <signal.h>
 #include    <syslog.h>
@@ -64,7 +90,7 @@ void *global_server_handle;
  * it also restricts us to linking against the Kv5 GSS-API library.
  * Since this is *k*admind, that shouldn't be a problem.
  */
-extern         char *krb5_defkeyname;
+extern         char *krb5_overridekeyname;
 
 char *build_princ_name(char *name, char *realm);
 void log_badauth(OM_uint32 major, OM_uint32 minor,
@@ -315,7 +341,7 @@ int main(int argc, char *argv[])
                      htons(addr.sin_port));
          }
          kadm5_destroy(global_server_handle);
-         krb5_klog_close();      
+         krb5_klog_close();
          exit(1);
      }
      memset(&addr, 0, sizeof(addr));
@@ -386,9 +412,10 @@ int main(int argc, char *argv[])
          exit(1);
      }
 
-     /* XXX krb5_defkeyname is an internal library global and should
-        go away */
-     krb5_defkeyname = params.admin_keytab;
+     /* XXX krb5_overridekeyname is an internal library global and should
+        go away.  This is an awful hack. */
+
+     krb5_overridekeyname = params.admin_keytab;
 
      /*
       * Try to acquire creds for the old OV services as well as the
@@ -402,6 +429,7 @@ int main(int argc, char *argv[])
                           "failing.");
          fprintf(stderr, "%s: Cannot set GSS-API authentication names.\n",
                  whoami);
+         _svcauth_gssapi_unset_names();
          kadm5_destroy(global_server_handle);
          krb5_klog_close();      
          exit(1);
@@ -428,6 +456,7 @@ int main(int argc, char *argv[])
                 error_message(ret));
          fprintf(stderr, "%s: Cannot initialize acl file: %s\n",
                  whoami, error_message(ret));
+         _svcauth_gssapi_unset_names();
          kadm5_destroy(global_server_handle);
          krb5_klog_close();
          exit(1);
@@ -438,6 +467,7 @@ int main(int argc, char *argv[])
          krb5_klog_syslog(LOG_ERR, "Cannot detach from tty: %s", error_message(ret));
          fprintf(stderr, "%s: Cannot detach from tty: %s\n",
                  whoami, error_message(ret));
+         _svcauth_gssapi_unset_names();
          kadm5_destroy(global_server_handle);
          krb5_klog_close();
          exit(1);
@@ -449,6 +479,7 @@ int main(int argc, char *argv[])
      krb5_klog_syslog(LOG_INFO, "finished, exiting");
 
      /* Clean up memory, etc */
+     _svcauth_gssapi_unset_names();
      kadm5_destroy(global_server_handle);
      close(s);
      acl_finish(context, 0);
@@ -934,6 +965,7 @@ void do_schpw(int s1, kadm5_config_params *params)
                         error_message(errno));
        fprintf(stderr, "Cannot create connecting socket: %s",
                error_message(errno));
+       _svcauth_gssapi_unset_names();
        kadm5_destroy(global_server_handle);
        krb5_klog_close();        
        exit(1);
index e64ee0e386264beb389bbdb32b9a457398fed839..b00913cde96bd535797dcfa03185a66862e2b492 100644 (file)
@@ -1,3 +1,18 @@
+1998-10-27  Marc Horowitz  <marc@mit.edu>
+
+       * admin_server.c, kadm_funcs.c, kadm_ser_wrap.c, kadm_server.h:
+       convert to new crypto api
+
+Fri Jul 31 18:17:16 1998  Tom Yu  <tlyu@mit.edu>
+
+       * kadm_ser_wrap.c (kadm_ser_init): Remove references to
+       master_encblock, as it's no longer needed in the new crypto API,
+       adjusting kdb calls accordingly.  Also punt calls to use_enctype,
+       process_key, etc.
+
+       * admin_server.c (clear_secrets): Remove references to
+       master_encblock, due to new crypto API.
+
 Mon Jul 20 11:20:32 1998  Ezra Peisach  <epeisach@mit.edu>
 
        * acl_files.c: Include stdlib.h if present.
index 35dd6608f1d896a36e6aa6571164f27bee648148..22a0007de6b8939701f96498cd41cd651407706a 100644 (file)
@@ -332,7 +332,7 @@ char *el;
 
     hv = hashval(el) % h->size;
     while(h->tbl[hv] != NULL && strcmp(h->tbl[hv], el)) hv = (hv+1) % h->size;
-    s = malloc(strlen(el)+1);
+    s = (char *) malloc(strlen(el)+1);
     strcpy(s, el);
     h->tbl[hv] = s;
     h->entries++;
index 9cd2f8fb51e650864103859e0a2825f7cd9eb84f..90bf087c95fb258a00e28fb3bba48b743da62b98 100644 (file)
@@ -239,9 +239,6 @@ char *argv[];
 
 static void clear_secrets()
 {
-    krb5_finish_key(kadm_context, &server_parm.master_encblock);
-    memset((char *)&server_parm.master_encblock, 0,
-          sizeof (server_parm.master_encblock));
     memset((char *)server_parm.master_keyblock.contents, 0,
           server_parm.master_keyblock.length);
     server_parm.mkvno = 0L;
@@ -479,7 +476,7 @@ void process_client(fd, who)
     }
 
     status = krb5_dbekd_decrypt_key_data(kadm_context,
-                                        &server_parm.master_encblock,
+                                        &server_parm.master_keyblock,
                                         kdatap,
                                         &cpw_skey,
                                         (krb5_keysalt *) NULL);
index 1d32073007f9180a73c428c01ede1d6286433d9b..658d4b721cd688dcaf518e208a53f39066b7dd4e 100644 (file)
@@ -591,6 +591,8 @@ des_cblock newpw;
     sblock.data.length = 0;
     sblock.data.data = (char *) NULL;
     retval = krb5_dbekd_encrypt_key_data(kadm_context,
+                                        /* XXX but I'm ifdef'd out here,
+                                           so I can't really test this. */
                                         &server_parm.master_encblock,
                                         &localpw,
                                         &sblock,
index 2c5c8076c2518c52cfa4b0d8c6c2437ee996f826..bca814d0766d15e42a1972db43ef0669b38710e8 100644 (file)
@@ -83,18 +83,7 @@ kadm_ser_init(inter, realm)
     /* setting up the database */
     mkey_name = KRB5_KDB_M_NAME;
 
-#ifdef KADM5
     server_parm.master_keyblock.enctype = params->enctype;
-    krb5_use_enctype(kadm_context, &server_parm.master_encblock, 
-                    server_parm.master_keyblock.enctype);
-#else
-    if (inter == 1) {
-       server_parm.master_keyblock.enctype = ENCTYPE_DES_CBC_MD5;
-       krb5_use_enctype(kadm_context, &server_parm.master_encblock, 
-                        server_parm.master_keyblock.enctype);
-    } else
-       server_parm.master_keyblock.enctype = ENCTYPE_UNKNOWN;
-#endif
     
     retval = krb5_db_setup_mkey_name(kadm_context, mkey_name, realm,
                                     (char **) 0,
@@ -102,24 +91,15 @@ kadm_ser_init(inter, realm)
     if (retval)
        return KADM_NO_MAST;
     krb5_db_fetch_mkey(kadm_context, server_parm.master_princ,
-                      &server_parm.master_encblock,
+                      server_parm.master_keyblock.enctype,
                       (inter == 1), FALSE,
-#ifdef KADM5
                       params->stash_file,
-#else
-                      (char *) NULL,
-#endif
                       NULL,
                       &server_parm.master_keyblock);
     if (retval)
        return KADM_NO_MAST;
     retval = krb5_db_verify_master_key(kadm_context, server_parm.master_princ,
-                                      &server_parm.master_keyblock,
-                                      &server_parm.master_encblock);
-    if (retval)
-       return KADM_NO_VERI;
-    retval = krb5_process_key(kadm_context, &server_parm.master_encblock,
-                             &server_parm.master_keyblock);
+                                      &server_parm.master_keyblock);
     if (retval)
        return KADM_NO_VERI;
     retval = krb5_db_get_principal(kadm_context, server_parm.master_princ,
index e7a7fed272fa0f1547aa3773ee70808b219b1f7d..f2932732653a3f754c5ae162b8ecca9e5bd9aa3d 100644 (file)
@@ -35,7 +35,6 @@ typedef struct {
   char sinst[INST_SZ];
   char krbrlm[REALM_SZ];
   krb5_principal sprinc;
-  krb5_encrypt_block master_encblock;
   krb5_principal master_princ;
   krb5_keyblock master_keyblock;
   krb5_deltat max_life;
index 30cf89bdd6babc307ef6e60dd467e7bfe101f0cb..757ac7dc583981394609d2f26c066412d5bf58ed 100644 (file)
@@ -1,3 +1,56 @@
+1998-10-27  Marc Horowitz  <marc@mit.edu>
+
+       * do_as_req.c, do_tgs_req.c, extern.h, kdc_preauth.c, kdc_util.c,
+       kerberos_v4.c, main.c: conver to new crypto api.
+
+Fri Sep 25 19:47:26 1998  Tom Yu  <tlyu@mit.edu>
+
+       * kerberos_v4.c (check_princ): Re-order if statements that check
+       for null keys to make Purify shut up.
+
+Thu Sep 17 18:21:51 1998  Tom Yu  <tlyu@mit.edu>
+
+       * kdc_util.c (kdc_get_server_key): Fix to not use cached tgs key
+       to prevent lossage when it might be out of date by always fetching
+       the correct kvno for the ticket out of the database.
+
+Tue Sep  1 19:34:30 1998  Tom Yu  <tlyu@mit.edu>
+
+       * kerberos_v4.c (compat_decrypt_key): Add
+       ENCTYPE_LOCAL_DES3_HMAC_SHA1 to the list of keytypes to bash.
+       (kerb_get_principal): Add ENCTYPE_LOCAL_DES3_HMAC_SHA1 to the list
+       of searched enctypes.
+
+Wed Aug 19 13:37:00 1998  Tom Yu  <tlyu@mit.edu>
+
+       * kerberos_v4.c (set_tgtkey): Add kvno arg to fetch an explicit
+       kvno.  Also compare kvno as well as realm when caching the TGT
+       key.  Declare as static.
+       (kerb_get_principal): Add kvno argument to permit searching for
+       an explicit kvno.
+       (kerberos_v4): Extract the kvno directly out of the krb_req, since
+       we know what the format is.
+
+Wed Aug 12 18:40:08 1998  Tom Yu  <tlyu@mit.edu>
+
+       * kerberos_v4.c: Add macro K4KDC_ENCTYPE_OK to determine whether a
+       given enctype is compatible with single-DES krb4.
+       (compat_decrypt_key): Declare as static.  Change call signature to
+       include an output krb5_keyblock as well as an input to determine
+       whether the principal should be treated as a service principal.
+       Bash the enctype of the keyblock to raw des3 if it's full-blown
+       des3.
+       (kerb_get_principal): Add k5key and issrv arguments as in
+       compat_decrypt_key, mostly to pass them on there.  Hardcode a
+       search order that includes des3 for looking up service keys.
+       (kerberos_v4): Call krb_create_ticket or krb_cr_tkt_krb5 as
+       appropriate to the key type.  While we're at it, s/ktbtgt/krbtgt/
+       just to avoid confusing people.
+       (check_princ): Add k5key and issrv args for as in
+       compat_decrypt_key.  Fix up null key detection to only operate if
+       it's a single-des key.
+       (set_tgtkey): Call krb_set_key_krb5 if appropriate.
+
 Tue Jul 21 20:29:38 1998  Tom Yu  <tlyu@mit.edu>
 
        * replay.c (kdc_check_lookaside):
index 22d5b1b563e4b74599eb8ad0fe0563793c4fb263..b6fa39d3dfe556a06b4c290f4de38b171fed6194 100644 (file)
@@ -65,10 +65,9 @@ krb5_data **response;                        /* filled in with a response packet */
     int c_nprincs = 0, s_nprincs = 0;
     krb5_boolean more;
     krb5_timestamp kdc_time, authtime;
-    krb5_keyblock *session_key = 0;
+    krb5_keyblock session_key;
     krb5_keyblock encrypting_key;
     const char *status;
-    krb5_encrypt_block eblock;
     krb5_key_data  *server_key, *client_key;
     krb5_enctype useenctype;
 #ifdef KRBCONF_KDC_MODIFIES_KDB
@@ -82,6 +81,7 @@ krb5_data **response;                 /* filled in with a response packet */
     ticket_reply.enc_part.ciphertext.data = 0;
     e_data.data = 0;
     encrypting_key.contents = 0;
+    session_key.contents = 0;
 
 #ifdef HAVE_NETINET_IN_H
     if (from->address->addrtype == ADDRTYPE_INET)
@@ -172,12 +172,9 @@ krb5_data **response;                      /* filled in with a response packet */
        errcode = KRB5KDC_ERR_ETYPE_NOSUPP;
        goto errout;
     }
-    krb5_use_enctype(kdc_context, &eblock, useenctype);
-    
-    if ((errcode = krb5_random_key(kdc_context, &eblock,
-                                 krb5_enctype_array[useenctype]->random_sequence,
-                                 &session_key))) {
-       /* random key failed */
+
+    if ((errcode = krb5_c_make_random_key(kdc_context, useenctype,
+                                         &session_key))) {
        status = "RANDOM_KEY_FAILED";
        goto errout;
     }
@@ -200,7 +197,7 @@ krb5_data **response;                       /* filled in with a response packet */
     if (isflagset(request->kdc_options, KDC_OPT_ALLOW_POSTDATE))
            setflag(enc_tkt_reply.flags, TKT_FLG_MAY_POSTDATE);
 
-    enc_tkt_reply.session = session_key;
+    enc_tkt_reply.session = &session_key;
     enc_tkt_reply.client = request->client;
     enc_tkt_reply.transited.tr_type = KRB5_DOMAIN_X500_COMPRESS;
     enc_tkt_reply.transited.tr_contents = empty_string; /* equivalent of "" */
@@ -312,7 +309,7 @@ krb5_data **response;                       /* filled in with a response packet */
 
     /* convert server.key into a real key (it may be encrypted
        in the database) */
-    if ((errcode = krb5_dbekd_decrypt_key_data(kdc_context, &master_encblock, 
+    if ((errcode = krb5_dbekd_decrypt_key_data(kdc_context, &master_keyblock, 
                                               server_key, &encrypting_key,
                                               NULL))) {
        status = "DECRYPT_SERVER_KEY";
@@ -353,7 +350,7 @@ krb5_data **response;                       /* filled in with a response packet */
     }
 
     /* convert client.key_data into a real key */
-    if ((errcode = krb5_dbekd_decrypt_key_data(kdc_context, &master_encblock, 
+    if ((errcode = krb5_dbekd_decrypt_key_data(kdc_context, &master_keyblock, 
                                               client_key, &encrypting_key,
                                               NULL))) {
        status = "DECRYPT_CLIENT_KEY";
@@ -366,7 +363,7 @@ krb5_data **response;                       /* filled in with a response packet */
     reply.padata = 0;
     reply.client = request->client;
     reply.ticket = &ticket_reply;
-    reply_encpart.session = session_key;
+    reply_encpart.session = &session_key;
     if ((errcode = fetch_last_req_info(&client, &reply_encpart.last_req))) {
        status = "FETCH_LAST_REQ";
        goto errout;
@@ -397,7 +394,7 @@ krb5_data **response;                       /* filled in with a response packet */
     reply.enc_part.enctype = encrypting_key.enctype;
 
     errcode = krb5_encode_kdc_rep(kdc_context, KRB5_AS_REP, &reply_encpart, 
-                                 &encrypting_key,  &reply, response);
+                                 0, &encrypting_key,  &reply, response);
     krb5_free_keyblock_contents(kdc_context, &encrypting_key);
     encrypting_key.contents = 0;
 
@@ -465,8 +462,8 @@ errout:
     }
     if (s_nprincs)
        krb5_db_free_principal(kdc_context, &server, s_nprincs);
-    if (session_key)
-       krb5_free_keyblock(kdc_context, session_key);
+    if (session_key.contents)
+       krb5_free_keyblock_contents(kdc_context, &session_key);
     if (ticket_reply.enc_part.ciphertext.data) {
        memset(ticket_reply.enc_part.ciphertext.data , 0,
               ticket_reply.enc_part.ciphertext.length);
index ff6f214d3d45e2c5871cc40203e4a5c19fa2685d..7faf748da3a5c717c570334ccb50c584e71b4433 100644 (file)
@@ -62,7 +62,6 @@ int   portnum;
 krb5_data **response;                  /* filled in with a response packet */
 {
     krb5_keyblock * subkey;
-    krb5_encrypt_block eblock;
     krb5_kdc_req *request = 0;
     krb5_db_entry server;
     krb5_kdc_rep reply;
@@ -76,7 +75,7 @@ krb5_data **response;                 /* filled in with a response packet */
     int nprincs = 0;
     krb5_boolean more;
     krb5_timestamp kdc_time, authtime=0;
-    krb5_keyblock *session_key = 0;
+    krb5_keyblock session_key;
     krb5_timestamp until, rtime;
     krb5_keyblock encrypting_key;
     krb5_key_data  *server_key;
@@ -88,6 +87,8 @@ krb5_data **response;                 /* filled in with a response packet */
     register int i;
     int firstpass = 1;
     const char *status = 0;
+
+    session_key.contents = 0;
     
     retval = decode_krb5_tgs_req(pkt, &request);
     if (retval)
@@ -258,10 +259,8 @@ tgt_again:
        goto cleanup;
     }
     
-    krb5_use_enctype(kdc_context, &eblock, useenctype);
-    errcode = krb5_random_key(kdc_context, &eblock, 
-                            krb5_enctype_array[useenctype]->random_sequence,
-                            &session_key);
+    errcode = krb5_c_make_random_key(kdc_context, useenctype, &session_key);
+
     if (errcode) {
        /* random key failed */
        status = "RANDOM_KEY_FAILED";
@@ -404,20 +403,8 @@ tgt_again:
 
     /* assemble any authorization data */
     if (request->authorization_data.ciphertext.data) {
-       krb5_encrypt_block eblock;
        krb5_data scratch;
 
-       /* decrypt the authdata in the request */
-       if (!valid_enctype(request->authorization_data.enctype)) {
-           status = "BAD_AUTH_ETYPE";
-           errcode = KRB5KDC_ERR_ETYPE_NOSUPP;
-           goto cleanup;
-       }
-       /* put together an eblock for this encryption */
-
-       krb5_use_enctype(kdc_context, &eblock,
-                        request->authorization_data.enctype);
-
        scratch.length = request->authorization_data.ciphertext.length;
        if (!(scratch.data =
              malloc(request->authorization_data.ciphertext.length))) {
@@ -425,28 +412,17 @@ tgt_again:
            errcode = ENOMEM;
            goto cleanup;
        }
-       /* do any necessary key pre-processing */
-       if ((errcode = krb5_process_key(kdc_context, &eblock,
-                                     header_ticket->enc_part2->session))) {
-           status = "AUTH_PROCESS_KEY";
-           free(scratch.data);
-           goto cleanup;
-       }
 
-       /* call the encryption routine */
-       if ((errcode = krb5_decrypt(kdc_context, (krb5_pointer) request->authorization_data.ciphertext.data,
-                                 (krb5_pointer) scratch.data,
-                                 scratch.length, &eblock, 0))) {
+       if ((errcode = krb5_c_decrypt(kdc_context,
+                                     header_ticket->enc_part2->session,
+                                     KRB5_KEYUSAGE_TGS_REQ_AD_SESSKEY,
+                                     0, &request->authorization_data,
+                                     &scratch))) {
            status = "AUTH_ENCRYPT_FAIL";
-           (void) krb5_finish_key(kdc_context, &eblock);
-           free(scratch.data);
-           goto cleanup;
-       }
-       if ((errcode = krb5_finish_key(kdc_context, &eblock))) {
-           status = "AUTH_FINISH_KEY";
            free(scratch.data);
            goto cleanup;
        }
+
        /* scratch now has the authorization data, so we decode it */
        errcode = decode_krb5_authdata(&scratch, &(request->unenc_authdata));
        free(scratch.data);
@@ -466,7 +442,7 @@ tgt_again:
        enc_tkt_reply.authorization_data =
            header_ticket->enc_part2->authorization_data;
 
-    enc_tkt_reply.session = session_key;
+    enc_tkt_reply.session = &session_key;
     enc_tkt_reply.client = header_ticket->enc_part2->client;
     enc_tkt_reply.transited.tr_type = KRB5_DOMAIN_X500_COMPRESS;
     enc_tkt_reply.transited.tr_contents = empty_string; /* equivalent of "" */
@@ -562,7 +538,7 @@ tgt_again:
        /* convert server.key into a real key (it may be encrypted
         *        in the database) */
        if ((errcode = krb5_dbekd_decrypt_key_data(kdc_context,
-                                                  &master_encblock, 
+                                                  &master_keyblock, 
                                                   server_key, &encrypting_key,
                                                   NULL))) {
            status = "DECRYPT_SERVER_KEY";
@@ -571,7 +547,6 @@ tgt_again:
        if ((encrypting_key.enctype == ENCTYPE_DES_CBC_CRC) &&
            (isflagset(server.attributes, KRB5_KDB_SUPPORT_DESMD5)))
            encrypting_key.enctype = ENCTYPE_DES_CBC_MD5;
-       ticket_reply.enc_part.kvno = server_key->key_data_kvno;
        errcode = krb5_encrypt_tkt_part(kdc_context, &encrypting_key,
                                        &ticket_reply);
        krb5_free_keyblock_contents(kdc_context, &encrypting_key);
@@ -579,6 +554,7 @@ tgt_again:
            status = "TKT_ENCRYPT";
            goto cleanup;
        }
+       ticket_reply.enc_part.kvno = server_key->key_data_kvno;
     }
 
     /* Start assembling the response */
@@ -588,7 +564,7 @@ tgt_again:
     reply.enc_part.kvno = 0;           /* We are using the session key */
     reply.ticket = &ticket_reply;
 
-    reply_encpart.session = session_key;
+    reply_encpart.session = &session_key;
     reply_encpart.nonce = request->nonce;
 
     /* copy the time fields EXCEPT for authtime; its location
@@ -616,6 +592,7 @@ tgt_again:
     reply.enc_part.enctype = subkey ? subkey->enctype :
                    header_ticket->enc_part2->session->enctype;
     errcode = krb5_encode_kdc_rep(kdc_context, KRB5_TGS_REP, &reply_encpart, 
+                                 subkey ? 1 : 0,
                                  subkey ? subkey :
                                  header_ticket->enc_part2->session,
                                  &reply, response);
@@ -661,8 +638,8 @@ cleanup:
        free(sname);
     if (nprincs)
        krb5_db_free_principal(kdc_context, &server, 1);
-    if (session_key)
-       krb5_free_keyblock(kdc_context, session_key);
+    if (session_key.contents)
+       krb5_free_keyblock_contents(kdc_context, &session_key);
     if (newtransited)
        free(enc_tkt_reply.transited.tr_contents.data); 
 
index e8de8a7e32080459608deab3d5ed208aa1735c33..c31e5c70e5272b303e002f6ba3ddbf9bc3882020 100644 (file)
@@ -56,7 +56,6 @@ typedef struct __kdc_realm_data {
     /*
      * Other per-realm data.
      */
-    krb5_encrypt_block realm_encblock; /* Per-realm master encryption block*/
     char               *realm_ports;   /* Per-realm KDC port */
     /*
      * Per-realm parameters.
@@ -79,7 +78,6 @@ extern kdc_realm_t    *kdc_active_realm;
 #define        kdc_context                     kdc_active_realm->realm_context
 #define        max_life_for_realm              kdc_active_realm->realm_maxlife
 #define        max_renewable_life_for_realm    kdc_active_realm->realm_maxrlife
-#define        master_encblock                 kdc_active_realm->realm_encblock
 #define        master_keyblock                 kdc_active_realm->realm_mkey
 #define        master_princ                    kdc_active_realm->realm_mprinc
 #define        tgs_key                         kdc_active_realm->realm_tgskey
index b88c7728318c892ca3836776719842395e4dd30b..0324694a2e36f6721871247d3969f69c2045491b 100644 (file)
  * Preauthentication routines for the KDC.
  */
 
+/*
+ * Copyright (C) 1998 by the FundsXpress, INC.
+ * 
+ * All rights reserved.
+ * 
+ * Export of this software from the United States of America may require
+ * a specific license from the United States Government.  It is the
+ * responsibility of any person or organization contemplating export to
+ * obtain such a license before exporting.
+ * 
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of FundsXpress. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  FundsXpress makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
 #include "k5-int.h"
 #include "kdc_util.h"
 #include "extern.h"
@@ -365,13 +391,18 @@ verify_enc_timestamp(context, client, request, enc_tkt_reply, pa)
     krb5_int32                 start;
     krb5_timestamp             timenow;
     
-    enc_ts_data.data = 0;
     scratch.data = pa->contents;
     scratch.length = pa->length;
+
+    enc_ts_data.data = 0;
     
     if ((retval = decode_krb5_enc_data(&scratch, &enc_data)) != 0)
        goto cleanup;
 
+    enc_ts_data.length = enc_data->ciphertext.length;
+    if ((enc_ts_data.data = (char *) malloc(enc_ts_data.length)) == NULL)
+       goto cleanup;
+
     start = 0;
     while (1) {
        if ((retval = krb5_dbe_search_enctype(context, client,
@@ -379,12 +410,14 @@ verify_enc_timestamp(context, client, request, enc_tkt_reply, pa)
                                              -1, 0, &client_key)))
            goto cleanup;
 
-       if ((retval = krb5_dbekd_decrypt_key_data(context, &master_encblock, 
+       if ((retval = krb5_dbekd_decrypt_key_data(context, &master_keyblock, 
                                                  client_key, &key, NULL)))
            goto cleanup;
+
        key.enctype = enc_data->enctype;
 
-       retval = krb5_decrypt_data(context, &key, 0, enc_data, &enc_ts_data);
+       retval = krb5_c_decrypt(context, &key, KRB5_KEYUSAGE_AS_REQ_PA_ENC_TS,
+                               0, enc_data, &enc_ts_data);
        krb5_free_keyblock_contents(context, &key);
        if (retval == 0)
            break;
@@ -492,6 +525,7 @@ get_etype_info(context, request, client, server, pa_data)
        goto cleanup;
     pa_data->contents = scratch->data;
     pa_data->length = scratch->length;
+    free(scratch);
 
     retval = 0;
 
@@ -615,7 +649,6 @@ get_sam_edata(context, request, client, server, pa_data)
     krb5_predicted_sam_response        psr;
     krb5_data *                        scratch;
     int                        i = 0;
-    krb5_encrypt_block         eblock;
     krb5_keyblock encrypting_key;
     char response[9];
     char inputblock[8];
@@ -666,6 +699,13 @@ get_sam_edata(context, request, client, server, pa_data)
          break;
        }
       }
+
+      krb5_princ_component(kdc_context,newp,probeslot)->data = 0;
+      krb5_princ_component(kdc_context,newp,probeslot)->length = 0;
+      krb5_princ_size(context, newp)--;
+
+      krb5_free_principal(kdc_context, newp);
+
       /* if sc.sam_type is set, it worked */
       if (sc.sam_type) {
        /* so use assoc to get the key out! */
@@ -678,14 +718,15 @@ get_sam_edata(context, request, client, server, pa_data)
                                         &assoc_key);
          if (retval) {
            char *sname;
-           krb5_unparse_name(kdc_context, newp, &sname);
+           krb5_unparse_name(kdc_context, request->client, &sname);
            com_err("krb5kdc", retval, 
                    "snk4 finding the enctype and key <%s>", sname);
+           free(sname);
            return retval;
          }
          /* convert server.key into a real key */
          retval = krb5_dbekd_decrypt_key_data(kdc_context,
-                                              &master_encblock, 
+                                              &master_keyblock, 
                                               assoc_key, &encrypting_key,
                                               NULL);
          if (retval) {
@@ -695,14 +736,10 @@ get_sam_edata(context, request, client, server, pa_data)
          }
          /* now we can use encrypting_key... */
        }
-      } else
+      } else {
        /* SAM is not an option - so don't return as hint */
        return KRB5_PREAUTH_BAD_TYPE;
-
-      krb5_princ_component(kdc_context,newp,probeslot)->data = 0;
-      krb5_princ_component(kdc_context,newp,probeslot)->length = 0;
-      krb5_princ_size(context, newp)--;
-      krb5_free_principal(kdc_context, newp);
+      }
     }
     sc.magic = KV5M_SAM_CHALLENGE;
     sc.sam_flags = KRB5_SAM_USE_SAD_AS_KEY;
@@ -721,21 +758,35 @@ get_sam_edata(context, request, client, server, pa_data)
       /* eblock is just to set the enctype */
       {
        const krb5_enctype type = ENCTYPE_DES_CBC_MD5;
-       if (!valid_enctype(type)) return KRB5_PROG_ETYPE_NOSUPP;
-       krb5_use_enctype(context, &eblock, type);
-       retval = krb5_string_to_key(context, &eblock, 
-                                   &psr.sam_key, &sc.sam_challenge, 
-                                   0 /* salt */);
-       retval = encode_krb5_predicted_sam_response(&psr, &scratch);
-       if (retval) goto cleanup;
+
+       if ((retval = krb5_c_string_to_key(context, type, &sc.sam_challenge,
+                                          0 /* salt */, &psr.sam_key)))
+           goto cleanup;
+
+       if ((retval = encode_krb5_predicted_sam_response(&psr, &scratch)))
+           goto cleanup;
        
        {
-         krb5_enc_data tmpdata;
-         retval = krb5_encrypt_data(context, master_encblock.key, 0, 
-                                    scratch, &tmpdata);
-         sc.sam_track_id = tmpdata.ciphertext;
+           size_t enclen;
+           krb5_enc_data tmpdata;
+
+           if ((retval = krb5_c_encrypt_length(context,
+                                               master_keyblock.enctype,
+                                               scratch->length, &enclen)))
+               goto cleanup;
+
+           if ((tmpdata.ciphertext.data = (char *) malloc(enclen)) == NULL) {
+               retval = ENOMEM;
+               goto cleanup;
+           }
+           tmpdata.ciphertext.length = enclen;
+
+           if ((retval = krb5_c_encrypt(context, &master_keyblock,
+                                        /* XXX */ 0, 0, scratch, &tmpdata)))
+               goto cleanup;
+
+           sc.sam_track_id = tmpdata.ciphertext;
        }
-       if (retval) goto cleanup;
       }
 
       sc.sam_response_prompt.data = "response prompt";
@@ -779,15 +830,17 @@ get_sam_edata(context, request, client, server, pa_data)
       /* generate digit string, take it mod 1000000 (six digits.) */
       {
        int j;
-       krb5_encrypt_block eblock;
-       krb5_keyblock *session_key = 0;
+       krb5_keyblock session_key;
        char outputblock[8];
        int i;
+
+       session_key.contents = 0;
+
        memset(inputblock, 0, 8);
-       krb5_use_enctype(kdc_context, &eblock, ENCTYPE_DES_CBC_CRC);
-       retval = krb5_random_key(kdc_context, &eblock, 
-                                krb5_enctype_array[ENCTYPE_DES_CBC_CRC]->random_sequence,
-                                &session_key);
+
+       retval = krb5_c_make_random_key(kdc_context, ENCTYPE_DES_CBC_CRC,
+                                       &session_key);
+
        if (retval) {
          /* random key failed */
          com_err("krb5kdc", retval,"generating random challenge for preauth");
@@ -795,41 +848,48 @@ get_sam_edata(context, request, client, server, pa_data)
        }
        /* now session_key has a key which we can pick bits out of */
        /* we need six decimal digits. Grab 6 bytes, div 2, mod 10 each. */
-       if (session_key->length != 8) {
+       if (session_key.length != 8) {
          com_err("krb5kdc", retval = KRB5KDC_ERR_ETYPE_NOSUPP,
                  "keytype didn't match code expectations");
          return retval;
        }
        for(i = 0; i<6; i++) {
-         inputblock[i] = '0' + ((session_key->contents[i]/2) % 10);
+         inputblock[i] = '0' + ((session_key.contents[i]/2) % 10);
        }
-       if (session_key)
-         krb5_free_keyblock(kdc_context, session_key);
+       if (session_key.contents)
+         krb5_free_keyblock_contents(kdc_context, &session_key);
 
        /* retval = krb5_finish_key(kdc_context, &eblock); */
        /* now we have inputblock containing the 8 byte input to DES... */
        sc.sam_challenge.data = inputblock;
        sc.sam_challenge.length = 6;
 
-       krb5_use_enctype(kdc_context, &eblock, ENCTYPE_DES_CBC_RAW);
        encrypting_key.enctype = ENCTYPE_DES_CBC_RAW;
-       /* do any necessary key pre-processing */
-       retval= krb5_process_key(kdc_context, &eblock, &encrypting_key);
 
        if (retval) {
          com_err("krb5kdc", retval, "snk4 processing key");
        }
 
        {
-         char ivec[8];
-         memset(ivec,0,8);
-         retval = krb5_encrypt(kdc_context, inputblock, outputblock, 8,
-                               &eblock, ivec);
-       }
-       if (retval) {
-         com_err("krb5kdc", retval, "snk4 response generation failed");
-         return retval;
+           krb5_data plain;
+           krb5_enc_data cipher;
+
+           plain.length = 8;
+           plain.data = inputblock;
+
+           /* XXX I know this is enough because of the fixed raw enctype.
+              if it's not, the underlying code will return a reasonable
+              error, which should never happen */
+           cipher.ciphertext.length = 8;
+           cipher.ciphertext.data = outputblock;
+
+           if ((retval = krb5_c_encrypt(kdc_context, &encrypting_key,
+                                        /* XXX */ 0, 0, &plain, &cipher))) {
+               com_err("krb5kdc", retval, "snk4 response generation failed");
+               return retval;
+           }
        }
+
        /* now output block is the raw bits of the response; convert it
           to display form */
        for (j=0; j<4; j++) {
@@ -863,20 +923,34 @@ sc.sam_challenge_label.length = strlen(sc.sam_challenge_label.data);
       /* string2key on sc.sam_challenge goes in here */
       /* eblock is just to set the enctype */
       {
-       const krb5_enctype type = ENCTYPE_DES_CBC_MD5;
-       if (!valid_enctype(type)) return KRB5_PROG_ETYPE_NOSUPP;
-       krb5_use_enctype(context, &eblock, type);
-       retval = krb5_string_to_key(context, &eblock, 
-                                   &psr.sam_key, &predict_response, 
-                                   0 /* salt */);
+       retval = krb5_c_string_to_key(context, ENCTYPE_DES_CBC_MD5,
+                                     &predict_response, 0 /* salt */,
+                                     &psr.sam_key);
+       if (retval) goto cleanup;
+
        retval = encode_krb5_predicted_sam_response(&psr, &scratch);
        if (retval) goto cleanup;
        
        {
-         krb5_enc_data tmpdata;
-         retval = krb5_encrypt_data(context, master_encblock.key, 0, 
-                                    scratch, &tmpdata);
-         sc.sam_track_id = tmpdata.ciphertext;
+           size_t enclen;
+           krb5_enc_data tmpdata;
+
+           if ((retval = krb5_c_encrypt_length(context,
+                                               master_keyblock.enctype,
+                                               scratch->length, &enclen)))
+               goto cleanup;
+
+           if ((tmpdata.ciphertext.data = (char *) malloc(enclen)) == NULL) {
+               retval = ENOMEM;
+               goto cleanup;
+           }
+           tmpdata.ciphertext.length = enclen;
+
+           if ((retval = krb5_c_encrypt(context, &master_keyblock,
+                                        /* XXX */ 0, 0, scratch, &tmpdata)))
+               goto cleanup;
+
+           sc.sam_track_id = tmpdata.ciphertext;
        }
        if (retval) goto cleanup;
       }
@@ -937,37 +1011,64 @@ verify_sam_response(context, client, request, enc_tkt_reply, pa)
     scratch.data = pa->contents;
     scratch.length = pa->length;
     
-    retval = decode_krb5_sam_response(&scratch, &sr);
-    if (retval) com_err("krb5kdc", retval, "decode_krb5_sam_response failed");
-    if (retval) goto cleanup;
+    if ((retval = decode_krb5_sam_response(&scratch, &sr))) {
+       scratch.data = 0;
+       com_err("krb5kdc", retval, "decode_krb5_sam_response failed");
+       goto cleanup;
+    }
 
     {
       krb5_enc_data tmpdata;
+
+      tmpdata.enctype = ENCTYPE_UNKNOWN;
       tmpdata.ciphertext = sr->sam_track_id;
-      retval = krb5_decrypt_data(context, master_encblock.key, 0, 
-                                &tmpdata, &scratch);
-      if (retval) com_err("krb5kdc", retval, "decrypt track_id failed");
+
+      scratch.length = tmpdata.ciphertext.length;
+      if ((scratch.data = (char *) malloc(scratch.length)) == NULL) {
+         retval = ENOMEM;
+         goto cleanup;
+      }
+
+      if ((retval = krb5_c_decrypt(context, &master_keyblock, /* XXX */ 0, 0,
+                                  &tmpdata, &scratch))) {
+         com_err("krb5kdc", retval, "decrypt track_id failed");
+         goto cleanup;
+      }
     }
-    if (retval) goto cleanup;
-    retval = decode_krb5_predicted_sam_response(&scratch, &psr);
-    if (retval) com_err("krb5kdc", retval, "decode_krb5_predicted_sam_response failed");
-    if (retval) goto cleanup;
+
+    if ((retval = decode_krb5_predicted_sam_response(&scratch, &psr))) {
+       com_err("krb5kdc", retval,
+               "decode_krb5_predicted_sam_response failed");
+       goto cleanup;
+    }
+
     {
-      /* now psr.sam_key is what we said to use... */
-      retval = krb5_decrypt_data(context, &psr->sam_key, 0, 
-                                &sr->sam_enc_nonce_or_ts, &scratch);
-      if (retval) com_err("krb5kdc", retval, "decrypt nonce_or_ts failed");
+       free(scratch.data);
+       scratch.length = sr->sam_enc_nonce_or_ts.ciphertext.length;
+       if ((scratch.data = (char *) malloc(scratch.length)) == NULL) {
+           retval = ENOMEM;
+           goto cleanup;
+       }
+
+       if ((retval = krb5_c_decrypt(context, &psr->sam_key, /* XXX */ 0,
+                                    0, &sr->sam_enc_nonce_or_ts, &scratch))) {
+           com_err("krb5kdc", retval, "decrypt nonce_or_ts failed");
+           goto cleanup;
+       }
+    }
+
+    if ((retval = decode_krb5_enc_sam_response_enc(&scratch, &esre))) {
+       com_err("krb5kdc", retval, "decode_krb5_enc_sam_response_enc failed");
+       goto cleanup;
     }
-    if (retval) goto cleanup;
-    retval = decode_krb5_enc_sam_response_enc(&scratch, &esre);
-    if (retval) com_err("krb5kdc", retval, "decode_krb5_enc_sam_response_enc failed");
-    if (retval) goto cleanup;
+
     if (esre->sam_timestamp != sr->sam_patimestamp) {
       retval = KRB5KDC_ERR_PREAUTH_FAILED;
       goto cleanup;
     }
-    retval = krb5_timeofday(context, &timenow);
-    if (retval) goto cleanup;
+
+    if ((retval = krb5_timeofday(context, &timenow)))
+       goto cleanup;
     
     if (labs(timenow - sr->sam_patimestamp) > context->clockskew) {
        retval = KRB5KRB_AP_ERR_SKEW;
@@ -975,8 +1076,11 @@ verify_sam_response(context, client, request, enc_tkt_reply, pa)
     }
 
     setflag(enc_tkt_reply->flags, TKT_FLG_HW_AUTH);
+
   cleanup:
-    if (retval) com_err("krb5kdc", retval, "sam verify failure");
+    if (retval)
+       com_err("krb5kdc", retval, "sam verify failure");
+    if (scratch.data) free(scratch.data);
     if (sr) free(sr);
     if (psr) free(psr);
     if (esre) free(esre);
index 863ffd19c9472cc275e295ebd586869ce8dd4655..51d4d7807e6e6fcb928ab0e7186ef8031adcbe02 100644 (file)
@@ -124,6 +124,7 @@ comp_cksum(kcontext, source, ticket, his_cksum)
     krb5_checksum      * his_cksum;
 {
     krb5_error_code      retval;
+    krb5_boolean         valid;
 
     if (!valid_cksumtype(his_cksum->checksum_type)) 
        return KRB5KDC_ERR_SUMTYPE_NOSUPP;
@@ -133,14 +134,15 @@ comp_cksum(kcontext, source, ticket, his_cksum)
        return KRB5KRB_AP_ERR_INAPP_CKSUM;
 
     /* verify checksum */
-    if ((retval = krb5_verify_checksum(kcontext, his_cksum->checksum_type,
-                                      his_cksum,
-                                      source->data, source->length, 
-                                      ticket->enc_part2->session->contents, 
-                                      ticket->enc_part2->session->length))) {
-       retval = KRB5KRB_AP_ERR_BAD_INTEGRITY;
-    }
-    return retval;
+    if ((retval = krb5_c_verify_checksum(kcontext, ticket->enc_part2->session,
+                                        KRB5_KEYUSAGE_TGS_REQ_AUTH_CKSUM,
+                                        source, his_cksum, &valid)))
+       return(retval);
+
+    if (!valid)
+       return(KRB5KRB_AP_ERR_BAD_INTEGRITY);
+
+    return(0);
 }
 
 krb5_error_code 
@@ -333,12 +335,15 @@ cleanup:
 /* XXX This function should no longer be necessary. 
  * The KDC should take the keytab associated with the realm and pass that to 
  * the krb5_rd_req_decode(). --proven
+ *
+ * It's actually still used by do_tgs_req() for u2u auth, and not too
+ * much else. -- tlyu
  */
 krb5_error_code
 kdc_get_server_key(ticket, key, kvno)
     krb5_ticket        * ticket;
     krb5_keyblock      ** key;
-    krb5_kvno          * kvno;
+    krb5_kvno          * kvno; /* XXX nothing uses this */
 {
     krb5_error_code      retval;
     krb5_db_entry        server;
@@ -347,64 +352,46 @@ kdc_get_server_key(ticket, key, kvno)
     krb5_key_data      * server_key;
     int                          i;
 
-    if (krb5_principal_compare(kdc_context, tgs_server, ticket->server)) {
-       retval = krb5_copy_keyblock(kdc_context, &tgs_key, key);
-       *kvno = tgs_kvno;
-       return retval;
-    } else {
-       nprincs = 1;
+    nprincs = 1;
 
-       if ((retval = krb5_db_get_principal(kdc_context, ticket->server,
-                                           &server, &nprincs,
-                                           &more))) {
-           return(retval);
-       }
-       if (more) {
-           krb5_db_free_principal(kdc_context, &server, nprincs);
-           return(KRB5KDC_ERR_PRINCIPAL_NOT_UNIQUE);
-       } else if (nprincs != 1) {
-           char *sname;
-
-           krb5_db_free_principal(kdc_context, &server, nprincs);
-           if (!krb5_unparse_name(kdc_context, ticket->server, &sname)) {
-               krb5_klog_syslog(LOG_ERR,"TGS_REQ: UNKNOWN SERVER: server='%s'",
-                      sname);
-               free(sname);
-           }
-           return(KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN);
-       }
-       /* 
-        * Get the latest version of the server key_data and
-        * convert the key into a real key (it may be encrypted in the database)
-        *
-        * Search the key list in the order specified by the key/salt list.
-        */
-       server_key = (krb5_key_data *) NULL;
-       for (i=0; i<kdc_active_realm->realm_nkstypes; i++) {
-           krb5_key_salt_tuple *kslist;
-
-           kslist = (krb5_key_salt_tuple *) kdc_active_realm->realm_kstypes;
-           if (!krb5_dbe_find_enctype(kdc_context,
-                                      &server,
-                                      kslist[i].ks_enctype,
-                                      -1,
-                                      -1,
-                                      &server_key))
-               break;
-       }
-       if (!server_key)
-           return(KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN);
-                                 
-       *kvno = server_key->key_data_kvno;
-       if ((*key = (krb5_keyblock *)malloc(sizeof **key))) {
-           retval = krb5_dbekd_decrypt_key_data(kdc_context, &master_encblock,
-                                                server_key,
-                                                *key, NULL);
-       } else
-           retval = ENOMEM;
+    if ((retval = krb5_db_get_principal(kdc_context, ticket->server,
+                                       &server, &nprincs,
+                                       &more))) {
+       return(retval);
+    }
+    if (more) {
        krb5_db_free_principal(kdc_context, &server, nprincs);
-       return retval;
+       return(KRB5KDC_ERR_PRINCIPAL_NOT_UNIQUE);
+    } else if (nprincs != 1) {
+       char *sname;
+
+       krb5_db_free_principal(kdc_context, &server, nprincs);
+       if (!krb5_unparse_name(kdc_context, ticket->server, &sname)) {
+           krb5_klog_syslog(LOG_ERR,"TGS_REQ: UNKNOWN SERVER: server='%s'",
+                            sname);
+           free(sname);
+       }
+       return(KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN);
     }
+    retval = krb5_dbe_find_enctype(kdc_context, &server,
+                                  ticket->enc_part.enctype, -1,
+                                  ticket->enc_part.kvno, &server_key);
+    if (retval)
+       goto errout;
+    if (!server_key) {
+       retval = KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN;
+       goto errout;
+    }
+    *kvno = server_key->key_data_kvno;
+    if ((*key = (krb5_keyblock *)malloc(sizeof **key))) {
+       retval = krb5_dbekd_decrypt_key_data(kdc_context, &master_keyblock,
+                                            server_key,
+                                            *key, NULL);
+    } else
+       retval = ENOMEM;
+errout:
+    krb5_db_free_principal(kdc_context, &server, nprincs);
+    return retval;
 }
 
 /* This probably wants to be updated if you support last_req stuff */
index f5a3a778953f8f68f0555325fa182b5ba651ba16..a1efd8b3759b9165324588a45f5badfed5459d51 100644 (file)
 
 extern int errno;
 
-int compat_decrypt_key PROTOTYPE((krb5_key_data *, C_Block));
-int kerb_get_principal PROTOTYPE((char *, char *, Principal *, int,
-                                 int *));
-int check_princ PROTOTYPE((char *, char *, unsigned, Principal *));
+static int compat_decrypt_key PROTOTYPE((krb5_key_data *, C_Block,
+                                        krb5_keyblock *, int));
+static int kerb_get_principal PROTOTYPE((char *, char *, Principal *, int,
+                                 int *, krb5_keyblock *, krb5_kvno, int));
+static int check_princ PROTOTYPE((char *, char *, unsigned, Principal *,
+                          krb5_keyblock *, int));
 
 #ifdef HAVE_STDARG_H
 char * v4_klog KRB5_PROTOTYPE((int, const char *, ...));
@@ -144,8 +146,8 @@ static krb5_data *response;
 
 void kerberos_v4 PROTOTYPE((struct sockaddr_in *, KTEXT));
 void kerb_err_reply PROTOTYPE((struct sockaddr_in *, KTEXT, long, char *));
-int set_tgtkey PROTOTYPE((char *));
+static int set_tgtkey PROTOTYPE((char *, krb5_kvno));
+
 /* Attributes converted from V5 to V4 - internal representation */
 #define V4_KDB_REQUIRES_PREAUTH  0x1
 #define V4_KDB_DISALLOW_ALL_TIX  0x2
@@ -334,36 +336,59 @@ hang()
 }
 #define kdb_encrypt_key( in, out, mk, mks, e_d_flag)
 #define LONGLEN 4
+#define K4KDC_ENCTYPE_OK(e)                    \
+((e) == ENCTYPE_DES_CBC_CRC                    \
+ || (e) == ENCTYPE_DES_CBC_MD4                 \
+ || (e) == ENCTYPE_DES_CBC_MD5                 \
+ || (e) == ENCTYPE_DES_CBC_RAW)
 
 /* take a v5 keyblock, masquerading as a v4 key,
  * decrypt it, and convert the resulting v5 keyblock
  * to a real v4 key.
  * this is ugly, but it saves changing more v4 code.
+ *
+ * Also, keep old krb5_keyblock around in case we want to use it later.
  */
-int compat_decrypt_key (in5, out4)
-     krb5_key_data *in5;
-     C_Block out4;
+static int
+compat_decrypt_key (in5, out4, out5, issrv)
+    krb5_key_data *in5;
+    C_Block out4;
+    krb5_keyblock *out5;
+    int issrv;                 /* whether it's a server key */
 {
-    krb5_keyblock out5;
-    int retval = -1;
+    krb5_error_code retval;
 
-    out5.contents = NULL;
-    if (krb5_dbekd_decrypt_key_data(kdc_context,&master_encblock,in5,&out5,NULL)){
+    out5->contents = NULL;
+    memset(out4, 0, sizeof(out4));
+    retval = krb5_dbekd_decrypt_key_data(kdc_context, &master_keyblock,
+                                        in5, out5, NULL);
+    if (retval) {
        lt = klog(L_DEATH_REQ, "KDC can't decrypt principal's key.");
+       out5->contents = NULL;
        return(retval);
     }
-    if (out5.length != KRB5_MIT_DES_KEYSIZE)
-       lt = klog(L_DEATH_REQ, "internal keysize error in kdc");
-    else if ((out5.enctype != ENCTYPE_DES_CBC_CRC) &&
-            (out5.enctype != ENCTYPE_DES_CBC_MD4) &&
-            (out5.enctype != ENCTYPE_DES_CBC_MD5) &&
-            (out5.enctype != ENCTYPE_DES_CBC_RAW))
-       lt = klog(L_DEATH_REQ, "incompatible principal key type.");
-    else {
-       memcpy(out4, out5.contents, out5.length);
-       retval = 0;
+    if (K4KDC_ENCTYPE_OK(out5->enctype)) {
+       if (out5->length == KRB5_MIT_DES_KEYSIZE) 
+           memcpy(out4, out5->contents, out5->length);
+       else {
+           lt = klog(L_DEATH_REQ, "internal keysize error in kdc");
+           krb5_free_keyblock_contents(kdc_context, out5);
+           out5->contents = NULL;
+           retval = -1;
+       }
+    } else {
+       if (!issrv) {
+           lt = klog(L_DEATH_REQ, "incompatible principal key type.");
+           krb5_free_keyblock_contents(kdc_context, out5);
+           out5->contents = NULL;
+           retval = -1;
+       } else {
+           /* KLUDGE! If it's a non-raw des3 key, bash its enctype */
+           if (out5->enctype == ENCTYPE_DES3_HMAC_SHA1 ||
+               out5->enctype == ENCTYPE_LOCAL_DES3_HMAC_SHA1)
+               out5->enctype = ENCTYPE_DES3_CBC_RAW;
+       }
     }
-    krb5_free_keyblock_contents(kdc_context, &out5);
     return(retval);
 }
 
@@ -372,13 +397,16 @@ int compat_decrypt_key (in5, out4)
 #define MIN5 300
 #define HR21 255
 
-int
-kerb_get_principal(name, inst, principal, maxn, more)
+static int
+kerb_get_principal(name, inst, principal, maxn, more, k5key, kvno, issrv)
     char   *name;               /* could have wild card */
     char   *inst;               /* could have wild card */
     Principal *principal;
     int maxn;          /* max number of name structs to return */
     int    *more;               /* more tuples than room for */
+    krb5_keyblock *k5key;
+    krb5_kvno kvno;
+    int issrv;                 /* true if retrieving a service key */
 {
     /* Note that this structure should not be passed to the
        krb5_free* functions, because the pointers within it point
@@ -430,27 +458,52 @@ kerb_get_principal(name, inst, principal, maxn, more)
         return(nprinc);
     } 
 
-    if (krb5_dbe_find_enctype(kdc_context,
-                              &entries,
-                              ENCTYPE_DES_CBC_CRC,
-                              KRB5_KDB_SALTTYPE_V4,
-                              -1,
-                              &pkey) &&
-       krb5_dbe_find_enctype(kdc_context,
-                              &entries,
-                              ENCTYPE_DES_CBC_CRC,
-                              -1,
-                              -1,
-                              &pkey))
-    {
-       lt = klog(L_KRB_PERR, "KDC V4: principal %s.%s isn't V4 compatible",
-                 name, inst);
-       krb5_db_free_principal(kdc_context, &entries, nprinc);
-       return(0);
+    if (!issrv) {
+       if (krb5_dbe_find_enctype(kdc_context,
+                                 &entries,
+                                 ENCTYPE_DES_CBC_CRC,
+                                 KRB5_KDB_SALTTYPE_V4,
+                                 kvno,
+                                 &pkey) &&
+           krb5_dbe_find_enctype(kdc_context,
+                                 &entries,
+                                 ENCTYPE_DES_CBC_CRC,
+                                 -1,
+                                 kvno,
+                                 &pkey)) {
+           lt = klog(L_KRB_PERR,
+                     "KDC V4: principal %s.%s isn't V4 compatible",
+                     name, inst);
+           krb5_db_free_principal(kdc_context, &entries, nprinc);
+           return(0);
+       }
+    } else {
+       /* XXX yes I know this is a hardcoded search order */
+       if (krb5_dbe_find_enctype(kdc_context, &entries,
+                                 ENCTYPE_DES3_CBC_RAW,
+                                 -1, kvno, &pkey) &&
+           krb5_dbe_find_enctype(kdc_context, &entries,
+                                 ENCTYPE_LOCAL_DES3_HMAC_SHA1,
+                                 -1, kvno, &pkey) &&
+           krb5_dbe_find_enctype(kdc_context, &entries,
+                                 ENCTYPE_DES3_HMAC_SHA1,
+                                 -1, kvno, &pkey) &&
+           krb5_dbe_find_enctype(kdc_context, &entries,
+                                 ENCTYPE_DES_CBC_CRC,
+                                 KRB5_KDB_SALTTYPE_V4, kvno, &pkey) &&
+           krb5_dbe_find_enctype(kdc_context, &entries,
+                                 ENCTYPE_DES_CBC_CRC,
+                                 -1, kvno, &pkey)) {
+           lt = klog(L_KRB_PERR,
+                     "KDC V4: failed to find key for %s.%s",
+                     name, inst);
+           krb5_db_free_principal(kdc_context, &entries, nprinc);
+           return(0);
+       }
     }
 
-    if (! compat_decrypt_key( pkey, k)) {
-       memcpy( &principal->key_low,           k,     LONGLEN);
+    if (!compat_decrypt_key(pkey, k, k5key, issrv)) {
+       memcpy( &principal->key_low, k, LONGLEN);
                memcpy( &principal->key_high, (krb5_ui_4 *) k + 1, LONGLEN);
     }
     /* convert v5's entries struct to v4's Principal struct:
@@ -550,7 +603,11 @@ kerberos_v4(client, pkt)
     Key_schedule key_s;
     char   *ptr;
 
+    krb5_keyblock k5key;
+    krb5_kvno kvno;
+
 
+    k5key.contents = NULL;     /* in case we have to free it */
 
     ciph->length = 0;
 
@@ -639,11 +696,14 @@ kerberos_v4(client, pkt)
               inet_ntoa(client_host), req_name_ptr, req_inst_ptr, 0);
 
            if ((i = check_princ(req_name_ptr, req_inst_ptr, 0,
-                                &a_name_data))) {
+                                &a_name_data, &k5key, 0))) {
                kerb_err_reply(client, pkt, i, lt);
                a_name_data.key_low = a_name_data.key_high = 0;
+               krb5_free_keyblock_contents(kdc_context, &k5key);
                return;
            }
+           /* don't use k5key for client */
+           krb5_free_keyblock_contents(kdc_context, &k5key);
            tk->length = 0;     /* init */
            if (strcmp(service, "krbtgt"))
                klog(L_NTGT_INTK,
@@ -651,10 +711,11 @@ kerberos_v4(client, pkt)
                    req_inst_ptr, service, instance, 0);
            /* this does all the checking */
            if ((i = check_princ(service, instance, lifetime,
-                                &s_name_data))) {
+                                &s_name_data, &k5key, 1))) {
                kerb_err_reply(client, pkt, i, lt);
                a_name_data.key_high = a_name_data.key_low = 0;
                s_name_data.key_high = s_name_data.key_low = 0;
+               krb5_free_keyblock_contents(kdc_context, &k5key);
                return;
            }
            /* Bound requested lifetime with service and user */
@@ -675,10 +736,22 @@ kerberos_v4(client, pkt)
            kdb_encrypt_key(key, key, master_key,
                            master_key_schedule, DECRYPT);
            /* construct and seal the ticket */
-           krb_create_ticket(tk, k_flags, a_name_data.name,
-               a_name_data.instance, local_realm,
-                client_host.s_addr, (char *) session_key, lifetime, kerb_time.tv_sec,
-                        s_name_data.name, s_name_data.instance, key);
+           if (K4KDC_ENCTYPE_OK(k5key.enctype)) {
+               krb_create_ticket(tk, k_flags, a_name_data.name,
+                                 a_name_data.instance, local_realm,
+                                 client_host.s_addr, (char *) session_key,
+                                 lifetime, kerb_time.tv_sec,
+                                 s_name_data.name, s_name_data.instance,
+                                 key);
+           } else {
+               krb_cr_tkt_krb5(tk, k_flags, a_name_data.name,
+                               a_name_data.instance, local_realm,
+                               client_host.s_addr, (char *) session_key,
+                               lifetime, kerb_time.tv_sec,
+                               s_name_data.name, s_name_data.instance,
+                               &k5key);
+           }
+           krb5_free_keyblock_contents(kdc_context, &k5key);
            memset(key, 0, sizeof(key));
            memset(key_s, 0, sizeof(key_s));
 
@@ -737,14 +810,15 @@ kerberos_v4(client, pkt)
            memcpy(auth->dat, pkt->dat, auth->length);
 
            strncpy(tktrlm, (char *)auth->dat + 3, REALM_SZ);
-           if (set_tgtkey(tktrlm)) {
+           kvno = (krb5_kvno)auth->dat[2];
+           if (set_tgtkey(tktrlm, kvno)) {
                lt = klog(L_ERR_UNK,
-                   "FAILED realm %s unknown. Host: %s ",
-                         tktrlm, inet_ntoa(client_host));
+                         "FAILED set_tgtkey realm %s, kvno %d. Host: %s ",
+                         tktrlm, kvno, inet_ntoa(client_host));
                kerb_err_reply(client, pkt, kerno, lt);
                return;
            }
-           kerno = krb_rd_req(auth, "ktbtgt", tktrlm, client_host.s_addr,
+           kerno = krb_rd_req(auth, "krbtgt", tktrlm, client_host.s_addr,
                ad, 0);
 
            if (kerno) {
@@ -784,9 +858,11 @@ kerberos_v4(client, pkt)
                return;
            }
            kerno = check_princ(service, instance, req_life,
-               &s_name_data);
+                               &s_name_data, &k5key, 1);
            if (kerno) {
                kerb_err_reply(client, pkt, kerno, lt);
+               s_name_data.key_high = s_name_data.key_low = 0;
+               krb5_free_keyblock_contents(kdc_context, &k5key);
                return;
            }
            /* Bound requested lifetime with service and user */
@@ -910,18 +986,21 @@ static char *krb4_stime(t)
     return st;
 }
 
-int check_princ(p_name, instance, lifetime, p)
+static int
+check_princ(p_name, instance, lifetime, p, k5key, issrv)
     char   *p_name;
     char   *instance;
     unsigned lifetime;
 
     Principal *p;
+    krb5_keyblock *k5key;
+    int issrv;                 /* whether this is a server key */
 {
     static int n;
     static int more;
  /* long trans; */
 
-    n = kerb_get_principal(p_name, instance, p, 1, &more);
+    n = kerb_get_principal(p_name, instance, p, 1, &more, k5key, 0, issrv);
     klog(L_ALL_REQ,
         "Principal: \"%s\", Instance: \"%s\" Lifetime = %d n = %d",
         p_name, instance, lifetime, n, 0);
@@ -986,11 +1065,13 @@ int check_princ(p_name, instance, lifetime, p)
     }
 
     /* If the user's key is null, we want to return an error */
-    if ((p->key_low == 0) && (p->key_high == 0)) {
-       /* User has a null key */
-       lt = klog(L_ERR_NKY, "Null key \"%s\" \"%s\"", p_name,
-           instance, 0);
-       return KERB_ERR_NULL_KEY;
+    if (k5key->contents != NULL && K4KDC_ENCTYPE_OK(k5key->enctype)) {
+       if ((p->key_low == 0) && (p->key_high == 0)) {
+           /* User has a null key */
+           lt = klog(L_ERR_NKY, "Null key \"%s\" \"%s\"", p_name,
+                     instance, 0);
+           return KERB_ERR_NULL_KEY;
+       }
     }
     /* make sure the service hasn't expired */
     if (((u_long) p->exp_date != 0)&&
@@ -1007,31 +1088,44 @@ int check_princ(p_name, instance, lifetime, p)
 
 
 /* Set the key for krb_rd_req so we can check tgt */
-int set_tgtkey(r)
+static int
+set_tgtkey(r, kvno)
     char   *r;                 /* Realm for desired key */
+    krb5_kvno kvno;
 {
     int     n;
     static char lastrealm[REALM_SZ] = "";
+    static int last_kvno = 0;
     Principal p_st;
     Principal *p = &p_st;
     C_Block key;
+    krb5_keyblock k5key;
 
-    if (!strcmp(lastrealm, r))
+    k5key.contents = NULL;
+    if (!strcmp(lastrealm, r) && last_kvno == kvno)
        return (KSUCCESS);
 
 /*  log("Getting key for %s", r); */
 
-    n = kerb_get_principal("krbtgt", r, p, 1, &more);
+    n = kerb_get_principal("krbtgt", r, p, 1, &more, &k5key, kvno, 1);
     if (n == 0)
        return (KFAILURE);
 
-    /* unseal tgt key from master key */
-    memcpy(key,                &p->key_low,  4);
-    memcpy(((krb5_ui_4 *) key) + 1, &p->key_high, 4);
-    kdb_encrypt_key(key, key, master_key,
-                   master_key_schedule, DECRYPT);
-    krb_set_key((char *) key, 0);
-    strcpy(lastrealm, r);
+    if (!K4KDC_ENCTYPE_OK(k5key.enctype)) {
+       krb_set_key_krb5(kdc_context, &k5key);
+       strcpy(lastrealm, r);
+       last_kvno = kvno;
+    } else {
+       /* unseal tgt key from master key */
+       memcpy(key,                &p->key_low,  4);
+       memcpy(((krb5_ui_4 *) key) + 1, &p->key_high, 4);
+       kdb_encrypt_key(key, key, master_key,
+                       master_key_schedule, DECRYPT);
+       krb_set_key((char *) key, 0);
+       strcpy(lastrealm, r);
+       last_kvno = kvno;
+    }
+    krb5_free_keyblock_contents(kdc_context, &k5key);
     return (KSUCCESS);
 }
 
index 4524c00f4ec87fb3f62d0ff1472cf5d1c42ae5df..a8f4233beb6206d40f77483c8aa313d8689cfdad 100644 (file)
@@ -166,8 +166,6 @@ finish_realm(rdp)
            memset(rdp->realm_tgskey.contents, 0, rdp->realm_tgskey.length);
            free(rdp->realm_tgskey.contents);
        }
-       if (rdp->realm_encblock.crypto_entry)
-               krb5_finish_key(rdp->realm_context, &rdp->realm_encblock);
        krb5_db_fini(rdp->realm_context);
        if (rdp->realm_tgsprinc)
            krb5_free_principal(rdp->realm_context, rdp->realm_tgsprinc);
@@ -326,17 +324,11 @@ init_realm(progname, rdp, realm, def_dbname, def_mpname,
        goto whoops;
     }
 
-    /* Select the specified encryption type */
-    /* krb5_db_fetch_mkey will setup the encblock for stashed keys */
-    if (manual)
-       krb5_use_enctype(rdp->realm_context, &rdp->realm_encblock, 
-                        rdp->realm_mkey.enctype);
-    
     /*
      * Get the master key.
      */
     if ((kret = krb5_db_fetch_mkey(rdp->realm_context, rdp->realm_mprinc,
-                                  &rdp->realm_encblock, manual,
+                                  rdp->realm_mkey.enctype, manual,
                                   FALSE, rdp->realm_stash,
                                   0, &rdp->realm_mkey))) {
        com_err(progname, kret,
@@ -363,8 +355,7 @@ init_realm(progname, rdp, realm, def_dbname, def_mpname,
     /* Verify the master key */
     if ((kret = krb5_db_verify_master_key(rdp->realm_context,
                                          rdp->realm_mprinc,
-                                         &rdp->realm_mkey,
-                                         &rdp->realm_encblock))) {
+                                         &rdp->realm_mkey))) {
        com_err(progname, kret,
                "while verifying master key for realm %s", realm);
        goto whoops;
@@ -415,17 +406,7 @@ init_realm(progname, rdp, realm, def_dbname, def_mpname,
     rdp->realm_mkvno = kdata->key_data_kvno;
     krb5_db_free_principal(rdp->realm_context, &db_entry, num2get);
 
-    /* Now preprocess the master key */
-    if ((kret = krb5_process_key(rdp->realm_context,
-                                &rdp->realm_encblock,
-                                &rdp->realm_mkey))) {
-       com_err(progname, kret,
-               "while processing master key for realm %s", realm);
-       goto whoops;
-    }
-
-    if ((kret = krb5_db_set_mkey(rdp->realm_context, 
-                                &rdp->realm_encblock))) {
+    if ((kret = krb5_db_set_mkey(rdp->realm_context, &rdp->realm_mkey))) {
        com_err(progname, kret,
                "while setting master key for realm %s", realm);
        goto whoops;
@@ -491,7 +472,7 @@ init_realm(progname, rdp, realm, def_dbname, def_mpname,
        goto whoops;
     }
     if (!(kret = krb5_dbekd_decrypt_key_data(rdp->realm_context,
-                                            &rdp->realm_encblock,
+                                            &rdp->realm_mkey,
                                             kdata,
                                             &rdp->realm_tgskey, NULL))){
        rdp->realm_tgskvno = kdata->key_data_kvno;
@@ -506,45 +487,40 @@ init_realm(progname, rdp, realm, def_dbname, def_mpname,
     }
 
     if (!rkey_init_done) {
-       krb5_enctype enctype;
-       krb5_encrypt_block temp_eblock;
+       krb5_timestamp now;
+       krb5_data seed;
 #ifdef KRB5_KRB4_COMPAT
-       krb5_keyblock *temp_key;
+       krb5_keyblock temp_key;
 #endif
        /*
         * If all that worked, then initialize the random key
         * generators.
         */
-       for (enctype = 0; enctype <= krb5_max_enctype; enctype++) {
-           if (krb5_enctype_array[enctype] &&
-               !krb5_enctype_array[enctype]->random_sequence) {
-               krb5_use_enctype(rdp->realm_context, &temp_eblock, enctype);
-               if ((kret = krb5_init_random_key(
-                        rdp->realm_context, &temp_eblock,
-                        &rdp->realm_mkey,
-                       &krb5_enctype_array[enctype]->random_sequence))) {
-                   com_err(progname, kret, 
-                           "while setting up random key generator for enctype %d--enctype disabled",
-                           enctype);
-                   krb5_enctype_array[enctype] = 0;
-               } else {
+
+       if ((kret = krb5_timeofday(rdp->realm_context, &now)))
+           goto whoops;
+       seed.length = sizeof(now);
+       seed.data = (char *) &now;
+       if ((kret = krb5_c_random_seed(rdp->realm_context, &seed)))
+           goto whoops;
+
+       seed.length = rdp->realm_mkey.length;
+       seed.data = rdp->realm_mkey.contents;
+
+       if ((kret = krb5_c_random_seed(rdp->realm_context, &seed)))
+           goto whoops;
+
 #ifdef KRB5_KRB4_COMPAT
-                   if (enctype == ENCTYPE_DES_CBC_CRC) {
-                       if ((kret = krb5_random_key(
-                           rdp->realm_context, &temp_eblock,
-                               krb5_enctype_array[enctype]->random_sequence,
-                               &temp_key)))
-                           com_err(progname, kret,
-                                   "while initializing V4 random key generator");
-                       else {
-                           (void) des_init_random_number_generator(temp_key->contents);
-                           krb5_free_keyblock(rdp->realm_context, temp_key);
-                       }
-                   }
-#endif
-               }
-           }
+       if ((kret = krb5_c_make_random_key(rdp->realm_context,
+                                          ENCTYPE_DES_CBC_CRC, &temp_key))) {
+           com_err(progname, kret,
+                   "while initializing V4 random key generator");
+           goto whoops;
        }
+
+       (void) des_init_random_number_generator(temp_key.contents);
+       krb5_free_keyblock_contents(rdp->realm_context, &temp_key);
+#endif
        rkey_init_done = 1;
     }
  whoops:
index e68edba1fa2b8620e41acef0108a9fe1b32ac502..40ef10cd172a5fade7287a3ea180eb49aeea5e2e 100644 (file)
@@ -1,3 +1,26 @@
+Tue Sep  1 19:35:44 1998  Tom Yu  <tlyu@mit.edu>
+
+       * cnv_tkt_skey.c (krb524_convert_tkt_skey): Add
+       ENCTYPE_LOCAL_DES3_HMAC_SHA1 to the list of enctypes to bash.
+
+       * krb524d.c (do_connection): Add ENCTYPE_LOCAL_DES3_HMAC_SHA1 to
+       the list of enctypes to search.
+
+Wed Aug 19 13:40:28 1998  Tom Yu  <tlyu@mit.edu>
+
+       * cnv_tkt_skey.c (krb524_convert_tkt_skey): Call krb_cr_tkt_krb5
+       if necessary, depending on th enctype.  Force enctype to be raw
+       DES3 if it's another DES3 type.
+
+       * krb524d.c (kdc_get_server_key): Add integer kvno argument,
+       rename previous kvno arg as kvnop, to distinguish returned (found)
+       kvno from the input kvno.
+       (lookup_service_key): Add kvnop argument to allow for returned
+       kvno.
+       (do_connection): Search for DES3 keys as well as DES.  Get the
+       found kvno as well, and use that instead of the kvno of the
+       incoming ticket.
+
 Fri Jul 24 19:38:58 1998  Geoffrey King  <gjking@mit.edu>
 
        * krb524d.c (main): Fork into the background by default, also
index df270776ab802638d7bab45950491dabfa2f4f26..4c51b6777fac2bde932d02c3a16112ffbfe0399f 100644 (file)
@@ -154,19 +154,39 @@ int krb524_convert_tkt_skey(context, v5tkt, v4tkt, v5_skey, v4_skey,
               (long) lifetime);
 
      /* XXX are there V5 flags we should map to V4 equivalents? */
-     ret = krb_create_ticket(v4tkt,
-                            0, /* flags */                          
-                            pname,
-                            pinst,
-                            prealm,
-                            *((unsigned long *)kaddr.contents),
-                            (char *) v5etkt->session->contents,
-                            lifetime,
-                            /* issue_data */
-                            server_time,
-                            sname,
-                            sinst,
-                            v4_skey->contents);
+     if (v4_skey->enctype == ENCTYPE_DES_CBC_CRC) {
+        ret = krb_create_ticket(v4tkt,
+                                0, /* flags */                      
+                                pname,
+                                pinst,
+                                prealm,
+                                *((unsigned long *)kaddr.contents),
+                                (char *) v5etkt->session->contents,
+                                lifetime,
+                                /* issue_data */
+                                server_time,
+                                sname,
+                                sinst,
+                                v4_skey->contents);
+     } else {
+        /* Force enctype to be raw if using DES3. */
+        if (v4_skey->enctype == ENCTYPE_DES3_HMAC_SHA1 ||
+            v4_skey->enctype == ENCTYPE_LOCAL_DES3_HMAC_SHA1)
+            v4_skey->enctype = ENCTYPE_DES3_CBC_RAW;
+        ret = krb_cr_tkt_krb5(v4tkt,
+                              0, /* flags */                        
+                              pname,
+                              pinst,
+                              prealm,
+                              *((unsigned long *)kaddr.contents),
+                              (char *) v5etkt->session->contents,
+                              lifetime,
+                              /* issue_data */
+                              server_time,
+                              sname,
+                              sinst,
+                              v4_skey);
+     }
 
      krb5_free_enc_tkt_part(context, v5etkt);
      v5tkt->enc_part2 = NULL;
index f72726fff358e085c4bc68b1afa37111e23c9f4f..1afeec2dce4cb90fdad05586e6e4b4451a75460b 100644 (file)
@@ -253,6 +253,7 @@ krb5_error_code do_connection(s, context)
      krb5_data msgdata, tktdata;
      char msgbuf[MSGSIZE], tktbuf[TKT_BUFSIZ], *p;
      int n, ret, saddrlen;
+     krb5_kvno v4kvno;
 
      /* Clear out keyblock contents so we don't accidentally free the stack.*/
      v5_service_key.contents = v4_service_key.contents = 0;
@@ -292,14 +293,28 @@ krb5_error_code do_connection(s, context)
          printf("V5 ticket decoded\n");
      
      if ((ret = lookup_service_key(context, v5tkt->server,
-                                  v5tkt->enc_part.enctype, 
-                                  &v5_service_key)))
+                                  v5tkt->enc_part.enctype,
+                                  v5tkt->enc_part.kvno,
+                                  &v5_service_key, NULL)))
          goto error;
 
      if ((ret = lookup_service_key(context, v5tkt->server,
+                                  ENCTYPE_DES3_CBC_RAW,
+                                  0, /* highest kvno */
+                                  &v4_service_key, &v4kvno)) &&
+        (ret = lookup_service_key(context, v5tkt->server,
+                                  ENCTYPE_LOCAL_DES3_HMAC_SHA1,
+                                  0,
+                                  &v4_service_key, &v4kvno)) &&
+        (ret = lookup_service_key(context, v5tkt->server,
+                                  ENCTYPE_DES3_HMAC_SHA1,
+                                  0,
+                                  &v4_service_key, &v4kvno)) &&
+        (ret = lookup_service_key(context, v5tkt->server,
                                   ENCTYPE_DES_CBC_CRC,
-                                  &v4_service_key)))
-         goto error;
+                                  0,
+                                  &v4_service_key, &v4kvno)))
+        goto error;
 
      if (debug)
          printf("service key retrieved\n");
@@ -334,7 +349,7 @@ error:
      if (ret)
          goto write_msg;
 
-     n = htonl(v5tkt->enc_part.kvno);
+     n = htonl(v4kvno);
      memcpy(p, (char *) &n, sizeof(int));
      p += sizeof(int);
      msgdata.length += sizeof(int);
@@ -363,32 +378,35 @@ write_msg:
      return ret;
 }
 
-krb5_error_code lookup_service_key(context, p, ktype, key)
+krb5_error_code lookup_service_key(context, p, ktype, kvno, key, kvnop)
      krb5_context context;
      krb5_principal p;
      krb5_enctype ktype;
+     krb5_kvno kvno;
      krb5_keyblock *key;
+     krb5_kvno *kvnop;
 {
      int ret;
      krb5_keytab_entry entry;
 
      if (use_keytab) {
-         if ((ret = krb5_kt_get_entry(context, kt, p, 0, ktype, &entry)))
+         if ((ret = krb5_kt_get_entry(context, kt, p, kvno, ktype, &entry)))
               return ret;
          memcpy(key, (char *) &entry.key, sizeof(krb5_keyblock));
          return 0;
      } else if (use_master) {
-         return kdc_get_server_key(context, p, key, NULL, ktype);
+         return kdc_get_server_key(context, p, key, kvnop, ktype, kvno);
      }
      return 0;
 }
 
-krb5_error_code kdc_get_server_key(context, service, key, kvno, ktype)
+krb5_error_code kdc_get_server_key(context, service, key, kvnop, ktype, kvno)
     krb5_context context;
     krb5_principal service;
     krb5_keyblock *key;
-    krb5_kvno *kvno;
+    krb5_kvno *kvnop;
     krb5_enctype ktype;
+    krb5_kvno kvno;
 {
     krb5_error_code ret;
     kadm5_principal_ent_rec server;
@@ -409,14 +427,14 @@ krb5_error_code kdc_get_server_key(context, service, key, kvno, ktype)
                                 ktype,
                                 (ktype == ENCTYPE_DES_CBC_CRC) ? 
                                 KRB5_KDB_SALTTYPE_V4 : -1,
-                                -1,
-                                key, NULL, kvno)) &&
+                                kvno,
+                                key, NULL, kvnop)) &&
        (ret = kadm5_decrypt_key(handle,
                                 &server,
                                 ktype,
                                 -1,
-                                -1,
-                                key, NULL, kvno))) {
+                                kvno,
+                                key, NULL, kvnop))) {
         kadm5_free_principal_ent(handle, &server);
         return (KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN);
     }
index dd0e7b56113739e65c1cd3489a755c4d684f480e..566afc88f3547a80b7244f28c9edb17b7c9677a9 100644 (file)
@@ -1,3 +1,34 @@
+Tue Sep 22 21:19:01 1998  Tom Yu  <tlyu@mit.edu>
+
+       * prng.c (krb5_c_random_make_octets): Fix to nfold into 15 bytes,
+       not one byte.
+
+Mon Sep 21 15:23:19 1998  Tom Yu  <tlyu@mit.edu>
+
+       * prng.c (krb5_c_random_seed): Fix memory leak.
+
+Mon Sep 14 23:21:17 1998  Tom Yu  <tlyu@mit.edu>
+
+       * old/decrypt.c (krb5_old_decrypt): Fix memory leak.
+
+Tue Sep  1 19:33:38 1998  Tom Yu  <tlyu@mit.edu>
+
+       * etypes.c: Add ETYPE_LOCAL_DES3_HMAC_SHA1 to deal with marc's
+       des3 code.  ETYPE_DES3_HMAC_SHA1 remains the same for now.
+
+Mon Aug 17 23:40:11 1998  Tom Yu  <tlyu@mit.edu>
+
+       * keyhash_provider/k5_md4des.c (k5_md4des_verify): Add
+       compatibility for krb5-beta5 checksums.
+
+       * keyhash_provider/k5_md5des.c (k5_md5des_verify): Add
+       compatibility for krb5-beta5 checksums.  Fix typos similar to
+       those corrected in k5_md4des.c.
+
+Sun Jul 19 12:00:00 1998  Marc Horowitz <marc@mit.edu>
+
+       * *.c: replace the crypto layer.
+
 Wed Apr 15 18:02:44 1998  Tom Yu  <tlyu@mit.edu>
 
        * Makefile.in (LIB): Rename to k5crypto.
index 468818cb800f5ab44ae133ed52a9325c45eadc52..48d035a78bc92758917569a5e02d7c0b77ae5c23 100644 (file)
@@ -1,7 +1,10 @@
 thisconfigdir=.
 BUILDTOP=$(REL)$(U)$(S)$(U)
-LOCAL_SUBDIRS=des crc32 md4 md5 sha os
-CFLAGS = $(CCOPTS) $(DEFS) -I$(srcdir)/crc32 -I$(srcdir)/des -I$(srcdir)/md4 -I$(srcdir)/md5 -I$(srcdir)/sha
+LOCAL_SUBDIRS=crc32 des dk enc_provider hash_provider keyhash_provider \
+       md4 md5 old raw sha1
+CFLAGS = $(CCOPTS) $(DEFS) -I$(srcdir)/enc_provider \
+       -I$(srcdir)/hash_provider -I$(srcdir)/keyhash_provider \
+       -I$(srcdir)/old -I$(srcdir)/raw -I$(srcdir)/dk
 
 ##DOSBUILDTOP = ..\..
 ##DOSLIBNAME=crypto.lib
@@ -9,37 +12,102 @@ CFLAGS = $(CCOPTS) $(DEFS) -I$(srcdir)/crc32 -I$(srcdir)/des -I$(srcdir)/md4 -I$
 ##DOSOBJFILELIST=@crypto.lst @des.lst @md4.lst @md5.lst @sha.lst @crc32.lst @os.lst
 ##DOSOBJFILEDEP =crypto.lst des.lst md4.lst md5.lst sha.lst crc32.lst os.lst
 
-MAC_SUBDIRS = des sha md4 md5 crc32 os
-
-OBJS=  cryptoconf.$(OBJEXT) \
-       encrypt_data.$(OBJEXT) \
-       krb5_glue.$(OBJEXT) \
-       decrypt_data.$(OBJEXT) \
-       des_crc.$(OBJEXT) \
-       des_md5.$(OBJEXT) \
-       des3_sha.$(OBJEXT) \
-       des3_raw.$(OBJEXT) \
-       raw_des.$(OBJEXT)
-
-SRCS=  $(srcdir)/cryptoconf.c \
-       $(srcdir)/encrypt_data.c \
-       $(srcdir)/krb5_glue.c \
-       $(srcdir)/decrypt_data.c \
-       $(srcdir)/des_crc.c \
-       $(srcdir)/des_md5.c \
-       $(srcdir)/des3_sha.c \
-       $(srcdir)/des3_raw.c \
-       $(srcdir)/raw_des.c 
+MAC_SUBDIRS = crc32 des dk enc_provider hash_provider keyhash_provider \
+       md4 md5 old raw sha1
+
+PROG_LIBPATH=-L$(TOPLIBD)
+PROG_RPATH=$(KRB5_LIBDIR)
+
+STLIBOBJS=\
+       block_size.o            \
+       checksum_length.o       \
+       cksumtype_to_string.o   \
+       cksumtypes.o            \
+       coll_proof_cksum.o      \
+       decrypt.o               \
+       encrypt.o               \
+       encrypt_length.o        \
+       enctype_compare.o       \
+       enctype_to_string.o     \
+       etypes.o                \
+       hmac.o                  \
+       keyed_cksum.o           \
+       keyed_checksum_types.o  \
+       make_checksum.o         \
+       make_random_key.o       \
+       nfold.o                 \
+       old_api_glue.o          \
+       prng.o                  \
+       string_to_cksumtype.o   \
+       string_to_enctype.o     \
+       string_to_key.o         \
+       valid_cksumtype.o       \
+       valid_enctype.o         \
+       verify_checksum.o
+
+OBJS=\
+       block_size.$(OBJEXT)            \
+       checksum_length.$(OBJEXT)       \
+       cksumtype_to_string.$(OBJEXT)   \
+       cksumtypes.$(OBJEXT)            \
+       coll_proof_cksum.$(OBJEXT)      \
+       decrypt.$(OBJEXT)               \
+       encrypt.$(OBJEXT)               \
+       encrypt_length.$(OBJEXT)        \
+       enctype_compare.$(OBJEXT)       \
+       enctype_to_string.$(OBJEXT)     \
+       etypes.$(OBJEXT)                \
+       hmac.$(OBJEXT)                  \
+       keyed_cksum.$(OBJEXT)           \
+       keyed_checksum_types.$(OBJEXT)  \
+       make_checksum.$(OBJEXT)         \
+       make_random_key.$(OBJEXT)       \
+       nfold.$(OBJEXT)                 \
+       old_api_glue.$(OBJEXT)          \
+       prng.$(OBJEXT)                  \
+       string_to_cksumtype.$(OBJEXT)   \
+       string_to_enctype.$(OBJEXT)     \
+       string_to_key.$(OBJEXT)         \
+       valid_cksumtype.$(OBJEXT)       \
+       valid_enctype.$(OBJEXT)         \
+       verify_checksum.$(OBJEXT)
+
+SRCS=\
+       $(subdir)/block_size.c          \
+       $(subdir)/checksum_length.c     \
+       $(subdir)/cksumtype_to_string.c \
+       $(subdir)/cksumtypes.c          \
+       $(subdir)/coll_proof_cksum.c    \
+       $(subdir)/decrypt.c             \
+       $(subdir)/encrypt.c             \
+       $(subdir)/encrypt_length.c      \
+       $(subdir)/enctype_compare.c     \
+       $(subdir)/enctype_to_string.c   \
+       $(subdir)/etypes.c              \
+       $(subdir)/hmac.c                \
+       $(subdir)/keyed_cksum.c         \
+       $(subdir)/keyed_checksum_types.c\
+       $(subdir)/make_checksum.c       \
+       $(subdir)/make_random_key.c     \
+       $(subdir)/nfold.c               \
+       $(subdir)/old_api_glue.c        \
+       $(subdir)/prng.c                \
+       $(subdir)/string_to_cksumtype.c \
+       $(subdir)/string_to_enctype.c   \
+       $(subdir)/string_to_key.c       \
+       $(subdir)/valid_cksumtype.c     \
+       $(subdir)/valid_enctype.c       \
+       $(subdir)/verify_checksum.c
+
 
 LIB=k5crypto
 LIBMAJOR=2
-LIBMINOR=0
+LIBMINOR=1
 RELDIR=crypto
-STLIBOBJS=cryptoconf.o encrypt_data.o decrypt_data.o \
-       des_crc.o des_md5.o des3_sha.o des3_raw.o raw_des.o krb5_glue.o
 
-STOBJLISTS=des/OBJS.ST md4/OBJS.ST md5/OBJS.ST sha/OBJS.ST crc32/OBJS.ST \
-       os/OBJS.ST OBJS.ST
+STOBJLISTS=crc32/OBJS.ST des/OBJS.ST dk/OBJS.ST enc_provider/OBJS.ST \
+       hash_provider/OBJS.ST keyhash_provider/OBJS.ST md4/OBJS.ST \
+       md5/OBJS.ST old/OBJS.ST raw/OBJS.ST sha1/OBJS.ST OBJS.ST
 
 # No dependencies.  Record places to find this shared object if the target
 # link editor and loader support it.
@@ -58,7 +126,14 @@ libcrypto.lib:
 
 clean-unix:: clean-liblinks clean-libs clean-libobjs
 
-check-unix::
+check-unix:: t_nfold
+       $(RUN_SETUP) ./t_nfold
+
+t_nfold$(EXEEXT): t_nfold.$(OBJEXT) nfold.$(OBJEXT)
+       $(CC_LINK) -o $@ t_nfold.$(OBJEXT) nfold.$(OBJEXT)
+
+clean::
+       $(RM) t_nfold.o t_nfold
 
 all-windows::
        cd crc32
@@ -67,61 +142,101 @@ all-windows::
        cd ..\des
        @echo Making in crypto\des
        -$(MAKE) -$(MFLAGS)
+       cd ..\dk
+       @echo Making in crypto\dk
+       -$(MAKE) -$(MFLAGS)
+       cd ..\enc_provider
+       @echo Making in crypto\enc_provider
+       -$(MAKE) -$(MFLAGS)
+       cd ..\hash_provider
+       @echo Making in crypto\hash_provider
+       -$(MAKE) -$(MFLAGS)
+       cd ..\keyhash_provider
+       @echo Making in crypto\keyhash_provider
+       -$(MAKE) -$(MFLAGS)
        cd ..\md4
        @echo Making in crypto\md4
        -$(MAKE) -$(MFLAGS)
-       cd ..\os
-       @echo Making in crypto\os
-       -$(MAKE) -$(MFLAGS)
        cd ..\md5
        @echo Making in crypto\md5
        -$(MAKE) -$(MFLAGS)
-       cd ..\sha
-       @echo Making in crypto\sha
+       cd ..\old
+       @echo Making in crypto\old
+       -$(MAKE) -$(MFLAGS)
+       cd ..\raw
+       @echo Making in crypto\raw
+       -$(MAKE) -$(MFLAGS)
+       cd ..\sha1
+       @echo Making in crypto\sha1
        -$(MAKE) -$(MFLAGS)
-       cd ..
 
 clean-windows::
        cd crc32
-       @echo Making clean in crypto\crc32
+       @echo Making in clean crypto\crc32
        -$(MAKE) -$(MFLAGS) clean
        cd ..\des
        @echo Making clean in crypto\des
        -$(MAKE) -$(MFLAGS) clean
+       cd ..\dk
+       @echo Making clean in crypto\dk
+       -$(MAKE) -$(MFLAGS) clean
+       cd ..\enc_provider
+       @echo Making clean in crypto\enc_provider
+       -$(MAKE) -$(MFLAGS) clean
+       cd ..\hash_provider
+       @echo Making clean in crypto\hash_provider
+       -$(MAKE) -$(MFLAGS) clean
+       cd ..\keyhash_provider
+       @echo Making clean in crypto\keyhash_provider
+       -$(MAKE) -$(MFLAGS) clean
        cd ..\md4
        @echo Making clean in crypto\md4
        -$(MAKE) -$(MFLAGS) clean
        cd ..\md5
        @echo Making clean in crypto\md5
        -$(MAKE) -$(MFLAGS) clean
-       cd ..\sha
-       @echo Making clean in crypto\sha
+       cd ..\old
+       @echo Making clean in crypto\old
        -$(MAKE) -$(MFLAGS) clean
-       cd ..\os
-       @echo Making clean in crypto\os
+       cd ..\raw
+       @echo Making clean in crypto\raw
+       -$(MAKE) -$(MFLAGS) clean
+       cd ..\sha1
+       @echo Making clean in crypto\sha1
        -$(MAKE) -$(MFLAGS) clean
-       cd ..
-       @echo Making clean locally
 
 check-windows::
        cd crc32
-       @echo Making check in crypto\crc32
+       @echo Making in check crypto\crc32
        -$(MAKE) -$(MFLAGS) check
        cd ..\des
        @echo Making check in crypto\des
        -$(MAKE) -$(MFLAGS) check
+       cd ..\dk
+       @echo Making check in crypto\dk
+       -$(MAKE) -$(MFLAGS) check
+       cd ..\enc_provider
+       @echo Making check in crypto\enc_provider
+       -$(MAKE) -$(MFLAGS) check
+       cd ..\hash_provider
+       @echo Making check in crypto\hash_provider
+       -$(MAKE) -$(MFLAGS) check
+       cd ..\keyhash_provider
+       @echo Making check in crypto\keyhash_provider
+       -$(MAKE) -$(MFLAGS) check
        cd ..\md4
        @echo Making check in crypto\md4
        -$(MAKE) -$(MFLAGS) check
        cd ..\md5
        @echo Making check in crypto\md5
        -$(MAKE) -$(MFLAGS) check
-       cd ..\sha
-       @echo Making check in crypto\sha
+       cd ..\old
+       @echo Making check in crypto\old
        -$(MAKE) -$(MFLAGS) check
-       cd ..\os
-       @echo Making check in crypto\os
+       cd ..\raw
+       @echo Making check in crypto\raw
+       -$(MAKE) -$(MFLAGS) check
+       cd ..\sha1
+       @echo Making check in crypto\sha1
        -$(MAKE) -$(MFLAGS) check
-       cd ..
-
 
diff --git a/src/lib/crypto/block_size.c b/src/lib/crypto/block_size.c
new file mode 100644 (file)
index 0000000..de5c3ac
--- /dev/null
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 1998 by the FundsXpress, INC.
+ * 
+ * All rights reserved.
+ * 
+ * Export of this software from the United States of America may require
+ * a specific license from the United States Government.  It is the
+ * responsibility of any person or organization contemplating export to
+ * obtain such a license before exporting.
+ * 
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of FundsXpress. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  FundsXpress makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#include "k5-int.h"
+#include "etypes.h"
+
+KRB5_DLLIMP krb5_error_code KRB5_CALLCONV
+krb5_c_block_size(context, enctype, blocksize)
+     krb5_context context;
+     krb5_enctype enctype;
+     size_t *blocksize;
+{
+    int i;
+
+    for (i=0; i<krb5_enctypes_length; i++) {
+       if (krb5_enctypes_list[i].etype == enctype)
+           break;
+    }
+
+    if (i == krb5_enctypes_length)
+       return(KRB5_BAD_ENCTYPE);
+
+    (*(krb5_enctypes_list[i].enc->block_size))(blocksize);
+
+    return(0);
+}
diff --git a/src/lib/crypto/checksum_length.c b/src/lib/crypto/checksum_length.c
new file mode 100644 (file)
index 0000000..38773ca
--- /dev/null
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 1998 by the FundsXpress, INC.
+ * 
+ * All rights reserved.
+ * 
+ * Export of this software from the United States of America may require
+ * a specific license from the United States Government.  It is the
+ * responsibility of any person or organization contemplating export to
+ * obtain such a license before exporting.
+ * 
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of FundsXpress. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  FundsXpress makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#include "k5-int.h"
+#include "cksumtypes.h"
+
+krb5_error_code
+krb5_c_checksum_length(context, cksumtype, length)
+     krb5_context context;
+     krb5_cksumtype cksumtype;
+     size_t *length;
+{
+    int i;
+
+    for (i=0; i<krb5_cksumtypes_length; i++) {
+       if (krb5_cksumtypes_list[i].ctype == cksumtype)
+           break;
+    }
+
+    if (i == krb5_cksumtypes_length)
+       return(KRB5_BAD_ENCTYPE);
+
+    if (krb5_cksumtypes_list[i].keyhash)
+       (*(krb5_cksumtypes_list[i].keyhash->hash_size))(length);
+    else
+       (*(krb5_cksumtypes_list[i].hash->hash_size))(length);
+
+    return(0);
+}
+       
diff --git a/src/lib/crypto/cksumtype_to_string.c b/src/lib/crypto/cksumtype_to_string.c
new file mode 100644 (file)
index 0000000..21cc590
--- /dev/null
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 1998 by the FundsXpress, INC.
+ * 
+ * All rights reserved.
+ * 
+ * Export of this software from the United States of America may require
+ * a specific license from the United States Government.  It is the
+ * responsibility of any person or organization contemplating export to
+ * obtain such a license before exporting.
+ * 
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of FundsXpress. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  FundsXpress makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#include "k5-int.h"
+#include "cksumtypes.h"
+
+KRB5_DLLIMP krb5_error_code KRB5_CALLCONV
+krb5_cksumtype_to_string(cksumtype, buffer, buflen)
+    krb5_cksumtype     cksumtype;
+    char               FAR * buffer;
+    size_t             buflen;
+{
+    int i;
+
+    for (i=0; i<krb5_cksumtypes_length; i++) {
+       if (krb5_cksumtypes_list[i].ctype == cksumtype) {
+           if ((strlen(krb5_cksumtypes_list[i].out_string)+1) > buflen)
+               return(ENOMEM);
+
+           strcpy(buffer, krb5_cksumtypes_list[i].out_string);
+           return(0);
+       }
+    }
+
+    return(EINVAL);
+}
diff --git a/src/lib/crypto/cksumtypes.c b/src/lib/crypto/cksumtypes.c
new file mode 100644 (file)
index 0000000..8107d3b
--- /dev/null
@@ -0,0 +1,74 @@
+/*
+ * Copyright (C) 1998 by the FundsXpress, INC.
+ * 
+ * All rights reserved.
+ * 
+ * Export of this software from the United States of America may require
+ * a specific license from the United States Government.  It is the
+ * responsibility of any person or organization contemplating export to
+ * obtain such a license before exporting.
+ * 
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of FundsXpress. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  FundsXpress makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#include "k5-int.h"
+#include "hash_provider.h"
+#include "keyhash_provider.h"
+#include "cksumtypes.h"
+
+struct krb5_cksumtypes krb5_cksumtypes_list[] = {
+    { CKSUMTYPE_CRC32, KRB5_CKSUMFLAG_NOT_COLL_PROOF,
+      "crc32", "CRC-32",
+      0, NULL,
+      &krb5_hash_crc32 },
+
+    { CKSUMTYPE_RSA_MD4, 0,
+      "md4", "RSA-MD4",
+      0, NULL,
+      &krb5_hash_md4 },
+    { CKSUMTYPE_RSA_MD4_DES, 0,
+      "md4-des", "RSA-MD4 with DES cbc mode",
+      ENCTYPE_DES_CBC_CRC, &krb5_keyhash_md4des,
+      NULL },
+
+    { CKSUMTYPE_DESCBC, 0,
+      "des-cbc", "DES cbc mode",
+      ENCTYPE_DES_CBC_CRC, &krb5_keyhash_descbc,
+      NULL },
+
+    { CKSUMTYPE_RSA_MD5, 0,
+      "md5", "RSA-MD5",
+      0, NULL,
+      &krb5_hash_md5 },
+    { CKSUMTYPE_RSA_MD5_DES, 0,
+      "md5-des", "RSA-MD5 with DES cbc mode",
+      ENCTYPE_DES_CBC_CRC, &krb5_keyhash_md5des,
+      NULL },
+
+    { CKSUMTYPE_NIST_SHA, 0,
+      "sha", "NIST-SHA",
+      0, NULL,
+      &krb5_hash_sha1 },
+
+    { CKSUMTYPE_HMAC_SHA1, KRB5_CKSUMFLAG_DERIVE,
+      "hmac-sha1", "HMAC-SHA1",
+      0, NULL,
+      &krb5_hash_sha1 },
+};
+
+int krb5_cksumtypes_length =
+sizeof(krb5_cksumtypes_list)/sizeof(struct krb5_cksumtypes);
+
diff --git a/src/lib/crypto/cksumtypes.h b/src/lib/crypto/cksumtypes.h
new file mode 100644 (file)
index 0000000..900a7c8
--- /dev/null
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 1998 by the FundsXpress, INC.
+ * 
+ * All rights reserved.
+ * 
+ * Export of this software from the United States of America may require
+ * a specific license from the United States Government.  It is the
+ * responsibility of any person or organization contemplating export to
+ * obtain such a license before exporting.
+ * 
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of FundsXpress. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  FundsXpress makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#include "k5-int.h"
+
+extern struct krb5_cksumtypes krb5_cksumtypes_list[];
+extern int krb5_cksumtypes_length;
+
diff --git a/src/lib/crypto/coll_proof_cksum.c b/src/lib/crypto/coll_proof_cksum.c
new file mode 100644 (file)
index 0000000..07925c6
--- /dev/null
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 1998 by the FundsXpress, INC.
+ * 
+ * All rights reserved.
+ * 
+ * Export of this software from the United States of America may require
+ * a specific license from the United States Government.  It is the
+ * responsibility of any person or organization contemplating export to
+ * obtain such a license before exporting.
+ * 
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of FundsXpress. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  FundsXpress makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#include "k5-int.h"
+#include "cksumtypes.h"
+
+krb5_boolean is_coll_proof_cksum(ctype)
+     krb5_cksumtype ctype;
+{
+    int i;
+
+    for (i=0; i<krb5_cksumtypes_length; i++) {
+       if (krb5_cksumtypes_list[i].ctype == ctype)
+           return((krb5_cksumtypes_list[i].flags &
+                   KRB5_CKSUMFLAG_NOT_COLL_PROOF)?0:1);
+    }
+
+    /* ick, but it's better than coredumping, which is what the
+       old code would have done */
+    return(0);
+}
index 19688e35e6412bd3da9bf5735d382cdbdb317402..2fb1faffbfa4e54dacccb142e6be2342c27ae93b 100644 (file)
@@ -4,136 +4,22 @@ AC_PROG_ARCHIVE
 AC_PROG_ARCHIVE_ADD
 AC_PROG_RANLIB
 AC_PROG_INSTALL
-dnl
-dnl Determine which cryptosystems we are enabling
-dnl
-AC_ARG_ENABLE([des-cbc-md5],
-[ --enable-des-cbc-md5         enable DES_CBC_MD5 (DEFAULT).
- --disable-des-cbc-md5         disable DES_CBC_MD5.],
-,
-enableval=yes)dnl
-if test "$enableval" = yes; then
-       AC_MSG_RESULT(Enabling DES_CBC_MD5)
-       AC_DEFINE(PROVIDE_DES_CBC_MD5)
-else
-       AC_MSG_RESULT(Disabling DES_CBC_MD5)
-fi
-dnl AC_ARG_ENABLE([des3-cbc-sha],
-dnl [ --enable-des3-cbc-sha            enable DES3_CBC_SHA (DEFAULT).
-dnl  --disable-des3-cbc-sha            disable DES3_CBC_SHA.],
-dnl ,
-dnl enableval=yes)dnl
-dnl if test "$enableval" = yes; then
-dnl    AC_MSG_RESULT(Enabling DES3_CBC_SHA)
-dnl    AC_DEFINE(PROVIDE_DES3_CBC_SHA)
-dnl else
-dnl    AC_MSG_RESULT(Disabling DES3_CBC_SHA)
-dnl fi
-AC_ARG_WITH([des-cbc-crc],
-[ --enable-des-cbc-crc         enable DES_CBC_CRC (DEFAULT).
- --disable-des-cbc-crc         disable DES_CBC_CRC.],
-,
-enableval=yes)dnl
-if test "$enableval" = yes; then
-       AC_MSG_RESULT(Enabling DES_CBC_CRC)
-       AC_DEFINE(PROVIDE_DES_CBC_CRC)
-else
-       AC_MSG_RESULT(Disabling DES_CBC_CRC)
-fi
-AC_ARG_WITH([des-cbc-raw],
-[ --enable-des-cbc-raw         enable DES_CBC_RAW (DEFAULT).
- --disable-des-cbc-raw         disable DES_CBC_RAW.],
-,
-enableval=yes)dnl
-if test "$enableval" = yes; then
-       AC_MSG_RESULT(Enabling DES_CBC_RAW)
-       AC_DEFINE(PROVIDE_DES_CBC_RAW)
-else
-       AC_MSG_RESULT(Disabling DES_CBC_RAW)
-fi
-dnl AC_ARG_WITH([des3-cbc-raw],
-dnl [ --enable-des3-cbc-raw            enable DES3_CBC_RAW (DEFAULT).
-dnl  --disable-des3-cbc-raw            disable DES3_CBC_RAW.],
-dnl ,
-dnl enableval=yes)dnl
-dnl if test "$enableval" = yes; then
-dnl    AC_MSG_RESULT(Enabling DES3_CBC_RAW)
-dnl    AC_DEFINE(PROVIDE_DES3_CBC_RAW)
-dnl else
-dnl    AC_MSG_RESULT(Disabling DES3_CBC_RAW)
-dnl fi
-AC_ARG_WITH([des-cbc-cksum],
-[ --enable-des-cbc-cksum               enable DES_CBC_CKSUM (DEFAULT).
- --disable-des-cbc-cksum       disable DES_CBC_CKSUM.],
-,
-enableval=yes)dnl
-if test "$enableval" = yes; then
-       AC_MSG_RESULT(Enabling DES_CBC_CKSUM)
-       AC_DEFINE(PROVIDE_DES_CBC_CKSUM)
-else
-       AC_MSG_RESULT(Disabling DES_CBC_CKSUM)
-fi
-AC_ARG_WITH([crc32],
-[ --enable-crc32                       enable CRC32 (DEFAULT).
- --disable-crc32               disable CRC32.],
-,
-enableval=yes)dnl
-if test "$enableval" = yes; then
-       AC_MSG_RESULT(Enabling CRC32)
-       AC_DEFINE(PROVIDE_CRC32)
-else
-       AC_MSG_RESULT(Disabling CRC32)
-fi
-AC_ARG_WITH([rsa-md4],
-[ --enable-rsa-md4             enable RSA_MD4 (DEFAULT).
- --disable-rsa-md4             disable RSA_MD4.],
-,
-enableval=yes)dnl
-if test "$enableval" = yes; then
-       AC_MSG_RESULT(Enabling RSA_MD4)
-       AC_DEFINE(PROVIDE_RSA_MD4)
-else
-       AC_MSG_RESULT(Disabling RSA_MD4)
-fi
-AC_ARG_WITH([rsa-md5],
-[ --enable-rsa-md5             enable RSA_MD5 (DEFAULT).
- --disable-rsa-md5             disable RSA_MD5.],
-,
-enableval=yes)dnl
-if test "$enableval" = yes; then
-       AC_MSG_RESULT(Enabling RSA_MD5)
-       AC_DEFINE(PROVIDE_RSA_MD5)
-else
-       AC_MSG_RESULT(Disabling RSA_MD5)
-fi
-dnl AC_ARG_WITH([nist-sha],
-dnl [ --enable-nist-sha                enable NIST_SHA (DEFAULT).
-dnl  --disable-nist-sha                disable NIST_SHA.],
-dnl ,
-dnl enableval=yes)dnl
-dnl if test "$enableval" = yes; then
-dnl    AC_MSG_RESULT(Enabling NIST_SHA)
-dnl    AC_DEFINE(PROVIDE_NIST_SHA)
-dnl else
-dnl    AC_MSG_RESULT(Disabling NIST_SHA)
-dnl fi
-
-AC_REPLACE_FUNCS(memmove)
-AC_HAVE_FUNCS(srand48 srand srandom getpid)
-AC_CHECK_HEADERS(sys/types.h)
-AC_PROG_LN_S
-KRB5_SOCKADDR_SA_LEN
 
 KRB5_RUN_FLAGS
+KRB5_BUILD_PROGRAM
 KRB5_BUILD_LIBOBJS
 KRB5_BUILD_LIBRARY
-KRB5_BUILD_PROGRAM
 
 K5_GEN_MAKEFILE(., lib libobj)
 K5_GEN_MAKEFILE(crc32, libobj)
 K5_GEN_MAKEFILE(des, libobj)
+K5_GEN_MAKEFILE(dk, libobj)
+K5_GEN_MAKEFILE(enc_provider, libobj)
+K5_GEN_MAKEFILE(hash_provider, libobj)
+K5_GEN_MAKEFILE(keyhash_provider, libobj)
 K5_GEN_MAKEFILE(md4, libobj)
 K5_GEN_MAKEFILE(md5, libobj)
-K5_GEN_MAKEFILE(os, libobj)
-K5_GEN_MAKEFILE(sha, libobj)
+K5_GEN_MAKEFILE(old, libobj)
+K5_GEN_MAKEFILE(raw, libobj)
+K5_GEN_MAKEFILE(sha1, libobj)
 K5_AC_OUTPUT
index 1ee004262c11bf37a5763c67fed3bbcd133810c1..5f6e617cb9eeffa0fb849c7bb056d8ae273caa41 100644 (file)
@@ -1,3 +1,7 @@
+Sun Jul 19 12:00:00 1998  Marc Horowitz <marc@mit.edu>
+
+       * *.c: replace the crypto layer.
+
 Wed Feb 18 16:05:45 1998  Tom Yu  <tlyu@mit.edu>
 
        * Makefile.in: Remove trailing slash from thisconfigdir.  Fix up
index b1ad86bdd8d3e40caf0b7499aed1d6939cc870d9..97ab64cf04b6dd3492aa96370883dbbb42cecef5 100644 (file)
@@ -7,25 +7,23 @@ CFLAGS = $(CCOPTS) $(DEFS)
 ##DOS##OBJFILE=..\crc32.lst
 ##WIN16##LIBNAME=..\crypto.lib
 
-STLIBOBJS=crc.o
-OBJS=  crc.$(OBJEXT)
-SRCS=  $(srcdir)/crc.c
+PROG_LIBPATH=-L$(TOPLIBD)
+PROG_RPATH=$(KRB5_LIBDIR)
 
-##DOS##LIBOBJS = $(OBJS)
+RUN_SETUP = @KRB5_RUN_ENV@ KRB5_CONFIG=$(SRCTOP)/config-files/krb5.conf
 
-all-unix:: all-libobjs
+STLIBOBJS= crc32.o
+
+OBJS= crc32.$(OBJEXT) 
 
-crctest: crctest.$(OBJEXT) $(OBJS)
-       $(RM) crctest
-       $(CC) -o crctest crctest.$(OBJEXT) $(CFLAGS) $(LDFLAGS) $(OBJS)
+SRCS= $(srcdir)/crc32.c
 
-crctest.exe:
-       $(CC) -o crctest.exe $(CFLAGS2) $(SRCS)
+##DOS##LIBOBJS = $(OBJS)
+
+all-unix:: all-libobjs
 
-check:: crctest$(EXEEXT)
-       $(C)crctest$(EXEEXT) < $(srcdir)$(S)crc-test
+includes:: depend
 
-clean:: 
-       $(RM) crctest$(EXEEXT) crctest.$(OBJEXT)
+depend:: $(SRCS)
 
 clean-unix:: clean-libobjs
index 28d0dc45196cd3a6f625526e68e6bb302223a66d..1b05b9ac6a79604bb70552ca6148245ad75e81c5 100644 (file)
  * Definitions for the CRC-32 checksum
  */
 
+/*
+ * Copyright (C) 1998 by the FundsXpress, INC.
+ * 
+ * All rights reserved.
+ * 
+ * Export of this software from the United States of America may require
+ * a specific license from the United States Government.  It is the
+ * responsibility of any person or organization contemplating export to
+ * obtain such a license before exporting.
+ * 
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of FundsXpress. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  FundsXpress makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
 
 #ifndef KRB5_CRC32__
 #define KRB5_CRC32__
 
-#define CRC32_CKSUM_LENGTH     (4*sizeof(krb5_octet))
+#define CRC32_CKSUM_LENGTH     4
+
+void
+mit_crc32 PROTOTYPE((krb5_const krb5_pointer in, krb5_const size_t in_length,
+                    unsigned long *c));
 
 extern krb5_checksum_entry crc32_cksumtable_entry;
 
diff --git a/src/lib/crypto/crc32/crc32.c b/src/lib/crypto/crc32/crc32.c
new file mode 100644 (file)
index 0000000..654981f
--- /dev/null
@@ -0,0 +1,166 @@
+/*
+ * lib/crypto/crc32/crc.c
+ *
+ * Copyright 1990 by the Massachusetts Institute of Technology.
+ * All Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ *   require a specific license from the United States Government.
+ *   It is the responsibility of any person or organization contemplating
+ *   export to obtain such a license before exporting.
+ * 
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ *
+ * CRC-32/AUTODIN-II routines
+ */
+
+#include "k5-int.h"
+#include "crc-32.h"
+
+/* This table and block of comments are taken from code labeled: */
+/*
+ * Copyright (C) 1986 Gary S. Brown.  You may use this program, or
+ * code or tables extracted from it, as desired without restriction.
+ */
+
+/* First, the polynomial itself and its table of feedback terms.  The  */
+/* polynomial is                                                       */
+/* X^32+X^26+X^23+X^22+X^16+X^12+X^11+X^10+X^8+X^7+X^5+X^4+X^2+X^1+X^0 */
+/* Note that we take it "backwards" and put the highest-order term in  */
+/* the lowest-order bit.  The X^32 term is "implied"; the LSB is the   */
+/* X^31 term, etc.  The X^0 term (usually shown as "+1") results in    */
+/* the MSB being 1.                                                    */
+
+/* Note that the usual hardware shift register implementation, which   */
+/* is what we're using (we're merely optimizing it by doing eight-bit  */
+/* chunks at a time) shifts bits into the lowest-order term.  In our   */
+/* implementation, that means shifting towards the right.  Why do we   */
+/* do it this way?  Because the calculated CRC must be transmitted in  */
+/* order from highest-order term to lowest-order term.  UARTs transmit */
+/* characters in order from LSB to MSB.  By storing the CRC this way,  */
+/* we hand it to the UART in the order low-byte to high-byte; the UART */
+/* sends each low-bit to hight-bit; and the result is transmission bit */
+/* by bit from highest- to lowest-order term without requiring any bit */
+/* shuffling on our part.  Reception works similarly.                  */
+
+/* The feedback terms table consists of 256, 32-bit entries.  Notes:   */
+/*                                                                     */
+/*  1. The table can be generated at runtime if desired; code to do so */
+/*     is shown later.  It might not be obvious, but the feedback      */
+/*     terms simply represent the results of eight shift/xor opera-    */
+/*     tions for all combinations of data and CRC register values.     */
+/*                                                                     */
+/*  2. The CRC accumulation logic is the same for all CRC polynomials, */
+/*     be they sixteen or thirty-two bits wide.  You simply choose the */
+/*     appropriate table.  Alternatively, because the table can be     */
+/*     generated at runtime, you can start by generating the table for */
+/*     the polynomial in question and use exactly the same "updcrc",   */
+/*     if your application needn't simultaneously handle two CRC       */
+/*     polynomials.  (Note, however, that XMODEM is strange.)          */
+/*                                                                     */
+/*  3. For 16-bit CRCs, the table entries need be only 16 bits wide;   */
+/*     of course, 32-bit entries work OK if the high 16 bits are zero. */
+/*                                                                     */
+/*  4. The values must be right-shifted by eight bits by the "updcrc"  */
+/*     logic; the shift must be unsigned (bring in zeroes).  On some   */
+/*     hardware you could probably optimize the shift in assembler by  */
+/*     using byte-swap instructions.                                   */
+
+static u_long const crc_table[256] = {
+    0x00000000, 0x77073096, 0xee0e612c, 0x990951ba,
+    0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3,
+    0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
+    0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91,
+    0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de,
+    0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
+    0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec,
+    0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5,
+    0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
+    0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b,
+    0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940,
+    0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
+    0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116,
+    0x21b4f4b5, 0x56b3c423, 0xcfba9599, 0xb8bda50f,
+    0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
+    0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d,
+    0x76dc4190, 0x01db7106, 0x98d220bc, 0xefd5102a,
+    0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
+    0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818,
+    0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01,
+    0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,
+    0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457,
+    0x65b0d9c6, 0x12b7e950, 0x8bbeb8ea, 0xfcb9887c,
+    0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
+    0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2,
+    0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb,
+    0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,
+    0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9,
+    0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086,
+    0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
+    0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4,
+    0x59b33d17, 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad,
+    0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,
+    0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683,
+    0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8,
+    0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
+    0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe,
+    0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7,
+    0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,
+    0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5,
+    0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252,
+    0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
+    0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60,
+    0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79,
+    0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
+    0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f,
+    0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04,
+    0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
+    0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a,
+    0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713,
+    0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,
+    0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21,
+    0x86d3d2d4, 0xf1d4e242, 0x68ddb3f8, 0x1fda836e,
+    0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
+    0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c,
+    0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45,
+    0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,
+    0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db,
+    0xaed16a4a, 0xd9d65adc, 0x40df0b66, 0x37d83bf0,
+    0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
+    0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6,
+    0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf,
+    0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
+    0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d
+    };
+
+void
+mit_crc32(in, in_length, cksum)
+    krb5_const krb5_pointer in;
+    krb5_const size_t in_length;
+    unsigned long *cksum;
+{
+    register u_char *data;
+    register u_long c = 0;
+    register int idx;
+    size_t i;
+
+    data = (u_char *)in;
+    for (i = 0; i < in_length; i++) {
+       idx = (int) (data[i] ^ c);
+       idx &= 0xff;
+       c >>= 8;
+       c ^= crc_table[idx];
+    }
+
+    *cksum = c;
+}
diff --git a/src/lib/crypto/cryptoconf.c b/src/lib/crypto/cryptoconf.c
deleted file mode 100644 (file)
index 62be745..0000000
+++ /dev/null
@@ -1,168 +0,0 @@
-/*
- * lib/crypto/cryptoconf.c
- *
- * Copyright 1990,1991 by the Massachusetts Institute of Technology.
- * All Rights Reserved.
- *
- * Export of this software from the United States of America may
- *   require a specific license from the United States Government.
- *   It is the responsibility of any person or organization contemplating
- *   export to obtain such a license before exporting.
- * 
- * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
- * distribute this software and its documentation for any purpose and
- * without fee is hereby granted, provided that the above copyright
- * notice appear in all copies and that both that copyright notice and
- * this permission notice appear in supporting documentation, and that
- * the name of M.I.T. not be used in advertising or publicity pertaining
- * to distribution of the software without specific, written prior
- * permission.  M.I.T. makes no representations about the suitability of
- * this software for any purpose.  It is provided "as is" without express
- * or implied warranty.
- * 
- *
- * Cryptosystem configurations
- */
-
-#include "k5-int.h"
-
-#if defined(PROVIDE_DES_CBC_CRC) || defined(PROVIDE_CRC32)
-#include "crc-32.h"
-#define CRC32_CKENTRY &crc32_cksumtable_entry
-#else
-#define CRC32_CKENTRY 0
-#endif
-
-#ifdef PROVIDE_RSA_MD4
-#include "rsa-md4.h"
-#define MD4_CKENTRY &rsa_md4_cksumtable_entry
-#define MD4_DES_CKENTRY &rsa_md4_des_cksumtable_entry
-#else
-#define MD4_CKENTRY 0
-#define MD4_DES_CKENTRY 0
-#endif
-
-#ifdef PROVIDE_RSA_MD5
-#include "rsa-md5.h"
-#define MD5_CKENTRY &rsa_md5_cksumtable_entry
-#define MD5_DES_CKENTRY &rsa_md5_des_cksumtable_entry
-#else
-#define MD5_CKENTRY 0
-#define MD5_DES_CKENTRY 0
-#endif
-
-#ifdef PROVIDE_NIST_SHA
-#include "shs.h"
-/* #define SHA_CKENTRY &nist_sha_cksumtable_entry */
-/* #define HMAC_SHA_CKENTRY &hmac_sha_cksumtable_entry */
-#define SHA_CKENTRY 0
-#define HMAC_SHA_CKENTRY 0
-#else
-#define SHA_CKENTRY 0
-#define HMAC_SHA_CKENTRY 0
-#endif
-
-#ifdef PROVIDE_SNEFRU
-#define XEROX_CKENTRY &snefru_cksumtable_entry
-#else
-#define XEROX_CKENTRY 0
-#endif
-
-#ifdef PROVIDE_DES_CBC_CKSUM
-#include "des_int.h"
-#define _DES_DONE__
-#define DES_CBC_CKENTRY &krb5_des_cbc_cksumtable_entry
-#else
-#define DES_CBC_CKENTRY 0
-#endif
-
-#ifdef PROVIDE_DES_CBC_CRC
-#ifndef _DES_DONE__
-#include "des_int.h"
-#define _DES_DONE__
-#endif
-#define DES_CBC_CRC_CSENTRY &krb5_des_crc_cst_entry
-#else
-#define DES_CBC_CRC_CSENTRY 0
-#endif
-
-#ifdef PROVIDE_DES_CBC_MD5
-#ifndef _DES_DONE__
-#include "des_int.h"
-#define _DES_DONE__
-#endif
-#define DES_CBC_MD5_CSENTRY &krb5_des_md5_cst_entry
-#else
-#define DES_CBC_MD5_CSENTRY 0
-#endif
-    
-#ifdef PROVIDE_DES_CBC_RAW
-#ifndef _DES_DONE__
-#include "des_int.h"
-#define _DES_DONE__
-#endif
-#define DES_CBC_RAW_CSENTRY &krb5_raw_des_cst_entry
-#else
-#define DES_CBC_RAW_CSENTRY 0
-#endif
-
-#ifdef PROVIDE_DES3_CBC_SHA
-#ifndef _DES_DONE__
-#include "des_int.h"
-#define _DES_DONE__
-#endif
-/* Don't try to enable triple DES unless you know what you are doing; */
-/* the current implementation of triple DES is NOT the final and */
-/* correct implementation.!!!  */
-/* #define DES3_CBC_SHA_CSENTRY &krb5_des3_sha_cst_entry */
-#define DES3_CBC_SHA_CSENTRY 0
-#else
-#define DES3_CBC_SHA_CSENTRY 0
-#endif
-
-#ifdef PROVIDE_DES3_CBC_RAW
-#ifndef _DES_DONE__
-#include "des_int.h"
-#define _DES_DONE__
-#endif
-/* #define DES3_CBC_RAW_CSENTRY &krb5_des3_raw_cst_entry */
-#define DES3_CBC_RAW_CSENTRY 0
-#else
-#define DES3_CBC_RAW_CSENTRY 0
-#endif
-
-
-/* WARNING:
-   make sure the order of entries in these tables matches the #defines in
-   "krb5/encryption.h"
- */
-
-krb5_cs_table_entry * NEAR krb5_enctype_array[] = {
-    0,                         /* ENCTYPE_NULL */
-    DES_CBC_CRC_CSENTRY,       /* ENCTYPE_DES_CBC_CRC */
-    0,                         /* ENCTYPE_DES_CBC_MD4 */
-    DES_CBC_MD5_CSENTRY,       /* ENCTYPE_DES_CBC_MD5 */
-    DES_CBC_RAW_CSENTRY,       /* ENCTYPE_DES_CBC_RAW */
-    DES3_CBC_SHA_CSENTRY,      /* ENCTYPE_DES3_CBC_SHA */
-    DES3_CBC_RAW_CSENTRY       /* ENCTYPE_DES3_CBC_RAW */
-};
-
-krb5_enctype krb5_max_enctype = sizeof(krb5_enctype_array)/sizeof(krb5_enctype_array[0]) - 1;
-
-krb5_checksum_entry * NEAR krb5_cksumarray[] = {
-    0,
-    CRC32_CKENTRY,             /* 1 - CKSUMTYPE_CRC32 */
-    MD4_CKENTRY,               /* 2 - CKSUMTYPE_RSA_MD4 */
-    MD4_DES_CKENTRY,           /* 3 - CKSUMTYPE_RSA_MD4_DES */
-    DES_CBC_CKENTRY,           /* 4 - CKSUMTYPE_DESCBC */
-    0,                         /* 5 - des-mac-k */
-    0,                         /* 6 - rsa-md4-des-k */
-    MD5_CKENTRY,               /* 7 - CKSUMTYPE_RSA_MD5 */
-    MD5_DES_CKENTRY,           /* 8 - CKSUMTYPE_RSA_MD5_DES */
-    SHA_CKENTRY,               /* 9 - CKSUMTYPE_NIST_SHA */
-    HMAC_SHA_CKENTRY           /* 10 - CKSUMTYPE_NIST_SHA_DES3 */
-};
-
-krb5_cksumtype krb5_max_cksum = sizeof(krb5_cksumarray)/sizeof(krb5_cksumarray[0]);
-
-#undef _DES_DONE__
diff --git a/src/lib/crypto/decrypt.c b/src/lib/crypto/decrypt.c
new file mode 100644 (file)
index 0000000..0d66ec0
--- /dev/null
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 1998 by the FundsXpress, INC.
+ * 
+ * All rights reserved.
+ * 
+ * Export of this software from the United States of America may require
+ * a specific license from the United States Government.  It is the
+ * responsibility of any person or organization contemplating export to
+ * obtain such a license before exporting.
+ * 
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of FundsXpress. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  FundsXpress makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#include "k5-int.h"
+#include "etypes.h"
+
+KRB5_DLLIMP krb5_error_code KRB5_CALLCONV
+krb5_c_decrypt(context, key, usage, ivec, input, output)
+     krb5_context context;
+     krb5_const krb5_keyblock *key;
+     krb5_keyusage usage;
+     krb5_const krb5_data *ivec;
+     krb5_const krb5_enc_data *input;
+     krb5_data *output;
+{
+    int i;
+
+    for (i=0; i<krb5_enctypes_length; i++) {
+       if (krb5_enctypes_list[i].etype == key->enctype)
+           break;
+    }
+
+    if (i == krb5_enctypes_length)
+       return(KRB5_BAD_ENCTYPE);
+
+    if ((input->enctype != ENCTYPE_UNKNOWN) &&
+       (krb5_enctypes_list[i].etype != input->enctype))
+       return(KRB5_BAD_ENCTYPE);
+
+    return((*(krb5_enctypes_list[i].decrypt))
+          (krb5_enctypes_list[i].enc, krb5_enctypes_list[i].hash,
+           key, usage, ivec, &input->ciphertext, output));
+}
diff --git a/src/lib/crypto/decrypt_data.c b/src/lib/crypto/decrypt_data.c
deleted file mode 100644 (file)
index ae886d0..0000000
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
- * Copyright 1995 by the Massachusetts Institute of Technology.
- * All Rights Reserved.
- *
- * Export of this software from the United States of America may
- *   require a specific license from the United States Government.
- *   It is the responsibility of any person or organization contemplating
- *   export to obtain such a license before exporting.
- *
- * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
- * distribute this software and its documentation for any purpose and
- * without fee is hereby granted, provided that the above copyright
- * notice appear in all copies and that both that copyright notice and
- * this permission notice appear in supporting documentation, and that
- * the name of M.I.T. not be used in advertising or publicity pertaining
- * to distribution of the software without specific, written prior
- * permission.  M.I.T. makes no representations about the suitability of
- * this software for any purpose.  It is provided "as is" without express
- * or implied warranty.
- *
- */
-
-#include "k5-int.h"
-
-/*
- * This routine takes a key and a krb5_enc_data structure as input, and
- * outputs the decrypted data in a krb5_data structure.  Note that
- * the krb5_data structure is not allocated.
- */
-krb5_error_code
-krb5_decrypt_data(context, key, ivec, enc_data, data)
-    krb5_context       context;
-    krb5_keyblock *    key;
-    krb5_pointer       ivec;
-    krb5_enc_data *    enc_data;
-    krb5_data *                data;
-{
-    krb5_error_code    retval;
-    krb5_encrypt_block eblock;
-
-    krb5_use_enctype(context, &eblock, key->enctype);
-    data->length = enc_data->ciphertext.length;
-    if (!(data->data = malloc(data->length)))
-       return ENOMEM;
-
-    if ((retval = krb5_process_key(context, &eblock, key)) != 0)
-       goto cleanup;
-
-    if ((retval = krb5_decrypt(context,
-                              (krb5_pointer) enc_data->ciphertext.data,
-                              (krb5_pointer) data->data,
-                              enc_data->ciphertext.length, &eblock, ivec))) {
-       krb5_finish_key(context, &eblock);
-        goto cleanup;
-    }
-    (void) krb5_finish_key(context, &eblock);
-
-    return 0;
-
-cleanup:
-    if (data->data) {
-       free(data->data);
-       data->data = 0;
-    }
-    return retval;
-}
diff --git a/src/lib/crypto/des/.rconf b/src/lib/crypto/des/.rconf
deleted file mode 100644 (file)
index b886964..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-ignore fp.c
-ignore ip.c
-ignore key_perm.h
-ignore odd.h
-ignore p.c
-ignore p_table.h
-ignore s_table.h
-ignore doc
index e236a9cb967befed444f13eb2a7fa8a639c134bb..70c431aa5c520d2ed2a65e1f5d9cac7fc9b9c002 100644 (file)
@@ -1,3 +1,7 @@
+Sun Jul 19 12:00:00 1998  Marc Horowitz <marc@mit.edu>
+
+       * *.c: replace the crypto layer.
+
 Wed Feb 18 16:06:23 1998  Tom Yu  <tlyu@mit.edu>
 
        * Makefile.in: Remove trailing slash from thisconfigdir.  Fix up
diff --git a/src/lib/crypto/des/FUNCTIONS b/src/lib/crypto/des/FUNCTIONS
deleted file mode 100644 (file)
index 7ed082e..0000000
+++ /dev/null
@@ -1,26 +0,0 @@
-File           Function                                Where?
-
-weak_key.c     mit_des_is_weak_key                     crypto
-string2key.c   mit_des_string_to_key                   ?
-random_key.c   mit_des_random_key                      ?
-process_ky.c   mit_des_process_key                     ?
-new_rn_key.c   mit_des_new_random_key                  ?
-               mit_des_init_random_number_generator    ?
-               mit_des_set_random_generator_seed       ?
-               mit_des_set_sequence_number             ?
-               mit_des_generate_random_block           ?
-krb_glue.c     mit_des_encrypt_func                    ?
-               mit_des_decrypt_func                    ?
-key_sched.c    mit_des_key_sched                       crypto
-key_parity.c   mit_des_fixup_key_parity                crypto
-               mit_des_check_key_parity                crypto
-init_rkey.c    mit_des_init_random_key                 crypto
-finish_key.c   mit_des_finish_key                      crypto
-fin_rndkey.c   mit_des_finish_random_key               crypto
-enc_dec.c      mit_des_cbc_encrypt                     crypto
-des.c          mit_des_ecb_encrypt                     crypto
-cs_entry.c     (var) mit_des_cryptosystem_entry        krb5
-               (var) krb5_des_cst_entry                krb5
-               (var) mit_des_cbc_cksumtable_entry      krb5
-cksum.c                mit_des_cbc_cksum                       crypto
-cbc_cksum.c    mit_des_cbc_checksum                    crypto
index 3f9311b96ea5e1b7cd429925a687003ef409543b..fdef9e869a2726cfcd8add7456677de7d0d7a905 100644 (file)
@@ -13,77 +13,41 @@ PROG_RPATH=$(KRB5_LIBDIR)
 RUN_SETUP = @KRB5_RUN_ENV@ KRB5_CONFIG=$(SRCTOP)/config-files/krb5.conf
 
 STLIBOBJS=\
-       afsstring2key.o \
-       cbc_cksum.o     \
-       finish_key.o    \
-       fin_rndkey.o    \
-       init_rkey.o     \
-       process_ky.o    \
-       random_key.o    \
-       string2key.o    \
-       key_sched.o     \
-       weak_key.o      \
+       afsstring2key.o \
+       d3_cbc.o        \
+       d3_kysched.o    \
        f_cbc.o         \
-       f_cksum.o       \
-       f_sched.o       \
-       f_ecb.o         \
+       f_cksum.o       \
        f_parity.o      \
+       f_sched.o       \
        f_tables.o      \
-       d3_cbc.o        \
-       d3_ecb.o        \
-       d3_kysched.o    \
-       d3_procky.o     \
-       d3_str2ky.o     \
-       u_nfold.o       \
-       u_rn_key.o
-
-OBJS=  afsstring2key.$(OBJEXT) \
-       cbc_cksum.$(OBJEXT)     \
-       finish_key.$(OBJEXT)    \
-       fin_rndkey.$(OBJEXT)    \
-       init_rkey.$(OBJEXT)     \
-       process_ky.$(OBJEXT)    \
-       random_key.$(OBJEXT)    \
-       string2key.$(OBJEXT)    \
-       key_sched.$(OBJEXT)     \
-       weak_key.$(OBJEXT)      \
+       key_sched.o     \
+       string2key.o    \
+       weak_key.o
+
+OBJS=  afsstring2key.$(OBJEXT) \
+       d3_cbc.$(OBJEXT)        \
+       d3_kysched.$(OBJEXT)    \
        f_cbc.$(OBJEXT)         \
-       f_cksum.$(OBJEXT)       \
-       f_sched.$(OBJEXT)       \
-       f_ecb.$(OBJEXT)         \
+       f_cksum.$(OBJEXT)       \
        f_parity.$(OBJEXT)      \
+       f_sched.$(OBJEXT)       \
        f_tables.$(OBJEXT)      \
-       d3_cbc.$(OBJEXT)        \
-       d3_ecb.$(OBJEXT)        \
-       d3_kysched.$(OBJEXT)    \
-       d3_procky.$(OBJEXT)     \
-       d3_str2ky.$(OBJEXT)     \
-       u_nfold.$(OBJEXT)       \
-       u_rn_key.$(OBJEXT)
-
-SRCS=  $(srcdir)/afsstring2key.c \
-       $(srcdir)/cbc_cksum.c   \
-       $(srcdir)/finish_key.c  \
-       $(srcdir)/fin_rndkey.c  \
-       $(srcdir)/init_rkey.c   \
-       $(srcdir)/process_ky.c  \
-       $(srcdir)/random_key.c  \
-       $(srcdir)/string2key.c  \
+       key_sched.$(OBJEXT)     \
+       string2key.$(OBJEXT)    \
+       weak_key.$(OBJEXT)
+
+SRCS=  $(srcdir)/afsstring2key.c       \
+       $(srcdir)/d3_cbc.c      \
+       $(srcdir)/d3_kysched.c  \
+       $(srcdir)/f_cbc.c       \
+       $(srcdir)/f_cksum.c     \
+       $(srcdir)/f_parity.c    \
+       $(srcdir)/f_sched.c     \
+       $(srcdir)/f_tables.c    \
        $(srcdir)/key_sched.c   \
        $(srcdir)/weak_key.c    \
-       $(srcdir)/f_cbc.c \
-       $(srcdir)/f_cksum.c \
-       $(srcdir)/f_sched.c \
-       $(srcdir)/f_ecb.c \
-       $(srcdir)/f_parity.c \
-       $(srcdir)/f_tables.c \
-       $(srcdir)/d3_cbc.c \
-       $(srcdir)/d3_ecb.c \
-       $(srcdir)/d3_kysched.c \
-       $(srcdir)/d3_procky.c \
-       $(srcdir)/d3_str2ky.c \
-       $(srcdir)/u_nfold.c \
-       $(srcdir)/u_rn_key.c
+       $(srcdir)/string2key.c
 
 ##DOS##LIBOBJS = $(OBJS)
 
@@ -93,22 +57,18 @@ includes:: depend
 
 depend:: $(SRCS)
 
-# FIXME, this is left from the previous DES implementation.
-clean::
-       $(RM) fp.c ip.c key_perm.h odd.h p.c p_table.h s_table.h
-
-verify$(EXEEXT): t_verify.$(OBJEXT) $(KRB5_BASE_DEPLIBS)
-       $(CC_LINK) -o $@ t_verify.$(OBJEXT) process_ky.o  key_sched.o \
-       ../cryptoconf.o ../des_crc.o $(KRB5_BASE_LIBS)
+TOBJS = key_sched.$(OBJEXT) f_sched.$(OBJEXT) f_cbc.$(OBJEXT) \
+       f_tables.$(OBJEXT) f_cksum.$(OBJEXT)
 
-destest$(EXEEXT): destest.$(OBJEXT) $(KRB5_BASE_DEPLIBS)
-       $(CC_LINK) -o $@ destest.$(OBJEXT) process_ky.o key_sched.o \
-       ../cryptoconf.o ../des_crc.o $(KRB5_BASE_LIBS)
+verify$(EXEEXT): t_verify.$(OBJEXT) $(TOBJS) f_parity.$(OBJEXT) \
+       $(COM_ERR_DEPLIB)
+       $(CC_LINK) -o $@ t_verify.$(OBJEXT) $(TOBJS) f_parity.$(OBJEXT) \
+               -lcom_err
 
-t_random$(EXEEXT): t_random.$(OBJEXT) $(KRB5_BASE_DEPLIBS)
-       $(CC_LINK) -o $@ t_random.$(OBJEXT) $(KRB5_BASE_LIBS)
+destest$(EXEEXT): destest.$(OBJEXT) $(TOBJS)
+       $(CC_LINK) -o $@ destest.$(OBJEXT) $(TOBJS)
 
-check-unix:: destest verify
+check-unix:: verify destest
        $(RUN_SETUP) ./verify -z
        $(RUN_SETUP) ./verify -m
        $(RUN_SETUP) ./verify
@@ -118,6 +78,6 @@ check-windows::
 
 clean:: 
        $(RM) destest$(EXEEXT) verify$(EXEEXT) destest.$(OBJEXT) \
-       t_verify.$(OBJEXT) t_random.$(OBJEXT) t_random$(EXEEXT)
+       t_verify.$(OBJEXT)
 
 clean-unix:: clean-libobjs
index 36c42c4823880759916808bc7d4ae08e1be232c7..7eac0807c28a6692668791f1f9c31381c0d5d3ff 100644 (file)
@@ -6,6 +6,32 @@
  * constructed by Mark Eichin, Cygnus Support, 1995.
  */
 
+/*
+ * Copyright (C) 1998 by the FundsXpress, INC.
+ * 
+ * All rights reserved.
+ * 
+ * Export of this software from the United States of America may require
+ * a specific license from the United States Government.  It is the
+ * responsibility of any person or organization contemplating export to
+ * obtain such a license before exporting.
+ * 
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of FundsXpress. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  FundsXpress makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
 #include "k5-int.h"
 #include "des_int.h"
 #include <ctype.h>
@@ -13,8 +39,7 @@
 static char *afs_crypt PROTOTYPE((char*,char*));
 
 krb5_error_code
-mit_afs_string_to_key (eblock, keyblock, data, salt)
-     const krb5_encrypt_block FAR * eblock;
+mit_afs_string_to_key (keyblock, data, salt)
      krb5_keyblock FAR * keyblock;
      const krb5_data FAR * data;
      const krb5_data FAR * salt;
@@ -29,7 +54,7 @@ mit_afs_string_to_key (eblock, keyblock, data, salt)
     register krb5_octet *key = keyblock->contents;
 
     if (data->length <= 8) {
-      char password[9];                /* trailing null for crypt() */
+      char password[9];                /* trailing nul for crypt() */
       strncpy(password, realm, 8);
       for (i=0; i<8; i++)
        if (isupper(password[i]))
@@ -39,6 +64,7 @@ mit_afs_string_to_key (eblock, keyblock, data, salt)
       for (i=0; i<8; i++)
        if (password[i] == '\0')
          password[i] = 'X';
+      password[8] = '\0';
       strncpy(key, (char *) afs_crypt(password, "#~") + 2, 8);
       for (i=0; i<8; i++)
        key[i] <<= 1;
diff --git a/src/lib/crypto/des/cbc_cksum.c b/src/lib/crypto/des/cbc_cksum.c
deleted file mode 100644 (file)
index 29a38a0..0000000
+++ /dev/null
@@ -1,164 +0,0 @@
-/*
- * lib/crypto/des/cbc_cksum.c
- *
- * Copyright 1985, 1986, 1987, 1988, 1990 by the Massachusetts Institute
- * of Technology.
- * All Rights Reserved.
- *
- * Under U.S. law, this software may not be exported outside the US
- * without license from the U.S. Commerce department.
- *
- * These routines form the library interface to the DES facilities.
- *
- * Export of this software from the United States of America may
- *   require a specific license from the United States Government.
- *   It is the responsibility of any person or organization contemplating
- *   export to obtain such a license before exporting.
- * 
- * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
- * distribute this software and its documentation for any purpose and
- * without fee is hereby granted, provided that the above copyright
- * notice appear in all copies and that both that copyright notice and
- * this permission notice appear in supporting documentation, and that
- * the name of M.I.T. not be used in advertising or publicity pertaining
- * to distribution of the software without specific, written prior
- * permission.  M.I.T. makes no representations about the suitability of
- * this software for any purpose.  It is provided "as is" without express
- * or implied warranty.
- * 
- *
- */
-
-#include "k5-int.h"
-#include "des_int.h"
-
-/*
-       produces cbc cheksum of sequence "in" of the length "in_length" 
-       with the help of key "key" of size "key_size" (which should be 8);
-       fills out krb5_checksum structure.
-
-       caller is responsible for allocating & freeing "contents" element in 
-       krb5_checksum structure.
-
-       returns: errors
-*/
-
-static krb5_error_code mit_des_cbc_checksum
-    PROTOTYPE((krb5_const krb5_pointer,
-              krb5_const size_t,
-              krb5_const krb5_pointer,
-              krb5_const size_t,
-              krb5_checksum FAR * ));
-
-static krb5_error_code mit_des_cbc_verf_cksum
-    PROTOTYPE ((krb5_const krb5_checksum FAR *,
-               krb5_const krb5_pointer,
-               krb5_const size_t,
-               krb5_const krb5_pointer,
-                krb5_const size_t ));
-
-static krb5_error_code
-mit_des_cbc_checksum(in, in_length, key, key_size, cksum)
-    krb5_const krb5_pointer in;
-    krb5_const size_t in_length;
-    krb5_const krb5_pointer key;
-    krb5_const size_t key_size;
-    krb5_checksum FAR * cksum;
-{
-    struct mit_des_ks_struct       *schedule;      /* pointer to key schedules */
-
-    if (cksum->length < sizeof(mit_des_cblock))
-       return KRB5_BAD_MSIZE;
-    if (key_size != sizeof(mit_des_cblock))
-       return KRB5_BAD_KEYSIZE;
-
-    if (!(schedule = (struct mit_des_ks_struct *) malloc(sizeof(mit_des_key_schedule))))
-        return ENOMEM;
-
-#define cleanup() { memset((char *)schedule, 0, sizeof(mit_des_key_schedule));\
-                   free( (char *) schedule); }
-
-    switch (mit_des_key_sched ((krb5_octet *)key, schedule)) {
-    case -1:
-        cleanup();
-        return KRB5DES_BAD_KEYPAR;
-
-    case -2:
-        cleanup();
-        return KRB5DES_WEAK_KEY;
-
-    default:
-        ;
-    }
-
-    cksum->checksum_type = CKSUMTYPE_DESCBC;
-    cksum->length = sizeof(mit_des_cblock);
-    mit_des_cbc_cksum(in, cksum->contents, in_length, schedule, key);
-
-    cleanup();
-
-    return 0;
-}
-    
-static krb5_error_code
-mit_des_cbc_verf_cksum(cksum, in, in_length, key, key_size)
-    krb5_const krb5_checksum FAR * cksum;
-    krb5_const krb5_pointer in;
-    krb5_const size_t in_length;
-    krb5_const krb5_pointer key;
-    krb5_const size_t key_size;
-{
-    struct mit_des_ks_struct       *schedule;      /* pointer to key schedules */
-    mit_des_cblock     contents;
-    krb5_error_code    retval;
-
-    if (key_size != sizeof(mit_des_cblock))
-       return KRB5_BAD_KEYSIZE;
-
-    if (!(schedule = (struct mit_des_ks_struct *) malloc(sizeof(mit_des_key_schedule))))
-        return ENOMEM;
-
-#define cleanup() { memset((char *)schedule, 0, sizeof(mit_des_key_schedule));\
-                   free( (char *) schedule); }
-
-    switch (mit_des_key_sched ((krb5_octet *)key, schedule)) {
-    case -1:
-        cleanup();
-        return KRB5DES_BAD_KEYPAR;
-
-    case -2:
-        cleanup();
-        return KRB5DES_WEAK_KEY;
-
-    default:
-        ;
-    }
-
-    mit_des_cbc_cksum(in, contents, in_length, schedule, key);
-
-    retval = 0;
-    if (cksum->checksum_type == CKSUMTYPE_DESCBC) {
-       if (cksum->length == sizeof(mit_des_cblock)) {
-           if (memcmp((char *) cksum->contents,
-                      (char *) contents,
-                      sizeof(mit_des_cblock)))
-               retval = KRB5KRB_AP_ERR_BAD_INTEGRITY;
-       }
-       else
-           retval = KRB5KRB_AP_ERR_BAD_INTEGRITY;
-    }
-    else
-       retval = KRB5KRB_AP_ERR_INAPP_CKSUM;
-    cleanup();
-
-    return retval;
-}
-
-krb5_checksum_entry krb5_des_cbc_cksumtable_entry = {
-    0,
-    mit_des_cbc_checksum,
-    mit_des_cbc_verf_cksum,
-    sizeof(mit_des_cblock),
-    1,                                 /* is collision proof */
-    1,                                 /* is keyed */
-};
diff --git a/src/lib/crypto/des/d3_ecb.c b/src/lib/crypto/des/d3_ecb.c
deleted file mode 100644 (file)
index 306f97d..0000000
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * Copyright 1995 by Richard P. Basch.  All Rights Reserved.
- * Copyright 1995 by Lehman Brothers, Inc.  All Rights Reserved.
- *
- * Export of this software from the United States of America may
- *   require a specific license from the United States Government.
- *   It is the responsibility of any person or organization contemplating
- *   export to obtain such a license before exporting.
- * 
- * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
- * distribute this software and its documentation for any purpose and
- * without fee is hereby granted, provided that the above copyright
- * notice appear in all copies and that both that copyright notice and
- * this permission notice appear in supporting documentation, and that
- * the name of Richard P. Basch, Lehman Brothers and M.I.T. not be used
- * in advertising or publicity pertaining to distribution of the software
- * without specific, written prior permission.  Richard P. Basch,
- * Lehman Brothers and M.I.T. make no representations about the suitability
- * of this software for any purpose.  It is provided "as is" without
- * express or implied warranty.
- */
-
-#include "des_int.h"
-#include "f_tables.h"
-
-/*
- * Triple-DES ECB encryption mode.
- */
-
-int
-mit_des3_ecb_encrypt(in, out, sched1, sched2, sched3, encrypt)
-       const mit_des_cblock FAR *in;
-       mit_des_cblock FAR *out;
-       mit_des_key_schedule sched1, sched2, sched3;
-       int encrypt;
-{
-       if (encrypt) {
-               mit_des_ecb_encrypt(in, out, sched1, encrypt);
-               mit_des_ecb_encrypt(out, out, sched2, !encrypt);
-               mit_des_ecb_encrypt(out, out, sched3, encrypt);
-       } else {
-               mit_des_ecb_encrypt(in, out, sched3, encrypt);
-               mit_des_ecb_encrypt(out, out, sched2, !encrypt);
-               mit_des_ecb_encrypt(out, out, sched1, encrypt);
-       }
-       return 0;
-}
diff --git a/src/lib/crypto/des/d3_procky.c b/src/lib/crypto/des/d3_procky.c
deleted file mode 100644 (file)
index 9c969a8..0000000
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
- * Copyright 1995 by Richard P. Basch.  All Rights Reserved.
- * Copyright 1995 by Lehman Brothers, Inc.  All Rights Reserved.
- *
- * Export of this software from the United States of America may
- *   require a specific license from the United States Government.
- *   It is the responsibility of any person or organization contemplating
- *   export to obtain such a license before exporting.
- * 
- * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
- * distribute this software and its documentation for any purpose and
- * without fee is hereby granted, provided that the above copyright
- * notice appear in all copies and that both that copyright notice and
- * this permission notice appear in supporting documentation, and that
- * the name of Richard P. Basch, Lehman Brothers and M.I.T. not be used
- * in advertising or publicity pertaining to distribution of the software
- * without specific, written prior permission.  Richard P. Basch,
- * Lehman Brothers and M.I.T. make no representations about the suitability
- * of this software for any purpose.  It is provided "as is" without
- * express or implied warranty.
- */
-
-#include "k5-int.h"
-#include "des_int.h"
-
-krb5_error_code
-mit_des3_process_key (eblock, keyblock)
-    krb5_encrypt_block * eblock;
-    const krb5_keyblock * keyblock;
-{
-    struct mit_des_ks_struct       *schedule;      /* pointer to key schedules */
-
-    if ((keyblock->enctype != ENCTYPE_DES3_CBC_SHA) &&
-       (keyblock->enctype != ENCTYPE_DES3_CBC_RAW))
-       return KRB5_PROG_ETYPE_NOSUPP;
-
-    if (keyblock->length != sizeof (mit_des3_cblock))
-       return KRB5_BAD_KEYSIZE;
-
-    if ( !(schedule = (struct mit_des_ks_struct *) malloc(3*sizeof(mit_des_key_schedule))) )
-        return ENOMEM;
-#define cleanup() { free( (char *) schedule); }
-
-    switch (mit_des3_key_sched (*(mit_des3_cblock *)keyblock->contents,
-                               *(mit_des3_key_schedule *)schedule)) {
-    case -1:
-       cleanup();
-       return KRB5DES_BAD_KEYPAR;
-
-    case -2:
-       cleanup();
-       return KRB5DES_WEAK_KEY;
-    }
-
-    eblock->key = (krb5_keyblock *) keyblock;
-    eblock->priv = (krb5_pointer) schedule;
-    eblock->priv_size = (krb5_int32) 3*sizeof(mit_des_key_schedule);
-
-    return 0;
-}
diff --git a/src/lib/crypto/des/d3_str2ky.c b/src/lib/crypto/des/d3_str2ky.c
deleted file mode 100644 (file)
index ed9f518..0000000
+++ /dev/null
@@ -1,137 +0,0 @@
-/*
- * Copyright 1995 by Richard P. Basch.  All Rights Reserved.
- * Copyright 1995 by Lehman Brothers, Inc.  All Rights Reserved.
- *
- * Export of this software from the United States of America may
- *   require a specific license from the United States Government.
- *   It is the responsibility of any person or organization contemplating
- *   export to obtain such a license before exporting.
- * 
- * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
- * distribute this software and its documentation for any purpose and
- * without fee is hereby granted, provided that the above copyright
- * notice appear in all copies and that both that copyright notice and
- * this permission notice appear in supporting documentation, and that
- * the name of Richard P. Basch, Lehman Brothers and M.I.T. not be used
- * in advertising or publicity pertaining to distribution of the software
- * without specific, written prior permission.  Richard P. Basch,
- * Lehman Brothers and M.I.T. make no representations about the suitability
- * of this software for any purpose.  It is provided "as is" without
- * express or implied warranty.
- */
-
-#include "k5-int.h"
-#include "des_int.h"
-
-/*
- * Triple-DES string-to-key algorithm
- *
- * 168-fold the input string (appended with any salt), and treat the resulting
- * 168 bits as three DES keys sans parity.  Process each set of 56 bits into
- * a usable DES key with odd parity, and twice encrypt the set of three usable
- * DES keys using Triple-DES CBC mode.  The result is then treated as three
- * DES keys, and should be corrected for parity.  Any DES key that is weak or
- * semi-weak is to be corrected by eXclusive-ORing with 00000000000000F0.
- */
-
-static mit_des_cblock zero_ivec = { 0, 0, 0, 0, 0, 0, 0, 0 };
-
-krb5_error_code
-mit_des3_string_to_key (eblock, keyblock, data, salt)
-const krb5_encrypt_block FAR * eblock;
-krb5_keyblock FAR * keyblock;
-const krb5_data FAR * data;
-const krb5_data FAR * salt;
-{
-    char *copystr;
-    mit_des_cblock *key;
-    unsigned int j;
-
-    int length;
-    mit_des3_key_schedule ks;
-    krb5_enctype enctype = eblock->crypto_entry->proto_enctype;
-
-    if ((enctype == ENCTYPE_DES3_CBC_SHA) ||
-       (enctype == ENCTYPE_DES3_CBC_RAW))
-       keyblock->length = sizeof(mit_des3_cblock);
-    else
-       return (KRB5_PROG_ETYPE_NOSUPP);
-
-    if ( !(keyblock->contents = (krb5_octet *)malloc(keyblock->length)) )
-       return(ENOMEM);
-
-    keyblock->magic = KV5M_KEYBLOCK;
-    keyblock->enctype = enctype;
-    key = (mit_des_cblock *)keyblock->contents;
-
-    if (salt)
-       length = data->length + salt->length;
-    else
-       length = data->length;
-
-    if (length < keyblock->length)
-       length = keyblock->length;
-
-    copystr = malloc((size_t) length);
-    if (!copystr) {
-       free(keyblock->contents);
-       keyblock->contents = 0;
-       return ENOMEM;
-    }
-
-    memset(copystr, 0, length);
-    memcpy(copystr, (char *) data->data, data->length);
-    if (salt)
-       memcpy(copystr + data->length, (char *)salt->data, salt->length);
-
-    /* n-fold into des3 key sans parity */
-    if (mit_des_n_fold(copystr, length, keyblock->contents,
-                      keyblock->length * 7 / 8))
-       return EINVAL;
-
-    /* Add space for parity (low bit) */
-    for (j = keyblock->length; j--; ) {
-       register int k;
-
-       k = (8-(j%8)) & 7;
-       keyblock->contents[j] =
-           ((keyblock->contents[j*7/8] << k) & 0xfe) +
-           ((k>1) ? keyblock->contents[j*7/8 +1] >> (8-k) : 0);
-    }
-       
-    /* fix key parity */
-    for (j = 0; j < keyblock->length/sizeof(mit_des_cblock); j++) {
-       mit_des_fixup_key_parity(key[j]);
-       if (mit_des_is_weak_key(key[j]))
-           ((krb5_octet *)(key[j]))[7] ^= 0xf0;
-    }
-
-    /* Now, CBC encrypt with itself */
-    (void) mit_des3_key_sched(*((mit_des3_cblock *)key), ks);
-    (void) mit_des3_cbc_encrypt(key, key, keyblock->length,
-                               ((mit_des_key_schedule *)ks)[0],
-                               ((mit_des_key_schedule *)ks)[1],
-                               ((mit_des_key_schedule *)ks)[2],
-                               zero_ivec, TRUE);
-    (void) mit_des3_cbc_encrypt(key, key, keyblock->length,
-                               ((mit_des_key_schedule *)ks)[0],
-                               ((mit_des_key_schedule *)ks)[1],
-                               ((mit_des_key_schedule *)ks)[2],
-                               key[2], TRUE);
-
-    /* erase key_sked */
-    memset((char *)ks, 0, sizeof(ks));
-
-    /* clean & free the input string */
-    memset(copystr, 0, (size_t) length);
-    krb5_xfree(copystr);
-
-    /* now fix up key parity again */
-    for (j = 0; j < keyblock->length/sizeof(mit_des_cblock); j++) {
-       mit_des_fixup_key_parity(key[j]);
-       if (mit_des_is_weak_key(key[j]))
-           ((krb5_octet *)(key[j]))[7] ^= 0xf0;
-    }
-
-    return 0;
-}
diff --git a/src/lib/crypto/des/des.h b/src/lib/crypto/des/des.h
deleted file mode 100644 (file)
index bd0a30b..0000000
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * include/des.h
- *
- * Copyright 1987, 1988 by the Massachusetts Institute of Technology.
- *
- * For copying and distribution information, please see the file
- * <mit-copyright.h>.
- *
- * Include file for the Data Encryption Standard library.
- */
-
-/* only do the whole thing once         */
-#ifndef DES_DEFS
-#define DES_DEFS
-
-#include "k5-int.h"
-
-#ifndef DES_INT32
-#ifdef SIZEOF_INT
-#if SIZEOF_INT >= 4
-#define DES_INT32 int
-#else
-#define DES_INT32 long
-#endif
-#else /* !defined(SIZEOF_INT) */
-#include <limits.h>
-#if (UINT_MAX >= 0xffffffff)
-#define DES_INT32 int
-#else
-#define DES_INT32 long
-#endif
-#endif /* !defined(SIZEOF_INT) */
-#endif /* !defined(DES_INT32) */
-
-#ifndef DES_UINT32
-#define DES_UINT32 unsigned DES_INT32
-#endif
-
-#ifndef NCOMPAT
-#define C_Block des_cblock
-#define Key_schedule des_key_schedule
-#define ENCRYPT DES_ENCRYPT
-#define DECRYPT DES_DECRYPT
-#define KEY_SZ DES_KEY_SZ
-#define string_to_key des_string_to_key
-#define read_pw_string des_read_pw_string
-#define random_key des_random_key
-#define pcbc_encrypt des_pcbc_encrypt
-#define key_sched des_key_sched
-#define cbc_encrypt des_cbc_encrypt
-#define cbc_cksum des_cbc_cksum
-#define C_Block_print des_cblock_print
-#define quad_cksum des_quad_cksum
-typedef struct des_ks_struct bit_64;
-#endif
-
-#define des_cblock_print(x) des_cblock_print_file(x, stdout)
-
-#endif /* DES_DEFS */
index df8e9ca1ed938dbaf0e8693a47a3df55929b9ae7..0f81908615f92f97d22271911846ce6728bc8080 100644 (file)
  * Private include file for the Data Encryption Standard library.
  */
 
+/*
+ * Copyright (C) 1998 by the FundsXpress, INC.
+ * 
+ * All rights reserved.
+ * 
+ * Export of this software from the United States of America may require
+ * a specific license from the United States Government.  It is the
+ * responsibility of any person or organization contemplating export to
+ * obtain such a license before exporting.
+ * 
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of FundsXpress. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  FundsXpress makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
 /* only do the whole thing once         */
 #ifndef DES_INTERNAL_DEFS
 #define DES_INTERNAL_DEFS
@@ -112,8 +138,7 @@ error(MIT_DES_KEYSIZE does not equal KRB5_MIT_DES_KEYSIZE)
 
 /* afsstring2key.c */
 extern krb5_error_code mit_afs_string_to_key
-       PROTOTYPE((const krb5_encrypt_block FAR *eblock,
-                  krb5_keyblock FAR *keyblock,
+       PROTOTYPE((krb5_keyblock FAR *keyblock,
                   const krb5_data FAR *data,
                   const krb5_data FAR *salt));
 
index 1e077a42399d577707b12d02720f1894ec4ced05..bf442e8698a86147fdbfb8024b7225b014dc9475 100644 (file)
  */
 
 
-#include "k5-int.h"
+/*
+ * Copyright (C) 1998 by the FundsXpress, INC.
+ * 
+ * All rights reserved.
+ * 
+ * Export of this software from the United States of America may require
+ * a specific license from the United States Government.  It is the
+ * responsibility of any person or organization contemplating export to
+ * obtain such a license before exporting.
+ * 
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of FundsXpress. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  FundsXpress makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
 #include "des_int.h"
 #include "com_err.h"
 
-extern int errno;
-extern mit_des_ecb_encrypt();
-
 #include <stdio.h>
 
-
 void convert PROTOTYPE((char *, unsigned char []));
 
 void des_cblock_print_file PROTOTYPE((mit_des_cblock, FILE *));
 
+char zeroblock[8] = {0,0,0,0,0,0,0,0};
+
 void
 main(argc, argv)
 int argc;
@@ -46,38 +69,23 @@ char *argv[];
 {
     char block1[17], block2[17], block3[17];
 
-    krb5_encrypt_block eblock;
-    krb5_keyblock keyblock;
-    krb5_context context;
     mit_des_cblock key, input, output, output2;
-    krb5_error_code retval;
+    mit_des_key_schedule sched;
     int num = 0;
+    int retval;
 
     int error = 0;
-    /* This is a crock and we know it... We win because 
-       none of these tests rely on a valid context pointer */
-    context = 0;
-
-    /* do some initialisation */
-    initialize_krb5_error_table();
-
-    krb5_use_enctype(context, &eblock, ENCTYPE_DES_CBC_CRC);
-    keyblock.magic = KV5M_KEYBLOCK;
-    keyblock.enctype = ENCTYPE_DES_CBC_CRC;
-    keyblock.length = sizeof (mit_des_cblock);
-    keyblock.contents = (krb5_octet *)key;
 
     while (scanf("%16s %16s %16s", block1, block2, block3) == 3) {
        convert(block1, key);
        convert(block2, input);
        convert(block3, output);
 
-        if (retval = krb5_process_key(context, &eblock,&keyblock)) {
-            com_err("des test", retval, "can't process key");
-            exit(-1);
+       if (retval = mit_des_key_sched(key, sched)) {
+            fprintf(stderr, "des test: can't process key");
+            exit(1);
         }
-       mit_des_ecb_encrypt(&input, &output2,
-                           (struct mit_des_ks_struct *)eblock.priv,1);
+       mit_des_cbc_encrypt(&input, &output2, 8, sched, zeroblock, 1);
 
        if (memcmp((char *)output2, (char *)output, 8)) {
            fprintf(stderr, 
@@ -91,8 +99,7 @@ char *argv[];
        /*
         * Now try decrypting....
         */
-       mit_des_ecb_encrypt(&output, &output2,
-                           (struct mit_des_ks_struct *)eblock.priv,0);
+       mit_des_cbc_encrypt(&output, &output2, 8, sched, zeroblock, 0);
 
        if (memcmp((char *)output2, (char *)input, 8)) {
            fprintf(stderr, 
@@ -103,10 +110,6 @@ char *argv[];
            error++;
        }
 
-        if (retval = krb5_finish_key(context, &eblock)) {
-            com_err("des verify", retval, "can't finish key");
-            exit(-1);
-        }
        num++;
     }
 
@@ -157,7 +160,6 @@ unsigned char cblock[];
  * Fake out the DES library, for the purposes of testing.
  */
 
-#include "des.h"
 #include "des_int.h"
 
 int
diff --git a/src/lib/crypto/des/f_README b/src/lib/crypto/des/f_README
deleted file mode 100644 (file)
index 0d381e3..0000000
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- * Copyright (c) 1990 Dennis Ferguson.  All rights reserved.
- *
- * Commercial use is permitted only if products which are derived from
- * or include this software are made available for purchase and/or use
- * in Canada.  Otherwise, redistribution and use in source and binary
- * forms are permitted.
- */
-
-Sorry about the poor quality of installation instructions.  Included
-here are replacements for the DES portions of Eric Young's kerberos
-DES library replacement.  To use this you will need his distribution.
-Untar the latter and:
-
-(1) Copy all .c and .h files into the distribution directory.  This will
-    overwrite some files and add others.
-
-(2) Apply the patch included here to set_key.c in the distribution directory.
-
-(3) Edit the Imakefile (or the Makefile) to include the following files
-    on the SRCS= line:
-
-       des_tables.c ecb_buffer.c make_sched.c
-
-    Add the following files to the OBJS= line:
-
-       des_tables.o ecb_buffer.o make_sched.o
-
-    Add the following file to the CODE= line:
-
-       des_tables.h
-
-Recompile and you're done.
-
-The salient differences between this DES and Eric Young's are as follows:
-
-(1) There are no dependencies on byte ordering, the ability to do
-    unaligned loads and stores, or any other machine dependencies
-    that I know of.  There are no #ifdef's.  The code could probably
-    be made faster by adding such things, but not enough to be worth
-    it.
-
-(2) Combined S and P tables are used for the inner loop of the cipher
-    routine and the E expansion is computed on the fly, like Eric
-    Young's code, but the computation is reordered from the standard
-    to save instructions.
-
-(3) The initial and final permutations are table driven, and take
-    about the same amount of work as a single round of the inner
-    loop (i.e. only about 12% of the work done for an ecb encryption
-    is spent in the IP and FP code).
-
-(4) Since NTP (for which this DES was originally implemented) uses
-    lots of keys to encrypt small things, the key permutation code
-    has been well worked over and is quite speedy (the amount of
-    work required to permute a key is on the order of that required
-    to do a single ECB encryption, more or less).
-
-(5) Since the code required to do an ECB encryption using the tables
-    is actually fairly compact, even with lots of inlining, it was
-    implemented as a macro and is expanded in situ where needed.
-
-On the one machine I ran a comparison on this code ran 80% faster than
-Eric's, compiled into a slightly smaller space, and did pass destest.
-I suspect this stuff is also faster, and not a lot larger, than the
-library MIT doesn't export with kerberos.  You mileage may vary.
-
-The silly copyright was a (probably ineffective) afterthought.  If it
-really inconveniences you give me a call.
diff --git a/src/lib/crypto/des/f_ecb.c b/src/lib/crypto/des/f_ecb.c
deleted file mode 100644 (file)
index a1d1dcb..0000000
+++ /dev/null
@@ -1,95 +0,0 @@
-/*
- * Copyright (c) 1990 Dennis Ferguson.  All rights reserved.
- *
- * Commercial use is permitted only if products which are derived from
- * or include this software are made available for purchase and/or use
- * in Canada.  Otherwise, redistribution and use in source and binary
- * forms are permitted.
- */
-
-/*
- * des_ecb_encrypt.c - do an encryption in ECB mode
- */
-#include "des_int.h"
-#include "f_tables.h"
-
-/*
- * des_ecb_encrypt - {en,de}crypt a block in ECB mode
- */
-int
-mit_des_ecb_encrypt(in, out, schedule, encrypt)
-       const mit_des_cblock *in;
-       mit_des_cblock *out;
-       mit_des_key_schedule schedule;
-       int encrypt;
-{
-       register unsigned DES_INT32 left, right;
-       register unsigned DES_INT32 temp;
-       register int i;
-
-       {
-               /*
-                * Need a temporary for copying the data in
-                */
-               register unsigned char *datap;
-
-               /*
-                * Copy the input block into the registers
-                */
-               datap = (unsigned char *)in;
-               GET_HALF_BLOCK(left, datap);
-               GET_HALF_BLOCK(right, datap);
-       }
-
-       /*
-        * Do the initial permutation.
-        */
-       DES_INITIAL_PERM(left, right, temp);
-
-       /*
-        * Now the rounds.  Use different code depending on whether it
-        * is an encryption or a decryption (gross, should keep both
-        * sets of keys in the key schedule instead).
-        */
-       if (encrypt) {
-               register unsigned DES_INT32 *kp;
-
-               kp = (unsigned DES_INT32 *)schedule;
-               for (i = 0; i < 8; i++) {
-                       DES_SP_ENCRYPT_ROUND(left, right, temp, kp);
-                       DES_SP_ENCRYPT_ROUND(right, left, temp, kp);
-               }
-       } else {
-               register unsigned DES_INT32 *kp;
-
-               /*
-                * Point kp past end of schedule
-                */
-               kp = ((unsigned DES_INT32 *)schedule) + (2 * 16);;
-               for (i = 0; i < 8; i++) {
-                       DES_SP_DECRYPT_ROUND(left, right, temp, kp);
-                       DES_SP_DECRYPT_ROUND(right, left, temp, kp);
-               }
-       }
-
-       /*
-        * Do the final permutation
-        */
-       DES_FINAL_PERM(left, right, temp);
-
-       /*
-        * Finally, copy the result out a byte at a time
-        */
-       {
-               register unsigned char *datap;
-
-               datap = (unsigned char *)out;
-               PUT_HALF_BLOCK(left, datap);
-               PUT_HALF_BLOCK(right, datap);
-       }
-
-       /*
-        * return nothing
-        */
-       return (0);
-}
diff --git a/src/lib/crypto/des/f_pcbc.c b/src/lib/crypto/des/f_pcbc.c
deleted file mode 100644 (file)
index cb44544..0000000
+++ /dev/null
@@ -1,207 +0,0 @@
-/*
- * Copyright (c) 1990 Dennis Ferguson.  All rights reserved.
- *
- * Commercial use is permitted only if products which are derived from
- * or include this software are made available for purchase and/or use
- * in Canada.  Otherwise, redistribution and use in source and binary
- * forms are permitted.
- */
-
-/*
- * des_pcbc_encrypt.c - encrypt a string of characters in error propagation mode
- */
-#include "des_int.h"
-#include "f_tables.h"
-
-/*
- * des_pcbc_encrypt - {en,de}crypt a stream in PCBC mode
- */
-int
-mit_des_pcbc_encrypt(in, out, length, schedule, ivec, encrypt)
-       mit_des_cblock *in;
-       mit_des_cblock *out;
-       long length;
-       mit_des_key_schedule schedule;
-       mit_des_cblock ivec;
-       int encrypt;
-{
-       register unsigned DES_INT32 left, right;
-       register unsigned DES_INT32 temp;
-       register unsigned DES_INT32 *kp;
-       register unsigned char *ip, *op;
-
-       /*
-        * Copy the key pointer, just once
-        */
-       kp = (unsigned DES_INT32 *)schedule;
-
-       /*
-        * Deal with encryption and decryption separately.
-        */
-       if (encrypt) {
-               register unsigned DES_INT32 plainl;
-               register unsigned DES_INT32 plainr;
-
-               /*
-                * Initialize left and right with the contents of the initial
-                * vector.
-                */
-               ip = (unsigned char *)ivec;
-               GET_HALF_BLOCK(left, ip);
-               GET_HALF_BLOCK(right, ip);
-
-               /*
-                * Suitably initialized, now work the length down 8 bytes
-                * at a time.
-                */
-               ip = (unsigned char *)in;
-               op = (unsigned char *)out;
-               while (length > 0) {
-                       /*
-                        * Get block of input.  If the length is
-                        * greater than 8 this is straight
-                        * forward.  Otherwise we have to fart around.
-                        */
-                       if (length > 8) {
-                               GET_HALF_BLOCK(plainl, ip);
-                               GET_HALF_BLOCK(plainr, ip);
-                               left ^= plainl;
-                               right ^= plainr;
-                               length -= 8;
-                       } else {
-                               /*
-                                * Oh, shoot.  We need to pad the
-                                * end with zeroes.  Work backwards
-                                * to do this.  We know this is the
-                                * last block, though, so we don't have
-                                * to save the plain text.
-                                */
-                               ip += (int) length;
-                               switch(length) {
-                               case 8:
-                                       right ^=  *(--ip) & FF_UINT32;
-                               case 7:
-                                       right ^= (*(--ip) & FF_UINT32) <<  8;
-                               case 6:
-                                       right ^= (*(--ip) & FF_UINT32) << 16;
-                               case 5:
-                                       right ^= (*(--ip) & FF_UINT32) << 24;
-                               case 4:
-                                       left  ^=  *(--ip) & FF_UINT32;
-                               case 3:
-                                       left  ^= (*(--ip) & FF_UINT32) <<  8;
-                               case 2:
-                                       left  ^= (*(--ip) & FF_UINT32) << 16;
-                               case 1:
-                                       left  ^= (*(--ip) & FF_UINT32) << 24;
-                                       break;
-                               }
-                               length = 0;
-                       }
-
-                       /*
-                        * Encrypt what we have
-                        */
-                       DES_DO_ENCRYPT(left, right, temp, kp);
-
-                       /*
-                        * Copy the results out
-                        */
-                       PUT_HALF_BLOCK(left, op);
-                       PUT_HALF_BLOCK(right, op);
-
-                       /*
-                        * Xor with the old plain text
-                        */
-                       left ^= plainl;
-                       right ^= plainr;
-               }
-       } else {
-               /*
-                * Decrypting is harder than encrypting because of
-                * the necessity of remembering a lot more things.
-                * Should think about this a little more...
-                */
-               unsigned DES_INT32 ocipherl, ocipherr;
-               unsigned DES_INT32 cipherl, cipherr;
-
-               if (length <= 0)
-                       return 0;
-
-               /*
-                * Prime the old cipher with ivec.
-                */
-               ip = (unsigned char *)ivec;
-               GET_HALF_BLOCK(ocipherl, ip);
-               GET_HALF_BLOCK(ocipherr, ip);
-
-               /*
-                * Now do this in earnest until we run out of length.
-                */
-               ip = (unsigned char *)in;
-               op = (unsigned char *)out;
-               for (;;) {              /* check done inside loop */
-                       /*
-                        * Read a block from the input into left and
-                        * right.  Save this cipher block for later.
-                        */
-                       GET_HALF_BLOCK(left, ip);
-                       GET_HALF_BLOCK(right, ip);
-                       cipherl = left;
-                       cipherr = right;
-
-                       /*
-                        * Decrypt this.
-                        */
-                       DES_DO_DECRYPT(left, right, temp, kp);
-
-                       /*
-                        * Xor with the old cipher to get plain
-                        * text.  Output 8 or less bytes of this.
-                        */
-                       left ^= ocipherl;
-                       right ^= ocipherr;
-                       if (length > 8) {
-                               length -= 8;
-                               PUT_HALF_BLOCK(left, op);
-                               PUT_HALF_BLOCK(right, op);
-                               /*
-                                * Save current cipher block here
-                                */
-                               ocipherl = cipherl ^ left;
-                               ocipherr = cipherr ^ right;
-                       } else {
-                               /*
-                                * Trouble here.  Start at end of output,
-                                * work backwards.
-                                */
-                               op += (int) length;
-                               switch(length) {
-                               case 8:
-                                       *(--op) = (unsigned char) (right & 0xff);
-                               case 7:
-                                       *(--op) = (unsigned char) ((right >> 8) & 0xff);
-                               case 6:
-                                       *(--op) = (unsigned char) ((right >> 16) & 0xff);
-                               case 5:
-                                       *(--op) = (unsigned char) ((right >> 24) & 0xff);
-                               case 4:
-                                       *(--op) = (unsigned char) (left & 0xff);
-                               case 3:
-                                       *(--op) = (unsigned char) ((left >> 8) & 0xff);
-                               case 2:
-                                       *(--op) = (unsigned char) ((left >> 16) & 0xff);
-                               case 1:
-                                       *(--op) = (unsigned char) ((left >> 24) & 0xff);
-                                       break;
-                               }
-                               break;          /* we're done */
-                       }
-               }
-       }
-
-       /*
-        * Done, return nothing.
-        */
-       return 0;
-}
diff --git a/src/lib/crypto/des/fin_rndkey.c b/src/lib/crypto/des/fin_rndkey.c
deleted file mode 100644 (file)
index 7b8a2c3..0000000
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * lib/crypto/des/fin_rndkey.c
- *
- * Copyright 1990,1991 by the Massachusetts Institute of Technology.
- * Copyright 1996 by Lehman Brothers, Inc.
- * All Rights Reserved.
- *
- * Export of this software from the United States of America may
- *   require a specific license from the United States Government.
- *   It is the responsibility of any person or organization contemplating
- *   export to obtain such a license before exporting.
- * 
- * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
- * distribute this software and its documentation for any purpose and
- * without fee is hereby granted, provided that the above copyright
- * notice appear in all copies and that both that copyright notice and
- * this permission notice appear in supporting documentation, and that
- * the name of M.I.T. or Lehman Brothers not be used in advertising or
- * publicity pertaining to distribution of the software without
- * specific, written prior permission.  M.I.T. and Lehman Brothers
- * make no representations about the suitability of this software for
- * any purpose.  It is provided "as is" without express or implied
- * warranty.
- */
-
-#include "k5-int.h"
-#include "des_int.h"
-
-/*
-        free any resources held by "seed" and assigned by init_random_key()
- */
-
-krb5_error_code mit_des_finish_random_key (eblock, p_state)
-    const krb5_encrypt_block * eblock;
-    krb5_pointer * p_state;
-{
-    mit_des_random_state * state = *p_state;
-
-    if (! state) return 0;
-
-    if (state->sequence.data) {
-       memset((char *)state->sequence.data, 0, state->sequence.length);
-       krb5_xfree(state->sequence.data);
-    }
-
-    mit_des_finish_key(&state->eblock);
-
-    krb5_xfree(state);
-    *p_state = 0;
-    return 0;
-}
diff --git a/src/lib/crypto/des/finish_key.c b/src/lib/crypto/des/finish_key.c
deleted file mode 100644 (file)
index e7e9e13..0000000
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * lib/crypto/des/finish_key.c
- *
- * Copyright 1990 by the Massachusetts Institute of Technology.
- * All Rights Reserved.
- *
- * Export of this software from the United States of America may
- *   require a specific license from the United States Government.
- *   It is the responsibility of any person or organization contemplating
- *   export to obtain such a license before exporting.
- * 
- * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
- * distribute this software and its documentation for any purpose and
- * without fee is hereby granted, provided that the above copyright
- * notice appear in all copies and that both that copyright notice and
- * this permission notice appear in supporting documentation, and that
- * the name of M.I.T. not be used in advertising or publicity pertaining
- * to distribution of the software without specific, written prior
- * permission.  M.I.T. makes no representations about the suitability of
- * this software for any purpose.  It is provided "as is" without express
- * or implied warranty.
- * 
- *
- */
-
-#include "k5-int.h"
-#include "des_int.h"
-
-/*
-       does any necessary clean-up on the eblock (such as releasing
-       resources held by eblock->priv).
-
-       returns: errors
- */
-
-krb5_error_code
-mit_des_finish_key (eblock)
-    krb5_encrypt_block FAR * eblock;
-{
-    if (eblock->priv) {
-       memset((char *)eblock->priv, 0, (size_t) eblock->priv_size);
-       free(eblock->priv);
-    }
-    eblock->priv = 0;
-    eblock->priv_size = 0;
-    /* free/clear other stuff here? */
-    return 0;
-}
diff --git a/src/lib/crypto/des/init_rkey.c b/src/lib/crypto/des/init_rkey.c
deleted file mode 100644 (file)
index 5096647..0000000
+++ /dev/null
@@ -1,167 +0,0 @@
-/*
- * lib/crypto/des/init_rkey.c
- *
- * Copyright 1990 by the Massachusetts Institute of Technology.
- * All Rights Reserved.
- *
- * Export of this software from the United States of America may
- *   require a specific license from the United States Government.
- *   It is the responsibility of any person or organization contemplating
- *   export to obtain such a license before exporting.
- * 
- * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
- * distribute this software and its documentation for any purpose and
- * without fee is hereby granted, provided that the above copyright
- * notice appear in all copies and that both that copyright notice and
- * this permission notice appear in supporting documentation, and that
- * the name of M.I.T. not be used in advertising or publicity pertaining
- * to distribution of the software without specific, written prior
- * permission.  M.I.T. makes no representations about the suitability of
- * this software for any purpose.  It is provided "as is" without express
- * or implied warranty.
- */
-
-#include "k5-int.h"
-#include "des_int.h"
-
-/*
-        initialize the random key generator using the encryption key,
-        "seedblock", and allocating private sequence information, filling
-        in "seed" with the address of such information.
-        "seed" is later passed to the random_key() function to provide
-        sequence information.
- */
-
-#ifndef min
-#define min(a,b) (((a) > (b)) ? (b) : (a))
-#endif
-
-krb5_error_code
-mit_des_init_random_key (eblock, seedblock, state)
-    const krb5_encrypt_block * eblock;
-    const krb5_keyblock * seedblock;
-    krb5_pointer * state;
-{
-    mit_des_random_state * p_state = 0;
-    krb5_keyblock *new_key;
-    krb5_enctype enctype = eblock->crypto_entry->proto_enctype;
-    krb5_error_code kret = 0;
-    krb5_address **addrs = 0;
-    krb5_data seed;
-    krb5_int32 now;
-    krb5_int32 unow;
-    unsigned char *cp;
-
-    switch (enctype)
-    {
-    case ENCTYPE_DES_CBC_CRC:
-    case ENCTYPE_DES_CBC_MD4:
-    case ENCTYPE_DES_CBC_MD5:
-    case ENCTYPE_DES_CBC_RAW:
-       enctype = ENCTYPE_DES_CBC_RAW;
-       break;
-
-    case ENCTYPE_DES3_CBC_SHA:
-    case ENCTYPE_DES3_CBC_RAW:
-       enctype = ENCTYPE_DES3_CBC_RAW;
-       break;
-
-    default:
-       return KRB5_BAD_ENCTYPE;
-    }
-
-    p_state = (mit_des_random_state *) malloc(sizeof(mit_des_random_state));
-    *state = (krb5_pointer) p_state;
-
-    if (! p_state) {
-       kret = ENOMEM;
-       goto cleanup;
-    }
-
-    memset(p_state, 0, sizeof(*p_state));
-    p_state->eblock.crypto_entry = krb5_enctype_array[enctype]->system;
-    p_state->sequence.length = p_state->eblock.crypto_entry->keysize;
-    p_state->sequence.data = (krb5_pointer) malloc(p_state->sequence.length);
-
-    if (! p_state->sequence.data) {
-       kret = ENOMEM;
-       goto cleanup;
-    }
-
-    /*
-     * Generate a temporary value that is based on the
-     * input seed and the hostid (sequence number)
-     * such that it gives no useful information about the input.
-     *
-     * Then use the temporary value as the new seed and the current
-     * time as a sequence number to give us a stream that was not
-     * previously used.
-     *
-     * This result will be the seed for the random number stream
-     * (the sequence number will start at zero).
-     */
-
-    /* seed = input */
-    seed.data = seedblock->contents;
-    seed.length = seedblock->length;
-    kret = mit_des_set_random_generator_seed(&seed, p_state);
-    if (kret) goto cleanup;
-
-    /* sequence = hostid */
-    if (!krb5_crypto_os_localaddr(&addrs) && addrs && *addrs) {
-       memcpy((char *)p_state->sequence.data, (char *)addrs[0]->contents,
-             min(p_state->sequence.length, addrs[0]->length));
-       /* XXX may not do all of the sequence number. */
-    }
-    if (addrs) {
-       /* can't use krb5_free_addresses due to circular dependencies in
-          libraries */
-       register krb5_address **addr2;
-       for (addr2 = addrs; *addr2; addr2++) {
-           krb5_xfree((*addr2)->contents);
-           krb5_xfree(*addr2);
-       }
-       krb5_xfree(addrs);
-    }
-
-    /* tmp.seed = random(input,hostid) */
-    kret = mit_des_random_key(NULL, p_state, &new_key);
-    if (kret) goto cleanup;
-    seed.data = new_key->contents;
-    seed.length = new_key->length;
-    kret = mit_des_set_random_generator_seed(&seed, p_state);
-    (void) memset(new_key->contents, 0, new_key->length);
-    krb5_xfree(new_key->contents);
-    krb5_xfree(new_key);
-    if (kret) goto cleanup;
-
-    /* sequence = time */
-    (void) krb5_crypto_us_timeofday(&now, &unow);
-    cp = p_state->sequence.data;
-    *cp++ = (now >> 24) & 0xff;
-    *cp++ = (now >> 16) & 0xff;
-    *cp++ = (now >> 8) & 0xff;
-    *cp++ = now & 0xff;
-    *cp++ = (unow >> 24) & 0xff;
-    *cp++ = (unow >> 16) & 0xff;
-    *cp++ = (unow >> 8) & 0xff;
-    *cp++ = unow &0xff;
-
-    /* seed = random(tmp.seed, time) */
-    kret = mit_des_random_key(NULL, p_state, &new_key);
-    if (kret) goto cleanup;
-    seed.data = new_key->contents;
-    seed.length = new_key->length;
-    kret = mit_des_set_random_generator_seed(&seed, p_state);
-    (void) memset(new_key->contents, 0, new_key->length);
-    krb5_xfree(new_key->contents);
-    krb5_xfree(new_key);
-    if (kret) goto cleanup;
-    
-    return 0;
-
-cleanup:
-    if (kret)
-       mit_des_finish_random_key(eblock, state);
-    return kret;
-}
diff --git a/src/lib/crypto/des/process_ky.c b/src/lib/crypto/des/process_ky.c
deleted file mode 100644 (file)
index 64cef57..0000000
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- * lib/crypto/des/process_ky.c
- *
- * Copyright 1990 by the Massachusetts Institute of Technology.
- * All Rights Reserved.
- *
- * Export of this software from the United States of America may
- *   require a specific license from the United States Government.
- *   It is the responsibility of any person or organization contemplating
- *   export to obtain such a license before exporting.
- * 
- * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
- * distribute this software and its documentation for any purpose and
- * without fee is hereby granted, provided that the above copyright
- * notice appear in all copies and that both that copyright notice and
- * this permission notice appear in supporting documentation, and that
- * the name of M.I.T. not be used in advertising or publicity pertaining
- * to distribution of the software without specific, written prior
- * permission.  M.I.T. makes no representations about the suitability of
- * this software for any purpose.  It is provided "as is" without express
- * or implied warranty.
- */
-
-#include "k5-int.h"
-#include "des_int.h"
-
-/*
-        does any necessary key preprocessing (such as computing key
-                schedules for DES).
-        eblock->crypto_entry must be set by the caller; the other elements
-        of eblock are to be assigned by this function.
-        [in particular, eblock->key must be set by this function if the key
-        is needed in raw form by the encryption routine]
-
-        The caller may not move or reallocate "keyblock" before calling
-        finish_key on "eblock"
-
-        returns: errors
- */
-
-krb5_error_code
-mit_des_process_key (eblock, keyblock)
-    krb5_encrypt_block * eblock;
-    const krb5_keyblock * keyblock;
-{
-    struct mit_des_ks_struct       *schedule;      /* pointer to key schedules */
-    
-    if (keyblock->length != sizeof (mit_des_cblock))
-       return KRB5_BAD_KEYSIZE;
-
-    if ( !(schedule = (struct mit_des_ks_struct *) malloc(sizeof(mit_des_key_schedule))) )
-        return ENOMEM;
-#define cleanup() { free( (char *) schedule); }
-
-    switch (mit_des_key_sched (keyblock->contents, schedule)) {
-    case -1:
-       cleanup();
-       return KRB5DES_BAD_KEYPAR;
-
-    case -2:
-       cleanup();
-       return KRB5DES_WEAK_KEY;
-
-    default:
-       eblock->key = (krb5_keyblock *) keyblock;
-       eblock->priv = (krb5_pointer) schedule;
-       eblock->priv_size = (krb5_int32) sizeof(mit_des_key_schedule);
-       return 0;
-    }
-}
diff --git a/src/lib/crypto/des/random_key.c b/src/lib/crypto/des/random_key.c
deleted file mode 100644 (file)
index 1dc4600..0000000
+++ /dev/null
@@ -1,95 +0,0 @@
-/*
- * lib/crypto/des/random_key.c
- *
- * Copyright 1990,1991 by the Massachusetts Institute of Technology.
- * Copyright 1996 by Lehman Brothers, Inc.
- * All Rights Reserved.
- *
- * Export of this software from the United States of America may
- *   require a specific license from the United States Government.
- *   It is the responsibility of any person or organization contemplating
- *   export to obtain such a license before exporting.
- * 
- * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
- * distribute this software and its documentation for any purpose and
- * without fee is hereby granted, provided that the above copyright
- * notice appear in all copies and that both that copyright notice and
- * this permission notice appear in supporting documentation, and that
- * the name of M.I.T. or Lehman Brothers not be used in advertising or
- * publicity pertaining to distribution of the software without
- * specific, written prior permission.  M.I.T. and Lehman Brothers
- * make no representations about the suitability of this software for
- * any purpose.  It is provided "as is" without express or implied
- * warranty.
- */
-
-#include "k5-int.h"
-#include "des_int.h"
-
-static void mit_des_generate_random_key
-       PROTOTYPE((mit_des_random_state * state, krb5_keyblock * randkey));
-
-
-/*
-        generate a random encryption key, allocating storage for it and
-        filling in the keyblock address in *keyblock
- */
-
-krb5_error_code
-mit_des_random_key (eblock, state, keyblock)
-    const krb5_encrypt_block * eblock;
-    krb5_pointer state;
-    krb5_keyblock ** keyblock;
-{
-    krb5_keyblock *randkey;
-    int keysize = ((mit_des_random_state *)state)->eblock.crypto_entry->keysize;
-
-    if (eblock == NULL)
-       /* We are being called from the random number initialization routine */
-       eblock = &((mit_des_random_state *)state)->eblock;
-
-    if (!(randkey = (krb5_keyblock *)malloc(sizeof(*randkey))))
-       return ENOMEM;
-    if (!(randkey->contents = (krb5_octet *)malloc(keysize))) {
-       krb5_xfree(randkey);
-       return ENOMEM;
-    }
-    randkey->magic = KV5M_KEYBLOCK;
-    randkey->length = keysize;
-    randkey->enctype = eblock->crypto_entry->proto_enctype;
-
-    do {
-       mit_des_generate_random_key(state, randkey);
-       mit_des_fixup_keyblock_parity(randkey);
-    } while (mit_des_is_weak_keyblock(randkey));
-
-    *keyblock = randkey;
-    return 0;
-}
-
-static mit_des_cblock zero_ivec = { 0, 0, 0, 0, 0, 0, 0, 0 };
-
-static void
-mit_des_generate_random_key(state, randkey)
-    mit_des_random_state * state;
-    krb5_keyblock * randkey;
-{
-    krb5_encrypt_block *eblock = &state->eblock;
-    int i;
-
-    (* state->eblock.crypto_entry->encrypt_func)
-       (state->sequence.data /*in*/, randkey->contents /*out*/,
-        state->sequence.length, eblock, zero_ivec);
-    if (state->sequence.length > sizeof(mit_des_cblock))
-       (* state->eblock.crypto_entry->encrypt_func)
-           (randkey->contents /*in*/, randkey->contents /*out*/,
-            randkey->length, eblock,
-            randkey->contents + randkey->length - sizeof(mit_des_cblock));
-
-    /* Increment the sequence number, with wraparound (LSB) */
-    for (i = 0; i < state->sequence.length; i++) {
-       state->sequence.data[i] = (state->sequence.data[i] + 1) & 0xff;
-       if (state->sequence.data[i])
-           break;
-    }
-}
index 8a2b1415b7673587b1c786cf0a7856b105842b55..79b7c9cbd84602612e281dfb8e70166e1e844cfb 100644 (file)
  * or implied warranty.
  */
 
+/*
+ * Copyright (C) 1998 by the FundsXpress, INC.
+ * 
+ * All rights reserved.
+ * 
+ * Export of this software from the United States of America may require
+ * a specific license from the United States Government.  It is the
+ * responsibility of any person or organization contemplating export to
+ * obtain such a license before exporting.
+ * 
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of FundsXpress. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  FundsXpress makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
 #include "k5-int.h"
 #include "des_int.h"
 
@@ -41,8 +67,7 @@
  */
 
 krb5_error_code
-mit_des_string_to_key (eblock, keyblock, data, salt)
-const krb5_encrypt_block FAR * eblock;
+mit_des_string_to_key_int (keyblock, data, salt)
 krb5_keyblock FAR * keyblock;
 const krb5_data FAR * data;
 const krb5_data FAR * salt;
@@ -59,28 +84,19 @@ const krb5_data FAR * salt;
     register char *p_char;
     char k_char[64];
     mit_des_key_schedule key_sked;
-    krb5_enctype enctype = eblock->crypto_entry->proto_enctype;
 
 #ifndef min
 #define min(A, B) ((A) < (B) ? (A): (B))
 #endif
 
-    if ((enctype != ENCTYPE_DES_CBC_CRC) && (enctype != ENCTYPE_DES_CBC_MD4) &&
-       (enctype != ENCTYPE_DES_CBC_MD5) && (enctype != ENCTYPE_DES_CBC_RAW)) 
-       return (KRB5_PROG_ETYPE_NOSUPP);
-
-    if ( !(keyblock->contents = (krb5_octet *)malloc(sizeof(mit_des_cblock))) )
-       return(ENOMEM);
-
     keyblock->magic = KV5M_KEYBLOCK;
     keyblock->length = sizeof(mit_des_cblock);
-    keyblock->enctype = eblock->crypto_entry->proto_enctype;
     key = keyblock->contents;
 
     if (salt) {
       if (salt->length == -1) {
        /* cheat and do AFS string2key instead */
-       return mit_afs_string_to_key (eblock, keyblock, data, salt);
+       return mit_afs_string_to_key (keyblock, data, salt);
       } else 
        length = data->length + salt->length;
       }
diff --git a/src/lib/crypto/des/t_random.c b/src/lib/crypto/des/t_random.c
deleted file mode 100644 (file)
index bc013bd..0000000
+++ /dev/null
@@ -1,117 +0,0 @@
-/*
- * lib/crypto/des/t_random.c
- *
- * Copyright 1996 by the Massachusetts Institute of Technology.
- * All Rights Reserved.
- *
- * Export of this software from the United States of America may
- *   require a specific license from the United States Government.
- *   It is the responsibility of any person or organization contemplating
- *   export to obtain such a license before exporting.
- * 
- * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
- * distribute this software and its documentation for any purpose and
- * without fee is hereby granted, provided that the above copyright
- * notice appear in all copies and that both that copyright notice and
- * this permission notice appear in supporting documentation, and that
- * the name of M.I.T. not be used in advertising or publicity pertaining
- * to distribution of the software without specific, written prior
- * permission.  M.I.T. makes no representations about the suitability of
- * this software for any purpose.  It is provided "as is" without express
- * or implied warranty.
- * 
- *
- * Test a DES implementation against known inputs & outputs
- */
-
-#include "k5-int.h"
-#include "des_int.h"
-#include <stdio.h>
-#include "com_err.h"
-
-extern krb5_cryptosystem_entry mit_des_cryptosystem_entry;
-
-char *progname;
-int nflag = 2;
-int vflag;
-int mflag;
-int zflag;
-int pid;
-int mit_des_debug;
-
-krb5_data kdata;
-
-unsigned char key2[8] = { 0x08,0x19,0x2a,0x3b,0x4c,0x5d,0x6e,0x7f };
-unsigned char zerokey[8] = { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 };
-
-void print_key(key)
-       krb5_keyblock *key;
-{
-       int     i;
-
-       printf("key type: %d, length = %d, contents =", key->enctype,
-              key->length);
-       for (i=0; i < key->length; i++) {
-               printf(" %02x", key->contents[i]);
-       }
-       printf("\n");
-}
-
-/*
- * Can also add :
- * plaintext = 0, key = 0, cipher = 0x8ca64de9c1b123a7 (or is it a 1?)
- */
-
-void
-main(argc,argv)
-    int argc;
-    char *argv[];
-{
-    /* Local Declarations */
-    krb5_context context;
-    krb5_encrypt_block eblock;
-    krb5_keyblock keyblock, *randkey;
-    void *random_seed = 0;
-
-#ifdef WINDOWS
-    /* Set screen window buffer to infinite size -- MS default is tiny.  */
-    _wsetscreenbuf (fileno (stdout), _WINBUFINF);
-#endif
-
-    /* do some initialisation */
-    krb5_init_context(&context);
-
-    krb5_use_enctype(context, &eblock, ENCTYPE_DES_CBC_CRC);
-    keyblock.enctype = ENCTYPE_DES_CBC_CRC;
-    keyblock.length = sizeof(mit_des_cblock);
-
-    keyblock.contents = key2;
-
-    printf("init_random: ");
-    print_key(&keyblock);
-    krb5_init_random_key(context, &eblock, &keyblock, &random_seed);
-    krb5_random_key(context, &eblock, random_seed, &randkey);
-    print_key(randkey);
-    krb5_free_keyblock(context, randkey);
-    krb5_random_key(context, &eblock, random_seed, &randkey);
-    print_key(randkey);
-    krb5_free_keyblock(context, randkey);
-    krb5_finish_random_key(context, &eblock, &random_seed);
-
-    keyblock.contents = zerokey;
-
-    printf("\n\ninit_random: ");
-    print_key(&keyblock);
-
-    krb5_init_random_key(context, &eblock, &keyblock, &random_seed);
-    krb5_random_key(context, &eblock, random_seed, &randkey);
-    print_key(randkey);
-    krb5_free_keyblock(context, randkey);
-    krb5_random_key(context, &eblock, random_seed, &randkey);
-    print_key(randkey);
-    krb5_free_keyblock(context, randkey);
-    krb5_finish_random_key(context, &eblock, &random_seed);
-
-    krb5_free_context(context);
-}
-
index 82a73e21fb4e39fdee10d5fdc1d6a8a2ee925b3d..e8a7dc0eed89e864b414960a98c50cb18e0783be 100644 (file)
  *             -1 ==> error
  */
 
+/*
+ * Copyright (C) 1998 by the FundsXpress, INC.
+ * 
+ * All rights reserved.
+ * 
+ * Export of this software from the United States of America may require
+ * a specific license from the United States Government.  It is the
+ * responsibility of any person or organization contemplating export to
+ * obtain such a license before exporting.
+ * 
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of FundsXpress. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  FundsXpress makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
 #include "k5-int.h"
 #include "des_int.h"
 #include <stdio.h>
 #include "com_err.h"
 
-extern krb5_cryptosystem_entry mit_des_cryptosystem_entry;
-
 char *progname;
 int nflag = 2;
 int vflag;
@@ -43,10 +67,6 @@ int zflag;
 int pid;
 int mit_des_debug;
 
-krb5_encrypt_block eblock;
-krb5_keyblock keyblock;
-krb5_data kdata;
-
 unsigned char cipher_text[64];
 unsigned char clear_text[64] = "Now is the time for all " ;
 unsigned char clear_text2[64] = "7654321 Now is the time for ";
@@ -56,23 +76,6 @@ unsigned char zero_text[8] = {0x0,0,0,0,0,0,0,0};
 unsigned char msb_text[8] = {0x0,0,0,0, 0,0,0,0x40}; /* to ANSI MSB */
 unsigned char *input;
 
-unsigned char *nfold_in[] = {
-    "basch",
-    "eichin",
-    "sommerfeld",
-    "MASSACHVSETTS INSTITVTE OF TECHNOLOGY" };
-
-unsigned char nfold_192[4][24] = {
-    { 0x1a, 0xab, 0x6b, 0x42, 0x96, 0x4b, 0x98, 0xb2, 0x1f, 0x8c, 0xde, 0x2d,
-      0x24, 0x48, 0xba, 0x34, 0x55, 0xd7, 0x86, 0x2c, 0x97, 0x31, 0x64, 0x3f },
-    { 0x65, 0x69, 0x63, 0x68, 0x69, 0x6e, 0x4b, 0x73, 0x2b, 0x4b, 0x1b, 0x43,
-      0xda, 0x1a, 0x5b, 0x99, 0x5a, 0x58, 0xd2, 0xc6, 0xd0, 0xd2, 0xdc, 0xca },
-    { 0x2f, 0x7a, 0x98, 0x55, 0x7c, 0x6e, 0xe4, 0xab, 0xad, 0xf4, 0xe7, 0x11,
-      0x92, 0xdd, 0x44, 0x2b, 0xd4, 0xff, 0x53, 0x25, 0xa5, 0xde, 0xf7, 0x5c },
-    { 0xdb, 0x3b, 0x0d, 0x8f, 0x0b, 0x06, 0x1e, 0x60, 0x32, 0x82, 0xb3, 0x08,
-      0xa5, 0x08, 0x41, 0x22, 0x9a, 0xd7, 0x98, 0xfa, 0xb9, 0x54, 0x0c, 0x1b }
-};
-
 /* 0x0123456789abcdef */
 unsigned char default_key[8] = {
     0x01,0x23,0x45,0x67,0x89,0xab,0xcd,0xef
@@ -86,7 +89,6 @@ unsigned char default_ivec[8] = {
 unsigned char *ivec;
 unsigned char zero_key[8] = {1,1,1,1,1,1,1,1}; /* just parity bits */
 int i,j;
-krb5_error_code retval;
 
 unsigned char cipher1[8] = {
     0x25,0xdd,0xac,0x3e,0x96,0x17,0x64,0x67
@@ -117,14 +119,15 @@ unsigned char mresult[8] = {
  * plaintext = 0, key = 0, cipher = 0x8ca64de9c1b123a7 (or is it a 1?)
  */
 
-void
+mit_des_key_schedule sched;
+
+int
 main(argc,argv)
     int argc;
     char *argv[];
 {
     /* Local Declarations */
-    krb5_context context;
-    int         in_length;
+    int         in_length, retval;
     void do_encrypt();
     void do_decrypt();
 
@@ -164,23 +167,13 @@ main(argc,argv)
     }
 
     /* do some initialisation */
-    initialize_krb5_error_table(); 
-    krb5_init_context(&context);
-
-    krb5_use_enctype(context, &eblock, ENCTYPE_DES_CBC_CRC);
-    keyblock.enctype = ENCTYPE_DES_CBC_CRC;
-    keyblock.length = sizeof(mit_des_cblock);
 
     /* use known input and key */
 
     /* ECB zero text zero key */
     if (zflag) {
        input = zero_text;
-       keyblock.contents = (krb5_octet *)zero_key;
-       if (retval = krb5_process_key(context, &eblock,&keyblock)) {
-           com_err("des verify", retval, "can't process zero key");
-           exit(-1);
-       }
+       mit_des_key_sched(zero_key, sched);
        printf("plaintext = key = 0, cipher = 0x8ca64de9c1b123a7\n");
        do_encrypt(input,cipher_text);
        printf("\tcipher  = (low to high bytes)\n\t\t");
@@ -188,26 +181,17 @@ main(argc,argv)
            printf("%02x ",cipher_text[j]);
        printf("\n");
        do_decrypt(output,cipher_text);
-       if (retval = krb5_finish_key(context, &eblock)) {
-           com_err("des verify", retval, "can't finish zero key");
-           exit(-1);
-       }
        if ( memcmp((char *)cipher_text, (char *)zresult, 8) ) {
            printf("verify: error in zero key test\n");
            exit(-1);
        }
 
-       krb5_free_context(context);
        exit(0);
     }
 
     if (mflag) {
        input = msb_text;
-       keyblock.contents = (krb5_octet *)key3;
-       if (retval = krb5_process_key(context, &eblock,&keyblock)) {
-           com_err("des verify", retval, "can't process key3");
-           exit(-1);
-       }
+       mit_des_key_sched(key3, sched);
        printf("plaintext = 0x00 00 00 00 00 00 00 40, ");
        printf("key = 0x80 01 01 01 01 01 01 01\n");
        printf("        cipher = 0xa380e02a6be54696\n");
@@ -218,26 +202,17 @@ main(argc,argv)
        }
        printf("\n");
        do_decrypt(output,cipher_text);
-       if (retval = krb5_finish_key(context, &eblock)) {
-           com_err("des verify", retval, "can't finish key3");
-           exit(-1);
-       }
        if ( memcmp((char *)cipher_text, (char *)mresult, 8) ) {
            printf("verify: error in msb test\n");
            exit(-1);
        }
-       krb5_free_context(context);
        exit(0);
     }
 
     /* ECB mode Davies and Price */
     {
        input = zero_text;
-       keyblock.contents = (krb5_octet *)key2;
-       if (retval = krb5_process_key(context, &eblock,&keyblock)) {
-           com_err("des verify", retval, "can't process key2");
-           exit(-1);
-       }
+       mit_des_key_sched(key2, sched);
        printf("Examples per FIPS publication 81, keys ivs and cipher\n");
        printf("in hex.  These are the correct answers, see below for\n");
        printf("the actual answers.\n\n");
@@ -253,10 +228,6 @@ main(argc,argv)
            printf("%02x ",cipher_text[j]);
        printf("\n\n");
        do_decrypt(output,cipher_text);
-       if (retval = krb5_finish_key(context, &eblock)) {
-           com_err("des verify", retval, "can't finish key2");
-           exit(-1);
-       }
        if ( memcmp((char *)cipher_text, (char *)cipher1, 8) ) {
            printf("verify: error in ECB encryption\n");
            exit(-1);
@@ -267,11 +238,7 @@ main(argc,argv)
 
     /* ECB mode */
     {
-       keyblock.contents = (krb5_octet *)default_key;
-       if (retval = krb5_process_key(context, &eblock,&keyblock)) {
-           com_err("des verify", retval, "can't process key2");
-           exit(-1);
-       }
+       mit_des_key_sched(default_key, sched);
        input = clear_text;
        ivec = default_ivec;
        printf("EXAMPLE ECB\tkey = 0123456789abcdef\n");
@@ -306,14 +273,14 @@ main(argc,argv)
     if (retval = mit_des_cbc_encrypt((mit_des_cblock *) input,
                                     (mit_des_cblock *) cipher_text,
                                     (size_t) in_length, 
-                                    (struct mit_des_ks_struct *)eblock.priv,
+                                    sched,
                                     ivec,
                                     MIT_DES_ENCRYPT)) {
        com_err("des verify", retval, "can't encrypt");
        exit(-1);
     }
     printf("\tciphertext = (low to high bytes)\n");
-    for (i = 0; i <= 7; i++) {
+    for (i = 0; i <= 2; i++) {
        printf("\t\t");
        for (j = 0; j <= 7; j++) {
            printf("%02x ",cipher_text[i*8+j]);
@@ -323,7 +290,7 @@ main(argc,argv)
     if (retval = mit_des_cbc_encrypt((mit_des_cblock *) cipher_text,
                                     (mit_des_cblock *) clear_text,
                                     (size_t) in_length, 
-                                    eblock.priv,
+                                    sched,
                                     ivec,
                                     MIT_DES_DECRYPT)) {
        com_err("des verify", retval, "can't decrypt");
@@ -345,16 +312,12 @@ main(argc,argv)
     printf("or some part thereof\n");
     input = clear_text2;
     mit_des_cbc_cksum(input,cipher_text,(long) strlen((char *)input),
-                     eblock.priv,ivec);
+                     sched,ivec);
     printf("ACTUAL CBC checksum\n");
     printf("\t\tencrypted cksum = (low to high bytes)\n\t\t");
     for (j = 0; j<=7; j++)
        printf("%02x ",cipher_text[j]);
     printf("\n\n");
-    if (retval = krb5_finish_key(context, &eblock)) {
-       com_err("des verify", retval, "can't finish key2");
-       exit(-1);
-    }
     if ( memcmp((char *)cipher_text, (char *)checksum, 8) ) {
        printf("verify: error in CBC cheksum\n");
        exit(-1);
@@ -362,25 +325,6 @@ main(argc,argv)
     else 
        printf("verify: CBC checksum is correct\n\n");
 
-    printf("N-fold\n");
-    for (i=0; i<sizeof(nfold_in)/sizeof(char *); i++) {
-       kdata.data = nfold_in[i];
-       kdata.length = strlen(kdata.data);
-       printf("\tInput:\t\"%.*s\"\n", kdata.length, kdata.data);
-       printf("\t192-Fold:\t");
-       mit_des_n_fold(kdata.data, kdata.length, cipher_text, 24);
-       for (j=0; j<24; j++)
-           printf("%s%02x", (j&3) ? "" : " ", cipher_text[j]);
-       printf("\n");
-       if (memcmp(cipher_text, nfold_192[i], 24)) {
-           printf("verify: error in n-fold\n");
-           exit(-1);
-       };
-    }
-    printf("verify: N-fold is correct\n\n");
-
-    krb5_free_context(context);
-    
     exit(0);
 }
 
@@ -412,9 +356,11 @@ do_encrypt(in,out)
     char *out;
 {
     for (i =1; i<=nflag; i++) {
-       mit_des_ecb_encrypt((mit_des_cblock *)in,
+       mit_des_cbc_encrypt((mit_des_cblock *)in,
                            (mit_des_cblock *)out,
-                           (struct mit_des_ks_struct *)eblock.priv,
+                           8,
+                           sched,
+                           zero_text,
                            MIT_DES_ENCRYPT);
        if (mit_des_debug) {
            printf("\nclear %s\n",in);
@@ -434,9 +380,11 @@ do_decrypt(in,out)
     /* try to invert it */
 {
     for (i =1; i<=nflag; i++) {
-       mit_des_ecb_encrypt((mit_des_cblock *)out,
+       mit_des_cbc_encrypt((mit_des_cblock *)out,
                            (mit_des_cblock *)in,
-                           (struct mit_des_ks_struct *)eblock.priv,
+                           8,
+                           sched,
+                           zero_text,
                            MIT_DES_DECRYPT);
        if (mit_des_debug) {
            printf("clear %s\n",in);
@@ -453,8 +401,6 @@ do_decrypt(in,out)
  * Fake out the DES library, for the purposes of testing.
  */
 
-#include "des.h"
-
 int
 mit_des_is_weak_key(key)
     mit_des_cblock key;
diff --git a/src/lib/crypto/des/u_nfold.c b/src/lib/crypto/des/u_nfold.c
deleted file mode 100644 (file)
index 6da58cb..0000000
+++ /dev/null
@@ -1,99 +0,0 @@
-/*
- * Copyright 1995 by Richard P. Basch.  All Rights Reserved.
- * Copyright 1995 by Lehman Brothers, Inc.  All Rights Reserved.
- *
- * Export of this software from the United States of America may
- *   require a specific license from the United States Government.
- *   It is the responsibility of any person or organization contemplating
- *   export to obtain such a license before exporting.
- * 
- * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
- * distribute this software and its documentation for any purpose and
- * without fee is hereby granted, provided that the above copyright
- * notice appear in all copies and that both that copyright notice and
- * this permission notice appear in supporting documentation, and that
- * the name of Richard P. Basch, Lehman Brothers and M.I.T. not be used
- * in advertising or publicity pertaining to distribution of the software
- * without specific, written prior permission.  Richard P. Basch,
- * Lehman Brothers and M.I.T. make no representations about the suitability
- * of this software for any purpose.  It is provided "as is" without
- * express or implied warranty.
- *
- *
- * N-folding algorithm
- *    Described in "A Better Key Schedule for DES-like Ciphers"
- *    by Uri Blumenthal and Steven M. Bellovin
- *    based on the work done by Lars Knudsen.
- *
- * To n-fold a number X, replicate the input value X to a length that is
- * the least common multiple of n and the length of X.  Before each
- * repetition, the input value is rotated to the right by 13 bit positions.
- * The successive n-bit chunks are added together using 1's complement
- * addition (addition with end-around carry) to yield a n-bit result.
- *
- * The algorithm here assumes that the input and output are padded to
- * octet boundaries (8-bit multiple).
- */
-
-#include "k5-int.h"
-
-#define ROTATE_VALUE 13
-
-krb5_error_code
-mit_des_n_fold(inbuf, inlen, outbuf, outlen)
-    krb5_octet *inbuf;
-    size_t inlen;
-    krb5_octet *outbuf;
-    size_t outlen;
-{
-    register int bytes;
-    register krb5_octet *tempbuf;
-    
-    if (inbuf == (krb5_octet *)NULL)
-       return EINVAL;
-    if (outbuf == (krb5_octet *)NULL)
-       return EINVAL;
-
-    tempbuf = (krb5_octet *)malloc(inlen);
-    if (tempbuf == (krb5_octet *)NULL)
-       return ENOMEM;
-
-    memset(outbuf, 0, outlen);
-    bytes = 0;
-
-#ifndef min
-#define min(a,b) ((a) < (b) ? (a) : (b))
-#endif
-
-    do {
-       unsigned int j, k;
-
-       /* Rotate input */
-       k = ((bytes/inlen) * ROTATE_VALUE) % (inlen*8);
-       for (j = (k+7)/8; j < inlen + (k+7)/8; j++)
-           tempbuf[j % inlen] =
-               ((inbuf[((8*j-k)/8)%inlen] << ((8-(k&7))&7)) +
-                ((k&7) ? (inbuf[((8*j-k)/8 +1)%inlen] >> (k&7)) : 0))
-               & 0xff;
-
-       for (k=0, j=inlen; j--; ) {
-           k += outbuf[(bytes+j) % outlen] + tempbuf[j];
-           outbuf[(bytes+j) % outlen] = k & 0xff;
-           k >>= 8;
-       }
-       j = bytes % outlen;
-       while (k) {
-           if (j == 0)
-               j = outlen;
-           j--;
-           k += outbuf[j];
-           outbuf[j] = k & 0xff;
-           k >>= 8;
-       }
-       bytes += inlen;
-    } while (bytes % outlen);
-
-    free(tempbuf);
-    
-    return 0;
-}
diff --git a/src/lib/crypto/des/u_rn_key.c b/src/lib/crypto/des/u_rn_key.c
deleted file mode 100644 (file)
index 44d3c73..0000000
+++ /dev/null
@@ -1,139 +0,0 @@
-/*
- * Copyright 1996 by Richard P. Basch.  All Rights Reserved.
- * Copyright 1996 by Lehman Brothers, Inc.  All Rights Reserved.
- *
- * Export of this software from the United States of America may
- *   require a specific license from the United States Government.
- *   It is the responsibility of any person or organization contemplating
- *   export to obtain such a license before exporting.
- * 
- * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
- * distribute this software and its documentation for any purpose and
- * without fee is hereby granted, provided that the above copyright
- * notice appear in all copies and that both that copyright notice and
- * this permission notice appear in supporting documentation, and that
- * the name of Richard P. Basch, Lehman Brothers and M.I.T. not be used
- * in advertising or publicity pertaining to distribution of the software
- * without specific, written prior permission.  Richard P. Basch,
- * Lehman Brothers and M.I.T. make no representations about the suitability
- * of this software for any purpose.  It is provided "as is" without
- * express or implied warranty.
- *
- *
- * Based on the version written by Mark Lillibridge, MIT Project Athena.
- *
- * Under U.S. law, this software may not be exported outside the US
- * without license from the U.S. Commerce department.
- */
-
-#include "k5-int.h"
-#include "des_int.h"
-
-int
-mit_des_is_weak_keyblock(keyblock)
-    krb5_keyblock * keyblock;
-{
-    int i;
-    
-    for (i = 0; i < keyblock->length/sizeof(mit_des_cblock); i++)
-       if (mit_des_is_weak_key(*((mit_des_cblock *)keyblock->contents + i)))
-           return 1;
-    return 0;
-}
-
-void
-mit_des_fixup_keyblock_parity(keyblock)
-    krb5_keyblock * keyblock;
-{
-    int i;
-    
-    for (i = 0; i < keyblock->length/sizeof(mit_des_cblock); i++)
-       mit_des_fixup_key_parity(*((mit_des_cblock *)keyblock->contents + i));
-}
-
-/*
- * mit_des_set_random_generator_seed: this routine is used to select a random
- *                                number stream.  The stream that results is
- *                                totally determined by the passed in key.
- *                                (I.e., calling this routine again with the
- *                                same key allows repeating a sequence of
- *                                random numbers)
- */
-krb5_error_code
-mit_des_set_random_generator_seed(seed, p_state)
-    const krb5_data * seed;
-    krb5_pointer p_state;
-{
-    krb5_error_code kret;
-    register int i;
-    mit_des_cblock *new_key;
-    mit_des_random_state *state = p_state;
-
-    if (state->eblock.key) {
-       if (state->eblock.key->contents) {
-           memset(state->eblock.key->contents, 0, state->eblock.key->length);
-           krb5_xfree(state->eblock.key->contents);
-       }
-    }
-
-    state->eblock.key = (krb5_keyblock *)malloc(sizeof(krb5_keyblock));
-    if (! state->eblock.key)
-       return ENOMEM;
-
-    state->eblock.key->enctype = state->eblock.crypto_entry->proto_enctype;
-    state->eblock.key->length = state->eblock.crypto_entry->keysize;
-    state->eblock.key->contents = (krb5_octet *)malloc(state->eblock.key->length);
-    if (! state->eblock.key->contents) {
-       krb5_xfree(state->eblock.key);
-       state->eblock.key = 0;
-       return ENOMEM;
-    }
-
-    kret = mit_des_n_fold(seed->data, seed->length,
-               state->eblock.key->contents, state->eblock.key->length);
-    if (kret) return kret;
-
-    mit_des_fixup_keyblock_parity(state->eblock.key);
-
-    for (i = 0; i < state->eblock.key->length/sizeof(mit_des_cblock); i++) {
-       new_key = (mit_des_cblock *)state->eblock.key->contents + i;
-       if (mit_des_is_weak_key(*new_key)) {
-           (*new_key)[0] ^= 0xF0;
-           mit_des_fixup_key_parity(*new_key);
-       }
-    }
-
-    /* destroy any old key schedule */
-    mit_des_finish_key(&state->eblock);
-    
-    /* compute the key schedule */
-    (* state->eblock.crypto_entry->process_key)
-       (&state->eblock, state->eblock.key);
-
-    /* now we can destroy the key... */
-    memset(state->eblock.key->contents, 0, state->eblock.key->length);
-    krb5_xfree(state->eblock.key->contents);
-    krb5_xfree(state->eblock.key);
-    state->eblock.key = (krb5_keyblock *) 0;
-
-    /* "seek" to the start of the stream: */
-    memset(state->sequence.data, 0, state->sequence.length);
-
-    return 0;
-}
-
-krb5_error_code
-mit_des_set_random_sequence_number(sequence, p_state)
-    const krb5_data *sequence;
-    krb5_pointer p_state;
-{
-    mit_des_random_state *state = p_state;
-    int length = state->eblock.crypto_entry->keysize;
-
-    if (length > sequence->length)
-       length = sequence->length;
-
-    memcpy(state->sequence.data, sequence->data, length);
-    
-    return 0;
-}
diff --git a/src/lib/crypto/des3_raw.c b/src/lib/crypto/des3_raw.c
deleted file mode 100644 (file)
index 62e3d72..0000000
+++ /dev/null
@@ -1,104 +0,0 @@
-/*
- * lib/crypto/des3_raw.c
- *
- * Copyright 1996 by the Massachusetts Institute of Technology.
- * All Rights Reserved.
- *
- * Export of this software from the United States of America may
- *   require a specific license from the United States Government.
- *   It is the responsibility of any person or organization contemplating
- *   export to obtain such a license before exporting.
- * 
- * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
- * distribute this software and its documentation for any purpose and
- * without fee is hereby granted, provided that the above copyright
- * notice appear in all copies and that both that copyright notice and
- * this permission notice appear in supporting documentation, and that
- * the name of M.I.T. not be used in advertising or publicity pertaining
- * to distribution of the software without specific, written prior
- * permission.  M.I.T. makes no representations about the suitability of
- * this software for any purpose.  It is provided "as is" without express
- * or implied warranty.
- */
-
-#include "k5-int.h"
-#include "des_int.h"
-
-krb5_error_code mit_des3_raw_encrypt_func
-    PROTOTYPE(( krb5_const_pointer, krb5_pointer, const size_t,
-               krb5_encrypt_block *, krb5_pointer ));
-
-krb5_error_code mit_des3_raw_decrypt_func
-    PROTOTYPE(( krb5_const_pointer, krb5_pointer, const size_t,
-               krb5_encrypt_block *, krb5_pointer ));
-
-static krb5_cryptosystem_entry mit_des3_raw_cryptosystem_entry = {
-    0,
-    mit_des3_raw_encrypt_func,
-    mit_des3_raw_decrypt_func,
-    mit_des3_process_key,
-    mit_des_finish_key,
-    mit_des3_string_to_key,
-    mit_des_init_random_key,
-    mit_des_finish_random_key,
-    mit_des_random_key,
-    sizeof(mit_des_cblock),
-    0,
-    sizeof(mit_des3_cblock),
-    ENCTYPE_DES3_CBC_RAW
-    };
-
-krb5_cs_table_entry krb5_des3_raw_cst_entry = {
-    0,
-    &mit_des3_raw_cryptosystem_entry,
-    0
-    };
-
-krb5_error_code
-mit_des3_raw_decrypt_func(in, out, size, key, ivec)
-    krb5_const_pointer in;
-    krb5_pointer out;
-    const size_t size;
-    krb5_encrypt_block * key;
-    krb5_pointer ivec;
-{
-    return (mit_des3_cbc_encrypt((const mit_des_cblock *) in, 
-                                out, 
-                                size, 
-                                (struct mit_des_ks_struct *)key->priv,
-                                ((struct mit_des_ks_struct *)key->priv) + 1,
-                                ((struct mit_des_ks_struct *)key->priv) + 2,
-                                ivec ? ivec : (krb5_pointer)key->key->contents,
-                                MIT_DES_DECRYPT));
-}
-
-krb5_error_code
-mit_des3_raw_encrypt_func(in, out, size, key, ivec)
-    krb5_const_pointer in;
-    krb5_pointer out;
-    const size_t size;
-    krb5_encrypt_block * key;
-    krb5_pointer ivec;
-{
-   int sumsize;
-
-   /* round up to des block size */
-
-   sumsize =  krb5_roundup(size, sizeof(mit_des_cblock));
-
-   /* assemble crypto input into the output area, then encrypt in place. */
-
-   memset((char *)out, 0, sumsize);
-   memcpy((char *)out, (char *)in, size);
-
-    /* We depend here on the ability of this DES implementation to
-       encrypt plaintext to ciphertext in-place. */
-    return (mit_des3_cbc_encrypt(out, 
-                                out, 
-                                sumsize, 
-                                (struct mit_des_ks_struct *)key->priv,
-                                ((struct mit_des_ks_struct *)key->priv) + 1,
-                                ((struct mit_des_ks_struct *)key->priv) + 2,
-                                ivec ? ivec : (krb5_pointer)key->key->contents,
-                                MIT_DES_ENCRYPT));
-}
diff --git a/src/lib/crypto/des3_sha.c b/src/lib/crypto/des3_sha.c
deleted file mode 100644 (file)
index 9b060e5..0000000
+++ /dev/null
@@ -1,178 +0,0 @@
-/*
- * lib/crypto/des3-sha.c
- *
- * Copyright 1996 by Lehman Brothers, Inc.
- * All Rights Reserved.
- *
- * Export of this software from the United States of America may
- *   require a specific license from the United States Government.
- *   It is the responsibility of any person or organization contemplating
- *   export to obtain such a license before exporting.
- * 
- * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
- * distribute this software and its documentation for any purpose and
- * without fee is hereby granted, provided that the above copyright
- * notice appear in all copies and that both that copyright notice and
- * this permission notice appear in supporting documentation, and that
- * the name of Lehman Brothers or M.I.T. not be used in advertising or
- * publicity pertaining to distribution of the software without
- * specific, written prior permission.  Lehman Brothers and
- * M.I.T. make no representations about the suitability of this
- * software for any purpose.  It is provided "as is" without express
- * or implied warranty.
- */
-
-#include "k5-int.h"
-#include "shs.h"
-#include "des_int.h"
-
-
-#define DES3_SHA_CONFOUNDER_SIZE       sizeof(mit_des_cblock)
-
-static krb5_error_code
-mit_des3_sha_encrypt_func
-    PROTOTYPE(( krb5_const_pointer, krb5_pointer, const size_t,
-               krb5_encrypt_block *, krb5_pointer ));
-
-static krb5_error_code
-mit_des3_sha_decrypt_func
-    PROTOTYPE(( krb5_const_pointer, krb5_pointer, const size_t,
-               krb5_encrypt_block *, krb5_pointer ));
-
-static mit_des_cblock zero_ivec = { 0 };
-
-static krb5_cryptosystem_entry mit_des3_sha_cryptosystem_entry = {
-    0,
-    mit_des3_sha_encrypt_func,
-    mit_des3_sha_decrypt_func, 
-    mit_des3_process_key,
-    mit_des_finish_key,
-    mit_des3_string_to_key,
-    mit_des_init_random_key,
-    mit_des_finish_random_key,
-    mit_des_random_key,
-    sizeof(mit_des_cblock),
-    NIST_SHA_CKSUM_LENGTH + DES3_SHA_CONFOUNDER_SIZE,
-    sizeof(mit_des3_cblock),
-    ENCTYPE_DES3_CBC_SHA
-    };
-
-krb5_cs_table_entry krb5_des3_sha_cst_entry = {
-    0,
-    &mit_des3_sha_cryptosystem_entry,
-    0
-    };
-
-
-static krb5_error_code
-mit_des3_sha_encrypt_func(in, out, size, key, ivec)
-    krb5_const_pointer in;
-    krb5_pointer out;
-    const size_t size;
-    krb5_encrypt_block * key;
-    krb5_pointer ivec;
-{
-    krb5_checksum cksum;
-    krb5_octet         contents[NIST_SHA_CKSUM_LENGTH];
-    int sumsize;
-    krb5_error_code retval;
-
-    /* caller passes data size, and saves room for the padding. */
-    /* format of ciphertext, per RFC is:
-      +-----------+----------+-------------+-----+
-      |confounder |   check  |   msg-seq   | pad |
-      +-----------+----------+-------------+-----+
-      
-      our confounder is 8 bytes
-      our checksum is NIST_SHA_CKSUM_LENGTH
-     */
-    sumsize =  krb5_roundup(size + mit_des3_sha_cryptosystem_entry.pad_minimum,
-                           mit_des3_sha_cryptosystem_entry.block_length);
-
-    /* assemble crypto input into the output area, then encrypt in place. */
-
-    memset((char *)out, 0, sumsize);
-
-    /* put in the confounder */
-    if ((retval = krb5_random_confounder(DES3_SHA_CONFOUNDER_SIZE, out)))
-       return retval;
-
-    memcpy((char *)out + mit_des3_sha_cryptosystem_entry.pad_minimum,
-          (char *)in, size);
-
-    cksum.length = sizeof(contents);
-    cksum.contents = contents; 
-
-    /* This is equivalent to krb5_calculate_checksum(CKSUMTYPE_SHA,...)
-       but avoids use of the cryptosystem config table which can not be
-       referenced here if this object is to be included in a shared library. */
-    retval = nist_sha_cksumtable_entry.sum_func((krb5_pointer) out, sumsize,
-                                               0, 0, &cksum);
-    if (retval)
-       return retval;
-
-    memcpy((char *)out + DES3_SHA_CONFOUNDER_SIZE,
-          (char *)contents, NIST_SHA_CKSUM_LENGTH);
-
-    /* We depend here on the ability of this DES-3 implementation to
-       encrypt plaintext to ciphertext in-place. */
-    retval = mit_des3_cbc_encrypt(out,
-                                 out,
-                                 sumsize,
-                                 (struct mit_des_ks_struct *) key->priv,
-                                 ((struct mit_des_ks_struct *) key->priv) + 1,
-                                 ((struct mit_des_ks_struct *) key->priv) + 2,
-                                 ivec ? ivec : (krb5_pointer)zero_ivec,
-                                 MIT_DES_ENCRYPT);
-    return retval;
-}
-
-static krb5_error_code
-mit_des3_sha_decrypt_func(in, out, size, key, ivec)
-    krb5_const_pointer in;
-    krb5_pointer out;
-    const size_t size;
-    krb5_encrypt_block * key;
-    krb5_pointer ivec;
-{
-    krb5_checksum cksum;
-    krb5_octet         contents_prd[NIST_SHA_CKSUM_LENGTH];
-    krb5_octet  contents_get[NIST_SHA_CKSUM_LENGTH];
-    char       *p;
-    krb5_error_code   retval;
-
-    if ( size < krb5_roundup(mit_des3_sha_cryptosystem_entry.pad_minimum,
-                            mit_des3_sha_cryptosystem_entry.block_length))
-       return KRB5_BAD_MSIZE;
-
-    retval = mit_des3_cbc_encrypt((const mit_des_cblock *) in,
-                                 out,
-                                 size,
-                                 (struct mit_des_ks_struct *) key->priv,
-                                 ((struct mit_des_ks_struct *) key->priv) + 1,
-                                 ((struct mit_des_ks_struct *) key->priv) + 2,
-                                 ivec ? ivec : (krb5_pointer)zero_ivec,
-                                 MIT_DES_DECRYPT);
-    if (retval)
-       return retval;
-
-    cksum.length = sizeof(contents_prd);
-    cksum.contents = contents_prd;
-    p = (char *)out + DES3_SHA_CONFOUNDER_SIZE;
-    memcpy((char *)contents_get, p, NIST_SHA_CKSUM_LENGTH);
-    memset(p, 0, NIST_SHA_CKSUM_LENGTH);
-
-    retval = nist_sha_cksumtable_entry.sum_func(out, size, 0, 0, &cksum);
-    if (retval)
-       return retval;
-
-    if (memcmp((char *)contents_get,
-              (char *)contents_prd,
-              NIST_SHA_CKSUM_LENGTH))
-        return KRB5KRB_AP_ERR_BAD_INTEGRITY;
-
-    memmove((char *)out, (char *)out +
-           mit_des3_sha_cryptosystem_entry.pad_minimum,
-           size - mit_des3_sha_cryptosystem_entry.pad_minimum);
-    return 0;
-}
diff --git a/src/lib/crypto/des_crc.c b/src/lib/crypto/des_crc.c
deleted file mode 100644 (file)
index 6317f61..0000000
+++ /dev/null
@@ -1,170 +0,0 @@
-/*
- * lib/crypto/des-crc.32
- *
- * Copyright 1994 by the Massachusetts Institute of Technology.
- * All Rights Reserved.
- *
- * Export of this software from the United States of America may
- *   require a specific license from the United States Government.
- *   It is the responsibility of any person or organization contemplating
- *   export to obtain such a license before exporting.
- * 
- * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
- * distribute this software and its documentation for any purpose and
- * without fee is hereby granted, provided that the above copyright
- * notice appear in all copies and that both that copyright notice and
- * this permission notice appear in supporting documentation, and that
- * the name of M.I.T. not be used in advertising or publicity pertaining
- * to distribution of the software without specific, written prior
- * permission.  M.I.T. makes no representations about the suitability of
- * this software for any purpose.  It is provided "as is" without express
- * or implied warranty.
- */
-
-#include "k5-int.h"
-#include "crc-32.h"
-#include "des_int.h"
-
-krb5_error_code mit_des_crc_encrypt_func
-    PROTOTYPE(( krb5_const_pointer, krb5_pointer, const size_t,
-               krb5_encrypt_block *, krb5_pointer ));
-
-krb5_error_code mit_des_crc_decrypt_func
-    PROTOTYPE(( krb5_const_pointer, krb5_pointer, const size_t,
-               krb5_encrypt_block *, krb5_pointer ));
-
-
-static krb5_cryptosystem_entry mit_des_crc_cryptosystem_entry = {
-    0,
-    mit_des_crc_encrypt_func,
-    mit_des_crc_decrypt_func, 
-    mit_des_process_key,
-    mit_des_finish_key,
-    mit_des_string_to_key,
-    mit_des_init_random_key,
-    mit_des_finish_random_key,
-    mit_des_random_key,
-    sizeof(mit_des_cblock),
-    CRC32_CKSUM_LENGTH+sizeof(mit_des_cblock),
-    sizeof(mit_des_cblock),
-    ENCTYPE_DES_CBC_CRC
-    };
-
-krb5_cs_table_entry krb5_des_crc_cst_entry = {
-    0,
-    &mit_des_crc_cryptosystem_entry,
-    0
-    };
-
-
-krb5_error_code
-mit_des_crc_encrypt_func(in, out, size, key, ivec)
-    krb5_const_pointer in;
-    krb5_pointer out;
-    const size_t size;
-    krb5_encrypt_block * key;
-    krb5_pointer ivec;
-{
-    krb5_checksum cksum;
-    krb5_octet         contents[CRC32_CKSUM_LENGTH];
-    int sumsize;
-    krb5_error_code retval;
-
-/*    if ( size < sizeof(mit_des_cblock) )
-       return KRB5_BAD_MSIZE; */
-
-    /* caller passes data size, and saves room for the padding. */
-    /* format of ciphertext, per RFC is:
-      +-----------+----------+-------------+-----+
-      |confounder |   check  |   msg-seq   | pad |
-      +-----------+----------+-------------+-----+
-      
-      our confounder is 8 bytes (one cblock);
-      our checksum is CRC32_CKSUM_LENGTH
-     */
-    sumsize =  krb5_roundup(size+CRC32_CKSUM_LENGTH+sizeof(mit_des_cblock),
-                           sizeof(mit_des_cblock));
-
-    /* assemble crypto input into the output area, then encrypt in place. */
-
-    memset((char *)out, 0, sumsize);
-
-    /* put in the confounder */
-    if ((retval = krb5_random_confounder(sizeof(mit_des_cblock), out)))
-       return retval;
-
-    memcpy((char *)out+sizeof(mit_des_cblock)+CRC32_CKSUM_LENGTH, (char *)in,
-          size);
-
-    cksum.length = sizeof(contents);
-    cksum.contents = contents; 
-
-    /* This is equivalent to krb5_calculate_checksum(CKSUMTYPE_CRC32,...)
-       but avoids use of the cryptosystem config table which can not be
-       referenced here if this object is to be included in a shared library.  */
-    if ((retval = crc32_cksumtable_entry.sum_func((krb5_pointer) out,
-                                                 sumsize,
-                                                 (krb5_pointer)key->key->contents,
-                                                 sizeof(mit_des_cblock),
-                                                 &cksum)))
-       return retval;
-
-    memcpy((char *)out+sizeof(mit_des_cblock), (char *)contents,
-          CRC32_CKSUM_LENGTH);
-
-    /* We depend here on the ability of this DES implementation to
-       encrypt plaintext to ciphertext in-place. */
-    return (mit_des_cbc_encrypt(out, 
-                               out,
-                               sumsize, 
-                               (struct mit_des_ks_struct *) key->priv, 
-                               ivec ? ivec : (krb5_pointer)key->key->contents,
-                               MIT_DES_ENCRYPT));
-    
-}
-
-krb5_error_code
-mit_des_crc_decrypt_func(in, out, size, key, ivec)
-    krb5_const_pointer in;
-    krb5_pointer out;
-    const size_t size;
-    krb5_encrypt_block * key;
-    krb5_pointer ivec;
-{
-    krb5_checksum cksum;
-    krb5_octet         contents_prd[CRC32_CKSUM_LENGTH];
-    krb5_octet  contents_get[CRC32_CKSUM_LENGTH];
-    char       *p;
-    krb5_error_code   retval;
-
-    if ( size < 2*sizeof(mit_des_cblock) )
-       return KRB5_BAD_MSIZE;
-
-    retval = mit_des_cbc_encrypt((const mit_des_cblock FAR *) in,
-                                out,
-                                size,
-                                (struct mit_des_ks_struct *) key->priv,
-                                ivec ? ivec : (krb5_pointer)key->key->contents,
-                                MIT_DES_DECRYPT);
-    if (retval)
-       return retval;
-
-    cksum.length = sizeof(contents_prd);
-    cksum.contents = contents_prd;
-    p = (char *)out + sizeof(mit_des_cblock);
-    memcpy((char *)contents_get, p, CRC32_CKSUM_LENGTH);
-    memset(p, 0, CRC32_CKSUM_LENGTH);
-
-    if ((retval = crc32_cksumtable_entry.sum_func(out, size,
-                                                 (krb5_pointer)key->key->contents,
-                                                 sizeof(mit_des_cblock),
-                                                 &cksum)))
-       return retval;
-
-    if (memcmp((char *)contents_get, (char *)contents_prd, CRC32_CKSUM_LENGTH) )
-        return KRB5KRB_AP_ERR_BAD_INTEGRITY;
-    memmove((char *)out, (char *)out +
-          sizeof(mit_des_cblock) + CRC32_CKSUM_LENGTH,
-          size - sizeof(mit_des_cblock) - CRC32_CKSUM_LENGTH);
-    return 0;
-}
diff --git a/src/lib/crypto/des_md5.c b/src/lib/crypto/des_md5.c
deleted file mode 100644 (file)
index 6794f56..0000000
+++ /dev/null
@@ -1,171 +0,0 @@
-/*
- * lib/crypto/des-md5.32
- *
- * Copyright 1994 by the Massachusetts Institute of Technology.
- * All Rights Reserved.
- *
- * Export of this software from the United States of America may
- *   require a specific license from the United States Government.
- *   It is the responsibility of any person or organization contemplating
- *   export to obtain such a license before exporting.
- * 
- * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
- * distribute this software and its documentation for any purpose and
- * without fee is hereby granted, provided that the above copyright
- * notice appear in all copies and that both that copyright notice and
- * this permission notice appear in supporting documentation, and that
- * the name of M.I.T. not be used in advertising or publicity pertaining
- * to distribution of the software without specific, written prior
- * permission.  M.I.T. makes no representations about the suitability of
- * this software for any purpose.  It is provided "as is" without express
- * or implied warranty.
- */
-
-#include "k5-int.h"
-#include "rsa-md5.h"
-#include "des_int.h"
-
-krb5_error_code mit_des_md5_encrypt_func
-    PROTOTYPE(( krb5_const_pointer, krb5_pointer, const size_t,
-               krb5_encrypt_block *, krb5_pointer ));
-
-krb5_error_code mit_des_md5_decrypt_func
-    PROTOTYPE(( krb5_const_pointer, krb5_pointer, const size_t,
-               krb5_encrypt_block *, krb5_pointer ));
-
-static mit_des_cblock zero_ivec = { 0 };
-
-static krb5_cryptosystem_entry mit_des_md5_cryptosystem_entry = {
-    0,
-    mit_des_md5_encrypt_func,
-    mit_des_md5_decrypt_func, 
-    mit_des_process_key,
-    mit_des_finish_key,
-    mit_des_string_to_key,
-    mit_des_init_random_key,
-    mit_des_finish_random_key,
-    mit_des_random_key,
-    sizeof(mit_des_cblock),
-    RSA_MD5_CKSUM_LENGTH+sizeof(mit_des_cblock),
-    sizeof(mit_des_cblock),
-    ENCTYPE_DES_CBC_MD5
-    };
-
-krb5_cs_table_entry krb5_des_md5_cst_entry = {
-    0,
-    &mit_des_md5_cryptosystem_entry,
-    0
-    };
-
-
-krb5_error_code
-mit_des_md5_encrypt_func(in, out, size, key, ivec)
-    krb5_const_pointer in;
-    krb5_pointer out;
-    const size_t size;
-    krb5_encrypt_block * key;
-    krb5_pointer ivec;
-{
-    krb5_checksum cksum;
-    krb5_octet         contents[RSA_MD5_CKSUM_LENGTH];
-    int sumsize;
-    krb5_error_code retval;
-
-/*    if ( size < sizeof(mit_des_cblock) )
-       return KRB5_BAD_MSIZE; */
-
-    /* caller passes data size, and saves room for the padding. */
-    /* format of ciphertext, per RFC is:
-      +-----------+----------+-------------+-----+
-      |confounder |   check  |   msg-seq   | pad |
-      +-----------+----------+-------------+-----+
-      
-      our confounder is 8 bytes (one cblock);
-      our checksum is RSA_MD5_CKSUM_LENGTH
-     */
-    sumsize =  krb5_roundup(size+RSA_MD5_CKSUM_LENGTH+sizeof(mit_des_cblock),
-                           sizeof(mit_des_cblock));
-
-    /* assemble crypto input into the output area, then encrypt in place. */
-
-    memset((char *)out, 0, sumsize);
-
-    /* put in the confounder */
-    if ((retval = krb5_random_confounder(sizeof(mit_des_cblock), out)))
-       return retval;
-
-    memcpy((char *)out+sizeof(mit_des_cblock)+RSA_MD5_CKSUM_LENGTH, (char *)in,
-          size);
-
-    cksum.length = sizeof(contents);
-    cksum.contents = contents; 
-
-    /* This is equivalent to krb5_calculate_checksum(CKSUMTYPE_MD5,...)
-       but avoids use of the cryptosystem config table which can not be
-       referenced here if this object is to be included in a shared library.  */
-    if ((retval = rsa_md5_cksumtable_entry.sum_func((krb5_pointer) out,
-                                                   sumsize,
-                                                   (krb5_pointer)key->key->contents,
-                                                   sizeof(mit_des_cblock),
-                                                   &cksum)))
-       return retval;
-
-    memcpy((char *)out+sizeof(mit_des_cblock), (char *)contents,
-          RSA_MD5_CKSUM_LENGTH);
-
-    /* We depend here on the ability of this DES implementation to
-       encrypt plaintext to ciphertext in-place. */
-    return (mit_des_cbc_encrypt(out, 
-                               out,
-                               sumsize, 
-                               (struct mit_des_ks_struct *) key->priv, 
-                               ivec ? ivec : (krb5_pointer)zero_ivec,
-                               MIT_DES_ENCRYPT));
-    
-}
-
-krb5_error_code
-mit_des_md5_decrypt_func(in, out, size, key, ivec)
-    krb5_const_pointer in;
-    krb5_pointer out;
-    const size_t size;
-    krb5_encrypt_block * key;
-    krb5_pointer ivec;
-{
-    krb5_checksum cksum;
-    krb5_octet         contents_prd[RSA_MD5_CKSUM_LENGTH];
-    krb5_octet  contents_get[RSA_MD5_CKSUM_LENGTH];
-    char       *p;
-    krb5_error_code   retval;
-
-    if ( size < 2*sizeof(mit_des_cblock) )
-       return KRB5_BAD_MSIZE;
-
-    retval = mit_des_cbc_encrypt((const mit_des_cblock *) in,
-                                out,
-                                size,
-                                (struct mit_des_ks_struct *) key->priv,
-                                ivec ? ivec : (krb5_pointer)zero_ivec,
-                                MIT_DES_DECRYPT);
-    if (retval)
-       return retval;
-
-    cksum.length = sizeof(contents_prd);
-    cksum.contents = contents_prd;
-    p = (char *)out + sizeof(mit_des_cblock);
-    memcpy((char *)contents_get, p, RSA_MD5_CKSUM_LENGTH);
-    memset(p, 0, RSA_MD5_CKSUM_LENGTH);
-
-    if ((retval = rsa_md5_cksumtable_entry.sum_func(out, size,
-                                                   (krb5_pointer)key->key->contents,
-                                                   sizeof(mit_des_cblock),
-                                                   &cksum)))
-       return retval;
-
-    if (memcmp((char *)contents_get, (char *)contents_prd, RSA_MD5_CKSUM_LENGTH) )
-        return KRB5KRB_AP_ERR_BAD_INTEGRITY;
-    memmove((char *)out, (char *)out +
-          sizeof(mit_des_cblock) + RSA_MD5_CKSUM_LENGTH,
-          size - sizeof(mit_des_cblock) - RSA_MD5_CKSUM_LENGTH);
-    return 0;
-}
diff --git a/src/lib/crypto/encrypt.c b/src/lib/crypto/encrypt.c
new file mode 100644 (file)
index 0000000..76b8c84
--- /dev/null
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 1998 by the FundsXpress, INC.
+ * 
+ * All rights reserved.
+ * 
+ * Export of this software from the United States of America may require
+ * a specific license from the United States Government.  It is the
+ * responsibility of any person or organization contemplating export to
+ * obtain such a license before exporting.
+ * 
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of FundsXpress. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  FundsXpress makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#include "k5-int.h"
+#include "etypes.h"
+
+KRB5_DLLIMP krb5_error_code KRB5_CALLCONV
+krb5_c_encrypt(context, key, usage, ivec, input, output)
+     krb5_context context;
+     krb5_const krb5_keyblock *key;
+     krb5_keyusage usage;
+     krb5_const krb5_data *ivec;
+     krb5_const krb5_data *input;
+     krb5_enc_data *output;
+{
+    int i;
+
+    for (i=0; i<krb5_enctypes_length; i++) {
+       if (krb5_enctypes_list[i].etype == key->enctype)
+           break;
+    }
+
+    if (i == krb5_enctypes_length)
+       return(KRB5_BAD_ENCTYPE);
+
+    output->magic = KV5M_ENC_DATA;
+    output->kvno = 0;
+    output->enctype = key->enctype;
+
+    return((*(krb5_enctypes_list[i].encrypt))
+          (krb5_enctypes_list[i].enc, krb5_enctypes_list[i].hash,
+           key, usage, ivec, input, &output->ciphertext));
+}
diff --git a/src/lib/crypto/encrypt_data.c b/src/lib/crypto/encrypt_data.c
deleted file mode 100644 (file)
index b2f039f..0000000
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- * Copyright 1995 by the Massachusetts Institute of Technology.
- * All Rights Reserved.
- *
- * Export of this software from the United States of America may
- *   require a specific license from the United States Government.
- *   It is the responsibility of any person or organization contemplating
- *   export to obtain such a license before exporting.
- *
- * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
- * distribute this software and its documentation for any purpose and
- * without fee is hereby granted, provided that the above copyright
- * notice appear in all copies and that both that copyright notice and
- * this permission notice appear in supporting documentation, and that
- * the name of M.I.T. not be used in advertising or publicity pertaining
- * to distribution of the software without specific, written prior
- * permission.  M.I.T. makes no representations about the suitability of
- * this software for any purpose.  It is provided "as is" without express
- * or implied warranty.
- *
- */
-
-#include "k5-int.h"
-
-/*
- * This routine takes a key and a krb5_data structure as input, and
- * outputs the encrypted data in a krb5_enc_data structure.  Note that
- * the krb5_enc_data structure is not allocated, and the kvno field is
- * not filled in.
- */
-krb5_error_code
-krb5_encrypt_data(context, key, ivec, data, enc_data)
-    krb5_context       context;
-    krb5_keyblock *    key;
-    krb5_pointer       ivec;
-    krb5_data *                data;
-    krb5_enc_data *    enc_data;
-{
-    krb5_error_code    retval;
-    krb5_encrypt_block eblock;
-
-    krb5_use_enctype(context, &eblock, key->enctype);
-
-    enc_data->magic = KV5M_ENC_DATA;
-    enc_data->kvno = 0;
-    enc_data->enctype = key->enctype;
-    enc_data->ciphertext.length = krb5_encrypt_size(data->length,
-                                                   eblock.crypto_entry);
-    enc_data->ciphertext.data = malloc(enc_data->ciphertext.length);
-    if (enc_data->ciphertext.data == 0)
-       return ENOMEM;
-
-    if ((retval = krb5_process_key(context, &eblock, key)) != 0)
-       goto cleanup;
-
-    if ((retval = krb5_encrypt(context, (krb5_pointer) data->data,
-                              (krb5_pointer) enc_data->ciphertext.data,
-                              data->length, &eblock, ivec))) {
-       krb5_finish_key(context, &eblock);
-        goto cleanup;
-    }
-    (void) krb5_finish_key(context, &eblock);
-
-    return 0;
-
-cleanup:
-    free(enc_data->ciphertext.data);
-    return retval;
-}
-    
diff --git a/src/lib/crypto/encrypt_length.c b/src/lib/crypto/encrypt_length.c
new file mode 100644 (file)
index 0000000..005b221
--- /dev/null
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 1998 by the FundsXpress, INC.
+ * 
+ * All rights reserved.
+ * 
+ * Export of this software from the United States of America may require
+ * a specific license from the United States Government.  It is the
+ * responsibility of any person or organization contemplating export to
+ * obtain such a license before exporting.
+ * 
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of FundsXpress. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  FundsXpress makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#include "k5-int.h"
+#include "etypes.h"
+
+KRB5_DLLIMP krb5_error_code KRB5_CALLCONV
+krb5_c_encrypt_length(context, enctype, inputlen, length)
+     krb5_context context;
+     krb5_enctype enctype;
+     size_t inputlen;
+     size_t *length;
+{
+    int i;
+
+    for (i=0; i<krb5_enctypes_length; i++) {
+       if (krb5_enctypes_list[i].etype == enctype)
+           break;
+    }
+
+    if (i == krb5_enctypes_length)
+       return(KRB5_BAD_ENCTYPE);
+
+    (*(krb5_enctypes_list[i].encrypt_len))
+       (krb5_enctypes_list[i].enc, krb5_enctypes_list[i].hash,
+        inputlen, length);
+
+    return(0);
+}
diff --git a/src/lib/crypto/enctype_compare.c b/src/lib/crypto/enctype_compare.c
new file mode 100644 (file)
index 0000000..8972589
--- /dev/null
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 1998 by the FundsXpress, INC.
+ * 
+ * All rights reserved.
+ * 
+ * Export of this software from the United States of America may require
+ * a specific license from the United States Government.  It is the
+ * responsibility of any person or organization contemplating export to
+ * obtain such a license before exporting.
+ * 
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of FundsXpress. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  FundsXpress makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#include "k5-int.h"
+#include "etypes.h"
+
+krb5_error_code
+krb5_c_enctype_compare(context, e1, e2, similar)
+     krb5_context context;
+     krb5_enctype e1;
+     krb5_enctype e2;
+     krb5_boolean *similar;
+{
+    int i, j;
+
+    for (i=0; i<krb5_enctypes_length; i++) 
+       if (krb5_enctypes_list[i].etype == e1)
+           break;
+
+    if (i == krb5_enctypes_length)
+       return(KRB5_BAD_ENCTYPE);
+
+    for (j=0; j<krb5_enctypes_length; j++) 
+       if (krb5_enctypes_list[j].etype == e2)
+           break;
+
+    if (j == krb5_enctypes_length)
+       return(KRB5_BAD_ENCTYPE);
+
+    *similar = 
+       ((krb5_enctypes_list[i].enc == krb5_enctypes_list[j].enc) &&
+        (krb5_enctypes_list[i].str2key == krb5_enctypes_list[j].str2key));
+
+    return(0);
+}
diff --git a/src/lib/crypto/enctype_to_string.c b/src/lib/crypto/enctype_to_string.c
new file mode 100644 (file)
index 0000000..2c25a52
--- /dev/null
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 1998 by the FundsXpress, INC.
+ * 
+ * All rights reserved.
+ * 
+ * Export of this software from the United States of America may require
+ * a specific license from the United States Government.  It is the
+ * responsibility of any person or organization contemplating export to
+ * obtain such a license before exporting.
+ * 
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of FundsXpress. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  FundsXpress makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#include "k5-int.h"
+#include "etypes.h"
+
+KRB5_DLLIMP krb5_error_code KRB5_CALLCONV
+krb5_enctype_to_string(enctype, buffer, buflen)
+    krb5_enctype       enctype;
+    char               FAR * buffer;
+    size_t             buflen;
+{
+    int i;
+
+    for (i=0; i<krb5_enctypes_length; i++) {
+       if (krb5_enctypes_list[i].etype == enctype) {
+           if ((strlen(krb5_enctypes_list[i].out_string)+1) > buflen)
+               return(ENOMEM);
+
+           strcpy(buffer, krb5_enctypes_list[i].out_string);
+           return(0);
+       }
+    }
+
+    return(EINVAL);
+}
diff --git a/src/lib/crypto/etypes.c b/src/lib/crypto/etypes.c
new file mode 100644 (file)
index 0000000..cebb5bd
--- /dev/null
@@ -0,0 +1,82 @@
+/*
+ * Copyright (C) 1998 by the FundsXpress, INC.
+ * 
+ * All rights reserved.
+ * 
+ * Export of this software from the United States of America may require
+ * a specific license from the United States Government.  It is the
+ * responsibility of any person or organization contemplating export to
+ * obtain such a license before exporting.
+ * 
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of FundsXpress. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  FundsXpress makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#include "k5-int.h"
+#include "enc_provider.h"
+#include "hash_provider.h"
+#include "etypes.h"
+#include "old.h"
+#include "raw.h"
+#include "dk.h"
+
+/* these will be linear searched.  if they ever get big, a binary
+   search or hash table would be better, which means these would need
+   to be sorted.  An array would be more efficient, but that assumes
+   that the keytypes are all near each other.  I'd rather not make
+   that assumption. */
+
+struct krb5_keytypes krb5_enctypes_list[] = {
+    { ENCTYPE_DES_CBC_CRC,
+      "des-cbc-crc", "DES cbc mode with CRC-32",
+      &krb5_enc_des, &krb5_hash_crc32,
+      krb5_old_encrypt_length, krb5_old_encrypt, krb5_old_decrypt,
+      krb5_des_string_to_key },
+    { ENCTYPE_DES_CBC_MD4,
+      "des-cbc-md4", "DES cbc mode with RSA-MD4",
+      &krb5_enc_des, &krb5_hash_md4,
+      krb5_old_encrypt_length, krb5_old_encrypt, krb5_old_decrypt,
+      krb5_des_string_to_key },
+    { ENCTYPE_DES_CBC_MD5,
+      "des-cbc-md5", "DES cbc mode with RSA-MD5",
+      &krb5_enc_des, &krb5_hash_md5,
+      krb5_old_encrypt_length, krb5_old_encrypt, krb5_old_decrypt,
+      krb5_des_string_to_key },
+
+    { ENCTYPE_DES_CBC_RAW,
+      "des-cbc-raw", "DES cbc mode raw",
+      &krb5_enc_des, NULL,
+      krb5_raw_encrypt_length, krb5_raw_encrypt, krb5_raw_decrypt,
+      krb5_des_string_to_key },
+    { ENCTYPE_DES3_CBC_RAW,
+      "des3-cbc-raw", "Triple DES cbc mode raw",
+      &krb5_enc_des3, NULL,
+      krb5_raw_encrypt_length, krb5_raw_encrypt, krb5_raw_decrypt,
+      krb5_dk_string_to_key },
+
+    { ENCTYPE_DES3_HMAC_SHA1,
+      "des3-hmac-sha1", "Triple DES with HMAC/sha1",
+      &krb5_enc_des3, &krb5_hash_sha1,
+      krb5_dk_encrypt_length, krb5_dk_encrypt, krb5_dk_decrypt,
+      krb5_dk_string_to_key },
+    { ENCTYPE_DES_HMAC_SHA1,
+      "des-hmac-sha1", "DES with HMAC/sha1",
+      &krb5_enc_des, &krb5_hash_sha1,
+      krb5_dk_encrypt_length, krb5_dk_encrypt, krb5_dk_decrypt,
+      krb5_dk_string_to_key },
+};
+
+int krb5_enctypes_length =
+sizeof(krb5_enctypes_list)/sizeof(struct krb5_keytypes);
diff --git a/src/lib/crypto/etypes.h b/src/lib/crypto/etypes.h
new file mode 100644 (file)
index 0000000..53d8b65
--- /dev/null
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 1998 by the FundsXpress, INC.
+ * 
+ * All rights reserved.
+ * 
+ * Export of this software from the United States of America may require
+ * a specific license from the United States Government.  It is the
+ * responsibility of any person or organization contemplating export to
+ * obtain such a license before exporting.
+ * 
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of FundsXpress. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  FundsXpress makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#include "k5-int.h"
+
+extern struct krb5_keytypes krb5_enctypes_list[];
+extern int krb5_enctypes_length;
diff --git a/src/lib/crypto/hmac.c b/src/lib/crypto/hmac.c
new file mode 100644 (file)
index 0000000..7cf11a6
--- /dev/null
@@ -0,0 +1,131 @@
+/*
+ * Copyright (C) 1998 by the FundsXpress, INC.
+ * 
+ * All rights reserved.
+ * 
+ * Export of this software from the United States of America may require
+ * a specific license from the United States Government.  It is the
+ * responsibility of any person or organization contemplating export to
+ * obtain such a license before exporting.
+ * 
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of FundsXpress. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  FundsXpress makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#include "k5-int.h"
+
+/*
+ * the HMAC transform looks like:
+ *
+ * H(K XOR opad, H(K XOR ipad, text))
+ *
+ * where H is a cryptographic hash
+ * K is an n byte key
+ * ipad is the byte 0x36 repeated blocksize times
+ * opad is the byte 0x5c repeated blocksize times
+ * and text is the data being protected
+ */
+
+krb5_error_code
+krb5_hmac(hash, key, icount, input, output)
+     krb5_const struct krb5_hash_provider *hash;
+     krb5_const krb5_keyblock *key;
+     unsigned int icount;
+     krb5_const krb5_data *input;
+     krb5_data *output;
+{
+    size_t hashsize, blocksize;
+    unsigned char *xorkey, *ihash;
+    int i;
+    krb5_data *hashin, hashout;
+    krb5_error_code ret;
+
+    (*(hash->hash_size))(&hashsize);
+    (*(hash->block_size))(&blocksize);
+
+    if (key->length > blocksize)
+       return(KRB5_CRYPTO_INTERNAL);
+    if (output->length < hashsize)
+       return(KRB5_BAD_MSIZE);
+    /* if this isn't > 0, then there won't be enough space in this
+       array to compute the outer hash */
+    if (icount == 0)
+       return(KRB5_CRYPTO_INTERNAL);
+
+    /* allocate space for the xor key, hash input vector, and inner hash */
+
+    if ((xorkey = (unsigned char *) malloc(blocksize)) == NULL)
+       return(ENOMEM);
+    if ((ihash = (unsigned char *) malloc(hashsize)) == NULL) {
+       free(xorkey);
+       return(ENOMEM);
+    }
+    if ((hashin = (krb5_data *)malloc(sizeof(krb5_data)*(icount+1))) == NULL) {
+       free(ihash);
+       free(xorkey);
+       return(ENOMEM);
+    }
+
+    /* create the inner padded key */
+
+    memset(xorkey, 0x36, blocksize);
+
+    for (i=0; i<key->length; i++)
+       xorkey[i] ^= key->contents[i];
+
+    /* compute the inner hash */
+
+    for (i=0; i<icount; i++) {
+       hashin[0].length = blocksize;
+       hashin[0].data = xorkey;
+       hashin[i+1] = input[i];
+    }
+
+    hashout.length = hashsize;
+    hashout.data = ihash;
+
+    if (ret = ((*(hash->hash))(icount+1, hashin, &hashout)))
+       goto cleanup;
+
+    /* create the outer padded key */
+
+    memset(xorkey, 0x5c, blocksize);
+
+    for (i=0; i<key->length; i++)
+       xorkey[i] ^= key->contents[i];
+
+    /* compute the outer hash */
+
+    hashin[0].length = blocksize;
+    hashin[0].data = xorkey;
+    hashin[1] = hashout;
+
+    output->length = hashsize;
+
+    if (ret = ((*(hash->hash))(2, hashin, output)))
+       memset(output->data, 0, output->length);
+
+    /* ret is set correctly by the prior call */
+
+cleanup:
+    memset(xorkey, 0, blocksize);
+    memset(ihash, 0, hashsize);
+
+    free(hashin);
+    free(ihash);
+    free(xorkey);
+
+    return(ret);
+}
diff --git a/src/lib/crypto/keyed_checksum_types.c b/src/lib/crypto/keyed_checksum_types.c
new file mode 100644 (file)
index 0000000..cf0b736
--- /dev/null
@@ -0,0 +1,95 @@
+/*
+ * Copyright (C) 1998 by the FundsXpress, INC.
+ * 
+ * All rights reserved.
+ * 
+ * Export of this software from the United States of America may require
+ * a specific license from the United States Government.  It is the
+ * responsibility of any person or organization contemplating export to
+ * obtain such a license before exporting.
+ * 
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of FundsXpress. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  FundsXpress makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#include "k5-int.h"
+#include "etypes.h"
+#include "cksumtypes.h"
+
+static int etype_match(e1, e2)
+     krb5_enctype e1, e2;
+{
+    int i1, i2;
+
+    for (i1=0; i1<krb5_enctypes_length; i1++) 
+       if (krb5_enctypes_list[i1].etype == e1)
+           break;
+
+    for (i2=0; i2<krb5_enctypes_length; i2++) 
+       if (krb5_enctypes_list[i2].etype == e2)
+           break;
+
+    return((i1 < krb5_enctypes_length) &&
+          (i2 < krb5_enctypes_length) &&
+          (krb5_enctypes_list[i1].enc == krb5_enctypes_list[i2].enc));
+}
+
+krb5_error_code
+krb5_c_keyed_checksum_types(context, enctype, count, cksumtypes)
+     krb5_context context;
+     krb5_enctype enctype;
+     unsigned int *count;
+     krb5_cksumtype **cksumtypes;
+{
+    unsigned int i, c;
+
+    c = 0;
+    for (i=0; i<krb5_cksumtypes_length; i++) {
+       if ((krb5_cksumtypes_list[i].keyhash &&
+            etype_match(krb5_cksumtypes_list[i].keyed_etype, enctype)) ||
+           (krb5_cksumtypes_list[i].flags & KRB5_CKSUMFLAG_DERIVE)) {
+           c++;
+       }
+    }
+
+    *count = c;
+
+    if ((*cksumtypes = (krb5_cksumtype *) malloc(c*sizeof(krb5_cksumtype)))
+       == NULL)
+       return(ENOMEM);
+
+    c = 0;
+    for (i=0; i<krb5_cksumtypes_length; i++) {
+       if ((krb5_cksumtypes_list[i].keyhash &&
+            etype_match(krb5_cksumtypes_list[i].keyed_etype, enctype)) ||
+           (krb5_cksumtypes_list[i].flags & KRB5_CKSUMFLAG_DERIVE)) {
+           (*cksumtypes)[c] = krb5_cksumtypes_list[i].ctype;
+           c++;
+       }
+    }
+
+    return(0);
+}
+
+void
+krb5_free_cksumtypes(context, val)
+    krb5_context context;
+    krb5_cksumtype FAR * val;
+{
+    if (val)
+       krb5_xfree(val);
+    return;
+}
+
diff --git a/src/lib/crypto/keyed_cksum.c b/src/lib/crypto/keyed_cksum.c
new file mode 100644 (file)
index 0000000..0ff6d3e
--- /dev/null
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 1998 by the FundsXpress, INC.
+ * 
+ * All rights reserved.
+ * 
+ * Export of this software from the United States of America may require
+ * a specific license from the United States Government.  It is the
+ * responsibility of any person or organization contemplating export to
+ * obtain such a license before exporting.
+ * 
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of FundsXpress. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  FundsXpress makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#include "k5-int.h"
+#include "cksumtypes.h"
+
+krb5_boolean is_keyed_cksum(ctype)
+     krb5_cksumtype ctype;
+{
+    int i;
+
+    for (i=0; i<krb5_cksumtypes_length; i++) {
+       if (krb5_cksumtypes_list[i].ctype == ctype) {
+           if (krb5_cksumtypes_list[i].keyhash ||
+               (krb5_cksumtypes_list[i].flags &
+                KRB5_CKSUMFLAG_DERIVE))
+               return(1);
+           else
+               return(0);
+       }
+    }
+
+    /* ick, but it's better than coredumping, which is what the
+       old code would have done */
+    return(-1);
+}
diff --git a/src/lib/crypto/krb5_glue.c b/src/lib/crypto/krb5_glue.c
deleted file mode 100644 (file)
index 3b26aed..0000000
+++ /dev/null
@@ -1,233 +0,0 @@
-/*
- * lib/krb5/krb/crypto_glue.c
- *
- * Copyright 1996 by the Massachusetts Institute of Technology.
- * All Rights Reserved.
- *
- * Export of this software from the United States of America may
- *   require a specific license from the United States Government.
- *   It is the responsibility of any person or organization contemplating
- *   export to obtain such a license before exporting.
- * 
- * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
- * distribute this software and its documentation for any purpose and
- * without fee is hereby granted, provided that the above copyright
- * notice appear in all copies and that both that copyright notice and
- * this permission notice appear in supporting documentation, and that
- * the name of M.I.T. not be used in advertising or publicity pertaining
- * to distribution of the software without specific, written prior
- * permission.  M.I.T. makes no representations about the suitability of
- * this software for any purpose.  It is provided "as is" without express
- * or implied warranty.
- *
- * Exported routines:
- *   krb5_use_enctype()
- *   krb5_checksum_size()
- *   krb5_encrypt_size()
- *   krb5_calculate_checksum()
- *   krb5_verify_checksum()
- *   krb5_encrypt()
- *   krb5_decrypt()
- *   krb5_process_key()
- *   krb5_finish_key()
- *   krb5_string_to_key()
- *   krb5_init_random_key()
- *   krb5_finish_random_key()
- *   krb5_random_key()
- *   krb5_eblock_enctype()
- *
- * Internal library routines:
- *   is_coll_proof_cksum()
- *   is_keyed_cksum()
- *   valid_cksumtype()
- *   valid_enctype()
- */
-
-#include "k5-int.h"
-
-
-KRB5_DLLIMP size_t KRB5_CALLCONV
-krb5_encrypt_size(length, crypto)
-    krb5_const size_t                  length;
-    krb5_const krb5_cryptosystem_entry FAR * crypto;
-{
-    return krb5_roundup(length + crypto->pad_minimum, crypto->block_length);
-}
-
-krb5_boolean KRB5_CALLCONV
-valid_enctype(ktype)
-    krb5_const krb5_enctype    ktype;
-{
-    return ((ktype<=krb5_max_enctype) && (ktype>0) && krb5_enctype_array[ktype]);
-}
-
-krb5_boolean KRB5_CALLCONV
-valid_cksumtype(cktype)
-    krb5_const krb5_cksumtype  cktype;
-{
-    return ((cktype<=krb5_max_cksum) && (cktype>0) && krb5_cksumarray[cktype]);
-}
-
-krb5_boolean KRB5_CALLCONV
-is_coll_proof_cksum(cktype)
-    krb5_const krb5_cksumtype  cktype;
-{
-    return(krb5_cksumarray[cktype]->is_collision_proof);
-}
-
-krb5_boolean KRB5_CALLCONV
-is_keyed_cksum(cktype)
-    krb5_const krb5_cksumtype  cktype;
-{
-    return (krb5_cksumarray[cktype]->uses_key);
-}
-
-KRB5_DLLIMP krb5_error_code KRB5_CALLCONV
-krb5_use_enctype(context, eblock, enctype)
-    krb5_context               context;
-    krb5_encrypt_block         FAR * eblock;
-    krb5_const krb5_enctype    enctype;
-{
-    eblock->crypto_entry = krb5_enctype_array[(enctype)]->system;
-    return 0;
-}
-
-KRB5_DLLIMP size_t KRB5_CALLCONV
-krb5_checksum_size(context, cktype)
-    krb5_context               context;
-    krb5_const krb5_cksumtype  cktype;
-{
-    return krb5_cksumarray[cktype]->checksum_length;
-}
-
-KRB5_DLLIMP krb5_error_code KRB5_CALLCONV
-krb5_calculate_checksum(context, cktype, in, in_length, seed, seed_length, outcksum)
-    krb5_context               context;
-    krb5_const krb5_cksumtype  cktype;
-    krb5_const krb5_pointer    in;
-    krb5_const size_t          in_length;
-    krb5_const krb5_pointer    seed;
-    krb5_const size_t          seed_length;
-    krb5_checksum      FAR *outcksum;
-{
-    return krb5_x(((*krb5_cksumarray[cktype]->sum_func)),
-                 (in, in_length, seed, seed_length, outcksum));
-}
-
-KRB5_DLLIMP krb5_error_code KRB5_CALLCONV
-krb5_verify_checksum(context, cktype, cksum, in, in_length, seed, seed_length)
-    krb5_context               context;
-    krb5_const krb5_cksumtype  cktype;
-    krb5_const krb5_checksum   FAR *cksum;
-    krb5_const krb5_pointer    in;
-    krb5_const size_t          in_length;
-    krb5_const krb5_pointer    seed;
-    krb5_const size_t          seed_length;
-{
-    return krb5_x((*krb5_cksumarray[cktype]->sum_verf_func),
-                 (cksum, in, in_length, seed, seed_length));
-}
-
-KRB5_DLLIMP krb5_enctype KRB5_CALLCONV
-krb5_eblock_enctype(context, eblock)
-    krb5_context                       context;
-    krb5_const krb5_encrypt_block      FAR * eblock;
-{
-    return eblock->crypto_entry->proto_enctype;
-}
-
-KRB5_DLLIMP krb5_error_code KRB5_CALLCONV
-krb5_encrypt(context, inptr, outptr, size, eblock, ivec)
-    krb5_context       context;
-    krb5_const krb5_pointer    inptr;
-    krb5_pointer               outptr;
-    krb5_const size_t          size;
-    krb5_encrypt_block         FAR * eblock;
-    krb5_pointer               ivec;
-{
-    return krb5_x(eblock->crypto_entry->encrypt_func,
-                 (inptr, outptr, size, eblock, ivec));
-}
-
-
-KRB5_DLLIMP krb5_error_code KRB5_CALLCONV
-krb5_decrypt(context, inptr, outptr, size, eblock, ivec)
-    krb5_context               context;
-    krb5_const krb5_pointer    inptr;
-    krb5_pointer               outptr;
-    krb5_const size_t          size;
-    krb5_encrypt_block         FAR * eblock;
-    krb5_pointer               ivec;
-{
-    return krb5_x(eblock->crypto_entry->decrypt_func,
-                 (inptr, outptr, size, eblock, ivec));
-}
-
-
-KRB5_DLLIMP krb5_error_code KRB5_CALLCONV
-krb5_process_key(context, eblock, key)
-    krb5_context               context;
-    krb5_encrypt_block         FAR * eblock;
-    krb5_const krb5_keyblock   FAR * key;
-{
-    return krb5_x(eblock->crypto_entry->process_key,
-                 (eblock, key));
-}
-
-KRB5_DLLIMP krb5_error_code KRB5_CALLCONV
-krb5_finish_key(context, eblock)
-    krb5_context       context;
-    krb5_encrypt_block FAR * eblock;
-{
-    return krb5_x(eblock->crypto_entry->finish_key,(eblock));
-}
-
-
-KRB5_DLLIMP krb5_error_code KRB5_CALLCONV
-krb5_string_to_key(context, eblock, keyblock, data, princ)
-    krb5_context                       context;
-    krb5_const krb5_encrypt_block      FAR * eblock;
-    krb5_keyblock                      FAR * keyblock;
-    krb5_const krb5_data               FAR * data;
-    krb5_const krb5_data               FAR * princ;
-{
-    return krb5_x(eblock->crypto_entry->string_to_key,
-                 (eblock, keyblock, data, princ));
-}
-
-
-KRB5_DLLIMP krb5_error_code KRB5_CALLCONV
-krb5_init_random_key(context, eblock, keyblock, ptr)
-    krb5_context                       context;
-    krb5_const krb5_encrypt_block      FAR * eblock;
-    krb5_const krb5_keyblock           FAR * keyblock;
-    krb5_pointer                       FAR * ptr;
-{
-    return krb5_x(eblock->crypto_entry->init_random_key,
-                 (eblock, keyblock, ptr));
-}
-
-
-KRB5_DLLIMP krb5_error_code KRB5_CALLCONV
-krb5_finish_random_key(context, eblock, ptr)
-    krb5_context                       context;
-    krb5_const krb5_encrypt_block      FAR * eblock;
-    krb5_pointer                       FAR * ptr;
-{
-    return krb5_x(eblock->crypto_entry->finish_random_key,
-                 (eblock, ptr));
-}
-
-
-KRB5_DLLIMP krb5_error_code KRB5_CALLCONV
-krb5_random_key(context, eblock, ptr, keyblock)
-    krb5_context                       context;
-    krb5_const krb5_encrypt_block      FAR * eblock;
-    krb5_pointer                       ptr;
-    krb5_keyblock                      FAR * FAR * keyblock;
-{
-    return krb5_x(eblock->crypto_entry->random_key,
-                 (eblock, ptr, keyblock));
-}
-
-
diff --git a/src/lib/crypto/make_checksum.c b/src/lib/crypto/make_checksum.c
new file mode 100644 (file)
index 0000000..b2faef1
--- /dev/null
@@ -0,0 +1,111 @@
+/*
+ * Copyright (C) 1998 by the FundsXpress, INC.
+ * 
+ * All rights reserved.
+ * 
+ * Export of this software from the United States of America may require
+ * a specific license from the United States Government.  It is the
+ * responsibility of any person or organization contemplating export to
+ * obtain such a license before exporting.
+ * 
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of FundsXpress. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  FundsXpress makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#include "k5-int.h"
+#include "cksumtypes.h"
+#include "etypes.h"
+
+krb5_error_code
+krb5_c_make_checksum(context, cksumtype, key, usage, input, cksum)
+     krb5_context context;
+     krb5_cksumtype cksumtype;
+     krb5_const krb5_keyblock *key;
+     krb5_keyusage usage;
+     krb5_const krb5_data *input;
+     krb5_checksum *cksum;
+{
+    int i, e1, e2;
+    krb5_data data;
+    krb5_error_code ret;
+    size_t cksumlen;
+
+    for (i=0; i<krb5_cksumtypes_length; i++) {
+       if (krb5_cksumtypes_list[i].ctype == cksumtype)
+           break;
+    }
+
+    if (i == krb5_cksumtypes_length)
+       return(KRB5_BAD_ENCTYPE);
+
+    if (krb5_cksumtypes_list[i].keyhash)
+       (*(krb5_cksumtypes_list[i].keyhash->hash_size))(&cksumlen);
+    else
+       (*(krb5_cksumtypes_list[i].hash->hash_size))(&cksumlen);
+
+    cksum->length = cksumlen;
+
+    if ((cksum->contents = (krb5_octet *) malloc(cksum->length)) == NULL)
+       return(ENOMEM);
+
+    data.length = cksum->length;
+    data.data = cksum->contents;
+
+    if (krb5_cksumtypes_list[i].keyhash) {
+       /* check if key is compatible */
+
+       if (krb5_cksumtypes_list[i].keyed_etype) {
+           for (e1=0; e1<krb5_enctypes_length; e1++) 
+               if (krb5_enctypes_list[e1].etype ==
+                   krb5_cksumtypes_list[i].keyed_etype)
+                   break;
+
+           for (e2=0; e2<krb5_enctypes_length; e2++) 
+               if (krb5_enctypes_list[e2].etype == key->enctype)
+                   break;
+
+           if ((e1 == krb5_enctypes_length) ||
+               (e2 == krb5_enctypes_length) ||
+               (krb5_enctypes_list[e1].enc != krb5_enctypes_list[e2].enc)) {
+               ret = KRB5_BAD_ENCTYPE;
+               goto cleanup;
+           }
+       }
+
+       ret = (*(krb5_cksumtypes_list[i].keyhash->hash))(key, 0, input, &data);
+    } else if (krb5_cksumtypes_list[i].flags & KRB5_CKSUMFLAG_DERIVE) {
+       /* any key is ok */
+
+       ret = krb5_dk_make_checksum(krb5_cksumtypes_list[i].hash,
+                                   key, usage, input, &data);
+    } else {
+       /* no key is used */
+
+       ret = (*(krb5_cksumtypes_list[i].hash->hash))(1, input, &data);
+    }
+
+    if (!ret) {
+       cksum->magic = KV5M_CHECKSUM;
+       cksum->checksum_type = cksumtype;
+    }
+
+cleanup:
+    if (ret) {
+       memset(cksum->contents, 0, cksum->length);
+       free(cksum->contents);
+    }
+
+    return(ret);
+}
diff --git a/src/lib/crypto/make_random_key.c b/src/lib/crypto/make_random_key.c
new file mode 100644 (file)
index 0000000..391f56d
--- /dev/null
@@ -0,0 +1,84 @@
+/*
+ * Copyright (C) 1998 by the FundsXpress, INC.
+ * 
+ * All rights reserved.
+ * 
+ * Export of this software from the United States of America may require
+ * a specific license from the United States Government.  It is the
+ * responsibility of any person or organization contemplating export to
+ * obtain such a license before exporting.
+ * 
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of FundsXpress. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  FundsXpress makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#include "k5-int.h"
+#include "etypes.h"
+
+KRB5_DLLIMP krb5_error_code KRB5_CALLCONV
+krb5_c_make_random_key(context, enctype, random_key)
+     krb5_context context;
+     krb5_enctype enctype;
+     krb5_keyblock *random_key;
+{
+    int i;
+    krb5_error_code ret;
+    struct krb5_enc_provider *enc;
+    size_t keybytes, keylength;
+    krb5_data random;
+    unsigned char *bytes;
+
+    for (i=0; i<krb5_enctypes_length; i++) {
+       if (krb5_enctypes_list[i].etype == enctype)
+           break;
+    }
+
+    if (i == krb5_enctypes_length)
+       return(KRB5_BAD_ENCTYPE);
+
+    enc = krb5_enctypes_list[i].enc;
+
+    (*(enc->keysize))(&keybytes, &keylength);
+
+    if ((bytes = (unsigned char *) malloc(keybytes)) == NULL)
+       return(ENOMEM);
+    if ((random_key->contents = (krb5_octet *) malloc(keylength)) == NULL) {
+       free(bytes);
+       return(ENOMEM);
+    }
+
+    random.data = bytes;
+    random.length = keybytes;
+
+    if (ret = krb5_c_random_make_octets(context, &random))
+       goto cleanup;
+
+    random_key->magic = KV5M_KEYBLOCK;
+    random_key->enctype = enctype;
+    random_key->length = keylength;
+
+    ret = ((*(enc->make_key))(&random, random_key));
+
+cleanup:
+    memset(bytes, 0, keybytes);
+    free(bytes);
+
+    if (ret) {
+       memset(random_key->contents, 0, keylength);
+       free(random_key->contents);
+    }
+
+    return(ret);
+}
diff --git a/src/lib/crypto/md4/.rconf b/src/lib/crypto/md4/.rconf
deleted file mode 100644 (file)
index de30fd8..0000000
+++ /dev/null
@@ -1,2 +0,0 @@
-ignore RFC1186.TXT
-ignore RFC1186B.TXT
index 3ca8c0872864f10f8626bc7ab74262d27f05b803..7714d4a43f857268731ead5b90c26fec507abc06 100644 (file)
@@ -1,3 +1,7 @@
+Sun Jul 19 12:00:00 1998  Marc Horowitz <marc@mit.edu>
+
+       * *.c: replace the crypto layer.
+
 Tue Mar  3 08:39:47 1998  Ezra Peisach  <epeisach@kangaroo.mit.edu>
 
        * Makefile.in (t_cksum): Do not depend on libkrb5.a, use 
index 739b34b84c1316a29f765d6abe1d55ea716bc985..be6baebb013f2eaae8b17ea85fa3512cdf7f72fc 100644 (file)
@@ -1,7 +1,6 @@
 thisconfigdir=./..
 BUILDTOP=$(REL)$(U)$(S)$(U)$(S)$(U)
-# -I$(srcdir) is needed to pull in $(srcdir)/rsa-md4.h for ./t_mddriver.c.
-CFLAGS = $(CCOPTS) $(DEFS) -I$(srcdir)/../des -I"$(srcdir)"
+CFLAGS = $(CCOPTS) $(DEFS)
 
 ##DOS##BUILDTOP = ..\..\..
 ##DOS##PREFIXDIR=md4
@@ -11,16 +10,22 @@ CFLAGS = $(CCOPTS) $(DEFS) -I$(srcdir)/../des -I"$(srcdir)"
 PROG_LIBPATH=-L$(TOPLIBD)
 PROG_RPATH=$(KRB5_LIBDIR)
 
-RUN_SETUP=@KRB5_RUN_ENV@
+RUN_SETUP = @KRB5_RUN_ENV@ KRB5_CONFIG=$(SRCTOP)/config-files/krb5.conf
 
-STLIBOBJS=md4.o md4glue.o md4crypto.o
-OBJS=  md4.$(OBJEXT) md4glue.$(OBJEXT) md4crypto.$(OBJEXT)
-SRCS=  $(srcdir)/md4.c $(srcdir)/md4glue.c $(srcdir)/md4crypto.c
+STLIBOBJS= md4.o
+
+OBJS= md4.$(OBJEXT) 
+
+SRCS= $(srcdir)/md4.c
 
 ##DOS##LIBOBJS = $(OBJS)
 
 all-unix:: all-libobjs
 
+includes:: depend
+
+depend:: $(SRCS)
+
 t_mddriver.c: $(srcdir)/../md5/t_mddriver.c
        $(CP) $(srcdir)/../md5/t_mddriver.c t_mddriver.c
 
@@ -35,24 +40,13 @@ t_mddriver.exe:
        $(CC) -DMD=4 $(CFLAGS2) -o t_mddriver t_mddriver.c md4.c
        $(RM) md4.obj
 
-t_cksum.c: $(srcdir)/../md5/t_cksum.c
-       $(CP) $(srcdir)/../md5/t_cksum.c t_cksum.c
-
-t_cksum.o: t_cksum.c
-       $(CC) -DMD=4 $(CFLAGS) -c  t_cksum.c
-
-t_cksum: t_cksum.o $(KRB5_BASE_DEPLIBS)
-       $(CC_LINK) -o t_cksum t_cksum.o $(KRB5_BASE_LIBS)
-
-check-unix:: t_mddriver t_cksum
+check-unix:: t_mddriver
        $(RUN_SETUP) $(C)t_mddriver -x
-       $(RUN_SETUP) $(C)t_cksum "this is a test"
 
 check-windows:: t_mddriver$(EXEEXT)
        $(C)t_mddriver$(EXEEXT) -x
 
 clean:: 
        $(RM) t_mddriver$(EXEEXT) t_mddriver.$(OBJEXT) t_mddriver.c
-       $(RM) t_cksum$(EXEEXT) t_cksum.$(OBJEXT) t_cksum.c
 
 clean-unix:: clean-libobjs
diff --git a/src/lib/crypto/md4/md4crypto.c b/src/lib/crypto/md4/md4crypto.c
deleted file mode 100644 (file)
index eac9647..0000000
+++ /dev/null
@@ -1,385 +0,0 @@
-/*
- * lib/crypto/md4/md4crypto.c
- *
- * Copyright 1991 by the Massachusetts Institute of Technology.
- * All Rights Reserved.
- *
- * Export of this software from the United States of America may
- *   require a specific license from the United States Government.
- *   It is the responsibility of any person or organization contemplating
- *   export to obtain such a license before exporting.
- * 
- * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
- * distribute this software and its documentation for any purpose and
- * without fee is hereby granted, provided that the above copyright
- * notice appear in all copies and that both that copyright notice and
- * this permission notice appear in supporting documentation, and that
- * the name of M.I.T. not be used in advertising or publicity pertaining
- * to distribution of the software without specific, written prior
- * permission.  M.I.T. makes no representations about the suitability of
- * this software for any purpose.  It is provided "as is" without express
- * or implied warranty.
- * 
- *
- * Kerberos glue for MD4 sample implementation.
- */
-
-#include "k5-int.h"
-#include "rsa-md4.h"
-#include "des_int.h"   /* we cheat a bit and call it directly... */
-
-/*
- * In Kerberos V5 Beta 5 and previous releases the RSA-MD4-DES implementation
- * did not follow RFC1510.  The folowing definitions control the compatibility
- * with these releases.
- *
- * If MD4_K5BETA_COMPAT is defined, then compatability mode is enabled.  That
- * means that both checksum functions are compiled and available for use and
- * the additional interface md4_crypto_compat_ctl() is defined.
- *
- * If MD4_K5BETA_COMPAT_DEF is defined and compatability mode is enabled, then
- * the compatible behaviour becomes the default.
- *
- */
-#define MD4_K5BETA_COMPAT
-#define MD4_K5BETA_COMPAT_DEF
-
-
-/* Windows needs to these prototypes for the assignment below */
-
-#ifdef MD4_K5BETA_COMPAT
-krb5_error_code
-krb5_md4_crypto_compat_sum_func PROTOTYPE((
-       krb5_const krb5_pointer in,
-       krb5_const size_t in_length,
-       krb5_const krb5_pointer seed,
-       krb5_const size_t seed_length,
-       krb5_checksum *outcksum));
-#endif
-
-krb5_error_code
-krb5_md4_crypto_sum_func PROTOTYPE((
-       krb5_const krb5_pointer in,
-       krb5_const size_t in_length,
-       krb5_const krb5_pointer seed,
-       krb5_const size_t seed_length,
-       krb5_checksum *outcksum));
-
-krb5_error_code
-krb5_md4_crypto_verify_func PROTOTYPE((
-       krb5_const krb5_checksum FAR *cksum,
-       krb5_const krb5_pointer in,
-       krb5_const size_t in_length,
-       krb5_const krb5_pointer seed,
-       krb5_const size_t seed_length));
-
-static mit_des_cblock zero_ivec = { 0 };
-
-static void
-krb5_md4_calculate_cksum(md4ctx, confound, confound_length, in, in_length)
-    krb5_MD4_CTX               *md4ctx;
-    krb5_pointer       confound;
-    size_t             confound_length;
-    krb5_pointer       in;
-    size_t             in_length;
-{
-    krb5_MD4Init(md4ctx);
-    if (confound && confound_length)
-       krb5_MD4Update(md4ctx, confound, confound_length);
-    krb5_MD4Update(md4ctx, in, in_length);
-    krb5_MD4Final(md4ctx);
-}
-
-#ifdef MD4_K5BETA_COMPAT
-/*
- * Generate the RSA-MD4-DES checksum in a manner which is compatible with
- * K5 Beta implementations.  Sigh...
- */
-krb5_error_code
-krb5_md4_crypto_compat_sum_func(in, in_length, seed, seed_length, outcksum)
-    krb5_const krb5_pointer in;
-    krb5_const size_t in_length;
-    krb5_const krb5_pointer seed;
-    krb5_const size_t seed_length;
-    krb5_checksum FAR *outcksum;
-{
-    krb5_octet outtmp[OLD_RSA_MD4_DES_CKSUM_LENGTH];
-    krb5_octet *input = (krb5_octet *)in;
-    krb5_encrypt_block eblock;
-    krb5_keyblock keyblock;
-    krb5_error_code retval;
-    krb5_MD4_CTX working;
-
-    if (outcksum->length < OLD_RSA_MD4_DES_CKSUM_LENGTH)
-       return KRB5_BAD_MSIZE;
-
-    krb5_MD4Init(&working);
-    krb5_MD4Update(&working, input, in_length);
-    krb5_MD4Final(&working);
-
-    outcksum->checksum_type = CKSUMTYPE_RSA_MD4_DES;
-    outcksum->length = OLD_RSA_MD4_DES_CKSUM_LENGTH;
-
-    memcpy((char *)outtmp, (char *)&working.digest[0], 16);
-
-    memset((char *)&working, 0, sizeof(working));
-
-    keyblock.length = seed_length;
-    keyblock.contents = (krb5_octet *)seed;
-    keyblock.enctype = ENCTYPE_DES_CBC_MD4;
-
-    if ((retval = mit_des_process_key(&eblock, &keyblock)))
-       return retval;
-    /* now encrypt it */
-    retval = mit_des_cbc_encrypt((mit_des_cblock *)&outtmp[0],
-                                (mit_des_cblock *)outcksum->contents,
-                                OLD_RSA_MD4_DES_CKSUM_LENGTH,
-                                (struct mit_des_ks_struct *)eblock.priv,
-                                keyblock.contents,
-                                MIT_DES_ENCRYPT);
-    if (retval) {
-       (void) mit_des_finish_key(&eblock);
-       return retval;
-    }
-    return mit_des_finish_key(&eblock);
-}
-#endif /* MD4_K5BETA_COMPAT */
-
-/*
- * Generate the RSA-MD4-DES checksum correctly.
- */
-krb5_error_code
-krb5_md4_crypto_sum_func(in, in_length, seed, seed_length, outcksum)
-    krb5_const krb5_pointer in;
-    krb5_const size_t in_length;
-    krb5_const krb5_pointer seed;
-    krb5_const size_t seed_length;
-    krb5_checksum FAR *outcksum;
-{
-    krb5_octet outtmp[NEW_RSA_MD4_DES_CKSUM_LENGTH];
-    mit_des_cblock     tmpkey;
-    krb5_encrypt_block eblock;
-    krb5_keyblock keyblock;
-    krb5_error_code retval;
-    size_t i;
-
-    krb5_MD4_CTX working;
-
-    /* Generate the confounder in place */
-    if ((retval = krb5_random_confounder(RSA_MD4_DES_CONFOUND_LENGTH, outtmp)))
-       return(retval);
-
-    /* Calculate the checksum */
-    krb5_md4_calculate_cksum(&working,
-                       (krb5_pointer) outtmp,
-                       (size_t) RSA_MD4_DES_CONFOUND_LENGTH,
-                       in,
-                       in_length);
-
-    outcksum->checksum_type = CKSUMTYPE_RSA_MD4_DES;
-    outcksum->length = NEW_RSA_MD4_DES_CKSUM_LENGTH;
-
-    /* Now blast in the digest */
-    memcpy((char *) &outtmp[RSA_MD4_DES_CONFOUND_LENGTH],
-          (char *) &working.digest[0],
-          RSA_MD4_CKSUM_LENGTH);
-
-    /* Clean up droppings */
-    memset((char *)&working, 0, sizeof(working));
-
-    /* Set up the temporary copy of the key (see RFC 1510 section 6.4.3) */
-    memset((char *) tmpkey, 0, sizeof(mit_des_cblock));
-    for (i=0; (i<seed_length) && (i<sizeof(mit_des_cblock)); i++)
-       tmpkey[i] = (((krb5_octet *) seed)[i]) ^ 0xf0;
-
-    keyblock.length = sizeof(mit_des_cblock);
-    keyblock.contents = (krb5_octet *) tmpkey;
-    keyblock.enctype = ENCTYPE_DES_CBC_MD4;
-
-    if ((retval = mit_des_process_key(&eblock, &keyblock)))
-       return retval;
-    /* now encrypt it */
-    retval = mit_des_cbc_encrypt((mit_des_cblock *)&outtmp[0],
-                                (mit_des_cblock *)outcksum->contents,
-                                NEW_RSA_MD4_DES_CKSUM_LENGTH,
-                                (struct mit_des_ks_struct *)eblock.priv,
-                                zero_ivec,
-                                MIT_DES_ENCRYPT);
-    if (retval) {
-       (void) mit_des_finish_key(&eblock);
-       return retval;
-    }
-    return mit_des_finish_key(&eblock);
-}
-
-krb5_error_code
-krb5_md4_crypto_verify_func(cksum, in, in_length, seed, seed_length)
-    krb5_const krb5_checksum FAR *cksum;
-    krb5_const krb5_pointer in;
-    krb5_const size_t in_length;
-    krb5_const krb5_pointer seed;
-    krb5_const size_t seed_length;
-{
-    krb5_octet outtmp[NEW_RSA_MD4_DES_CKSUM_LENGTH];
-    mit_des_cblock     tmpkey;
-    krb5_encrypt_block eblock;
-    krb5_keyblock keyblock;
-    krb5_error_code retval;
-    size_t i;
-
-    krb5_MD4_CTX working;
-
-    retval = 0;
-    if (cksum->checksum_type == CKSUMTYPE_RSA_MD4_DES) {
-#ifdef MD4_K5BETA_COMPAT
-       /*
-        * We have a backwards compatibility problem here.  Kerberos
-        * version 5 Beta 5 and previous releases did not correctly
-        * generate RSA-MD4-DES checksums.  The way that we can
-        * differentiate is by the length of the provided checksum.
-        * If it's only OLD_RSA_MD4_DES_CKSUM_LENGTH, then it's the
-        * old style, otherwise it's the correct implementation.
-        */
-       if (cksum->length == OLD_RSA_MD4_DES_CKSUM_LENGTH) {
-           /*
-            * If we're verifying the Old Style (tm) checksum, then we can just
-            * recalculate the checksum and encrypt it and see if it's the
-            * same.
-            */
-
-           /* Recalculate the checksum with no confounder */
-           krb5_md4_calculate_cksum(&working,
-                               (krb5_pointer) NULL,
-                               (size_t) 0,
-                               in,
-                               in_length);
-
-           /* Use the key "as-is" */
-           keyblock.length = seed_length;
-           keyblock.contents = (krb5_octet *) seed;
-           keyblock.enctype = ENCTYPE_DES_CBC_MD4;
-
-           if ((retval = mit_des_process_key(&eblock, &keyblock)))
-               return retval;
-           /* now encrypt the checksum */
-           retval = mit_des_cbc_encrypt((mit_des_cblock *)&working.digest[0],
-                                        (mit_des_cblock *)&outtmp[0],
-                                        RSA_MD4_CKSUM_LENGTH,
-                                        (struct mit_des_ks_struct *)
-                                               eblock.priv,
-                                        keyblock.contents,
-                                        MIT_DES_ENCRYPT);
-           if (retval) {
-               (void) mit_des_finish_key(&eblock);
-               return retval;
-           }
-           if ((retval = mit_des_finish_key(&eblock)))
-               return(retval);
-
-           /* Compare the encrypted checksums */
-           if (memcmp((char *) &outtmp[0],
-                      (char *) cksum->contents,
-                      OLD_RSA_MD4_DES_CKSUM_LENGTH))
-               retval = KRB5KRB_AP_ERR_BAD_INTEGRITY;
-       }
-       else
-#endif /* MD4_K5BETA_COMPAT */
-       if (cksum->length == (NEW_RSA_MD4_DES_CKSUM_LENGTH)) {
-           /*
-            * If we're verifying the correct implementation, then we have
-            * to do a little more work because we must decrypt the checksum
-            * because it contains the confounder in it.  So, figure out
-            * what our key variant is and then do it!
-            */
-
-           /* Set up the variant of the key (see RFC 1510 section 6.4.3) */
-           memset((char *) tmpkey, 0, sizeof(mit_des_cblock));
-           for (i=0; (i<seed_length) && (i<sizeof(mit_des_cblock)); i++)
-               tmpkey[i] = (((krb5_octet *) seed)[i]) ^ 0xf0;
-
-           keyblock.length = sizeof(mit_des_cblock);
-           keyblock.contents = (krb5_octet *) tmpkey;
-           keyblock.enctype = ENCTYPE_DES_CBC_MD4;
-
-           if ((retval = mit_des_process_key(&eblock, &keyblock)))
-               return retval;
-           /* now decrypt it */
-           retval = mit_des_cbc_encrypt((mit_des_cblock *)cksum->contents,
-                                        (mit_des_cblock *)&outtmp[0],
-                                        NEW_RSA_MD4_DES_CKSUM_LENGTH,
-                                        (struct mit_des_ks_struct *)
-                                               eblock.priv,
-                                        zero_ivec,
-                                        MIT_DES_DECRYPT);
-           if (retval) {
-               (void) mit_des_finish_key(&eblock);
-               return retval;
-           }
-           if ((retval = mit_des_finish_key(&eblock)))
-               return(retval);
-
-           /* Now that we have the decrypted checksum, try to regenerate it */
-           krb5_md4_calculate_cksum(&working,
-                               (krb5_pointer) outtmp,
-                               (size_t) RSA_MD4_DES_CONFOUND_LENGTH,
-                               in,
-                               in_length);
-
-           /* Compare the checksums */
-           if (memcmp((char *) &outtmp[RSA_MD4_DES_CONFOUND_LENGTH],
-                      (char *) &working.digest[0],
-                      RSA_MD4_CKSUM_LENGTH))
-               retval = KRB5KRB_AP_ERR_BAD_INTEGRITY;
-       }
-       else 
-           retval = KRB5KRB_AP_ERR_BAD_INTEGRITY;
-    }
-    else
-       retval = KRB5KRB_AP_ERR_INAPP_CKSUM;
-
-    /* Clean up droppings */
-    memset((char *)&working, 0, sizeof(working));
-    return(retval);
-}
-
-krb5_checksum_entry rsa_md4_des_cksumtable_entry = 
-#if    defined(MD4_K5BETA_COMPAT) && defined(MD4_K5BETA_COMPAT_DEF)
-{
-    0,
-    krb5_md4_crypto_compat_sum_func,
-    krb5_md4_crypto_verify_func,
-    OLD_RSA_MD4_DES_CKSUM_LENGTH,
-    1,                                 /* is collision proof */
-    1,                                 /* uses key */
-};
-#else  /* MD4_K5BETA_COMPAT && MD4_K5BETA_COMPAT_DEF */
-{
-    0,
-    krb5_md4_crypto_sum_func,
-    krb5_md4_crypto_verify_func,
-    NEW_RSA_MD4_DES_CKSUM_LENGTH,
-    1,                                 /* is collision proof */
-    1,                                 /* uses key */
-};
-#endif /* MD4_K5BETA_COMPAT && MD4_K5BETA_COMPAT_DEF */
-
-#ifdef MD4_K5BETA_COMPAT
-/*
- * Turn on/off compatible checksum generation.
- */
-void
-krb5_md4_crypto_compat_ctl(scompat)
-    krb5_boolean       scompat;
-{
-    if (scompat) {
-       rsa_md4_des_cksumtable_entry.sum_func = krb5_md4_crypto_compat_sum_func;
-       rsa_md4_des_cksumtable_entry.checksum_length =
-           OLD_RSA_MD4_DES_CKSUM_LENGTH;
-    }
-    else {
-       rsa_md4_des_cksumtable_entry.sum_func = krb5_md4_crypto_sum_func;
-       rsa_md4_des_cksumtable_entry.checksum_length =
-           NEW_RSA_MD4_DES_CKSUM_LENGTH;
-    }
-}
-#endif /* MD4_K5BETA_COMPAT */
diff --git a/src/lib/crypto/md4/md4driver.c b/src/lib/crypto/md4/md4driver.c
deleted file mode 100644 (file)
index 425ef29..0000000
+++ /dev/null
@@ -1,202 +0,0 @@
-/*
- *     lib/crypto/md4/md4driver.c
- */
-
-/*
- **********************************************************************
- ** md4driver.c -- sample routines to test                           **
- ** RSA Data Security, Inc. MD4 message digest algorithm.            **
- ** Created: 2/16/90 RLR                                             **
- ** Updated: 1/91 SRD                                                **
- **********************************************************************
- */
-
-/*
- **********************************************************************
- ** Copyright (C) 1990, RSA Data Security, Inc. All rights reserved. **
- **                                                                  **
- ** RSA Data Security, Inc. makes no representations concerning      **
- ** either the merchantability of this software or the suitability   **
- ** of this software for any particular purpose.  It is provided "as **
- ** is" without express or implied warranty of any kind.             **
- **                                                                  **
- ** These notices must be retained in any copies of any part of this **
- ** documentation and/or software.                                   **
- **********************************************************************
- */
-
-#include "k5-int.h"
-#include "rsa-md4.h"
-
-/* Prints message digest buffer in mdContext as 32 hexadecimal digits.
-   Order is from low-order byte to high-order byte of digest.
-   Each byte is printed with high-order hexadecimal digit first.
- */
-static void MDPrint (mdContext)
-krb5_MD4_CTX *mdContext;
-{
-  int i;
-
-  for (i = 0; i < 16; i++)
-    printf ("%02x", mdContext->digest[i]);
-}
-
-/* size of test block */
-#define TEST_BLOCK_SIZE 1000
-
-/* number of blocks to process */
-#define TEST_BLOCKS 2000
-
-/* number of test bytes = TEST_BLOCK_SIZE * TEST_BLOCKS */
-static long TEST_BYTES = (long)TEST_BLOCK_SIZE * (long)TEST_BLOCKS;
-
-/* A time trial routine, to measure the speed of MD4.
-   Measures wall time required to digest TEST_BLOCKS * TEST_BLOCK_SIZE
-   characters.
- */
-static void MDTimeTrial ()
-{
-  krb5_MD4_CTX mdContext;
-  time_t endTime, startTime;
-  unsigned char data[TEST_BLOCK_SIZE];
-  unsigned int i;
-
-  /* initialize test data */
-  for (i = 0; i < TEST_BLOCK_SIZE; i++)
-    data[i] = (unsigned char)(i & 0xFF);
-
-  /* start timer */
-  printf ("MD4 time trial. Processing %ld characters...\n", TEST_BYTES);
-  time (&startTime);
-
-  /* digest data in TEST_BLOCK_SIZE byte blocks */
-  krb5_MD4Init (&mdContext);
-  for (i = TEST_BLOCKS; i > 0; i--)
-    krb5_MD4Update (&mdContext, data, TEST_BLOCK_SIZE);
-  krb5_MD4Final (&mdContext);
-  /* stop timer, get time difference */
-  time (&endTime);
-  MDPrint (&mdContext);
-  printf (" is digest of test input.\n");
-  printf
-    ("Seconds to process test input: %ld\n", (long)(endTime-startTime));
-  printf
-    ("Characters processed per second: %ld\n",
-     TEST_BYTES/(endTime-startTime));
-}
-
-/* Computes the message digest for string inString.
-   Prints out message digest, a space, the string (in quotes) and a
-   carriage return.
- */
-static void MDString (inString)
-char *inString;
-{
-  krb5_MD4_CTX mdContext;
-  unsigned int len = strlen (inString);
-
-  krb5_MD4Init (&mdContext);
-  krb5_MD4Update (&mdContext, inString, len);
-  krb5_MD4Final (&mdContext);
-  MDPrint (&mdContext);
-  printf (" \"%s\"\n\n", inString);
-}
-
-/* Computes the message digest for a specified file.
-   Prints out message digest, a space, the file name, and a carriage
-   return.
- */
-static void MDFile (filename)
-char *filename;
-{
-#ifdef __STDC__
-  FILE *inFile = fopen (filename, "rb");
-#else
-  FILE *inFile = fopen (filename, "r");
-#endif
-  krb5_MD4_CTX mdContext;
-  int bytes;
-  unsigned char data[1024];
-
-  if (inFile == NULL) {
-    printf ("%s can't be opened.\n", filename);
-    return;
-  }
-
-  krb5_MD4Init (&mdContext);
-  while ((bytes = fread (data, 1, 1024, inFile)) != 0)
-    krb5_MD4Update (&mdContext, data, bytes);
-  krb5_MD4Final (&mdContext);
-  MDPrint (&mdContext);
-  printf (" %s\n", filename);
-  fclose (inFile);
-}
-
-
-/* Writes the message digest of the data from stdin onto stdout,
-   followed by a carriage return.
- */
-static void MDFilter ()
-{
-  krb5_MD4_CTX mdContext;
-  int bytes;
-  unsigned char data[16];
-
-  krb5_MD4Init (&mdContext);
-  while ((bytes = fread (data, 1, 16, stdin)) != 0)
-    krb5_MD4Update (&mdContext, data, bytes);
-  krb5_MD4Final (&mdContext);
-  MDPrint (&mdContext);
-  printf ("\n");
-}
-
-/* Runs a standard suite of test data.
- */
-static void MDTestSuite ()
-{
-  printf ("MD4 test suite results:\n\n");
-  MDString ("");
-  MDString ("a");
-  MDString ("abc");
-  MDString ("message digest");
-  MDString ("abcdefghijklmnopqrstuvwxyz");
-  MDString
-    ("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789");
-  MDString
-    ("1234567890123456789012345678901234567890\
-1234567890123456789012345678901234567890");
-  /* Contents of file foo are "abc" */
-  MDFile ("foo");
-}
-
-void main (argc, argv)
-int argc;
-char *argv[];
-{
-  int i;
-
-  /* For each command line argument in turn:
-  ** filename          -- prints message digest and name of file
-  ** -sstring          -- prints message digest and contents of string
-  ** -t                -- prints time trial statistics for 1M characters
-  ** -x                -- execute a standard suite of test data
-  ** (no args)         -- writes messages digest of stdin onto stdout
-  */
-  if (argc == 1)
-    MDFilter ();
-  else
-    for (i = 1; i < argc; i++)
-      if (argv[i][0] == '-' && argv[i][1] == 's')
-        MDString (argv[i] + 2);
-      else if (strcmp (argv[i], "-t") == 0)
-        MDTimeTrial ();
-      else if (strcmp (argv[i], "-x") == 0)
-        MDTestSuite ();
-      else MDFile (argv[i]);
-}
-
-/*
- **********************************************************************
- ** End of md4driver.c                                               **
- ******************************* (cut) ********************************
- */
diff --git a/src/lib/crypto/md4/md4glue.c b/src/lib/crypto/md4/md4glue.c
deleted file mode 100644 (file)
index f7e566e..0000000
+++ /dev/null
@@ -1,115 +0,0 @@
-/*
- * lib/crypto/md4/md4glue.c
- *
- * Copyright 1990,1991 by the Massachusetts Institute of Technology.
- * All Rights Reserved.
- *
- * Export of this software from the United States of America may
- *   require a specific license from the United States Government.
- *   It is the responsibility of any person or organization contemplating
- *   export to obtain such a license before exporting.
- * 
- * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
- * distribute this software and its documentation for any purpose and
- * without fee is hereby granted, provided that the above copyright
- * notice appear in all copies and that both that copyright notice and
- * this permission notice appear in supporting documentation, and that
- * the name of M.I.T. not be used in advertising or publicity pertaining
- * to distribution of the software without specific, written prior
- * permission.  M.I.T. makes no representations about the suitability of
- * this software for any purpose.  It is provided "as is" without express
- * or implied warranty.
- * 
- * Kerberos glue for MD4 sample implementation.
- */
-
-#include "k5-int.h"
-#include "rsa-md4.h"
-
-/* Windows needs to these prototypes for the assignment below */
-
-krb5_error_code
-krb5_md4_sum_func PROTOTYPE((
-       krb5_const krb5_pointer in,
-       krb5_const size_t in_length,
-       krb5_const krb5_pointer seed,
-       krb5_const size_t seed_length,
-       krb5_checksum FAR *outcksum));
-
-krb5_error_code
-krb5_md4_verify_func PROTOTYPE((
-       krb5_const krb5_checksum FAR *cksum,
-       krb5_const krb5_pointer in,
-       krb5_const size_t in_length,
-       krb5_const krb5_pointer seed,
-       krb5_const size_t seed_length));
-
-krb5_error_code
-krb5_md4_sum_func(in, in_length, seed, seed_length, outcksum)
-    krb5_const krb5_pointer in;
-    krb5_const size_t in_length;
-    krb5_const krb5_pointer seed;
-    krb5_const size_t seed_length;
-    krb5_checksum FAR *outcksum;
-{
-    krb5_octet *input = (krb5_octet *)in;
-    krb5_MD4_CTX working;
-
-    if (outcksum->length < RSA_MD4_CKSUM_LENGTH)
-       return KRB5_BAD_MSIZE;
-    
-    krb5_MD4Init(&working);
-    krb5_MD4Update(&working, input, in_length);
-    krb5_MD4Final(&working);
-
-    outcksum->checksum_type = CKSUMTYPE_RSA_MD4;
-    outcksum->length = RSA_MD4_CKSUM_LENGTH;
-
-    memcpy((char *)outcksum->contents, (char *)&working.digest[0],
-          RSA_MD4_CKSUM_LENGTH);
-
-    memset((char *)&working, 0, sizeof(working));
-    return 0;
-}
-
-krb5_error_code
-krb5_md4_verify_func(cksum, in, in_length, seed, seed_length)
-    krb5_const krb5_checksum FAR *cksum;
-    krb5_const krb5_pointer in;
-    krb5_const size_t in_length;
-    krb5_const krb5_pointer seed;
-    krb5_const size_t seed_length;
-{
-    krb5_octet *input = (krb5_octet *)in;
-    krb5_MD4_CTX working;
-    krb5_error_code retval;
-
-    retval = 0;
-    if (cksum->checksum_type == CKSUMTYPE_RSA_MD4) {
-       if (cksum->length == RSA_MD4_CKSUM_LENGTH) {
-           krb5_MD4Init(&working);
-           krb5_MD4Update(&working, input, in_length);
-           krb5_MD4Final(&working);
-
-           if (memcmp((char *) cksum->contents,
-                      (char *) &working.digest[0],
-                      RSA_MD4_CKSUM_LENGTH))
-               retval = KRB5KRB_AP_ERR_BAD_INTEGRITY;
-           memset((char *)&working, 0, sizeof(working));
-       }
-       else
-           retval = KRB5KRB_AP_ERR_BAD_INTEGRITY;
-    }
-    else
-       retval = KRB5KRB_AP_ERR_INAPP_CKSUM;
-    return retval;
-}
-
-krb5_checksum_entry rsa_md4_cksumtable_entry = {
-    0,
-    krb5_md4_sum_func,
-    krb5_md4_verify_func,
-    RSA_MD4_CKSUM_LENGTH,
-    1,                                 /* is collision proof */
-    0,                                 /* doesn't use key */
-};
index 1c0026add4739642de98d209d30284003d1f36a0..79fb94a7dd0d414c5f476aa8a6288009c187eafd 100644 (file)
@@ -1,3 +1,7 @@
+Sun Jul 19 12:00:00 1998  Marc Horowitz <marc@mit.edu>
+
+       * *.c: replace the crypto layer.
+
 Tue Mar  3 08:42:10 1998  Ezra Peisach  <epeisach@kangaroo.mit.edu>
 
        * Makefile.in (t_cksum): Do not depend on libkrb5.a, use 
index 3707f897b82e231225b153b84c500a66678b57f5..219fa3081a47c213834bbfa2d6453f9ea72301f0 100644 (file)
@@ -1,6 +1,6 @@
 thisconfigdir=./..
 BUILDTOP=$(REL)$(U)$(S)$(U)$(S)$(U)
-CFLAGS = $(CCOPTS) $(DEFS) -I$(srcdir)/../des
+CFLAGS = $(CCOPTS) $(DEFS)
 
 ##DOS##BUILDTOP = ..\..\..
 ##DOS##PREFIXDIR=md5
@@ -10,35 +10,35 @@ CFLAGS = $(CCOPTS) $(DEFS) -I$(srcdir)/../des
 PROG_LIBPATH=-L$(TOPLIBD)
 PROG_RPATH=$(KRB5_LIBDIR)
 
-RUN_SETUP = @KRB5_RUN_ENV@
+RUN_SETUP = @KRB5_RUN_ENV@ KRB5_CONFIG=$(SRCTOP)/config-files/krb5.conf
 
-STLIBOBJS=md5.o md5glue.o md5crypto.o
+STLIBOBJS= md5.o
 
-OBJS=  md5.$(OBJEXT) md5glue.$(OBJEXT) md5crypto.$(OBJEXT)
-SRCS=  $(srcdir)/md5.c $(srcdir)/md5glue.c $(srcdir)/md5crypto.c
+OBJS= md5.$(OBJEXT) 
+
+SRCS= $(srcdir)/md5.c
 
 ##DOS##LIBOBJS = $(OBJS)
 
 all-unix:: all-libobjs
 
+includes:: depend
+
+depend:: $(SRCS)
+
 t_mddriver: t_mddriver.o md5.o
        $(CC) $(CFLAGS) $(LDFLAGS) -o t_mddriver t_mddriver.o md5.o
 
 t_mddriver.exe:
        $(CC) $(CFLAGS2) -o t_mddriver.exe t_mddriver.c md5.c
 
-t_cksum: t_cksum.o $(KRB5_BASE_DEPLIBS)
-       $(CC_LINK) -o t_cksum t_cksum.o $(KRB5_BASE_LIBS)
-
-check-unix:: t_mddriver t_cksum
+check-unix:: t_mddriver
        $(RUN_SETUP) $(C)t_mddriver -x
-       $(RUN_SETUP) $(C)t_cksum "this is a test"
 
 check-windows:: t_mddriver$(EXEEXT)
        $(C)t_mddriver$(EXEEXT) -x
 
 clean:: 
        $(RM) t_mddriver$(EXEEXT) t_mddriver.$(OBJEXT)
-       $(RM) t_cksum$(EXEEXT) t_cksum.$(OBJEXT)
 
 clean-unix:: clean-libobjs
diff --git a/src/lib/crypto/md5/md5crypto.c b/src/lib/crypto/md5/md5crypto.c
deleted file mode 100644 (file)
index b83e50e..0000000
+++ /dev/null
@@ -1,353 +0,0 @@
-#include "k5-int.h"
-#include "rsa-md5.h"
-#include "des_int.h"   /* we cheat a bit and call it directly... */
-
-/*
- * In Kerberos V5 Beta 5 and previous releases the RSA-MD5-DES implementation
- * did not follow RFC1510.  The folowing definitions control the compatibility
- * with these releases.
- *
- * If MD5_K5BETA_COMPAT is defined, then compatability mode is enabled.  That
- * means that both checksum functions are compiled and available for use and
- * the additional interface krb5_md5_crypto_compat_ctl() is defined.
- *
- * If MD5_K5BETA_COMPAT_DEF is defined and compatability mode is enabled, then
- * the compatible behaviour becomes the default.
- *
- */
-#define MD5_K5BETA_COMPAT
-#define MD5_K5BETA_COMPAT_DEF
-
-
-/* Windows needs to these prototypes for the assignment below */
-
-#ifdef MD5_K5BETA_COMPAT
-krb5_error_code
-krb5_md5_crypto_compat_sum_func PROTOTYPE((
-       krb5_const krb5_pointer in,
-       krb5_const size_t in_length,
-       krb5_const krb5_pointer seed,
-       krb5_const size_t seed_length,
-       krb5_checksum FAR *outcksum));
-#endif
-
-krb5_error_code
-krb5_md5_crypto_sum_func PROTOTYPE((
-       krb5_const krb5_pointer in,
-       krb5_const size_t in_length,
-       krb5_const krb5_pointer seed,
-       krb5_const size_t seed_length,
-       krb5_checksum FAR *outcksum));
-
-krb5_error_code
-krb5_md5_crypto_verify_func PROTOTYPE((
-       krb5_const krb5_checksum FAR *cksum,
-       krb5_const krb5_pointer in,
-       krb5_const size_t in_length,
-       krb5_const krb5_pointer seed,
-       krb5_const size_t seed_length));
-
-static mit_des_cblock zero_ivec = { 0 };
-
-static void
-krb5_md5_calculate_cksum(md5ctx, confound, confound_length, in, in_length)
-    krb5_MD5_CTX               *md5ctx;
-    krb5_pointer       in;
-    size_t             in_length;
-    krb5_pointer       confound;
-    size_t             confound_length;
-{
-    krb5_MD5Init(md5ctx);
-    if (confound && confound_length)
-       krb5_MD5Update(md5ctx, confound, confound_length);
-    krb5_MD5Update(md5ctx, in, in_length);
-    krb5_MD5Final(md5ctx);
-}
-
-#ifdef MD5_K5BETA_COMPAT
-krb5_error_code
-krb5_md5_crypto_compat_sum_func(in, in_length, seed, seed_length, outcksum)
-    krb5_const krb5_pointer in;
-    krb5_const size_t in_length;
-    krb5_const krb5_pointer seed;
-    krb5_const size_t seed_length;
-    krb5_checksum FAR *outcksum;
-{
-    krb5_octet outtmp[OLD_RSA_MD5_DES_CKSUM_LENGTH];
-    krb5_octet *input = (krb5_octet *)in;
-    krb5_encrypt_block eblock;
-    krb5_keyblock keyblock;
-    krb5_error_code retval;
-
-    krb5_MD5_CTX working;
-
-    krb5_MD5Init(&working);
-    krb5_MD5Update(&working, input, in_length);
-    krb5_MD5Final(&working);
-
-    outcksum->checksum_type = CKSUMTYPE_RSA_MD5_DES;
-    outcksum->length = OLD_RSA_MD5_DES_CKSUM_LENGTH;
-
-    memcpy((char *)outtmp, (char *)&working.digest[0], 16);
-
-    memset((char *)&working, 0, sizeof(working));
-
-    keyblock.length = seed_length;
-    keyblock.contents = (krb5_octet *)seed;
-    keyblock.enctype = ENCTYPE_DES_CBC_MD5;
-
-    if ((retval = mit_des_process_key(&eblock, &keyblock)))
-       return retval;
-    /* now encrypt it */
-    retval = mit_des_cbc_encrypt((mit_des_cblock *)&outtmp[0],
-                                (mit_des_cblock *)outcksum->contents,
-                                OLD_RSA_MD5_DES_CKSUM_LENGTH,
-                                (struct mit_des_ks_struct *)eblock.priv,
-                                keyblock.contents,
-                                MIT_DES_ENCRYPT);
-    if (retval) {
-       (void) mit_des_finish_key(&eblock);
-       return retval;
-    }
-    return mit_des_finish_key(&eblock);
-}
-#endif /* MD5_K5BETA_COMPAT */
-
-krb5_error_code
-krb5_md5_crypto_sum_func(in, in_length, seed, seed_length, outcksum)
-    krb5_const krb5_pointer in;
-    krb5_const size_t in_length;
-    krb5_const krb5_pointer seed;
-    krb5_const size_t seed_length;
-    krb5_checksum FAR *outcksum;
-{
-    krb5_octet outtmp[NEW_RSA_MD5_DES_CKSUM_LENGTH];
-    mit_des_cblock     tmpkey;
-    krb5_encrypt_block eblock;
-    krb5_keyblock keyblock;
-    krb5_error_code retval;
-    size_t i;
-    krb5_MD5_CTX working;
-
-    if (outcksum->length < NEW_RSA_MD5_DES_CKSUM_LENGTH)
-       return KRB5_BAD_MSIZE;
-
-    /* Generate the confounder in place */
-    if ((retval = krb5_random_confounder(RSA_MD5_DES_CONFOUND_LENGTH, outtmp)))
-       return(retval);
-
-    /* Calculate the checksum */
-    krb5_md5_calculate_cksum(&working,
-                       (krb5_pointer) outtmp,
-                       (size_t) RSA_MD5_DES_CONFOUND_LENGTH,
-                       in,
-                       in_length);
-
-    outcksum->checksum_type = CKSUMTYPE_RSA_MD5_DES;
-    outcksum->length = NEW_RSA_MD5_DES_CKSUM_LENGTH;
-
-    /* Now blast in the digest */
-    memcpy((char *)&outtmp[RSA_MD5_DES_CONFOUND_LENGTH],
-          (char *)&working.digest[0],
-          RSA_MD5_CKSUM_LENGTH);
-
-    /* Clean up the droppings */
-    memset((char *)&working, 0, sizeof(working));
-
-    /* Set up the temporary copy of the key (see RFC 1510 section 6.4.5) */
-    memset((char *) tmpkey, 0, sizeof(mit_des_cblock));
-    for (i=0; (i<seed_length) && (i<sizeof(mit_des_cblock)); i++)
-       tmpkey[i] = (((krb5_octet *) seed)[i]) ^ 0xf0;
-
-    keyblock.length = sizeof(mit_des_cblock);
-    keyblock.contents = (krb5_octet *) tmpkey;
-    keyblock.enctype = ENCTYPE_DES_CBC_MD5;
-
-    if ((retval = mit_des_process_key(&eblock, &keyblock)))
-       return retval;
-    /* now encrypt it */
-    retval = mit_des_cbc_encrypt((mit_des_cblock *)&outtmp[0],
-                                (mit_des_cblock *)outcksum->contents,
-                                NEW_RSA_MD5_DES_CKSUM_LENGTH,
-                                (struct mit_des_ks_struct *)eblock.priv,
-                                zero_ivec,
-                                MIT_DES_ENCRYPT);
-    if (retval) {
-       (void) mit_des_finish_key(&eblock);
-       return retval;
-    }
-    return mit_des_finish_key(&eblock);
-}
-
-krb5_error_code
-krb5_md5_crypto_verify_func(cksum, in, in_length, seed, seed_length)
-    krb5_const krb5_checksum FAR *cksum;
-    krb5_const krb5_pointer in;
-    krb5_const size_t in_length;
-    krb5_const krb5_pointer seed;
-    krb5_const size_t seed_length;
-{
-    krb5_octet outtmp[NEW_RSA_MD5_DES_CKSUM_LENGTH];
-    mit_des_cblock     tmpkey;
-    krb5_encrypt_block eblock;
-    krb5_keyblock keyblock;
-    krb5_error_code retval;
-    size_t i;
-
-    krb5_MD5_CTX working;
-
-    retval = 0;
-    if (cksum->checksum_type == CKSUMTYPE_RSA_MD5_DES) {
-#ifdef MD5_K5BETA_COMPAT
-       /*
-        * We have a backwards compatibility problem here.  Kerberos
-        * version 5 Beta 5 and previous releases did not correctly
-        * generate RSA-MD5-DES checksums.  The way that we can
-        * differentiate is by the length of the provided checksum.
-        * If it's only OLD_RSA_MD5_DES_CKSUM_LENGTH, then it's the
-        * old style, otherwise it's the correct implementation.
-        */
-       if (cksum->length == OLD_RSA_MD5_DES_CKSUM_LENGTH) {
-           /*
-            * If we're verifying the Old Style (tm) checksum, then we can just
-            * recalculate the checksum and encrypt it and see if it's the
-            * same.
-            */
-
-           /* Recalculate the checksum with no confounder */
-           krb5_md5_calculate_cksum(&working,
-                               (krb5_pointer) NULL,
-                               (size_t) 0,
-                               in,
-                               in_length);
-
-           /* Use the key "as-is" */
-           keyblock.length = seed_length;
-           keyblock.contents = (krb5_octet *) seed;
-           keyblock.enctype = ENCTYPE_DES_CBC_MD5;
-
-           if ((retval = mit_des_process_key(&eblock, &keyblock)))
-               return retval;
-           /* now encrypt the checksum */
-           retval = mit_des_cbc_encrypt((mit_des_cblock *)&working.digest[0],
-                                        (mit_des_cblock *)&outtmp[0],
-                                        OLD_RSA_MD5_DES_CKSUM_LENGTH,
-                                        (struct mit_des_ks_struct *)
-                                               eblock.priv,
-                                        keyblock.contents,
-                                        MIT_DES_ENCRYPT);
-           if (retval) {
-               (void) mit_des_finish_key(&eblock);
-               return retval;
-           }
-           if ((retval = mit_des_finish_key(&eblock)))
-               return(retval);
-
-           /* Compare the encrypted checksums */
-           if (memcmp((char *) &outtmp[0],
-                      (char *) cksum->contents,
-                      OLD_RSA_MD5_DES_CKSUM_LENGTH))
-               retval = KRB5KRB_AP_ERR_BAD_INTEGRITY;
-       }
-       else
-#endif /* MD5_K5BETA_COMPAT */
-       if (cksum->length == (NEW_RSA_MD5_DES_CKSUM_LENGTH)) {
-           /*
-            * If we're verifying the correct implementation, then we have
-            * to do a little more work because we must decrypt the checksum
-            * because it contains the confounder in it.  So, figure out
-            * what our key variant is and then do it!
-            */
-
-           /* Set up the variant of the key (see RFC 1510 section 6.4.5) */
-           memset((char *) tmpkey, 0, sizeof(mit_des_cblock));
-           for (i=0; (i<seed_length) && (i<sizeof(mit_des_cblock)); i++)
-               tmpkey[i] = (((krb5_octet *) seed)[i]) ^ 0xf0;
-
-           keyblock.length = sizeof(mit_des_cblock);
-           keyblock.contents = (krb5_octet *) tmpkey;
-           keyblock.enctype = ENCTYPE_DES_CBC_MD5;
-
-           if ((retval = mit_des_process_key(&eblock, &keyblock)))
-               return retval;
-           /* now decrypt it */
-           retval = mit_des_cbc_encrypt((mit_des_cblock *)cksum->contents,
-                                        (mit_des_cblock *)&outtmp[0],
-                                        NEW_RSA_MD5_DES_CKSUM_LENGTH,
-                                        (struct mit_des_ks_struct *)
-                                               eblock.priv,
-                                        zero_ivec,
-                                        MIT_DES_DECRYPT);
-           if (retval) {
-               (void) mit_des_finish_key(&eblock);
-               return retval;
-           }
-           if ((retval = mit_des_finish_key(&eblock)))
-               return(retval);
-
-           /* Now that we have the decrypted checksum, try to regenerate it */
-           krb5_md5_calculate_cksum(&working,
-                               (krb5_pointer) outtmp,
-                               (size_t) RSA_MD5_DES_CONFOUND_LENGTH,
-                               in,
-                               in_length);
-
-           /* Compare the checksums */
-           if (memcmp((char *) &outtmp[RSA_MD5_DES_CONFOUND_LENGTH],
-                      (char *) &working.digest[0],
-                      RSA_MD5_CKSUM_LENGTH))
-               retval = KRB5KRB_AP_ERR_BAD_INTEGRITY;
-       }
-       else 
-           retval = KRB5KRB_AP_ERR_BAD_INTEGRITY;
-    }
-    else
-       retval = KRB5KRB_AP_ERR_INAPP_CKSUM;
-
-    /* Clean up droppings */
-    memset((char *)&working, 0, sizeof(working));
-    return(retval);
-}
-
-krb5_checksum_entry rsa_md5_des_cksumtable_entry =
-#if    defined(MD5_K5BETA_COMPAT) && defined(MD5_K5BETA_COMPAT_DEF)
-{
-    0,
-    krb5_md5_crypto_compat_sum_func,
-    krb5_md5_crypto_verify_func,
-    OLD_RSA_MD5_DES_CKSUM_LENGTH,
-    1,                                 /* is collision proof */
-    1,                                 /* uses key */
-};
-#else  /* MD5_K5BETA_COMPAT && MD5_K5BETA_COMPAT_DEF */
-{
-    0,
-    krb5_md5_crypto_sum_func,
-    krb5_md5_crypto_verify_func,
-    NEW_RSA_MD5_DES_CKSUM_LENGTH,
-    1,                                 /* is collision proof */
-    1,                                 /* uses key */
-};
-#endif /* MD5_K5BETA_COMPAT && MD5_K5BETA_COMPAT_DEF */
-
-#ifdef MD5_K5BETA_COMPAT
-/*
- * Turn on/off compatible checksum generation.
- */
-void
-krb5_md5_crypto_compat_ctl(scompat)
-    krb5_boolean       scompat;
-{
-    if (scompat) {
-       rsa_md5_des_cksumtable_entry.sum_func = krb5_md5_crypto_compat_sum_func;
-       rsa_md5_des_cksumtable_entry.checksum_length =
-           OLD_RSA_MD5_DES_CKSUM_LENGTH;
-    }
-    else {
-       rsa_md5_des_cksumtable_entry.sum_func = krb5_md5_crypto_sum_func;
-       rsa_md5_des_cksumtable_entry.checksum_length =
-           NEW_RSA_MD5_DES_CKSUM_LENGTH;
-    }
-}
-#endif /* MD5_K5BETA_COMPAT */
-
diff --git a/src/lib/crypto/md5/md5glue.c b/src/lib/crypto/md5/md5glue.c
deleted file mode 100644 (file)
index 66d5aa7..0000000
+++ /dev/null
@@ -1,89 +0,0 @@
-#include "k5-int.h"
-#include "rsa-md5.h"
-
-/* Windows needs to these prototypes for the assignment below */
-
-krb5_error_code
-krb5_md5_sum_func PROTOTYPE((
-       krb5_const krb5_pointer in,
-       krb5_const size_t in_length,
-       krb5_const krb5_pointer seed,
-       krb5_const size_t seed_length,
-       krb5_checksum FAR *outcksum));
-
-krb5_error_code
-krb5_md5_verify_func PROTOTYPE((
-       krb5_const krb5_checksum FAR *cksum,
-       krb5_const krb5_pointer in,
-       krb5_const size_t in_length,
-       krb5_const krb5_pointer seed,
-       krb5_const size_t seed_length));
-
-krb5_error_code
-krb5_md5_sum_func(in, in_length, seed, seed_length, outcksum)
-    krb5_const krb5_pointer in;
-    krb5_const size_t in_length;
-    krb5_const krb5_pointer seed;
-    krb5_const size_t seed_length;
-    krb5_checksum FAR *outcksum;
-{
-    krb5_octet *input = (krb5_octet *)in;
-    krb5_MD5_CTX working;
-
-    if (outcksum->length < RSA_MD5_CKSUM_LENGTH)
-       return KRB5_BAD_MSIZE;
-    
-    krb5_MD5Init(&working);
-    krb5_MD5Update(&working, input, in_length);
-    krb5_MD5Final(&working);
-
-    outcksum->checksum_type = CKSUMTYPE_RSA_MD5;
-    outcksum->length = RSA_MD5_CKSUM_LENGTH;
-
-    memcpy((char *)outcksum->contents, (char *)&working.digest[0], 16);
-
-    memset((char *)&working, 0, sizeof(working));
-    return 0;
-}
-
-krb5_error_code
-krb5_md5_verify_func(cksum, in, in_length, seed, seed_length)
-    krb5_const krb5_checksum FAR *cksum;
-    krb5_const krb5_pointer in;
-    krb5_const size_t in_length;
-    krb5_const krb5_pointer seed;
-    krb5_const size_t seed_length;
-{
-    krb5_octet *input = (krb5_octet *)in;
-    krb5_MD5_CTX working;
-    krb5_error_code retval;
-
-    retval = 0;
-    if (cksum->checksum_type == CKSUMTYPE_RSA_MD5) {
-       if (cksum->length == RSA_MD5_CKSUM_LENGTH) {
-           krb5_MD5Init(&working);
-           krb5_MD5Update(&working, input, in_length);
-           krb5_MD5Final(&working);
-
-           if (memcmp((char *) cksum->contents,
-                      (char *) &working.digest[0],
-                      RSA_MD5_CKSUM_LENGTH))
-               retval = KRB5KRB_AP_ERR_BAD_INTEGRITY;
-           memset((char *)&working, 0, sizeof(working));
-       }
-       else
-           retval = KRB5KRB_AP_ERR_BAD_INTEGRITY;
-    }
-    else
-       retval = KRB5KRB_AP_ERR_INAPP_CKSUM;
-    return retval;
-}
-
-krb5_checksum_entry rsa_md5_cksumtable_entry = {
-    0,
-    krb5_md5_sum_func,
-    krb5_md5_verify_func,
-    RSA_MD5_CKSUM_LENGTH,
-    1,                                 /* is collision proof */
-    0,                                 /* doesn't use key */
-};
diff --git a/src/lib/crypto/md5/t_cksum.c b/src/lib/crypto/md5/t_cksum.c
deleted file mode 100644 (file)
index 5bc6370..0000000
+++ /dev/null
@@ -1,203 +0,0 @@
-/*
- * lib/crypto/md5/t_cksum.c
- *
- * Copyright 1995 by the Massachusetts Institute of Technology.
- * All Rights Reserved.
- *
- * Export of this software from the United States of America may
- *   require a specific license from the United States Government.
- *   It is the responsibility of any person or organization contemplating
- *   export to obtain such a license before exporting.
- *
- * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
- * distribute this software and its documentation for any purpose and
- * without fee is hereby granted, provided that the above copyright
- * notice appear in all copies and that both that copyright notice and
- * this permission notice appear in supporting documentation, and that
- * the name of M.I.T. not be used in advertising or publicity pertaining
- * to distribution of the software without specific, written prior
- * permission.  M.I.T. makes no representations about the suitability of
- * this software for any purpose.  It is provided "as is" without express
- * or implied warranty.
- *
- */
-
-/*
- * t_cksum.c - Test checksum and checksum compatability for rsa-md[4,5]-des
- */
-
-#ifndef        MD
-#define        MD      5
-#endif /* MD */
-
-#include "k5-int.h"
-#if    MD == 4
-#include "rsa-md4.h"
-#endif /* MD == 4 */
-#if    MD == 5
-#include "rsa-md5.h"
-#endif /* MD == 5 */
-#include "des_int.h"
-
-#define MD5_K5BETA_COMPAT
-#define MD4_K5BETA_COMPAT
-
-#if    MD == 4
-#define        CONFOUNDER_LENGTH       RSA_MD4_DES_CONFOUND_LENGTH
-#define        NEW_CHECKSUM_LENGTH     NEW_RSA_MD4_DES_CKSUM_LENGTH
-#define        OLD_CHECKSUM_LENGTH     OLD_RSA_MD4_DES_CKSUM_LENGTH
-#define        CHECKSUM_TYPE           CKSUMTYPE_RSA_MD4_DES
-#ifdef MD4_K5BETA_COMPAT
-#define        K5BETA_COMPAT   1
-#else  /* MD4_K5BETA_COMPAT */
-#undef K5BETA_COMPAT
-#endif /* MD4_K5BETA_COMPAT */
-#define        CKSUM_FUNCTION          krb5_md4_crypto_sum_func
-#define        COMPAT_FUNCTION         krb5_md4_crypto_compat_sum_func
-#define        VERIFY_FUNCTION         krb5_md4_crypto_verify_func
-#endif /* MD == 4 */
-
-#if    MD == 5
-#define        CONFOUNDER_LENGTH       RSA_MD5_DES_CONFOUND_LENGTH
-#define        NEW_CHECKSUM_LENGTH     NEW_RSA_MD5_DES_CKSUM_LENGTH
-#define        OLD_CHECKSUM_LENGTH     OLD_RSA_MD5_DES_CKSUM_LENGTH
-#define        CHECKSUM_TYPE           CKSUMTYPE_RSA_MD5_DES
-#ifdef MD5_K5BETA_COMPAT
-#define        K5BETA_COMPAT   1
-#else  /* MD5_K5BETA_COMPAT */
-#undef K5BETA_COMPAT
-#endif /* MD5_K5BETA_COMPAT */
-#define        CKSUM_FUNCTION          krb5_md5_crypto_sum_func
-#define        COMPAT_FUNCTION         krb5_md5_crypto_compat_sum_func
-#define        VERIFY_FUNCTION         krb5_md5_crypto_verify_func
-#endif /* MD == 5 */
-
-static void
-print_checksum(text, number, message, checksum)
-     char      *text;
-     int       number;
-     char      *message;
-     krb5_checksum     *checksum;
-{
-  int i;
-
-  printf("%s MD%d checksum(\"%s\") = ", text, number, message);
-  for (i=0; i<checksum->length; i++)
-    printf("%02x", checksum->contents[i]);
-  printf("\n");
-}
-
-/*
- * Test the checksum verification of Old Style (tm) and correct RSA-MD[4,5]-DES
- * checksums.
- */
-int
-main(argc, argv)
-     int argc;
-     char **argv;
-{
-  int                  msgindex;
-  krb5_context         kcontext;
-  krb5_encrypt_block   encblock;
-  krb5_keyblock                keyblock;
-  krb5_error_code      kret;
-  krb5_checksum                oldstyle_checksum;
-  krb5_checksum                newstyle_checksum;
-  krb5_data            pwdata;
-  char                 *pwd;
-
-  pwd = "test password";
-  pwdata.length = strlen(pwd);
-  pwdata.data = pwd;
-  krb5_use_enctype(kcontext, &encblock, DEFAULT_KDC_ENCTYPE);
-  if ((kret = mit_des_string_to_key(&encblock, &keyblock, &pwdata, NULL))) {
-    printf("mit_des_string_to_key choked with %d\n", kret);
-    return(kret);
-  }
-  if ((kret = mit_des_process_key(&encblock, &keyblock))) {
-    printf("mit_des_process_key choked with %d\n", kret);
-    return(kret);
-  }
-
-  oldstyle_checksum.length = OLD_CHECKSUM_LENGTH;
-  if (!(oldstyle_checksum.contents = (krb5_octet *) malloc(OLD_CHECKSUM_LENGTH))) {
-    printf("cannot get memory for old style checksum\n");
-    return(ENOMEM);
-  }
-  newstyle_checksum.length = NEW_CHECKSUM_LENGTH;
-  if (!(newstyle_checksum.contents = (krb5_octet *)
-       malloc(NEW_CHECKSUM_LENGTH))) {
-    printf("cannot get memory for new style checksum\n");
-    return(ENOMEM);
-  }
-  for (msgindex = 1; msgindex < argc; msgindex++) {
-    if ((kret = CKSUM_FUNCTION(argv[msgindex],
-                              strlen(argv[msgindex]),
-                              (krb5_pointer) keyblock.contents,
-                              keyblock.length,
-                              &newstyle_checksum))) {
-      printf("krb5_calculate_checksum choked with %d\n", kret);
-      break;
-    }
-    print_checksum("correct", MD, argv[msgindex], &newstyle_checksum);
-#ifdef K5BETA_COMPAT
-    if ((kret = COMPAT_FUNCTION(argv[msgindex],
-                               strlen(argv[msgindex]),
-                               (krb5_pointer) keyblock.contents,
-                               keyblock.length,
-                               &oldstyle_checksum))) {
-      printf("old style calculate_checksum choked with %d\n", kret);
-      break;
-    }
-    print_checksum("old", MD, argv[msgindex], &oldstyle_checksum);
-#endif /* K5BETA_COMPAT */
-    if ((kret = VERIFY_FUNCTION(&newstyle_checksum,
-                               argv[msgindex],
-                               strlen(argv[msgindex]),
-                               (krb5_pointer) keyblock.contents,
-                               keyblock.length))) {
-      printf("verify on new checksum choked with %d\n", kret);
-      break;
-    }
-    printf("Verify succeeded for \"%s\"\n", argv[msgindex]);
-#ifdef K5BETA_COMPAT
-    if ((kret = VERIFY_FUNCTION(&oldstyle_checksum,
-                               argv[msgindex],
-                               strlen(argv[msgindex]),
-                               (krb5_pointer) keyblock.contents,
-                               keyblock.length))) {
-      printf("verify on old checksum choked with %d\n", kret);
-      break;
-    }
-    printf("Compatible checksum verify succeeded for \"%s\"\n",
-          argv[msgindex]);
-#endif /* K5BETA_COMPAT */
-    newstyle_checksum.contents[0]++;
-    if (!(kret = VERIFY_FUNCTION(&newstyle_checksum,
-                                argv[msgindex],
-                                strlen(argv[msgindex]),
-                                (krb5_pointer) keyblock.contents,
-                                keyblock.length))) {
-      printf("verify on new checksum should have choked\n");
-      break;
-    }
-    printf("Verify of bad checksum OK for \"%s\"\n", argv[msgindex]);
-#ifdef K5BETA_COMPAT
-    oldstyle_checksum.contents[0]++;
-    if (!(kret = VERIFY_FUNCTION(&oldstyle_checksum,
-                                argv[msgindex],
-                                strlen(argv[msgindex]),
-                                (krb5_pointer) keyblock.contents,
-                                keyblock.length))) {
-      printf("verify on old checksum should have choked\n");
-      break;
-    }
-    printf("Compatible checksum verify of altered checksum OK for \"%s\"\n",
-          argv[msgindex]);
-#endif /* K5BETA_COMPAT */
-    kret = 0;
-  }
-  if (!kret)
-    printf("%d tests passed successfully for MD%d checksum\n", argc-1, MD);
-  return(kret);
-}
diff --git a/src/lib/crypto/nfold.c b/src/lib/crypto/nfold.c
new file mode 100644 (file)
index 0000000..07c539e
--- /dev/null
@@ -0,0 +1,132 @@
+/*
+ * Copyright (C) 1998 by the FundsXpress, INC.
+ * 
+ * All rights reserved.
+ * 
+ * Export of this software from the United States of America may require
+ * a specific license from the United States Government.  It is the
+ * responsibility of any person or organization contemplating export to
+ * obtain such a license before exporting.
+ * 
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of FundsXpress. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  FundsXpress makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#include "k5-int.h"
+#include <memory.h>
+
+/*
+n-fold(k-bits):
+  l = lcm(n,k)
+  r = l/k
+  s = k-bits | k-bits rot 13 | k-bits rot 13*2 | ... | k-bits rot 13*(r-1)
+  compute the 1's complement sum:
+       n-fold = s[0..n-1]+s[n..2n-1]+s[2n..3n-1]+..+s[(k-1)*n..k*n-1]
+*/
+
+/* representation: msb first, assume n and k are multiples of 8, and
+   that k>=16.  this is the case of all the cryptosystems which are
+   likely to be used.  this function can be replaced if that
+   assumption ever fails.  */
+
+/* input length is in bits */
+
+void
+krb5_nfold(inbits, in, outbits, out)
+     int inbits;
+     krb5_const unsigned char *in;
+     int outbits;
+     unsigned char *out;
+{
+    int a,b,c,gcd,lcm;
+    int reps;
+    int byte, i, msbit;
+
+    /* the code below is more readable if I make these bytes
+       instead of bits */
+
+    inbits >>= 3;
+    outbits >>= 3;
+
+    /* first compute lcm(n,k) */
+
+    a = outbits;
+    b = inbits;
+
+    while(b != 0) {
+       c = b;
+       b = a%b;
+       a = c;
+    }
+
+    lcm = outbits*inbits/a;
+
+    /* now do the real work */
+
+    memset(out, 0, outbits);
+    byte = 0;
+
+    /* this will end up cycling through k lcm(k,n)/k times, which
+       is correct */
+    for (i=lcm-1; i>=0; i--) {
+       /* compute the msbit in k which gets added into this byte */
+       msbit = (/* first, start with the msbit in the first, unrotated
+                   byte */
+                ((inbits<<3)-1)
+                /* then, for each byte, shift to the right for each
+                   repetition */
+                +(((inbits<<3)+13)*(i/inbits))
+                /* last, pick out the correct byte within that
+                   shifted repetition */
+                +((inbits-(i%inbits))<<3)
+                )%(inbits<<3);
+
+       /* pull out the byte value itself */
+       byte += (((in[((inbits-1)-(msbit>>3))%inbits]<<8)|
+                 (in[((inbits)-(msbit>>3))%inbits]))
+                >>((msbit&7)+1))&0xff;
+
+       /* do the addition */
+       byte += out[i%outbits];
+       out[i%outbits] = byte&0xff;
+
+#if 0
+       printf("msbit[%d] = %d\tbyte = %02x\tsum = %03x\n", i, msbit,
+              (((in[((inbits-1)-(msbit>>3))%inbits]<<8)|
+                (in[((inbits)-(msbit>>3))%inbits]))
+               >>((msbit&7)+1))&0xff, byte);
+#endif
+
+       /* keep around the carry bit, if any */
+       byte >>= 8;
+
+#if 0
+       printf("carry=%d\n", byte);
+#endif
+    }
+
+    /* if there's a carry bit left over, add it back in */
+    if (byte) {
+       for (i=outbits-1; i>=0; i--) {
+           /* do the addition */
+           byte += out[i];
+           out[i] = byte&0xff;
+
+           /* keep around the carry bit, if any */
+           byte >>= 8;
+       }
+    }
+}
+
diff --git a/src/lib/crypto/old_api_glue.c b/src/lib/crypto/old_api_glue.c
new file mode 100644 (file)
index 0000000..64be9b8
--- /dev/null
@@ -0,0 +1,360 @@
+/*
+ * Copyright (C) 1998 by the FundsXpress, INC.
+ * 
+ * All rights reserved.
+ * 
+ * Export of this software from the United States of America may require
+ * a specific license from the United States Government.  It is the
+ * responsibility of any person or organization contemplating export to
+ * obtain such a license before exporting.
+ * 
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of FundsXpress. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  FundsXpress makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#include "k5-int.h"
+
+krb5_error_code krb5_encrypt(context, inptr, outptr, size, eblock, ivec)
+     krb5_context context;
+     krb5_const krb5_pointer inptr;
+     krb5_pointer outptr;
+     krb5_const size_t size;
+     krb5_encrypt_block FAR * eblock;
+     krb5_pointer ivec;
+{
+    krb5_data inputd, ivecd;
+    krb5_enc_data outputd;
+    size_t blocksize, outlen;
+    krb5_error_code ret;
+
+    if (ivec) {
+       if (ret = krb5_c_block_size(context, eblock->key->enctype, &blocksize))
+           return(ret);
+
+       ivecd.length = blocksize;
+       ivecd.data = ivec;
+    }
+
+    /* size is the length of the input cleartext data */
+    inputd.length = size;
+    inputd.data = inptr;
+
+    /* The size of the output buffer isn't part of the old api.  Not too
+       safe.  So, we assume here that it's big enough. */
+    if (ret = krb5_c_encrypt_length(context, eblock->key->enctype, size,
+                                   &outlen))
+       return(ret);
+
+    outputd.ciphertext.length = outlen;
+    outputd.ciphertext.data = outptr;
+
+    return(krb5_c_encrypt(context, eblock->key, 0, ivec?&ivecd:0,
+                         &inputd, &outputd));
+}
+
+krb5_error_code krb5_decrypt(context, inptr, outptr, size, eblock, ivec)
+     krb5_context context;
+     krb5_const krb5_pointer inptr;
+     krb5_pointer outptr;
+     krb5_const size_t size;
+     krb5_encrypt_block FAR * eblock;
+     krb5_pointer ivec;
+{
+    krb5_enc_data inputd;
+    krb5_data outputd, ivecd;
+    size_t blocksize;
+    krb5_error_code ret;
+
+    if (ivec) {
+       if (ret = krb5_c_block_size(context, eblock->key->enctype, &blocksize))
+           return(ret);
+
+       ivecd.length = blocksize;
+       ivecd.data = ivec;
+    }
+
+    /* size is the length of the input ciphertext data */
+    inputd.enctype = eblock->key->enctype;
+    inputd.ciphertext.length = size;
+    inputd.ciphertext.data = inptr;
+
+    /* we don't really know how big this is, but the code tends to assume
+       that the output buffer size should be the same as the input
+       buffer size */
+    outputd.length = size;
+    outputd.data = outptr;
+
+    return(krb5_c_decrypt(context, eblock->key, 0, ivec?&ivecd:0,
+                         &inputd, &outputd));
+}
+
+krb5_error_code krb5_process_key(context, eblock, key)
+     krb5_context context;
+     krb5_encrypt_block FAR * eblock;
+     krb5_const krb5_keyblock FAR * key;
+{
+    eblock->key = (krb5_keyblock *) key;
+
+    return(0);
+}
+
+krb5_error_code krb5_finish_key(context, eblock)
+     krb5_context context;
+     krb5_encrypt_block FAR * eblock;
+{
+    return(0);
+}
+
+krb5_error_code krb5_string_to_key(context, eblock, keyblock, data, salt)
+     krb5_context context;
+     krb5_const krb5_encrypt_block FAR * eblock;
+     krb5_keyblock FAR * keyblock;
+     krb5_const krb5_data FAR * data;
+     krb5_const krb5_data FAR * salt;
+{
+    return(krb5_c_string_to_key(context, eblock->crypto_entry, data, salt,
+                               keyblock));
+}
+
+krb5_error_code krb5_init_random_key(context, eblock, keyblock, ptr)
+     krb5_context context;
+     krb5_const krb5_encrypt_block FAR * eblock;
+     krb5_const krb5_keyblock FAR * keyblock;
+     krb5_pointer FAR * ptr;
+{
+    krb5_data data;
+
+    data.length = keyblock->length;
+    data.data = keyblock->contents;
+
+    return(krb5_c_random_seed(context, &data));
+}
+
+krb5_error_code krb5_finish_random_key(context, eblock, ptr)
+     krb5_context context;
+     krb5_const krb5_encrypt_block FAR * eblock;
+     krb5_pointer FAR * ptr;
+{
+    return(0);
+}
+
+krb5_error_code krb5_random_key(context, eblock, ptr, keyblock)
+     krb5_context context;
+     krb5_const krb5_encrypt_block FAR * eblock;
+     krb5_pointer ptr;
+     krb5_keyblock FAR * FAR * keyblock;
+{
+    krb5_keyblock *key;
+    krb5_error_code ret;
+
+    if ((key = (krb5_keyblock *) malloc(sizeof(krb5_keyblock))) == NULL)
+       return(ENOMEM);
+
+    if (ret = krb5_c_make_random_key(context, eblock->crypto_entry, key))
+       free(key);
+
+    *keyblock = key;
+
+    return(ret);
+}
+
+krb5_enctype krb5_eblock_enctype(context, eblock)
+     krb5_context context;
+     krb5_const krb5_encrypt_block FAR * eblock;
+{
+    return(eblock->crypto_entry);
+}
+
+krb5_error_code krb5_use_enctype(context, eblock, enctype)
+     krb5_context context;
+     krb5_encrypt_block FAR * eblock;
+     krb5_const krb5_enctype enctype;
+{
+    eblock->crypto_entry = enctype;
+
+    return(0);
+}
+
+size_t krb5_encrypt_size(length, crypto)
+     size_t length;
+     krb5_enctype crypto;
+{
+    size_t ret;
+
+    if (krb5_c_encrypt_length(/* XXX */ 0, crypto, length, &ret))
+       return(-1); /* XXX */
+
+    return(ret);
+}
+
+size_t krb5_checksum_size(context, ctype)
+     krb5_context context;
+     krb5_cksumtype ctype;
+{
+    size_t ret;
+
+    if (krb5_c_checksum_length(context, ctype, &ret))
+       return(-1); /* XXX */
+
+    return(ret);
+}
+
+krb5_error_code krb5_calculate_checksum(context, ctype, in, in_length,
+                                       seed, seed_length, outcksum)
+     krb5_context context;
+     krb5_const krb5_cksumtype ctype;
+     krb5_const krb5_pointer in;
+     krb5_const size_t in_length;
+     krb5_const krb5_pointer seed;
+     krb5_const size_t seed_length;
+     krb5_checksum FAR * outcksum;
+{
+    krb5_data input;
+    krb5_keyblock key;
+    krb5_error_code ret;
+    krb5_checksum cksum;
+
+    input.data = in;
+    input.length = in_length;
+
+    key.length = seed_length;
+    key.contents = seed;
+
+    if (ret = krb5_c_make_checksum(context, ctype, &key, 0, &input, &cksum))
+       return(ret);
+
+    if (outcksum->length < cksum.length) {
+       memset(cksum.contents, 0, cksum.length);
+       free(cksum.contents);
+       return(KRB5_BAD_MSIZE);
+    }
+
+    outcksum->magic = cksum.magic;
+    outcksum->checksum_type = cksum.checksum_type;
+    memcpy(outcksum->contents, cksum.contents, cksum.length);
+    outcksum->length = cksum.length;
+
+    free(cksum.contents);
+    
+    return(0);
+}
+
+krb5_error_code krb5_verify_checksum(context, ctype, cksum, in, in_length,
+                                    seed, seed_length)
+     krb5_context context;
+     krb5_cksumtype ctype;
+     krb5_const krb5_checksum FAR * cksum;
+     krb5_const krb5_pointer in;
+     krb5_const size_t in_length;
+     krb5_const krb5_pointer seed;
+     krb5_const size_t seed_length;
+{
+    krb5_data input;
+    krb5_keyblock key;
+    krb5_error_code ret;
+    krb5_boolean valid;
+
+    input.data = in;
+    input.length = in_length;
+
+    key.length = seed_length;
+    key.contents = seed;
+
+    if (ret = krb5_c_verify_checksum(context, &key, 0, &input, cksum,
+                                    &valid))
+       return(ret);
+
+    if (!valid)
+       return(KRB5KRB_AP_ERR_BAD_INTEGRITY);
+
+    return(0);
+}
+
+krb5_error_code krb5_random_confounder(size, ptr)
+     size_t size;
+     krb5_pointer ptr;
+{
+    krb5_data random;
+
+    random.length = size;
+    random.data = ptr;
+
+    return(krb5_c_random_make_octets(/* XXX */ 0, &random));
+}
+
+krb5_error_code krb5_encrypt_data(context, key, ivec, data, enc_data)
+     krb5_context context;
+     krb5_keyblock *key;
+     krb5_pointer ivec;
+     krb5_data *data;
+     krb5_enc_data *enc_data;
+{
+    krb5_error_code ret;
+    size_t enclen, blocksize;
+    krb5_data ivecd;
+
+    if (ret = krb5_c_encrypt_length(context, key->enctype, data->length,
+                                   &enclen))
+       return(ret);
+
+    if (ivec) {
+       if (ret = krb5_c_block_size(context, key->enctype, &blocksize))
+           return(ret);
+
+       ivecd.length = blocksize;
+       ivecd.data = ivec;
+    }
+
+    enc_data->magic = KV5M_ENC_DATA;
+    enc_data->kvno = 0;
+    enc_data->enctype = key->enctype;
+    enc_data->ciphertext.length = enclen;
+    if ((enc_data->ciphertext.data = malloc(enclen)) == NULL)
+       return(ENOMEM);
+
+    if (ret = krb5_c_encrypt(context, key, 0, ivec?&ivecd:0, data, enc_data))
+       free(enc_data->ciphertext.data);
+
+    return(ret);
+}
+
+krb5_error_code krb5_decrypt_data(context, key, ivec, enc_data, data)
+     krb5_context context;
+     krb5_keyblock *key;
+     krb5_pointer ivec;
+     krb5_enc_data *enc_data;
+     krb5_data *data;
+{
+    krb5_error_code ret;
+    krb5_data ivecd;
+    size_t blocksize;
+
+    if (ivec) {
+       if (ret = krb5_c_block_size(context, key->enctype, &blocksize))
+           return(ret);
+
+       ivecd.length = blocksize;
+       ivecd.data = ivec;
+    }
+
+    data->length = enc_data->ciphertext.length;
+    if ((data->data = (krb5_octet *) malloc(data->length)) == NULL)
+       return(ENOMEM);
+
+    if (ret = krb5_c_decrypt(context, key, 0, ivec?&ivecd:0, enc_data, data))
+       free(data->data);
+
+    return(0);
+}
diff --git a/src/lib/crypto/os/.Sanitize b/src/lib/crypto/os/.Sanitize
deleted file mode 100644 (file)
index 2e24ee6..0000000
+++ /dev/null
@@ -1,39 +0,0 @@
-# Sanitize.in for Kerberos V5
-
-# Each directory to survive it's way into a release will need a file
-# like this one called "./.Sanitize".  All keyword lines must exist,
-# and must exist in the order specified by this file.  Each directory
-# in the tree will be processed, top down, in the following order.
-
-# Hash started lines like this one are comments and will be deleted
-# before anything else is done.  Blank lines will also be squashed
-# out.
-
-# The lines between the "Do-first:" line and the "Things-to-keep:"
-# line are executed as a /bin/sh shell script before anything else is
-# done in this 
-
-Do-first:
-
-# All files listed between the "Things-to-keep:" line and the
-# "Files-to-sed:" line will be kept.  All other files will be removed.
-# Directories listed in this section will have their own Sanitize
-# called.  Directories not listed will be removed in their entirety
-# with rm -rf.
-
-Things-to-keep:
-
-.cvsignore
-ChangeLog
-Makefile.in
-configure
-configure.in
-c_localaddr.c
-c_ustime.c
-rnd_confoun.c
-
-Things-to-lose:
-
-Do-last:
-
-# End of file.
diff --git a/src/lib/crypto/os/ChangeLog b/src/lib/crypto/os/ChangeLog
deleted file mode 100644 (file)
index ebcb593..0000000
+++ /dev/null
@@ -1,204 +0,0 @@
-Wed Feb 18 16:08:30 1998  Tom Yu  <tlyu@mit.edu>
-
-       * Makefile.in: Remove trailing slash from thisconfigdir.  Fix up
-       BUILDTOP for new conventions.
-
-Fri Feb 13 15:20:54 1998  Theodore Ts'o  <tytso@rsts-11.mit.edu>
-
-       * Makefile.in (thisconfigdir), configure.in: Point the
-               configuration directory at our parent, and remove our
-               local configure.in
-
-Mon Feb  2 17:02:29 1998  Theodore Ts'o  <tytso@rsts-11.mit.edu>
-
-       * Makefile.in: Define BUILDTOP and thisconfigdir in the Makefile
-
-Fri Nov 28 21:23:42 1997  Tom Yu  <tlyu@mit.edu>
-
-       * configure.in: Add AC_PROG_LN_S to deal with symlinking in
-       memmove.c.  This is a kludge, as we really should have a more sane
-       way to deal with missing posix functions.
-
-Thu Sep 25 21:53:11 1997  Tom Yu  <tlyu@mit.edu>
-
-       * c_localaddr.c: Replace KRB5_USE_INET with something more sane.
-
-Tue Aug 12 09:09:14 1997  Ezra Peisach  <epeisach@mit.edu>
-
-       * Makefile.in (SRCS): Add $(srcdir) as needed.
-
-Fri Jul  4 00:13:02 1997  Theodore Y. Ts'o  <tytso@mit.edu>
-
-       * c_localaddr.c (local_addr_fallback_kludge): Added Winsock
-               kludge for finding your local IP address.  May not work
-               for all stacks, so we use it as a fallback.
-       
-Sat Feb 22 18:54:53 1997  Richard Basch  <basch@lehman.com>
-
-       * Makefile.in: Use some of the new library list build rules in
-               win-post.in
-
-Mon Feb 17 17:24:41 1997  Richard Basch  <basch@lehman.com>
-
-       * c_ustime.c: Fixed microsecond adjustment code (win32)
-
-Thu Nov 21 00:58:04 EST 1996    Richard Basch   <basch@lehman.com>
-
-        * Makefile.in: Win32 build
-
-       * c_ustime.c: The Win32 time calculation is different from DOS'
-               so the DOS version shouldn't be trying to use the same
-               part of the ifdef.
-
-       * rnd_confoun.c: Fix function declaration (win32)
-
-Sun Dec 29 21:54:42 1996  Tom Yu  <tlyu@mit.edu>
-
-       * Makefile.in:
-       * configure.in: Update to use new library building procedure.
-
-Wed Jun 12 00:12:52 1996  Theodore Ts'o  <tytso@rsts-11.mit.edu>
-
-       * c_ustime.c: Fix WIN32 to be _WIN32
-
-       * c_localaddr.c: Add #ifdef _WIN32 in places where we had #ifdef _MSDOS
-       
-
-Sat Feb 24 00:34:15 1996  Theodore Y. Ts'o  <tytso@dcl>
-
-       * c_ustime.c (krb5_crypto_us_timeofday): Add Windows 95/NT time
-               function.  (Does this time function work under Windows?
-               We'll find out....)
-
-Thu Feb 15 10:57:27 1996  Ezra Peisach  <epeisach@kangaroo.mit.edu>
-
-       * c_localaddr.c: Set magic number in krb5_address.
-
-Fri Oct  6 22:00:48 1995  Theodore Y. Ts'o  <tytso@dcl>
-
-       * Makefile.in: Remove ##DOS!include of config/windows.in.
-               config/windows.in is now included by wconfig.
-
-Mon Sep 25 16:49:15 1995  Theodore Y. Ts'o  <tytso@dcl>
-
-       * Makefile.in: Removed "foo:: foo-$(WHAT)" lines from the
-               Makefile. 
-
-Fri Sep 22 12:00:00 1995  James Mattly  <mattly@fusion.com>
-
-       * c_localaddr.c:  change close on a socket to closesocket, sockets on
-               macintosh arn't files
-
-Wed Sep 13 10:33:53 1995 Keith Vetter (keithv@fusion.com)
-
-       * Makefile.in: PC builds all C files because of function name changes.
-       * c_localtime.c, c_ustime.c: removed INTERFACE keyword.
-
-Wed Sep 13 17:32:36 1995  Theodore Y. Ts'o  <tytso@dcl>
-
-       * c_localaddr.c (krb5_crypto_os_localaddr): Clear the buffer
-               before calling the SIOCGIFCONF ioctl.  This makes purify
-               happy.
-
-Thu Sep  7 12:00:00 1995  James Mattly <mattly@fusion.com>
-       
-       * Renamed ustime.c to c_ustime.c
-       * Renamed localaddr.c to c_localaddr.c because Mac can't have
-         two files with the same name.
-       * Makefile.in, .Sanitize updated for the above change.
-
-Thu Aug 24 18:40:48 1995  Theodore Y. Ts'o  <tytso@dcl>
-
-       * .Sanitize: Update file list
-
-Sat Jul 29 03:17:21 1995  Tom Yu  <tlyu@lothlorien.MIT.EDU>
-
-       * localaddr.c (krb5_crypto_os_localaddr): Don't bash the return
-               from SIOCGIFCONF with the output of a SIOCGIFFLAGS.  Duh.
-
-Wed Jul 19 17:17:54 1995  Tom Yu  <tlyu@lothlorien.MIT.EDU>
-
-       * localaddr.c: also add definition of max if it's not there.
-
-       * localaddr.c: fix definition of ifreq_size so it actually works
-
-Mon Jul 17 16:04:00 1995  Sam Hartman  <hartmans@tertius.mit.edu>
-
-       * localaddr.c (krb5_crypto_os_localaddr): Deal with variable sized
-        ifreq structures if sockaddr contains sa_len field.
-
-       * configure.in: Check to see if struct sockaddr has sa_len.
-
-Thu Jul  6 17:13:11 1995  Tom Yu  <tlyu@lothlorien.MIT.EDU>
-
-       * localaddr.c: migrated from lib/krb5/os
-
-       * ustime.c: migrated from lib/krb5/os; removed context variable
-               from arglist.
-
-       * Makefile.in: don't copy or remove localaddr.c and ustime.c;
-               they're local now.
-
-Fri Jun  9 19:18:41 1995    <tytso@rsx-11.mit.edu>
-
-       * configure.in: Remove standardized set of autoconf macros, which
-               are now handled by CONFIG_RULES.
-
-Thu May 25 22:16:35 1995  Theodore Y. Ts'o  (tytso@dcl)
-
-       * configure.in, Makefile.in: Add support for shared libraries.
-
-Thu Apr 13 15:49:16 1995 Keith Vetter (keithv@fusion.com)
-
-       * *.[ch]: removed unneeded INTERFACE from non-api functions.
-
-Sat Mar 25 15:38:23 1995  Mark Eichin  <eichin@cygnus.com>
-
-       * Makefile.in (memmove.c): memmove.c is in krb5/posix, not krb5/os.
-
-Wed Mar 22 11:44:07 1995    <tytso@rsx-11.mit.edu>
-
-       * Makefile.in: Use $(SRCTOP) instead of $(srcdir), since Mac's
-               don't like dealing with $(U)$(U).
-
-Fri Mar 17 16:21:46 1995  Theodore Y. Ts'o  (tytso@dcl)
-
-       * Makefile.in: Fix rules for localdr.c, ustime.c, and memmove.c so
-               that they reference $(srcdir) where appropriate.
-
-Thu Mar 16 21:24:43 1995  John Gilmore  (gnu at toad.com)
-
-       * Makefile.in (LDFLAGS):  Eliminate, comes in from pre.in.
-       (all-mac):  Add.
-       (localaddr.c, ustime.c, memmove.c):  Fix paths to work on Mac.
-
-Tue Mar 14 17:23:02 1995 Keith Vetter (keithv@fusion.com)
-
-       * Makefile.in: no longer need to bring in ustime and localaddr for
-          windows since everything's going into one DLL in the end.
-
-Thu Mar 2 17:56:48 1995 Keith Vetter (keithv@fusion.com)
-
-       * Makefile.in: changed LIBNAME for the PC, and  brought in ustime
-           and localaddr from the krb/os directory.
-        * rnd_conf.c: added cast to the seed assignment.
-
-Mon Feb 20 16:25:36 1995 Keith Vetter (keithv@fusion.com)
-
-       * Makfile.in: made to work for the PC
-        * rnd_confoun.c: added windows INTERFACE keyword
-
-Wed Jan 25 20:24:35 1995  John Gilmore  (gnu at toad.com)
-
-       * rnd_confoun.c: Replace <.../...> includes with "..."s.
-
-Mon Oct 24 14:58:14 1994    (tytso@rsx-11)
-
-       * configure.in:
-       * rnd_confoun.c (krb5_random_confounder): Use the srand48/lrand48
-               functions if available.
-
-Fri Oct 14 00:21:05 1994  Theodore Y. Ts'o  (tytso@dcl)
-
-       * Makefile.in: Remove symlinked files on make clean.
-
diff --git a/src/lib/crypto/os/Makefile.in b/src/lib/crypto/os/Makefile.in
deleted file mode 100644 (file)
index d4c5f41..0000000
+++ /dev/null
@@ -1,28 +0,0 @@
-thisconfigdir=./..
-BUILDTOP=$(REL)$(U)$(S)$(U)$(S)$(U)
-CFLAGS = $(CCOPTS) $(DEFS)
-
-##DOS##BUILDTOP = ..\..\..
-##DOS##PREFIXDIR=os
-##DOS##OBJFILE=..\os.lst
-##WIN16##LIBNAME=..\crypto.lib
-
-STLIBOBJS = rnd_confoun.o c_localaddr.o c_ustime.o @LIBOBJS@
-
-COBJS= rnd_confoun.$(OBJEXT) c_localaddr.$(OBJEXT) c_ustime.$(OBJEXT) 
-OBJS= $(COBJS) $(LIBOBJS)
-
-SRCS=  $(srcdir)/rnd_confoun.c $(srcdir)/c_localaddr.c $(srcdir)/c_ustime.c
-
-##DOS##LIBOBJS = $(COBJS)
-
-all-unix:: all-libobjs
-
-memmove.c: $(SRCTOP)$(S)lib$(S)krb5$(S)posix$(S)memmove.c
-       -$(LN) $(SRCTOP)$(S)lib$(S)krb5$(S)posix$(S)memmove.c $@
-
-memmove.o: memmove.c
-
-clean-unix:: clean-libobjs
-clean:: 
-       $(RM) memmove.c
diff --git a/src/lib/crypto/os/c_localaddr.c b/src/lib/crypto/os/c_localaddr.c
deleted file mode 100644 (file)
index 3b3bcb4..0000000
+++ /dev/null
@@ -1,348 +0,0 @@
-/*
- * lib/crypto/os/c_localaddr.c
- *
- * Copyright 1990,1991 by the Massachusetts Institute of Technology.
- * All Rights Reserved.
- *
- * Export of this software from the United States of America may
- *   require a specific license from the United States Government.
- *   It is the responsibility of any person or organization contemplating
- *   export to obtain such a license before exporting.
- * 
- * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
- * distribute this software and its documentation for any purpose and
- * without fee is hereby granted, provided that the above copyright
- * notice appear in all copies and that both that copyright notice and
- * this permission notice appear in supporting documentation, and that
- * the name of M.I.T. not be used in advertising or publicity pertaining
- * to distribution of the software without specific, written prior
- * permission.  M.I.T. makes no representations about the suitability of
- * this software for any purpose.  It is provided "as is" without express
- * or implied warranty.
- * 
- *
- * Return the protocol addresses supported by this host.
- *
- * XNS support is untested, but "Should just work".
- */
-
-
-#define NEED_SOCKETS
-#include "k5-int.h"
-
-#if !defined(HAVE_MACSOCK_H) && !defined(_MSDOS) && !defined(_WIN32)
-
-/* needed for solaris, harmless elsewhere... */
-#define BSD_COMP
-#include <sys/ioctl.h>
-#include <sys/time.h>
-#include <errno.h>
-
-/*
- * The SIOCGIF* ioctls require a socket.
- * It doesn't matter *what* kind of socket they use, but it has to be
- * a socket.
- *
- * Of course, you can't just ask the kernel for a socket of arbitrary
- * type; you have to ask for one with a valid type.
- *
- */
-#ifdef HAVE_NETINET_IN_H
-
-#include <netinet/in.h>
-
-#ifndef USE_AF
-#define USE_AF AF_INET
-#define USE_TYPE SOCK_DGRAM
-#define USE_PROTO 0
-#endif
-
-#endif
-
-#ifdef KRB5_USE_NS
-
-#include <netns/ns.h>
-
-#ifndef USE_AF
-#define USE_AF AF_NS
-#define USE_TYPE SOCK_DGRAM
-#define USE_PROTO 0            /* guess */
-#endif
-
-#endif
-/*
- * Add more address families here.
- */
-
-/*
- * BSD 4.4 defines the size of an ifreq to be
- * max(sizeof(ifreq), sizeof(ifreq.ifr_name)+ifreq.ifr_addr.sa_len
- * However, under earlier systems, sa_len isn't present, so the size is 
- * just sizeof(struct ifreq)
- */
-#ifdef HAVE_SA_LEN
-#ifndef max
-#define max(a,b) ((a) > (b) ? (a) : (b))
-#endif
-#define ifreq_size(i) max(sizeof(struct ifreq),\
-     sizeof((i).ifr_name)+(i).ifr_addr.sa_len)
-#else
-#define ifreq_size(i) sizeof(struct ifreq)
-#endif /* HAVE_SA_LEN*/
-
-
-
-extern int errno;
-
-/*
- * Return all the protocol addresses of this host.
- *
- * We could kludge up something to return all addresses, assuming that
- * they're valid kerberos protocol addresses, but we wouldn't know the
- * real size of the sockaddr or know which part of it was actually the
- * host part.
- *
- * This uses the SIOCGIFCONF, SIOCGIFFLAGS, and SIOCGIFADDR ioctl's.
- */
-
-krb5_error_code
-krb5_crypto_os_localaddr(addr)
-    krb5_address ***addr;
-{
-    struct ifreq *ifr, ifreq;
-    struct ifconf ifc;
-    int s, code, n, i;
-    char buf[1024];
-    krb5_address *addr_temp [ 1024/sizeof(struct ifreq) ];
-    int n_found;
-    int mem_err = 0;
-    
-    memset(buf, 0, sizeof(buf));
-    ifc.ifc_len = sizeof(buf);
-    ifc.ifc_buf = buf;
-    
-    s = socket (USE_AF, USE_TYPE, USE_PROTO);
-    if (s < 0)
-       return errno;
-
-    code = ioctl (s, SIOCGIFCONF, (char *)&ifc);
-    if (code < 0) {
-       int retval = errno;
-       closesocket (s);
-       return retval;
-    }
-    n = ifc.ifc_len;
-    
-n_found = 0;
-    for (i = 0; i < n; i+= ifreq_size(*ifr) ) {
-       krb5_address *address;
-       ifr = (struct ifreq *)((caddr_t) ifc.ifc_buf+i);
-
-       strncpy(ifreq.ifr_name, ifr->ifr_name, sizeof (ifreq.ifr_name));
-       if (ioctl (s, SIOCGIFFLAGS, (char *)&ifreq) < 0)
-           continue;
-
-#ifdef IFF_LOOPBACK
-       if (ifreq.ifr_flags & IFF_LOOPBACK) 
-           continue;
-#endif
-
-       if (!(ifreq.ifr_flags & IFF_UP)) 
-           /* interface is down; skip */
-           continue;
-
-       /* ifr->ifr_addr has what we want! */
-       switch (ifr->ifr_addr.sa_family) {
-#ifdef HAVE_NETINET_IN_H
-       case AF_INET:
-           {
-               struct sockaddr_in *in =
-                   (struct sockaddr_in *)&ifr->ifr_addr;
-               
-               address = (krb5_address *)
-                   malloc (sizeof(krb5_address));
-               if (address) {
-                   address->magic = KV5M_ADDRESS;
-                   address->addrtype = ADDRTYPE_INET;
-                   address->length = sizeof(struct in_addr);
-                   address->contents = (unsigned char *)malloc(address->length);
-                   if (!address->contents) {
-                       krb5_xfree(address);
-                       address = 0;
-                       mem_err++;
-                   } else {
-                       memcpy ((char *)address->contents,
-                               (char *)&in->sin_addr, 
-                               address->length);
-                       break;
-                   }
-               } else mem_err++;
-           }
-#endif
-#ifdef KRB5_USE_NS
-           case AF_XNS:
-           {  
-               struct sockaddr_ns *ns =
-                   (struct sockaddr_ns *)&ifr->ifr_addr;
-               address = (krb5_address *)
-                   malloc (sizeof (krb5_address) + sizeof (struct ns_addr));
-               if (address) {
-                   address->magic = KV5M_ADDRESS;
-                   address->addrtype = ADDRTYPE_XNS; 
-
-                   /* XXX should we perhaps use ns_host instead? */
-
-                   address->length = sizeof(struct ns_addr);
-                   address->contents = (unsigned char *)malloc(address->length);
-                   if (!address->contents) {
-                       krb5_xfree(address);
-                       address = 0;
-                       mem_err++;
-                   } else {
-                       memcpy ((char *)address->contents,
-                               (char *)&ns->sns_addr,
-                               address->length);
-                       break;
-                   }
-               } else mem_err++;
-               break;
-           }
-#endif
-       /*
-        * Add more address families here..
-        */
-       default:
-           continue;
-       }
-       if (address)
-           addr_temp[n_found++] = address;
-       address = 0;
-    }
-    closesocket(s);
-
-    *addr = (krb5_address **)malloc (sizeof (krb5_address *) * (n_found+1));
-    if (*addr == 0)
-       mem_err++;
-    
-    if (mem_err) {
-       for (i=0; i<n_found; i++) {
-           krb5_xfree(addr_temp[i]);
-           addr_temp[i] = 0;
-       }
-       return ENOMEM;
-    }
-    
-    for (i=0; i<n_found; i++) {
-       (*addr)[i] = addr_temp[i];
-    }
-    (*addr)[n_found] = 0;
-    return 0;
-}
-
-#else /* Windows/Mac version */
-
-/*
- * Hold on to your lunch!  Backup kludge method of obtaining your
- * local IP address, courtesy of Windows Socket Network Programming,
- * by Robert Quinn
- */
-#if defined(_MSDOS) || defined(_WIN32)
-static struct hostent *local_addr_fallback_kludge()
-{
-       static struct hostent   host;
-       static SOCKADDR_IN      addr;
-       static char *           ip_ptrs[2];
-       SOCKET                  sock;
-       int                     size = sizeof(SOCKADDR);
-       int                     err;
-
-       sock = socket(AF_INET, SOCK_DGRAM, 0);
-       if (sock == INVALID_SOCKET)
-               return NULL;
-
-       /* connect to arbitrary port and address (NOT loopback) */
-       addr.sin_family = AF_INET;
-       addr.sin_port = htons(IPPORT_ECHO);
-       addr.sin_addr.s_addr = inet_addr("204.137.220.51");
-
-       err = connect(sock, (LPSOCKADDR) &addr, sizeof(SOCKADDR));
-       if (err == SOCKET_ERROR)
-               return NULL;
-
-       err = getsockname(sock, (LPSOCKADDR) &addr, (int FAR *) size);
-       if (err == SOCKET_ERROR)
-               return NULL;
-
-       closesocket(sock);
-
-       host.h_name = 0;
-       host.h_aliases = 0;
-       host.h_addrtype = AF_INET;
-       host.h_length = 4;
-       host.h_addr_list = ip_ptrs;
-       ip_ptrs[0] = (char *) &addr.sin_addr.s_addr;
-       ip_ptrs[1] = NULL;
-
-       return &host;
-}
-#endif
-
-/* No ioctls in winsock so we just assume there is only one networking 
- * card per machine, so gethostent is good enough. 
- */
-krb5_error_code
-krb5_crypto_os_localaddr (krb5_address ***addr) {
-    char host[64];                              /* Name of local machine */
-    struct hostent *hostrec;
-    int err;
-
-    *addr = calloc (2, sizeof (krb5_address *));
-    if (*addr == NULL)
-        return ENOMEM;
-
-#ifdef HAVE_MACSOCK_H
-    hostrec = getmyipaddr();
-#else /* HAVE_MACSOCK_H */
-    err = 0;
-    
-    if (gethostname (host, sizeof(host))) {
-        err = WSAGetLastError();
-    }
-
-    if (!err) {
-           hostrec = gethostbyname (host);
-           if (hostrec == NULL) {
-                   err = WSAGetLastError();
-           }
-    }
-
-    if (err) {
-           hostrec = local_addr_fallback_kludge();
-           if (!hostrec)
-                   return err;
-    }
-#endif /* HAVE_MACSOCK_H */
-
-    (*addr)[0] = calloc (1, sizeof(krb5_address));
-    if ((*addr)[0] == NULL) {
-        free (*addr);
-        return ENOMEM;
-    }
-    (*addr)[0]->magic = KV5M_ADDRESS;
-    (*addr)[0]->addrtype = hostrec->h_addrtype;
-    (*addr)[0]->length = hostrec->h_length;
-    (*addr)[0]->contents = (unsigned char *)malloc((*addr)[0]->length);
-    if (!(*addr)[0]->contents) {
-        free((*addr)[0]);
-        free(*addr);
-        return ENOMEM;
-    } else {
-        memcpy ((*addr)[0]->contents,
-                hostrec->h_addr,
-                (*addr)[0]->length);
-    }
-       /* FIXME, deal with the case where gethostent returns multiple addrs */
-
-    return(0);
-}
-#endif
diff --git a/src/lib/crypto/os/rnd_confoun.c b/src/lib/crypto/os/rnd_confoun.c
deleted file mode 100644 (file)
index e904cb5..0000000
+++ /dev/null
@@ -1,98 +0,0 @@
-/*
- * lib/crypto/os/rnd_confoun.c
- *
- * Copyright 1990 by the Massachusetts Institute of Technology.
- * All Rights Reserved.
- *
- * Export of this software from the United States of America may
- *   require a specific license from the United States Government.
- *   It is the responsibility of any person or organization contemplating
- *   export to obtain such a license before exporting.
- * 
- * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
- * distribute this software and its documentation for any purpose and
- * without fee is hereby granted, provided that the above copyright
- * notice appear in all copies and that both that copyright notice and
- * this permission notice appear in supporting documentation, and that
- * the name of M.I.T. not be used in advertising or publicity pertaining
- * to distribution of the software without specific, written prior
- * permission.  M.I.T. makes no representations about the suitability of
- * this software for any purpose.  It is provided "as is" without express
- * or implied warranty.
- * 
- *
- * krb5_random_confounder()
- */
-
-#include "k5-int.h"
-
-#ifdef HAVE_SYS_TIME_H
-#include <sys/time.h>
-#ifdef TIME_WITH_SYS_TIME
-#include <time.h>
-#endif
-#else
-#include <time.h>
-#endif
-
-#ifdef HAVE_SRAND48
-#define SRAND  srand48
-#define RAND   lrand48
-#define RAND_TYPE      long
-#endif
-
-#if !defined(RAND_TYPE) && defined(HAVE_SRAND)
-#define SRAND  srand
-#define RAND   rand
-#define RAND_TYPE      int
-#endif
-
-#if !defined(RAND_TYPE) && defined(HAVE_SRANDOM)       
-#define SRAND  srandom
-#define RAND   random
-#define RAND_TYPE      long
-#endif
-
-#if !defined(RAND_TYPE)
-You need a random number generator!
-#endif
-
-/*
- * Generate a random confounder
- */
-KRB5_DLLIMP krb5_error_code KRB5_CALLCONV
-krb5_random_confounder(size, fillin)
-size_t size;
-krb5_pointer fillin;
-{
-    static int seeded = 0;
-    register krb5_octet *real_fill;
-    RAND_TYPE  rval;
-
-    if (!seeded) {
-       /* time() defined in 4.12.2.4, but returns a time_t, which is an
-          "arithmetic type" (4.12.1) */
-       rval = (RAND_TYPE) time(0);
-       SRAND(rval);
-#ifdef HAVE_GETPID
-       rval = RAND();
-       rval ^= getpid();
-       SRAND(rval);
-#endif
-       seeded = 1;
-    }
-
-    real_fill = (krb5_octet *)fillin;
-    while (size > 0) {
-       rval = RAND();
-       *real_fill = rval & 0xff;
-       real_fill++;
-       size--;
-       if (size) {
-           *real_fill = (rval >> 8) & 0xff;
-           real_fill++;
-           size--;
-       }
-    }
-    return 0;
-}
diff --git a/src/lib/crypto/prng.c b/src/lib/crypto/prng.c
new file mode 100644 (file)
index 0000000..2d4f664
--- /dev/null
@@ -0,0 +1,155 @@
+/*
+ * Copyright (C) 1998 by the FundsXpress, INC.
+ * 
+ * All rights reserved.
+ * 
+ * Export of this software from the United States of America may require
+ * a specific license from the United States Government.  It is the
+ * responsibility of any person or organization contemplating export to
+ * obtain such a license before exporting.
+ * 
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of FundsXpress. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  FundsXpress makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#include "k5-int.h"
+#include "enc_provider.h"
+
+/* This random number generator is a feedback generator based on a
+   block cipher.  It uses DES by default, since it guaranteed to be
+   present in the system, but can be changed.  As new seed data comes
+   in, the old state is folded with the new seed into new state.  Each
+   time random bytes are requested, the seed is used as a key and
+   cblock, and the encryption is used as the output.  The output is
+   fed back as new seed data, as described above. */
+
+/* this can be replaced with another encryption provider, since
+   everything below uses it abstractly */
+
+struct krb5_enc_provider *enc = &krb5_enc_des;
+
+/* XXX state.  Should it be in krb5_context? */
+
+static int inited = 0;
+static size_t blocksize, keybytes, keylength;
+static int random_count;
+/* keybytes | state-block | encblock | key | new-keybytes | new-state-block */
+static unsigned char *random_state; 
+#define STATE (random_state)
+#define STATEKEY (STATE)
+#define STATEBLOCK (STATEKEY+keybytes)
+#define STATESIZE (keybytes+blocksize)
+#define OUTPUT (STATE)
+#define OUTPUTSIZE (STATESIZE+blocksize)
+#define RANDBLOCK (STATEBLOCK+blocksize)
+#define KEYCONTENTS (RANDBLOCK+blocksize)
+#define NEWSTATE (KEYCONTENTS+keylength)
+#define ALLSTATESIZE (keybytes+blocksize*2+keylength+keybytes+blocksize)
+
+krb5_error_code
+krb5_c_random_seed(krb5_context context, krb5_data *data)
+{
+    unsigned char *fold_input;
+
+    if (inited == 0) {
+       /* this does a bunch of malloc'ing up front, so that
+          generating random keys doesn't have to malloc, so it can't
+          fail.  seeding still malloc's, but that's less common. */
+
+       enc->block_size(&blocksize);
+       enc->keysize(&keybytes, &keylength);
+       if ((random_state = (unsigned char *) malloc(ALLSTATESIZE)) == NULL)
+           return(ENOMEM);
+       random_count = 0;
+       inited = 1;
+
+       krb5_nfold(data->length*8, data->data, STATESIZE*8, STATE);
+
+       return(0);
+    }
+
+    if ((fold_input =
+        (unsigned char *) malloc(data->length+STATESIZE)) == NULL)
+       return(ENOMEM);
+
+    memcpy(fold_input, data->data, data->length);
+    memcpy(fold_input+data->length, STATE, STATESIZE);
+
+    krb5_nfold((data->length+STATESIZE)*8, fold_input,
+              STATESIZE*8, STATE);
+    free(fold_input);
+    return(0);
+}
+
+krb5_error_code
+krb5_c_random_make_octets(krb5_context context, krb5_data *data)
+{
+    krb5_error_code ret;
+    krb5_data data1, data2;
+    krb5_keyblock key;
+    int bytes;
+
+    if (inited == 0) {
+       /* i need some entropy.  I'd use the current time and pid, but
+          that could cause portability problems. */
+       abort();
+    }
+
+    bytes = 0;
+
+    while (bytes < data->length) {
+       if (random_count == 0) {
+           /* set up random krb5_data, and key to be filled in */
+           data1.length = keybytes;
+           data1.data = STATEKEY;
+           key.length = keylength;
+           key.contents = KEYCONTENTS;
+
+           /* fill it in */
+           if (ret = ((*(enc->make_key))(&data1, &key)))
+               return(ret);
+
+           /* encrypt the block */
+           data1.length = blocksize;
+           data1.data = STATEBLOCK;
+           data2.length = blocksize;
+           data2.data = RANDBLOCK;
+           if (ret = ((*(enc->encrypt))(&key, NULL, &data1, &data2)))
+               return(ret);
+
+           /* fold the new output back into the state */
+
+           krb5_nfold(OUTPUTSIZE*8, OUTPUT, STATESIZE*8, NEWSTATE);
+           memcpy(STATE, NEWSTATE, STATESIZE);
+
+           random_count = blocksize;
+       }
+
+       if ((data->length - bytes) <= random_count) {
+           memcpy(data->data + bytes, RANDBLOCK+(blocksize-random_count),
+                  data->length - bytes);
+           random_count -= (data->length - bytes);
+           break;
+       }
+
+       memcpy(data->data + bytes, RANDBLOCK+(blocksize - random_count),
+              random_count);
+
+       bytes += random_count;
+       random_count = 0;
+    }
+
+    return(0);
+}
diff --git a/src/lib/crypto/raw_des.c b/src/lib/crypto/raw_des.c
deleted file mode 100644 (file)
index 65e0ebd..0000000
+++ /dev/null
@@ -1,100 +0,0 @@
-/*
- * lib/crypto/raw-des.c
- *
- * Copyright 1994, 1995 by the Massachusetts Institute of Technology.
- * All Rights Reserved.
- *
- * Export of this software from the United States of America may
- *   require a specific license from the United States Government.
- *   It is the responsibility of any person or organization contemplating
- *   export to obtain such a license before exporting.
- * 
- * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
- * distribute this software and its documentation for any purpose and
- * without fee is hereby granted, provided that the above copyright
- * notice appear in all copies and that both that copyright notice and
- * this permission notice appear in supporting documentation, and that
- * the name of M.I.T. not be used in advertising or publicity pertaining
- * to distribution of the software without specific, written prior
- * permission.  M.I.T. makes no representations about the suitability of
- * this software for any purpose.  It is provided "as is" without express
- * or implied warranty.
- */
-
-#include "k5-int.h"
-#include "des_int.h"
-
-krb5_error_code mit_raw_des_encrypt_func
-    PROTOTYPE(( krb5_const_pointer, krb5_pointer, const size_t,
-               krb5_encrypt_block *, krb5_pointer ));
-
-krb5_error_code mit_raw_des_decrypt_func
-    PROTOTYPE(( krb5_const_pointer, krb5_pointer, const size_t,
-               krb5_encrypt_block *, krb5_pointer ));
-
-static krb5_cryptosystem_entry mit_raw_des_cryptosystem_entry = {
-    0,
-    mit_raw_des_encrypt_func,
-    mit_raw_des_decrypt_func,
-    mit_des_process_key,
-    mit_des_finish_key,
-    mit_des_string_to_key,
-    mit_des_init_random_key,
-    mit_des_finish_random_key,
-    mit_des_random_key,
-    sizeof(mit_des_cblock),
-    0,
-    sizeof(mit_des_cblock),
-    ENCTYPE_DES_CBC_RAW
-    };
-
-krb5_cs_table_entry krb5_raw_des_cst_entry = {
-    0,
-    &mit_raw_des_cryptosystem_entry,
-    0
-    };
-
-krb5_error_code
-mit_raw_des_decrypt_func(in, out, size, key, ivec)
-    krb5_const_pointer in;
-    krb5_pointer out;
-    const size_t size;
-    krb5_encrypt_block * key;
-    krb5_pointer ivec;
-{
-    return (mit_des_cbc_encrypt ((const mit_des_cblock *) in, 
-                                out, 
-                                size, 
-                                (struct mit_des_ks_struct *)key->priv, 
-                                ivec ? ivec : (krb5_pointer)key->key->contents,
-                                MIT_DES_DECRYPT));
-}
-
-krb5_error_code
-mit_raw_des_encrypt_func(in, out, size, key, ivec)
-    krb5_const_pointer in;
-    krb5_pointer out;
-    const size_t size;
-    krb5_encrypt_block * key;
-    krb5_pointer ivec;
-{
-   int sumsize;
-
-   /* round up to des block size */
-
-   sumsize =  krb5_roundup(size, sizeof(mit_des_cblock));
-
-   /* assemble crypto input into the output area, then encrypt in place. */
-
-   memset((char *)out, 0, sumsize);
-   memcpy((char *)out, (char *)in, size);
-
-    /* We depend here on the ability of this DES implementation to
-       encrypt plaintext to ciphertext in-place. */
-    return (mit_des_cbc_encrypt (out, 
-                                out, 
-                                sumsize, 
-                                (struct mit_des_ks_struct *)key->priv, 
-                                ivec ? ivec : (krb5_pointer)key->key->contents,
-                                MIT_DES_ENCRYPT));
-}
diff --git a/src/lib/crypto/sha/.Sanitize b/src/lib/crypto/sha/.Sanitize
deleted file mode 100644 (file)
index 886bb2b..0000000
+++ /dev/null
@@ -1,42 +0,0 @@
-# Sanitize.in for Kerberos V5
-
-# Each directory to survive it's way into a release will need a file
-# like this one called "./.Sanitize".  All keyword lines must exist,
-# and must exist in the order specified by this file.  Each directory
-# in the tree will be processed, top down, in the following order.
-
-# Hash started lines like this one are comments and will be deleted
-# before anything else is done.  Blank lines will also be squashed
-# out.
-
-# The lines between the "Do-first:" line and the "Things-to-keep:"
-# line are executed as a /bin/sh shell script before anything else is
-# done in this 
-
-Do-first:
-
-# All files listed between the "Things-to-keep:" line and the
-# "Files-to-sed:" line will be kept.  All other files will be removed.
-# Directories listed in this section will have their own Sanitize
-# called.  Directories not listed will be removed in their entirety
-# with rm -rf.
-
-Things-to-keep:
-
-.cvsignore
-ChangeLog
-Makefile.in
-configure
-configure.in
-sha_crypto.c
-sha_glue.c
-shs.c
-shs.h
-hmac_sha.c
-t_shs.c
-
-Things-to-lose:
-
-Do-last:
-
-# End of file.
diff --git a/src/lib/crypto/sha/ChangeLog b/src/lib/crypto/sha/ChangeLog
deleted file mode 100644 (file)
index 19abbbf..0000000
+++ /dev/null
@@ -1,89 +0,0 @@
-Wed Feb 18 16:09:05 1998  Tom Yu  <tlyu@mit.edu>
-
-       * Makefile.in: Remove trailing slash from thisconfigdir.  Fix up
-       BUILDTOP for new conventions.
-
-Fri Feb 13 15:20:54 1998  Theodore Ts'o  <tytso@rsts-11.mit.edu>
-
-       * Makefile.in (thisconfigdir), configure.in: Point the
-               configuration directory at our parent, and remove our
-               local configure.in
-
-Mon Feb  2 17:02:29 1998  Theodore Ts'o  <tytso@rsts-11.mit.edu>
-
-       * Makefile.in: Define BUILDTOP and thisconfigdir in the Makefile
-
-Tue Oct 28 16:37:18 1997  Tom Yu  <tlyu@voltage-multiplier.mit.edu>
-
-       * shs.c, sha_glue.c, hmac_sha.c: Fix to deal with LONG wider than
-       32 bits.
-
-       * t_shs.c: Print out the actual and expected values on error.
-
-Sat Feb 22 18:52:09 1997  Richard Basch  <basch@lehman.com>
-
-       * Makefile.in: Use some of the new library list build rules in
-               win-post.in
-
-Thu Jan 30 21:31:39 1997  Richard Basch  <basch@lehman.com>
-
-       * sha_crypto.c sha_glue.c:
-               Declare the functions to take const args where possible
-               Remove extra includes
-
-       * sha_crypto.c: Function prototypes did not match function names.
-
-Thu Nov 21 00:58:04 EST 1996   Richard Basch   <basch@lehman.com>
-
-       * Makefile.in: Win32 build fixed
-
-Sun Dec 29 21:56:35 1996  Tom Yu  <tlyu@mit.edu>
-
-       * Makefile.in:
-       * configure.in: Update to use new library build procedure.
-
-Wed Aug 28 17:40:53 1996  Theodore Ts'o  <tytso@rsts-11.mit.edu>
-
-       * shs.c: Only include sys/types.h if present.
-
-       * configure.in: Check for sys/types.h
-
-Thu Jun 13 10:54:27 1996  Ezra Peisach  <epeisach@kangaroo.mit.edu>
-
-       * hmac_sha.c: Include string.h for memcpy prototype
-
-Sat Jun  8 07:44:35 1996  Ezra Peisach  (epeisach@mit.edu)
-
-       * shs.c (longReverse): Test for big vs little endian failed for
-               little endian machines.
-
-Thu Jun  6 15:43:26 1996  Theodore Y. Ts'o  <tytso@mit.edu>
-
-       * shs.c (longReverse): Don't use htonl(); it doesn't exist under
-               Windows.  Instead do the test by casting a pointer to an
-               integer to a char *.
-
-Mon May 20 17:15:32 1996  Theodore Y. Ts'o  <tytso@mit.edu>
-
-       * t_shs.c (main): Don't do timing tests; it takes too long!
-
-Tue May 14 17:09:36 1996  Richard Basch  <basch@lehman.com>
-
-       * .Sanitize: reflect current files
-       * Makefile.in: added hmac-sha
-       * hmac_sha.c: implement HMAC-SHA
-       * sha_crypto.c: use hmac-sha
-       * sha_glue.c: sanity check the passed in checksum length
-       * shs.h: replaced sha-des3 with hmac-sha
-
-Fri May 10 11:19:53 1996  Ezra Peisach  <epeisach@kangaroo.mit.edu>
-
-       * shs.c (longReverse): Remove extraneous \.
-               (expand): Start #define in first column.
-
-Fri May 10 01:19:18 1996  Richard Basch  <basch@lehman.com>
-
-       * Makefile.in configure.in t_shs.c sha_glue.c sha_crypto.c shs.c shs.h:
-       Initial check-in of the functions to support the NIST FIPS 180
-       SHA algorithm.  Provide interfaces for cksum-sha, cksum-sha-des3.
-       (enctype-des3-sha is also being defined)
diff --git a/src/lib/crypto/sha/Makefile.in b/src/lib/crypto/sha/Makefile.in
deleted file mode 100644 (file)
index 058ac0d..0000000
+++ /dev/null
@@ -1,43 +0,0 @@
-thisconfigdir=./..
-BUILDTOP=$(REL)$(U)$(S)$(U)$(S)$(U)
-CFLAGS = $(CCOPTS) $(DEFS) -I$(srcdir)/../des
-
-##DOS##BUILDTOP = ..\..\..
-##DOS##PREFIXDIR=sha
-##DOS##OBJFILE=..\sha.lst
-##WIN16##LIBNAME=..\crypto.lib
-
-STLIBOBJS=shs.o hmac_sha.o sha_crypto.o sha_glue.o
-
-OBJS=  shs.$(OBJEXT)           \
-       hmac_sha.$(OBJEXT)      \
-       sha_crypto.$(OBJEXT)    \
-       sha_glue.$(OBJEXT)
-
-SRCS=  $(srcdir)/shs.c         \
-       $(srcdir)/hmac_sha.c    \
-       $(srcdir)/sha_crypto.c  \
-       $(srcdir)/sha_glue.c
-
-
-##DOS##LIBOBJS = $(OBJS)
-
-
-all-unix:: all-libobjs
-
-t_shs: t_shs.o shs.o
-       $(CC) $(CFLAGS) $(LDFLAGS) -o t_shs t_shs.o shs.o
-
-t_shs.exe:
-       $(CC) $(CFLAGS2) -o t_shs.exe t_shs.c shs.c
-
-check-unix:: t_shs
-       $(C)t_shs -x
-
-check-windows:: t_shs$(EXEEXT)
-       $(C)t_shs$(EXEEXT) -x
-
-clean:: 
-       $(RM) t_shs$(EXEEXT) t_shs.$(OBJEXT)
-
-clean-unix:: clean-libobjs
diff --git a/src/lib/crypto/sha/hmac_sha.c b/src/lib/crypto/sha/hmac_sha.c
deleted file mode 100644 (file)
index d57092e..0000000
+++ /dev/null
@@ -1,101 +0,0 @@
-#include <string.h>
-#include "shs.h"
-
-#define PAD_SZ 64
-
-
-krb5_error_code
-hmac_sha(text, text_len, key, key_len, digest)
-    krb5_octet * text;                 /* pointer to data stream */
-    int                text_len;               /* length of data stream */
-    krb5_octet * key;                  /* pointer to authentication key */
-    int                key_len;                /* length of authentication key */
-    krb5_octet * digest;               /* caller digest to be filled in */
-{
-    SHS_INFO context;
-    krb5_octet k_ipad[PAD_SZ]; /* inner padding - key XORd with ipad */
-    krb5_octet k_opad[PAD_SZ]; /* outer padding - key XORd with opad */
-    int i;
-    krb5_octet *cp;
-    LONG *lp;
-    /* sanity check parameters */
-    if (!text || !key || !digest)
-       /* most heinous, probably should log something */
-       return EINVAL;
-
-    /* if key is longer than 64 bytes reset it to key=SHA(key) */
-    if (key_len > sizeof(k_ipad)) {
-       shsInit(&context);
-       shsUpdate(&context, key, key_len);
-       shsFinal(&context);
-
-       cp = digest;
-       lp = context.digest;
-       while (cp < digest + SHS_DIGESTSIZE) {
-           *cp++ = (*lp >> 24) & 0xff;
-           *cp++ = (*lp >> 16) & 0xff;
-           *cp++ = (*lp >> 8) & 0xff;
-           *cp++ = *lp++ & 0xff;
-       }
-       key = digest;
-       key_len = SHS_DIGESTSIZE;
-    }
-    /*
-     * the HMAC_SHA transform looks like:
-     *
-     * SHA(K XOR opad, SHA(K XOR ipad, text))
-     *
-     * where K is an n byte key
-     * ipad is the byte 0x36 repeated 64 times
-     * opad is the byte 0x5c repeated 64 times
-     * and text is the data being protected
-     */
-    /* start out by storing key in pads */
-    memset(k_ipad, 0x36, sizeof(k_ipad));
-    memset(k_opad, 0x5c, sizeof(k_opad));
-
-    /* XOR key with ipad and opad values */
-    for (i = 0; i < key_len; i++) {
-       k_ipad[i] ^= key[i];
-       k_opad[i] ^= key[i];
-    }
-
-    /*
-     * perform inner SHA
-     */
-    shsInit(&context);
-    shsUpdate(&context, k_ipad, sizeof(k_ipad));
-    shsUpdate(&context, text, text_len);
-    shsFinal(&context);
-
-    cp = digest;
-    lp = context.digest;
-    while (cp < digest + SHS_DIGESTSIZE) {
-       *cp++ = (*lp >> 24) & 0xff;
-       *cp++ = (*lp >> 16) & 0xff;
-       *cp++ = (*lp >> 8) & 0xff;
-       *cp++ = *lp++ & 0xff;
-    }
-    
-    /*
-     * perform outer SHA
-     */
-    shsInit(&context);
-    shsUpdate(&context, k_opad, sizeof(k_opad));
-    shsUpdate(&context, digest, SHS_DIGESTSIZE);
-    shsFinal(&context);
-
-    cp = digest;
-    lp = context.digest;
-    while (cp < digest + SHS_DIGESTSIZE) {
-       *cp++ = (*lp >> 24) & 0xff;
-       *cp++ = (*lp >> 16) & 0xff;
-       *cp++ = (*lp >> 8) & 0xff;
-       *cp++ = *lp++ & 0xff;
-    }
-
-    return 0;
-}
diff --git a/src/lib/crypto/sha/sha_crypto.c b/src/lib/crypto/sha/sha_crypto.c
deleted file mode 100644 (file)
index b539b11..0000000
+++ /dev/null
@@ -1,76 +0,0 @@
-#include "shs.h"
-
-/* Windows needs to these prototypes for the assignment below */
-
-static krb5_error_code
-krb5_sha_crypto_sum_func
-       PROTOTYPE((krb5_const krb5_pointer in,
-                  krb5_const size_t in_length,
-                  krb5_const krb5_pointer seed,
-                  krb5_const size_t seed_length,
-                  krb5_checksum FAR *outcksum));
-
-static krb5_error_code
-krb5_sha_crypto_verify_func
-       PROTOTYPE((krb5_const krb5_checksum FAR *cksum,
-                  krb5_const krb5_pointer in,
-                  krb5_const size_t in_length,
-                  krb5_const krb5_pointer seed,
-                  krb5_const size_t seed_length));
-
-static krb5_error_code
-krb5_sha_crypto_sum_func(in, in_length, seed, seed_length, outcksum)
-    krb5_const krb5_pointer in;
-    krb5_const size_t in_length;
-    krb5_const krb5_pointer seed;
-    krb5_const size_t seed_length;
-    krb5_checksum FAR *outcksum;
-{
-    krb5_error_code retval;
-
-    if (outcksum->length < HMAC_SHA_CKSUM_LENGTH)
-       return KRB5_BAD_MSIZE;
-
-    outcksum->checksum_type = CKSUMTYPE_HMAC_SHA;
-    outcksum->length = HMAC_SHA_CKSUM_LENGTH;
-
-    retval = hmac_sha(in, in_length, seed, seed_length, outcksum->contents);
-    return retval;
-}
-
-static krb5_error_code
-krb5_sha_crypto_verify_func(cksum, in, in_length, seed, seed_length)
-    krb5_const krb5_checksum FAR *cksum;
-    krb5_const krb5_pointer in;
-    krb5_const size_t in_length;
-    krb5_const krb5_pointer seed;
-    krb5_const size_t seed_length;
-{
-    krb5_octet digest[HMAC_SHA_CKSUM_LENGTH];
-    krb5_error_code retval;
-
-    if (cksum->checksum_type != CKSUMTYPE_HMAC_SHA)
-       return KRB5KRB_AP_ERR_INAPP_CKSUM;
-    if (cksum->length != HMAC_SHA_CKSUM_LENGTH)
-       return KRB5KRB_AP_ERR_BAD_INTEGRITY;
-
-    retval = hmac_sha(in, in_length, seed, seed_length, digest);
-    if (retval) goto cleanup;
-
-    if (memcmp((char *)digest, (char *)cksum->contents, cksum->length))
-       retval = KRB5KRB_AP_ERR_BAD_INTEGRITY;
-
-cleanup:
-    memset((char *)digest, 0, sizeof(digest));
-    return retval;
-}
-
-krb5_checksum_entry hmac_sha_cksumtable_entry =
-{
-    0,
-    krb5_sha_crypto_sum_func,
-    krb5_sha_crypto_verify_func,
-    HMAC_SHA_CKSUM_LENGTH,
-    1,                                 /* is collision proof */
-    1,                                 /* uses key */
-};
diff --git a/src/lib/crypto/sha/sha_glue.c b/src/lib/crypto/sha/sha_glue.c
deleted file mode 100644 (file)
index 58a93b7..0000000
+++ /dev/null
@@ -1,97 +0,0 @@
-#include "shs.h"
-
-krb5_error_code
-krb5_sha_sum_func
-       PROTOTYPE((krb5_const krb5_pointer      in,
-                  krb5_const size_t            in_length,
-                  krb5_const krb5_pointer      seed,
-                  krb5_const size_t            seed_length,
-                  krb5_checksum                FAR *outcksum));
-
-krb5_error_code
-krb5_sha_verify_func
-       PROTOTYPE((krb5_const krb5_checksum     FAR *cksum,
-                  krb5_const krb5_pointer      in,
-                  krb5_const size_t            in_length,
-                  krb5_const krb5_pointer      seed,
-                  krb5_const size_t            seed_length));
-
-krb5_error_code
-krb5_sha_sum_func(in, in_length, seed, seed_length, outcksum)
-       krb5_const krb5_pointer in;
-       krb5_const size_t       in_length;
-       krb5_const krb5_pointer seed;
-       krb5_const size_t       seed_length;
-       krb5_checksum           FAR *outcksum;
-{
-    krb5_octet *input = (krb5_octet *)in;
-    krb5_octet *cp;
-    LONG *lp;
-    SHS_INFO working;
-
-    if (outcksum->length < SHS_DIGESTSIZE)
-       return KRB5_BAD_MSIZE;
-    
-    shsInit(&working);
-    shsUpdate(&working, input, in_length);
-    shsFinal(&working);
-
-    outcksum->checksum_type = CKSUMTYPE_NIST_SHA;
-    outcksum->length = SHS_DIGESTSIZE;
-
-    cp = outcksum->contents;
-    lp = working.digest;
-    while (lp < working.digest + 16) {
-       *cp++ = (*lp >> 24) & 0xff;
-       *cp++ = (*lp >> 16) & 0xff;
-       *cp++ = (*lp >> 8) & 0xff;
-       *cp++ = (*lp++) & 0xff;
-    }
-    memset((char *)&working, 0, sizeof(working));
-    return 0;
-}
-
-krb5_error_code
-krb5_sha_verify_func(cksum, in, in_length, seed, seed_length)
-       krb5_const krb5_checksum        FAR *cksum;
-       krb5_const krb5_pointer         in;
-       krb5_const size_t               in_length;
-       krb5_const krb5_pointer         seed;
-       krb5_const size_t               seed_length;
-{
-    krb5_octet *input = (krb5_octet *)in;
-    SHS_INFO working;
-    krb5_error_code retval;
-    int i;
-    krb5_octet *cp;
-
-    if (cksum->checksum_type != CKSUMTYPE_NIST_SHA)
-       return KRB5KRB_AP_ERR_INAPP_CKSUM;
-    if (cksum->length != SHS_DIGESTSIZE)
-       return KRB5KRB_AP_ERR_BAD_INTEGRITY;
-
-    shsInit(&working);
-    shsUpdate(&working, input, in_length);
-    shsFinal(&working);
-
-    retval = 0;
-    for (i = 0, cp = cksum->contents; i < 5; i++, cp += 4) {
-       if (working.digest[i] !=
-           (LONG) cp[0] << 24 | (LONG) cp[1] << 16 |
-           (LONG) cp[2] << 8 | (LONG) cp[3]) {
-           retval = KRB5KRB_AP_ERR_BAD_INTEGRITY;
-           break;
-       }
-    }
-    memset((char *) &working, 0, sizeof(working));
-    return retval;
-}
-
-krb5_checksum_entry nist_sha_cksumtable_entry = {
-    0,
-    krb5_sha_sum_func,
-    krb5_sha_verify_func,
-    SHS_DIGESTSIZE,
-    1,                                 /* is collision proof */
-    0,                                 /* doesn't use key */
-};
diff --git a/src/lib/crypto/sha/shs.c b/src/lib/crypto/sha/shs.c
deleted file mode 100644 (file)
index e18f3af..0000000
+++ /dev/null
@@ -1,392 +0,0 @@
-#ifdef HAVE_SYS_TYPES_H
-#include <sys/types.h>
-#endif
-#include <string.h>
-#include "shs.h"
-
-/* The SHS f()-functions.  The f1 and f3 functions can be optimized to
-   save one boolean operation each - thanks to Rich Schroeppel,
-   rcs@cs.arizona.edu for discovering this */
-
-#define f1(x,y,z)   ( z ^ ( x & ( y ^ z ) ) )           /* Rounds  0-19 */
-#define f2(x,y,z)   ( x ^ y ^ z )                       /* Rounds 20-39 */
-#define f3(x,y,z)   ( ( x & y ) | ( z & ( x | y ) ) )   /* Rounds 40-59 */
-#define f4(x,y,z)   ( x ^ y ^ z )                       /* Rounds 60-79 */
-
-/* The SHS Mysterious Constants */
-
-#define K1  0x5A827999L                                 /* Rounds  0-19 */
-#define K2  0x6ED9EBA1L                                 /* Rounds 20-39 */
-#define K3  0x8F1BBCDCL                                 /* Rounds 40-59 */
-#define K4  0xCA62C1D6L                                 /* Rounds 60-79 */
-
-/* SHS initial values */
-
-#define h0init  0x67452301L
-#define h1init  0xEFCDAB89L
-#define h2init  0x98BADCFEL
-#define h3init  0x10325476L
-#define h4init  0xC3D2E1F0L
-
-/* Note that it may be necessary to add parentheses to these macros if they
-   are to be called with expressions as arguments */
-
-/* 32-bit rotate left - kludged with shifts */
-
-#define ROTL(n,X)  (((X) << (n)) & 0xffffffff | ((X) >> (32 - n)))
-
-/* The initial expanding function.  The hash function is defined over an
-   80-word expanded input array W, where the first 16 are copies of the input
-   data, and the remaining 64 are defined by
-
-        W[ i ] = W[ i - 16 ] ^ W[ i - 14 ] ^ W[ i - 8 ] ^ W[ i - 3 ]
-
-   This implementation generates these values on the fly in a circular
-   buffer - thanks to Colin Plumb, colin@nyx10.cs.du.edu for this
-   optimization.
-
-   The updated SHS changes the expanding function by adding a rotate of 1
-   bit.  Thanks to Jim Gillogly, jim@rand.org, and an anonymous contributor
-   for this information */
-
-#ifdef NEW_SHS
-#define expand(W,i) ( W[ i & 15 ] = ROTL( 1, ( W[ i & 15 ] ^ W[ (i - 14) & 15 ] ^ \
-                                                 W[ (i - 8) & 15 ] ^ W[ (i - 3) & 15 ] )))
-#else
-#define expand(W,i) ( W[ i & 15 ] ^= W[ (i - 14) & 15 ] ^ \
-                     W[ (i - 8) & 15 ] ^ W[ (i - 3) & 15 ] )
-#endif /* NEW_SHS */
-
-/* The prototype SHS sub-round.  The fundamental sub-round is:
-
-        a' = e + ROTL( 5, a ) + f( b, c, d ) + k + data;
-        b' = a;
-        c' = ROTL( 30, b );
-        d' = c;
-        e' = d;
-
-   but this is implemented by unrolling the loop 5 times and renaming the
-   variables ( e, a, b, c, d ) = ( a', b', c', d', e' ) each iteration.
-   This code is then replicated 20 times for each of the 4 functions, using
-   the next 20 values from the W[] array each time */
-
-#define subRound(a, b, c, d, e, f, k, data) \
-    ( e += ROTL( 5, a ) + f( b, c, d ) + k + data, \
-      e &= 0xffffffff, b = ROTL( 30, b ) )
-
-/* Initialize the SHS values */
-
-void shsInit(shsInfo)
-    SHS_INFO *shsInfo;
-{
-    /* Set the h-vars to their initial values */
-    shsInfo->digest[ 0 ] = h0init;
-    shsInfo->digest[ 1 ] = h1init;
-    shsInfo->digest[ 2 ] = h2init;
-    shsInfo->digest[ 3 ] = h3init;
-    shsInfo->digest[ 4 ] = h4init;
-
-    /* Initialise bit count */
-    shsInfo->countLo = shsInfo->countHi = 0;
-}
-
-/* Perform the SHS transformation.  Note that this code, like MD5, seems to
-   break some optimizing compilers due to the complexity of the expressions
-   and the size of the basic block.  It may be necessary to split it into
-   sections, e.g. based on the four subrounds
-
-   Note that this corrupts the shsInfo->data area */
-
-static void SHSTransform KRB5_PROTOTYPE((LONG *digest, LONG *data));
-
-static
-void SHSTransform(digest, data)
-    LONG *digest;
-    LONG *data;
-{
-    LONG A, B, C, D, E;     /* Local vars */
-    LONG eData[ 16 ];       /* Expanded data */
-
-    /* Set up first buffer and local data buffer */
-    A = digest[ 0 ];
-    B = digest[ 1 ];
-    C = digest[ 2 ];
-    D = digest[ 3 ];
-    E = digest[ 4 ];
-    memcpy(eData, data, sizeof (eData));
-
-    /* Heavy mangling, in 4 sub-rounds of 20 interations each. */
-    subRound( A, B, C, D, E, f1, K1, eData[  0 ] );
-    subRound( E, A, B, C, D, f1, K1, eData[  1 ] );
-    subRound( D, E, A, B, C, f1, K1, eData[  2 ] );
-    subRound( C, D, E, A, B, f1, K1, eData[  3 ] );
-    subRound( B, C, D, E, A, f1, K1, eData[  4 ] );
-    subRound( A, B, C, D, E, f1, K1, eData[  5 ] );
-    subRound( E, A, B, C, D, f1, K1, eData[  6 ] );
-    subRound( D, E, A, B, C, f1, K1, eData[  7 ] );
-    subRound( C, D, E, A, B, f1, K1, eData[  8 ] );
-    subRound( B, C, D, E, A, f1, K1, eData[  9 ] );
-    subRound( A, B, C, D, E, f1, K1, eData[ 10 ] );
-    subRound( E, A, B, C, D, f1, K1, eData[ 11 ] );
-    subRound( D, E, A, B, C, f1, K1, eData[ 12 ] );
-    subRound( C, D, E, A, B, f1, K1, eData[ 13 ] );
-    subRound( B, C, D, E, A, f1, K1, eData[ 14 ] );
-    subRound( A, B, C, D, E, f1, K1, eData[ 15 ] );
-    subRound( E, A, B, C, D, f1, K1, expand( eData, 16 ) );
-    subRound( D, E, A, B, C, f1, K1, expand( eData, 17 ) );
-    subRound( C, D, E, A, B, f1, K1, expand( eData, 18 ) );
-    subRound( B, C, D, E, A, f1, K1, expand( eData, 19 ) );
-
-    subRound( A, B, C, D, E, f2, K2, expand( eData, 20 ) );
-    subRound( E, A, B, C, D, f2, K2, expand( eData, 21 ) );
-    subRound( D, E, A, B, C, f2, K2, expand( eData, 22 ) );
-    subRound( C, D, E, A, B, f2, K2, expand( eData, 23 ) );
-    subRound( B, C, D, E, A, f2, K2, expand( eData, 24 ) );
-    subRound( A, B, C, D, E, f2, K2, expand( eData, 25 ) );
-    subRound( E, A, B, C, D, f2, K2, expand( eData, 26 ) );
-    subRound( D, E, A, B, C, f2, K2, expand( eData, 27 ) );
-    subRound( C, D, E, A, B, f2, K2, expand( eData, 28 ) );
-    subRound( B, C, D, E, A, f2, K2, expand( eData, 29 ) );
-    subRound( A, B, C, D, E, f2, K2, expand( eData, 30 ) );
-    subRound( E, A, B, C, D, f2, K2, expand( eData, 31 ) );
-    subRound( D, E, A, B, C, f2, K2, expand( eData, 32 ) );
-    subRound( C, D, E, A, B, f2, K2, expand( eData, 33 ) );
-    subRound( B, C, D, E, A, f2, K2, expand( eData, 34 ) );
-    subRound( A, B, C, D, E, f2, K2, expand( eData, 35 ) );
-    subRound( E, A, B, C, D, f2, K2, expand( eData, 36 ) );
-    subRound( D, E, A, B, C, f2, K2, expand( eData, 37 ) );
-    subRound( C, D, E, A, B, f2, K2, expand( eData, 38 ) );
-    subRound( B, C, D, E, A, f2, K2, expand( eData, 39 ) );
-
-    subRound( A, B, C, D, E, f3, K3, expand( eData, 40 ) );
-    subRound( E, A, B, C, D, f3, K3, expand( eData, 41 ) );
-    subRound( D, E, A, B, C, f3, K3, expand( eData, 42 ) );
-    subRound( C, D, E, A, B, f3, K3, expand( eData, 43 ) );
-    subRound( B, C, D, E, A, f3, K3, expand( eData, 44 ) );
-    subRound( A, B, C, D, E, f3, K3, expand( eData, 45 ) );
-    subRound( E, A, B, C, D, f3, K3, expand( eData, 46 ) );
-    subRound( D, E, A, B, C, f3, K3, expand( eData, 47 ) );
-    subRound( C, D, E, A, B, f3, K3, expand( eData, 48 ) );
-    subRound( B, C, D, E, A, f3, K3, expand( eData, 49 ) );
-    subRound( A, B, C, D, E, f3, K3, expand( eData, 50 ) );
-    subRound( E, A, B, C, D, f3, K3, expand( eData, 51 ) );
-    subRound( D, E, A, B, C, f3, K3, expand( eData, 52 ) );
-    subRound( C, D, E, A, B, f3, K3, expand( eData, 53 ) );
-    subRound( B, C, D, E, A, f3, K3, expand( eData, 54 ) );
-    subRound( A, B, C, D, E, f3, K3, expand( eData, 55 ) );
-    subRound( E, A, B, C, D, f3, K3, expand( eData, 56 ) );
-    subRound( D, E, A, B, C, f3, K3, expand( eData, 57 ) );
-    subRound( C, D, E, A, B, f3, K3, expand( eData, 58 ) );
-    subRound( B, C, D, E, A, f3, K3, expand( eData, 59 ) );
-
-    subRound( A, B, C, D, E, f4, K4, expand( eData, 60 ) );
-    subRound( E, A, B, C, D, f4, K4, expand( eData, 61 ) );
-    subRound( D, E, A, B, C, f4, K4, expand( eData, 62 ) );
-    subRound( C, D, E, A, B, f4, K4, expand( eData, 63 ) );
-    subRound( B, C, D, E, A, f4, K4, expand( eData, 64 ) );
-    subRound( A, B, C, D, E, f4, K4, expand( eData, 65 ) );
-    subRound( E, A, B, C, D, f4, K4, expand( eData, 66 ) );
-    subRound( D, E, A, B, C, f4, K4, expand( eData, 67 ) );
-    subRound( C, D, E, A, B, f4, K4, expand( eData, 68 ) );
-    subRound( B, C, D, E, A, f4, K4, expand( eData, 69 ) );
-    subRound( A, B, C, D, E, f4, K4, expand( eData, 70 ) );
-    subRound( E, A, B, C, D, f4, K4, expand( eData, 71 ) );
-    subRound( D, E, A, B, C, f4, K4, expand( eData, 72 ) );
-    subRound( C, D, E, A, B, f4, K4, expand( eData, 73 ) );
-    subRound( B, C, D, E, A, f4, K4, expand( eData, 74 ) );
-    subRound( A, B, C, D, E, f4, K4, expand( eData, 75 ) );
-    subRound( E, A, B, C, D, f4, K4, expand( eData, 76 ) );
-    subRound( D, E, A, B, C, f4, K4, expand( eData, 77 ) );
-    subRound( C, D, E, A, B, f4, K4, expand( eData, 78 ) );
-    subRound( B, C, D, E, A, f4, K4, expand( eData, 79 ) );
-
-    /* Build message digest */
-    digest[ 0 ] += A;
-    digest[ 0 ] &= 0xffffffff;
-    digest[ 1 ] += B;
-    digest[ 1 ] &= 0xffffffff;
-    digest[ 2 ] += C;
-    digest[ 2 ] &= 0xffffffff;
-    digest[ 3 ] += D;
-    digest[ 3 ] &= 0xffffffff;
-    digest[ 4 ] += E;
-    digest[ 4 ] &= 0xffffffff;
-}
-
-/* When run on a little-endian CPU we need to perform byte reversal on an
-   array of longwords.  It is possible to make the code endianness-
-   independant by fiddling around with data at the byte level, but this
-   makes for very slow code, so we rely on the user to sort out endianness
-   at compile time */
-
-void longReverse( LONG *buffer, int byteCount )
-{
-    LONG value;
-    static int init = 0;
-    char *cp;
-
-    switch (init) {
-    case 0:
-       init=1;
-       cp = (char *) &init;
-       if (*cp == 1) {
-           init=2;
-           break;
-       }
-       init=1;
-       /* fall through - MSB */
-    case 1:
-       return;
-    }
-
-    byteCount /= sizeof( LONG );
-    while( byteCount-- ) {
-        value = *buffer;
-        value = ( ( value & 0xFF00FF00L ) >> 8  ) | 
-                ( ( value & 0x00FF00FFL ) << 8 );
-        *buffer++ = ( value << 16 ) | ( value >> 16 );
-    }
-}
-
-/* Update SHS for a block of data */
-
-void shsUpdate(shsInfo, buffer, count)
-    SHS_INFO *shsInfo;
-    BYTE *buffer;
-    int count;
-{
-    LONG tmp;
-    int dataCount, canfill;
-    LONG *lp;
-
-    /* Update bitcount */
-    tmp = shsInfo->countLo;
-    shsInfo->countLo = tmp + (((LONG) count) << 3 );
-    if ((shsInfo->countLo &= 0xffffffff) < tmp)
-        shsInfo->countHi++;    /* Carry from low to high */
-    shsInfo->countHi += count >> 29;
-
-    /* Get count of bytes already in data */
-    dataCount = (int) (tmp >> 3) & 0x3F;
-
-    /* Handle any leading odd-sized chunks */
-    if (dataCount) {
-       lp = shsInfo->data + dataCount / 4;
-       canfill = (count >= dataCount);
-       dataCount = SHS_DATASIZE - dataCount;
-
-       if (dataCount % 4) {
-           /* Fill out a full 32 bit word first if needed -- this
-              is not very efficient (computed shift amount),
-              but it shouldn't happen often. */
-           while (dataCount % 4 && count > 0) {
-               *lp |= (LONG) *buffer++ << ((3 - dataCount++ % 4) * 8);
-               count--;
-           }
-           lp++;
-       }
-       while (lp < shsInfo->data + 16) {
-           *lp = (LONG) *buffer++ << 24;
-           *lp |= (LONG) *buffer++ << 16;
-           *lp |= (LONG) *buffer++ << 8;
-           *lp++ |= (LONG) *buffer++;
-           if ((count -= 4) < 4 && lp < shsInfo->data + 16) {
-               *lp = 0;
-               switch (count % 4) {
-               case 3:
-                   *lp |= (LONG) buffer[2] << 8;
-               case 2:
-                   *lp |= (LONG) buffer[1] << 16;
-               case 1:
-                   *lp |= (LONG) buffer[0] << 24;
-               }
-               break;
-               count = 0;
-           }
-       }
-       if (canfill) {
-           SHSTransform(shsInfo->digest, shsInfo->data);
-       }
-    }
-
-    /* Process data in SHS_DATASIZE chunks */
-    while (count >= SHS_DATASIZE) {
-       lp = shsInfo->data;
-       while (lp < shsInfo->data + 16) {
-           *lp = ((LONG) *buffer++) << 24;
-           *lp |= ((LONG) *buffer++) << 16;
-           *lp |= ((LONG) *buffer++) << 8;
-           *lp++ |= (LONG) *buffer++;
-       }
-       SHSTransform(shsInfo->digest, shsInfo->data);
-       count -= SHS_DATASIZE;
-    }
-
-    if (count > 0) {
-       lp = shsInfo->data;
-       while (count > 4) {
-           *lp = ((LONG) *buffer++) << 24;
-           *lp |= ((LONG) *buffer++) << 16;
-           *lp |= ((LONG) *buffer++) << 8;
-           *lp++ |= (LONG) *buffer++;
-           count -= 4;
-       }
-       *lp = 0;
-       switch (count % 4) {
-       case 0:
-           *lp |= ((LONG) buffer[3]);
-       case 3:
-           *lp |= ((LONG) buffer[2]) << 8;
-       case 2:
-           *lp |= ((LONG) buffer[1]) << 16;
-       case 1:
-           *lp |= ((LONG) buffer[0]) << 24;
-       }
-    }
-}
-
-/* Final wrapup - pad to SHS_DATASIZE-byte boundary with the bit pattern
-   1 0* (64-bit count of bits processed, MSB-first) */
-
-void shsFinal(shsInfo)
-    SHS_INFO *shsInfo;
-{
-    int count;
-    LONG *lp;
-    BYTE *dataPtr;
-
-    /* Compute number of bytes mod 64 */
-    count = (int) shsInfo->countLo;
-    count = (count >> 3) & 0x3F;
-
-    /* Set the first char of padding to 0x80.  This is safe since there is
-       always at least one byte free */
-    lp = shsInfo->data + count / 4;
-    switch (count % 4) {
-    case 3:
-       *lp++ |= (LONG) 0x80;
-       break;
-    case 2:
-       *lp++ |= (LONG) 0x80 << 8;
-       break;
-    case 1:
-       *lp++ |= (LONG) 0x80 << 16;
-       break;
-    case 0:
-       *lp++ = (LONG) 0x80 << 24;
-    }
-
-    if (lp > shsInfo->data + 14) {
-       /* Pad out to 64 bytes if not enough room for length words */
-       *lp = 0;
-       SHSTransform(shsInfo->digest, shsInfo->data);
-       lp = shsInfo->data;
-    }
-    /* Pad out to 56 bytes */
-    while (lp < shsInfo->data + 14)
-       *lp++ = 0;
-    /* Append length in bits and transform */
-    *lp++ = shsInfo->countHi;
-    *lp++ = shsInfo->countLo;
-    SHSTransform(shsInfo->digest, shsInfo->data);
-}
diff --git a/src/lib/crypto/sha/shs.h b/src/lib/crypto/sha/shs.h
deleted file mode 100644 (file)
index 01acddb..0000000
+++ /dev/null
@@ -1,59 +0,0 @@
-#ifndef _SHS_DEFINED
-
-#include <k5-int.h>
-
-#define _SHS_DEFINED
-
-/* Some useful types */
-
-typedef krb5_octet     BYTE;
-
-/* Old DOS/Windows compilers are case-insensitive */
-#if !defined(_MSDOS) && !defined(_WIN32)
-typedef krb5_ui_4      LONG;
-#endif
-
-
-/* Define the following to use the updated SHS implementation */
-#define NEW_SHS         /**/
-
-/* The SHS block size and message digest sizes, in bytes */
-
-#define SHS_DATASIZE    64
-#define SHS_DIGESTSIZE  20
-
-/* The structure for storing SHS info */
-
-typedef struct {
-               LONG digest[ 5 ];            /* Message digest */
-               LONG countLo, countHi;       /* 64-bit bit count */
-               LONG data[ 16 ];             /* SHS data buffer */
-               } SHS_INFO;
-
-/* Message digest functions (shs.c) */
-void shsInit
-       KRB5_PROTOTYPE((SHS_INFO *shsInfo));
-void shsUpdate
-       KRB5_PROTOTYPE((SHS_INFO *shsInfo, BYTE *buffer, int count));
-void shsFinal
-       KRB5_PROTOTYPE((SHS_INFO *shsInfo));
-
-
-/* Keyed Message digest functions (hmac_sha.c) */
-krb5_error_code hmac_sha
-       KRB5_PROTOTYPE((krb5_octet *text,
-                       int text_len,
-                       krb5_octet *key,
-                       int key_len,
-                       krb5_octet *digest));
-
-
-#define NIST_SHA_CKSUM_LENGTH          SHS_DIGESTSIZE
-#define HMAC_SHA_CKSUM_LENGTH          SHS_DIGESTSIZE
-
-
-extern krb5_checksum_entry
-    nist_sha_cksumtable_entry,
-    hmac_sha_cksumtable_entry;
-
-#endif /* _SHS_DEFINED */
diff --git a/src/lib/crypto/sha/t_shs.c b/src/lib/crypto/sha/t_shs.c
deleted file mode 100644 (file)
index da55992..0000000
+++ /dev/null
@@ -1,132 +0,0 @@
-/****************************************************************************
-*                                                                           *
-*                               SHS Test Code                               *
-*                                                                           *
-****************************************************************************/
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <time.h>
-#include "shs.h"
-
-/* Test the SHS implementation */
-
-#ifdef NEW_SHS
-
-static LONG shsTestResults[][ 5 ] = {
-    { 0xA9993E36L, 0x4706816AL, 0xBA3E2571L, 0x7850C26CL, 0x9CD0D89DL, },
-    { 0x84983E44L, 0x1C3BD26EL, 0xBAAE4AA1L, 0xF95129E5L, 0xE54670F1L, },
-    { 0x34AA973CL, 0xD4C4DAA4L, 0xF61EEB2BL, 0xDBAD2731L, 0x6534016FL, }
-    };
-
-#else
-
-static LONG shsTestResults[][ 5 ] = {
-    { 0x0164B8A9L, 0x14CD2A5EL, 0x74C4F7FFL, 0x082C4D97L, 0xF1EDF880L },
-    { 0xD2516EE1L, 0xACFA5BAFL, 0x33DFC1C4L, 0x71E43844L, 0x9EF134C8L },
-    { 0x3232AFFAL, 0x48628A26L, 0x653B5AAAL, 0x44541FD9L, 0x0D690603L }
-    };
-#endif /* NEW_SHS */
-
-static int compareSHSresults(shsInfo, shsTestLevel)
-SHS_INFO *shsInfo;
-int shsTestLevel;
-{
-    int i, fail = 0;
-
-    /* Compare the returned digest and required values */
-    for( i = 0; i < 5; i++ )
-        if( shsInfo->digest[ i ] != shsTestResults[ shsTestLevel ][ i ] )
-           fail = 1;
-    if (fail) {
-       printf("\nExpected: ");
-       for (i = 0; i < 5; i++) {
-           printf("%8.8lx ", shsTestResults[shsTestLevel][i]);
-       }
-       printf("\nGot:      ");
-       for (i = 0; i < 5; i++) {
-           printf("%8.8lx ", shsInfo->digest[i]);
-       }
-       printf("\n");
-       return( -1 );
-    }
-    return( 0 );
-}
-
-main()
-{
-    SHS_INFO shsInfo;
-    unsigned int i;
-    time_t secondCount;
-    BYTE data[ 200 ];
-
-    /* Make sure we've got the endianness set right.  If the machine is
-       big-endian (up to 64 bits) the following value will be signed,
-       otherwise it will be unsigned.  Unfortunately we can't test for odd
-       things like middle-endianness without knowing the size of the data
-       types */
-
-    /* Test SHS against values given in SHS standards document */
-    printf( "Running SHS test 1 ... " );
-    shsInit( &shsInfo );
-    shsUpdate( &shsInfo, ( BYTE * ) "abc", 3 );
-    shsFinal( &shsInfo );
-    if( compareSHSresults( &shsInfo, 0 ) == -1 )
-        {
-        putchar( '\n' );
-        puts( "SHS test 1 failed" );
-        exit( -1 );
-        }
-#ifdef NEW_SHS
-    puts( "passed, result= A9993E364706816ABA3E25717850C26C9CD0D89D" );
-#else
-    puts( "passed, result= 0164B8A914CD2A5E74C4F7FF082C4D97F1EDF880" );
-#endif /* NEW_SHS */
-
-    printf( "Running SHS test 2 ... " );
-    shsInit( &shsInfo );
-    shsUpdate( &shsInfo, ( BYTE * ) "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", 56 );
-    shsFinal( &shsInfo );
-    if( compareSHSresults( &shsInfo, 1 ) == -1 )
-        {
-        putchar( '\n' );
-        puts( "SHS test 2 failed" );
-        exit( -1 );
-        }
-#ifdef NEW_SHS
-    puts( "passed, result= 84983E441C3BD26EBAAE4AA1F95129E5E54670F1" );
-#else
-    puts( "passed, result= D2516EE1ACFA5BAF33DFC1C471E438449EF134C8" );
-#endif /* NEW_SHS */
-
-    printf( "Running SHS test 3 ... " );
-    shsInit( &shsInfo );
-    for( i = 0; i < 15625; i++ )
-        shsUpdate( &shsInfo, ( BYTE * ) "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", 64 );
-    shsFinal( &shsInfo );
-    if( compareSHSresults( &shsInfo, 2 ) == -1 )
-        {
-        putchar( '\n' );
-        puts( "SHS test 3 failed" );
-        exit( -1 );
-        }
-#ifdef NEW_SHS
-    puts( "passed, result= 34AA973CD4C4DAA4F61EEB2BDBAD27316534016F" );
-#else
-    puts( "passed, result= 3232AFFA48628A26653B5AAA44541FD90D690603" );
-#endif /* NEW_SHS */
-
-#if 0
-    printf( "\nTesting speed for 100MB data... " );
-    shsInit( &shsInfo );
-    secondCount = time( NULL );
-    for( i = 0; i < 500000U; i++ )
-        shsUpdate( &shsInfo, data, 200 );
-    secondCount = time( NULL ) - secondCount;
-    printf( "done.  Time = %ld seconds, %ld kbytes/second.\n", \
-            secondCount, 100500L / secondCount );
-#endif
-
-    puts( "\nAll SHS tests passed" );
-    exit( 0 );
-}
diff --git a/src/lib/crypto/string_to_cksumtype.c b/src/lib/crypto/string_to_cksumtype.c
new file mode 100644 (file)
index 0000000..fe46e8a
--- /dev/null
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 1998 by the FundsXpress, INC.
+ * 
+ * All rights reserved.
+ * 
+ * Export of this software from the United States of America may require
+ * a specific license from the United States Government.  It is the
+ * responsibility of any person or organization contemplating export to
+ * obtain such a license before exporting.
+ * 
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of FundsXpress. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  FundsXpress makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#include "k5-int.h"
+#include "cksumtypes.h"
+
+KRB5_DLLIMP krb5_error_code KRB5_CALLCONV
+krb5_string_to_cksumtype(string, cksumtypep)
+    char               FAR * string;
+    krb5_cksumtype     FAR * cksumtypep;
+{
+    int i;
+
+    for (i=0; i<krb5_cksumtypes_length; i++) {
+       if (strcasecmp(krb5_cksumtypes_list[i].in_string, string) == 0) {
+           *cksumtypep = krb5_cksumtypes_list[i].ctype;
+           return(0);
+       }
+    }
+
+    return(EINVAL);
+}
diff --git a/src/lib/crypto/string_to_enctype.c b/src/lib/crypto/string_to_enctype.c
new file mode 100644 (file)
index 0000000..8d3e6a3
--- /dev/null
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 1998 by the FundsXpress, INC.
+ * 
+ * All rights reserved.
+ * 
+ * Export of this software from the United States of America may require
+ * a specific license from the United States Government.  It is the
+ * responsibility of any person or organization contemplating export to
+ * obtain such a license before exporting.
+ * 
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of FundsXpress. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  FundsXpress makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#include "k5-int.h"
+#include "etypes.h"
+
+KRB5_DLLIMP krb5_error_code KRB5_CALLCONV
+krb5_string_to_enctype(string, enctypep)
+    char               FAR * string;
+    krb5_enctype       FAR * enctypep;
+{
+    int i;
+
+    for (i=0; i<krb5_enctypes_length; i++) {
+       if (strcasecmp(krb5_enctypes_list[i].in_string, string) == 0) {
+           *enctypep = krb5_enctypes_list[i].etype;
+           return(0);
+       }
+    }
+
+    return(EINVAL);
+}
diff --git a/src/lib/crypto/string_to_key.c b/src/lib/crypto/string_to_key.c
new file mode 100644 (file)
index 0000000..a569e49
--- /dev/null
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 1998 by the FundsXpress, INC.
+ * 
+ * All rights reserved.
+ * 
+ * Export of this software from the United States of America may require
+ * a specific license from the United States Government.  It is the
+ * responsibility of any person or organization contemplating export to
+ * obtain such a license before exporting.
+ * 
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of FundsXpress. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  FundsXpress makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#include "k5-int.h"
+#include "etypes.h"
+
+KRB5_DLLIMP krb5_error_code KRB5_CALLCONV
+krb5_c_string_to_key(context, enctype, string, salt, key)
+     krb5_context context;
+     krb5_enctype enctype;
+     krb5_const krb5_data *string;
+     krb5_const krb5_data *salt;
+     krb5_keyblock *key;
+{
+    int i;
+    krb5_error_code ret;
+    struct krb5_enc_provider *enc;
+    size_t keybytes, keylength;
+
+    for (i=0; i<krb5_enctypes_length; i++) {
+       if (krb5_enctypes_list[i].etype == enctype)
+           break;
+    }
+
+    if (i == krb5_enctypes_length)
+       return(KRB5_BAD_ENCTYPE);
+
+    enc = krb5_enctypes_list[i].enc;
+
+    (*(enc->keysize))(&keybytes, &keylength);
+
+    if ((key->contents = (krb5_octet *) malloc(keylength)) == NULL)
+       return(ENOMEM);
+
+    key->magic = KV5M_KEYBLOCK;
+    key->enctype = enctype;
+    key->length = keylength;
+
+    if (ret = ((*(krb5_enctypes_list[i].str2key))(enc, string, salt, key))) {
+       memset(key->contents, 0, keylength);
+       free(key->contents);
+    }
+
+    return(ret);
+}
diff --git a/src/lib/crypto/t_nfold.c b/src/lib/crypto/t_nfold.c
new file mode 100644 (file)
index 0000000..2693318
--- /dev/null
@@ -0,0 +1,76 @@
+/*
+ * lib/crypto/t_nfold.c
+ *
+ * Copyright 1988, 1990 by the Massachusetts Institute of Technology.
+ * All Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ *   require a specific license from the United States Government.
+ *   It is the responsibility of any person or organization contemplating
+ *   export to obtain such a license before exporting.
+ * 
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ *
+ * Program to test the correctness of nfold implementation.
+ *
+ * exit returns         0 ==> success
+ *             -1 ==> error
+ */
+
+#include <stdio.h>
+#include <string.h>
+
+#include "k5-int.h"
+
+unsigned char *nfold_in[] = {
+    "basch",
+    "eichin",
+    "sommerfeld",
+    "MASSACHVSETTS INSTITVTE OF TECHNOLOGY" };
+
+unsigned char nfold_192[4][24] = {
+    { 0x1a, 0xab, 0x6b, 0x42, 0x96, 0x4b, 0x98, 0xb2, 0x1f, 0x8c, 0xde, 0x2d,
+      0x24, 0x48, 0xba, 0x34, 0x55, 0xd7, 0x86, 0x2c, 0x97, 0x31, 0x64, 0x3f },
+    { 0x65, 0x69, 0x63, 0x68, 0x69, 0x6e, 0x4b, 0x73, 0x2b, 0x4b, 0x1b, 0x43,
+      0xda, 0x1a, 0x5b, 0x99, 0x5a, 0x58, 0xd2, 0xc6, 0xd0, 0xd2, 0xdc, 0xca },
+    { 0x2f, 0x7a, 0x98, 0x55, 0x7c, 0x6e, 0xe4, 0xab, 0xad, 0xf4, 0xe7, 0x11,
+      0x92, 0xdd, 0x44, 0x2b, 0xd4, 0xff, 0x53, 0x25, 0xa5, 0xde, 0xf7, 0x5c },
+    { 0xdb, 0x3b, 0x0d, 0x8f, 0x0b, 0x06, 0x1e, 0x60, 0x32, 0x82, 0xb3, 0x08,
+      0xa5, 0x08, 0x41, 0x22, 0x9a, 0xd7, 0x98, 0xfa, 0xb9, 0x54, 0x0c, 0x1b }
+};
+
+int
+main(argc, argv)
+     int argc;
+     char *argv[];
+{
+    unsigned char cipher_text[64];
+    int i, j;
+
+    printf("N-fold\n");
+    for (i=0; i<sizeof(nfold_in)/sizeof(char *); i++) {
+       printf("\tInput:\t\"%.*s\"\n", strlen(nfold_in[i]), nfold_in[i]);
+       printf("\t192-Fold:\t");
+       krb5_nfold(strlen(nfold_in[i])*8, nfold_in[i], 24*8, cipher_text);
+       for (j=0; j<24; j++)
+           printf("%s%02x", (j&3) ? "" : " ", cipher_text[j]);
+       printf("\n");
+       if (memcmp(cipher_text, nfold_192[i], 24)) {
+           printf("verify: error in n-fold\n");
+           exit(-1);
+       };
+    }
+    printf("verify: N-fold is correct\n\n");
+
+    exit(0);
+}
diff --git a/src/lib/crypto/valid_cksumtype.c b/src/lib/crypto/valid_cksumtype.c
new file mode 100644 (file)
index 0000000..24108a3
--- /dev/null
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 1998 by the FundsXpress, INC.
+ * 
+ * All rights reserved.
+ * 
+ * Export of this software from the United States of America may require
+ * a specific license from the United States Government.  It is the
+ * responsibility of any person or organization contemplating export to
+ * obtain such a license before exporting.
+ * 
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of FundsXpress. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  FundsXpress makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#include "k5-int.h"
+#include "cksumtypes.h"
+
+krb5_boolean valid_cksumtype(ctype)
+     krb5_cksumtype ctype;
+{
+    int i;
+
+    for (i=0; i<krb5_cksumtypes_length; i++) {
+       if (krb5_cksumtypes_list[i].ctype == ctype)
+           return(1);
+    }
+
+    return(0);
+}
diff --git a/src/lib/crypto/valid_enctype.c b/src/lib/crypto/valid_enctype.c
new file mode 100644 (file)
index 0000000..03944c0
--- /dev/null
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 1998 by the FundsXpress, INC.
+ * 
+ * All rights reserved.
+ * 
+ * Export of this software from the United States of America may require
+ * a specific license from the United States Government.  It is the
+ * responsibility of any person or organization contemplating export to
+ * obtain such a license before exporting.
+ * 
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of FundsXpress. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  FundsXpress makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#include "k5-int.h"
+#include "etypes.h"
+
+krb5_boolean valid_enctype(etype)
+     krb5_enctype etype;
+{
+    int i;
+
+    for (i=0; i<krb5_enctypes_length; i++) {
+       if (krb5_enctypes_list[i].etype == etype)
+           return(1);
+    }
+
+    return(0);
+}
diff --git a/src/lib/crypto/verify_checksum.c b/src/lib/crypto/verify_checksum.c
new file mode 100644 (file)
index 0000000..f2749c8
--- /dev/null
@@ -0,0 +1,84 @@
+/*
+ * Copyright (C) 1998 by the FundsXpress, INC.
+ * 
+ * All rights reserved.
+ * 
+ * Export of this software from the United States of America may require
+ * a specific license from the United States Government.  It is the
+ * responsibility of any person or organization contemplating export to
+ * obtain such a license before exporting.
+ * 
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of FundsXpress. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  FundsXpress makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#include "k5-int.h"
+#include "cksumtypes.h"
+
+krb5_error_code
+krb5_c_verify_checksum(context, key, usage, data, cksum, valid)
+     krb5_context context;
+     krb5_const krb5_keyblock *key;
+     krb5_keyusage usage;
+     krb5_const krb5_data *data;
+     krb5_const krb5_checksum *cksum;
+     krb5_boolean *valid;
+{
+    int i;
+    size_t hashsize;
+    krb5_error_code ret;
+    krb5_data indata;
+    krb5_checksum computed;
+
+    for (i=0; i<krb5_cksumtypes_length; i++) {
+       if (krb5_cksumtypes_list[i].ctype == cksum->checksum_type)
+           break;
+    }
+
+    if (i == krb5_cksumtypes_length)
+       return(KRB5_BAD_ENCTYPE);
+
+    /* if there's actually a verify function, call it */
+
+    indata.length = cksum->length;
+    indata.data = cksum->contents;
+
+    if (krb5_cksumtypes_list[i].keyhash &&
+       krb5_cksumtypes_list[i].keyhash->verify)
+       return((*(krb5_cksumtypes_list[i].keyhash->verify))(key, 0, data,
+                                                           &indata, valid));
+
+    /* otherwise, make the checksum again, and compare */
+
+    if (ret = krb5_c_checksum_length(context, cksum->checksum_type, &hashsize))
+       return(ret);
+
+    if (cksum->length != hashsize)
+       return(KRB5_BAD_MSIZE);
+
+    computed.length = hashsize;
+
+    if (ret = krb5_c_make_checksum(context, cksum->checksum_type, key, usage,
+                                  data, &computed)) {
+       free(computed.contents);
+       return(ret);
+    }
+
+    *valid = (memcmp(computed.contents, cksum->contents, hashsize) == 0);
+
+    free(computed.contents);
+
+    return(0);
+}
index ce04691e9582eb47f7d9ff132cad3da6685ac190..4eeef1028744a3cf4ea5f942a9aa374d64422796 100644 (file)
@@ -1,6 +1,12 @@
+1998-10-27  Marc Horowitz  <marc@mit.edu>
+
+       * random_key.c, new_rnd_key.c: make the v4 compat random key code
+       use the krb5 crypto interface, instead of the des implementation
+       internals.
+
 Wed Apr 15 18:03:43 1998  Tom Yu  <tlyu@mit.edu>
 
-       * Makefile.in (SHLIB_EXPDEPS): 
+       * Makefile.in (SHLIB_EXPDEPS):
        (SHLIB_EXPLIBS): Rename libcrypto -> libk5crypto.
 
 Tue Mar  3 08:59:03 1998  Ezra Peisach  <epeisach@kangaroo.mit.edu>
index 541a516e6159f3fa97438ea6ea39264749fd1586..e96e03f9991696f4e26112bb5c83adfd1d4ea56f 100644 (file)
@@ -14,7 +14,7 @@ PROG_RPATH=$(KRB5_LIBDIR)
 RUN_SETUP=@KRB5_RUN_ENV@
 
 LIB=des425
-LIBMAJOR=2
+LIBMAJOR=3
 LIBMINOR=0
 RELDIR=des425
 # Depends on libk5crypto and libkrb5
@@ -27,7 +27,6 @@ SHLIB_RDIRS=$(KRB5_LIBDIR)
 
 STOBJLISTS=OBJS.ST
 STLIBOBJS=cksum.o      \
-       des.o           \
        enc_dec.o       \
        key_parity.o    \
        key_sched.o     \
@@ -44,7 +43,6 @@ STLIBOBJS=cksum.o     \
 
 
 OBJS=  cksum.$(OBJEXT)         \
-       des.$(OBJEXT)           \
        enc_dec.$(OBJEXT)       \
        key_parity.$(OBJEXT)    \
        key_sched.$(OBJEXT)     \
@@ -60,7 +58,6 @@ OBJS= cksum.$(OBJEXT)         \
        k4_glue.$(OBJEXT)
 
 SRCS=  $(srcdir)/cksum.c       \
-       $(srcdir)/des.c         \
        $(srcdir)/enc_dec.c     \
        $(srcdir)/key_parity.c  \
        $(srcdir)/key_sched.c   \
index 943b9e03b5d093a7514262bb44cd574d2159b5a0..4dd2e4be76c5ae30090b291613718c7b374f6548 100644 (file)
  *
  */
 
-
-#include "des.h"
-
-krb5_pointer des425_random_state = 0;
-
 /*
- * des_new_random_key: create a random des key
- *
- * Requires: des_set_random_number_generater_seed must be at called least
- *           once before this routine is called.
- *
- * Notes: the returned key has correct parity and is guarenteed not
- *        to be a weak des key.  Des_generate_random_block is used to
- *        provide the random bits.
+ * Copyright (C) 1998 by the FundsXpress, INC.
+ * 
+ * All rights reserved.
+ * 
+ * Export of this software from the United States of America may require
+ * a specific license from the United States Government.  It is the
+ * responsibility of any person or organization contemplating export to
+ * obtain such a license before exporting.
+ * 
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of FundsXpress. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  FundsXpress makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  */
-KRB5_DLLIMP int KRB5_CALLCONV
-des_new_random_key(key)
-    mit_des_cblock key;
-{
-    krb5_keyblock * keyblock;
-    krb5_error_code kret;
 
-    kret = mit_des_random_key(NULL, des425_random_state, &keyblock);
-    if (kret) return kret;
-    
-    memcpy(key, keyblock->contents, sizeof(mit_des_cblock));
-    krb5_free_keyblock(NULL, keyblock);
-    return 0;
-}
+
+#include "des.h"
 
 /*
  * des_init_random_number_generator:
@@ -71,67 +70,38 @@ void
 des_init_random_number_generator(key)
     mit_des_cblock key;
 {
-    krb5_keyblock keyblock;
-    krb5_encrypt_block eblock;
-
-    krb5_use_enctype(NULL, &eblock, ENCTYPE_DES_CBC_CRC);
+    krb5_data seed;
 
-    keyblock.enctype = ENCTYPE_DES_CBC_CRC;
-    keyblock.length = sizeof(mit_des_cblock);
-    keyblock.contents = (krb5_octet *)key;
+    seed.length = sizeof(key);
+    seed.data = key;
 
-    if (des425_random_state)
-       mit_des_finish_random_key(&eblock, &des425_random_state);
-    mit_des_init_random_key(&eblock, &keyblock, &des425_random_state);
+    if (krb5_c_random_seed(/* XXX */ 0, &seed))
+       /* XXX */ abort();
 }
 
 /*
- * This module implements a random number generator faculty such that the next
- * number in any random number stream is very hard to predict without knowing
- * the seed for that stream even given the preceeding random numbers.
- */
-
-/*
- * des_set_random_generator_seed: this routine is used to select a random
- *                                number stream.  The stream that results is
- *                                totally determined by the passed in key.
- *                                (I.e., calling this routine again with the
- *                                same key allows repeating a sequence of
- *                                random numbers)
+ * des_new_random_key: create a random des key
+ *
+ * Requires: des_set_random_number_generater_seed must be at called least
+ *           once before this routine is called.
  *
- * Requires: key is a valid des key.  I.e., has correct parity and is not a
- *           weak des key.
+ * Notes: the returned key has correct parity and is guarenteed not
+ *        to be a weak des key.  Des_generate_random_block is used to
+ *        provide the random bits.
  */
-KRB5_DLLIMP void KRB5_CALLCONV
-des_set_random_generator_seed(key)
+KRB5_DLLIMP int KRB5_CALLCONV
+des_new_random_key(key)
     mit_des_cblock key;
 {
-    krb5_data seed;
+    krb5_keyblock keyblock;
+    krb5_error_code kret;
 
-    seed.length = sizeof(mit_des_cblock);
-    seed.data = (krb5_pointer) key;
+    kret = krb5_c_make_random_key(/* XXX */ 0, ENCTYPE_DES_CBC_CRC, &keyblock);
+    if (kret) return kret;
+    
+    memcpy(key, keyblock.contents, sizeof(mit_des_cblock));
+    krb5_free_keyblock_contents(/* XXX */ 0, &keyblock);
 
-    if (!des425_random_state)
-       des_init_random_number_generator(key);
-    mit_des_set_random_generator_seed(&seed, des425_random_state);
+    return 0;
 }
 
-
-/*
- * des_set_sequence_number: this routine is used to set the sequence number
- *                          of the current random number stream.  This routine
- *                          may be used to "seek" within the current random
- *                          number stream.
- *
- * Note that des_set_random_generator_seed resets the sequence number to 0.
- */
-void
-des_set_sequence_number(new_sequence_number)
-    mit_des_cblock new_sequence_number;
-{
-    krb5_data sequence;
-
-    sequence.length = sizeof(new_sequence_number);
-    sequence.data = (char FAR *)new_sequence_number;
-    mit_des_set_random_sequence_number(&sequence, des425_random_state);
-}
index 04399c1f0526682e83fdb50ef253c1c1010ff61b..fde324dece48c37ffe3317c11c8120aa0277eb9c 100644 (file)
  *
  */
 
+/*
+ * Copyright (C) 1998 by the FundsXpress, INC.
+ * 
+ * All rights reserved.
+ * 
+ * Export of this software from the United States of America may require
+ * a specific license from the United States Government.  It is the
+ * responsibility of any person or organization contemplating export to
+ * obtain such a license before exporting.
+ * 
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of FundsXpress. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  FundsXpress makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
 
 #include "des.h"
 
-extern krb5_pointer des425_random_state;
-
 /* random_key */
 int
 des_random_key(key)
     mit_des_cblock *key;
 {
-    krb5_encrypt_block eblock;
     krb5_keyblock      keyblock;
-    krb5_keyblock      *new_key;
     krb5_error_code    kret;
-    mit_des_cblock     nullkey;
-
-    krb5_use_enctype(NULL, &eblock, ENCTYPE_DES_CBC_CRC);
-
-    memset(nullkey, 0, sizeof(mit_des_cblock));
-    mit_des_fixup_key_parity(*key);
-
-    keyblock.enctype = ENCTYPE_DES_CBC_CRC;
-    keyblock.length = sizeof(mit_des_cblock);
-    keyblock.contents = (krb5_octet *)nullkey;
 
-    if (! des425_random_state)
-       mit_des_init_random_key(&eblock, &keyblock, &des425_random_state);
+    if (kret = krb5_c_make_random_key(/* XXX */ 0, ENCTYPE_DES_CBC_CRC,
+                                     &keyblock))
+       return(kret);
 
-    kret = mit_des_random_key(NULL, des425_random_state, &new_key);
-    if (kret) return kret;
+    memcpy(key, keyblock.contents, sizeof(mit_des_cblock));
 
-    memcpy(key, new_key->contents, sizeof(mit_des_cblock));
-    krb5_free_keyblock(NULL, new_key);
     return(0);
 }
 
index 6835596f79773a63fc8bb2215e3494ff106c0406..843207133508b894d271deeba4650ed9268b060d 100644 (file)
@@ -9,7 +9,7 @@ LOCAL_SUBDIRS= generic krb5
 MAC_SUBDIRS = generic krb5
 
 LIB=gssapi_krb5
-LIBMAJOR=1
+LIBMAJOR=2
 LIBMINOR=1
 STOBJLISTS=generic/OBJS.ST krb5/OBJS.ST
 SHLIB_EXPDEPS=\
index 74f13a4a3e54a394ecc391f81d2e5a9918581781..601ca76f6b9c810452663757363cc6a5af971c7e 100644 (file)
@@ -1,3 +1,8 @@
+1998-10-27  Marc Horowitz  <marc@mit.edu>
+
+       * gssapi.hin: define GSS_S_DUPLICATE_ELEMENT, GSS_S_NAME_NOT_MN,
+       and GSS_S_GAP_TOKEN as per gss v2 c bindings
+
 1998-06-08  Theodore Ts'o  <tytso@rsts-11.mit.edu>
 
        * oid_ops.c (generic_gss_release_oid): Recognize our own "self"
index d00e19ab946482362347163ebd0ceed932dc1a98..a30b7943110701f1066546a7be57bbbed368ff6c 100644 (file)
@@ -307,11 +307,10 @@ typedef   int             gss_cred_usage_t;
 #define GSS_S_BAD_QOP (((OM_uint32) 14ul) << GSS_C_ROUTINE_ERROR_OFFSET)
 #define GSS_S_UNAUTHORIZED (((OM_uint32) 15ul) << GSS_C_ROUTINE_ERROR_OFFSET)
 #define GSS_S_UNAVAILABLE (((OM_uint32) 16ul) << GSS_C_ROUTINE_ERROR_OFFSET)
-/*
- * XXX new functions.  Check to get official error number assigments?
- */
 #define GSS_S_DUPLICATE_ELEMENT \
      (((OM_uint32) 17ul) << GSS_C_ROUTINE_ERROR_OFFSET)
+#define GSS_S_NAME_NOT_MN \
+     (((OM_uint32) 18ul) << GSS_C_ROUTINE_ERROR_OFFSET)
 
 /*
  * Supplementary info bits:
@@ -320,9 +319,6 @@ typedef     int             gss_cred_usage_t;
 #define GSS_S_DUPLICATE_TOKEN (1 << (GSS_C_SUPPLEMENTARY_OFFSET + 1))
 #define GSS_S_OLD_TOKEN (1 << (GSS_C_SUPPLEMENTARY_OFFSET + 2))
 #define GSS_S_UNSEQ_TOKEN (1 << (GSS_C_SUPPLEMENTARY_OFFSET + 3))
-/*
- * XXX not in the cbindings yet.  remove this comment when it is
- */
 #define GSS_S_GAP_TOKEN (1 << (GSS_C_SUPPLEMENTARY_OFFSET + 4))
 
 
index ddeed4227e71680ffe09bba51326b18c7fedd51c..99ba45fe3814c163a889ab38f69acef9286facbd 100644 (file)
@@ -40,4 +40,7 @@ error_code G_BAD_HOSTNAME, "Hostname in SERVICE-NAME string could not be canonic
 error_code G_WRONG_MECH, "Mechanism is incorrect"
 error_code G_BAD_TOK_HEADER, "Token header is malformed or corrupt"
 error_code G_BAD_DIRECTION, "Packet was replayed in wrong direction"
+error_code G_TOK_TRUNC, "Token is missing data"
+error_code G_REFLECT, "Token was reflected"
+error_code G_WRONG_TOKID, "Received token ID does not match expected token ID"
 end
index 627b5011bc80dec5b756f93966ad0aa9034a053f..9e186a1538983fcd4b61670478dd66c0a0fe4b27 100644 (file)
@@ -205,9 +205,12 @@ gss_int32 g_verify_token_header(mech, body_size, buf_in, tok_type, toksize)
    if ((toksize-=2) < 0)
       return(G_BAD_TOK_HEADER);
 
+   if (ret)
+       return(ret);
+
    if ((*buf++ != ((tok_type>>8)&0xff)) ||
-       (*buf++ != (tok_type&0xff)))
-      return(G_BAD_TOK_HEADER);
+       (*buf++ != (tok_type&0xff))) 
+      return(G_WRONG_TOKID);
 
    if (!ret) {
        *buf_in = buf;
index a94aeb72d4a3b6b3ae8d530da56ddfb54d78b8d8..e12dfdb2b3fcdfee98da62621196bd3fa1a12572 100644 (file)
@@ -1,3 +1,42 @@
+1998-10-27  Marc Horowitz  <marc@mit.edu>
+
+       * Makefile.in, accept_sec_context.c, acquire_cred.c, canon_name.c,
+       delete_sec_context.c, disp_status.c, gssapiP_krb5.h,
+       gssapi_err_krb5.et, gssapi_krb5.c, gssapi_krb5.h,
+       init_sec_context.c, inq_cred.c, inq_names.c, k5seal.c, k5unseal.c,
+       rel_oid.c, ser_sctx.c, util_cksum.c, util_crypt.c, util_seed.c,
+       util_seqnum.c, wrap_size_limit.c: convert to new crypto api.
+       Implement new krb5 v2 gssapi mechanism.
+
+       * add_cred.c, util_ctxsetup.c: New files needed to implement the
+       krb5 v2 mech.
+
+Mon Sep 21 00:32:28 1998  Tom Yu  <tlyu@mit.edu>
+
+       * accept_sec_context.c (krb5_gss_accept_sec_context): Free authdat
+       even on success to avoid a memory leak.
+
+       * util_cksum.c (kg_checksum_channel_bindings): Fix memory leak by
+       not allocating cksum->contents unless we have to return a
+       zero-filled one.
+
+       * k5unseal.c (kg_unseal_v1): Fix memorly leak by not allocating
+       md5cksum.contents.
+
+       * k5seal.c (make_seal_token_v1): Fix memory leak by not allocating
+       md5cksum.contents.
+
+       * accept_sec_context.c (krb5_gss_accept_sec_context): Only free
+       ap_req.data if it was allocated by kg2_parse_token(), otherwise we
+       lose very badly trying to free the middle of a potentially
+       malloc()'ed block, possibly coredumping.
+
+Thu Sep  3 19:35:44 1998  Tom Yu  <tlyu@mit.edu>
+
+       * accept_sec_context.c (krb5_gss_accept_sec_context): Fix typo;
+       bash the enctype in ctx->subkey->enctype rather than just
+       "enctype", which nothing checks.
+
 Fri Jul 24 21:13:53 1998  Tom Yu  <tlyu@mit.edu>
 
        * wrap_size_limit.c (krb5_gss_wrap_size_limit): Fix to round down
index 5b74b81d993af208ba99980d23502c238b9ac557..00b575c34f0b2c010b253b6ff77142730344ad47 100644 (file)
@@ -18,6 +18,7 @@ gssapi_err_krb5.c: gssapi_err_krb5.et
 SRCS = \
        $(srcdir)/accept_sec_context.c \
        $(srcdir)/acquire_cred.c \
+       $(srcdir)/add_cred.c \
        $(srcdir)/canon_name.c \
        $(srcdir)/compare_name.c \
        $(srcdir)/context_time.c \
@@ -50,6 +51,7 @@ SRCS = \
        $(srcdir)/unseal.c \
        $(srcdir)/util_cksum.c \
        $(srcdir)/util_crypt.c \
+       $(srcdir)/util_ctxsetup.c \
        $(srcdir)/util_seed.c \
        $(srcdir)/util_seqnum.c \
        $(srcdir)/val_cred.c \
@@ -63,6 +65,7 @@ SRCS = \
 OBJS = \
        accept_sec_context.$(OBJEXT) \
        acquire_cred.$(OBJEXT) \
+       add_cred.$(OBJEXT) \
        canon_name.$(OBJEXT) \
        compare_name.$(OBJEXT) \
        context_time.$(OBJEXT) \
@@ -95,6 +98,7 @@ OBJS = \
        unseal.$(OBJEXT) \
        util_cksum.$(OBJEXT) \
        util_crypt.$(OBJEXT) \
+       util_ctxsetup.$(OBJEXT) \
        util_seed.$(OBJEXT) \
        util_seqnum.$(OBJEXT) \
        val_cred.$(OBJEXT) \
@@ -108,6 +112,7 @@ OBJS = \
 STLIBOBJS = \
        accept_sec_context.o \
        acquire_cred.o \
+       add_cred.o \
        canon_name.o \
        compare_name.o \
        context_time.o \
@@ -140,6 +145,7 @@ STLIBOBJS = \
        unseal.o \
        util_cksum.o \
        util_crypt.o \
+       util_ctxsetup.o \
        util_seed.o \
        util_seqnum.o \
        val_cred.o \
index ee204d3e0ae6dfd186d7dd2b28db6c37788c3027..90e988ae051a2eb874f8d91fdc0c3a10141e8808 100644 (file)
  * PERFORMANCE OF THIS SOFTWARE.
  */
 
+/*
+ * Copyright (C) 1998 by the FundsXpress, INC.
+ * 
+ * All rights reserved.
+ * 
+ * Export of this software from the United States of America may require
+ * a specific license from the United States Government.  It is the
+ * responsibility of any person or organization contemplating export to
+ * obtain such a license before exporting.
+ * 
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of FundsXpress. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  FundsXpress makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
 #include "k5-int.h"
 #include "gssapiP_krb5.h"
 #include <memory.h>
@@ -58,9 +84,8 @@ rd_req_keyproc(krb5_pointer keyprocarg, krb5_principal server,
 
 /* Decode, decrypt and store the forwarded creds in the local ccache. */
 static krb5_error_code
-rd_and_store_for_creds(context, auth_context, inbuf, out_cred)
+rd_and_store_for_creds(context, inbuf, out_cred)
     krb5_context context;
-    krb5_auth_context auth_context;
     krb5_data *inbuf;
     krb5_gss_cred_id_t *out_cred;
 {
@@ -69,10 +94,16 @@ rd_and_store_for_creds(context, auth_context, inbuf, out_cred)
     krb5_ccache ccache;
     krb5_gss_cred_id_t cred = NULL;
     extern krb5_cc_ops krb5_mcc_ops;
+    krb5_auth_context auth_context = NULL;
 
-    if ((retval = krb5_rd_cred(context, auth_context, inbuf, &creds, NULL))) 
+    if ((retval = krb5_auth_con_init(context, &auth_context)))
        return(retval);
 
+    krb5_auth_con_setflags(context, auth_context, 0);
+
+    if ((retval = krb5_rd_cred(context, auth_context, inbuf, &creds, NULL))) 
+       goto cleanup;
+
     /* Lots of kludging going on here... Some day the ccache interface
        will be rewritten though */
 
@@ -91,47 +122,51 @@ rd_and_store_for_creds(context, auth_context, inbuf, out_cred)
 
     /* generate a delegated credential handle */
     if (out_cred) {
-      /* allocate memory for a cred_t... */
-      if (!(cred =
-           (krb5_gss_cred_id_t) xmalloc(sizeof(krb5_gss_cred_id_rec)))) {
-       retval = ENOMEM; /* out of memory? */
-       goto cleanup;
-      }
+       /* allocate memory for a cred_t... */
+       if (!(cred =
+             (krb5_gss_cred_id_t) xmalloc(sizeof(krb5_gss_cred_id_rec)))) {
+           retval = ENOMEM; /* out of memory? */
+           goto cleanup;
+       }
 
-      /* zero it out... */
-      memset(cred, 0, sizeof(krb5_gss_cred_id_rec));
+       /* zero it out... */
+       memset(cred, 0, sizeof(krb5_gss_cred_id_rec));
 
-      /* copy the client principle into it... */
-      if ((retval =
-          krb5_copy_principal(context, creds[0]->client, &(cred->princ)))) {
-       retval = ENOMEM; /* out of memory? */
-       xfree(cred); /* clean up memory on failure */
-       cred = NULL;
-       goto cleanup;
-      }
-
-      cred->usage = GSS_C_INITIATE; /* we can't accept with this */
-      /* cred->princ already set */
-      cred->actual_mechs = gss_mech_set_krb5_both; /* both mechs work */
-      cred->prerfc_mech = cred->rfc_mech = 1; /* Ibid. */
-      cred->keytab = NULL; /* no keytab associated with this... */
-      cred->ccache = ccache; /* but there is a credential cache */
-      cred->tgt_expire = creds[0]->times.endtime; /* store the end time */
+       /* copy the client principle into it... */
+       if ((retval =
+            krb5_copy_principal(context, creds[0]->client, &(cred->princ)))) {
+           retval = ENOMEM; /* out of memory? */
+           xfree(cred); /* clean up memory on failure */
+           cred = NULL;
+           goto cleanup;
+       }
+
+       cred->usage = GSS_C_INITIATE; /* we can't accept with this */
+       /* cred->princ already set */
+       cred->prerfc_mech = 1; /* this cred will work with all three mechs */
+       cred->rfc_mech = 1;
+       cred->rfcv2_mech = 1; 
+       cred->keytab = NULL; /* no keytab associated with this... */
+       cred->ccache = ccache; /* but there is a credential cache */
+       cred->tgt_expire = creds[0]->times.endtime; /* store the end time */
     }
 
     /* If there were errors, there might have been a memory leak
-    if (!cred)
-      if ((retval = krb5_cc_close(context, ccache)))
-       goto cleanup;
-       */
+       if (!cred)
+       if ((retval = krb5_cc_close(context, ccache)))
+       goto cleanup;
+    */
 cleanup:
     krb5_free_tgt_creds(context, creds);
 
     if (!cred && ccache)
-      (void)krb5_cc_close(context, ccache);
+       (void)krb5_cc_close(context, ccache);
 
     if (out_cred)
-      *out_cred = cred; /* return credential */
+       *out_cred = cred; /* return credential */
+
+    if (auth_context)
+       krb5_auth_con_free(context, auth_context);
 
     return retval;
 }
@@ -158,16 +193,17 @@ krb5_gss_accept_sec_context(minor_status, context_handle,
    unsigned char *ptr, *ptr2;
    char *sptr;
    long tmp;
+   size_t md5len;
    int bigend;
    krb5_gss_cred_id_t cred = 0;
-   krb5_data ap_req;
+   krb5_data ap_rep, ap_req, mic;
    int i;
    krb5_error_code code;
    krb5_address addr, *paddr;
    krb5_authenticator *authdat = 0;
-   krb5_checksum md5;
+   krb5_checksum reqcksum;
    krb5_principal name = NULL;
-   int gss_flags = 0;
+   krb5_ui_4 gss_flags = 0;
    int decode_req_message = 0;
    krb5_gss_ctx_id_rec *ctx = 0;
    krb5_enctype enctype;
@@ -177,14 +213,18 @@ krb5_gss_accept_sec_context(minor_status, context_handle,
    krb5_auth_context auth_context = NULL;
    krb5_ticket * ticket = NULL;
    int option_id;
-   krb5_data option;
-   krb5_auth_context auth_context_cred = NULL;
+   krb5_data option, cksumdata;
    const gss_OID_desc *mech_used = NULL;
    OM_uint32 major_status = GSS_S_FAILURE;
    krb5_error krb_error_data;
    krb5_data scratch;
    gss_cred_id_t cred_handle = NULL;
    krb5_gss_cred_id_t deleg_cred = NULL;
+   int token_length;
+   int gsskrb5_vers;
+   int nctypes;
+   krb5_cksumtype *ctypes;
+   struct kg2_option fwcred;
 
    if (GSS_ERROR(kg_get_context(minor_status, &context)))
       return(GSS_S_FAILURE);
@@ -196,7 +236,11 @@ krb5_gss_accept_sec_context(minor_status, context_handle,
    output_token->length = 0;
    output_token->value = NULL;
    token.value = 0;
-   md5.contents = 0;
+   reqcksum.contents = 0;
+   mic.data = 0;
+   ap_req.data = 0;
+   ap_rep.data = 0;
+   cksumdata.data = 0;
    
    if (mech_type)
       *mech_type = GSS_C_NULL_OID;
@@ -217,18 +261,19 @@ krb5_gss_accept_sec_context(minor_status, context_handle,
 
    /* handle default cred handle */
    if (verifier_cred_handle == GSS_C_NO_CREDENTIAL) {
-          major_status = krb5_gss_acquire_cred(&code, GSS_C_NO_NAME,
-                               GSS_C_INDEFINITE, GSS_C_NO_OID_SET,
-                               GSS_C_ACCEPT, &cred_handle,
-                               NULL, NULL);
-          if (major_status != GSS_S_COMPLETE)
-                  goto fail;
-   } else
-          cred_handle = verifier_cred_handle;
+       major_status = krb5_gss_acquire_cred(&code, GSS_C_NO_NAME,
+                                           GSS_C_INDEFINITE, GSS_C_NO_OID_SET,
+                                           GSS_C_ACCEPT, &cred_handle,
+                                           NULL, NULL);
+       if (major_status != GSS_S_COMPLETE)
+          goto fail;
+   } else {
+       cred_handle = verifier_cred_handle;
+   }
 
-   major_status = krb5_gss_validate_cred(minor_status, verifier_cred_handle);
+   major_status = krb5_gss_validate_cred(&code, verifier_cred_handle);
    if (GSS_ERROR(major_status))
-          goto fail;
+       goto fail;
 
    cred = (krb5_gss_cred_id_t) cred_handle;
 
@@ -236,9 +281,9 @@ krb5_gss_accept_sec_context(minor_status, context_handle,
 
    if ((cred->usage != GSS_C_ACCEPT) &&
        (cred->usage != GSS_C_BOTH)) {
-          code = 0;
-          major_status = GSS_S_NO_CRED;
-          goto fail;
+       code = 0;
+       major_status = GSS_S_NO_CRED;
+       goto fail;
    }
 
    /* verify the token's integrity, and leave the token in ap_req.
@@ -246,60 +291,92 @@ krb5_gss_accept_sec_context(minor_status, context_handle,
 
    ptr = (unsigned char *) input_token->value;
 
-   if ((err = g_verify_token_header((gss_OID) gss_mech_krb5, &(ap_req.length),
-                                   &ptr, KG_TOK_CTX_AP_REQ,
-                                   input_token->length))) {
-       /*
-        * Previous versions of this library used the old mech_id
-        * and some broken behavior (wrong IV on checksum
-        * encryption).  We support the old mech_id for
-        * compatibility, and use it to decide when to use the
-        * old behavior.
-        */
-       if (err != G_WRONG_MECH ||
-           (code = g_verify_token_header((gss_OID) gss_mech_krb5_old,
-                                         &(ap_req.length), 
-                                         &ptr, KG_TOK_CTX_AP_REQ,
-                                         input_token->length))) {
-               major_status = GSS_S_DEFECTIVE_TOKEN;
-               goto fail;
-       } else {
-#if 0       /* Don't restrict mechanisms when accepting contexts */
-            if (! cred->prerfc_mech) {
-                    code = G_WRONG_MECH;
-                    major_status = GSS_S_DEFECTIVE_TOKEN;
-                    goto fail;
-            }
-#endif
-            mech_used = gss_mech_krb5_old;
-       }
+   if (!(code = g_verify_token_header((gss_OID) gss_mech_krb5,
+                                     &(ap_req.length),
+                                     &ptr, KG_TOK_CTX_AP_REQ,
+                                     input_token->length))) {
+       if (! cred->rfc_mech) {
+          code = G_WRONG_MECH;
+          major_status = GSS_S_DEFECTIVE_TOKEN;
+          goto fail;
+       }
+       mech_used = gss_mech_krb5;
+       gsskrb5_vers = 1000;
+   } else if ((code == G_WRONG_MECH) &&
+             !(code = g_verify_token_header((gss_OID) gss_mech_krb5_old,
+                                            &(ap_req.length), 
+                                            &ptr, KG_TOK_CTX_AP_REQ,
+                                            input_token->length))) {
+       /*
+       * Previous versions of this library used the old mech_id
+       * and some broken behavior (wrong IV on checksum
+       * encryption).  We support the old mech_id for
+       * compatibility, and use it to decide when to use the
+       * old behavior.
+       */
+       if (! cred->prerfc_mech) {
+          code = G_WRONG_MECH;
+          major_status = GSS_S_DEFECTIVE_TOKEN;
+          goto fail;
+       }
+       mech_used = gss_mech_krb5_old;
+       gsskrb5_vers = 1000;
+   } else if ((code == G_WRONG_MECH) &&
+             !(code = g_verify_token_header((gss_OID) gss_mech_krb5_v2,
+                                            &token_length, 
+                                            &ptr, KG2_TOK_INITIAL,
+                                            input_token->length))) {
+       if (! cred->rfcv2_mech) {
+          code = G_WRONG_MECH;
+          major_status = GSS_S_DEFECTIVE_TOKEN;
+          goto fail;
+       }
+       mech_used = gss_mech_krb5_v2;
+       gsskrb5_vers = 2000;
    } else {
-#if 0  /* Don't restrict mechanisms when accepting contexts */
-       if (! cred->rfc_mech) {
-               code = G_WRONG_MECH;
-               major_status = GSS_S_DEFECTIVE_TOKEN;
-               goto fail;
-       }
-#endif
-       mech_used = gss_mech_krb5;
+       major_status = GSS_S_DEFECTIVE_TOKEN;
+       goto fail;
    }
 
-   sptr = (char *) ptr;
-   TREAD_STR(sptr, ap_req.data, ap_req.length);
-   decode_req_message = 1;
+   if (gsskrb5_vers == 2000) {
+       /* gss krb5 v2 */
+
+       fwcred.option_id = KRB5_GSS_FOR_CREDS_OPTION;
+       fwcred.data = NULL;
+
+       if (GSS_ERROR(major_status =
+                    kg2_parse_token(&code, ptr, token_length,
+                                    &gss_flags, &nctypes, &ctypes,
+                                    delegated_cred_handle?1:0,
+                                    &fwcred, &ap_req, NULL))) {
+          goto fail;
+       }
+
+       gss_flags = (ptr[0]<<24) | (ptr[1]<<16) | (ptr[2]<<8) | ptr[3];
+
+       gss_flags &= ~GSS_C_DELEG_FLAG; /* mask out the delegation flag;
+                                         if there's a delegation, we'll
+                                         set it below */
+   } else {
+       /* gss krb5 v1 */
+
+       sptr = (char *) ptr;
+       TREAD_STR(sptr, ap_req.data, ap_req.length);
+       decode_req_message = 1;
+   }
 
    /* construct the sender_addr */
 
    if ((input_chan_bindings != GSS_C_NO_CHANNEL_BINDINGS) &&
        (input_chan_bindings->initiator_addrtype == GSS_C_AF_INET)) {
-      /* XXX is this right? */
-      addr.addrtype = ADDRTYPE_INET;
-      addr.length = input_chan_bindings->initiator_address.length;
-      addr.contents = input_chan_bindings->initiator_address.value;
+       /* XXX is this right? */
+       addr.addrtype = ADDRTYPE_INET;
+       addr.length = input_chan_bindings->initiator_address.length;
+       addr.contents = input_chan_bindings->initiator_address.value;
 
-      paddr = &addr;
+       paddr = &addr;
    } else {
-      paddr = NULL;
+       paddr = NULL;
    }
 
    /* decode the AP_REQ message */
@@ -307,13 +384,18 @@ krb5_gss_accept_sec_context(minor_status, context_handle,
    /* decode the message */
 
    if ((code = krb5_auth_con_init(context, &auth_context))) {
-       *minor_status = code;
-       return(GSS_S_FAILURE);
+       major_status = GSS_S_FAILURE;
+       goto fail;
    }
    if ((code = krb5_auth_con_setrcache(context, auth_context, cred->rcache))) {
-       *minor_status = code;
-       return(GSS_S_FAILURE);
+       major_status = GSS_S_FAILURE;
+       goto fail;
    }
+   if ((code = krb5_auth_con_setaddrs(context, auth_context, NULL, paddr))) {
+       major_status = GSS_S_FAILURE;
+       goto fail;
+   }
+
    if ((code = krb5_rd_req(context, &auth_context, &ap_req, cred->princ,
                           cred->keytab, NULL, &ticket))) {
        major_status = GSS_S_FAILURE;
@@ -328,137 +410,142 @@ krb5_gss_accept_sec_context(minor_status, context_handle,
    if ((authdat->authenticator->subkey == NULL) ||
        (authdat->ticket->enc_part2 == NULL)) {
           code = KG_NO_SUBKEY;
+          major_status = GSS_S_FAILURE;
           goto fail;
    }
 #endif
 
-   /* verify that the checksum is correct */
+   if (gsskrb5_vers == 2000) {
+       bigend = 1;
+   } else {
+       /* gss krb5 v1 */
 
-   /*
-      The checksum may be either exactly 24 bytes, in which case
-      no options are specified, or greater than 24 bytes, in which case
-      one or more options are specified. Currently, the only valid
-      option is KRB5_GSS_FOR_CREDS_OPTION ( = 1 ).
-   */
-
-   if ((authdat->checksum->checksum_type != CKSUMTYPE_KG_CB) ||
-       (authdat->checksum->length < 24)) {
-          code = 0;
-          major_status = GSS_S_BAD_BINDINGS;
+       /* stash this now, for later. */
+       if (code = krb5_c_checksum_length(context, CKSUMTYPE_RSA_MD5,
+                                        &md5len)) {
+          major_status = GSS_S_FAILURE;
           goto fail;
-   }
+       }
 
-   /*
-      "Be liberal in what you accept, and
-       conservative in what you send"
-               -- rfc1123
+       /* verify that the checksum is correct */
 
-       This code will let this acceptor interoperate with an initiator
-       using little-endian or big-endian integer encoding.
-   */
+       /*
+        The checksum may be either exactly 24 bytes, in which case
+        no options are specified, or greater than 24 bytes, in which case
+        one or more options are specified. Currently, the only valid
+        option is KRB5_GSS_FOR_CREDS_OPTION ( = 1 ).
+       */
+
+       if ((authdat->checksum->checksum_type != CKSUMTYPE_KG_CB) ||
+          (authdat->checksum->length < 24)) {
+          code = 0;
+          major_status = GSS_S_BAD_BINDINGS;
+          goto fail;
+       }
 
-   ptr = (unsigned char *) authdat->checksum->contents;
-   bigend = 0;
+       /*
+        "Be liberal in what you accept, and
+        conservative in what you send"
+        -- rfc1123
 
-   TREAD_INT(ptr, tmp, bigend);
+        This code will let this acceptor interoperate with an initiator
+        using little-endian or big-endian integer encoding.
+       */
 
-   if (tmp != krb5_checksum_size(context, CKSUMTYPE_RSA_MD5)) {
        ptr = (unsigned char *) authdat->checksum->contents;
-       bigend = 1;
+       bigend = 0;
 
        TREAD_INT(ptr, tmp, bigend);
 
-       if (tmp != krb5_checksum_size(context, CKSUMTYPE_RSA_MD5)) {
-          major_status = GSS_S_FAILURE;
-          code = KG_BAD_LENGTH;
-          goto fail;
+       if (tmp != md5len) {
+          ptr = (unsigned char *) authdat->checksum->contents;
+          bigend = 1;
+
+          TREAD_INT(ptr, tmp, bigend);
+
+          if (tmp != md5len) {
+              code = KG_BAD_LENGTH;
+              major_status = GSS_S_FAILURE;
+              goto fail;
+          }
        }
-   }
 
-   /* at this point, bigend is set according to the initiator's byte order */
+       /* at this point, bigend is set according to the initiator's
+         byte order */
 
-   if ((code = kg_checksum_channel_bindings(context, input_chan_bindings, &md5,
-                                           bigend))) {
-       major_status = GSS_S_BAD_BINDINGS;
-       goto fail;
-   }
+       if ((code = kg_checksum_channel_bindings(context, input_chan_bindings,
+                                               &reqcksum, bigend))) {
+          major_status = GSS_S_BAD_BINDINGS;
+          goto fail;
+       }
 
-   TREAD_STR(ptr, ptr2, md5.length);
-   if (memcmp(ptr2, md5.contents, md5.length) != 0) {
+       TREAD_STR(ptr, ptr2, reqcksum.length);
+       if (memcmp(ptr2, reqcksum.contents, reqcksum.length) != 0) {
           code = 0;
           major_status = GSS_S_BAD_BINDINGS;
           goto fail;
-   }
-
-   xfree(md5.contents);
-   md5.contents = 0;
-
-   TREAD_INT(ptr, gss_flags, bigend);
-   gss_flags &= ~GSS_C_DELEG_FLAG; /* mask out the delegation flag; if there's
-                                     a delegation, we'll set it below */
-   decode_req_message = 0;
-
-   /* if the checksum length > 24, there are options to process */
+       }
 
-   if(authdat->checksum->length > 24) {
+       xfree(reqcksum.contents);
+       reqcksum.contents = 0;
 
-       i = authdat->checksum->length - 24;
+       TREAD_INT(ptr, gss_flags, bigend);
+       gss_flags &= ~GSS_C_DELEG_FLAG; /* mask out the delegation flag; if
+                                         there's a delegation, we'll set
+                                         it below */
+       decode_req_message = 0;
 
-       while(i>0) {
+       /* if the checksum length > 24, there are options to process */
 
-           TREAD_INT16(ptr, option_id, bigend);
+       if(authdat->checksum->length > 24) {
 
-           switch(option_id) {
+          i = authdat->checksum->length - 24;
 
-               case KRB5_GSS_FOR_CREDS_OPTION:
+          while(i>0) {
 
-                   TREAD_INT16(ptr, option.length, bigend);
+              TREAD_INT16(ptr, option_id, bigend);
 
-                   /* have to use ptr2, since option.data is wrong type and
-                      macro uses ptr as both lvalue and rvalue */
+              switch(option_id) {
 
-                   TREAD_STR(ptr, ptr2, bigend);
-                   option.data = (char FAR *) ptr2;
+              case KRB5_GSS_FOR_CREDS_OPTION:
 
-                   /* get a temporary auth_context structure for the
-                      call to rd_and_store_for_creds() and clear its flags */
+                  TREAD_INT16(ptr, option.length, bigend);
 
-                   if ((code = krb5_auth_con_init(context,
-                                                  &auth_context_cred))) {
-                       major_status = GSS_S_FAILURE;
-                       goto fail;
-                   }
+                  /* have to use ptr2, since option.data is wrong type and
+                     macro uses ptr as both lvalue and rvalue */
 
-                   krb5_auth_con_setflags(context, auth_context_cred, 0);
+                  TREAD_STR(ptr, ptr2, bigend);
+                  option.data = (char FAR *) ptr2;
 
-                   /* store the delegated credential */
+                  /* store the delegated credential */
 
-                   rd_and_store_for_creds(context, auth_context_cred,
-                                          &option,
-                                          (delegated_cred_handle) ?
-                                          &deleg_cred : NULL);
+                  if (code = rd_and_store_for_creds(context, &option,
+                                                    (delegated_cred_handle) ?
+                                                    &deleg_cred : NULL)) {
+                      major_status = GSS_S_FAILURE;
+                      goto fail;
+                  }
 
-                   i -= option.length + 4;
+                  i -= option.length + 4;
 
-                   krb5_auth_con_free(context, auth_context_cred);
+                  gss_flags |= GSS_C_DELEG_FLAG; /* got a delegation */
 
-                   gss_flags |= GSS_C_DELEG_FLAG; /* got a delegation */
+                  break;
 
-                   break;
+                  /* default: */
+                  /* unknown options aren't an error */
 
-                   /* default: */
-                   /* unknown options aren't an error */
+              } /* switch */
+          } /* while */
+       } /* if */
+   }
 
-           } /* switch */
-       } /* while */
-    } /* if */
-                       
    /* create the ctx struct and start filling it in */
 
    if ((ctx = (krb5_gss_ctx_id_rec *) xmalloc(sizeof(krb5_gss_ctx_id_rec)))
        == NULL) {
-       major_status = GSS_S_FAILURE;
        code = ENOMEM;
+       major_status = GSS_S_FAILURE;
        goto fail;
    }
 
@@ -469,83 +556,177 @@ krb5_gss_accept_sec_context(minor_status, context_handle,
    ctx->gss_flags = KG_IMPLFLAGS(gss_flags);
    ctx->seed_init = 0;
    ctx->big_endian = bigend;
-
-   major_status = GSS_S_FAILURE;
+   ctx->gsskrb5_version = gsskrb5_vers;
 
    /* Intern the ctx pointer so that delete_sec_context works */
    if (! kg_save_ctx_id((gss_ctx_id_t) ctx)) {
-          code = G_VALIDATE_FAILED;
-          xfree(ctx);
-          ctx = 0;
-          goto fail;
+       xfree(ctx);
+       ctx = 0;
+
+       code = G_VALIDATE_FAILED;
+       major_status = GSS_S_FAILURE;
+       goto fail;
    }
-   
-   if ((code = krb5_copy_principal(context, cred->princ, &ctx->here)))
-          goto fail;
 
-   if ((code = krb5_copy_principal(context, authdat->client, &ctx->there)))
-          goto fail;
+   if ((code = krb5_copy_principal(context, cred->princ, &ctx->here))) {
+       major_status = GSS_S_FAILURE;
+       goto fail;
+   }
 
-   /* done with authdat */
-   krb5_free_authenticator(context, authdat);
-   authdat = 0;
+   if ((code = krb5_copy_principal(context, authdat->client, &ctx->there))) {
+       major_status = GSS_S_FAILURE;
+       goto fail;
+   }
 
    if ((code = krb5_auth_con_getremotesubkey(context, auth_context,
-                                            &ctx->subkey)))
-          goto fail;
+                                            &ctx->subkey))) { 
+       major_status = GSS_S_FAILURE;      
+       goto fail;
+   }
 
    /* use the session key if the subkey isn't present */
 
    if (ctx->subkey == NULL) {
        if ((code = krb5_auth_con_getkey(context, auth_context,
-                                       &ctx->subkey)))
-              goto fail;
+                                       &ctx->subkey))) {
+          major_status = GSS_S_FAILURE;
+          goto fail;
+       }
    }
 
    if (ctx->subkey == NULL) {
        /* this isn't a very good error, but it's not clear to me this
          can actually happen */
+       major_status = GSS_S_FAILURE;
        code = KRB5KDC_ERR_NULL_KEY;
        goto fail;
    }
 
-   switch(ctx->subkey->enctype) {
-   case ENCTYPE_DES_CBC_MD5:
-   case ENCTYPE_DES_CBC_CRC:
-       enctype = ENCTYPE_DES_CBC_RAW;
-       ctx->signalg = 0;
-       ctx->cksum_size = 8;
-       ctx->sealalg = 0;
-       break;
+   if (gsskrb5_vers == 2000) {
+       int cblen;
+       krb5_boolean valid;
+
+       /* intersect the token ctypes with the local ctypes */
+
+       if (code = krb5_c_keyed_checksum_types(context, ctx->subkey->enctype,
+                                             &ctx->nctypes, &ctx->ctypes))
+          goto fail;
+
+       if (nctypes == 0) {
+          code = KRB5_CRYPTO_INTERNAL;
+          goto fail;
+       }
+
+       kg2_intersect_ctypes(&ctx->nctypes, ctx->ctypes, nctypes, ctypes);
+
+       if (nctypes == 0) {
+          code = KG_NO_CTYPES;
+          goto fail;
+       }
+
+       /* process the delegated cred, if any */
+
+       if (fwcred.data) {
+          krb5_data option;
+
+          option.length = fwcred.length;
+          option.data = fwcred.data;
+
+          if (code = rd_and_store_for_creds(context, &option, &deleg_cred)) {
+              major_status = GSS_S_FAILURE;
+              goto fail;
+          }
+
+          gss_flags |= GSS_C_DELEG_FLAG; /* got a delegation */
+       }
+
+       /* construct the checksum buffer */
+
+       cblen = 4*5;
+       if (input_chan_bindings)
+          cblen += (input_chan_bindings->initiator_address.length+
+                    input_chan_bindings->acceptor_address.length+
+                    input_chan_bindings->application_data.length);
+
+       cksumdata.length = cblen + ((char *)(ap_req.data-2) - (char *)(ptr-2));
+
+       if ((cksumdata.data = (char *) malloc(cksumdata.length)) == NULL) {
+          code = ENOMEM;
+          major_status = GSS_S_FAILURE;
+          goto fail;
+       }
+
+       ptr2 = cksumdata.data;
+
+       if (input_chan_bindings) {
+          TWRITE_INT(ptr2, input_chan_bindings->initiator_addrtype, 1);
+          TWRITE_BUF(ptr2, input_chan_bindings->initiator_address, 1);
+          TWRITE_INT(ptr2, input_chan_bindings->acceptor_addrtype, 1);
+          TWRITE_BUF(ptr2, input_chan_bindings->acceptor_address, 1);
+          TWRITE_BUF(ptr2, input_chan_bindings->application_data, 1);
+       } else {
+          memset(ptr2, 0, cblen);
+          ptr2 += cblen;
+       }
+
+       memcpy(ptr2, ptr-2, ((char *)(ap_req.data-2) - (char *)(ptr-2)));
+
+       if (code = krb5_c_verify_checksum(context, ctx->subkey,
+                                        KRB5_KEYUSAGE_AP_REQ_AUTH_CKSUM,
+                                        &cksumdata, authdat->checksum,
+                                        &valid)) {
+          major_status = GSS_S_FAILURE;
+          goto fail;
+       }
+
+       free(cksumdata.data);
+       cksumdata.data = 0;
+
+       if (!valid) {
+          code = 0;
+          major_status = GSS_S_BAD_SIG;
+          goto fail;
+       }
+   } else {
+       /* gss krb5 v1 */
+
+       switch(ctx->subkey->enctype) {
+       case ENCTYPE_DES_CBC_MD5:
+       case ENCTYPE_DES_CBC_CRC:
+          ctx->subkey->enctype = ENCTYPE_DES_CBC_RAW;
+          ctx->signalg = 0;
+          ctx->cksum_size = 8;
+          ctx->sealalg = 0;
+          break;
 #if 0
-   case ENCTYPE_DES3_CBC_MD5:
-       enctype = ENCTYPE_DES3_CBC_RAW;
-       ctx->signalg = 3;
-       ctx->cksum_size = 16;
-       ctx->sealalg = 1;
-       break;
+       case ENCTYPE_DES3_CBC_MD5:
+          enctype = ENCTYPE_DES3_CBC_RAW;
+          ctx->signalg = 3;
+          ctx->cksum_size = 16;
+          ctx->sealalg = 1;
+          break;
 #endif
-   default:
-       code = KRB5_BAD_ENCTYPE;
-       goto fail;
-   }
-
-   /* fill in the encryption descriptors */
+       default:
+          code = KRB5_BAD_ENCTYPE;
+          goto fail;
+       }
 
-   krb5_use_enctype(context, &ctx->enc.eblock, enctype);
-   ctx->enc.processed = 0;
+       /* fill in the encryption descriptors */
 
-   if ((code = krb5_copy_keyblock(context, ctx->subkey, &ctx->enc.key)))
+       if ((code = krb5_copy_keyblock(context, ctx->subkey, &ctx->enc))) {
+          major_status = GSS_S_FAILURE;
           goto fail;
+       }
 
-   for (i=0; i<ctx->enc.key->length; i++)
-      /*SUPPRESS 113*/
-      ctx->enc.key->contents[i] ^= 0xf0;
+       for (i=0; i<ctx->enc->length; i++)
+          /*SUPPRESS 113*/
+          ctx->enc->contents[i] ^= 0xf0;
 
-   krb5_use_enctype(context, &ctx->seq.eblock, enctype);
-   ctx->seq.processed = 0;
-   if ((code = krb5_copy_keyblock(context, ctx->subkey, &ctx->seq.key)))
+       if ((code = krb5_copy_keyblock(context, ctx->subkey, &ctx->seq))) {
+          major_status = GSS_S_FAILURE;
           goto fail;
+       }
+   }
 
    ctx->endtime = ticket->enc_part2->times.endtime;
    ctx->krb_flags = ticket->enc_part2->flags;
@@ -554,13 +735,15 @@ krb5_gss_accept_sec_context(minor_status, context_handle,
 
    krb5_auth_con_getremoteseqnumber(context, auth_context, &ctx->seq_recv);
 
-   if ((code = krb5_timeofday(context, &now)))
-          goto fail;
+   if ((code = krb5_timeofday(context, &now))) {
+       major_status = GSS_S_FAILURE;
+       goto fail;
+   }
 
    if (ctx->endtime < now) {
-          code = 0;
-          major_status = GSS_S_CREDENTIALS_EXPIRED;
-          goto fail;
+       code = 0;
+       major_status = GSS_S_CREDENTIALS_EXPIRED;
+       goto fail;
    }
 
    g_order_init(&(ctx->seqstate), ctx->seq_recv,
@@ -573,40 +756,156 @@ krb5_gss_accept_sec_context(minor_status, context_handle,
    /* generate an AP_REP if necessary */
 
    if (ctx->gss_flags & GSS_C_MUTUAL_FLAG) {
-      krb5_data ap_rep;
-      unsigned char * ptr;
-      if ((code = krb5_mk_rep(context, auth_context, &ap_rep)))
-             goto fail;
-
-      krb5_auth_con_getlocalseqnumber(context, auth_context, &ctx->seq_send);
-      token.length = g_token_size((gss_OID) mech_used, ap_rep.length);
-
-      if ((token.value = (unsigned char *) xmalloc(token.length)) == NULL) {
-             code = ENOMEM;
-             goto fail;
-      }
-      ptr = token.value;
-      g_make_token_header((gss_OID) mech_used, ap_rep.length,
-                         &ptr, KG_TOK_CTX_AP_REP);
-
-      TWRITE_STR(ptr, ap_rep.data, ap_rep.length);
-      xfree(ap_rep.data);
+       unsigned char * ptr;
+       if ((code = krb5_mk_rep(context, auth_context, &ap_rep))) {
+          major_status = GSS_S_FAILURE;
+          goto fail;
+       }
+
+       krb5_auth_con_getlocalseqnumber(context, auth_context,
+                                      &ctx->seq_send);
+
+       /* the reply token hasn't been sent yet, but that's ok. */
+       ctx->established = 1;
+
+       if (ctx->gsskrb5_version == 2000) {
+          krb5_ui_4 tok_flags;
+
+          tok_flags =
+              (ctx->gss_flags & GSS_C_DELEG_FLAG)?KG2_RESP_FLAG_DELEG_OK:0;
+
+          cksumdata.length = 8 + 4*ctx->nctypes + 4;
+
+          if ((cksumdata.data = (char *) malloc(cksumdata.length)) == NULL) {
+              code = ENOMEM;
+              major_status = GSS_S_FAILURE;
+              goto fail;
+          }
+
+          /* construct the token fields */
+
+          ptr = cksumdata.data;
+
+          ptr[0] = (KG2_TOK_RESPONSE >> 8) & 0xff;
+          ptr[1] = KG2_TOK_RESPONSE & 0xff;
+
+          ptr[2] = (tok_flags >> 24) & 0xff;
+          ptr[3] = (tok_flags >> 16) & 0xff;
+          ptr[4] = (tok_flags >> 8) & 0xff;
+          ptr[5] = tok_flags & 0xff;
+
+          ptr[6] = (ctx->nctypes >> 8) & 0xff;
+          ptr[7] = ctx->nctypes & 0xff;
+
+          ptr += 8;
+
+          for (i=0; i<ctx->nctypes; i++) {
+              ptr[i] = (ctx->ctypes[i] >> 24) & 0xff;
+              ptr[i+1] = (ctx->ctypes[i] >> 16) & 0xff;
+              ptr[i+2] = (ctx->ctypes[i] >> 8) & 0xff;
+              ptr[i+3] = ctx->ctypes[i] & 0xff;
+
+              ptr += 4;
+          }
+
+          memset(ptr, 0, 4);
+
+          /* make the MIC token */
+
+          {
+              gss_buffer_desc text, token;
+
+              text.length = cksumdata.length;
+              text.value = cksumdata.data;
+
+              /* ctx->seq_send must be set before this call */
+
+              if (GSS_ERROR(major_status =
+                            krb5_gss_get_mic(&code, ctx,
+                                             GSS_C_QOP_DEFAULT,
+                                             &text, &token)))
+                  goto fail;
+
+              mic.length = token.length;
+              mic.data = token.value;
+          }
+
+          token.length = g_token_size((gss_OID) mech_used,
+                                      (cksumdata.length-2)+4+ap_rep.length+
+                                      mic.length);
+
+          if ((token.value = (unsigned char *) xmalloc(token.length))
+              == NULL) {
+              code = ENOMEM;
+              major_status = GSS_S_FAILURE;
+              goto fail;
+          }
+          ptr = token.value;
+          g_make_token_header((gss_OID) mech_used,
+                              (cksumdata.length-2)+4+ap_rep.length+mic.length,
+                              &ptr, KG2_TOK_RESPONSE);
+
+          memcpy(ptr, cksumdata.data+2, cksumdata.length-2);
+          ptr += cksumdata.length-2;
+
+          ptr[0] = (ap_rep.length >> 8) & 0xff;
+          ptr[1] = ap_rep.length & 0xff;
+          memcpy(ptr+2, ap_rep.data, ap_rep.length);
+
+          ptr += (2+ap_rep.length);
+
+          ptr[0] = (mic.length >> 8) & 0xff;
+          ptr[1] = mic.length & 0xff;
+          memcpy(ptr+2, mic.data, mic.length);
+
+          ptr += (2+mic.length);
+
+          free(cksumdata.data);
+          cksumdata.data = 0;
+
+          /* gss krb5 v2 */
+       } else {
+          /* gss krb5 v1 */
+
+          token.length = g_token_size((gss_OID) mech_used, ap_rep.length);
+
+          if ((token.value = (unsigned char *) xmalloc(token.length))
+              == NULL) {
+              major_status = GSS_S_FAILURE;
+              code = ENOMEM;
+              goto fail;
+          }
+          ptr = token.value;
+          g_make_token_header((gss_OID) mech_used, ap_rep.length,
+                              &ptr, KG_TOK_CTX_AP_REP);
+
+          TWRITE_STR(ptr, ap_rep.data, ap_rep.length);
+          xfree(ap_rep.data);
+
+          ctx->established = 1;
+
+       }
    } else {
-      token.length = 0;
-      token.value = NULL;
-      ctx->seq_send = ctx->seq_recv;
+       token.length = 0;
+       token.value = NULL;
+       ctx->seq_send = ctx->seq_recv;
+
+       ctx->established = 1;
    }
 
    /* set the return arguments */
 
    if (src_name) {
-      if ((code = krb5_copy_principal(context, ctx->there, &name)))
-             goto fail;
-      /* intern the src_name */
-      if (! kg_save_name((gss_name_t) name)) {
-             code = G_VALIDATE_FAILED;
-             goto fail;
-      }
+       if ((code = krb5_copy_principal(context, ctx->there, &name))) {
+          major_status = GSS_S_FAILURE;
+          goto fail;
+       }
+       /* intern the src_name */
+       if (! kg_save_name((gss_name_t) name)) {
+          code = G_VALIDATE_FAILED;
+          major_status = GSS_S_FAILURE;
+          goto fail;
+       }
    }
 
    if (mech_type)
@@ -618,7 +917,6 @@ krb5_gss_accept_sec_context(minor_status, context_handle,
    if (ret_flags)
       *ret_flags = ctx->gss_flags;
 
-   ctx->established = 1;
    *context_handle = ctx;
    *output_token = token;
 
@@ -626,39 +924,54 @@ krb5_gss_accept_sec_context(minor_status, context_handle,
       *src_name = (gss_name_t) name;
 
    if (delegated_cred_handle && deleg_cred) {
-     if (!kg_save_cred_id((gss_cred_id_t) deleg_cred)) {
-       code = G_VALIDATE_FAILED;
-       goto fail;
-     }
+       if (!kg_save_cred_id((gss_cred_id_t) deleg_cred)) {
+          major_status = GSS_S_FAILURE;
+          code = G_VALIDATE_FAILED;
+          goto fail;
+       }
 
-     *delegated_cred_handle = (gss_cred_id_t) deleg_cred;
+       *delegated_cred_handle = (gss_cred_id_t) deleg_cred;
    }
 
    /* finally! */
 
    *minor_status = 0;
-   return(GSS_S_COMPLETE);
+   major_status = GSS_S_COMPLETE;
 
-fail:
+ fail:
+   if (ctypes)
+       free(ctypes);
    if (authdat)
-          krb5_free_authenticator(context, authdat);
+       krb5_free_authenticator(context, authdat);
+   if (reqcksum.contents)
+       xfree(reqcksum.contents);
+   if (ap_rep.data)
+       xfree(ap_rep.data);
+   if (mic.data)
+       xfree(mic.data);
+   if (cksumdata.data)
+       xfree(cksumdata.data);
+
+   if (!GSS_ERROR(major_status))
+       return(major_status);
+
+   /* from here on is the real "fail" code */
+
    if (ctx)
-          (void) krb5_gss_delete_sec_context(minor_status, 
-                                             (gss_ctx_id_t *) &ctx, NULL);
+       (void) krb5_gss_delete_sec_context(minor_status, 
+                                         (gss_ctx_id_t *) &ctx, NULL);
+   if (deleg_cred) { /* free memory associated with the deleg credential */
+       if (deleg_cred->ccache)
+          (void)krb5_cc_close(context, deleg_cred->ccache);
+       if (deleg_cred->princ)
+          krb5_free_principal(context, deleg_cred->princ);
+       xfree(deleg_cred);
+   }
    if (token.value)
-          xfree(token.value);
+       xfree(token.value);
    if (name) {
-        (void) kg_delete_name((gss_name_t) name);
-        krb5_free_principal(context, name);
-   }
-   if (md5.contents)
-        xfree(md5.contents);
-   if (deleg_cred) { /* free memory associated with the deleg credential */
-     if (deleg_cred->ccache)
-       (void)krb5_cc_close(context, deleg_cred->ccache);
-     if (deleg_cred->princ)
-       krb5_free_principal(context, deleg_cred->princ);
-     xfree(deleg_cred);
+       (void) kg_delete_name((gss_name_t) name);
+       krb5_free_principal(context, name);
    }
 
    *minor_status = code;
@@ -670,48 +983,75 @@ fail:
     * decode the authenticator to read out the gss_flags field.
     */
    if (decode_req_message) {
-          krb5_ap_req  * request;
+       krb5_ap_req     * request;
           
-          if (decode_krb5_ap_req(&ap_req, &request))
-                  return (major_status);
-          if (request->ap_options & AP_OPTS_MUTUAL_REQUIRED)
-                  gss_flags |= GSS_C_MUTUAL_FLAG;
-          krb5_free_ap_req(context, request);
+       if (decode_krb5_ap_req(&ap_req, &request))
+          return (major_status);
+       if (request->ap_options & AP_OPTS_MUTUAL_REQUIRED)
+          gss_flags |= GSS_C_MUTUAL_FLAG;
+       krb5_free_ap_req(context, request);
    }
 
    if (cred && (gss_flags & GSS_C_MUTUAL_FLAG)) {
-          /*
-           * The client is expecting a response, so we can send an
-           * error token back
-           */
-          memset(&krb_error_data, 0, sizeof(krb_error_data));
-
-          code  -= ERROR_TABLE_BASE_krb5;
-          if (code < 0 || code > 128)
-                  code = 60 /* KRB_ERR_GENERIC */;
-
-          krb_error_data.error = code;
-          (void) krb5_us_timeofday(context, &krb_error_data.stime,
-                                   &krb_error_data.susec);
-          krb_error_data.server = cred->princ;
+       int tmsglen, toktype;
+
+       /*
+       * The client is expecting a response, so we can send an
+       * error token back
+       */
+       memset(&krb_error_data, 0, sizeof(krb_error_data));
+
+       code  -= ERROR_TABLE_BASE_krb5;
+       if (code < 0 || code > 128)
+          code = 60 /* KRB_ERR_GENERIC */;
+
+       krb_error_data.error = code;
+       (void) krb5_us_timeofday(context, &krb_error_data.stime,
+                               &krb_error_data.susec);
+       krb_error_data.server = cred->princ;
           
-          code = krb5_mk_error(context, &krb_error_data, &scratch);
-          if (code)
-                  return (major_status);
+       code = krb5_mk_error(context, &krb_error_data, &scratch);
+       if (code)
+          return (major_status);
+
+       if (gsskrb5_vers == 2000) {
+          tmsglen = 12+scratch.length;
+          toktype = KG2_TOK_RESPONSE;
+       } else {
+          tmsglen = scratch.length;
+          toktype = KG_TOK_CTX_ERROR;
+       }
 
-          token.length = g_token_size((gss_OID) mech_used, scratch.length);
-          token.value = (unsigned char *) xmalloc(token.length);
-          if (!token.value)
-                  return (major_status);
+       token.length = g_token_size((gss_OID) mech_used, tmsglen);
+       token.value = (unsigned char *) xmalloc(token.length);
+       if (!token.value)
+          return (major_status);
 
-          ptr = token.value;
-          g_make_token_header((gss_OID) mech_used, scratch.length,
-                              &ptr, KG_TOK_CTX_ERROR);
+       ptr = token.value;
+       g_make_token_header((gss_OID) mech_used, tmsglen, &ptr, toktype);
+
+       if (gsskrb5_vers == 2000) {
+          krb5_ui_4 flags;
+
+          flags = KG2_RESP_FLAG_ERROR;
+
+          ptr[0] = (flags << 24) & 0xff;
+          ptr[1] = (flags << 16) & 0xff;
+          ptr[2] = (flags << 8) & 0xff;
+          ptr[3] = flags & 0xff;
+
+          memset(ptr+4, 0, 6);
+
+          ptr[10] = (scratch.length << 8) & 0xff;
+          ptr[11] = scratch.length & 0xff;
+
+          ptr += 12;
+       }
 
-          TWRITE_STR(ptr, scratch.data, scratch.length);
-          xfree(scratch.data);
+       TWRITE_STR(ptr, scratch.data, scratch.length);
+       xfree(scratch.data);
 
-          *output_token = token;
+       *output_token = token;
    }
    if (!verifier_cred_handle && cred_handle) {
           krb5_gss_release_cred(&code, cred_handle);
index 1ca1bf31a7dfa2a693d7349b4a13bdb192d4c314..f968b7d4f6ede17eb4eeae24c9919d22aeab6c8a 100644 (file)
  * PERFORMANCE OF THIS SOFTWARE.
  */
 
+/*
+ * Copyright (C) 1998 by the FundsXpress, INC.
+ * 
+ * All rights reserved.
+ * 
+ * Export of this software from the United States of America may require
+ * a specific license from the United States Government.  It is the
+ * responsibility of any person or organization contemplating export to
+ * obtain such a license before exporting.
+ * 
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of FundsXpress. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  FundsXpress makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
 #include "gssapiP_krb5.h"
 #ifdef HAVE_STRING_H
 #include <string.h>
@@ -248,8 +274,7 @@ krb5_gss_acquire_cred(minor_status, desired_name, time_req,
    size_t i;
    krb5_gss_cred_id_t cred;
    gss_OID_set ret_mechs;
-   const gss_OID_set_desc FAR * valid_mechs;
-   int req_old, req_new;
+   int req_old, req_new, req_v2;
    OM_uint32 ret;
    krb5_error_code code;
 
@@ -277,27 +302,24 @@ krb5_gss_acquire_cred(minor_status, desired_name, time_req,
       contains krb5 */
 
    if (desired_mechs == GSS_C_NULL_OID_SET) {
-      valid_mechs = gss_mech_set_krb5_both;
       req_old = 1;
       req_new = 1;
+      req_v2 = 1;
    } else {
       req_old = 0;
       req_new = 0;
+      req_v2 = 0;
 
       for (i=0; i<desired_mechs->count; i++) {
         if (g_OID_equal(gss_mech_krb5_old, &(desired_mechs->elements[i])))
            req_old++;
         if (g_OID_equal(gss_mech_krb5, &(desired_mechs->elements[i])))
            req_new++;
+        if (g_OID_equal(gss_mech_krb5_v2, &(desired_mechs->elements[i])))
+           req_v2++;
       }
 
-      if (req_old && req_new) {
-        valid_mechs = gss_mech_set_krb5_both;
-      } else if (req_old) {
-        valid_mechs = gss_mech_set_krb5_old;
-      } else if (req_new) {
-        valid_mechs = gss_mech_set_krb5;
-      } else {
+      if (!req_old && !req_new && !req_v2) {
         *minor_status = 0;
         return(GSS_S_BAD_MECH);
       }
@@ -314,9 +336,9 @@ krb5_gss_acquire_cred(minor_status, desired_name, time_req,
 
    cred->usage = cred_usage;
    cred->princ = NULL;
-   cred->actual_mechs = valid_mechs;
    cred->prerfc_mech = req_old;
    cred->rfc_mech = req_new;
+   cred->rfcv2_mech = req_v2;
 
    cred->keytab = NULL;
    cred->ccache = NULL;
@@ -407,17 +429,30 @@ krb5_gss_acquire_cred(minor_status, desired_name, time_req,
    /* create mechs */
 
    if (actual_mechs) {
-      if (! g_copy_OID_set(cred->actual_mechs, &ret_mechs)) {
-        if (cred->ccache)
-           (void)krb5_cc_close(context, cred->ccache);
-        if (cred->keytab)
-           (void)krb5_kt_close(context, cred->keytab);
-        if (cred->princ)
-           krb5_free_principal(context, cred->princ);
-        xfree(cred);
-        *minor_status = ENOMEM;
-        return(GSS_S_FAILURE);
-      }
+       if (GSS_ERROR(ret = generic_gss_create_empty_oid_set(minor_status,
+                                                           &ret_mechs)) ||
+          (cred->prerfc_mech &&
+           GSS_ERROR(ret = generic_gss_add_oid_set_member(minor_status,
+                                                          gss_mech_krb5_old,
+                                                          &ret_mechs))) ||
+          (cred->rfc_mech &&
+           GSS_ERROR(ret = generic_gss_add_oid_set_member(minor_status,
+                                                          gss_mech_krb5,
+                                                          &ret_mechs))) ||
+          (cred->rfcv2_mech &&
+           GSS_ERROR(ret = generic_gss_add_oid_set_member(minor_status,
+                                                          gss_mech_krb5_v2,
+                                                          &ret_mechs)))) {
+          if (cred->ccache)
+              (void)krb5_cc_close(context, cred->ccache);
+          if (cred->keytab)
+              (void)krb5_kt_close(context, cred->keytab);
+          if (cred->princ)
+              krb5_free_principal(context, cred->princ);
+          xfree(cred);
+          /* *minor_status set above */
+          return(ret);
+       }
    }
 
    /* intern the credential handle */
@@ -445,39 +480,3 @@ krb5_gss_acquire_cred(minor_status, desired_name, time_req,
 
    return(GSS_S_COMPLETE);
 }
-
-/* V2 interface */
-OM_uint32
-krb5_gss_add_cred(minor_status, input_cred_handle,
-                 desired_name, desired_mech, cred_usage,
-                 initiator_time_req, acceptor_time_req,
-                 output_cred_handle, actual_mechs, 
-                 initiator_time_rec, acceptor_time_rec)
-    OM_uint32          *minor_status;
-    gss_cred_id_t      input_cred_handle;
-    gss_name_t         desired_name;
-    gss_OID            desired_mech;
-    gss_cred_usage_t   cred_usage;
-    OM_uint32          initiator_time_req;
-    OM_uint32          acceptor_time_req;
-    gss_cred_id_t      *output_cred_handle;
-    gss_OID_set                *actual_mechs;
-    OM_uint32          *initiator_time_rec;
-    OM_uint32          *acceptor_time_rec;
-{
-    /*
-     * This does not apply to our single-mechanism implementation.  Decide
-     * if the correct error is BAD_MECH or DUPLICATE_ELEMENT.
-     */
-
-    /* verify that the requested mechanism is the default, or
-       is krb5 */
-
-    if ((desired_mech != GSS_C_NULL_OID) &&
-       (g_OID_equal(desired_mech, gss_mech_krb5)))
-       return(GSS_S_BAD_MECH);
-
-    *minor_status = 0;
-    return(GSS_S_DUPLICATE_ELEMENT);
-}
-
diff --git a/src/lib/gssapi/krb5/add_cred.c b/src/lib/gssapi/krb5/add_cred.c
new file mode 100644 (file)
index 0000000..2a6fdb4
--- /dev/null
@@ -0,0 +1,309 @@
+/*
+ * Copyright (C) 1998 by the FundsXpress, INC.
+ * 
+ * All rights reserved.
+ * 
+ * Export of this software from the United States of America may require
+ * a specific license from the United States Government.  It is the
+ * responsibility of any person or organization contemplating export to
+ * obtain such a license before exporting.
+ * 
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of FundsXpress. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  FundsXpress makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#include "gssapiP_krb5.h"
+#ifdef HAVE_STRING_H
+#include <string.h>
+#else
+#include <strings.h>
+#endif
+
+/*
+ * $Id$
+ */
+
+/* V2 interface */
+OM_uint32
+krb5_gss_add_cred(minor_status, input_cred_handle,
+                 desired_name, desired_mech, cred_usage,
+                 initiator_time_req, acceptor_time_req,
+                 output_cred_handle, actual_mechs, 
+                 initiator_time_rec, acceptor_time_rec)
+    OM_uint32          *minor_status;
+    gss_cred_id_t      input_cred_handle;
+    gss_name_t         desired_name;
+    gss_OID            desired_mech;
+    gss_cred_usage_t   cred_usage;
+    OM_uint32          initiator_time_req;
+    OM_uint32          acceptor_time_req;
+    gss_cred_id_t      *output_cred_handle;
+    gss_OID_set                *actual_mechs;
+    OM_uint32          *initiator_time_rec;
+    OM_uint32          *acceptor_time_rec;
+{
+    krb5_context       context;
+    OM_uint32          major_status, lifetime;
+    krb5_gss_cred_id_t cred;
+    krb5_error_code    code;
+
+    /* this is pretty simple, since there's not really any difference
+       between the underlying mechanisms.  The main hair is in copying
+       a mechanism if requested. */
+
+    /* check if the desired_mech is bogus */
+
+    if (!g_OID_equal(desired_mech, gss_mech_krb5_v2) &&
+       !g_OID_equal(desired_mech, gss_mech_krb5) &&
+       !g_OID_equal(desired_mech, gss_mech_krb5_old)) {
+       *minor_status = 0;
+       return(GSS_S_BAD_MECH);
+    }
+
+    /* check if the desired_mech is bogus */
+
+    if ((cred_usage != GSS_C_INITIATE) &&
+       (cred_usage != GSS_C_ACCEPT) &&
+       (cred_usage != GSS_C_BOTH)) {
+       *minor_status = (OM_uint32) G_BAD_USAGE;
+       return(GSS_S_FAILURE);
+    }
+
+    /* since the default credential includes all the mechanisms,
+       return an error for that case. */
+
+    /*SUPPRESS 29*/
+    if (input_cred_handle == GSS_C_NO_CREDENTIAL) {
+       *minor_status = 0;
+       return(GSS_S_DUPLICATE_ELEMENT);
+    }
+
+    /* verify the credential */
+    if (GSS_ERROR(major_status =
+                 krb5_gss_validate_cred(minor_status, input_cred_handle)))
+       return(major_status);
+
+    cred = (krb5_gss_cred_id_t) input_cred_handle;
+
+    /* check if the cred_usage is equal or "less" than the passed-in cred
+       if copying */
+
+    if (!((cred->usage == cred_usage) ||
+         ((cred->usage == GSS_C_BOTH) &&
+          (output_cred_handle != NULL)))) {
+      *minor_status = (OM_uint32) G_BAD_USAGE;
+      return(GSS_S_FAILURE);
+    }
+
+    /* check that desired_mech isn't already in the credential */
+
+    if ((g_OID_equal(desired_mech, gss_mech_krb5_old) && cred->prerfc_mech) ||
+       (g_OID_equal(desired_mech, gss_mech_krb5) && cred->rfc_mech) ||
+       (g_OID_equal(desired_mech, gss_mech_krb5_v2) && cred->rfcv2_mech)) {
+       *minor_status = 0;
+       return(GSS_S_DUPLICATE_ELEMENT);
+    }
+
+    if (GSS_ERROR(kg_get_context(minor_status, &context)))
+       return(GSS_S_FAILURE);
+
+    /* verify the desired_name */
+
+    /*SUPPRESS 29*/
+    if ((desired_name != (gss_name_t) NULL) &&
+       (! kg_validate_name(desired_name))) {
+       *minor_status = (OM_uint32) G_VALIDATE_FAILED;
+       return(GSS_S_CALL_BAD_STRUCTURE|GSS_S_BAD_NAME);
+    }
+
+    /* make sure the desired_name is the same as the existing one */
+
+    if (desired_name &&
+       !krb5_principal_compare(context, (krb5_principal) desired_name,
+                               cred->princ)) {
+       *minor_status = 0;
+       return(GSS_S_BAD_NAME);
+    }
+
+    /* copy the cred if necessary */
+
+    if (output_cred_handle) {
+       /* make a copy */
+       krb5_gss_cred_id_t new_cred;
+       char *kttype, ktboth[1024];
+       char *cctype, *ccname, ccboth[1024];
+
+       if ((new_cred =
+            (krb5_gss_cred_id_t) xmalloc(sizeof(krb5_gss_cred_id_rec)))
+           == NULL) {
+           *minor_status = ENOMEM;
+           return(GSS_S_FAILURE);
+       }
+       memset(new_cred, 0, sizeof(krb5_gss_cred_id_rec));
+       
+       new_cred->usage = cred_usage;
+       new_cred->prerfc_mech = cred->prerfc_mech;
+       new_cred->rfc_mech = cred->rfc_mech;
+       new_cred->rfcv2_mech = cred->rfcv2_mech;
+       new_cred->tgt_expire = cred->tgt_expire;
+
+       if (code = krb5_copy_principal(context, cred->princ,
+                                      &new_cred->princ)) {
+           free(new_cred);
+
+           *minor_status = code;
+           return(GSS_S_FAILURE);
+       }
+           
+       if (cred->keytab) {
+           kttype = krb5_kt_get_type(context, cred->keytab);
+           if ((strlen(kttype)+2) > sizeof(ktboth)) {
+               krb5_free_principal(context, new_cred->princ);
+               free(new_cred);
+
+               *minor_status = ENOMEM;
+               return(GSS_S_FAILURE);
+           }
+
+           strcpy(ktboth, kttype);
+           strcat(ktboth, ":");
+
+           if (code = krb5_kt_get_name(context, cred->keytab,
+                                       ktboth+strlen(ktboth),
+                                       sizeof(ktboth)-strlen(ktboth))) {
+               krb5_free_principal(context, new_cred->princ);
+               free(new_cred);
+
+               *minor_status = code;
+               return(GSS_S_FAILURE);
+           }
+
+           if (code = krb5_kt_resolve(context, ktboth, &new_cred->keytab)) {
+               krb5_free_principal(context, new_cred->princ);
+               free(new_cred);
+
+               *minor_status = code;
+               return(GSS_S_FAILURE);
+           }
+       } else {
+           new_cred->keytab = NULL;
+       }
+               
+       if (cred->rcache) {
+           /* Open the replay cache for this principal. */
+           if ((code = krb5_get_server_rcache(context,
+                                              krb5_princ_component(context, cred->princ, 0),
+                                              &new_cred->rcache))) {
+               if (new_cred->keytab)
+                   krb5_kt_close(context, new_cred->keytab);
+               krb5_free_principal(context, new_cred->princ);
+               free(new_cred);
+
+               *minor_status = code;
+               return(GSS_S_FAILURE);
+           }
+       } else {
+           new_cred->rcache = NULL;
+       }
+
+       if (cred->ccache) {
+           cctype = krb5_cc_get_type(context, cred->ccache);
+           ccname = krb5_cc_get_name(context, cred->ccache);
+
+           if ((strlen(cctype)+strlen(ccname)+2) > sizeof(ccboth)) {
+               if (new_cred->rcache)
+                   krb5_rc_close(context, new_cred->rcache);
+               if (new_cred->keytab)
+                   krb5_kt_close(context, new_cred->keytab);
+               krb5_free_principal(context, new_cred->princ);
+               free(new_cred);
+
+               *minor_status = ENOMEM;
+               return(GSS_S_FAILURE);
+           }
+
+           strcpy(ccboth, cctype);
+           strcat(ccboth, ":");
+           strcat(ccboth, ccname);
+
+           if (code = krb5_cc_resolve(context, ccboth, &new_cred->ccache)) {
+               if (new_cred->rcache)
+                   krb5_rc_close(context, new_cred->rcache);
+               if (new_cred->keytab)
+                   krb5_kt_close(context, new_cred->keytab);
+               krb5_free_principal(context, new_cred->princ);
+               free(new_cred);
+
+               *minor_status = code;
+               return(GSS_S_FAILURE);
+           }
+       } else {
+           new_cred->ccache = NULL;
+       }
+
+       /* intern the credential handle */
+
+       if (! kg_save_cred_id((gss_cred_id_t) new_cred)) {
+           if (new_cred->ccache)
+               krb5_cc_close(context, new_cred->ccache);
+           if (new_cred->rcache)
+               krb5_rc_close(context, new_cred->rcache);
+           if (new_cred->keytab)
+               krb5_kt_close(context, new_cred->keytab);
+           krb5_free_principal(context, new_cred->princ);
+           free(new_cred);
+
+           *minor_status = (OM_uint32) G_VALIDATE_FAILED;
+           return(GSS_S_FAILURE);
+       }
+
+       /* modify new_cred */
+
+       cred = new_cred;
+    }
+               
+    /* set the flag for the new mechanism */
+
+    if (g_OID_equal(desired_mech, gss_mech_krb5_old))
+       cred->prerfc_mech = 1;
+    else if (g_OID_equal(desired_mech, gss_mech_krb5))
+       cred->rfc_mech = 1;
+    else if (g_OID_equal(desired_mech, gss_mech_krb5_v2))
+       cred->rfcv2_mech = 1;
+
+    /* set the outputs */
+
+    if (GSS_ERROR(major_status = krb5_gss_inquire_cred(minor_status, cred,
+                                                      NULL, &lifetime,
+                                                      NULL, actual_mechs))) {
+       OM_uint32 dummy;
+       
+       if (output_cred_handle)
+           (void) krb5_gss_release_cred(&dummy, (gss_cred_id_t *) &cred);
+
+       return(major_status);
+    }
+
+    if (initiator_time_rec)
+       *initiator_time_rec = lifetime;
+    if (acceptor_time_rec)
+       *acceptor_time_rec = lifetime;
+
+    if (output_cred_handle)
+       *output_cred_handle = cred;
+
+    *minor_status = 0;
+    return(GSS_S_COMPLETE);
+}
index 652745c7b823ded05f1e789548adbe30ba9108ac..688366e1f96e69da2b8c04eea17a168a1aa8d4af 100644 (file)
@@ -31,13 +31,12 @@ OM_uint32 krb5_gss_canonicalize_name(OM_uint32  *minor_status,
                                     const gss_OID mech_type,
                                     gss_name_t *output_name)
 {
-       if ((mech_type == GSS_C_NULL_OID) ||
-           !g_OID_equal(mech_type, gss_mech_krb5)) {
-               if (minor_status)
-                       *minor_status = 0;
-               return(GSS_S_BAD_MECH);
-       }
-               
-       return gss_duplicate_name(minor_status, input_name,
-                                 output_name);
+    if (!g_OID_equal(gss_mech_krb5_v2, mech_type) &&
+       !g_OID_equal(gss_mech_krb5, mech_type) &&
+       !g_OID_equal(gss_mech_krb5_old, mech_type)) {
+       *minor_status = 0;
+       return(GSS_S_BAD_MECH);
+    }
+
+    return(gss_duplicate_name(minor_status, input_name, output_name));
 }
index 16964995a7ce55abb232d7d72d7bbadbc5490b19..28c23589062f6209454d89da0c619509ab3cd027 100644 (file)
@@ -80,15 +80,11 @@ krb5_gss_delete_sec_context(minor_status, context_handle, output_token)
    if (ctx->seqstate)
       g_order_free(&(ctx->seqstate));
 
-   if (ctx->enc.processed)
-      krb5_finish_key(context, &ctx->enc.eblock);
-   if (ctx->enc.key)
-      krb5_free_keyblock(context, ctx->enc.key);
+   if (ctx->enc)
+      krb5_free_keyblock(context, ctx->enc);
 
-   if (ctx->seq.processed)
-      krb5_finish_key(context, &ctx->seq.eblock);
-   if (ctx->seq.key)
-      krb5_free_keyblock(context, ctx->seq.key);
+   if (ctx->seq)
+      krb5_free_keyblock(context, ctx->seq);
 
    if (ctx->here)
       krb5_free_principal(context, ctx->here);
@@ -105,6 +101,9 @@ krb5_gss_delete_sec_context(minor_status, context_handle, output_token)
    if (ctx->mech_used)
        gss_release_oid(minor_status, &ctx->mech_used);
    
+   if (ctx->ctypes)
+       xfree(ctx->ctypes);
+
    /* Zero out context */
    memset(ctx, 0, sizeof(*ctx));
    xfree(ctx);
index 4dc13843ce567b5306d34d341019724e01565a8b..3a6ba7b1ae76f270a8ab0abe3e73c70604eccef1 100644 (file)
@@ -49,10 +49,12 @@ krb5_gss_display_status(minor_status, status_value, status_type,
       return(GSS_S_FAILURE);
 
    if ((mech_type != GSS_C_NULL_OID) &&
-       (! g_OID_equal(gss_mech_krb5, mech_type))) {
-      *minor_status = 0;
-      return(GSS_S_BAD_MECH);
-   }
+       !g_OID_equal(gss_mech_krb5_v2, mech_type) &&
+       !g_OID_equal(gss_mech_krb5, mech_type) &&
+       !g_OID_equal(gss_mech_krb5_old, mech_type)) {
+       *minor_status = 0;
+       return(GSS_S_BAD_MECH);
+    }
 
    if (status_type == GSS_C_GSS_CODE) {
       return(g_display_major_status(minor_status, status_value,
index 11b7c50f44907ac55c5929339ebb3b3be2b29e0b..bcbde389438eaad8bf07e18e3e982f2e8a624dbb 100644 (file)
                         ((x) & (GSS_C_MUTUAL_FLAG | GSS_C_REPLAY_FLAG | \
                                 GSS_C_SEQUENCE_FLAG | GSS_C_DELEG_FLAG)))
 
+#define KG2_TOK_INITIAL                0x0101
+#define KG2_TOK_RESPONSE       0x0202
+#define KG2_TOK_MIC            0x0303
+#define KG2_TOK_WRAP_INTEG     0x0404
+#define KG2_TOK_WRAP_PRIV      0x0505
+
 #define KRB5_GSS_FOR_CREDS_OPTION 1
 
+#define KG2_RESP_FLAG_ERROR            0x0001
+#define KG2_RESP_FLAG_DELEG_OK         0x0002
+
 /** internal types **/
 
 typedef krb5_principal krb5_gss_name_t;
@@ -78,25 +87,19 @@ typedef struct _krb5_gss_cred_id_rec {
    /* name/type of credential */
    gss_cred_usage_t usage;
    krb5_principal princ;       /* this is not interned as a gss_name_t */
-   const gss_OID_set_desc *actual_mechs;
-   int prerfc_mech;            /* these are a cache of the set above */
+   int prerfc_mech;
    int rfc_mech;
+   int rfcv2_mech;
 
    /* keytab (accept) data */
    krb5_keytab keytab;
+   krb5_rcache rcache;
 
    /* ccache (init) data */
    krb5_ccache ccache;
    krb5_timestamp tgt_expire;
-   krb5_rcache rcache;
 } krb5_gss_cred_id_rec, *krb5_gss_cred_id_t; 
 
-typedef struct _krb5_gss_enc_desc {
-   int processed;
-   krb5_keyblock *key;
-   krb5_encrypt_block eblock;
-} krb5_gss_enc_desc;
-
 typedef struct _krb5_gss_ctx_id_rec {
    int initiate;       /* nonzero if initiating, zero if accepting */
    OM_uint32 gss_flags;
@@ -108,21 +111,35 @@ typedef struct _krb5_gss_ctx_id_rec {
    int signalg;
    int cksum_size;
    int sealalg;
-   krb5_gss_enc_desc enc;
-   krb5_gss_enc_desc seq;
+   krb5_keyblock *enc;
+   krb5_keyblock *seq;
    krb5_timestamp endtime;
    krb5_flags krb_flags;
-   krb5_int32 seq_send;
-   krb5_int32 seq_recv;
+   /* XXX these used to be signed.  the old spec is inspecific, and
+      the new spec specifies unsigned.  I don't believe that the change
+      affects the wire encoding. */
+   krb5_ui_4 seq_send;
+   krb5_ui_4 seq_recv;
    void *seqstate;
    int established;
    int big_endian;
    krb5_auth_context auth_context;
    gss_OID_desc *mech_used;
+   int gsskrb5_version;
+   int nctypes;
+   krb5_cksumtype *ctypes;
 } krb5_gss_ctx_id_rec, *krb5_gss_ctx_id_t;
 
 extern void *kg_vdb;
 
+struct kg2_option {
+    int option_id;             /* set by caller */
+    int length;                        /* filled in by parser */
+    unsigned char *data;       /* filled in by parser.  points inside
+                                  passed-in token, so nothing needs to
+                                  be freed */
+};
+
 /* helper macros */
 
 #define kg_save_name(name)             g_save_name(&kg_vdb,name)
@@ -151,12 +168,12 @@ krb5_error_code kg_checksum_channel_bindings
                                             int bigend));
 
 krb5_error_code kg_make_seq_num PROTOTYPE((krb5_context context,
-                                          krb5_gss_enc_desc *ed,
+                                          krb5_keyblock *key,
             int direction, krb5_int32 seqnum, unsigned char *cksum,
                                unsigned char *buf));
 
 krb5_error_code kg_get_seq_num PROTOTYPE((krb5_context context,
-                                         krb5_gss_enc_desc *ed,
+                                         krb5_keyblock *key,
             unsigned char *cksum, unsigned char *buf, int *direction,
                                          krb5_int32 *seqnum));
 
@@ -164,19 +181,20 @@ krb5_error_code kg_make_seed PROTOTYPE((krb5_context context,
                                        krb5_keyblock *key,
                                        unsigned char *seed));
 
-int kg_confounder_size PROTOTYPE((krb5_gss_enc_desc *ed));
+int kg_confounder_size PROTOTYPE((krb5_context context, krb5_keyblock *key));
 
-krb5_error_code kg_make_confounder PROTOTYPE((krb5_gss_enc_desc *ed,
-            unsigned char *buf));
+krb5_error_code kg_make_confounder PROTOTYPE((krb5_context context, 
+           krb5_keyblock *key, unsigned char *buf));
 
-int kg_encrypt_size PROTOTYPE((krb5_gss_enc_desc *ed, int n));
+int kg_encrypt_size PROTOTYPE((krb5_context context,
+                              krb5_keyblock *key, int n));
 
 krb5_error_code kg_encrypt PROTOTYPE((krb5_context context, 
-            krb5_gss_enc_desc *ed,
+            krb5_keyblock *key,
             krb5_pointer iv, krb5_pointer in, krb5_pointer out, int length));
 
 krb5_error_code kg_decrypt PROTOTYPE((krb5_context context,
-                           krb5_gss_enc_desc *ed
+                           krb5_keyblock *key
                           krb5_pointer iv, krb5_pointer in, krb5_pointer out, int length));
 
 OM_uint32 kg_seal PROTOTYPE((krb5_context context,
@@ -223,6 +241,23 @@ krb5_error_code kg_ctx_internalize PROTOTYPE((krb5_context kcontext,
 OM_uint32 kg_get_context PROTOTYPE((OM_uint32 *minor_status,
                                    krb5_context *context));
        
+OM_uint32
+kg2_parse_token PROTOTYPE((OM_uint32 *minor_status,
+                          unsigned char *ptr,
+                          int length,
+                          krb5_ui_4 *flags,
+                          int *nctypes, /* OUT */
+                          krb5_cksumtype **ctypes, /* OUT */
+                          int noptions,
+                          struct kg2_option *options, /* INOUT */
+                          krb5_data *kmsg,
+                          krb5_data *mic));
+
+void kg2_intersect_ctypes PROTOTYPE((int *nc1, 
+                                    krb5_cksumtype *c1,
+                                    int nc2,
+                                    const krb5_cksumtype *c2));
+
 /** declarations of internal name mechanism functions **/
 
 OM_uint32 krb5_gss_acquire_cred
index 54a126518b34fb9ff556ba66bc6b10369c879f96..3c9be6351fb3ebfd11cae9a226cfcca193725102 100644 (file)
@@ -35,4 +35,5 @@ error_code KG_CRED, "Bad magic number for krb5_gss_cred_id_t"
 error_code KG_ENC_DESC, "Bad magic number for krb5_gss_enc_desc"
 error_code KG_BAD_SEQ, "Sequence number in token is corrupt"
 error_code KG_EMPTY_CCACHE, "Credential cache is empty"
+error_code KG_NO_CTYPES, "Acceptor and Initiator share no checksum types"
 end
index c0942c39a63b2173771441d3301d1a296041434e..aaa47ea06536797d7bd69d09c2661ebc146e5fa1 100644 (file)
  * PERFORMANCE OF THIS SOFTWARE.
  */
 
+/*
+ * Copyright (C) 1998 by the FundsXpress, INC.
+ * 
+ * All rights reserved.
+ * 
+ * Export of this software from the United States of America may require
+ * a specific license from the United States Government.  It is the
+ * responsibility of any person or organization contemplating export to
+ * obtain such a license before exporting.
+ * 
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of FundsXpress. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  FundsXpress makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
 /*
  * $Id$
  */
@@ -43,6 +69,9 @@
  * The OID of the proposed standard krb5 mechanism is:
  *     iso(1) member-body(2) US(840) mit(113554) infosys(1) gssapi(2)
  *     krb5(2) = 1.2.840.113554.1.2.2
+ * The OID of the proposed standard krb5 v2 mechanism is:
+ *     iso(1) member-body(2) US(840) mit(113554) infosys(1) gssapi(2)
+ *     krb5v2(3) = 1.2.840.113554.1.2.3
  *     
  */
 
@@ -58,8 +87,13 @@ const gss_OID_desc krb5_gss_oid_array[] = {
    {5, "\053\005\001\005\002"},
    /* this is the official, rfc-specified OID */
    {9, "\052\206\110\206\367\022\001\002\002"},
+   /* these two are name type OID's */
    {10, "\052\206\110\206\367\022\001\002\002\001"},
    {10, "\052\206\110\206\367\022\001\002\002\002"},
+   /* this is the v2 assigned OID */
+   {9, "\052\206\110\206\367\022\001\002\003"},
+   /* this is the official, rfc-specified OID again */
+   {9, "\052\206\110\206\367\022\001\002\002"},
    { 0, 0 }
 };
 
@@ -67,16 +101,21 @@ const gss_OID_desc * const gss_mech_krb5_old = krb5_gss_oid_array+0;
 const gss_OID_desc * const gss_mech_krb5 = krb5_gss_oid_array+1;
 const gss_OID_desc * const gss_nt_krb5_name = krb5_gss_oid_array+2;
 const gss_OID_desc * const gss_nt_krb5_principal = krb5_gss_oid_array+3;
+const gss_OID_desc * const gss_mech_krb5_v2 = krb5_gss_oid_array+4;
 
 static const gss_OID_set_desc oidsets[] = {
    {1, (gss_OID) krb5_gss_oid_array+0},
    {1, (gss_OID) krb5_gss_oid_array+1},
    {2, (gss_OID) krb5_gss_oid_array+0},
+   {1, (gss_OID) krb5_gss_oid_array+4},
+   {2, (gss_OID) krb5_gss_oid_array+4},
 };
 
 const gss_OID_set_desc * const gss_mech_set_krb5_old = oidsets+0;
 const gss_OID_set_desc * const gss_mech_set_krb5 = oidsets+1;
 const gss_OID_set_desc * const gss_mech_set_krb5_both = oidsets+2;
+const gss_OID_set_desc * const gss_mech_set_krb5_v2 = oidsets+3;
+const gss_OID_set_desc * const gss_mech_set_krb5_v1v2 = oidsets+4;
 
 void *kg_vdb = NULL;
 
index 63ac530f318b90af312285d0dc6ff9a7a0a2c84e..e4eccbb42920e766746a75f2da270bc33de917c9 100644 (file)
 
 extern const gss_OID_desc * const gss_mech_krb5;
 extern const gss_OID_desc * const gss_mech_krb5_old;
+extern const gss_OID_desc * const gss_mech_krb5_v2;
 extern const gss_OID_set_desc * const gss_mech_set_krb5;
 extern const gss_OID_set_desc * const gss_mech_set_krb5_old;
 extern const gss_OID_set_desc * const gss_mech_set_krb5_both;
+extern const gss_OID_set_desc * const gss_mech_set_krb5_v2;
+extern const gss_OID_set_desc * const gss_mech_set_krb5_v1v2;
 
 extern const gss_OID_desc * const gss_nt_krb5_name;
 extern const gss_OID_desc * const gss_nt_krb5_principal;
index 50855b58cf9fae1521a5f2b41296190064143726..4ff2085b4fd62b34b5e22e0f163c72cfc04c8f35 100644 (file)
  * PERFORMANCE OF THIS SOFTWARE.
  */
 
+/*
+ * Copyright (C) 1998 by the FundsXpress, INC.
+ * 
+ * All rights reserved.
+ * 
+ * Export of this software from the United States of America may require
+ * a specific license from the United States Government.  It is the
+ * responsibility of any person or organization contemplating export to
+ * obtain such a license before exporting.
+ * 
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of FundsXpress. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  FundsXpress makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
 #include "gssapiP_krb5.h"
 #include <memory.h>
 #include <stdlib.h>
 int krb5_gss_dbg_client_expcreds = 0;
 
 static krb5_error_code
-make_ap_req(context, auth_context, cred, server, now, endtime, chan_bindings, 
-           req_flags, krb_flags, mech_type, token)
+make_ap_req_v2(context, auth_context, cred, server, now, endtime,
+              chan_bindings, req_flags, krb_flags, mech_type,
+              ret_nctypes, ret_ctypes, token)
+    krb5_context context;
+    krb5_auth_context * auth_context;
+    krb5_gss_cred_id_t cred;
+    krb5_principal server;
+    krb5_timestamp now;
+    krb5_timestamp *endtime;
+    gss_channel_bindings_t chan_bindings;
+    OM_uint32 *req_flags;
+    krb5_flags *krb_flags;
+    gss_OID mech_type;
+    int *ret_nctypes;
+    krb5_cksumtype **ret_ctypes;
+    gss_buffer_t token;
+{
+    krb5_flags mk_req_flags = 0;
+    krb5_int32 con_flags;
+    krb5_error_code code;
+    krb5_creds in_creds, *out_creds = 0;
+    krb5_data credmsg, cksumdata, ap_req;
+    int i, tlen, cblen, nctypes;
+    krb5_cksumtype *ctypes;
+    unsigned char *t, *ptr;
+
+    credmsg.data = 0;
+    cksumdata.data = 0;
+    ap_req.data = 0;
+    ctypes = 0;
+
+    /* this probably isn't necessary */
+    if (*auth_context)
+       krb5_auth_con_free(context, *auth_context);
+
+    *auth_context = 0;
+
+    /* create the option data if necessary */
+
+    if (*req_flags & GSS_C_DELEG_FLAG) {
+       /* first get KRB_CRED message, so we know its length */
+
+       /* clear the time check flag that was set in krb5_auth_con_init() */
+       krb5_auth_con_getflags(context, *auth_context, &con_flags);
+       krb5_auth_con_setflags(context, *auth_context,
+                              con_flags & ~KRB5_AUTH_CONTEXT_DO_TIME);
+
+       code = krb5_fwd_tgt_creds(context, *auth_context, 0,
+                                 cred->princ, server, cred->ccache, 1,
+                                 &credmsg);
+
+       /* turn KRB5_AUTH_CONTEXT_DO_TIME back on */
+       krb5_auth_con_setflags(context, *auth_context, con_flags);
+
+       if (code) {
+           /* don't fail here; just don't accept/do the delegation
+               request */
+           *req_flags &= ~GSS_C_DELEG_FLAG;
+       } else {
+           if (credmsg.length > KRB5_INT16_MAX) {
+               krb5_free_data_contents(context, &credmsg);
+               return(KRB5KRB_ERR_FIELD_TOOLONG);
+           }
+       }
+    } else {
+       credmsg.length = 0;
+    }
+       
+    /*
+     * Get the credential, for the session key etype
+     */
+
+    memset((char *) &in_creds, 0, sizeof(krb5_creds));
+
+    if ((code = krb5_copy_principal(context, cred->princ, &in_creds.client)))
+       goto cleanup;
+    if ((code = krb5_copy_principal(context, server, &in_creds.server)))
+       goto cleanup;
+    in_creds.times.endtime = *endtime;
+
+    if ((code = krb5_get_credentials(context, 0, cred->ccache, 
+                                    &in_creds, &out_creds)))
+       goto cleanup;
+
+    /*
+     * Enforce a stricter limit (without timeskew forgiveness at the
+     * boundaries) because accept_sec_context code is also similarly
+     * non-forgiving.
+     */
+    if (!krb5_gss_dbg_client_expcreds && out_creds->times.endtime < now) {
+       code = KRB5KRB_AP_ERR_TKT_EXPIRED;
+       goto cleanup;
+    }
+
+    /* construct the list of compatible cksum types */
+
+    if (code = krb5_c_keyed_checksum_types(context,
+                                          out_creds->keyblock.enctype,
+                                          &nctypes, &ctypes))
+       goto cleanup;
+
+    if (nctypes == 0) {
+       code = KRB5_CRYPTO_INTERNAL;
+       goto cleanup;
+    }
+
+    /* construct the checksum fields */
+
+    cblen = 4*5;
+    if (chan_bindings)
+       cblen += (chan_bindings->initiator_address.length+
+                 chan_bindings->acceptor_address.length+
+                 chan_bindings->application_data.length);
+
+    cksumdata.length = cblen + 8 + 4*nctypes + 4;
+    if (credmsg.length)
+       cksumdata.length += 4 + credmsg.length;
+
+    if ((cksumdata.data = (char *) malloc(cksumdata.length)) == NULL)
+       goto cleanup;
+
+    /* helper macros.  This code currently depends on a long being 32
+       bits, and htonl dtrt. */
+
+    ptr = cksumdata.data;
+
+    if (chan_bindings) {
+       TWRITE_INT(ptr, chan_bindings->initiator_addrtype, 1);
+       TWRITE_BUF(ptr, chan_bindings->initiator_address, 1);
+       TWRITE_INT(ptr, chan_bindings->acceptor_addrtype, 1);
+       TWRITE_BUF(ptr, chan_bindings->acceptor_address, 1);
+       TWRITE_BUF(ptr, chan_bindings->application_data, 1);
+    } else {
+       memset(ptr, 0, cblen);
+       ptr += cblen;
+    }
+
+    /* construct the token fields */
+
+    ptr[0] = (KG2_TOK_INITIAL >> 8) & 0xff;
+    ptr[1] = KG2_TOK_INITIAL & 0xff;
+
+    ptr[2] = (*req_flags >> 24) & 0xff;
+    ptr[3] = (*req_flags >> 16) & 0xff;
+    ptr[4] = (*req_flags >> 8) & 0xff;
+    ptr[5] = *req_flags & 0xff;
+
+    ptr[6] = (nctypes >> 8) & 0xff;
+    ptr[7] = nctypes & 0xff;
+
+    ptr += 8;
+
+    for (i=0; i<nctypes; i++) {
+       ptr[0] = (ctypes[i] >> 24) & 0xff;
+       ptr[1] = (ctypes[i] >> 16) & 0xff;
+       ptr[2] = (ctypes[i] >> 8) & 0xff;
+       ptr[3] = ctypes[i] & 0xff;
+
+       ptr += 4;
+    }
+
+    if (credmsg.length) {
+       ptr[0] = (KRB5_GSS_FOR_CREDS_OPTION >> 8) & 0xff;
+       ptr[1] = KRB5_GSS_FOR_CREDS_OPTION & 0xff;
+
+       ptr[2] = (credmsg.length >> 8) & 0xff;
+       ptr[3] = credmsg.length & 0xff;
+
+       ptr += 4;
+
+       memcpy(ptr, credmsg.data, credmsg.length);
+
+       ptr += credmsg.length;
+    }
+
+    memset(ptr, 0, 4);
+
+    /* call mk_req.  subkey and ap_req need to be used or destroyed */
+
+    mk_req_flags = AP_OPTS_USE_SUBKEY;
+
+    if (*req_flags & GSS_C_MUTUAL_FLAG)
+       mk_req_flags |= AP_OPTS_MUTUAL_REQUIRED;
+
+    if ((code = krb5_mk_req_extended(context, auth_context, mk_req_flags,
+                                    &cksumdata, out_creds, &ap_req)))
+       goto cleanup;
+
+   /* store the interesting stuff from creds and authent */
+   *endtime = out_creds->times.endtime;
+   *krb_flags = out_creds->ticket_flags;
+
+   /* build up the token */
+
+   /* allocate space for the token */
+   tlen = g_token_size((gss_OID) mech_type,
+                      (cksumdata.length-(2+cblen))+2+ap_req.length);
+
+   if ((t = (unsigned char *) xmalloc(tlen)) == NULL) {
+      code = ENOMEM;
+      goto cleanup;
+   }
+
+   ptr = t;
+
+   g_make_token_header((gss_OID) mech_type,
+                      (cksumdata.length-(2+cblen))+2+ap_req.length,
+                      &ptr, KG2_TOK_INITIAL);
+
+   /* skip over the channel bindings and the token id */
+   memcpy(ptr, cksumdata.data+cblen+2, cksumdata.length-(cblen+2));
+   ptr += cksumdata.length-(cblen+2);
+   ptr[0] = (ap_req.length >> 8) & 0xff;
+   ptr[1] = ap_req.length & 0xff;
+   ptr += 2;
+   memcpy(ptr, ap_req.data, ap_req.length);
+
+   /* pass allocated data back */
+
+   *ret_nctypes = nctypes;
+   *ret_ctypes = ctypes;
+
+   token->length = tlen;
+   token->value = (void *) t;
+
+   code = 0;
+
+cleanup:
+   if (code) {
+       if (*auth_context)
+          krb5_auth_con_free(context, *auth_context);
+       if (ctypes)
+          krb5_free_cksumtypes(context, ctypes);
+   }
+
+   if (out_creds)
+       krb5_free_creds(context, out_creds);
+   krb5_free_cred_contents(context, &in_creds);
+   if (credmsg.data)
+       free(credmsg.data);
+   if (ap_req.data)
+       free(ap_req.data);
+   if (cksumdata.data)
+       free(cksumdata.data);
+
+   return(code);
+}
+
+static krb5_error_code
+make_ap_req_v1(context, auth_context, cred, server, now, endtime,
+              chan_bindings, req_flags, krb_flags, mech_type, token)
     krb5_context context;
     krb5_auth_context * auth_context;
     krb5_gss_cred_id_t cred;
@@ -142,15 +417,16 @@ make_ap_req(context, auth_context, cred, server, now, endtime, chan_bindings,
 
     /* fill in the necessary fields in creds */
     memset((char *) &in_creds, 0, sizeof(krb5_creds));
+
     if ((code = krb5_copy_principal(context, cred->princ, &in_creds.client)))
        goto cleanup;
     if ((code = krb5_copy_principal(context, server, &in_creds.server)))
        goto cleanup;
-    in_creds.keyblock.enctype = ENCTYPE_DES_CBC_CRC;
     in_creds.times.endtime = *endtime;
+    in_creds.keyblock.enctype = ENCTYPE_DES_CBC_CRC;
     
     /*
-     * Get the credential..., I don't know in 0 is a good value for the
+     * Get the credential..., I don't know if 0 is a good value for the
      * kdcoptions
      */
     if ((code = krb5_get_credentials(context, 0, cred->ccache, 
@@ -222,10 +498,6 @@ cleanup:
    return (code);
 }
 
-#define IS_KRB_ERROR(dat)\
-       ((dat) && (dat)->length && ((dat)->data[0] == 0x7e ||\
-                                   (dat)->data[0] == 0x5e))
-
 OM_uint32
 krb5_gss_init_sec_context(minor_status, claimant_cred_handle,
                          context_handle, target_name, mech_type,
@@ -251,10 +523,11 @@ krb5_gss_init_sec_context(minor_status, claimant_cred_handle,
    krb5_error_code code; 
    krb5_gss_ctx_id_rec *ctx;
    krb5_timestamp now;
-   krb5_enctype enctype;
    gss_buffer_desc token;
-   int i;
-   int err;
+   int gsskrb5_vers;
+   int i, err;
+   krb5_ui_4 resp_flags, field_length, opt_id;
+   OM_uint32 major_status, dummy;
 
    if (GSS_ERROR(kg_get_context(minor_status, &context)))
       return(GSS_S_FAILURE);
@@ -289,15 +562,33 @@ krb5_gss_init_sec_context(minor_status, claimant_cred_handle,
 
    err = 0;
    if (mech_type == GSS_C_NULL_OID) {
-       mech_type = cred->rfc_mech?gss_mech_krb5:gss_mech_krb5_old;
+       if (cred->rfcv2_mech) {
+          mech_type = gss_mech_krb5_v2;
+          gsskrb5_vers = 2000;
+       } else if (cred->rfc_mech) {
+          mech_type = gss_mech_krb5;
+          gsskrb5_vers = 1000;
+       } else if (cred->prerfc_mech) {
+          mech_type = gss_mech_krb5_old;
+          gsskrb5_vers = 1000;
+       } else {
+          err = 1;
+       }
+   } else if (g_OID_equal(mech_type, gss_mech_krb5_v2)) {
+       if (!cred->rfcv2_mech)
+          err = 1;
+       gsskrb5_vers = 2000;
    } else if (g_OID_equal(mech_type, gss_mech_krb5)) {
        if (!cred->rfc_mech)
           err = 1;
+       gsskrb5_vers = 1000;
    } else if (g_OID_equal(mech_type, gss_mech_krb5_old)) {
        if (!cred->prerfc_mech)
           err = 1;
-   } else
+       gsskrb5_vers = 1000;
+   } else {
        err = 1;
+   }
    
    if (err) {
       *minor_status = 0;
@@ -351,6 +642,9 @@ krb5_gss_init_sec_context(minor_status, claimant_cred_handle,
       ctx->seed_init = 0;
       ctx->big_endian = 0;  /* all initiators do little-endian, as per spec */
       ctx->seqstate = 0;
+      ctx->gsskrb5_version = gsskrb5_vers;
+      ctx->nctypes = 0;
+      ctx->ctypes = 0;
 
       if ((code = krb5_timeofday(context, &now))) {
        free(ctx);
@@ -377,63 +671,94 @@ krb5_gss_init_sec_context(minor_status, claimant_cred_handle,
         return(GSS_S_FAILURE);
       }
 
-      if ((code = make_ap_req(context, &(ctx->auth_context), cred, 
-                             ctx->there, now, &ctx->endtime,
-                             input_chan_bindings, 
-                             &ctx->gss_flags, &ctx->krb_flags, mech_type,
-                             &token))) {
-        krb5_free_principal(context, ctx->here);
-        krb5_free_principal(context, ctx->there);
-        xfree(ctx);
-        *minor_status = code;
-
-        if ((code == KRB5_FCC_NOFILE) || (code == KRB5_CC_NOTFOUND) ||
-            (code == KG_EMPTY_CCACHE))
-            return GSS_S_NO_CRED;
-        if (code == KRB5KRB_AP_ERR_TKT_EXPIRED)
-                return GSS_S_CREDENTIALS_EXPIRED;
-        return(GSS_S_FAILURE);
-      }
-
-      krb5_auth_con_getlocalseqnumber(context, ctx->auth_context, &ctx->seq_send);
-      krb5_auth_con_getlocalsubkey(context, ctx->auth_context, &ctx->subkey);
-
-      /* fill in the encryption descriptors */
-
-      switch(ctx->subkey->enctype) {
-      case ENCTYPE_DES_CBC_MD5:
-      case ENCTYPE_DES_CBC_CRC:
-         enctype = ENCTYPE_DES_CBC_RAW;
-         ctx->signalg = 0;
-         ctx->cksum_size = 8;
-         ctx->sealalg = 0;
-         break;
+      if (ctx->gsskrb5_version == 2000) {
+         /* gsskrb5 v2 */
+
+         ctx->gss_flags & ~GSS_C_DELEG_FLAG;
+
+         if ((code = make_ap_req_v2(context, &(ctx->auth_context), cred, 
+                                    ctx->there, now, &ctx->endtime,
+                                    input_chan_bindings, 
+                                    &ctx->gss_flags, &ctx->krb_flags,
+                                    mech_type, &ctx->nctypes, &ctx->ctypes,
+                                    &token))) {
+             krb5_free_principal(context, ctx->here);
+             krb5_free_principal(context, ctx->there);
+             xfree(ctx);
+             *minor_status = code;
+
+             if ((code == KRB5_FCC_NOFILE) || (code == KRB5_CC_NOTFOUND) ||
+                 (code == KG_EMPTY_CCACHE))
+                 return GSS_S_NO_CRED;
+             if (code == KRB5KRB_AP_ERR_TKT_EXPIRED)
+                 return GSS_S_CREDENTIALS_EXPIRED;
+             return(GSS_S_FAILURE);
+         }
+
+         krb5_auth_con_getlocalseqnumber(context, ctx->auth_context,
+                                         &ctx->seq_send);
+         krb5_auth_con_getlocalsubkey(context, ctx->auth_context,
+                                      &ctx->subkey);
+      } else {
+         /* gsskrb5 v1 */
+
+         if ((code = make_ap_req_v1(context, &(ctx->auth_context), cred, 
+                                    ctx->there, now, &ctx->endtime,
+                                    input_chan_bindings, 
+                                    &ctx->gss_flags, &ctx->krb_flags,
+                                    mech_type,
+                                    &token))) {
+             krb5_free_principal(context, ctx->here);
+             krb5_free_principal(context, ctx->there);
+             xfree(ctx);
+             *minor_status = code;
+
+             if ((code == KRB5_FCC_NOFILE) || (code == KRB5_CC_NOTFOUND) ||
+                 (code == KG_EMPTY_CCACHE))
+                 return GSS_S_NO_CRED;
+             if (code == KRB5KRB_AP_ERR_TKT_EXPIRED)
+                 return GSS_S_CREDENTIALS_EXPIRED;
+             return(GSS_S_FAILURE);
+         }
+
+         krb5_auth_con_getlocalseqnumber(context, ctx->auth_context,
+                                         &ctx->seq_send);
+         krb5_auth_con_getlocalsubkey(context, ctx->auth_context,
+                                      &ctx->subkey);
+
+         /* fill in the encryption descriptors */
+
+         switch(ctx->subkey->enctype) {
+         case ENCTYPE_DES_CBC_MD5:
+         case ENCTYPE_DES_CBC_CRC:
+             ctx->subkey->enctype = ENCTYPE_DES_CBC_RAW;
+             ctx->signalg = 0;
+             ctx->cksum_size = 8;
+             ctx->sealalg = 0;
+             break;
 #if 0
-      case ENCTYPE_DES3_CBC_MD5:
-         enctype = ENCTYPE_DES3_CBC_RAW;
-         ctx->signalg = 3;
-         ctx->cksum_size = 16;
-         ctx->sealalg = 1;
-         break;
+         case ENCTYPE_DES3_CBC_MD5:
+             enctype = ENCTYPE_DES3_CBC_RAW;
+             ctx->signalg = 3;
+             ctx->cksum_size = 16;
+             ctx->sealalg = 1;
+             break;
 #endif
-      default:
-         return GSS_S_FAILURE;
-      }
+         default:
+             return GSS_S_FAILURE;
+         }
 
-      /* the encryption key is the session key XOR 0xf0f0f0f0f0f0f0f0 */
+         /* the encryption key is the session key XOR 0xf0f0f0f0f0f0f0f0 */
 
-      krb5_use_enctype(context, &ctx->enc.eblock, enctype);
-      ctx->enc.processed = 0;
-      if ((code = krb5_copy_keyblock(context, ctx->subkey, &ctx->enc.key)))
-        return(code); 
-      for (i=0; i<ctx->enc.key->length; i++)
-        /*SUPPRESS 113*/
-        ctx->enc.key->contents[i] ^= 0xf0;
+         if ((code = krb5_copy_keyblock(context, ctx->subkey, &ctx->enc)))
+             return(code);
+         for (i=0; i<ctx->enc->length; i++)
+             /*SUPPRESS 113*/
+             ctx->enc->contents[i] ^= 0xf0;
 
-      krb5_use_enctype(context, &ctx->seq.eblock, enctype);
-      ctx->seq.processed = 0;
-      if ((code = krb5_copy_keyblock(context, ctx->subkey, &ctx->seq.key)))
-         return(code);
+         if ((code = krb5_copy_keyblock(context, ctx->subkey, &ctx->seq)))
+             return(code);
+      }
 
       /* at this point, the context is constructed and valid,
         hence, releaseable */
@@ -493,7 +818,7 @@ krb5_gss_init_sec_context(minor_status, claimant_cred_handle,
    } else {
       unsigned char *ptr;
       char *sptr;
-      krb5_data ap_rep;
+      krb5_data ap_rep, mic;
       krb5_ap_rep_enc_part *ap_rep_data;
       krb5_error *krb_error;
 
@@ -512,11 +837,8 @@ krb5_gss_init_sec_context(minor_status, claimant_cred_handle,
       if ((ctx->established) ||
          (((gss_cred_id_t) cred) != claimant_cred_handle) ||
          ((ctx->gss_flags & GSS_C_MUTUAL_FLAG) == 0)) {
-        (void)krb5_gss_delete_sec_context(minor_status, 
-                                          context_handle, NULL);
-        /* XXX this minor status is wrong if an arg was changed */
-        *minor_status = KG_CONTEXT_ESTABLISHED;
-        return(GSS_S_FAILURE);
+         code = KG_CONTEXT_ESTABLISHED;
+         goto fail;
       }
 
       if (! krb5_principal_compare(context, ctx->there, 
@@ -538,47 +860,106 @@ krb5_gss_init_sec_context(minor_status, claimant_cred_handle,
 
       ptr = (unsigned char *) input_token->value;
 
-      if ((err = g_verify_token_header((gss_OID) mech_type, &(ap_rep.length),
-                                      &ptr, KG_TOK_CTX_AP_REP,
-                                      input_token->length))) {
+      if (ctx->gsskrb5_version == 2000) {
+         int token_length;
+         int nctypes;
+         krb5_cksumtype *ctypes;
+
+         /* gsskrb5 v2 */
+
+         if ((err = g_verify_token_header((gss_OID) mech_type,
+                                          &token_length,
+                                          &ptr, KG2_TOK_RESPONSE,
+                                          input_token->length))) {
+             (void)krb5_gss_delete_sec_context(minor_status, 
+                                               context_handle, NULL);
+             *minor_status = err;
+             return(GSS_S_DEFECTIVE_TOKEN);
+         }
+
+         if (GSS_ERROR(major_status =
+                       kg2_parse_token(minor_status, ptr, token_length,
+                                       &resp_flags, &nctypes, &ctypes,
+                                       0, NULL, &ap_rep, &mic))) {
+             free(ctypes);
+             (void)krb5_gss_delete_sec_context(&dummy, context_handle, NULL);
+             return(major_status);
+         }
+
+         kg2_intersect_ctypes(&ctx->nctypes, ctx->ctypes, nctypes, ctypes);
+
+         free(ctypes);
+
+         if (ctx->nctypes == 0) {
+             code = KG_NO_CTYPES;
+             goto fail;
+         }
+
+         if (resp_flags & KG2_RESP_FLAG_ERROR) {
+             if (code = krb5_rd_error(context, &ap_rep, &krb_error))
+                 goto fail;
+
+             if (krb_error->error)
+                 code = krb_error->error + ERROR_TABLE_BASE_krb5;
+             else
+                 code = 0;
+
+             krb5_free_error(context, krb_error);
+
+             goto fail;
+         }
+
+         if (resp_flags & KG2_RESP_FLAG_DELEG_OK)
+             ctx->gss_flags |= GSS_C_DELEG_FLAG;
+
+         /* drop through to ap_rep handling */
+      } else {
+         /* gsskrb5 v1 */
+
+         if ((err = g_verify_token_header((gss_OID) mech_type,
+                                          &(ap_rep.length),
+                                          &ptr, KG_TOK_CTX_AP_REP,
+                                          input_token->length))) {
              if (g_verify_token_header((gss_OID) mech_type, &(ap_rep.length),
                                        &ptr, KG_TOK_CTX_ERROR,
                                        input_token->length) == 0) {
 
-                     /* Handle a KRB_ERROR message from the server */
+                 /* Handle a KRB_ERROR message from the server */
 
-                     sptr = (char *) ptr;           /* PC compiler bug */
-                     TREAD_STR(sptr, ap_rep.data, ap_rep.length);
+                 sptr = (char *) ptr;           /* PC compiler bug */
+                 TREAD_STR(sptr, ap_rep.data, ap_rep.length);
                      
-                     code = krb5_rd_error(context, &ap_rep, &krb_error);
-                     if (code)
-                             goto fail;
-                     if (krb_error->error)
-                             code = krb_error->error + ERROR_TABLE_BASE_krb5;
-                     else
-                             code = 0;
-                     krb5_free_error(context, krb_error);
+                 code = krb5_rd_error(context, &ap_rep, &krb_error);
+                 if (code)
                      goto fail;
+                 if (krb_error->error)
+                     code = krb_error->error + ERROR_TABLE_BASE_krb5;
+                 else
+                     code = 0;
+                 krb5_free_error(context, krb_error);
+                 goto fail;
              } else {
-                     *minor_status = err;
-                     return(GSS_S_DEFECTIVE_TOKEN);
+                 *minor_status = 0;
+                 return(GSS_S_DEFECTIVE_TOKEN);
              }
-      }
+         }
 
-      sptr = (char *) ptr;                      /* PC compiler bug */
-      TREAD_STR(sptr, ap_rep.data, ap_rep.length);
+         sptr = (char *) ptr;                      /* PC compiler bug */
+         TREAD_STR(sptr, ap_rep.data, ap_rep.length);
+      }
 
       /* decode the ap_rep */
-      if ((code = krb5_rd_rep(context,ctx->auth_context,&ap_rep,
+      if ((code = krb5_rd_rep(context, ctx->auth_context, &ap_rep,
                              &ap_rep_data))) {
-             /*
-              * XXX A hack for backwards compatiblity.
-              * To be removed in 1999 -- proven 
-              */
-             krb5_auth_con_setuseruserkey(context,ctx->auth_context,ctx->subkey);
-             if ((krb5_rd_rep(context, ctx->auth_context, &ap_rep,
-                            &ap_rep_data)))
-                     goto fail;
+         /*
+          * XXX A hack for backwards compatiblity.
+          * To be removed in 1999 -- proven 
+          */
+         krb5_auth_con_setuseruserkey(context, ctx->auth_context,
+                                      ctx->subkey);
+         if ((krb5_rd_rep(context, ctx->auth_context, &ap_rep,
+                          &ap_rep_data)))
+             goto fail;
       }
 
       /* store away the sequence number */
@@ -593,6 +974,25 @@ krb5_gss_init_sec_context(minor_status, claimant_cred_handle,
       /* set established */
       ctx->established = 1;
 
+      if (ctx->gsskrb5_version == 2000) {
+         gss_buffer_desc mic_data, mic_token;
+
+         /* start with the token id */
+         mic_data.value = ptr-2;
+         /* end before the ap-rep length */
+         mic_data.length = ((char*)(ap_rep.data-2)-(char*)(ptr-2));
+
+         mic_token.length = mic.length;
+         mic_token.value = mic.data;
+
+         if (GSS_ERROR(major_status = 
+                       krb5_gss_verify_mic(minor_status, *context_handle,
+                                           &mic_data, &mic_token, NULL))) {
+             (void)krb5_gss_delete_sec_context(&dummy, context_handle, NULL);
+             return(major_status);
+         }
+      }
+
       /* set returns */
 
       if (time_rec) {
@@ -602,7 +1002,7 @@ krb5_gss_init_sec_context(minor_status, claimant_cred_handle,
       }
 
       if (ret_flags)
-        *ret_flags = KG_IMPLFLAGS(req_flags);
+        *ret_flags = ctx->gss_flags;
 
       if (actual_mech_type)
         *actual_mech_type = mech_type;
@@ -616,8 +1016,8 @@ krb5_gss_init_sec_context(minor_status, claimant_cred_handle,
    return(GSS_S_COMPLETE);
 
 fail:
-   (void)krb5_gss_delete_sec_context(minor_status, 
-                                    (gss_ctx_id_t) ctx, NULL);
+   (void)krb5_gss_delete_sec_context(minor_status, context_handle, NULL);
+
    *minor_status = code;
    return(GSS_S_FAILURE);
 }
index ee5d436c19bafb798cc5848693b372c7614911fd..c800012c84d946596546205d9fc56393c7071e4d 100644 (file)
  * PERFORMANCE OF THIS SOFTWARE.
  */
 
+/*
+ * Copyright (C) 1998 by the FundsXpress, INC.
+ * 
+ * All rights reserved.
+ * 
+ * Export of this software from the United States of America may require
+ * a specific license from the United States Government.  It is the
+ * responsibility of any person or organization contemplating export to
+ * obtain such a license before exporting.
+ * 
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of FundsXpress. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  FundsXpress makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
 #include "gssapiP_krb5.h"
 
 OM_uint32
@@ -39,6 +65,7 @@ krb5_gss_inquire_cred(minor_status, cred_handle, name, lifetime_ret,
    krb5_deltat lifetime;
    krb5_principal ret_name;
    gss_OID_set mechs;
+   OM_uint32 ret;
 
    if (GSS_ERROR(kg_get_context(minor_status, &context)))
       return(GSS_S_FAILURE);
@@ -84,12 +111,26 @@ krb5_gss_inquire_cred(minor_status, cred_handle, name, lifetime_ret,
       }
    }
 
-   if (mechanisms)
-      if (! g_copy_OID_set(cred->actual_mechs, &mechs)) {
-        krb5_free_principal(context, ret_name);
-        *minor_status = ENOMEM;
-        return(GSS_S_FAILURE);
-      }
+   if (mechanisms) {
+       if (GSS_ERROR(ret = generic_gss_create_empty_oid_set(minor_status,
+                                                           &mechs)) ||
+          (cred->prerfc_mech &&
+           GSS_ERROR(ret = generic_gss_add_oid_set_member(minor_status,
+                                                          gss_mech_krb5_old,
+                                                          &mechs))) ||
+          (cred->rfc_mech &&
+           GSS_ERROR(ret = generic_gss_add_oid_set_member(minor_status,
+                                                          gss_mech_krb5,
+                                                          &mechs))) ||
+          (cred->rfcv2_mech &&
+           GSS_ERROR(ret = generic_gss_add_oid_set_member(minor_status,
+                                                          gss_mech_krb5_v2,
+                                                          &mechs)))) {
+          krb5_free_principal(context, ret_name);
+          /* *minor_status set above */
+          return(ret);
+       }
+   }
 
    if (name) {
       if (! kg_save_name((gss_name_t) ret_name)) {
@@ -139,7 +180,9 @@ krb5_gss_inquire_cred_by_mech(minor_status, cred_handle,
      * We only know how to handle our own creds.
      */
     if ((mech_type != GSS_C_NULL_OID) &&
-       !g_OID_equal(gss_mech_krb5, mech_type)) {
+       !g_OID_equal(gss_mech_krb5_old, mech_type) &&
+       !g_OID_equal(gss_mech_krb5, mech_type) &&
+       !g_OID_equal(gss_mech_krb5_v2, mech_type)) {
        *minor_status = 0;
        return(GSS_S_NO_CRED);
     }
index 9c5f4745091206ac5887255b8aaf0f6f0e7b9a1c..01a1994301f106685bce12e115fee5acd56ffdcd 100644 (file)
@@ -43,10 +43,11 @@ krb5_gss_inquire_names_for_mech(minor_status, mechanism, name_types)
      * We only know how to handle our own mechanism.
      */
     if ((mechanism != GSS_C_NULL_OID) &&
+       !g_OID_equal(gss_mech_krb5_v2, mechanism) &&
        !g_OID_equal(gss_mech_krb5, mechanism) &&
        !g_OID_equal(gss_mech_krb5_old, mechanism)) {
        *minor_status = 0;
-       return(GSS_S_FAILURE);
+       return(GSS_S_BAD_MECH);
     }
 
     /* We're okay.  Create an empty OID set */
index c174bb7cbfc6bb4bad53c6024e2b613e043c7798..e1877b71f9c071da598fd2de83d2b0373405a1ae 100644 (file)
  * PERFORMANCE OF THIS SOFTWARE.
  */
 
+/*
+ * Copyright (C) 1998 by the FundsXpress, INC.
+ * 
+ * All rights reserved.
+ * 
+ * Export of this software from the United States of America may require
+ * a specific license from the United States Government.  It is the
+ * responsibility of any person or organization contemplating export to
+ * obtain such a license before exporting.
+ * 
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of FundsXpress. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  FundsXpress makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
 #include "gssapiP_krb5.h"
 
 static krb5_error_code
-make_seal_token(context, enc_ed, seq_ed, seqnum, direction, text, token,
-               signalg, cksum_size, sealalg, encrypt, toktype,
-               bigend, oid)
+make_priv_token_v2 PROTOTYPE((krb5_context context,
+                             krb5_keyblock *subkey,
+                             krb5_int32 *seqnum,
+                             int direction,
+                             gss_buffer_t text,
+                             gss_buffer_t token,
+                             gss_OID oid));
+
+static krb5_error_code
+make_priv_token_v2(context, subkey, seqnum, direction, text, token, oid)
      krb5_context context;
-     krb5_gss_enc_desc *enc_ed;
-     krb5_gss_enc_desc *seq_ed;
+     krb5_keyblock *subkey;
+     krb5_int32 *seqnum;
+     int direction;
+     gss_buffer_t text;
+     gss_buffer_t token;
+     gss_OID oid;
+{
+   krb5_data plain;
+   krb5_enc_data cipher;
+   krb5_error_code code;
+   size_t enclen;
+   int tlen;
+   unsigned char *t, *ptr;
+
+   plain.data = 0;
+   cipher.ciphertext.data = 0;
+   t = 0;
+
+   plain.length = 7+text->length;
+   if ((plain.data = (void *) malloc(plain.length)) == NULL) {
+       code = ENOMEM;
+       goto cleanup;
+   }
+
+   plain.data[0] = (*seqnum >> 24) & 0xff;
+   plain.data[1] = (*seqnum >> 16) & 0xff;
+   plain.data[2] = (*seqnum >> 8) & 0xff;
+   plain.data[3] = *seqnum & 0xff;
+
+   plain.data[4] = direction?0:0xff;
+   
+   plain.data[5] = (text->length >> 8) & 0xff;
+   plain.data[6] = text->length & 0xff;
+
+   memcpy(plain.data+7, text->value, text->length);
+
+   if (code = krb5_c_encrypt_length(context, subkey->enctype, 
+                                   plain.length, &enclen))
+       goto cleanup;
+
+   tlen = g_token_size((gss_OID) oid, 2+enclen);
+
+   if ((t = (unsigned char *) xmalloc(tlen)) == NULL)
+      return(ENOMEM);
+
+   ptr = t;
+
+   g_make_token_header((gss_OID) oid, 2+enclen, &ptr,
+                      KG2_TOK_WRAP_PRIV);
+
+   ptr[0] = (enclen >> 8) & 0xff;
+   ptr[1] = enclen & 0xff;
+
+   cipher.ciphertext.length = enclen;
+   cipher.ciphertext.data = ptr+2;
+
+   if (code = krb5_c_encrypt(context, subkey,
+                            KRB5_KEYUSAGE_GSS_TOK_WRAP_PRIV,
+                            0, &plain, &cipher))
+       goto cleanup;
+
+   /* that's it.  return the token */
+
+   (*seqnum)++;
+
+   token->length = tlen;
+   token->value = (void *) t;
+
+   code = 0;
+
+cleanup:
+   if (plain.data)
+       free(plain.data);
+   if (code) {
+       if (t)
+          free(t);
+   }
+
+   return(code);
+}
+
+static krb5_error_code
+make_integ_token_v2 PROTOTYPE((krb5_context context,
+                              krb5_keyblock *subkey,
+                              krb5_cksumtype ctype,
+                              krb5_int32 *seqnum,
+                              int direction,
+                              gss_buffer_t text,
+                              gss_buffer_t token,
+                              int toktype,
+                              gss_OID oid));
+
+static krb5_error_code
+make_integ_token_v2(context, subkey, ctype, seqnum, direction, text, token, 
+                   toktype, oid)
+     krb5_context context;
+     krb5_keyblock *subkey;
+     krb5_cksumtype ctype;
+     krb5_int32 *seqnum;
+     int direction;
+     gss_buffer_t text;
+     gss_buffer_t token;
+     int toktype;
+     gss_OID oid;
+{
+    krb5_error_code code;
+    int tmp, tlen;
+    unsigned char *t, *ptr;
+    krb5_data plain;
+    krb5_checksum cksum;
+
+    plain.data = 0;
+    t = 0;
+    cksum.contents = 0;
+
+    /* assemble the checksum buffer and compute the checksum */
+
+    plain.length = 7+text->length;
+
+    if ((plain.data = (char *) malloc(plain.length)) == NULL)
+       goto cleanup;
+
+    plain.data[0] = (*seqnum >> 24) & 0xff;
+    plain.data[1] = (*seqnum >> 16) & 0xff;
+    plain.data[2] = (*seqnum >> 8) & 0xff;
+    plain.data[3] = *seqnum & 0xff;
+
+    plain.data[4] = direction?0:0xff;
+
+    plain.data[5] = (text->length >> 8) & 0xff;
+    plain.data[6] = text->length & 0xff;
+
+    memcpy(plain.data+7, text->value, text->length);
+
+    if (code = krb5_c_make_checksum(context, ctype, subkey,
+                                   (toktype == KG2_TOK_WRAP_INTEG)?
+                                   KRB5_KEYUSAGE_GSS_TOK_WRAP_INTEG:
+                                   KRB5_KEYUSAGE_GSS_TOK_MIC,
+                                   &plain, &cksum))
+       goto cleanup;
+
+    /* assemble the token itself */
+
+    if (toktype == KG2_TOK_WRAP_INTEG)
+       tmp = 4+(7+text->length)+2+cksum.length;
+    else
+       tmp = 4+(5)+2+cksum.length;
+
+    tlen = g_token_size((gss_OID) oid, tmp);
+
+    if ((t = (unsigned char *) xmalloc(tlen)) == NULL)
+       return(ENOMEM);
+
+    ptr = t;
+
+    g_make_token_header((gss_OID) oid, tmp, &ptr, toktype);
+
+    ptr[0] = (ctype >> 24) & 0xff;
+    ptr[1] = (ctype >> 16) & 0xff;
+    ptr[2] = (ctype >> 8) & 0xff;
+    ptr[3] = ctype & 0xff;
+
+    ptr += 4;
+
+    if (toktype == KG2_TOK_WRAP_INTEG) {
+       memcpy(ptr, plain.data, 7+text->length);
+       ptr += 7+text->length;
+    } else {
+       memcpy(ptr, plain.data, 5);
+       ptr += 5;
+    }
+
+    ptr[0] = (cksum.length >> 8) & 0xff;
+    ptr[1] = cksum.length & 0xff;
+    ptr += 2;
+
+    memcpy(ptr, cksum.contents, cksum.length);
+
+    /* that's it.  return the token */
+
+    (*seqnum)++;
+
+    token->length = tlen;
+    token->value = (void *) t;
+
+    code = 0;
+
+cleanup:
+    if (plain.data)
+       free(plain.data);
+    if (cksum.contents)
+       krb5_free_checksum_contents(context, &cksum);
+    if (code) {
+       if (t)
+           free(t);
+    }
+
+   return(code);
+}
+
+static krb5_error_code
+make_seal_token_v1 PROTOTYPE((krb5_context context,
+                             krb5_keyblock *enc,
+                             krb5_keyblock *seq,
+                             krb5_int32 *seqnum,
+                             int direction,
+                             gss_buffer_t text,
+                             gss_buffer_t token,
+                             int signalg,
+                             int cksum_size,
+                             int sealalg,
+                             int encrypt,
+                             int toktype,
+                             int bigend,
+                             gss_OID oid));
+
+static krb5_error_code
+make_seal_token_v1(context, enc, seq, seqnum, direction, text, token,
+                  signalg, cksum_size, sealalg, encrypt, toktype,
+                  bigend, oid)
+     krb5_context context;
+     krb5_keyblock *enc;
+     krb5_keyblock *seq;
      krb5_int32 *seqnum;
      int direction;
      gss_buffer_t text;
@@ -42,7 +296,9 @@ make_seal_token(context, enc_ed, seq_ed, seqnum, direction, text, token,
      gss_OID oid;
 {
    krb5_error_code code;
+   size_t sumlen;
    char *data_ptr;
+   krb5_data plaind;
    krb5_checksum md5cksum;
    krb5_checksum cksum;
    int conflen=0, tmsglen, tlen;
@@ -54,7 +310,7 @@ make_seal_token(context, enc_ed, seq_ed, seqnum, direction, text, token,
       if (bigend && !encrypt) {
         tmsglen = text->length;
       } else {
-        conflen = kg_confounder_size(enc_ed);
+        conflen = kg_confounder_size(context, enc);
         /* XXX knows that des block size is 8 */
         tmsglen = (conflen+text->length+8)&(~7);
       }
@@ -96,27 +352,24 @@ make_seal_token(context, enc_ed, seq_ed, seqnum, direction, text, token,
 
    /* pad the plaintext, encrypt if needed, and stick it in the token */
 
-   /* initialize the the cksum and allocate the contents buffer */
+   /* initialize the the cksum */
+   if (code = krb5_c_checksum_length(context, CKSUMTYPE_RSA_MD5, &sumlen))
+       return(code);
+
    md5cksum.checksum_type = CKSUMTYPE_RSA_MD5;
-   md5cksum.length = krb5_checksum_size(context, CKSUMTYPE_RSA_MD5);
-   if ((md5cksum.contents = (krb5_octet *) xmalloc(md5cksum.length)) == NULL) {
-      return(ENOMEM);
-   }
+   md5cksum.length = sumlen;
    if (toktype == KG_TOK_SEAL_MSG) {
       unsigned char *plain;
       unsigned char pad;
 
       if (!bigend || encrypt) {
         if ((plain = (unsigned char *) xmalloc(tmsglen)) == NULL) {
-           xfree(md5cksum.contents);
            xfree(t);
            return(ENOMEM);
         }
 
-        if ((code = kg_make_confounder(enc_ed, plain))) {
+        if ((code = kg_make_confounder(context, enc, plain))) {
            xfree(plain);
-           xfree(md5cksum.contents);
            xfree(t);
            return(code);
         }
@@ -133,12 +386,11 @@ make_seal_token(context, enc_ed, seq_ed, seqnum, direction, text, token,
       }
 
       if (encrypt) {
-        if ((code = kg_encrypt(context, enc_ed, NULL, (krb5_pointer) plain,
+        if ((code = kg_encrypt(context, enc, NULL, (krb5_pointer) plain,
                                (krb5_pointer) (ptr+cksum_size+14),
                                tmsglen))) {
            if (plain)
               xfree(plain);
-           xfree(md5cksum.contents);
            xfree(t);
            return(code);
         }
@@ -156,7 +408,6 @@ make_seal_token(context, enc_ed, seq_ed, seqnum, direction, text, token,
             (char *) xmalloc(8 + (bigend ? text->length : tmsglen)))) {
          if (plain)
              xfree(plain);
-         xfree(md5cksum.contents);
          xfree(t);
          return(ENOMEM);
       }
@@ -165,15 +416,15 @@ make_seal_token(context, enc_ed, seq_ed, seqnum, direction, text, token,
          (void) memcpy(data_ptr+8, text->value, text->length);
       else
          (void) memcpy(data_ptr+8, plain, tmsglen);
-      code = krb5_calculate_checksum(context, md5cksum.checksum_type, data_ptr,
-                                    8 + (bigend ? text->length : tmsglen),
-                                    0, 0, &md5cksum);
+      plaind.length = 8 + (bigend ? text->length : tmsglen);
+      plaind.data = data_ptr;
+      code = krb5_c_make_checksum(context, md5cksum.checksum_type,
+                                 0, 0, &plaind, &md5cksum);
       xfree(data_ptr);
 
       if (code) {
          if (plain)
              xfree(plain);
-         xfree(md5cksum.contents);
          xfree(t);
          return(code);
          memcpy(ptr+14+cksum_size, plain, tmsglen);
@@ -185,18 +436,17 @@ make_seal_token(context, enc_ed, seq_ed, seqnum, direction, text, token,
       /* compute the checksum */
 
       if (! (data_ptr = (char *) xmalloc(8 + text->length))) {
-         xfree(md5cksum.contents);
          xfree(t);
          return(ENOMEM);
       }
       (void) memcpy(data_ptr, ptr-2, 8);
       (void) memcpy(data_ptr+8, text->value, text->length);
-      code = krb5_calculate_checksum(context, md5cksum.checksum_type, data_ptr,
-                                    8 + text->length,
-                                    0, 0, &md5cksum);
+      plaind.length = 8 + text->length;
+      plaind.data = data_ptr;
+      code = krb5_c_make_checksum(context, md5cksum.checksum_type, 0, 0,
+                                 &plaind, &md5cksum);
       xfree(data_ptr);
       if (code) {
-         xfree(md5cksum.contents);
          xfree(t);
          return(code);
       }
@@ -214,16 +464,19 @@ make_seal_token(context, enc_ed, seq_ed, seqnum, direction, text, token,
          DES encryption the long way, and keep the last block
          as the MAC */
 
+       /* XXX not converted to new api since it's inside an #if 0 */
+
        /* initialize the the cksum and allocate the contents buffer */
        cksum.checksum_type = CKSUMTYPE_DESCBC;
        cksum.length = krb5_checksum_size(context, CKSUMTYPE_DESCBC);
        if ((cksum.contents = (krb5_octet *) xmalloc(cksum.length)) == NULL)
           return(ENOMEM);
 
+       /* XXX not converted to new api since it's inside an #if 0 */
        if (code = krb5_calculate_checksum(context, cksum.checksum_type,
                                          md5cksum.contents, 16,
-                                         seq_ed->key->contents, 
-                                         seq_ed->key->length,
+                                         seq->contents, 
+                                         seq->length,
                                          &cksum)) {
          xfree(cksum.contents);
          xfree(md5cksum.contents);
@@ -235,9 +488,9 @@ make_seal_token(context, enc_ed, seq_ed, seqnum, direction, text, token,
 
        xfree(cksum.contents);
 #else
-       if ((code = kg_encrypt(context, seq_ed,
+       if ((code = kg_encrypt(context, seq,
                              (g_OID_equal(oid, gss_mech_krb5_old) ?
-                              seq_ed->key->contents : NULL),
+                              seq->contents : NULL),
                              md5cksum.contents, md5cksum.contents, 16))) {
          xfree(md5cksum.contents);
          xfree(t);
@@ -257,7 +510,7 @@ make_seal_token(context, enc_ed, seq_ed, seqnum, direction, text, token,
 
    /* create the seq_num */
 
-   if ((code = kg_make_seq_num(context, seq_ed, direction?0:0xff, *seqnum,
+   if ((code = kg_make_seq_num(context, seq, direction?0:0xff, *seqnum,
                               ptr+14, ptr+6))) {
       xfree(t);
       return(code);
@@ -320,17 +573,42 @@ kg_seal(context, minor_status, context_handle, conf_req_flag, qop_req,
       return(GSS_S_FAILURE);
    }
 
-   if ((code = make_seal_token(context, &ctx->enc, &ctx->seq,
-                              &ctx->seq_send, ctx->initiate,
-                              input_message_buffer, output_message_buffer,
-                              ctx->signalg, ctx->cksum_size, ctx->sealalg,
-                              conf_req_flag, toktype, ctx->big_endian,
-                              ctx->mech_used))) {
+   if (ctx->gsskrb5_version == 2000) {
+       if (toktype == KG_TOK_WRAP_MSG) {
+          if (conf_req_flag)
+              toktype = KG2_TOK_WRAP_PRIV;
+          else
+              toktype = KG2_TOK_WRAP_INTEG;
+       } else {
+          toktype = KG2_TOK_MIC;
+       }
+
+       if (conf_req_flag) {
+          code = make_priv_token_v2(context, ctx->subkey, &ctx->seq_send,
+                                    ctx->initiate, input_message_buffer,
+                                    output_message_buffer, ctx->mech_used);
+       } else {
+          code = make_integ_token_v2(context, ctx->subkey, ctx->ctypes[0],
+                                     &ctx->seq_send, ctx->initiate,
+                                     input_message_buffer,
+                                     output_message_buffer, toktype,
+                                     ctx->mech_used);
+       }
+   } else {
+       code = make_seal_token_v1(context, ctx->enc, ctx->seq,
+                                &ctx->seq_send, ctx->initiate,
+                                input_message_buffer, output_message_buffer,
+                                ctx->signalg, ctx->cksum_size, ctx->sealalg,
+                                conf_req_flag, toktype, ctx->big_endian,
+                                ctx->mech_used);
+   }
+
+   if (code) {
       *minor_status = code;
       return(GSS_S_FAILURE);
    }
 
-   if ((toktype == KG_TOK_SEAL_MSG) && conf_state)
+   if (conf_state)
       *conf_state = conf_req_flag;
 
    *minor_status = 0;
index 041cae06a3e6cd146a74719e5c0ff247320a1b64..c32e3255d5f436eb50f0ecba9505d9f811e08fa3 100644 (file)
  * PERFORMANCE OF THIS SOFTWARE.
  */
 
+/*
+ * Copyright (C) 1998 by the FundsXpress, INC.
+ * 
+ * All rights reserved.
+ * 
+ * Export of this software from the United States of America may require
+ * a specific license from the United States Government.  It is the
+ * responsibility of any person or organization contemplating export to
+ * obtain such a license before exporting.
+ * 
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of FundsXpress. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  FundsXpress makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
 #include "gssapiP_krb5.h"
 #include <memory.h>
 
  * $Id$
  */
 
+static OM_uint32
+kg2_verify_mic(context, minor_status, ctx, ptr, bodysize,
+              text, qop_state)
+     krb5_context context;
+     OM_uint32 *minor_status;
+     krb5_gss_ctx_id_rec *ctx;
+     unsigned char *ptr;
+     int bodysize;
+     gss_buffer_t text;
+     gss_qop_t *qop_state;
+{
+    size_t cksumlen;
+    krb5_error_code code;
+    krb5_data plain;
+    krb5_cksumtype tctype;
+    krb5_ui_4 tseqnum;
+    int tdirection;
+    krb5_checksum cksum;
+    krb5_boolean ckvalid;
+    krb5_timestamp now;
+    OM_uint32 retval;
+
+    plain.data = 0;
+    cksum.contents = 0;
+
+    /* verify the header */
+
+    if (bodysize < 11) {
+       free(plain.data);
+       *minor_status = G_TOK_TRUNC;
+       return(GSS_S_DEFECTIVE_TOKEN);
+    }
+
+    /* allocate the checksum buffer */
+
+    plain.length = 7+text->length;
+
+    if ((plain.data = (char *) malloc(plain.length)) == NULL) {
+       *minor_status = ENOMEM;
+       return(GSS_S_FAILURE);
+    }
+
+    /* suck out the body parts from the token */
+
+    tctype = (krb5_cksumtype) ((ptr[0]<<24) | (ptr[1]<<16) |
+                              (ptr[2]<<8) | ptr[3]);
+    ptr += 4;
+
+    memcpy(plain.data, ptr, 5);
+    tseqnum = ((ptr[0]<<24) | (ptr[1]<<16) | (ptr[2]<<8) | ptr[3]);
+    ptr += 4;
+    tdirection = ptr[0];
+    ptr += 1;
+
+    cksum.length = (ptr[0]<<8) | ptr[1];
+    ptr += 2;
+    bodysize -= 11;
+
+    if (cksum.length != bodysize) {
+       free(plain.data);
+       *minor_status = G_TOK_TRUNC;
+       return(GSS_S_DEFECTIVE_TOKEN);
+    }
+
+    cksum.contents = ptr;
+    cksum.checksum_type = tctype;
+
+    /* finish assembling the checksum buffer and compute the checksum */
+
+    plain.data[5] = (text->length >> 8) & 0xff;
+    plain.data[6] = text->length & 0xff;
+
+    memcpy(plain.data+7, text->value, text->length);
+
+    if (code = krb5_c_verify_checksum(context, ctx->subkey,
+                                     KRB5_KEYUSAGE_GSS_TOK_MIC,
+                                     &plain, &cksum, &ckvalid)) {
+       free(plain.data);
+       *minor_status = code;
+       return(GSS_S_FAILURE);
+    }
+
+    if (!ckvalid) {
+       free(plain.data);
+       *minor_status = 0;
+       return(GSS_S_BAD_SIG);
+    }
+
+    /* check context expiry */
+
+   if ((code = krb5_timeofday(context, &now))) {
+       free(plain.data);
+       *minor_status = code;
+       return(GSS_S_FAILURE);
+   }
+
+   if (now > ctx->endtime) {
+       free(plain.data);
+       *minor_status = 0;
+       return(GSS_S_CONTEXT_EXPIRED);
+   }
+
+   /* do sequencing checks */
+
+   if ((ctx->initiate && tdirection != 0xff) ||
+       (!ctx->initiate && tdirection != 0)) {
+       free(plain.data);
+       *minor_status = G_BAD_DIRECTION;
+       return(GSS_S_BAD_SIG);
+   }
+
+   retval = g_order_check(&(ctx->seqstate), tseqnum);
+
+   free(plain.data);
+
+   if (retval) {
+       *minor_status = 0;
+       return(retval);
+   }
+
+   if (qop_state)
+       *qop_state = GSS_C_QOP_DEFAULT;
+
+   *minor_status = 0;
+   return(GSS_S_COMPLETE);
+}
+
+static OM_uint32
+kg2_unwrap_integ(context, minor_status, ctx, ptr, bodysize, output, qop_state)
+     krb5_context context;
+     OM_uint32 *minor_status;
+     krb5_gss_ctx_id_rec *ctx;
+     unsigned char *ptr;
+     int bodysize;
+     gss_buffer_t output;
+     gss_qop_t *qop_state;
+{
+    krb5_error_code code;
+    OM_uint32 retval;
+    krb5_ui_4 tseqnum;
+    int tdirection;
+    int tmsglen;
+    unsigned char *tmsg;
+    krb5_data plain;
+    krb5_checksum tcksum;
+    krb5_boolean ckvalid;
+    krb5_timestamp now;
+
+    output->length = 0;
+    output->value = NULL;
+
+    /* read the body parts out of the message */
+
+    if (bodysize < 11) {
+       *minor_status = G_TOK_TRUNC;
+       return(GSS_S_DEFECTIVE_TOKEN);
+    }
+
+    tcksum.checksum_type = (krb5_cksumtype) ((ptr[0]<<24) | (ptr[1]<<16) |
+                                            (ptr[2]<<8) | ptr[3]);
+    ptr += 4;
+
+    plain.data = ptr;
+
+    tseqnum = ((ptr[0]<<24) | (ptr[1]<<16) | (ptr[2]<<8) | ptr[3]);
+    ptr += 4;
+    tdirection = ptr[0];
+    ptr += 1;
+
+    tmsglen = (ptr[0]<<8) | ptr[1];
+    ptr += 2;
+    bodysize -= 11;
+
+    if (bodysize < tmsglen) {
+       *minor_status = G_TOK_TRUNC;
+       return(GSS_S_DEFECTIVE_TOKEN);
+    }
+
+    tmsg = ptr;
+    ptr += tmsglen;
+    bodysize -= tmsglen;
+
+    plain.length = ((char*)ptr) - ((char *)plain.data);
+
+    tcksum.length = (ptr[0]<<8) | ptr[1];
+    ptr += 2;
+    bodysize -= 2;
+
+    if (bodysize != tcksum.length) {
+       *minor_status = G_TOK_TRUNC;
+       return(GSS_S_DEFECTIVE_TOKEN);
+    }
+
+    tcksum.contents = ptr;
+
+    /* verify the MIC */
+
+    if (code = krb5_c_verify_checksum(context, ctx->subkey,
+                                     KRB5_KEYUSAGE_GSS_TOK_WRAP_INTEG,
+                                     &plain, &tcksum, &ckvalid)) {
+       *minor_status = code;
+       return(GSS_S_FAILURE);
+    }
+
+    if (!ckvalid) {
+       *minor_status = 0;
+       return(GSS_S_BAD_SIG);
+    }
+
+    /* check context expiry */
+
+   if ((code = krb5_timeofday(context, &now))) {
+       *minor_status = code;
+       return(GSS_S_FAILURE);
+   }
+
+   if (now > ctx->endtime) {
+       *minor_status = 0;
+       return(GSS_S_CONTEXT_EXPIRED);
+   }
+
+   /* do sequencing checks */
+
+   if ((ctx->initiate && tdirection != 0xff) ||
+       (!ctx->initiate && tdirection != 0)) {
+       *minor_status = G_BAD_DIRECTION;
+       return(GSS_S_BAD_SIG);
+   }
+
+   if (retval = g_order_check(&(ctx->seqstate), tseqnum)) {
+       *minor_status = 0;
+       return(retval);
+   }
+
+   if ((output->value = (void *) malloc(tmsglen)) == NULL) {
+       *minor_status = ENOMEM;
+       return(GSS_S_FAILURE);
+   }
+
+   memcpy(output->value, tmsg, tmsglen);
+   output->length = tmsglen;
+
+   if (qop_state)
+       *qop_state = GSS_C_QOP_DEFAULT;
+
+   *minor_status = 0;
+   return(GSS_S_COMPLETE);
+}
+
+static OM_uint32
+kg2_unwrap_priv(context, minor_status, ctx, ptr, bodysize, output, qop_state)
+     krb5_context context;
+     OM_uint32 *minor_status;
+     krb5_gss_ctx_id_rec *ctx;
+     unsigned char *ptr;
+     int bodysize;
+     gss_buffer_t output;
+     gss_qop_t *qop_state;
+{
+    krb5_error_code code;
+    OM_uint32 retval;
+    krb5_enc_data cipher;
+    krb5_data plain;
+    krb5_ui_4 tseqnum;
+    int tdirection;
+    int tmsglen;
+    unsigned char *tmsg;
+    krb5_timestamp now;
+
+    output->length = 0;
+    output->value = NULL;
+
+    /* read the body parts out of the message */
+
+    if (bodysize < 2) {
+       *minor_status = G_TOK_TRUNC;
+       return(GSS_S_DEFECTIVE_TOKEN);
+    }
+
+    cipher.ciphertext.length = (ptr[0]<<8) | ptr[1];
+    ptr += 2;
+    bodysize -= 2;
+
+    if (bodysize != cipher.ciphertext.length) {
+       *minor_status = G_TOK_TRUNC;
+       return(GSS_S_DEFECTIVE_TOKEN);
+    }
+
+    cipher.ciphertext.data = ptr;
+    cipher.enctype = ENCTYPE_UNKNOWN;
+
+    plain.length = cipher.ciphertext.length;
+    if ((plain.data = (char *) malloc(plain.length)) == NULL) {
+       *minor_status = 0;
+       return(GSS_S_FAILURE);
+    }
+
+    /* decrypt (and implicitly verify) the encrypted data */
+
+    if (code = krb5_c_decrypt(context, ctx->subkey,
+                             KRB5_KEYUSAGE_GSS_TOK_WRAP_PRIV,
+                             0, &cipher, &plain)) {
+       free(plain.data);
+       *minor_status = code;
+       return(GSS_S_FAILURE);
+    }
+
+    /* parse out the encrypted fields */
+
+    ptr = plain.data;
+    bodysize = plain.length;
+
+    if (bodysize < 7) {
+       free(plain.data);
+       *minor_status = G_TOK_TRUNC;
+       return(GSS_S_DEFECTIVE_TOKEN);
+    }
+
+    tseqnum = ((ptr[0]<<24) | (ptr[1]<<16) | (ptr[2]<<8) | ptr[3]);
+    ptr += 4;
+    tdirection = ptr[0];
+    ptr += 1;
+
+    tmsglen = (ptr[0]<<8) | ptr[1];
+    ptr += 2;
+    bodysize -= 7;
+
+    /* check context expiry */
+
+    if ((code = krb5_timeofday(context, &now))) {
+       free(plain.data);
+       *minor_status = code;
+       return(GSS_S_FAILURE);
+    }
+
+    if (now > ctx->endtime) {
+       free(plain.data);
+       *minor_status = 0;
+       return(GSS_S_CONTEXT_EXPIRED);
+    }
+
+    /* do sequencing checks */
+
+    if ((ctx->initiate && tdirection != 0xff) ||
+       (!ctx->initiate && tdirection != 0)) {
+       free(plain.data);
+       *minor_status = G_BAD_DIRECTION;
+       return(GSS_S_BAD_SIG);
+    }
+
+    if (retval = g_order_check(&(ctx->seqstate), tseqnum)) {
+       free(plain.data);
+       *minor_status = 0;
+       return(retval);
+    }
+
+    /* now copy out the data.  can't do a strict equality check here,
+       since the output could be padded.  */
+
+    if (bodysize < tmsglen) {
+       free(plain.data);
+       *minor_status = G_TOK_TRUNC;
+       return(GSS_S_DEFECTIVE_TOKEN);
+    }
+
+    tmsg = ptr;
+
+    if ((output->value = (void *) malloc(tmsglen)) == NULL) {
+       free(plain.data);
+       *minor_status = ENOMEM;
+       return(GSS_S_FAILURE);
+    }
+
+    memcpy(output->value, tmsg, tmsglen);
+    output->length = tmsglen;
+
+    if (qop_state)
+       *qop_state = GSS_C_QOP_DEFAULT;
+
+    free(plain.data);
+
+    *minor_status = 0;
+    return(GSS_S_COMPLETE);
+}
+
 /* message_buffer is an input if SIGN, output if SEAL, and ignored if DEL_CTX
-   conf_state is only valid if SEAL.
-   */
+   conf_state is only valid if SEAL. */
 
 OM_uint32
-kg_unseal(context, minor_status, context_handle, input_token_buffer,
-         message_buffer, conf_state, qop_state, toktype)
+kg_unseal_v1(context, minor_status, ctx, ptr, bodysize, message_buffer,
+            conf_state, qop_state, toktype)
      krb5_context context;
      OM_uint32 *minor_status;
-     gss_ctx_id_t context_handle;
-     gss_buffer_t input_token_buffer;
+     krb5_gss_ctx_id_rec *ctx;
+     unsigned char *ptr;
+     int bodysize;
      gss_buffer_t message_buffer;
      int *conf_state;
      int *qop_state;
      int toktype;
 {
-   krb5_gss_ctx_id_rec *ctx;
    krb5_error_code code;
-   int bodysize;
    int tmsglen;
    int conflen = 0;
    int signalg;
    int sealalg;
    gss_buffer_desc token;
-   unsigned char *ptr;
    krb5_checksum cksum;
    krb5_checksum desmac;
    krb5_checksum md5cksum;
+   krb5_data plaind;
    char *data_ptr;
    krb5_timestamp now;
    unsigned char *plain;
@@ -64,38 +473,13 @@ kg_unseal(context, minor_status, context_handle, input_token_buffer,
    int direction;
    krb5_int32 seqnum;
    OM_uint32 retval;
+   size_t sumlen;
 
    if (toktype == KG_TOK_SEAL_MSG) {
       message_buffer->length = 0;
       message_buffer->value = NULL;
    }
 
-   /* validate the context handle */
-   if (! kg_validate_ctx_id(context_handle)) {
-      *minor_status = (OM_uint32) G_VALIDATE_FAILED;
-      return(GSS_S_NO_CONTEXT);
-   }
-
-   ctx = (krb5_gss_ctx_id_rec *) context_handle;
-
-   if (! ctx->established) {
-      *minor_status = KG_CTX_INCOMPLETE;
-      return(GSS_S_NO_CONTEXT);
-   }
-
-   /* parse the token, leave the data in message_buffer, setting conf_state */
-
-   /* verify the header */
-
-   ptr = (unsigned char *) input_token_buffer->value;
-
-   if ((err = g_verify_token_header((gss_OID) ctx->mech_used, &bodysize,
-                                   &ptr, toktype,
-                                   input_token_buffer->length))) {
-      *minor_status = err;
-      return(GSS_S_DEFECTIVE_TOKEN);
-   }
-
    /* get the sign and seal algorithms */
 
    signalg = ptr[0] + (ptr[1]<<8);
@@ -159,7 +543,7 @@ kg_unseal(context, minor_status, context_handle, input_token_buffer,
            return(GSS_S_FAILURE);
         }
 
-        if ((code = kg_decrypt(context, &ctx->enc, NULL,
+        if ((code = kg_decrypt(context, ctx->enc, NULL,
                                ptr+14+cksum_len, plain, tmsglen))) {
            xfree(plain);
            *minor_status = code;
@@ -174,7 +558,7 @@ kg_unseal(context, minor_status, context_handle, input_token_buffer,
       if ((sealalg == 0xffff) && ctx->big_endian) {
         token.length = tmsglen;
       } else {
-        conflen = kg_confounder_size(&ctx->enc);
+        conflen = kg_confounder_size(context, ctx->enc);
         token.length = tmsglen - conflen - plain[tmsglen-1];
       }
 
@@ -200,15 +584,12 @@ kg_unseal(context, minor_status, context_handle, input_token_buffer,
 
    /* compute the checksum of the message */
 
-   /* initialize the the cksum and allocate the contents buffer */
+   /* initialize the the cksum */
+   if (code = krb5_c_checksum_length(context, CKSUMTYPE_RSA_MD5, &sumlen))
+       return(code);
+
    md5cksum.checksum_type = CKSUMTYPE_RSA_MD5;
-   md5cksum.length = krb5_checksum_size(context, CKSUMTYPE_RSA_MD5);
-   if ((md5cksum.contents = (krb5_octet *) xmalloc(md5cksum.length)) == NULL) {
-      if (sealalg != 0xffff)
-        xfree(plain);
-      *minor_status = ENOMEM;
-      return(GSS_S_FAILURE);
-   }
+   md5cksum.length = sumlen;
 
    switch (signalg) {
    case 0:
@@ -219,7 +600,6 @@ kg_unseal(context, minor_status, context_handle, input_token_buffer,
 
       if (! (data_ptr = (void *)
             xmalloc(8 + (ctx->big_endian ? token.length : plainlen)))) {
-         xfree(md5cksum.contents);
          if (sealalg != 0xffff)
              xfree(plain);
          if (toktype == KG_TOK_SEAL_MSG)
@@ -235,14 +615,13 @@ kg_unseal(context, minor_status, context_handle, input_token_buffer,
       else
          (void) memcpy(data_ptr+8, plain, plainlen);
 
-      code = krb5_calculate_checksum(context, md5cksum.checksum_type,
-                                    data_ptr, 8 +
-                                    (ctx->big_endian ? token.length :
-                                     plainlen), 0, 0, &md5cksum);
+      plaind.length = 8 + (ctx->big_endian ? token.length : plainlen);
+      plaind.data = data_ptr;
+      code = krb5_c_make_checksum(context, md5cksum.checksum_type, 0, 0,
+                                 &plaind, &md5cksum);
       xfree(data_ptr);
 
       if (code) {
-         xfree(md5cksum.contents);
          if (toktype == KG_TOK_SEAL_MSG)
              xfree(token.value);
          *minor_status = code;
@@ -264,6 +643,7 @@ kg_unseal(context, minor_status, context_handle, input_token_buffer,
          return(GSS_S_FAILURE);
       }
 
+      /* XXX not converted to new api since it's inside an #if 0 */
       if (code = krb5_calculate_checksum(context, cksum.checksum_type,
                                         md5cksum.contents, 16,
                                         ctx->seq.key->contents, 
@@ -281,9 +661,9 @@ kg_unseal(context, minor_status, context_handle, input_token_buffer,
 
       xfree(cksum.contents);
 #else
-      if ((code = kg_encrypt(context, &ctx->seq,
+      if ((code = kg_encrypt(context, ctx->seq,
                             (g_OID_equal(ctx->mech_used, gss_mech_krb5_old) ?
-                             ctx->seq.key->contents : NULL),
+                             ctx->seq->contents : NULL),
                             md5cksum.contents, md5cksum.contents, 16))) {
         xfree(md5cksum.contents);
         if (toktype == KG_TOK_SEAL_MSG)
@@ -333,15 +713,15 @@ kg_unseal(context, minor_status, context_handle, input_token_buffer,
       else
          (void) memcpy(data_ptr+8+sizeof(ctx->seed),
                        plain, plainlen);
-      code = krb5_calculate_checksum(context, md5cksum.checksum_type,
-                                    data_ptr, 8 + sizeof(ctx->seed) +
-                                    (ctx->big_endian ? token.length :
-                                     plainlen), 0, 0, &md5cksum);
-
+      plaind.length = 8 + sizeof(ctx->seed) +
+         (ctx->big_endian ? token.length : plainlen);
+      plaind.data = data_ptr;
+      xfree(md5cksum.contents);
+      code = krb5_c_make_checksum(context, md5cksum.checksum_type, 0, 0,
+                                 &plaind, &md5cksum);
       xfree(data_ptr);
 
       if (code) {
-         xfree(md5cksum.contents);
          if (sealalg == 0)
              xfree(plain);
          if (toktype == KG_TOK_SEAL_MSG)
@@ -394,7 +774,7 @@ kg_unseal(context, minor_status, context_handle, input_token_buffer,
 
    /* do sequencing checks */
 
-   if ((code = kg_get_seq_num(context, &(ctx->seq), ptr+14, ptr+6, &direction,
+   if ((code = kg_get_seq_num(context, ctx->seq, ptr+14, ptr+6, &direction,
                              &seqnum))) {
       if (toktype == KG_TOK_SEAL_MSG)
         xfree(token.value);
@@ -417,3 +797,88 @@ kg_unseal(context, minor_status, context_handle, input_token_buffer,
    *minor_status = 0;
    return(retval);
 }
+
+/* message_buffer is an input if SIGN, output if SEAL, and ignored if DEL_CTX
+   conf_state is only valid if SEAL. */
+
+OM_uint32
+kg_unseal(context, minor_status, context_handle, input_token_buffer,
+         message_buffer, conf_state, qop_state, toktype)
+     krb5_context context;
+     OM_uint32 *minor_status;
+     gss_ctx_id_t context_handle;
+     gss_buffer_t input_token_buffer;
+     gss_buffer_t message_buffer;
+     int *conf_state;
+     int *qop_state;
+     int toktype;
+{
+   krb5_gss_ctx_id_rec *ctx;
+   unsigned char *ptr;
+   int bodysize;
+   int err;
+   OM_uint32 retval;
+
+   /* validate the context handle */
+   if (! kg_validate_ctx_id(context_handle)) {
+      *minor_status = (OM_uint32) G_VALIDATE_FAILED;
+      return(GSS_S_NO_CONTEXT);
+   }
+
+   ctx = (krb5_gss_ctx_id_rec *) context_handle;
+
+   if (! ctx->established) {
+      *minor_status = KG_CTX_INCOMPLETE;
+      return(GSS_S_NO_CONTEXT);
+   }
+
+   /* parse the token, leave the data in message_buffer, setting conf_state */
+
+   /* verify the header */
+
+   ptr = (unsigned char *) input_token_buffer->value;
+
+   if (ctx->gsskrb5_version == 2000) {
+       if (!(err = g_verify_token_header((gss_OID) ctx->mech_used,
+                                        &bodysize, &ptr, KG2_TOK_MIC,
+                                        input_token_buffer->length))) {
+          return(kg2_verify_mic(context, minor_status, ctx, ptr, bodysize,
+                                message_buffer, qop_state));
+       } else if (!(err = g_verify_token_header((gss_OID) ctx->mech_used,
+                                               &bodysize, &ptr,
+                                               KG2_TOK_WRAP_INTEG,
+                                               input_token_buffer->length))) {
+          if (GSS_ERROR(retval = kg2_unwrap_integ(context, minor_status,
+                                                  ctx, ptr, bodysize,
+                                                  message_buffer, qop_state)))
+              return(retval);
+
+          if (conf_state)
+              *conf_state = 0;
+          return(GSS_S_COMPLETE);
+       } else if (!(err = g_verify_token_header((gss_OID) ctx->mech_used,
+                                               &bodysize, &ptr,
+                                               KG2_TOK_WRAP_PRIV,
+                                               input_token_buffer->length))) {
+          if (GSS_ERROR(retval = kg2_unwrap_priv(context, minor_status,
+                                                 ctx, ptr, bodysize,
+                                                 message_buffer, qop_state)))
+              return(retval);
+
+          if (conf_state)
+              *conf_state = 1;
+          return(GSS_S_COMPLETE);
+       }
+   } else {
+       if (!(err = g_verify_token_header((gss_OID) ctx->mech_used,
+                                        &bodysize, &ptr, toktype,
+                                        input_token_buffer->length))) {
+          return(kg_unseal_v1(context, minor_status, ctx, ptr, bodysize,
+                              message_buffer, conf_state, qop_state,
+                              toktype));
+       }
+   }
+
+   *minor_status = err;
+   return(GSS_S_DEFECTIVE_TOKEN);
+}
index f35727e3f1b34d384d427bd59fc3b91e0e373c63..afb2171b865f297a09628dd93047eddd6219a48e 100644 (file)
@@ -63,7 +63,8 @@ krb5_gss_internal_release_oid(minor_status, oid)
      * return GSS_S_CONTINUE_NEEDED for any OIDs it does not recognize.
      */
    
-    if ((*oid != gss_mech_krb5) &&
+    if ((*oid != gss_mech_krb5_v2) &&
+       (*oid != gss_mech_krb5) &&
        (*oid != gss_mech_krb5_old) &&
        (*oid != gss_nt_krb5_name) &&
        (*oid != gss_nt_krb5_principal)) {
index 36e70d742cc210cc2fc128dee01c13e7514300dd..36a16d426e4249e1c067e1b233bd658654c63c6d 100644 (file)
  * still be done. --marc
  */
 
-/*
- * Determine the size required for this krb5_gss_enc_desc.
- */
-static krb5_error_code
-kg_enc_desc_size(kcontext, arg, sizep)
-    krb5_context       kcontext;
-    krb5_pointer       arg;
-    size_t             *sizep;
-{
-    krb5_error_code    kret;
-    krb5_gss_enc_desc  *edescp;
-    size_t             required;
-
-    /*
-     * krb5_gss_cred_id_t requires:
-     * krb5_int32      for KG_ENC_DESC
-     * krb5_int32      for processed.
-     * krb5_int32      for trailer.
-     */
-    kret = EINVAL;
-    if ((edescp = (krb5_gss_enc_desc *) arg)) {
-       required = 3*sizeof(krb5_int32);
-       if (edescp->key)
-           kret = krb5_size_opaque(kcontext,
-                                   KV5M_KEYBLOCK,
-                                   (krb5_pointer) edescp->key,
-                                   &required);
-       else
-           kret = 0;
-       
-        /*
-         * We need to use size_opaque here because we're not sure as to the
-         * ancestry of this eblock, and we can't be sure that the magic number
-         * is set in it, so we ASSuME that it's ok.
-         */
-       if (!kret)
-           kret = krb5_size_opaque(kcontext,
-                                   KV5M_ENCRYPT_BLOCK,
-                                   (krb5_pointer) &edescp->eblock,
-                                   &required);
-
-       if (!kret)
-           *sizep += required;
-    }
-    return(kret);
-}
-
-/*
- * Externalize this krb5_gss_enc_desc.
- */
-static krb5_error_code
-kg_enc_desc_externalize(kcontext, arg, buffer, lenremain)
-    krb5_context       kcontext;
-    krb5_pointer       arg;
-    krb5_octet         **buffer;
-    size_t             *lenremain;
-{
-    krb5_error_code    kret;
-    krb5_gss_enc_desc  *enc_desc;
-    size_t             required;
-    krb5_octet         *bp;
-    size_t             remain;
-
-    required = 0;
-    bp = *buffer;
-    remain = *lenremain;
-    kret = EINVAL;
-    if ((enc_desc = (krb5_gss_enc_desc *) arg)) {
-       kret = ENOMEM;
-       if (!kg_enc_desc_size(kcontext, arg, &required) &&
-           (required <= remain)) {
-           /* Our identifier */
-           (void) krb5_ser_pack_int32(KG_ENC_DESC, &bp, &remain);
-
-           /* Now static data */
-           (void) krb5_ser_pack_int32((krb5_int32) enc_desc->processed,
-                                      &bp, &remain);
-
-           /* Now pack up dynamic data */
-           if (enc_desc->key)
-               kret = krb5_externalize_opaque(kcontext,
-                                              KV5M_KEYBLOCK,
-                                              (krb5_pointer) enc_desc->key,
-                                              &bp, &remain);
-           else
-               kret = 0;
-
-           if (!kret)
-               kret = krb5_externalize_opaque(kcontext,
-                                              KV5M_ENCRYPT_BLOCK,
-                                              (krb5_pointer)&enc_desc->eblock,
-                                              &bp, &remain);
-           if (!kret) {
-               (void) krb5_ser_pack_int32(KG_ENC_DESC, &bp, &remain);
-               *buffer = bp;
-               *lenremain = remain;
-           }
-       }
-    }
-    return(kret);
-}
-
-/*
- * Internalize this krb5_gss_enc_desc.
- */
-static krb5_error_code
-kg_enc_desc_internalize(kcontext, argp, buffer, lenremain)
-    krb5_context       kcontext;
-    krb5_pointer       *argp;
-    krb5_octet         **buffer;
-    size_t             *lenremain;
-{
-    krb5_error_code    kret;
-    krb5_gss_enc_desc  *edescp;
-    krb5_int32         ibuf;
-    krb5_octet         *bp;
-    krb5_encrypt_block *eblockp;
-    size_t             remain;
-
-    bp = *buffer;
-    remain = *lenremain;
-    kret = EINVAL;
-    /* Read our magic number */
-    if (krb5_ser_unpack_int32(&ibuf, &bp, &remain))
-       ibuf = 0;
-    if (ibuf == KG_ENC_DESC) {
-       kret = ENOMEM;
-
-       /* Get an enc_desc */
-       if ((remain >= (2*sizeof(krb5_int32))) &&
-           (edescp = (krb5_gss_enc_desc *)
-            xmalloc(sizeof(krb5_gss_enc_desc)))) {
-           memset(edescp, 0, sizeof(krb5_gss_enc_desc));
-
-           /* Get the static data */
-           (void) krb5_ser_unpack_int32(&ibuf, &bp, &remain);
-           edescp->processed = (int) ibuf;
-
-           /* edescp->key */
-           if ((kret = krb5_internalize_opaque(kcontext,
-                                               KV5M_KEYBLOCK,
-                                               (krb5_pointer *) &edescp->key,
-                                               &bp, &remain))) {
-               if (kret == EINVAL)
-                   kret = 0;
-           }
-
-           /* edescp->eblock */
-           if (!kret &&
-               (kret = krb5_internalize_opaque(kcontext,
-                                               KV5M_ENCRYPT_BLOCK,
-                                               (krb5_pointer *) &eblockp,
-                                               &bp, &remain))) {
-               if (kret == EINVAL)
-                   kret = 0;
-           }
-           else {
-               /* Successful, copy in allocated eblock to our structure */
-               memcpy(&edescp->eblock, eblockp, sizeof(edescp->eblock));
-               krb5_xfree(eblockp);
-           }
-
-           /* trailer */
-           if (!kret &&
-               !(kret = krb5_ser_unpack_int32(&ibuf, &bp, &remain)) &&
-               (ibuf == KG_ENC_DESC)) {
-               *buffer = bp;
-               *lenremain = remain;
-               *argp = (krb5_pointer) edescp;
-           }
-           else {
-               if (!kret && (ibuf != KG_ENC_DESC))
-                   kret = EINVAL;
-               if (edescp->eblock.key)
-                   krb5_free_keyblock(kcontext, edescp->eblock.key);
-               if (edescp->eblock.priv && edescp->eblock.priv_size)
-                   krb5_xfree(edescp->eblock.priv);
-               if (edescp->key)
-                   krb5_free_keyblock(kcontext, edescp->key);
-               xfree(edescp);
-           }
-       }
-    }
-    return(kret);
-}
-
 static krb5_error_code
 kg_oid_externalize(kcontext, arg, buffer, lenremain)
     krb5_context       kcontext;
@@ -416,12 +230,15 @@ kg_ctx_size(kcontext, arg, sizep)
      * krb5_int32      for seq_recv.
      * krb5_int32      for established.
      * krb5_int32      for big_endian.
+     * krb5_int32      for gsskrb5_version.
+     * krb5_int32      for nctypes.
      * krb5_int32      for trailer.
      */
     kret = EINVAL;
     if ((ctx = (krb5_gss_ctx_id_rec *) arg)) {
-       required = 14*sizeof(krb5_int32);
+       required = 16*sizeof(krb5_int32);
        required += sizeof(ctx->seed);
+       required += ctx->nctypes*sizeof(krb5_int32);
 
        kret = 0;
        if (!kret && ctx->here)
@@ -442,14 +259,16 @@ kg_ctx_size(kcontext, arg, sizep)
                                    (krb5_pointer) ctx->subkey,
                                    &required);
 
-       if (!kret)
-           kret = kg_enc_desc_size(kcontext,
-                                   (krb5_pointer) &ctx->enc,
+       if (!kret && ctx->enc)
+           kret = krb5_size_opaque(kcontext,
+                                   KV5M_KEYBLOCK,
+                                   (krb5_pointer) ctx->enc,
                                    &required);
 
-       if (!kret)
-           kret = kg_enc_desc_size(kcontext,
-                                   (krb5_pointer) &ctx->seq,
+       if (!kret && ctx->seq)
+           kret = krb5_size_opaque(kcontext,
+                                   KV5M_KEYBLOCK,
+                                   (krb5_pointer) ctx->seq,
                                    &required);
 
        if (!kret)
@@ -486,6 +305,7 @@ kg_ctx_externalize(kcontext, arg, buffer, lenremain)
     size_t             required;
     krb5_octet         *bp;
     size_t             remain;
+    int                        i;
 
     required = 0;
     bp = *buffer;
@@ -526,6 +346,10 @@ kg_ctx_externalize(kcontext, arg, buffer, lenremain)
                                       &bp, &remain);
            (void) krb5_ser_pack_int32((krb5_int32) ctx->big_endian,
                                       &bp, &remain);
+           (void) krb5_ser_pack_int32((krb5_int32) ctx->gsskrb5_version,
+                                      &bp, &remain);
+           (void) krb5_ser_pack_int32((krb5_int32) ctx->nctypes,
+                                      &bp, &remain);
 
            /* Now dynamic data */
            kret = 0;
@@ -552,14 +376,16 @@ kg_ctx_externalize(kcontext, arg, buffer, lenremain)
                                               (krb5_pointer) ctx->subkey,
                                               &bp, &remain);
 
-           if (!kret)
-               kret = kg_enc_desc_externalize(kcontext,
-                                              (krb5_pointer) &ctx->enc,
+           if (!kret && ctx->enc)
+               kret = krb5_externalize_opaque(kcontext,
+                                              KV5M_KEYBLOCK,
+                                              (krb5_pointer) ctx->enc,
                                               &bp, &remain);
 
-           if (!kret)
-               kret = kg_enc_desc_externalize(kcontext,
-                                              (krb5_pointer) &ctx->seq,
+           if (!kret && ctx->seq)
+               kret = krb5_externalize_opaque(kcontext,
+                                              KV5M_KEYBLOCK,
+                                              (krb5_pointer) ctx->seq,
                                               &bp, &remain);
 
            if (!kret && ctx->seqstate)
@@ -571,6 +397,13 @@ kg_ctx_externalize(kcontext, arg, buffer, lenremain)
                                               KV5M_AUTH_CONTEXT,
                                               (krb5_pointer) ctx->auth_context,
                                               &bp, &remain);
+
+           for (i=0; i<ctx->nctypes; i++) {
+               if (!kret) {
+                   kret = krb5_ser_pack_int32((krb5_int32) ctx->ctypes[i],
+                                              &bp, &remain);
+               }
+           }
            
            if (!kret) {
                (void) krb5_ser_pack_int32(KG_CONTEXT, &bp, &remain);
@@ -597,7 +430,7 @@ kg_ctx_internalize(kcontext, argp, buffer, lenremain)
     krb5_int32         ibuf;
     krb5_octet         *bp;
     size_t             remain;
-    krb5_gss_enc_desc  *edp;
+    int                        i;
 
     bp = *buffer;
     remain = *lenremain;
@@ -640,6 +473,10 @@ kg_ctx_internalize(kcontext, argp, buffer, lenremain)
            ctx->established = (int) ibuf;
            (void) krb5_ser_unpack_int32(&ibuf, &bp, &remain);
            ctx->big_endian = (int) ibuf;
+           (void) krb5_ser_unpack_int32(&ibuf, &bp, &remain);
+           ctx->gsskrb5_version = (int) ibuf;
+           (void) krb5_ser_unpack_int32(&ibuf, &bp, &remain);
+           ctx->nctypes = (int) ibuf;
 
            if ((kret = kg_oid_internalize(kcontext, &ctx->mech_used, &bp,
                                           &remain))) {
@@ -670,29 +507,21 @@ kg_ctx_internalize(kcontext, argp, buffer, lenremain)
                if (kret == EINVAL)
                    kret = 0;
            }
-           if (!kret) {
-               if ((kret = kg_enc_desc_internalize(kcontext,
-                                                   (krb5_pointer *) &edp,
-                                                   &bp, &remain))) {
-                   if (kret == EINVAL)
-                       kret = 0;
-               }
-               else {
-                   memcpy(&ctx->enc, edp, sizeof(ctx->enc));
-                   xfree(edp);
-               }
+           if (!kret &&
+               (kret = krb5_internalize_opaque(kcontext,
+                                               KV5M_KEYBLOCK,
+                                               (krb5_pointer *) &ctx->enc,
+                                               &bp, &remain))) {
+               if (kret == EINVAL)
+                   kret = 0;
            }
-           if (!kret) {
-               if ((kret = kg_enc_desc_internalize(kcontext,
-                                                   (krb5_pointer *) &edp,
-                                                   &bp, &remain))) {
-                   if (kret == EINVAL)
-                       kret = 0;
-               }
-               else {
-                   memcpy(&ctx->seq, edp, sizeof(ctx->seq));
-                   xfree(edp);
-               }
+           if (!kret &&
+               (kret = krb5_internalize_opaque(kcontext,
+                                               KV5M_KEYBLOCK,
+                                               (krb5_pointer *) &ctx->seq,
+                                               &bp, &remain))) {
+               if (kret == EINVAL)
+                   kret = 0;
            }
 
            if (!kret) {
@@ -708,6 +537,22 @@ kg_ctx_internalize(kcontext, argp, buffer, lenremain)
                                       (krb5_pointer *) &ctx->auth_context,
                                               &bp, &remain);
                
+           if (!kret) {
+               if (ctx->nctypes) {
+                   if ((ctx->ctypes = (krb5_cksumtype *)
+                        malloc(ctx->nctypes*sizeof(krb5_cksumtype))) == NULL){
+                       kret = ENOMEM;
+                   }
+
+                   for (i=0; i<ctx->nctypes; i++) {
+                       if (!kret) {
+                           kret = krb5_ser_unpack_int32(&ibuf, &bp, &remain);
+                           ctx->ctypes[i] = (krb5_cksumtype) ibuf;
+                       }
+                   }
+               }
+           }
+
            /* Get trailer */
            if (!kret &&
                !(kret = krb5_ser_unpack_int32(&ibuf, &bp, &remain)) &&
@@ -719,18 +564,10 @@ kg_ctx_internalize(kcontext, argp, buffer, lenremain)
            else {
                if (!kret && (ibuf != KG_CONTEXT))
                    kret = EINVAL;
-               if (ctx->seq.eblock.key)
-                   krb5_free_keyblock(kcontext, ctx->seq.eblock.key);
-               if (ctx->seq.eblock.priv && ctx->seq.eblock.priv_size)
-                   krb5_xfree(ctx->seq.eblock.priv);
-               if (ctx->seq.key)
-                   krb5_free_keyblock(kcontext, ctx->seq.key);
-               if (ctx->enc.eblock.key)
-                   krb5_free_keyblock(kcontext, ctx->enc.eblock.key);
-               if (ctx->enc.eblock.priv && ctx->enc.eblock.priv_size)
-                   krb5_xfree(ctx->enc.eblock.priv);
-               if (ctx->enc.key)
-                   krb5_free_keyblock(kcontext, ctx->enc.key);
+               if (ctx->seq)
+                   krb5_free_keyblock(kcontext, ctx->seq);
+               if (ctx->enc)
+                   krb5_free_keyblock(kcontext, ctx->enc);
                if (ctx->subkey)
                    krb5_free_keyblock(kcontext, ctx->subkey);
                if (ctx->there)
index 68561f10b31cffc7800121c3f7f344e2575e6a92..10e6b657fd12897e846f197fe883ab21b1cc3f98 100644 (file)
@@ -36,20 +36,25 @@ kg_checksum_channel_bindings(context, cb, cksum, bigend)
 {
    int len;
    char *buf, *ptr;
+   size_t sumlen;
+   krb5_data plaind;
    krb5_error_code code;
 
-   /* initialize the the cksum and allocate the contents buffer */
+   /* initialize the the cksum */
+   if (code = krb5_c_checksum_length(context, CKSUMTYPE_RSA_MD5, &sumlen))
+       return(code);
+
    cksum->checksum_type = CKSUMTYPE_RSA_MD5;
-   cksum->length = krb5_checksum_size(context, CKSUMTYPE_RSA_MD5);
-   if ((cksum->contents = (krb5_octet *) xmalloc(cksum->length)) == NULL) {
-      return(ENOMEM);
-   }
+   cksum->length = sumlen;
  
    /* generate a buffer full of zeros if no cb specified */
 
    if (cb == GSS_C_NO_CHANNEL_BINDINGS) {
-      memset(cksum->contents, '\0', cksum->length);
-      return(0);
+       if ((cksum->contents = (krb5_octet *) xmalloc(cksum->length)) == NULL) {
+          return(ENOMEM);
+       }
+       memset(cksum->contents, '\0', cksum->length);
+       return(0);
    }
 
    /* create the buffer to checksum into */
@@ -75,9 +80,11 @@ kg_checksum_channel_bindings(context, cb, cksum, bigend)
 
    /* checksum the data */
 
-   if (code = krb5_calculate_checksum(context, CKSUMTYPE_RSA_MD5, 
-                                     buf, len, NULL, 0, cksum)) {
-      xfree(cksum->contents);
+   plaind.length = len;
+   plaind.data = buf;
+
+   if (code = krb5_c_make_checksum(context, CKSUMTYPE_RSA_MD5, 0, 0,
+                                  &plaind, cksum)) {
       xfree(buf);
       return(code);
    }
index 1684377ad66aa91ad76b05e895258e625fa18f40..93d46946c1afb74c8e03a55b88b32bd3fd46b610 100644 (file)
  * PERFORMANCE OF THIS SOFTWARE.
  */
 
+/*
+ * Copyright (C) 1998 by the FundsXpress, INC.
+ * 
+ * All rights reserved.
+ * 
+ * Export of this software from the United States of America may require
+ * a specific license from the United States Government.  It is the
+ * responsibility of any person or organization contemplating export to
+ * obtain such a license before exporting.
+ * 
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of FundsXpress. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  FundsXpress makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
 #include "k5-int.h"
 #include "gssapiP_krb5.h"
 #include <memory.h>
 static unsigned char zeros[8] = {0,0,0,0,0,0,0,0};
 
 int
-kg_confounder_size(ed)
-     krb5_gss_enc_desc *ed;
+kg_confounder_size(context, key)
+     krb5_context context;
+     krb5_keyblock *key;
 {
-   /* XXX Abstraction violation!!! */
+   krb5_error_code code;
+   size_t blocksize;
+
+   if (code = krb5_c_block_size(context, key->enctype, &blocksize))
+      return(-1); /* XXX */
 
-   return(ed->eblock.crypto_entry->block_length);
+   return(blocksize);
 }
 
 krb5_error_code
-kg_make_confounder(ed, buf)
-     krb5_gss_enc_desc *ed;
+kg_make_confounder(context, key, buf)
+     krb5_context context;
+     krb5_keyblock *key;
      unsigned char *buf;
 {
-   /* XXX Abstraction violation!!! */
+   krb5_error_code code;
+   size_t blocksize;
+   krb5_data random;
+
+   if (code = krb5_c_block_size(context, key->enctype, &blocksize))
+       return(code);
 
-   return(krb5_random_confounder(ed->eblock.crypto_entry->block_length, buf));
+   random.length = blocksize;
+   random.data = buf;
+
+   return(krb5_c_random_make_octets(context, &random));
 }
 
 int
-kg_encrypt_size(ed, n)
-     krb5_gss_enc_desc *ed;
+kg_encrypt_size(context, key, n)
+     krb5_context context;
+     krb5_keyblock *key;
      int n;
 {
-   return(krb5_encrypt_size(n, ed->eblock.crypto_entry));
+   krb5_error_code code;
+   size_t enclen;
+
+   if (code = krb5_c_encrypt_length(context, key->enctype, n, &enclen))
+      return(-1); /* XXX */
+
+   return(enclen);
 }
 
 krb5_error_code
-kg_encrypt(context, ed, iv, in, out, length)
+kg_encrypt(context, key, iv, in, out, length)
      krb5_context context;
-     krb5_gss_enc_desc *ed;
+     krb5_keyblock *key;
      krb5_pointer iv;
      krb5_pointer in;
      krb5_pointer out;
      int length;
 {
    krb5_error_code code;
-   krb5_pointer tmp;
-
-   if (! ed->processed) {
-      if (code = krb5_process_key(context, &ed->eblock, ed->key))
-        return(code);
-      ed->processed = 1;
+   size_t blocksize;
+   krb5_data ivd, *pivd, inputd;
+   krb5_enc_data outputd;
+
+   if (iv) {
+       if (code = krb5_c_block_size(context, key->enctype, &blocksize))
+          return(code);
+
+       ivd.length = blocksize;
+       ivd.data = iv;
+       pivd = &ivd;
+   } else {
+       pivd = NULL;
    }
 
-   /* this is lame.  the krb5 encryption interfaces no longer allow
-      you to encrypt in place.  perhaps this should be fixed, but
-      dealing here is easier for now --marc */
-
-   if ((tmp = (krb5_pointer) xmalloc(length)) == NULL)
-      return(ENOMEM);
+   inputd.length = length;
+   inputd.data = in;
 
-   memcpy(tmp, in, length);
+   outputd.ciphertext.length = length;
+   outputd.ciphertext.data = out;
 
-   code = krb5_encrypt(context, tmp, out, length, &ed->eblock, 
-                      iv?iv:(krb5_pointer)zeros);
-
-   xfree(tmp);
-
-   if (code)
-      return(code);
-
-   return(0);
+   return(krb5_c_encrypt(context, key,
+                        /* XXX this routine is only used for the old
+                           bare-des stuff which doesn't use the
+                           key usage */ 0, pivd, &inputd, &outputd));
 }
 
 /* length is the length of the cleartext. */
 
 krb5_error_code
-kg_decrypt(context, ed, iv, in, out, length)
+kg_decrypt(context, key, iv, in, out, length)
      krb5_context context;
-     krb5_gss_enc_desc *ed;
+     krb5_keyblock *key;
      krb5_pointer iv;
      krb5_pointer in;
      krb5_pointer out;
      int length;
 {
    krb5_error_code code;
-   int elen;
-   char *buf;
-
-   if (! ed->processed) {
-      if (code = krb5_process_key(context, &ed->eblock, ed->key))
-        return(code);
-      ed->processed = 1;
+   size_t blocksize, enclen;
+   krb5_data ivd, *pivd, outputd;
+   krb5_enc_data inputd;
+
+   if (iv) {
+       if (code = krb5_c_block_size(context, key->enctype, &blocksize))
+          return(code);
+
+       ivd.length = blocksize;
+       ivd.data = iv;
+       pivd = &ivd;
+   } else {
+       pivd = NULL;
    }
 
-   elen = krb5_encrypt_size(length, ed->eblock.crypto_entry);
-   if ((buf = (char *) xmalloc(elen)) == NULL)
-      return(ENOMEM);
-
-   if (code = krb5_decrypt(context, in, buf, elen, &ed->eblock, 
-                          iv?iv:(krb5_pointer)zeros)) {
-      xfree(buf);
-      return(code);
-   }
+   inputd.enctype = ENCTYPE_UNKNOWN;
+   inputd.ciphertext.length = length;
+   inputd.ciphertext.data = in;
 
-   memcpy(out, buf, length);
-   xfree(buf);
+   outputd.length = length;
+   outputd.data = out;
 
-   return(0);
+   return(krb5_c_decrypt(context, key,
+                        /* XXX this routine is only used for the old
+                           bare-des stuff which doesn't use the
+                           key usage */ 0, pivd, &inputd, &outputd));
 }
diff --git a/src/lib/gssapi/krb5/util_ctxsetup.c b/src/lib/gssapi/krb5/util_ctxsetup.c
new file mode 100644 (file)
index 0000000..0add6bf
--- /dev/null
@@ -0,0 +1,208 @@
+/*
+ * Copyright (C) 1998 by the FundsXpress, INC.
+ * 
+ * All rights reserved.
+ * 
+ * Export of this software from the United States of America may require
+ * a specific license from the United States Government.  It is the
+ * responsibility of any person or organization contemplating export to
+ * obtain such a license before exporting.
+ * 
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of FundsXpress. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  FundsXpress makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#include "gssapiP_krb5.h"
+
+/* from the token, flags is stored directly. nctypes/ctypes is
+   allocated and returns the length and list of ctypes in the token.
+   noptions/options lists all the options which the caller cares
+   about.  Those which are present in the token are filled in; the
+   order and length are not changed.  If an error is returned, the
+   option list is in an indeterminate state. */
+
+OM_uint32
+kg2_parse_token(minor_status, ptr, token_length, flags, nctypes, ctypes,
+               noptions, options, kmsg, mic)
+     OM_uint32 *minor_status;
+     unsigned char *ptr;
+     int token_length;
+     krb5_ui_4 *flags;
+     int *nctypes; /* OUT */
+     krb5_cksumtype **ctypes; /* OUT */
+     int noptions; 
+     struct kg2_option *options; /* INOUT */
+     krb5_data *kmsg;
+     krb5_data *mic;
+{
+    int field_length, i;
+    int opt_id;
+
+    *ctypes = 0;
+
+    /* read the flags */
+
+    if (token_length < 4)
+       goto defective;
+    *flags = (ptr[0]<<24) | (ptr[1]<<16) | (ptr[2]<<8) | ptr[3];
+    ptr += 4;
+    token_length -= 4;
+
+    /* read out the token list */
+
+    if (token_length < 2)
+       goto defective;
+    field_length = (ptr[0]<<8) | ptr[1];
+    ptr += 2;
+    token_length -= 2;
+
+    *nctypes = field_length;
+
+    if (*nctypes == 0) {
+       *minor_status = 0;
+       return(GSS_S_DEFECTIVE_TOKEN);
+    }
+
+    if ((*ctypes = (krb5_cksumtype *)
+        malloc((*nctypes) * sizeof(krb5_cksumtype))) == NULL) {
+       *minor_status = ENOMEM;
+       return(GSS_S_FAILURE);
+    }
+
+    for (i=0; i<field_length; i++) {
+       if (token_length < 4)
+           goto defective;
+
+       (*ctypes)[i] = (krb5_cksumtype) ((ptr[0]<<24) | (ptr[1]<<16) |
+                                     (ptr[2]<<8) | ptr[3]);
+       ptr += 4;
+       token_length -= 4;
+    }
+
+    do {
+       if (token_length < 4)
+           goto defective;
+       opt_id = (ptr[0]<<8) | ptr[1];
+       field_length = (ptr[2]<<8) | ptr[3];
+       ptr += 4;
+       token_length -= 4;
+
+       if (token_length < field_length)
+           goto defective;
+
+       for (i=0; i<noptions; i++) {
+           if (options[i].option_id = opt_id) {
+               options[i].length = field_length;
+               options[i].data = ptr;
+           }
+           break;
+       }
+           
+       ptr += field_length;
+       token_length -= field_length;
+    } while (opt_id);
+
+    if (token_length < 2)
+       goto defective;
+    field_length = (ptr[0]<<8) | ptr[1];
+    ptr += 2;
+    token_length -= 2;
+
+    if (token_length < field_length)
+       goto defective;
+
+    kmsg->length = field_length;
+    kmsg->data = ptr;
+
+    ptr += field_length;
+    token_length -= field_length;
+
+    /* if there's anything left, assume it's a mic.  the mic isn't
+       necessarily present */
+
+    if (mic && token_length) {
+       if (token_length < 2)
+           goto defective;
+       field_length = (ptr[0]<<8) | ptr[1];
+       ptr += 2;
+       token_length -= 2;
+
+       if (token_length < field_length)
+           goto defective;
+
+       mic->length = field_length;
+       mic->data = ptr;
+
+       ptr += field_length;
+       token_length -= field_length;
+    } else if (mic) {
+       mic->length = 0;
+       mic->data = ptr;
+    }
+
+    if (token_length)
+       goto defective;
+
+    return(GSS_S_COMPLETE);
+
+defective:
+    if (*ctypes)
+       free(*ctypes);
+
+    *minor_status = 0;
+    return(GSS_S_DEFECTIVE_TOKEN);
+}
+    
+/* nc1/c1 will be modified to contain the intersection of the
+   two lists. */
+
+void
+kg2_intersect_ctypes(nc1, c1, nc2, c2)
+     int *nc1;
+     krb5_cksumtype *c1;
+     int nc2;
+     const krb5_cksumtype *c2;
+{
+    int i, j, count;
+    krb5_cksumtype tmp;
+
+    count = 0;
+
+    for (i=0; i<*nc1; i++) {
+       /* first, check to make sure that c1[i] isn't a duplicate in c1 */
+       for (j=0; j<i; j++)
+           if (c1[i] == c1[j])
+               break;
+       if (j<i)
+           continue;
+       /* check if c1[i] is in c2.  If it is, keep it by swapping
+          it into c1[count] and incrementing count.  If count < i, then
+          that field has already been looked at and skipped as
+          not intersecting, which is ok. */
+
+       for (j=0; j<nc2; j++)
+           if (c1[i] == c2[j])
+               break;
+       if ((j<nc2) && (count != i)) {
+           tmp = c1[count];
+           c1[count] = c1[i];
+           c1[i] = tmp;
+       }
+       count++;
+    }
+
+    *nc1 = count;
+}
+
index 14f3652452262c31d474606cf6668f808c48f0a3..206ee68a7b91f008fb75099f4e22f003e0b77ee7 100644 (file)
@@ -36,24 +36,20 @@ kg_make_seed(context, key, seed)
      unsigned char *seed;
 {
    krb5_error_code code;
-   krb5_gss_enc_desc ed;
+   krb5_keyblock *tmpkey;
    int i;
 
-   if (code = krb5_copy_keyblock(context, key, &ed.key))
+   if (code = krb5_copy_keyblock(context, key, &tmpkey))
       return(code);
 
    /* reverse the key bytes, as per spec */
 
-   for (i=0; i<ed.key->length; i++)
-      ed.key->contents[i] = key->contents[key->length - 1 - i];
+   for (i=0; i<tmpkey->length; i++)
+      tmpkey->contents[i] = key->contents[key->length - 1 - i];
 
-   krb5_use_enctype(context, &ed.eblock, ENCTYPE_DES_CBC_RAW);
-   ed.processed = 0;
+   code = kg_encrypt(context, tmpkey, NULL, zeros, seed, 16);
 
-   code = kg_encrypt(context, &ed, NULL, zeros, seed, 16);
-
-   krb5_finish_key(context, &ed.eblock);
-   krb5_free_keyblock(context, ed.key);
+   krb5_free_keyblock(context, tmpkey);
 
    return(code);
 }
index ed9293f7789937d86f9b771d051c4e1cce67a698..e14b2f3fec89a29b14b33d943618f561f2a2fe64 100644 (file)
@@ -27,9 +27,9 @@
  */
 
 krb5_error_code
-kg_make_seq_num(context, ed, direction, seqnum, cksum, buf)
+kg_make_seq_num(context, key, direction, seqnum, cksum, buf)
      krb5_context context;
-     krb5_gss_enc_desc *ed;
+     krb5_keyblock *key;
      int direction;
      krb5_int32 seqnum;
      unsigned char *cksum;
@@ -47,12 +47,12 @@ kg_make_seq_num(context, ed, direction, seqnum, cksum, buf)
    plain[6] = direction;
    plain[7] = direction;
 
-   return(kg_encrypt(context, ed, cksum, plain, buf, 8));
+   return(kg_encrypt(context, key, cksum, plain, buf, 8));
 }
 
-krb5_error_code kg_get_seq_num(context, ed, cksum, buf, direction, seqnum)
+krb5_error_code kg_get_seq_num(context, key, cksum, buf, direction, seqnum)
      krb5_context context;
-     krb5_gss_enc_desc *ed;
+     krb5_keyblock *key;
      unsigned char *cksum;
      unsigned char *buf;
      int *direction;
@@ -61,7 +61,7 @@ krb5_error_code kg_get_seq_num(context, ed, cksum, buf, direction, seqnum)
    krb5_error_code code;
    unsigned char plain[8];
 
-   if (code = kg_decrypt(context, ed, cksum, buf, plain, 8))
+   if (code = kg_decrypt(context, key, cksum, buf, plain, 8))
       return(code);
 
    if ((plain[4] != plain[5]) ||
index f2366d16e2085abd1b7304ab1732f0af5cc3fbb9..74594926097ef716e569cd26026f87fc5865f9bb 100644 (file)
  * PERFORMANCE OF THIS SOFTWARE.
  */
 
+/*
+ * Copyright (C) 1998 by the FundsXpress, INC.
+ * 
+ * All rights reserved.
+ * 
+ * Export of this software from the United States of America may require
+ * a specific license from the United States Government.  It is the
+ * responsibility of any person or organization contemplating export to
+ * obtain such a license before exporting.
+ * 
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of FundsXpress. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  FundsXpress makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
 #include "gssapiP_krb5.h"
 
 /*
@@ -39,8 +65,7 @@ krb5_gss_wrap_size_limit(minor_status, context_handle, conf_req_flag,
 {
     krb5_context       context;
     krb5_gss_ctx_id_rec        *ctx;
-    OM_uint32          cfsize;
-    OM_uint32          ohlen;
+    krb5_error_code code;
 
     if (GSS_ERROR(kg_get_context(minor_status, &context)))
        return(GSS_S_FAILURE);
@@ -63,19 +88,86 @@ krb5_gss_wrap_size_limit(minor_status, context_handle, conf_req_flag,
        return(GSS_S_NO_CONTEXT);
     }
 
-    /* Calculate the token size and subtract that from the output size */
-    cfsize = (conf_req_flag) ? kg_confounder_size(&ctx->enc) : 0;
-    ohlen = g_token_size((gss_OID) ctx->mech_used,
-                        (unsigned int) cfsize + ctx->cksum_size + 14);
+    if (ctx->gsskrb5_version == 2000) {
+       if (conf_req_flag) {
+           /* this is pretty gross.  take the max output, and call
+              krb5_c_encrypt_length to see how much overhead is added
+              on.  subtract that much, and see if it fits in the
+              requested space.  If not, start subtracting 1 until it
+              does.  This doesn't necessarily give us the optimal
+              packing, but I think that's ok (I could start adding 1
+              until I went over, but that seems like it's not worth
+              the effort).  This is probably O(blocksize), but that's
+              never going to be large. */
+
+           OM_uint32 headerlen, plainlen;
+           size_t enclen;
+
+           headerlen = g_token_size((gss_OID) ctx->mech_used, 2);
+           plainlen = req_output_size - headerlen;
+
+           if (code = krb5_c_encrypt_length(context, ctx->enc->enctype,
+                                            plainlen, &enclen)) {
+               *minor_status = code;
+               return(GSS_S_FAILURE);
+           }
+
+           plainlen -= plainlen - (enclen - plainlen);
+
+           if (code = krb5_c_encrypt_length(context, ctx->enc->enctype,
+                                            plainlen, &enclen)) {
+               *minor_status = code;
+               return(GSS_S_FAILURE);
+           }
 
-    if (ohlen < req_output_size)
+           while (headerlen + enclen > req_output_size) {
+               plainlen--;
+
+               if (code = krb5_c_encrypt_length(context, ctx->enc->enctype,
+                                                plainlen, &enclen)) {
+                   *minor_status = code;
+                   return(GSS_S_FAILURE);
+               }
+           }
+
+           /* subtract off the fixed size inside the encrypted part */
+
+           plainlen -= 7;
+
+           *max_input_size = plainlen;
+       } else {
+           size_t cksumlen;
+           OM_uint32 headerlen;
+
+           if (code = krb5_c_checksum_length(context, ctx->ctypes[0],
+                                             &cksumlen)) {
+               *minor_status = code;
+               return(GSS_S_FAILURE);
+           }
+
+           headerlen = g_token_size((gss_OID) ctx->mech_used, 13 + cksumlen);
+
+           *max_input_size = req_output_size - headerlen;
+       }
+    } else {
+       OM_uint32               cfsize;
+       OM_uint32               ohlen;
+
+       /* Calculate the token size and subtract that from the output size */
+       cfsize = (conf_req_flag) ? kg_confounder_size(context, ctx->enc) : 0;
+       ohlen = g_token_size((gss_OID) ctx->mech_used,
+                            (unsigned int) cfsize + ctx->cksum_size + 14);
+
+       if (ohlen < req_output_size)
            /*
             * Cannot have trailer length that will cause us to pad over
             * our length
             */
            *max_input_size = (req_output_size - ohlen - 1) & (~7);
-    else
+       else
            *max_input_size = 0;
+    }
+
     *minor_status = 0;
     return(GSS_S_COMPLETE);
 }
index ae8bb7e1b1ad30d17387c56b0a26cd657f9c6a14..64dc648d6ccda77f18bc4d50afc70fc886a6c8af 100644 (file)
@@ -1,3 +1,14 @@
+Thu Aug 13 17:21:06 1998  Tom Yu  <tlyu@mit.edu>
+
+       * alt_prof.c (krb5_read_realm_params): Fix to check
+       "supported_enctypes" if "kdc_supported_enctypes" isn't there.
+
+Wed Aug 12 20:19:08 1998  Tom Yu  <tlyu@mit.edu>
+
+       * alt_prof.c (krb5_read_realm_params): Use
+       "kdc_supported_enctypes" instead of "supported_enctypes" so that
+       the KDC and the kadmind will use different enctype lists.
+
 Wed Jul  8 04:48:50 1998  Geoffrey J. King  <gjking@mit.edu>
 
        * logger.c: Add the function krb5_klog_reopen() which closes
index b2260d67a88f3e7bcba8d869d6d6baf80b079d8e..934785322bac7d97e659315bd4090b82b92f4122 100644 (file)
@@ -866,8 +866,15 @@ krb5_read_realm_params(kcontext, realm, kdcprofile, kdcenv, rparamp)
     }
 
     /* Get the value for the supported enctype/salttype matrix */
-    hierarchy[2] = "supported_enctypes";
-    if (!krb5_aprof_get_string(aprofile, hierarchy, TRUE, &svalue)) {
+    /* XXX This is so that the kdc will search a different
+       enctype list than kadmind */
+    hierarchy[2] = "kdc_supported_enctypes";
+    kret = krb5_aprof_get_string(aprofile, hierarchy, TRUE, &svalue);
+    if (kret) {
+       hierarchy[2] = "supported_enctypes";
+       kret = krb5_aprof_get_string(aprofile, hierarchy, TRUE, &svalue);
+    }
+    if (!kret) {
        krb5_string_to_keysalts(svalue,
                                ", \t", /* Tuple separators     */
                                ":.-",  /* Key/salt separators  */
index e1e761ce533cf01caa3a47d56e8d085d28299f5b..5f46d21854436fb8a6e358a364a3b21a8d3b61dd 100644 (file)
@@ -1,3 +1,12 @@
+1998-10-27  Marc Horowitz  <marc@mit.edu>
+
+       * client_init.c (_kadm5_init_any): try the krb5 v2 mechanism
+       first, and if that fails, try the krb5 v1 mech.
+
+Sun Jul 26 18:11:56 1998  Sam Hartman  <hartmans@utwig.mesas.com>
+
+       * Makefile.in (LIBMAJOR): bump libmajor
+
 Wed Apr 15 18:05:57 1998  Tom Yu  <tlyu@mit.edu>
 
        * Makefile.in (SHLIB_EXPDEPS): 
index 662bc76019bd8d4acab489d26610fc4ba8ae82d2..b125ea7a1aa64350838c4b2359c4d8f355d1b507 100644 (file)
@@ -3,7 +3,7 @@ BUILDTOP=$(REL)$(U)$(S)$(U)$(S)$(U)
 CFLAGS = $(CCOPTS) $(DEFS) -I$(BUILDTOP)/include/kadm5
 
 LIB=kadm5clnt
-LIBMAJOR=2
+LIBMAJOR=3
 LIBMINOR=0
 STOBJLISTS=../OBJS.ST OBJS.ST
 SHLIB_EXPDEPS=\
index 11cd77c7483b6584f0f59b7f1b0fa557ea5e3d84..96c5907af74f2cb2225539c350fd8d2c00f9da30 100644 (file)
@@ -4,6 +4,32 @@
  * $Header$
  */
 
+/*
+ * Copyright (C) 1998 by the FundsXpress, INC.
+ * 
+ * All rights reserved.
+ * 
+ * Export of this software from the United States of America may require
+ * a specific license from the United States Government.  It is the
+ * responsibility of any person or organization contemplating export to
+ * obtain such a license before exporting.
+ * 
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of FundsXpress. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  FundsXpress makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
 #if !defined(lint) && !defined(__CODECENTER__)
 static char *rcsid = "$Header$";
 #endif
@@ -444,12 +470,26 @@ static kadm5_ret_t _kadm5_init_any(char *client_name,
                                        &minor_stat,
                                        gss_client_creds,
                                        gss_target,
-                                       GSS_C_NULL_OID,
+                                       gss_mech_krb5_v2,
+                                       GSS_C_MUTUAL_FLAG | GSS_C_REPLAY_FLAG,
+                                       0,
+                                       NULL,
+                                       NULL,
+                                       NULL);
+
+     if (!handle->clnt->cl_auth)
+        handle->clnt->cl_auth = auth_gssapi_create(handle->clnt,
+                                       &gssstat,
+                                       &minor_stat,
+                                       gss_client_creds,
+                                       gss_target,
+                                       gss_mech_krb5,
                                        GSS_C_MUTUAL_FLAG | GSS_C_REPLAY_FLAG,
                                        0,
                                        NULL,
                                        NULL,
                                        NULL);
+
      (void) gss_release_name(&minor_stat, &gss_target);
 #endif /* ! INIT_TEST */
 
index 04011541b130440f2f5bb99c140491090bff7e52..67dbe38429d7aa42de278bd238b3d1285daabce5 100644 (file)
@@ -1,3 +1,11 @@
+1998-10-27  Marc Horowitz  <marc@mit.edu>
+
+       * server_kdb.c, svr_principal.c: convert to new crypto api
+
+Sun Jul 26 18:09:55 1998  Sam Hartman  <hartmans@utwig.mesas.com>
+
+       * Makefile.in (LIBMAJOR): bump libmajor
+
 Wed Apr 15 18:06:14 1998  Tom Yu  <tlyu@mit.edu>
 
        * Makefile.in (SHLIB_EXPDEPS): 
index ff6552bd7248aaafdc25639616a2e8b74aa257e5..53e469863595366edd7720a4391fab898f502bd8 100644 (file)
@@ -6,7 +6,7 @@ CFLAGS = $(CCOPTS) $(DEFS) -I$(BUILDTOP)/include/kadm5 @HESIOD_DEFS@
 ##DOSLIBNAME = libkadm5srv.lib
 
 LIB=kadm5srv
-LIBMAJOR=2
+LIBMAJOR=3
 LIBMINOR=0
 STOBJLISTS=../OBJS.ST OBJS.ST
 SHLIB_EXPDEPS=\
index 1a900a380f80d3590e58d004c69279453dc2e95a..2487f88e024a2aea1bbbebfa2128428ec96609ca 100644 (file)
@@ -15,12 +15,10 @@ static char *rcsid = "$Header$";
 #include "server_internal.h"
 
 krb5_principal     master_princ;
-krb5_encrypt_block  master_encblock;
 krb5_keyblock      master_keyblock;
 krb5_db_entry      master_db;
 
 krb5_principal     hist_princ;
-krb5_encrypt_block  hist_encblock;
 krb5_keyblock      hist_key;
 krb5_db_entry      hist_db;
 krb5_kvno          hist_kvno;
@@ -49,11 +47,8 @@ krb5_error_code kdb_init_master(kadm5_server_handle_t handle,
 
     master_keyblock.enctype = handle->params.enctype;
 
-    krb5_use_enctype(handle->context, &master_encblock,
-                    master_keyblock.enctype);
-
     if (ret = krb5_db_fetch_mkey(handle->context, master_princ,
-                                &master_encblock, from_keyboard,
+                                master_keyblock.enctype, from_keyboard,
                                 FALSE /* only prompt once */,
                                 handle->params.stash_file,
                                 NULL /* I'm not sure about this,
@@ -65,21 +60,11 @@ krb5_error_code kdb_init_master(kadm5_server_handle_t handle,
        goto done;
 
     if ((ret = krb5_db_verify_master_key(handle->context, master_princ,
-                                        &master_keyblock,
-                                        &master_encblock))) {
+                                        &master_keyblock))) {
          krb5_db_fini(handle->context);
          return ret;
     }
 
-    /* the kdc gets the db mkvno here.  The admin server never uses this
-       bit of information, so there's no reason to retrieve it. */
-
-    if ((ret = krb5_process_key(handle->context, &master_encblock,
-                               &master_keyblock))) {
-          krb5_db_fini(handle->context);
-         goto done;
-    }
-
 done:
     if (r == NULL)
        free(realm);
@@ -190,16 +175,10 @@ krb5_error_code kdb_init_hist(kadm5_server_handle_t handle, char *r)
                                    &key_data))
        goto done;
 
-    if (ret = krb5_dbekd_decrypt_key_data(handle->context, &master_encblock,
+    if (ret = krb5_dbekd_decrypt_key_data(handle->context, &master_keyblock,
                                          key_data, &hist_key, NULL))
        goto done;
 
-    krb5_use_enctype(handle->context, &hist_encblock, hist_key.enctype);
-
-    if ((ret = krb5_process_key(handle->context, &hist_encblock,
-                               &hist_key)) != KSUCCESS)
-       goto done;
-    
     hist_kvno = key_data->key_data_kvno;
 
 done:
index ee45723a47b971cbeb203c379316bbc7533bda76..9504556ffbbf24d431cf388c01d71a627578aed3 100644 (file)
@@ -22,8 +22,6 @@ static char *rcsid = "$Header$";
 
 extern krb5_principal      master_princ;
 extern krb5_principal      hist_princ;
-extern krb5_encrypt_block  master_encblock;
-extern krb5_encrypt_block  hist_encblock;
 extern krb5_keyblock       master_keyblock;
 extern krb5_keyblock       hist_key;
 extern krb5_db_entry       master_db;
@@ -236,7 +234,7 @@ kadm5_create_principal(void *server_handle,
 
     /* initialize the keys */
 
-    if (ret = krb5_dbe_cpw(handle->context, &master_encblock,
+    if (ret = krb5_dbe_cpw(handle->context, &master_keyblock,
                           handle->params.keysalts,
                           handle->params.num_keysalts,
                           password,
@@ -816,20 +814,20 @@ done:
  * Arguments:
  *
  *     context                 (r) the krb5 context
- *     histkey_encblock        (r) the encblock that hist_key_data is
+ *     hist_keyblock           (r) the key that hist_key_data is
  *                             encrypted in
  *     n_new_key_data          (r) length of new_key_data
  *     new_key_data            (r) keys to check against
- *                             pw_hist_data, encrypted in histkey_encblock
+ *                             pw_hist_data, encrypted in hist_keyblock
  *     n_pw_hist_data          (r) length of pw_hist_data
  *     pw_hist_data            (r) passwords to check new_key_data against
  *
  * Effects:
  * For each new_key in new_key_data:
- *     decrypt new_key with the master_encblock
+ *     decrypt new_key with the master_keyblock
  *     for each password in pw_hist_data:
  *             for each hist_key in password:
- *                     decrypt hist_key with histkey_encblock
+ *                     decrypt hist_key with hist_keyblock
  *                     compare the new_key and hist_key
  *
  * Returns krb5 errors, KADM5_PASS_RESUSE if a key in
@@ -837,7 +835,7 @@ done:
  */
 static kadm5_ret_t
 check_pw_reuse(krb5_context context,
-              krb5_encrypt_block *histkey_encblock,
+              krb5_keyblock *hist_keyblock,
               int n_new_key_data, krb5_key_data *new_key_data,
               int n_pw_hist_data, osa_pw_hist_ent *pw_hist_data)
 {
@@ -847,7 +845,7 @@ check_pw_reuse(krb5_context context,
 
     for (x = 0; x < n_new_key_data; x++) {
         if (ret = krb5_dbekd_decrypt_key_data(context,
-                                              &master_encblock,
+                                              &master_keyblock,
                                               &(new_key_data[x]),
                                               &newkey, NULL))
            return(ret);
@@ -855,7 +853,7 @@ check_pw_reuse(krb5_context context,
             for (z = 0; z < pw_hist_data[y].n_key_data; z++) {
                  if (ret =
                      krb5_dbekd_decrypt_key_data(context,
-                                                 histkey_encblock,
+                                                 hist_keyblock,
                                                  &pw_hist_data[y].key_data[z],
                                                  &histkey, NULL))
                       return(ret);             
@@ -894,8 +892,8 @@ check_pw_reuse(krb5_context context,
  * Effects:
  *
  * hist->key_data is allocated to store n_key_data key_datas.  Each
- * element of key_data is decrypted with master_encblock, re-encrypted
- * in hist_encblock, and added to hist->key_data.  hist->n_key_data is
+ * element of key_data is decrypted with master_keyblock, re-encrypted
+ * in hist_key, and added to hist->key_data.  hist->n_key_data is
  * set to n_key_data.
  */
 int create_history_entry(krb5_context context, int n_key_data,
@@ -912,12 +910,12 @@ int create_history_entry(krb5_context context, int n_key_data,
 
      for (i = 0; i < n_key_data; i++) {
          if (ret = krb5_dbekd_decrypt_key_data(context,
-                                               &master_encblock,
+                                               &master_keyblock,
                                                &key_data[i],
                                                &key, &salt))
               return ret;
          if (ret = krb5_dbekd_encrypt_key_data(context,
-                                               &hist_encblock,
+                                               &hist_key,
                                                &key, &salt,
                                                key_data[i].key_data_kvno,
                                                &hist->key_data[i]))
@@ -1052,7 +1050,7 @@ kadm5_chpass_principal(void *server_handle,
                            KADM5_POLICY, &pol, principal)))
         goto done;
 
-    if (ret = krb5_dbe_cpw(handle->context, &master_encblock,
+    if (ret = krb5_dbe_cpw(handle->context, &master_keyblock,
                           handle->params.keysalts,
                           handle->params.num_keysalts,
                           password, 0 /* increment kvno */, &kdb))
@@ -1090,7 +1088,7 @@ kadm5_chpass_principal(void *server_handle,
             goto done;
 
        if (ret = check_pw_reuse(handle->context,
-                                &hist_encblock,
+                                &hist_key,
                                 kdb.n_key_data, kdb.key_data,
                                 1, &hist))
             goto done;
@@ -1102,7 +1100,7 @@ kadm5_chpass_principal(void *server_handle,
            }
 
            if (ret = check_pw_reuse(handle->context,
-                                    &hist_encblock,
+                                    &hist_key,
                                     kdb.n_key_data, kdb.key_data,
                                     adb.old_key_len, adb.old_keys))
                goto done;
@@ -1171,7 +1169,7 @@ kadm5_randkey_principal(void *server_handle,
     if ((ret = kdb_get_entry(handle, principal, &kdb, &adb)))
        return(ret);
 
-    if (ret = krb5_dbe_crk(handle->context, &master_encblock,
+    if (ret = krb5_dbe_crk(handle->context, &master_keyblock,
                           handle->params.keysalts,
                           handle->params.num_keysalts,
                           &kdb))
@@ -1213,7 +1211,7 @@ kadm5_randkey_principal(void *server_handle,
            }
 
            if (ret = check_pw_reuse(handle->context,
-                                    &hist_encblock,
+                                    &hist_key,
                                     kdb.n_key_data, kdb.key_data,
                                     adb.old_key_len, adb.old_keys))
                goto done;
@@ -1316,7 +1314,7 @@ kadm5_setv4key_principal(void *server_handle,
     keysalt.data.data = NULL;
 
     if (ret = krb5_dbekd_encrypt_key_data(handle->context,
-                                         &master_encblock,
+                                         &master_keyblock,
                                          keyblock, &keysalt,
                                          kvno + 1,
                                          kdb.key_data)) {
@@ -1361,7 +1359,7 @@ kadm5_setv4key_principal(void *server_handle,
            }
 
            if (ret = check_pw_reuse(handle->context,
-                                    &hist_encblock,
+                                    &hist_key,
                                     kdb.n_key_data, kdb.key_data,
                                     adb.old_key_len, adb.old_keys))
                goto done;
@@ -1402,9 +1400,9 @@ kadm5_setkey_principal(void *server_handle,
     krb5_int32                 now;
     kadm5_policy_ent_rec       pol;
     krb5_key_data              *key_data;
-    int                                i, kvno, ret, last_pwd, have_pol = 0;
-    int                                deskeys;
+    int                                i, j, kvno, ret, last_pwd, have_pol = 0;
     kadm5_server_handle_t      handle = server_handle;
+    krb5_boolean               similar;
 
     CHECK_HANDLE(server_handle);
 
@@ -1415,14 +1413,16 @@ kadm5_setkey_principal(void *server_handle,
                                 principal, hist_princ)) == TRUE))
        return KADM5_PROTECT_PRINCIPAL;
 
-    for (i = 0, deskeys = 0; i < n_keys; i++) {
-      if (keyblocks[i].enctype == ENCTYPE_DES_CBC_MD4 ||
-         keyblocks[i].enctype == ENCTYPE_DES_CBC_MD5 ||
-         keyblocks[i].enctype == ENCTYPE_DES_CBC_RAW ||
-         keyblocks[i].enctype == ENCTYPE_DES_CBC_CRC)
-       deskeys++;
-      if (deskeys > 1)
-       return KADM5_SETKEY_DUP_ENCTYPES;
+    for (i = 0; i < n_keys; i++) {
+       for (j = i+1; j < n_keys; j++) {
+           if (ret = krb5_c_enctype_compare(handle->context,
+                                            keyblocks[i].enctype,
+                                            keyblocks[j].enctype,
+                                            &similar))
+               return(ret);
+           if (similar)
+               return KADM5_SETKEY_DUP_ENCTYPES;
+       }
     }
 
     if ((ret = kdb_get_entry(handle, principal, &kdb, &adb)))
@@ -1443,7 +1443,7 @@ kadm5_setkey_principal(void *server_handle,
 
     for (i = 0; i < n_keys; i++) {
         if (ret = krb5_dbekd_encrypt_key_data(handle->context,
-                                              &master_encblock,
+                                              &master_keyblock,
                                               &keyblocks[i], NULL,
                                               kvno + 1,
                                               &kdb.key_data[i]))
@@ -1488,7 +1488,7 @@ kadm5_setkey_principal(void *server_handle,
            }
 
            if (ret = check_pw_reuse(handle->context,
-                                    &hist_encblock,
+                                    &hist_key,
                                     kdb.n_key_data, kdb.key_data,
                                     adb.old_key_len, adb.old_keys))
                goto done;
@@ -1521,7 +1521,7 @@ done:
 /*
  * Allocate an array of n_key_data krb5_keyblocks, fill in each
  * element with the results of decrypting the nth key in key_data with
- * master_encblock, and if n_keys is not NULL fill it in with the
+ * master_keyblock, and if n_keys is not NULL fill it in with the
  * number of keys decrypted.
  */
 static int decrypt_key_data(krb5_context context,
@@ -1538,7 +1538,7 @@ static int decrypt_key_data(krb5_context context,
 
      for (i = 0; i < n_key_data; i++) {
          if (ret = krb5_dbekd_decrypt_key_data(context,
-                                               &master_encblock,
+                                               &master_keyblock,
                                                &key_data[i], 
                                                &keys[i], NULL)) {
 
@@ -1609,7 +1609,7 @@ kadm5_ret_t kadm5_decrypt_key(void *server_handle,
         return ret;
 
     if (ret = krb5_dbekd_decrypt_key_data(handle->context,
-                                         &master_encblock, key_data,
+                                         &master_keyblock, key_data,
                                          keyblock, keysalt))
         return ret;
 
index ec0b38457caa18bf972558d98f444af26d52fccf..e12270d5c8fae2b034a37735fda9a1f04305ebca 100644 (file)
@@ -1,3 +1,33 @@
+1998-10-27  Marc Horowitz  <marc@mit.edu>
+
+       * kdb_xdr.c, kdb_cpw.c: remove the special knowledge of ENCTYPE
+       string-to-key equivalances.  the crypto api has a function for
+       this now.
+
+       * decrypt_key.c, encrypt_key.c, fetch_mkey.c, kdb_cpw.c,
+       kdb_db2.c, kdb_db2.h, kdb_dbm.c, keytab.c, verify_mky.c: change or
+       remove all the places krb5_encrypt_block was used
+       (this is mostly relevant to kdb manipulations).  It was usually
+       used to specify an enctype (which is now implied by the keyblock),
+       or to store or pass in a processed key (now the api just takes a
+       key directly, so these structures and functions do, too).  The kdb
+       key manuipulation functions also need to be made to use the new
+       api.
+
+Fri Sep 25 19:42:10 1998  Tom Yu  <tlyu@mit.edu>
+
+       * kdb_xdr.c (krb5_dbe_search_enctype): Re-order booleans so that
+       similar doesn't get checked unless (ktype >= 0) to avoid it being
+       stack garbage.
+
+Sun Aug 16 16:52:10 1998  Sam Hartman  <hartmans@utwig.mesas.com>
+
+       * Makefile.in (SHLIB_EXPLIBS): Include $(LIBS) so building on AIX works
+
+Sun Jul 26 18:12:22 1998  Sam Hartman  <hartmans@utwig.mesas.com>
+
+       * Makefile.in (LIBMAJOR): bump libmajor
+
 1998-05-06  Theodore Ts'o  <tytso@rsts-11.mit.edu>
 
        * t_kdb.c (main): POSIX states that getopt returns -1
index 9ec4b23d481251d8a88a7a60265407c4b7541595..c44b58631d61e21d3db2ab2f737e5692a16a7ff1 100644 (file)
@@ -7,14 +7,14 @@ PROG_LIBPATH=-L$(TOPLIBD)
 PROG_RPATH=$(KRB5_LIBDIR)
 
 LIB=kdb5
-LIBMAJOR=2
+LIBMAJOR=3
 LIBMINOR=0
 RELDIR=kdb
 # Depends on libk5crypto and libkrb5
 SHLIB_EXPDEPS = \
        $(TOPLIBD)/libk5crypto$(SHLIBEXT) \
        $(TOPLIBD)/libkrb5$(SHLIBEXT)
-SHLIB_EXPLIBS=-lkrb5 -lcom_err -lk5crypto
+SHLIB_EXPLIBS=-lkrb5 -lcom_err -lk5crypto $(LIBS)
 SHLIB_DIRS=-L$(TOPLIBD)
 SHLIB_RDIRS=$(KRB5_LIBDIR)
 
index 2aa199ac7e2e0e081ba99c95db61be58e47bf77d..0cfdbda8e0aa9877e3b8a9f6bb7565db7d6b03ab 100644 (file)
  * krb5_kdb_encrypt_key(), krb5_kdb_decrypt_key functions
  */
 
+/*
+ * Copyright (C) 1998 by the FundsXpress, INC.
+ * 
+ * All rights reserved.
+ * 
+ * Export of this software from the United States of America may require
+ * a specific license from the United States Government.  It is the
+ * responsibility of any person or organization contemplating export to
+ * obtain such a license before exporting.
+ * 
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of FundsXpress. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  FundsXpress makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
 #include "k5-int.h"
 
 /*
  */
 
 krb5_error_code
-krb5_dbekd_decrypt_key_data(context, eblock, key_data, keyblock, keysalt)
+krb5_dbekd_decrypt_key_data(context, mkey, key_data, dbkey, keysalt)
     krb5_context         context;
-    krb5_encrypt_block         * eblock;
+    const krb5_keyblock        * mkey;
     const krb5_key_data        * key_data;
-    krb5_keyblock      * keyblock;
+    krb5_keyblock      * dbkey;
     krb5_keysalt       * keysalt;
 {
     krb5_error_code      retval = 0;
     krb5_int16           tmplen;
     krb5_octet         * ptr;
+    krb5_enc_data        cipher;
+    krb5_data            plain;
 
-    keyblock->magic = KV5M_KEYBLOCK;
-    keyblock->enctype = key_data->key_data_type[0];
-
-    /* Decrypt key_data_contents */
-    if ((keyblock->contents = (krb5_octet *)malloc(krb5_encrypt_size(
-      key_data->key_data_length[0] - 2, eblock->crypto_entry))) == NULL)
-       return ENOMEM;
-
-    keyblock->length = 0;
     ptr = key_data->key_data_contents[0];
+
     if (ptr) {
        krb5_kdb_decode_int16(ptr, tmplen);
        ptr += 2;
-       keyblock->length = (int) tmplen;
-       if ((retval = krb5_decrypt(context, (krb5_pointer) ptr,
-                                  (krb5_pointer)keyblock->contents,
-                                  key_data->key_data_length[0] - 2, 
-                                  eblock, 0))) {
-           krb5_xfree(keyblock->contents);
-           keyblock->contents = 0;
-           keyblock->length = 0;
+
+       cipher.enctype = ENCTYPE_UNKNOWN;
+       cipher.ciphertext.length = key_data->key_data_length[0]-2;
+       cipher.ciphertext.data = ptr;
+       plain.length = key_data->key_data_length[0]-2;
+       if ((plain.data = (krb5_octet *) malloc(plain.length)) == NULL)
+           return(ENOMEM);
+
+       if ((retval = krb5_c_decrypt(context, mkey, 0 /* XXX */, 0,
+                                    &cipher, &plain))) {
+           krb5_xfree(plain.data);
            return retval;
        }
+
+       /* tmplen is the true length of the key.  plain.data is the
+          plaintext data length, but it may be padded, since the
+          old-style etypes didn't store the real length.  I can check
+          to make sure that there are enough bytes, but I can't do
+          any better than that. */
+
+       if (tmplen > plain.length) {
+           krb5_xfree(plain.data);
+           return(KRB5_CRYPTO_INTERNAL);
+       }
+
+       dbkey->magic = KV5M_KEYBLOCK;
+       dbkey->enctype = key_data->key_data_type[0];
+       dbkey->length = tmplen;
+       dbkey->contents = plain.data;
     }
 
     /* Decode salt data */
@@ -75,9 +114,11 @@ krb5_dbekd_decrypt_key_data(context, eblock, key_data, keyblock, keysalt)
            keysalt->type = key_data->key_data_type[1];
            if ((keysalt->data.length = key_data->key_data_length[1])) {
                if (!(keysalt->data.data=(char *)malloc(keysalt->data.length))){
-                   krb5_xfree(keyblock->contents);
-                   keyblock->contents = 0;
-                   keyblock->length = 0;
+                   if (key_data->key_data_contents[0]) {
+                       krb5_xfree(dbkey->contents);
+                       dbkey->contents = 0;
+                       dbkey->length = 0;
+                   }
                    return ENOMEM;
                }
                memcpy(keysalt->data.data, key_data->key_data_contents[1],
@@ -90,5 +131,6 @@ krb5_dbekd_decrypt_key_data(context, eblock, key_data, keyblock, keysalt)
            keysalt->data.length = 0;
        }
     }
+
     return retval;
 }
index ea7d17ca78a74f72b720986a4706015b0d5ec390..7bcfe11eb1969bbf8808fae4f9feed6311bdab53 100644 (file)
  * krb5_kdb_encrypt_key(), krb5_kdb_decrypt_key functions
  */
 
+/*
+ * Copyright (C) 1998 by the FundsXpress, INC.
+ * 
+ * All rights reserved.
+ * 
+ * Export of this software from the United States of America may require
+ * a specific license from the United States Government.  It is the
+ * responsibility of any person or organization contemplating export to
+ * obtain such a license before exporting.
+ * 
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of FundsXpress. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  FundsXpress makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
 #include "k5-int.h"
 
 /*
  */
 
 krb5_error_code
-krb5_dbekd_encrypt_key_data(context, eblock, keyblock, keysalt, keyver,key_data)
+krb5_dbekd_encrypt_key_data(context, mkey, dbkey, keysalt, keyver, key_data)
     krb5_context                 context;
-    krb5_encrypt_block                 * eblock;
-    const krb5_keyblock        * keyblock;
+    const krb5_keyblock                * mkey;
+    const krb5_keyblock        * dbkey;
     const krb5_keysalt         * keysalt;
     int                                  keyver;
     krb5_key_data              * key_data;
@@ -44,8 +70,10 @@ krb5_dbekd_encrypt_key_data(context, eblock, keyblock, keysalt, keyver,key_data)
     krb5_error_code              retval;
     krb5_keyblock                tmp;
     krb5_octet                 * ptr;
-    krb5_int16                   len;
+    size_t                       len;
     int                                  i;
+    krb5_data                    plain;
+    krb5_enc_data                cipher;
 
     for (i = 0; i < key_data->key_data_ver; i++)
        if (key_data->key_data_contents[i])
@@ -58,39 +86,32 @@ krb5_dbekd_encrypt_key_data(context, eblock, keyblock, keysalt, keyver,key_data)
      * The First element of the type/length/contents 
      * fields is the key type/length/contents
      */
-    key_data->key_data_type[0] = keyblock->enctype;
-    key_data->key_data_length[0] = krb5_encrypt_size(keyblock->length, 
-                                                    eblock->crypto_entry) + 2;
+    if ((retval = krb5_c_encrypt_length(context, mkey->enctype, dbkey->length,
+                                       &len)))
+       return(retval);
 
-    /* 
-     * because of checksum space requirements imposed by the encryption
-     * interface, we need to copy the input key into a larger area. 
-     */
-    tmp.contents = (krb5_octet *)malloc(key_data->key_data_length[0] - 2);
-    len = tmp.length = keyblock->length;
-    if (tmp.contents == NULL)
-       return ENOMEM;
+    if ((ptr = (krb5_octet *) malloc(2 + len)) == NULL)
+       return(ENOMEM);
 
-    memcpy((char *)tmp.contents, (const char *)keyblock->contents, tmp.length);
-    key_data->key_data_contents[0] = ptr = (krb5_octet *)malloc(
-                                       key_data->key_data_length[0]);
-    if (key_data->key_data_contents[0] == NULL) {
-       krb5_xfree(tmp.contents);
-       return ENOMEM;
-    }
+    key_data->key_data_type[0] = dbkey->enctype;
+    key_data->key_data_length[0] = 2 + len;
+    key_data->key_data_contents[0] = ptr;
 
-    krb5_kdb_encode_int16(len, ptr);
+    krb5_kdb_encode_int16(dbkey->length, ptr);
     ptr += 2;
-    if ((retval = krb5_encrypt(context, (krb5_pointer) tmp.contents,
-                              (krb5_pointer)(ptr), tmp.length,
-                              eblock, 0))) {
+
+    plain.length = dbkey->length;
+    plain.data = dbkey->contents;
+
+    cipher.ciphertext.length = len;
+    cipher.ciphertext.data = ptr;
+
+    if ((retval = krb5_c_encrypt(context, mkey, /* XXX */ 0, 0,
+                                &plain, &cipher))) {
        krb5_xfree(key_data->key_data_contents[0]);
-       krb5_xfree(tmp.contents);
        return retval;
     }
 
-    krb5_xfree(tmp.contents);
-
     /* After key comes the salt in necessary */
     if (keysalt) {
        if (keysalt->type > 0) {
@@ -108,5 +129,6 @@ krb5_dbekd_encrypt_key_data(context, eblock, keyblock, keysalt, keyver,key_data)
            }
        }
     }
+
     return retval;
 }
index 5eda4eae6b45023e72cca8e4e6237f2452f4ead9..829e0283cd7f92b40870be365cdf768d95e1ba79 100644 (file)
  * Fetch a database master key from somewhere.
  */
 
+/*
+ * Copyright (C) 1998 by the FundsXpress, INC.
+ * 
+ * All rights reserved.
+ * 
+ * Export of this software from the United States of America may require
+ * a specific license from the United States Government.  It is the
+ * responsibility of any person or organization contemplating export to
+ * obtain such a license before exporting.
+ * 
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of FundsXpress. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  FundsXpress makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
 #include "k5-int.h"
 
 /* these are available to other funcs, and the pointers may be reassigned */
@@ -52,10 +78,11 @@ char *krb5_mkey_pwd_prompt2 = KRB5_KDC_MKEY_2;
 #endif
 
 krb5_error_code
-krb5_db_fetch_mkey(context, mname, eblock, fromkeyboard, twice, keyfile, salt, key)
+krb5_db_fetch_mkey(context, mname, etype, fromkeyboard, twice, keyfile,
+                  salt, key)
     krb5_context context;
     krb5_principal mname;
-    krb5_encrypt_block * eblock;
+    krb5_enctype etype;
     krb5_boolean fromkeyboard;
     krb5_boolean twice;
     char *keyfile;
@@ -67,7 +94,6 @@ krb5_db_fetch_mkey(context, mname, eblock, fromkeyboard, twice, keyfile, salt, k
     krb5_data pwd;
     int size = sizeof(password);
 
-
     if (fromkeyboard) {
        krb5_data scratch;
 
@@ -83,8 +109,9 @@ krb5_db_fetch_mkey(context, mname, eblock, fromkeyboard, twice, keyfile, salt, k
                if (retval)
                        return retval;
        }
-       retval = krb5_string_to_key(context, eblock, key, &pwd,
-                                   salt ? salt : &scratch);
+       retval = krb5_c_string_to_key(context, etype, &pwd, salt?salt:&scratch,
+                                     key);
+
        if (!salt)
                krb5_xfree(scratch.data);
        memset(password, 0, sizeof(password)); /* erase it */
@@ -142,7 +169,8 @@ krb5_db_fetch_mkey(context, mname, eblock, fromkeyboard, twice, keyfile, salt, k
            key->contents = 0;
        } else
            retval = 0;
-       krb5_use_enctype(context, eblock, key->enctype);
+
+       key->enctype = etype;
        
     errout:
        (void) fclose(kf);
index ec7419e1c6f0c5a22f0e5acb3c8171d6f3236ceb..d68d784c19333e4355e1340b7c78486728463aa3 100644 (file)
  * 
  */
 
+/*
+ * Copyright (C) 1998 by the FundsXpress, INC.
+ * 
+ * All rights reserved.
+ * 
+ * Export of this software from the United States of America may require
+ * a specific license from the United States Government.  It is the
+ * responsibility of any person or organization contemplating export to
+ * obtain such a license before exporting.
+ * 
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of FundsXpress. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  FundsXpress makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
 #include "k5-int.h"
 #include "krb5/adm.h"
 #include <stdio.h>
@@ -61,32 +87,23 @@ cleanup_key_data(context, count, data)
     free(data);
 }
 
-/*
- * Currently we can only generate random keys for preinitialized
- * krb5_encrypt_block with a seed. This is bogus but currently
- * necessary to insure that we don't generate two keys with the 
- * same data.
- */
 static krb5_error_code
-add_key_rnd(context, master_eblock, ks_tuple, ks_tuple_count, db_entry, kvno)
+add_key_rnd(context, master_key, ks_tuple, ks_tuple_count, db_entry, kvno)
     krb5_context         context;
-    krb5_encrypt_block  * master_eblock;
+    krb5_keyblock       * master_key;
     krb5_key_salt_tuple        * ks_tuple;
     int                          ks_tuple_count;
     krb5_db_entry      * db_entry;
     int                          kvno;
 {
     krb5_principal       krbtgt_princ;
-    krb5_keyblock        krbtgt_key, * key;
-    krb5_pointer         krbtgt_seed;  
-    krb5_encrypt_block   krbtgt_eblock;
+    krb5_keyblock        key;
     krb5_db_entry        krbtgt_entry;
     krb5_key_data      * krbtgt_kdata;
-    krb5_boolean         more, found;
+    krb5_boolean         more;
     int                          max_kvno, one, i, j;
     krb5_error_code      retval;
 
-    memset(&krbtgt_key, 0, sizeof(krbtgt_key));
     retval = krb5_build_principal_ext(context, &krbtgt_princ,
                                      db_entry->princ->realm.length,
                                      db_entry->princ->realm.data,
@@ -119,17 +136,9 @@ add_key_rnd(context, master_eblock, ks_tuple, ks_tuple_count, db_entry, kvno)
     }
 
     for (i = 0; i < ks_tuple_count; i++) {
-       krb5_enctype new_enctype, old_enctype;
+       krb5_boolean similar;
 
-       switch (new_enctype = ks_tuple[i].ks_enctype) {
-       case ENCTYPE_DES_CBC_MD4:
-       case ENCTYPE_DES_CBC_MD5:
-       case ENCTYPE_DES_CBC_RAW:
-           new_enctype = ENCTYPE_DES_CBC_CRC;
-       default:
-           break;
-       }
-       found = 0;
+       similar = 0;
 
        /*
         * We could use krb5_keysalt_iterate to replace this loop, or use
@@ -137,74 +146,44 @@ add_key_rnd(context, master_eblock, ks_tuple, ks_tuple_count, db_entry, kvno)
         * circular library dependencies.
         */
        for (j = 0; j < i; j++) {
-           switch (old_enctype = ks_tuple[j].ks_enctype) {
-           case ENCTYPE_DES_CBC_MD4:
-           case ENCTYPE_DES_CBC_MD5:
-           case ENCTYPE_DES_CBC_RAW:
-               old_enctype = ENCTYPE_DES_CBC_CRC;
-           default:
-               break;
-           }
-           if (old_enctype == new_enctype) {
-               found = 1;
+           if ((retval = krb5_c_enctype_compare(context,
+                                                ks_tuple[i].ks_enctype,
+                                                ks_tuple[j].ks_enctype,
+                                                &similar)))
+               return(retval);
+
+           if (similar)
                break;
-           }
        }
-       if (found)
-           continue;
-        if (retval = krb5_dbe_create_key_data(context, db_entry)) 
-           goto add_key_rnd_err;
 
-       if (retval = krb5_dbe_find_enctype(context, &krbtgt_entry,
-                                          ks_tuple[i].ks_enctype,
-                                          -1, 0, &krbtgt_kdata)) 
-           goto add_key_rnd_err;
+       if (similar)
+           continue;
 
-       /* Decrypt key */
-       if (retval = krb5_dbekd_decrypt_key_data(context, master_eblock, 
-                                                krbtgt_kdata,&krbtgt_key,NULL))
+        if (retval = krb5_dbe_create_key_data(context, db_entry)) 
            goto add_key_rnd_err;
 
-       /* Init key */
-       krbtgt_key.enctype = ks_tuple[i].ks_enctype;
-       krb5_use_enctype(context, &krbtgt_eblock, ks_tuple[i].ks_enctype);
-       if (retval = krb5_process_key(context, &krbtgt_eblock, &krbtgt_key)) {
-           goto add_key_rnd_err;
-       }
+       /* there used to be code here to extract the old key, and derive
+          a new key from it.  Now that there's a unified prng, that isn't
+          necessary. */
 
-       /* Init random generator */
-       if (retval = krb5_init_random_key(context, &krbtgt_eblock,
-                                         &krbtgt_key, &krbtgt_seed)) {
-           krb5_finish_key(context, &krbtgt_eblock);
+       /* make new key */
+       if ((retval = krb5_c_make_random_key(context, ks_tuple[i].ks_enctype,
+                                            &key)))
            goto add_key_rnd_err;
-       }
 
-       if (retval = krb5_random_key(context,&krbtgt_eblock,krbtgt_seed,&key)) {
-           krb5_finish_random_key(context, &krbtgt_eblock, &krbtgt_seed);
-           krb5_finish_key(context, &krbtgt_eblock);
-           goto add_key_rnd_err;
-       }
+       retval = krb5_dbekd_encrypt_key_data(context, master_key, 
+                                            &key, NULL, kvno, 
+                                            &db_entry->key_data[db_entry->n_key_data-1]);
 
-       krb5_finish_random_key(context, &krbtgt_eblock, &krbtgt_seed);
-       krb5_finish_key(context, &krbtgt_eblock);
+       krb5_free_keyblock_contents(context, &key);
 
-       if (retval = krb5_dbekd_encrypt_key_data(context, master_eblock, 
-                                                key, NULL, kvno, 
-                                                &db_entry->key_data[db_entry->n_key_data-1])) {
-           krb5_free_keyblock(context, key);
+       if (retval)
            goto add_key_rnd_err;
-       }
-
-       /* Finish random key */
-       krb5_free_keyblock(context, key);
     }
 
-add_key_rnd_err:;
+add_key_rnd_err:
     krb5_db_free_principal(context, &krbtgt_entry, one);
-    if (krbtgt_key.contents && krbtgt_key.length) {
-       memset(krbtgt_key.contents, 0, krbtgt_key.length);
-       krb5_xfree(krbtgt_key.contents);
-    }
+
     return(retval);
 }
 
@@ -215,9 +194,9 @@ add_key_rnd_err:;
  * As a side effect all old keys are nuked.
  */
 krb5_error_code
-krb5_dbe_crk(context, master_eblock, ks_tuple, ks_tuple_count, db_entry)
+krb5_dbe_crk(context, master_key, ks_tuple, ks_tuple_count, db_entry)
     krb5_context         context;
-    krb5_encrypt_block  * master_eblock;
+    krb5_keyblock       * master_key;
     krb5_key_salt_tuple        * ks_tuple;
     int                          ks_tuple_count;
     krb5_db_entry      * db_entry;
@@ -237,7 +216,7 @@ krb5_dbe_crk(context, master_eblock, ks_tuple, ks_tuple_count, db_entry)
     /* increment the kvno */
     kvno++;
 
-    if (retval = add_key_rnd(context, master_eblock, ks_tuple, 
+    if (retval = add_key_rnd(context, master_key, ks_tuple, 
                             ks_tuple_count, db_entry, kvno)) {
        cleanup_key_data(context, db_entry->n_key_data, db_entry->key_data);
        db_entry->n_key_data = key_data_count;
@@ -255,9 +234,9 @@ krb5_dbe_crk(context, master_eblock, ks_tuple, ks_tuple_count, db_entry)
  * As a side effect all old keys older than the max kvno are nuked.
  */
 krb5_error_code
-krb5_dbe_ark(context, master_eblock, ks_tuple, ks_tuple_count, db_entry)
+krb5_dbe_ark(context, master_key, ks_tuple, ks_tuple_count, db_entry)
     krb5_context         context;
-    krb5_encrypt_block  * master_eblock;
+    krb5_keyblock       * master_key;
     krb5_key_salt_tuple        * ks_tuple;
     int                          ks_tuple_count;
     krb5_db_entry      * db_entry;
@@ -278,7 +257,7 @@ krb5_dbe_ark(context, master_eblock, ks_tuple, ks_tuple_count, db_entry)
     /* increment the kvno */
     kvno++;
 
-    if (retval = add_key_rnd(context, master_eblock, ks_tuple, 
+    if (retval = add_key_rnd(context, master_key, ks_tuple, 
                             ks_tuple_count, db_entry, kvno)) {
        cleanup_key_data(context, db_entry->n_key_data, db_entry->key_data);
        db_entry->n_key_data = key_data_count;
@@ -307,10 +286,10 @@ krb5_dbe_ark(context, master_eblock, ks_tuple, ks_tuple_count, db_entry)
  * If passwd is NULL the assumes that the caller wants a random password.
  */
 static krb5_error_code
-add_key_pwd(context, master_eblock, ks_tuple, ks_tuple_count, passwd, 
+add_key_pwd(context, master_key, ks_tuple, ks_tuple_count, passwd, 
            db_entry, kvno)
     krb5_context         context;
-    krb5_encrypt_block  * master_eblock;
+    krb5_keyblock       * master_key;
     krb5_key_salt_tuple        * ks_tuple;
     int                          ks_tuple_count;
     char               * passwd;
@@ -318,7 +297,6 @@ add_key_pwd(context, master_eblock, ks_tuple, ks_tuple_count, passwd,
     int                          kvno;
 {
     krb5_error_code      retval;
-    krb5_encrypt_block    key_eblock;
     krb5_keysalt         key_salt;
     krb5_keyblock        key;
     krb5_data            pwd;
@@ -328,40 +306,30 @@ add_key_pwd(context, master_eblock, ks_tuple, ks_tuple_count, passwd,
     retval = 0;
 
     for (i = 0; i < ks_tuple_count; i++) {
-       krb5_enctype new_enctype, old_enctype;
+       krb5_boolean similar;
+
+       similar = 0;
 
-       switch (new_enctype = ks_tuple[i].ks_enctype) {
-       case ENCTYPE_DES_CBC_MD4:
-       case ENCTYPE_DES_CBC_MD5:
-       case ENCTYPE_DES_CBC_RAW:
-           new_enctype = ENCTYPE_DES_CBC_CRC;
-       default:
-           break;
-       }
        /*
         * We could use krb5_keysalt_iterate to replace this loop, or use
         * krb5_keysalt_is_present for the loop below, but we want to avoid
         * circular library dependencies.
         */
-       for (found = j = 0; j < i; j++) {
-           if (ks_tuple[j].ks_salttype == ks_tuple[i].ks_salttype) {
-               switch (old_enctype = ks_tuple[j].ks_enctype) {
-               case ENCTYPE_DES_CBC_MD4:
-               case ENCTYPE_DES_CBC_MD5:
-               case ENCTYPE_DES_CBC_RAW:
-                   old_enctype = ENCTYPE_DES_CBC_CRC;
-               default:
-                   break;
-               }
-               if (old_enctype == new_enctype) {
-                   found = 1;
-                   break;
-               }
-           }
+       for (j = 0; j < i; j++) {
+           if ((retval = krb5_c_enctype_compare(context,
+                                                ks_tuple[i].ks_enctype,
+                                                ks_tuple[j].ks_enctype,
+                                                &similar)))
+               return(retval);
+
+           if (similar &&
+               (ks_tuple[j].ks_salttype == ks_tuple[i].ks_salttype))
+               break;
        }
-       if (found)
+
+       if (j < i)
            continue;
-       krb5_use_enctype(context, &key_eblock, ks_tuple[i].ks_enctype);
+
        if (retval = krb5_dbe_create_key_data(context, db_entry)) 
            return(retval);
 
@@ -422,8 +390,9 @@ add_key_pwd(context, master_eblock, ks_tuple, ks_tuple_count, passwd,
 
        pwd.data = passwd;
        pwd.length = strlen(passwd);
-       if (retval = krb5_string_to_key(context, &key_eblock, &key, &pwd, 
-                                       &key_salt.data)) {
+
+       if ((retval = krb5_c_string_to_key(context, ks_tuple[i].ks_enctype,
+                                          &pwd, &key_salt.data, &key))) {
             if (key_salt.data.data)
                  free(key_salt.data.data);
             return(retval);
@@ -433,7 +402,7 @@ add_key_pwd(context, master_eblock, ks_tuple, ks_tuple_count, passwd,
            key_salt.data.length = 
              krb5_princ_realm(context, db_entry->princ)->length;
 
-       if (retval = krb5_dbekd_encrypt_key_data(context, master_eblock, &key,
+       if (retval = krb5_dbekd_encrypt_key_data(context, master_key, &key,
                     (const krb5_keysalt *)&key_salt,
                     kvno, &db_entry->key_data[db_entry->n_key_data-1])) {
            if (key_salt.data.data)
@@ -455,10 +424,10 @@ add_key_pwd(context, master_eblock, ks_tuple, ks_tuple_count, passwd,
  * As a side effect all old keys are nuked.
  */
 krb5_error_code
-krb5_dbe_cpw(context, master_eblock, ks_tuple, ks_tuple_count, passwd,
+krb5_dbe_cpw(context, master_key, ks_tuple, ks_tuple_count, passwd,
             new_kvno, db_entry)
     krb5_context         context;
-    krb5_encrypt_block  * master_eblock;
+    krb5_keyblock       * master_key;
     krb5_key_salt_tuple        * ks_tuple;
     int                          ks_tuple_count;
     char               * passwd;
@@ -483,7 +452,7 @@ krb5_dbe_cpw(context, master_eblock, ks_tuple, ks_tuple_count, passwd,
     if (new_kvno < old_kvno+1)
        new_kvno = old_kvno+1;
 
-    if (retval = add_key_pwd(context, master_eblock, ks_tuple, ks_tuple_count,
+    if (retval = add_key_pwd(context, master_key, ks_tuple, ks_tuple_count,
                             passwd, db_entry, new_kvno)) {
        cleanup_key_data(context, db_entry->n_key_data, db_entry->key_data);
        db_entry->n_key_data = key_data_count;
@@ -501,9 +470,9 @@ krb5_dbe_cpw(context, master_eblock, ks_tuple, ks_tuple_count, passwd,
  * As a side effect all old keys older than the max kvno are nuked.
  */
 krb5_error_code
-krb5_dbe_apw(context, master_eblock, ks_tuple, ks_tuple_count, passwd, db_entry)
+krb5_dbe_apw(context, master_key, ks_tuple, ks_tuple_count, passwd, db_entry)
     krb5_context         context;
-    krb5_encrypt_block  * master_eblock;
+    krb5_keyblock       * master_key;
     krb5_key_salt_tuple        * ks_tuple;
     int                          ks_tuple_count;
     char               * passwd;
@@ -526,7 +495,7 @@ krb5_dbe_apw(context, master_eblock, ks_tuple, ks_tuple_count, passwd, db_entry)
     /* increment the kvno */
     new_kvno = old_kvno+1;
 
-    if (retval = add_key_pwd(context, master_eblock, ks_tuple, ks_tuple_count,
+    if (retval = add_key_pwd(context, master_key, ks_tuple, ks_tuple_count,
                             passwd, db_entry, new_kvno)) {
        cleanup_key_data(context, db_entry->n_key_data, db_entry->key_data);
        db_entry->n_key_data = key_data_count;
index 80c9213dd36d9879718bd016818481af626ff859..ab4d07e23179580dc9d35ba44673e086f15c0011 100644 (file)
  * 
  */
 
+/*
+ * Copyright (C) 1998 by the FundsXpress, INC.
+ * 
+ * All rights reserved.
+ * 
+ * Export of this software from the United States of America may require
+ * a specific license from the United States Government.  It is the
+ * responsibility of any person or organization contemplating export to
+ * obtain such a license before exporting.
+ * 
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of FundsXpress. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  FundsXpress makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
 #if HAVE_UNISTD_H
 #include <unistd.h>
 #endif
@@ -325,9 +351,9 @@ krb5_db2_db_close_database(context)
  * Set/Get the master key associated with the database
  */
 krb5_error_code
-krb5_db2_db_set_mkey(context, eblock)
+krb5_db2_db_set_mkey(context, key)
     krb5_context context;
-    krb5_encrypt_block *eblock;
+    krb5_keyblock *key;
 {
     krb5_db2_context *db_ctx;
 
@@ -335,14 +361,14 @@ krb5_db2_db_set_mkey(context, eblock)
        return(KRB5_KDB_DBNOTINITED);
 
     db_ctx = context->db_context;
-    db_ctx->db_master_key = eblock;
+    db_ctx->db_master_key = key;
     return 0;
 }
 
 krb5_error_code
-krb5_db2_db_get_mkey(context, eblock)
+krb5_db2_db_get_mkey(context, key)
     krb5_context context;
-    krb5_encrypt_block **eblock;
+    krb5_keyblock **key;
 {
     krb5_db2_context *db_ctx;
 
@@ -350,7 +376,7 @@ krb5_db2_db_get_mkey(context, eblock)
        return(KRB5_KDB_DBNOTINITED);
 
     db_ctx = context->db_context;
-    *eblock = db_ctx->db_master_key;
+    *key = db_ctx->db_master_key;
 
     return 0;
 }
index d17fde476995ba3a378000f75baffc6b6b683e7b..f2f01311e724e753cb8ee1c458e14d14fbf35de8 100644 (file)
@@ -58,7 +58,7 @@ typedef struct _krb5_db2_context {
     int                 db_locks_held;  /* Number of times locked       */
     int                 db_lock_mode;   /* Last lock mode, e.g. greatest*/
     krb5_boolean        db_nb_locks;    /* [Non]Blocking lock modes     */
-    krb5_encrypt_block *db_master_key;  /* Master key of database       */
+    krb5_keyblock      *db_master_key;  /* Master key of database       */
 } krb5_db2_context;
 
 #define KRB5_DB2_MAX_RETRY 5
index 1ae241dfa02dd62fd89144551563e23fa796d420..7af32d720be926d2584e014bba68780a21be388c 100644 (file)
@@ -330,10 +330,10 @@ krb5_dbm_db_close_database(context)
  * The should really reference the db_context
  */
 krb5_error_code
-krb5_dbm_db_set_mkey(context, db_context, eblock)
+krb5_dbm_db_set_mkey(context, db_context, key)
     krb5_context         context;
     krb5_db_context    * db_context;
-    krb5_encrypt_block  * eblock;
+    krb5_keyblock  * key;
 {
     krb5_db_context *db_ctx;
 
@@ -341,15 +341,15 @@ krb5_dbm_db_set_mkey(context, db_context, eblock)
        return(KRB5_KDB_DBNOTINITED);
 
     db_ctx = context->db_context;
-    db_ctx->db_master_key = eblock;
+    db_ctx->db_master_key = key;
     return 0;
 }
 
 krb5_error_code
-krb5_dbm_db_get_mkey(context, db_context, eblock)
+krb5_dbm_db_get_mkey(context, db_context, key)
     krb5_context         context;
     krb5_db_context    * db_context;
-    krb5_encrypt_block  **eblock;
+    krb5_keyblock  **key;
 {
     krb5_db_context *db_ctx;
 
@@ -357,7 +357,7 @@ krb5_dbm_db_get_mkey(context, db_context, eblock)
        return(KRB5_KDB_DBNOTINITED);
 
     db_ctx = context->db_context;
-    *eblock = db_ctx->db_master_key;
+    *key = db_ctx->db_master_key;
     return 0;
 
 }
index 209e4f3ca9ca5071f1ad3074c2c5b5f3c2e7f26e..a26b7f79da5a01d81b0eb7561d359c6157834723 100644 (file)
@@ -735,40 +735,27 @@ krb5_dbe_search_enctype(kcontext, dbentp, start, ktype, stype, kvno, kdatap)
        }
     }
 
-    /*
-     * ENCTYPE_DES_CBC_CRC, ENCTYPE_DES_CBC_MD4, ENCTYPE_DES_CBC_MD5,
-     * ENCTYPE_DES_CBC_RAW all use the same key.
-     */
-    switch (ktype) {
-    case ENCTYPE_DES_CBC_MD4:
-    case ENCTYPE_DES_CBC_MD5:
-    case ENCTYPE_DES_CBC_RAW:
-       ktype = ENCTYPE_DES_CBC_CRC;
-       break;
-    default:
-       break;
-    }
-
     maxkvno = -1;
     datap = (krb5_key_data *) NULL;
     for (i = *start; i < dbentp->n_key_data; i++) {
-        krb5_enctype db_ktype;
-        krb5_int32   db_stype;
-
-       switch (db_ktype = dbentp->key_data[i].key_data_type[0]) {
-       case ENCTYPE_DES_CBC_MD4:
-       case ENCTYPE_DES_CBC_MD5:
-       case ENCTYPE_DES_CBC_RAW:
-           db_ktype = ENCTYPE_DES_CBC_CRC;
-       default:
-           break;
-       }
+        krb5_boolean    similar;
+       krb5_error_code ret;
+        krb5_int32      db_stype;
+
        if (dbentp->key_data[i].key_data_ver > 1) {
            db_stype = dbentp->key_data[i].key_data_type[1];
        } else {
            db_stype = KRB5_KDB_SALTTYPE_NORMAL;
        }
-       if (((db_ktype == (krb5_enctype) ktype) || (ktype < 0)) && 
+       
+       if (ktype >= 0) {
+           if ((ret = krb5_c_enctype_compare(kcontext, (krb5_enctype) ktype,
+                                             dbentp->key_data[i].key_data_type[0],
+                                             &similar)))
+               return(ret);
+       }
+
+       if (((ktype < 0) || similar) &&
            ((db_stype == stype) || (stype < 0))) {
            if (kvno >= 0) {
                if (kvno == dbentp->key_data[i].key_data_kvno) {
index 9c184b5148881d4a6477400ad533d03f3c62d956..63a7bf7c88b8b14b9861941bbd7ba65d799cbd38 100644 (file)
@@ -89,7 +89,7 @@ krb5_ktkdb_get_entry(context, id, principal, kvno, enctype, entry)
     krb5_enctype         enctype;
     krb5_keytab_entry  * entry;
 {
-    krb5_encrypt_block  * master_key;
+    krb5_keyblock       * master_key;
     krb5_error_code      kerror = 0;
     krb5_key_data      * key_data;
     krb5_db_entry        db_entry;
index 121c72148847c6c9bf4a2ed54c38700b50e570ab..4bab17024eaa9f2cf6f4ead1c9e2c6e078a39512 100644 (file)
 /*
  * Verify that the master key in *mkey matches the database entry
  * for mprinc.
- *
- * eblock points to an encrypt_block used for the realm in question.
  */
 
 krb5_error_code
-krb5_db_verify_master_key(context, mprinc, mkey, eblock)
+krb5_db_verify_master_key(context, mprinc, mkey)
     krb5_context context;
     krb5_principal mprinc;
     krb5_keyblock *mkey;
-    krb5_encrypt_block *eblock;
 {
     krb5_error_code retval;
     krb5_db_entry master_entry;
@@ -60,24 +57,18 @@ krb5_db_verify_master_key(context, mprinc, mkey, eblock)
        return(KRB5KDC_ERR_PRINCIPAL_NOT_UNIQUE);
     }  
 
-    /* do any necessary key pre-processing */
-    if ((retval = krb5_process_key(context, eblock, mkey))) {
-       krb5_db_free_principal(context, &master_entry, nprinc);
-       return(retval);
-    }
-    if ((retval = krb5_dbekd_decrypt_key_data(context, eblock, 
+    if ((retval = krb5_dbekd_decrypt_key_data(context, mkey, 
                                              &master_entry.key_data[0],
                                              &tempkey, NULL))) {
-       (void) krb5_finish_key(context, eblock);
        krb5_db_free_principal(context, &master_entry, nprinc);
        return retval;
     }
+
     if (mkey->length != tempkey.length ||
-       memcmp((char *)mkey->contents, (char *)tempkey.contents,mkey->length)) {
+       memcmp((char *)mkey->contents,
+              (char *)tempkey.contents,mkey->length)) {
        retval = KRB5_KDB_BADMASTERKEY;
-       (void) krb5_finish_key(context, eblock);
-    } else
-       retval = krb5_finish_key(context, eblock);
+    }
 
     memset((char *)tempkey.contents, 0, tempkey.length);
     krb5_xfree(tempkey.contents);
index 54e185d2ec82f7a5ab159f641ba781fbfe451409..0162fc450f83088fa6983167ec7a0d5e76a9ae9b 100644 (file)
@@ -1,3 +1,26 @@
+Wed Aug 12 18:32:44 1998  Tom Yu  <tlyu@mit.edu>
+
+       * rd_req.c (krb_set_key): Nuke the krb5_keyblock if it's set.
+       (krb_set_key_krb5): New function to set a static krb5_keyblock for
+       decryption purposes.
+       (krb_clear_key_krb5): New function to clear the static
+       krb5_keyblock if it's set.
+       (krb_rd_req): Call decomp_ticket or decomp_tkt_krb5 as appropriate
+       to the key type.
+
+       * decomp_tkt.c (decomp_tkt_krb5): New wrapper to call
+       dcmp_tkt_int.
+       (decomp_ticket): Transform into wrapper to call dcmp_tkt_int.
+       (dcmp_tkt_int): New internal function; use a krb5_keyblock to
+       decrypt the ticket if present; else just use plain old C_Block.
+
+       * cr_tkt.c (krb_create_ticket): Transform into a wrapper that
+       calls krb_cr_tkt_int.
+       (krb_cr_tkt_krb5): New wrapper to call krb_cr_tkt_int.
+       (krb_cr_tkt_int): New internal function that potentially uses a
+       krb5_keyblock to encrypt the ticket, or just a C_Block if the
+       krb5_keyblock is not set.
+
 Mon Aug 10 17:51:59 1998  Matthew D Hancher  <mdh@mit.edu>
 
        * rd_svc_key.c (read_service_key): Don't call krb5_kt_close() if 
@@ -12,6 +35,14 @@ Fri Aug  7 11:04:03 1998  Tom Yu  <tlyu@mit.edu>
 
        * tf_util.c (tf_init): Add call to getuid() to initialize me.
 
+Thu Jul 30 13:13:30 1998  Sam Hartman  <hartmans@utwig.mesas.com>
+
+       * tf_util.c (tf_init): s/,/= so getuid() actually gets called
+
+Sun Jul 26 17:51:24 1998  Sam Hartman  <hartmans@utwig.mesas.com>
+
+       * Makefile.in (LIBMAJOR): Bump libmajor
+
 Thu Jul  9 19:35:01 1998  Matthew D Hancher  <mdh@mit.edu>
 
        * tf_util.c (tf_init): Fixed a potential race condition in the opening 
index f75a6327bf12a501a5a7f4869d79dd32c953e411..af2dca43c52d860e78b30db63bb26d5896d07094 100644 (file)
@@ -8,7 +8,7 @@ DEFINES=-I$(srcdir)/../../include/kerberosIV
 ##DOS##OBJFILE=krb4.lst
 
 LIB=krb4
-LIBMAJOR=1
+LIBMAJOR=2
 LIBMINOR=0
 RELDIR=krb4
 
index 39ed53859c80a6ac7aca98a56cea356e34694870..a8224f879a7fb4000c904beed4295fce1f07092e 100644 (file)
@@ -13,7 +13,7 @@
 #include "krb.h"
 #include "prot.h"
 #include <string.h>
-
+#include <krb5.h>
 /*
  * Create ticket takes as arguments information that should be in a
  * ticket, and the KTEXT object in which the ticket should be
  * <=7 bytes           null               null pad to 8 byte multiple
  *
  */
+int
+krb_create_ticket(tkt, flags, pname, pinstance, prealm, paddress,
+                 session, life, time_sec, sname, sinstance, key, k5key)
+    KTEXT   tkt;                /* Gets filled in by the ticket */
+    unsigned char flags;        /* Various Kerberos flags */
+    char    *pname;             /* Principal's name */
+    char    *pinstance;         /* Principal's instance */
+    char    *prealm;            /* Principal's authentication domain */
+    long    paddress;           /* Net address of requesting entity */
+    char    *session;           /* Session key inserted in ticket */
+    short   life;               /* Lifetime of the ticket */
+    long    time_sec;           /* Issue time and date */
+    char    *sname;             /* Service Name */
+    char    *sinstance;         /* Instance Name */
+    C_Block key;                /* Service's secret key */
+{
+    return krb_cr_tkt_int(tkt, flags, pname, pinstance, prealm, paddress,
+                         session, life, time_sec, sname, sinstance,
+                         key, NULL);
+}
 
-int krb_create_ticket(tkt, flags, pname, pinstance, prealm, paddress,
-                 session, life, time_sec, sname, sinstance, key)
+int
+krb_cr_tkt_krb5(tkt, flags, pname, pinstance, prealm, paddress,
+                 session, life, time_sec, sname, sinstance, k5key)
+    KTEXT   tkt;                /* Gets filled in by the ticket */
+    unsigned char flags;        /* Various Kerberos flags */
+    char    *pname;             /* Principal's name */
+    char    *pinstance;         /* Principal's instance */
+    char    *prealm;            /* Principal's authentication domain */
+    long    paddress;           /* Net address of requesting entity */
+    char    *session;           /* Session key inserted in ticket */
+    short   life;               /* Lifetime of the ticket */
+    long    time_sec;           /* Issue time and date */
+    char    *sname;             /* Service Name */
+    char    *sinstance;         /* Instance Name */
+    krb5_keyblock *k5key;      /* NULL if not present */
+{
+    C_Block key;
+
+    return krb_cr_tkt_int(tkt, flags, pname, pinstance, prealm, paddress,
+                         session, life, time_sec, sname, sinstance,
+                         key, k5key);
+}
+
+static int
+krb_cr_tkt_int(tkt, flags, pname, pinstance, prealm, paddress,
+              session, life, time_sec, sname, sinstance, key, k5key)
     KTEXT   tkt;                /* Gets filled in by the ticket */
     unsigned char flags;        /* Various Kerberos flags */
     char    *pname;             /* Principal's name */
@@ -84,6 +128,7 @@ int krb_create_ticket(tkt, flags, pname, pinstance, prealm, paddress,
     char    *sname;             /* Service Name */
     char    *sinstance;         /* Instance Name */
     C_Block key;                /* Service's secret key */
+    krb5_keyblock *k5key;      /* NULL if not present */
 {
     Key_schedule key_s;
     register char *data;        /* running index into ticket */
@@ -124,10 +169,43 @@ int krb_create_ticket(tkt, flags, pname, pinstance, prealm, paddress,
     }
 
 #ifndef NOENCRYPTION
-    /* Encrypt the ticket in the services key */        
-    key_sched(key,key_s);
-    pcbc_encrypt((C_Block *)tkt->dat,(C_Block *)tkt->dat,
-                 (long) tkt->length,key_s,(C_Block *)key,1);
+    /* Encrypt the ticket in the services key */
+    if (k5key != NULL) {
+       /* block locals */
+       krb5_data in;
+       krb5_enc_data out;
+       krb5_error_code ret;
+       size_t enclen;
+
+       in.length = tkt->length;
+       in.data = tkt->dat;
+       /* XXX assumes context arg is ignored */
+       ret = krb5_c_encrypt_length(NULL, k5key->enctype,
+                                   (size_t)in.length, &enclen);
+       if (ret)
+           return KFAILURE;
+       out.ciphertext.length = enclen;
+       out.ciphertext.data = malloc(enclen);
+       if (out.ciphertext.data == NULL)
+           return KFAILURE;    /* XXX maybe ENOMEM? */
+
+       /* XXX assumes context arg is ignored */
+       ret = krb5_c_encrypt(NULL, k5key, KRB5_KEYUSAGE_KDC_REP_TICKET,
+                            NULL, &in, &out);
+       if (ret) {
+           free(out.ciphertext.data);
+           return KFAILURE;
+       } else {
+           tkt->length = out.ciphertext.length;
+           memcpy(tkt->dat, out.ciphertext.data, out.ciphertext.length);
+           memset(out.ciphertext.data, 0, out.ciphertext.length);
+           free(out.ciphertext.data);
+       }
+    } else {
+       key_sched(key,key_s);
+       pcbc_encrypt((C_Block *)tkt->dat,(C_Block *)tkt->dat,
+                    (long) tkt->length,key_s,(C_Block *)key,1);
+    }
 #endif /* !NOENCRYPTION */
     return 0;
 }
index 3c595236870eadc0600ef343befbceadfe08fa35..d4dfd4edcb5ae4cc21cb667ed596f7f3816cf683 100644 (file)
@@ -13,6 +13,7 @@
 #include "krb.h"
 #include "prot.h"
 #include <string.h>
+#include <krb5.h>
 
 #ifdef KRB_CRYPT_DEBUG
 extern int krb_debug;
@@ -64,6 +65,57 @@ decomp_ticket(tkt, flags, pname, pinstance, prealm, paddress, session,
     C_Block key;               /* Service's secret key
                                  * (to decrypt the ticket) */
     Key_schedule key_s;                /* The precomputed key schedule */
+{
+    return
+       dcmp_tkt_int(tkt, flags, pname, pinstance, prealm,
+                    paddress, session, life, time_sec, sname, sinstance,
+                    key, key_s, NULL);
+}
+
+int
+decomp_tkt_krb5(tkt, flags, pname, pinstance, prealm, paddress, session,
+              life, time_sec, sname, sinstance, k5key)
+    KTEXT tkt;                 /* The ticket to be decoded */
+    unsigned char *flags;       /* Kerberos ticket flags */
+    char *pname;               /* Authentication name */
+    char *pinstance;           /* Principal's instance */
+    char *prealm;              /* Principal's authentication domain */
+    unsigned KRB4_32 *paddress; /* Net address of entity
+                                 * requesting ticket */
+    C_Block session;           /* Session key inserted in ticket */
+    int *life;                         /* Lifetime of the ticket */
+    unsigned KRB4_32 *time_sec; /* Issue time and date */
+    char *sname;               /* Service name */
+    char *sinstance;           /* Service instance */
+    krb5_keyblock *k5key;      /* krb5 keyblock of service */
+{
+    C_Block key;               /* placeholder; doesn't get used */
+    Key_schedule key_s;                /* placeholder; doesn't get used */
+
+    return
+       dcmp_tkt_int(tkt, flags, pname, pinstance, prealm, paddress, session,
+                    life, time_sec, sname, sinstance, key, key_s, k5key);
+}
+
+static int
+dcmp_tkt_int(tkt, flags, pname, pinstance, prealm, paddress, session,
+              life, time_sec, sname, sinstance, key, key_s, k5key)
+    KTEXT tkt;                 /* The ticket to be decoded */
+    unsigned char *flags;       /* Kerberos ticket flags */
+    char *pname;               /* Authentication name */
+    char *pinstance;           /* Principal's instance */
+    char *prealm;              /* Principal's authentication domain */
+    unsigned KRB4_32 *paddress; /* Net address of entity
+                                 * requesting ticket */
+    C_Block session;           /* Session key inserted in ticket */
+    int *life;                         /* Lifetime of the ticket */
+    unsigned KRB4_32 *time_sec; /* Issue time and date */
+    char *sname;               /* Service name */
+    char *sinstance;           /* Service instance */
+    C_Block key;               /* Service's secret key
+                                 * (to decrypt the ticket) */
+    Key_schedule key_s;                /* The precomputed key schedule */
+    krb5_keyblock *k5key;      /* krb5 keyblock of service */
 {
     static int tkt_swap_bytes;
     unsigned char *uptr;
@@ -83,8 +135,37 @@ decomp_ticket(tkt, flags, pname, pinstance, prealm, paddress, session,
        memset(keybuf, 0, sizeof(keybuf));      /* Clear the buffer */
     }
 #endif
-    pcbc_encrypt((C_Block *)tkt->dat,(C_Block *)tkt->dat,
-                 (long) tkt->length,key_s,(C_Block *) key,0);
+    if (k5key != NULL) {
+       /* block locals */
+       krb5_enc_data in;
+       krb5_data out;
+       krb5_error_code ret;
+
+       in.enctype = k5key->enctype;
+       in.kvno = 0;
+       in.ciphertext.length = tkt->length;
+       in.ciphertext.data = tkt->dat;
+       out.length = tkt->length;
+       out.data = malloc(tkt->length);
+       if (out.data == NULL)
+           return KFAILURE;    /* XXX maybe ENOMEM? */
+
+       /* XXX note the following assumes that context arg isn't used  */
+       ret =
+           krb5_c_decrypt(NULL, k5key,
+                          KRB5_KEYUSAGE_KDC_REP_TICKET, NULL, &in, &out);
+       if (ret) {
+           free(out.data);
+           return KFAILURE;
+       } else {
+           memcpy(tkt->dat, out.data, out.length);
+           memset(out.data, 0, out.length);
+           free(out.data);
+       }
+    } else {
+       pcbc_encrypt((C_Block *)tkt->dat,(C_Block *)tkt->dat,
+                    (long) tkt->length,key_s,(C_Block *) key,0);
+    }
 #endif /* ! NOENCRYPTION */
 #ifdef KRB_CRYPT_DEBUG
     if (krb_debug) {
index 79564e4f37564db2afbb8227ea57639dead62ef8..a78aadc881b71081ef1bcbb93725b5fe481a3a09 100644 (file)
@@ -32,6 +32,7 @@ static int st_kvno;           /* version number for this key */
 static char st_rlm[REALM_SZ];  /* server's realm */
 static char st_nam[ANAME_SZ];  /* service name */
 static char st_inst[INST_SZ];  /* server's instance */
+static int krb5_key;           /* whether krb5 key is used for decrypt */
 
 /*
  * This file contains two functions.  krb_set_key() takes a DES
@@ -62,11 +63,18 @@ static char st_inst[INST_SZ];       /* server's instance */
  * krb_rd_req().
  */
 
+#include <krb5.h>
+static krb5_keyblock srv_k5key;
+
 int
 krb_set_key(key,cvt)
     char *key;
     int cvt;
 {
+    if (krb5_key)
+       /* XXX assumes that context arg is ignored */
+       krb5_free_keyblock_contents(NULL, &srv_k5key);
+    krb5_key = 0;
 #ifdef NOENCRYPTION
     memset(ky, 0, sizeof(ky));
     return KSUCCESS;
@@ -79,6 +87,25 @@ krb_set_key(key,cvt)
 #endif /* NOENCRYPTION */
 }
 
+int
+krb_set_key_krb5(ctx, key)
+    krb5_context ctx;
+    krb5_keyblock *key;
+{
+    if (krb5_key)
+       krb5_free_keyblock_contents(ctx, &srv_k5key);
+    krb5_key = 1;
+    return krb5_copy_keyblock_contents(ctx, key, &srv_k5key);
+}
+
+void
+krb_clear_key_krb5(ctx)
+    krb5_context ctx;
+{
+    if (krb5_key)
+       krb5_free_keyblock_contents(ctx, &srv_k5key);
+    krb5_key = 0;
+}
 
 /*
  * krb_rd_req() takes an AUTH_MSG_APPL_REQUEST or
@@ -234,15 +261,25 @@ krb_rd_req(authent,service,instance,from_addr,ad,fn)
     /* Decrypt and take apart ticket */
 #endif
 
-    if (decomp_ticket(tkt,&ad->k_flags,ad->pname,ad->pinst,ad->prealm,
-                      &(ad->address),ad->session, &(ad->life),
-                      &(ad->time_sec),sname,iname,ky,serv_key)) {
+    if (!krb5_key) {
+       if (decomp_ticket(tkt,&ad->k_flags,ad->pname,ad->pinst,ad->prealm,
+                         &(ad->address),ad->session, &(ad->life),
+                         &(ad->time_sec),sname,iname,ky,serv_key)) {
 #ifdef KRB_CRYPT_DEBUG
-       log("Can't decode ticket");
+           log("Can't decode ticket");
 #endif
-        return(RD_AP_UNDEC);
+           return(RD_AP_UNDEC);
+       }
+    } else {
+       if (decomp_tkt_krb5(tkt, &ad->k_flags, ad->pname, ad->pinst,
+                           ad->prealm, &ad->address, ad->session,
+                           &ad->life, &ad->time_sec, sname, iname,
+                           srv_k5key)) {
+           return RD_AP_UNDEC;
+       }
     }
 
+
 #ifdef KRB_CRYPT_DEBUG
     if (krb_ap_req_debug) {
         log("Ticket Contents.");
index b3eb0b43a944f3b2f153c83c28fe517d73260925..1c7aadd9fa12c3598a6adc5b92665589a7e707d8 100644 (file)
@@ -182,7 +182,7 @@ int tf_init(tf_name, rw)
     int rw;
 {
     int     wflag;
-    uid_t   me, getuid();
+    uid_t   me= getuid();
     struct stat stat_buf, stat_buffd;
 #ifdef TKT_SHMEM
     char shmidname[MAXPATHLEN]; 
index f7922150e9e2376464d6df4404c9d8b667159fde..f1e1e81f9338f2205d1a45c50bcf6013e9f322af 100644 (file)
@@ -1,3 +1,11 @@
+Thu Jul 30 13:12:57 1998  Sam Hartman  <hartmans@utwig.mesas.com>
+
+       * configure.in: Test for sa_len so localaddr works on NetBSD.
+
+Sun Jul 26 17:46:47 1998  Sam Hartman  <hartmans@utwig.mesas.com>
+
+       * Makefile.in (LIBMAJOR): bump to 2
+
 Wed Apr 15 18:07:20 1998  Tom Yu  <tlyu@mit.edu>
 
        * Makefile.in (SHLIB_EXPDEPS): 
index 4864a2f94ff52fb6fb39679fcc4b08fb682f1996..12ce18512b854b5e6e79d1b6580205e2a224f4ee 100644 (file)
@@ -28,8 +28,8 @@ LIBDONE= error_tables/DONE asn.1/DONE ccache/DONE ccache/stdio/DONE \
 #SHLIB_LIBDIRS= @SHLIB_LIBDIRS@
 
 LIB=krb5
-LIBMAJOR=1
-LIBMINOR=2
+LIBMAJOR=2
+LIBMINOR=1
 
 STOBJLISTS= \
        error_tables/OBJS.ST \
index a42ad235c3448702535906ab5e735485adb00a7d..ca3f679f504395501bee65fabe2e28b5cda8bfe8 100644 (file)
@@ -1,3 +1,10 @@
+1998-10-27  Marc Horowitz  <marc@mit.edu>
+
+       * asn1buf.c (asn1buf_sync): interoperation testing against heimdal
+       revealed a bug.  if extra fields are present in a SEQUENCE, they
+       are not ignored and skipped.  This caused the decoder to get out
+       of sync.
+
 Thu Jul  2 15:30:25 1998  Theodore Y. Ts'o  <tytso@mit.edu>
 
        * asn1_encode.c: Make the magic Macintosh EPOCH offset be 70 years
index 30dad8b49133679fda3965907e9cec2a2fd5925e..52ac387d50dac687e5e4b98c063f81b37070c850 100644 (file)
@@ -93,7 +93,7 @@ void asn1buf_sync(buf, subbuf)
      asn1buf * buf;
      asn1buf * subbuf;
 {
-  buf->next = subbuf->next;
+  buf->next = subbuf->bound + 1;
 }
 
 asn1_error_code asn1buf_destroy(buf)
index 2a4d39551d5b97437a1be3ee1d4ec2b9bfab4b75..71aa06dc8230cfccf720011fa62f3a640f9a27cd 100644 (file)
@@ -7,6 +7,10 @@ Fri Aug 20 18:30:00 1998  Miro Jurisic  <meeroh@mit.edu>
        * Added Frank's CCache API cache implementation and made
                it default on the Mac
 
+Thu Jul 30 13:12:30 1998  Sam Hartman  <hartmans@utwig.mesas.com>
+
+       * ccbase.c: Enable memory ccache (merge adapted from Kerbnet)
+
 1998-05-27  Theodore Ts'o  <tytso@rsts-11.mit.edu>
 
        * Makefile.in: Add ccache/memory as a directory to be recursively
diff --git a/src/lib/krb5/ccache/ccapi/Makefile.in b/src/lib/krb5/ccache/ccapi/Makefile.in
deleted file mode 100644 (file)
index e47ded4..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
-thisconfigdir=./../..
-BUILDTOP=$(REL)$(U)$(S)$(U)$(S)$(U)$(S)$(U)
-CFLAGS = $(CCOPTS) $(DEFS)
-
-##DOS##BUILDTOP = ..\..\..\..
-##DOS##PREFIXDIR = ccache\file
-##DOS##OBJFILE = file.lst
-##WIN16##LIBNAME=..\..\krb5.lib
-
-STLIBOBJS      = \
-       stdcc.o \
-       stdcc_util.o 
-
-OBJS   = stdcc.${OBJEXT} stdcc_util.${OBJEXT}
-
-SRCS   = $(srcdir)/stdcc.c $(srcdir)/stdcc_util.c 
-
-##DOS##LIBOBJS = $(OBJS)
-
-all-unix:: all-libobjs
-clean-unix:: clean-libobjs
diff --git a/src/lib/krb5/ccache/ccapi/stdcc.c b/src/lib/krb5/ccache/ccapi/stdcc.c
deleted file mode 100644 (file)
index 2b9007b..0000000
+++ /dev/null
@@ -1,394 +0,0 @@
-/**********************************************************
-  *
-  *     stdcc.c - additions to the Kerberos 5 library to support the memory credentical cache API
-  *    
-  *      Revision 1.1.1.1 - Frank Dabek July 1998
-  *
-  **********************************************************/
-
-#include "stdcc.h"
-#include "string.h"
-
-//declare our global object wanna-be
-//must be installed in ccdefops.c
-krb5_cc_ops krb5_cc_stdcc_ops = {
-     0,
-     "API",
-      krb5_stdcc_get_name,
-      krb5_stdcc_resolve,
-      krb5_stdcc_generate_new,
-      krb5_stdcc_initialize,
-      krb5_stdcc_destroy,
-      krb5_stdcc_close,
-      krb5_stdcc_store,
-      krb5_stdcc_retrieve,
-      krb5_stdcc_get_principal,
-      krb5_stdcc_start_seq_get,
-      krb5_stdcc_next_cred,
-      krb5_stdcc_end_seq_get,
-      krb5_stdcc_remove, 
-      krb5_stdcc_set_flags,
-};
-
-// -- generate_new  --------------------------------
-// - create a new cache with a unique name, corresponds to creating a named cache
-// - iniitialize the API here if we have to.
-krb5_error_code  krb5_stdcc_generate_new 
-       (krb5_context context, krb5_ccache *id ) 
-       
-  {
-  
-       krb5_ccache newCache;
-       char name[kStringLiteralLen];
-       cc_time_t time;
-       int err;
-       
-       //make sure the API has been intialized
-       if (gCntrlBlock == NULL) {
-         err = cc_initialize(&gCntrlBlock, CC_API_VER_1, NULL, NULL);
-         if (err != CC_NOERROR) return err;
-    }
-       
-       //allocate the cache structure
-       newCache = (krb5_ccache) malloc(sizeof(struct _krb5_ccache));
-       if (newCache == NULL) return KRB5_CC_NOMEM;
-       
-       //create a unique name
-       cc_get_change_time(gCntrlBlock, &time);
-       sprintf(name, "gen_new_cache%d", time);
-       
-       //create the new cache
-       err = cc_create(gCntrlBlock, name, CC_CRED_V5,  
-                       name, 0L, &(((stdccCacheDataPtr)(newCache->data))->NamedCache) );
-       if (err != CC_NOERROR) return err;
-       
-       //setup some fields
-       newCache->ops = &krb5_cc_stdcc_ops;
-       newCache->data = (stdccCacheDataPtr)malloc(sizeof(stdccCacheData));
-       
-       //return a pointer to the new cache
-       *id = newCache;
-               
-        return CC_NOERROR;
-  }
-  
-// -- resolve ------------------------------
-//
-// - create a new cache with the name stored in residual
-krb5_error_code  krb5_stdcc_resolve 
-        (krb5_context context, krb5_ccache *id , const char *residual ) {
-
-       krb5_ccache newCache;
-       int err,pos;
-       char *cName;
-       
-       //make sure the API has been intialized
-       if (gCntrlBlock == NULL) {
-         err = cc_initialize(&gCntrlBlock, CC_API_VER_1, NULL, NULL);
-         if (err != CC_NOERROR) return err;
-    }
-    
-    newCache = (krb5_ccache) malloc(sizeof(struct _krb5_ccache));
-       if (newCache == NULL) return KRB5_CC_NOMEM;
-       
-       newCache->ops = &krb5_cc_stdcc_ops;
-       newCache->data = (stdccCacheDataPtr)malloc(sizeof(stdccCacheData));
-       if (newCache->data == NULL) return KRB5_CC_NOMEM;
-       
-       cName = residual;
-       //attempt to find a cache by the same name before creating it
-       err = cc_open(gCntrlBlock, cName, CC_CRED_V5, 0L, &(((stdccCacheDataPtr)(newCache->data))->NamedCache));
-       //we didn't find it.. create it.
-       if (err) {
-               err = cc_create(gCntrlBlock, cName, CC_CRED_V5,  cName, 
-                       0L, &(((stdccCacheDataPtr)(newCache->data))->NamedCache) );
-               if (err != CC_NOERROR) return err; //still an error, return it
-       }
-       
-       //return new cache structure
-       *id = newCache;
-       return CC_NOERROR;
-  }
-  
- // -- initialize --------------------------------
- //-initialize the cache, check to see if one already exists for this principal
- //    if not set our principal to this principal. This searching enables ticket sharing
-  krb5_error_code  krb5_stdcc_initialize 
-       (krb5_context context, krb5_ccache id,  krb5_principal princ) 
-
-  {
-  
-       int err, err1, found;
-       //char cName[kStringLiteralLen];
-       char *cName = nil;
-       ccache_p *testNC = NULL;
-       ccache_it *it;
-       char *p = NULL, *targetName = NULL;
-       
-       //test id for null
-       if (id == NULL) return KRB5_CC_NOMEM;
-       
-       //test for initialized API
-       if (gCntrlBlock == NULL)
-               return CC_NO_EXIST; 
-               
-       //create a principal name for the named cache
-       err = krb5_unparse_name(context, princ, &cName);
-       if (err)
-               return(err);
-               
-       //sprintf(cName, "%s@%s", krb5_princ_name(context, princ)->data, krb5_princ_realm(context, princ)->data);
-
-       //look for a cache already extant for this principal
-       it = NULL;
-       found = err = 0;
-       while ((err != CC_END) && (!found)) {
-               err = cc_seq_fetch_NCs(gCntrlBlock, &testNC, &it);
-               if (err == CC_NOERROR) {
-                       cc_get_principal(gCntrlBlock, testNC, &p);
-                       if (strcmp(p, cName) == 0) {
-                               found = 1;
-                               cc_get_name(gCntrlBlock, testNC, &targetName);
-                       }
-                       cc_free_principal(gCntrlBlock, p);
-                       err1 = cc_close(gCntrlBlock, &testNC);
-               }
-       }
-       
-       if (!found)  
-               //we didn't find one with the name we were looking for, use the one we had and change the name
-               cc_set_principal(gCntrlBlock, (((stdccCacheDataPtr)(id->data))->NamedCache), CC_CRED_V5, cName);
-       else {
-               //we found a cache for this guy, lets trash ours and use that one - let's not; sgm 10/7/98
-               //cc_destroy(gCntrlBlock, &(((stdccCacheDataPtr)(id->data))->NamedCache));
-               err = cc_open(gCntrlBlock, targetName, CC_CRED_V5, 0L, &(((stdccCacheDataPtr)(id->data))->NamedCache));
-               if (err != CC_NOERROR) return err; //error opening
-               cc_free_name(gCntrlBlock, targetName);
-       }
-       
-       free(cName);
-       
-       return CC_NOERROR;
-       
-       }
-
-
-// -- store ----------------------------------
-// - store some credentials in our cache
- krb5_error_code  krb5_stdcc_store 
-        (krb5_context context, krb5_ccache id , krb5_creds *creds )  {
-       
-       cred_union *cu = NULL;
-       int err;
-       
-               
-               //copy the fields from the almost identical structures
-               dupK52cc(context, creds, &cu);
-                       
-               //finally store the credential
-               //store will copy (that is duplicate) everything
-               err = cc_store(gCntrlBlock, ((stdccCacheDataPtr)(id->data))->NamedCache, *cu);
-               if (err != CC_NOERROR) return err;
-               
-               //free the cred union
-               err = cc_free_creds(gCntrlBlock, &cu);
-                
-               return err;
-}
-
-
-// -- start_seq_get --------------------------
-// - begin an iterator call to get all of the credentials in the cache
-krb5_error_code  krb5_stdcc_start_seq_get 
-(krb5_context context, krb5_ccache id , krb5_cc_cursor *cursor ) {
-
-       //all we have to do is initialize the cursor
-       *cursor = NULL;
-       return CC_NOERROR;
-}
-
-// -- next cred ---------------------------
-// - get the next credential in the cache as part of an iterator call
-// - this maps to call to cc_seq_fetch_creds
-krb5_error_code  krb5_stdcc_next_cred 
-        (krb5_context context, 
-                  krb5_ccache id , 
-                  krb5_cc_cursor *cursor , 
-                  krb5_creds *creds ) {
-
-       int err;
-       cred_union *credU = NULL;
-       cc_creds *c = NULL;
-       
-       err = cc_seq_fetch_creds(gCntrlBlock, ((stdccCacheDataPtr)(id->data))->NamedCache,
-                                                        &credU, (ccache_it **)cursor);
-       
-       if (err != CC_NOERROR)
-               return err;
-       
-       //copy data     (with translation)
-       dupCCtoK5(context, credU->cred.pV5Cred, creds);
-       
-       //free our version of the cred
-       cc_free_creds(gCntrlBlock, &credU);
-       
-       return CC_NOERROR;
-       
-}
-
-
-// -- retreive -------------------
-// - try to find a matching credential in the cache
-krb5_error_code  krb5_stdcc_retrieve 
-                       (krb5_context context, 
-                  krb5_ccache id, 
-                  krb5_flags whichfields, 
-                  krb5_creds *mcreds, 
-                  krb5_creds *creds ) {
-                  
-       krb5_cc_cursor curs = NULL;
-       krb5_creds *fetchcreds;
-               
-       fetchcreds = (krb5_creds *)malloc(sizeof(krb5_creds));
-       if (fetchcreds == NULL) return KRB5_CC_NOMEM;
-       
-       //we're going to use the iterators
-       krb5_stdcc_start_seq_get(context, id, &curs);
-       
-       while  (krb5_stdcc_next_cred(context, id, &curs, fetchcreds) == CC_NOERROR) {
-               //look at each credential for a match
-               //use this match routine since it takes the whichfields and the API doesn't
-               if (stdccCredsMatch(context, fetchcreds, mcreds, whichfields)) {
-                               //we found it, copy and exit
-                               *creds = *fetchcreds;
-                               krb5_stdcc_end_seq_get(context, id, &curs);
-                               return CC_NOERROR;
-                       }
-               //free copy allocated by next_cred
-               krb5_free_cred_contents(context, fetchcreds);
-               }
-               
-       //no luck, end get and exti
-       krb5_stdcc_end_seq_get(context, id, &curs);
-       
-       return KRB5_CC_NOTFOUND;
-}
-
-// -- end seq ------------------------
-// - just free up the storage assoicated with the cursor (if we could)
- krb5_error_code  krb5_stdcc_end_seq_get 
-        (krb5_context context, krb5_ccache id , krb5_cc_cursor *cursor ) {
-        
-       //the limitation of the Ccache api and the seq calls
-       //causes trouble. cursor might have already been freed
-       //and anyways it is in the mac's heap so we need FreePtr
-       //but all i have is free
-      // FreePtr(*cursor);
-      
-      //LEAK IT!
-       *cursor = NULL;
-     }
-     
-// -- close ---------------------------
-// - free our pointers to the NC
-krb5_error_code  
-krb5_stdcc_close(context, id, princ)
-   krb5_context context;
-   krb5_ccache id;
-   krb5_principal princ;
-{
-               
-       //free it
-       free((stdccCacheDataPtr)(id->data));
-       //null it out
-       (stdccCacheDataPtr)(id->data) = NULL;
-       
-       return CC_NOERROR;
-}
-
-// -- destroy -------------
-// - free our storage and the cache
-krb5_error_code  
-krb5_stdcc_destroy (krb5_context context, krb5_ccache id ) {
-
-       int err;
-       
-       //destroy the named cache
-       err = cc_destroy(gCntrlBlock, &(((stdccCacheDataPtr)(id->data))->NamedCache));
-       //free the pointer to the record that held the pointer to the cache
-       free((stdccCacheDataPtr)(id->data));
-       //null it out
-       (stdccCacheDataPtr)(id->data) = NULL;
-       
-       return err;
-}
-
-       
-// -- getname ---------------------------
-// - return the name of the named cache
-char *  krb5_stdcc_get_name 
-        (krb5_context context, krb5_ccache id ) {
-        
-       char *ret = NULL;
-          int err;
-          
-          //just a wrapper
-       err = cc_get_name(gCntrlBlock, (((stdccCacheDataPtr)(id->data))->NamedCache), &ret);
-       
-       if (err != CC_NOERROR)
-                       return ret;
-               else
-                       return NULL;
-                       
-}
-
-// -- get_principal ---------------------------
-// - return the principal associated with the named cache
-krb5_error_code  
-krb5_stdcc_get_principal (krb5_context context, krb5_ccache id , krb5_principal *princ ) {
-
-       int err;
-       char *name = NULL;
-       
-       //another wrapper
-       err = cc_get_principal(gCntrlBlock, (((stdccCacheDataPtr)(id->data))->NamedCache), &name);
-
-       if (err != CC_NOERROR) 
-               return err;
-               
-       //turn it into a krb principal
-       err = krb5_parse_name(context, name, princ);
-       
-       return err;     
-}
-
-// -- set_flags ---------------------------
-// - currently a NOP since we don't store any flags in the NC
-krb5_error_code  krb5_stdcc_set_flags 
-        (krb5_context context, krb5_ccache id , krb5_flags flags ) {
-
-       return CC_NOERROR;
-}
-
-// - remove ---------------------------
-// - remove the specified credentials from the NC
-krb5_error_code  krb5_stdcc_remove 
-        (krb5_context context, krb5_ccache id , krb5_flags flags, krb5_creds *creds ) {
-    
-       cred_union *cu = NULL;
-       int err;
-       
-       //convert to a cred union
-       dupK52cc(context, creds, &cu);
-       
-       //remove it
-       err = cc_remove_cred(gCntrlBlock, (((stdccCacheDataPtr)(id->data))->NamedCache), *cu);
-       if (err != CC_NOERROR) return err;
-       
-       //free the temp cred union
-       err = cc_free_creds(gCntrlBlock, &cu);
-       if (err != CC_NOERROR) return err;
-
-        return CC_NOERROR;
-      }
-     
\ No newline at end of file
diff --git a/src/lib/krb5/ccache/ccapi/stdcc.h b/src/lib/krb5/ccache/ccapi/stdcc.h
deleted file mode 100644 (file)
index c157770..0000000
+++ /dev/null
@@ -1,73 +0,0 @@
-//#include "k5-int.h"
-#include "krb5.h"
-       
-#if defined(macintosh)
-#include "CCache.h"
-#endif
-
-#if defined(_MSDOS) || defined(_WIN32)
-#include "cacheapi.h"
-#endif
-
-#define kStringLiteralLen 255
-
-//globals to be exported
-extern krb5_cc_ops krb5_cc_stdcc_ops;
-
-//structure to stash in the cache's data field
-//only holds another pointer to the actual cache right now
-typedef struct _stdccCacheData {
-       ccache_p *NamedCache;
-} stdccCacheData, *stdccCacheDataPtr;
-
-
-//function protoypes complete with bogus windowsesque macros.. 
-
-KRB5_DLLIMP krb5_error_code  krb5_stdcc_close
-        KRB5_PROTOTYPE((krb5_context, krb5_ccache id ));
-
-KRB5_DLLIMP krb5_error_code  krb5_stdcc_destroy 
-        KRB5_PROTOTYPE((krb5_context, krb5_ccache id ));
-
-KRB5_DLLIMP krb5_error_code  krb5_stdcc_end_seq_get 
-        KRB5_PROTOTYPE((krb5_context, krb5_ccache id , krb5_cc_cursor *cursor ));
-
-KRB5_DLLIMP krb5_error_code  krb5_stdcc_generate_new 
-        KRB5_PROTOTYPE((krb5_context, krb5_ccache *id ));
-
-KRB5_DLLIMP char *  krb5_stdcc_get_name 
-        KRB5_PROTOTYPE((krb5_context, krb5_ccache id ));
-
-KRB5_DLLIMP krb5_error_code  krb5_stdcc_get_principal 
-        KRB5_PROTOTYPE((krb5_context, krb5_ccache id , krb5_principal *princ ));
-
-KRB5_DLLIMP krb5_error_code  krb5_stdcc_initialize 
-        KRB5_PROTOTYPE((krb5_context, krb5_ccache id , krb5_principal princ ));
-
-KRB5_DLLIMP krb5_error_code  krb5_stdcc_next_cred 
-        KRB5_PROTOTYPE((krb5_context, 
-                  krb5_ccache id , 
-                  krb5_cc_cursor *cursor , 
-                  krb5_creds *creds ));
-
-KRB5_DLLIMP krb5_error_code  krb5_stdcc_resolve 
-        KRB5_PROTOTYPE((krb5_context, krb5_ccache *id , const char *residual ));
-     
-KRB5_DLLIMP krb5_error_code  krb5_stdcc_retrieve 
-        KRB5_PROTOTYPE((krb5_context, 
-                  krb5_ccache id , 
-                  krb5_flags whichfields , 
-                  krb5_creds *mcreds , 
-                  krb5_creds *creds ));
-
-KRB5_DLLIMP krb5_error_code  krb5_stdcc_start_seq_get 
-        KRB5_PROTOTYPE((krb5_context, krb5_ccache id , krb5_cc_cursor *cursor ));
-
-KRB5_DLLIMP krb5_error_code  krb5_stdcc_store 
-        KRB5_PROTOTYPE((krb5_context, krb5_ccache id , krb5_creds *creds ));
-
-KRB5_DLLIMP krb5_error_code  krb5_stdcc_set_flags 
-        KRB5_PROTOTYPE((krb5_context, krb5_ccache id , krb5_flags flags ));
-
-KRB5_DLLIMP krb5_error_code  krb5_stdcc_remove 
-        KRB5_PROTOTYPE((krb5_context, krb5_ccache id , krb5_flags flags, krb5_creds *creds));
diff --git a/src/lib/krb5/ccache/ccapi/stdcc_util.c b/src/lib/krb5/ccache/ccapi/stdcc_util.c
deleted file mode 100644 (file)
index 4f4fcfc..0000000
+++ /dev/null
@@ -1,368 +0,0 @@
-// stdcc_util.c
-// utility functions used in implementing the ccache api for krb5
-// not publicly exported
-// Frank Dabek, July 1998
-
-#include <stdlib.h>
-#include <string.h>
-#include "stdcc_util.h"
-#include "krb5.h"
-#include "kv5m_err.h"
-
-#define fieldSize 255
-
-/* on the Mac, we need the calls which allocate memory for the Credentials Cache to use
-   Ptr's in the system help, so that they stay global and so that bad things don't happen
-   when we call DisposePtr() on them.  However, on other systems, malloc is probably the
-   right thing to use.
-   So for any place where we allocate memory for the Credentials Cache, use sys_alloc() and
-   define it accordingly.
-*/
-
-#if defined(macintosh)
-#define sys_alloc(size) NewSafePtrSys(size)
-#else
-#define sys_alloc(size) malloc(size)
-#endif
-
-#if defined(macintosh)
-//stolen from CCacheUtils.c
-// -- NewSafePtrSys -----------------
-//  - analagous to NewSafePtr but memory is allocated in the system heap
-Ptr NewSafePtrSys(long size) {
-
-       Ptr retPtr;
-       
-       retPtr = NewPtrSys(size);
-       
-       if (retPtr != NULL)
-               HoldMemory(retPtr, size);
-       
-       return retPtr;
-}
-#endif
-
-// CopyCCDataArrayToK5
-// - copy and translate the null terminated arrays of data records
-//      used in k5 tickets
-int copyCCDataArrayToK5(cc_creds *cc, krb5_creds *kc, char whichArray) {
-
-       cc_data *ccAdr, **cbase;
-       krb5_address *kAdr, **kbase, **constKBase;
-       int numRecords = 0;
-               
-       
-       if (whichArray == kAddressArray) {
-               //check pointer
-               if (cc->addresses == NULL) {
-                       kc->addresses = NULL;
-                       return 0; }
-       } else if (whichArray == kAuthDataArray) {
-               //check pointer
-               if (cc->authdata == NULL) {
-                       kc->authdata = NULL;
-                       return 0; }
-       } else return -1;
-       
-
-       cbase = (whichArray == kAddressArray) ? cc->addresses : cc->authdata;
-       //calc number of records
-       while (*cbase++ != NULL) numRecords++;
-       //allocate new array
-       constKBase = kbase = (krb5_address **)malloc((numRecords+1)*sizeof(char *));
-       //reset base
-       cbase = (whichArray == kAddressArray) ? cc->addresses : cc->authdata;
-               
-               
-       //copy records
-       while (*cbase != NULL) {
-               *kbase = (krb5_address *)malloc(sizeof(krb5_address));
-               kAdr = *kbase;
-               ccAdr = *cbase;
-               kAdr->magic = (whichArray == kAddressArray) ? KV5M_ADDRESS : KV5M_AUTHDATA;
-               kAdr->addrtype = ccAdr->type;
-               kAdr->length = ccAdr->length;
-               kAdr->contents = (krb5_octet *)malloc(kAdr->length);
-               memcpy(kAdr->contents, ccAdr->data, kAdr->length);
-               //next element please
-               kbase++; cbase++;
-       }
-       
-       //write terminator
-       *kbase = NULL;
-       if (whichArray == kAddressArray) kc->addresses = constKBase;
-       else kc->authdata = (krb5_authdata **)constKBase;
-
-       return 0;
-}
-
-// copyK5DataArrayToCC
-// - analagous to above, but in the other direction
-int copyK5DataArrayToCC(krb5_creds *kc, cc_creds *cc, char whichArray) {
-
-       cc_data *ccAdr, **cbase, **constCBase;
-       krb5_address *kAdr, **kbase;
-       int numRecords = 0;
-               
-       
-       if (whichArray == kAddressArray) {
-               //check pointer
-               if (kc->addresses == NULL) {
-                       cc->addresses = NULL;
-                       return 0; }
-       } else if (whichArray == kAuthDataArray) {
-               //check pointer
-               if (kc->authdata == NULL) {
-                       cc->authdata = NULL;
-                       return 0; }
-       } else return -1;
-       
-
-       kbase = (whichArray == kAddressArray) ? kc->addresses : (krb5_address **)kc->authdata;
-       //calc number of records
-       while (*kbase++ != NULL) numRecords++;
-       //allocate new array
-       constCBase = cbase = (cc_data **)sys_alloc((numRecords+1)*sizeof(char *));
-       //reset base
-       kbase = (whichArray == kAddressArray) ? kc->addresses : (krb5_address **)kc->authdata;
-               
-               
-       //copy records
-       while (*kbase != NULL) {
-               *cbase = (cc_data *)sys_alloc(sizeof(krb5_address));
-               kAdr = *kbase;
-               ccAdr = *cbase;
-               ccAdr->type = kAdr->addrtype;
-               ccAdr->length = kAdr->length;
-               ccAdr->data = (unsigned char *)sys_alloc(ccAdr->length);
-               memcpy(ccAdr->data, kAdr->contents, kAdr->length);
-               //next element please
-               kbase++; cbase++;
-       }
-       
-       //write terminator
-       *cbase = NULL;
-       if (whichArray == kAddressArray) cc->addresses = (cc_data **)constCBase;
-       else cc->authdata = (cc_data **)constCBase;
-
-       return 0;
-}
-
-
-// dupcctok5
-// - allocate an empty k5 style ticket and copy info from the cc_creds ticket
-void dupCCtoK5(krb5_context context, cc_creds *src, krb5_creds *dest) {
-
-       int err;
-       
-       //allocate and copy
-       //copy all of those damn fields back
-       err = krb5_parse_name(context, src->client, &(dest->client));
-       err = krb5_parse_name(context, src->server, &(dest->server));
-       if (err) return; //parsename fails w/o krb5.ini for example
-       
-       //copy keyblock
-       dest->keyblock.enctype = src->keyblock.type;
-       dest->keyblock.length = src->keyblock.length;
-       dest->keyblock.contents = (krb5_octet *)malloc(dest->keyblock.length);
-       memcpy(dest->keyblock.contents, src->keyblock.data, dest->keyblock.length);
-       
-       //copy times
-       dest->times.authtime = src->authtime;
-       dest->times.starttime = src->starttime;
-       dest->times.endtime = src->endtime;
-       dest->times.renew_till = src->renew_till;
-       dest->is_skey = src->is_skey;
-       dest->ticket_flags = src->ticket_flags;
-       
-       //more branching fields
-       copyCCDataArrayToK5(src, dest, kAddressArray);
-       dest->ticket.length = src->ticket.length;
-       dest->ticket.data = (char *)malloc(src->ticket.length);
-       memcpy(dest->ticket.data, src->ticket.data, src->ticket.length);
-       dest->second_ticket.length = src->second_ticket.length;
-       (dest->second_ticket).data = ( char *)malloc(src->second_ticket.length);
-       memcpy(dest->second_ticket.data, src->second_ticket.data, src->second_ticket.length);
-       
-       //zero out magic number
-       dest->magic = 0;
-       //later
-       //copyCCDataArrayToK5(src, dest, kAuthDataArray);
-       //krb5 docs say that authdata can be nulled out if we 
-       //only want default behavior
-       dest->authdata = NULL;
-       
-       return;
-}
-
-// dupK52CC
-// - analagous to above but in the reverse direction
-void dupK52cc(krb5_context context, krb5_creds *creds, cred_union **cu) {
-
-               krb5_address **tA;
-               krb5_authdata **tAd;
-               cc_creds *c;
-               int err;
-       #ifdef macintosh
-               char *tempname = NULL;
-       #endif
-         
-               if (cu == NULL) return;
-               
-               //allocate the cred_union
-               *cu = (cred_union *)sys_alloc(sizeof(cred_union));
-               if ((*cu) == NULL) return;
-               (*cu)->cred_type = CC_CRED_V5;
-               
-               //allocate creds structure (and install)
-               c  = (cc_creds *)sys_alloc(sizeof(cc_creds));
-               if (c == NULL) return;
-               (*cu)->cred.pV5Cred = c;
-               
-               //convert krb5 principals to flat principals
-       #ifdef macintosh
-               //and make sure the memory for c->client and c->server is on the system heap with NewPtr
-               //for the Mac (krb5_unparse_name puts it in appl heap with malloc)
-               err = krb5_unparse_name(context, creds->client, &tempname);
-               c->client = sys_alloc(strlen(tempname));
-               if (c->client != NULL)
-                       strcpy(c->client,tempname);
-               free(tempname);
-               tempname = NULL;
-               
-               err = krb5_unparse_name(context, creds->server, &tempname);
-               c->server = sys_alloc(strlen(tempname));
-               if (c->server != NULL)
-                       strcpy(c->server,tempname);
-               free(tempname);
-       #else
-               err = krb5_unparse_name(context, creds->client, &(c->client));
-               err = krb5_unparse_name(context, creds->server, &(c->server));
-       #endif
-               if (err) return;
-               
-               //copy more fields
-               c->keyblock.type = creds->keyblock.enctype;
-               c->keyblock.length = creds->keyblock.length;
-               
-               if (creds->keyblock.contents != NULL) {
-                       c->keyblock.data = (unsigned char *)sys_alloc(creds->keyblock.length);
-                       memcpy(c->keyblock.data, creds->keyblock.contents, creds->keyblock.length);
-               } else {
-                       c->keyblock.data = NULL;
-               }
-               
-               c->authtime = creds->times.authtime;
-               c->starttime = creds->times.starttime;
-               c->endtime = creds->times.endtime;
-               c->renew_till = creds->times.renew_till;
-               c->is_skey = creds->is_skey;
-               c->ticket_flags = creds->ticket_flags;
-
-               copyK5DataArrayToCC(creds, c, kAddressArray);   
-
-               c->ticket.length = creds->ticket.length;
-               if (creds->ticket.data != NULL) {
-                       c->ticket.data = (unsigned char *)sys_alloc(creds->ticket.length);
-                       memcpy(c->ticket.data, creds->ticket.data, creds->ticket.length);
-               } else {
-                       c->ticket.data = NULL;
-               }
-               
-               c->second_ticket.length = creds->second_ticket.length;
-               if (creds->second_ticket.data != NULL) {
-                       c->second_ticket.data = (unsigned char *)sys_alloc(creds->second_ticket.length);
-                       memcpy(c->second_ticket.data, creds->second_ticket.data, creds->second_ticket.length);
-               } else {
-                       c->second_ticket.data = NULL;
-               }
-               
-               c->authdata = NULL;
-       
-       return;
-}
-       
-
-// bitTst
-// - utility function for below function
-int bitTst(int var, int mask) {
-
-       return var & mask;
-} 
-
-// stdccCredsMatch
-// - check to see if the creds match based on the whichFields variable
-// NOTE: if whichfields is zero we are now comparing 'standard fields.'
-//              This is the bug that was killing fetch for a week. The behaviour
-//              is what krb5 expects, however.
-int stdccCredsMatch(krb5_context context, krb5_creds *base, krb5_creds *match, int whichfields) {
-
-       krb5_ticket_times b, m;
-       krb5_authdata **bp, **mp;
-       krb5_boolean retval;
-       krb5_principal_data p1, p2;
-       
-
-       //always check the standard fields
-       if ((krb5_principal_compare(context, base->client, match->client) &&
-           krb5_principal_compare(context, base->server, match->server)) == false)
-           return FALSE;
-
-       if (bitTst(whichfields, KRB5_TC_MATCH_TIMES)) {
-               //test for matching times
-               //according to the file cache implementation we do:
-               if (match->times.renew_till) {
-               if (match->times.renew_till > base->times.renew_till)
-                   return FALSE;               /* this one expires too late */
-           }
-           if (match->times.endtime) {
-               if (match->times.endtime > base->times.endtime)
-                   return FALSE;               /* this one expires too late */
-           }
-       } //continue search
-       
-       if (bitTst(whichfields, KRB5_TC_MATCH_IS_SKEY)) 
-               if (base->is_skey != match->is_skey) return false;
-       
-       if (bitTst(whichfields, KRB5_TC_MATCH_FLAGS)) 
-               if (base->ticket_flags != match->ticket_flags) return false;
-               
-       if (bitTst(whichfields, KRB5_TC_MATCH_TIMES_EXACT)) {
-               b = base->times; m = match->times;
-               if ((b.authtime != m.authtime) ||
-                       (b.starttime != m.starttime) ||
-                       (b.endtime != m.endtime) ||
-                       (b.renew_till != m.renew_till)) return false;
-               }
-               
-       if (bitTst(whichfields, KRB5_TC_MATCH_AUTHDATA)) {
-               bp = base->authdata;
-               mp = match->authdata;
-               if ((bp != NULL) && (mp != NULL)) {
-               while ( (bp) && (*bp != NULL) ){
-                       if (( (*bp)->ad_type != (*mp)->ad_type) ||
-                               ( (*bp)->length != (*mp)->length) ||
-                               ( memcmp( (*bp)->contents, (*mp)->contents, (*bp)->length) != 0)) return false;
-                       mp++; bp++;
-               }
-         }
-       }
-       
-       if (bitTst(whichfields, KRB5_TC_MATCH_SRV_NAMEONLY)) {
-               //taken from cc_retrv.c
-               retval = krb5_principal_compare(context, base->client,match->client);
-               if (!retval) return false;
-         
-         }
-        
-       if (bitTst(whichfields, KRB5_TC_MATCH_2ND_TKT)) 
-               if ( (base->second_ticket.length != match->second_ticket.length) ||
-                       (memcmp(base->second_ticket.data, match->second_ticket.data, base->second_ticket.length) != 0))
-                       return false;
-                       
-       if (bitTst(whichfields, KRB5_TC_MATCH_KTYPE))
-               if (base->keyblock.enctype != match->keyblock.enctype) return false;
-                       
-       //if we fall through to here, they must match
-       return true;
-}
diff --git a/src/lib/krb5/ccache/ccapi/stdcc_util.h b/src/lib/krb5/ccache/ccapi/stdcc_util.h
deleted file mode 100644 (file)
index 7d0af3d..0000000
+++ /dev/null
@@ -1,25 +0,0 @@
-//stdcc_util.h
-// 
-// Frank Dabek, July 1998
-
-#if defined(macintosh)
-#include "CCache.h"
-#endif
-
-#if defined(_MSDOS) || defined(_WIN32)
-#include "cacheapi.h"
-#endif
-
-#include "krb5.h"
-
-//protoypes for private functions declared in stdcc_util.c
-int copyCCDataArrayToK5(cc_creds *cc, krb5_creds *kc, char whichArray);
-int copyK5DataArrayToCC(krb5_creds *kc, cc_creds *cc, char whichArray);
-void dupCCtoK5(krb5_context context, cc_creds *src, krb5_creds *dest);
-void dupK52cc(krb5_context context, krb5_creds *creds, cred_union **cu);
-int stdccCredsMatch(krb5_context context, krb5_creds *base, krb5_creds *match, int whichfields);
-int bitTst(int var, int mask);
-void typeK52cc(krb5_context context, krb5_creds *creds, cc_creds *c, char **client, char **server);
-#define kAddressArray 4 
-#define kAuthDataArray 5
-
index 4570f8053cd56adbd75e5f97beb9713bb13c72d2..ae89334a0fd8bc1223fdee3c1e77634806f44e19 100644 (file)
@@ -31,7 +31,11 @@ struct krb5_cc_typelist
   krb5_cc_ops *ops;
   struct krb5_cc_typelist *next;
  };
-static struct krb5_cc_typelist *cc_typehead = 0;
+extern krb5_cc_ops krb5_mcc_ops;
+
+static struct krb5_cc_typelist cc_entry = { &krb5_mcc_ops, NULL };
+
+static struct krb5_cc_typelist *cc_typehead = &cc_entry;
 
 /*
  * Register a new credentials cache type
index 1f924319a5ab08bc354110eed4066726b5765a8d..b42fbf0cee3f725d4d046adf8aaa33a8fbae2f7e 100644 (file)
@@ -12,6 +12,7 @@ AC_CHECK_FUNCS(flock fchmod chmod strftime strptime geteuid setenv unsetenv gete
 AC_REPLACE_FUNCS(vfprintf vsprintf strdup strcasecmp strerror memmove daemon getuid sscanf syslog)
 KRB5_AC_REGEX_FUNCS
 dnl
+KRB5_SOCKADDR_SA_LEN
 KRB5_BUILD_LIBRARY_WITH_DEPS
 KRB5_BUILD_LIBOBJS
 KRB5_BUILD_PROGRAM
index d8f8533c8b150945f2ece680b532ca90de80791f..b483116e1d8933e5540daaee79e8ddabd400864a 100644 (file)
@@ -315,4 +315,6 @@ error_code KRB5_CHPW_PWDNULL,               "New password cannot be zero length"
 error_code KRB5_CHPW_FAIL,             "Password change failed"
 error_code KRB5_KT_FORMAT,             "Bad format in keytab"
 
+error_code KRB5_NOPERM_ETYPE,  "Encryption type not permitted"
+
 end
index 2120127db12e70df94f7d215dface21a0c72779a..4e575b65199d02e0f3eb397ae74f17209ab00cb0 100644 (file)
@@ -1,3 +1,8 @@
+1998-10-27  Marc Horowitz  <marc@mit.edu>
+
+       * ktf_g_ent.c (krb5_ktfile_get_entry): restructure the code to use
+       the compare_enctypes function and not leak memory
+
 Fri Feb 27 18:03:33 1998  Theodore Ts'o  <tytso@rsts-11.mit.edu>
 
        * Makefile.in: Changed thisconfigdir to point at the lib/krb5
index 7122cb41d53d0e68dac22f8541d91461818b6444..57d6edabd650f70ebccd792df7b72570051ac177 100644 (file)
@@ -41,6 +41,7 @@ krb5_ktfile_get_entry(context, id, principal, kvno, enctype, entry)
     krb5_keytab_entry cur_entry, new_entry;
     krb5_error_code kerror = 0;
     int found_wrong_kvno = 0;
+    krb5_boolean similar;
 
     /* Open the keyfile for reading */
     if ((kerror = krb5_ktfileint_openr(context, id)))
@@ -53,53 +54,69 @@ krb5_ktfile_get_entry(context, id, principal, kvno, enctype, entry)
     cur_entry.principal = 0;
     cur_entry.vno = 0;
     cur_entry.key.contents = 0;
+
     while (TRUE) {
-       krb5_enctype entry_type;
-       
        if ((kerror = krb5_ktfileint_read_entry(context, id, &new_entry)))
            break;
 
-       switch (enctype) {
-       case ENCTYPE_DES_CBC_CRC:
-       case ENCTYPE_DES_CBC_MD5:
-       case ENCTYPE_DES_CBC_MD4:
-       case ENCTYPE_DES_CBC_RAW:
-           enctype = ENCTYPE_DES_CBC_CRC;
-           break;
+       /* by the time this loop exits, it must either free cur_entry,
+          and copy new_entry there, or free new_entry.  Otherwise, it
+          leaks. */
+
+       /* if the enctype is not ignored and doesn't match, free new_entry
+          and continue to the next */
+
+       if (enctype != IGNORE_ENCTYPE) {
+           if ((kerror = krb5_c_enctype_compare(context, enctype, 
+                                                new_entry.key.enctype,
+                                                &similar))) {
+               krb5_kt_free_entry(context, &new_entry);
+               break;
+           }
+
+           if (!similar) {
+               krb5_kt_free_entry(context, &new_entry);
+               continue;
+           }
        }
 
-       entry_type = new_entry.key.enctype;
-       switch(entry_type) {
-       case ENCTYPE_DES_CBC_CRC:
-       case ENCTYPE_DES_CBC_MD5:
-       case ENCTYPE_DES_CBC_MD4:
-       case ENCTYPE_DES_CBC_RAW:
-           entry_type = ENCTYPE_DES_CBC_CRC;
-           break;
+       /* if the principal isn't the one requested, free new_entry
+          and continue to the next. */
+
+       if (!krb5_principal_compare(context, principal, new_entry.principal)) {
+           krb5_kt_free_entry(context, &new_entry);
+           continue;
        }
 
-       if (((enctype == IGNORE_ENCTYPE)||
-           (entry_type == enctype))&&
-           krb5_principal_compare(context, principal, new_entry.principal)) {
-               if (kvno == IGNORE_VNO) {
-                       if (! cur_entry.principal ||
-                           (cur_entry.vno < new_entry.vno))
-                       {
-                           krb5_kt_free_entry(context, &cur_entry);
-                           cur_entry = new_entry;
-                       }
-               } else {
-                       if (new_entry.vno == kvno) {
-                           krb5_kt_free_entry(context, &cur_entry);
-                           cur_entry = new_entry;
-                           break;
-                       } else
-                            found_wrong_kvno++;
-               }
+       if (kvno == IGNORE_VNO) {
+           /* if this is the first match, or if the new vno is
+              bigger, free the current and keep the new.  Otherwise,
+              free the new. */
+              
+           if (! cur_entry.principal ||
+               (new_entry.vno > cur_entry.vno)) {
+               krb5_kt_free_entry(context, &cur_entry);
+               cur_entry = new_entry;
+           } else {
+               krb5_kt_free_entry(context, &new_entry);
+           }
        } else {
+           /* if this kvno matches, free the current (will there ever
+              be one?), keep the new, and break out.  Otherwise, remember
+              that we were here so we can return the right error, and
+              free the new */
+
+           if (new_entry.vno == kvno) {
+               krb5_kt_free_entry(context, &cur_entry);
+               cur_entry = new_entry;
+               break;
+           } else {
+               found_wrong_kvno++;
                krb5_kt_free_entry(context, &new_entry);
+           }
        }
     }
+
     if (kerror == KRB5_KT_END) {
         if (cur_entry.principal)
              kerror = 0;
index 49d6ef3bb5b3e7a6de504f7eb76a12fb20f181a1..9d1cfb02a0e3bf6959e11fa815fe073f53d813ff 100644 (file)
@@ -1,3 +1,39 @@
+1998-10-27  Marc Horowitz  <marc@mit.edu>
+
+       * vfy_increds.c: rearrange the code a bit to make it more clear
+       that the logic is correct.
+
+       * str_conv.c: remove enctype and cksumtype string converstions.
+       They're in the crypto library now, since the information drops
+       right into the enctype table.
+
+       * ser_eblk.c: ifdef the whole file out, since it's not used
+       anywhere.  it should probably be deleted, but I'm not sure about
+       backward-compatibility issues yet.
+
+       * rd_req_dec.c: check the auth_context permit-all flag and
+       permitted_enctypes list, and reject the request if the policy
+       check fails.
+
+       * init_ctx.c: add code to initialize the prng.  It's not great,
+       but can be improved, and the prng is reseeded when new keys are
+       processed. Read permitted_enctypes from the krb5.conf file, and
+       provide accessor functions for it.  Make the various etype list
+       parsers share code as a side effect.
+
+       * get_creds.c: add krb5_get_{validat,renew}ed_creds functions,
+       which are part of the new init_creds api.  The prototypes were
+       already in, krb5.hin but there was no implementing code.
+
+       * auth_con.c, auth_con.h: add a list of permitted enctypes to the
+       auth_context for rd_req to check, and create accessor functions
+       for this list.
+
+       * Makefile.in, enc_helper.c: add enc_helper.c.  This provides a
+       wrapper around the conventional way the library encrypts and wraps
+       encoded asn.1 structures, so the code isn't repeated in a dozen
+       places.
+
 Wed Aug 19 17:27:51 1998  Tom Yu  <tlyu@mit.edu>
 
        * conv_princ.c: Add some additional entries to sconv_list that
index ec6384e0724ab818d71ea344089e340a26218063..3c734210c0572aede9f13bc677302b15a18b8e7b 100644 (file)
@@ -32,6 +32,7 @@ STLIBOBJS= \
        cp_key_cnt.o    \
        decode_kdc.o    \
        decrypt_tk.o    \
+        enc_helper.o   \
        encode_kdc.o    \
        encrypt_tk.o    \
        free_rtree.o    \
@@ -114,6 +115,7 @@ OBJS=       addr_comp.$(OBJEXT)     \
        cp_key_cnt.$(OBJEXT)    \
        decode_kdc.$(OBJEXT)    \
        decrypt_tk.$(OBJEXT)    \
+        enc_helper.$(OBJEXT)   \
        encode_kdc.$(OBJEXT)    \
        encrypt_tk.$(OBJEXT)    \
        free_rtree.$(OBJEXT)    \
@@ -197,6 +199,7 @@ SRCS=       $(srcdir)/addr_comp.c   \
        $(srcdir)/cp_key_cnt.c  \
        $(srcdir)/decode_kdc.c  \
        $(srcdir)/decrypt_tk.c  \
+       $(srcdir)/enc_helper.c  \
        $(srcdir)/encode_kdc.c  \
        $(srcdir)/encrypt_tk.c  \
        $(srcdir)/free_rtree.c  \
index 37950862359c93ac90e23b7f707b4b27baa78ba5..335f7ae7ddfc9a4acb7f03bbf0250cead20bf85e 100644 (file)
@@ -1,4 +1,3 @@
-
 #include "k5-int.h"
 #include "auth_con.h"
 
@@ -71,6 +70,8 @@ krb5_auth_con_free(context, auth_context)
        krb5_free_keyblock(context, auth_context->remote_subkey);
     if (auth_context->rcache)
        krb5_rc_close(context, auth_context->rcache);
+    if (auth_context->permitted_etypes)
+       krb5_xfree(auth_context->permitted_etypes);
     free(auth_context);
     return 0;
 }
@@ -274,12 +275,16 @@ krb5_auth_con_initivector(context, auth_context)
     krb5_context         context;
     krb5_auth_context    auth_context;
 {
+    krb5_error_code ret;
+
     if (auth_context->keyblock) {
-       int size = krb5_enctype_array[auth_context->keyblock->enctype]->
-                     system->block_length;
+       size_t blocksize;
 
-       if ((auth_context->i_vector = (krb5_pointer)malloc(size))) {
-           memset(auth_context->i_vector, 0, size);
+       if ((ret = krb5_c_block_size(context, auth_context->keyblock->enctype,
+                                   &blocksize)))
+           return(ret);
+       if ((auth_context->i_vector = (krb5_pointer)malloc(blocksize))) {
+           memset(auth_context->i_vector, 0, blocksize);
            return 0;
        }
        return ENOMEM;
@@ -347,3 +352,58 @@ krb5_auth_con_getrcache(context, auth_context, rcache)
     return 0;
 }
     
+krb5_error_code
+krb5_auth_con_setpermetypes(context, auth_context, permetypes)
+    krb5_context         context;
+    krb5_auth_context    auth_context;
+    const krb5_enctype * permetypes;
+{
+    krb5_enctype       * newpe;
+    int i;
+
+    for (i=0; permetypes[i]; i++)
+       ;
+    i++; /* include the zero */
+
+    if ((newpe = (krb5_enctype *) malloc(i*sizeof(krb5_enctype)))
+       == NULL)
+       return(ENOMEM);
+
+    if (auth_context->permitted_etypes)
+       krb5_xfree(auth_context->permitted_etypes);
+
+    auth_context->permitted_etypes = newpe;
+
+    memcpy(newpe, permetypes, i*sizeof(krb5_enctype));
+
+    return 0;
+}
+
+krb5_error_code
+krb5_auth_con_getpermetypes(context, auth_context, permetypes)
+    krb5_context         context;
+    krb5_auth_context    auth_context;
+    krb5_enctype       ** permetypes;
+{
+    krb5_enctype       * newpe;
+    int i;
+
+    if (! auth_context->permitted_etypes) {
+       *permetypes = NULL;
+       return(0);
+    }
+
+    for (i=0; auth_context->permitted_etypes[i]; i++)
+       ;
+    i++; /* include the zero */
+
+    if ((newpe = (krb5_enctype *) malloc(i*sizeof(krb5_enctype)))
+       == NULL)
+       return(ENOMEM);
+
+    *permetypes = newpe;
+
+    memcpy(newpe, auth_context->permitted_etypes, i*sizeof(krb5_enctype));
+
+    return(0);
+}
index 9d9df0e8676aef0209e632750da03822e626d3e1..e6704169ed2529af42cd610a7d6b0a1f0ecb4292 100644 (file)
@@ -20,6 +20,7 @@ struct _krb5_auth_context {
     krb5_cksumtype     safe_cksumtype;         /* mk_safe, ... */
     krb5_pointer       i_vector;               /* mk_priv, rd_priv only */
     krb5_rcache                rcache;
+    krb5_enctype      * permitted_etypes;      /* rd_req */
 };
 
 
index 71e01a81113d96dd961b457a370dc22cbf0b7a56..60c983878fe537f5a0d7ff12b1f07b54d901a0ad 100644 (file)
@@ -48,18 +48,28 @@ krb5_decode_kdc_rep(context, enc_rep, key, dec_rep)
 {
     krb5_error_code retval;
     krb5_kdc_rep *local_dec_rep;
+    krb5_keyusage usage;
 
-    if (krb5_is_as_rep(enc_rep))
+    if (krb5_is_as_rep(enc_rep)) {
+       usage = KRB5_KEYUSAGE_AS_REP_ENCPART;
        retval = decode_krb5_as_rep(enc_rep, &local_dec_rep);
-    else if (krb5_is_tgs_rep(enc_rep))
+    } else if (krb5_is_tgs_rep(enc_rep)) {
+       usage = KRB5_KEYUSAGE_TGS_REP_ENCPART_SESSKEY;
+       /* KRB5_KEYUSAGE_TGS_REP_ENCPART_SUBKEY would go here, except
+          that this client code base doesn't ever put a subkey in the
+          tgs_req authenticator, so the tgs_rep is never encrypted in
+          one.  (Check send_tgs.c:krb5_send_tgs_basic(), near the top
+          where authent.subkey is set to 0) */
        retval = decode_krb5_tgs_rep(enc_rep, &local_dec_rep);
-    else
+    } else {
        return KRB5KRB_AP_ERR_MSG_TYPE;
+    }
 
     if (retval)
        return retval;
 
-    if (retval = krb5_kdc_rep_decrypt_proc(context, key, 0, local_dec_rep)) 
+    if (retval = krb5_kdc_rep_decrypt_proc(context, key, &usage,
+                                          local_dec_rep)) 
        krb5_free_kdc_rep(context, local_dec_rep);
     else
        *dec_rep = local_dec_rep;
index 354a3f2a06761d3b697de7cf100fb677d8d5e23b..47f675591a207b7921ce69afba6e4aafddfa9ae1 100644 (file)
@@ -42,43 +42,27 @@ krb5_decrypt_tkt_part(context, srv_key, ticket)
     register krb5_ticket FAR *ticket;
 {
     krb5_enc_tkt_part *dec_tkt_part;
-    krb5_encrypt_block eblock;
     krb5_data scratch;
     krb5_error_code retval;
 
     if (!valid_enctype(ticket->enc_part.enctype))
        return KRB5_PROG_ETYPE_NOSUPP;
 
-    /* put together an eblock for this encryption */
-    krb5_use_enctype(context, &eblock, ticket->enc_part.enctype);
-
     scratch.length = ticket->enc_part.ciphertext.length;
     if (!(scratch.data = malloc(ticket->enc_part.ciphertext.length)))
        return(ENOMEM);
 
-    /* do any necessary key pre-processing */
-    if (retval = krb5_process_key(context, &eblock, srv_key)) {
-       free(scratch.data);
-       return(retval);
-    }
-
     /* call the encryption routine */
-    if (retval = krb5_decrypt(context, 
-                             (krb5_pointer) ticket->enc_part.ciphertext.data,
-                             (krb5_pointer) scratch.data, scratch.length, 
-                             &eblock, 0)) {
-       (void) krb5_finish_key(context, &eblock);
+    if (retval = krb5_c_decrypt(context, srv_key,
+                               KRB5_KEYUSAGE_KDC_REP_TICKET, 0,
+                               &ticket->enc_part, &scratch)) {
        free(scratch.data);
        return retval;
     }
+
 #define clean_scratch() {memset(scratch.data, 0, scratch.length); \
 free(scratch.data);}
-    retval = krb5_finish_key(context, &eblock);
-    if (retval) {
 
-       clean_scratch();
-       return retval;
-    }
     /*  now decode the decrypted stuff */
     retval = decode_krb5_enc_tkt_part(&scratch, &dec_tkt_part);
     if (!retval) {
diff --git a/src/lib/krb5/krb/enc_helper.c b/src/lib/krb5/krb/enc_helper.c
new file mode 100644 (file)
index 0000000..ff42149
--- /dev/null
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 1998 by the FundsXpress, INC.
+ * 
+ * All rights reserved.
+ * 
+ * Export of this software from the United States of America may require
+ * a specific license from the United States Government.  It is the
+ * responsibility of any person or organization contemplating export to
+ * obtain such a license before exporting.
+ * 
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of FundsXpress. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  FundsXpress makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#include "k5-int.h"
+
+krb5_error_code
+krb5_encrypt_helper(context, key, usage, plain, cipher)
+     krb5_context context;
+     krb5_const krb5_keyblock *key;
+     krb5_keyusage usage;
+     krb5_const krb5_data *plain;
+     krb5_enc_data *cipher;
+{
+    krb5_error_code ret;
+    size_t enclen;
+
+    if (ret = krb5_c_encrypt_length(context, key->enctype, plain->length,
+                                   &enclen))
+       return(ret);
+
+    cipher->ciphertext.length = enclen;
+    if ((cipher->ciphertext.data = (char *) malloc(enclen)) == NULL)
+       return(ret);
+
+    if (ret = krb5_c_encrypt(context, key, usage, 0, plain, cipher))
+       free(cipher->ciphertext.data);
+
+    return(ret);
+}
+       
index bb9311f6af66d21b50612d418a3c4d68b9371fe1..e20c1f5364046cc44e14a04b3be2e9c038917a58 100644 (file)
 /* due to argument promotion rules, we need to use the DECLARG/OLDDECLARG
    stuff... */
 krb5_error_code
-krb5_encode_kdc_rep(context, type, encpart, client_key, dec_rep, enc_rep)
+krb5_encode_kdc_rep(context, type, encpart, using_subkey, client_key,
+                   dec_rep, enc_rep)
     krb5_context context;
     const krb5_msgtype type;
     const krb5_enc_kdc_rep_part * encpart;
+    int using_subkey;
     const krb5_keyblock * client_key;
     krb5_kdc_rep * dec_rep;
     krb5_data ** enc_rep;
@@ -52,14 +54,20 @@ krb5_encode_kdc_rep(context, type, encpart, client_key, dec_rep, enc_rep)
     krb5_data *scratch;
     krb5_error_code retval;
     krb5_enc_kdc_rep_part tmp_encpart;
-    krb5_encrypt_block eblock;
+    krb5_keyusage usage;
 
     if (!valid_enctype(dec_rep->enc_part.enctype))
        return KRB5_PROG_ETYPE_NOSUPP;
 
     switch (type) {
     case KRB5_AS_REP:
+       usage = KRB5_KEYUSAGE_AS_REP_ENCPART;
+       break;
     case KRB5_TGS_REP:
+       if (using_subkey)
+           usage = KRB5_KEYUSAGE_TGS_REP_ENCPART_SUBKEY;
+       else
+           usage = KRB5_KEYUSAGE_TGS_REP_ENCPART_SESSKEY;
        break;
     default:
        return KRB5_BADMSGTYPE;
@@ -89,23 +97,8 @@ krb5_encode_kdc_rep(context, type, encpart, client_key, dec_rep, enc_rep)
 #define cleanup_scratch() { (void) memset(scratch->data, 0, scratch->length); \
 krb5_free_data(context, scratch); }
 
-    krb5_use_enctype(context, &eblock, client_key->enctype);
-    dec_rep->enc_part.ciphertext.length =
-       krb5_encrypt_size(scratch->length, eblock.crypto_entry);
-    /* add padding area, and zero it */
-    if (!(scratch->data = realloc(scratch->data,
-                                 dec_rep->enc_part.ciphertext.length))) {
-       /* may destroy scratch->data */
-       krb5_xfree(scratch);
-       return ENOMEM;
-    }
-    memset(scratch->data + scratch->length, 0,
-         dec_rep->enc_part.ciphertext.length - scratch->length);
-    if (!(dec_rep->enc_part.ciphertext.data =
-         malloc(dec_rep->enc_part.ciphertext.length))) {
-       retval = ENOMEM;
-       goto clean_scratch;
-    }
+    retval = krb5_encrypt_helper(context, client_key, usage, scratch,
+                                &dec_rep->enc_part);
 
 #define cleanup_encpart() { \
 (void) memset(dec_rep->enc_part.ciphertext.data, 0, \
@@ -114,30 +107,10 @@ free(dec_rep->enc_part.ciphertext.data); \
 dec_rep->enc_part.ciphertext.length = 0; \
 dec_rep->enc_part.ciphertext.data = 0;}
 
-    retval = krb5_process_key(context, &eblock, client_key);
-    if (retval) {
-       goto clean_encpart;
-    }
-
-#define cleanup_prockey() {(void) krb5_finish_key(context, &eblock);}
-
-    retval = krb5_encrypt(context, (krb5_pointer) scratch->data,
-                             (krb5_pointer) dec_rep->enc_part.ciphertext.data,
-                             scratch->length, &eblock, 0);
-    if (retval) {
-       goto clean_prockey;
-    }
-
-    dec_rep->enc_part.enctype = krb5_eblock_enctype(context, &eblock);
-
-    /* do some cleanup */
     cleanup_scratch();
 
-    retval = krb5_finish_key(context, &eblock);
-    if (retval) {
-       cleanup_encpart();
-       return retval;
-    }
+    if (retval)
+       return(retval);
 
     /* now it's ready to be encoded for the wire! */
 
@@ -149,18 +122,9 @@ dec_rep->enc_part.ciphertext.data = 0;}
        retval = encode_krb5_tgs_rep(dec_rep, enc_rep);
        break;
     }
+
     if (retval)
        cleanup_encpart();
-    return retval;
-
- clean_prockey:
-    cleanup_prockey();
- clean_encpart:
-    cleanup_encpart();
- clean_scratch:
-    cleanup_scratch();
 
     return retval;
 }
-
-
index cb1fb28b9d01c0a5381352bc6b7ada3afe8c922b..e1a1b1850e2f0726693948d3a688e6393699ba52 100644 (file)
@@ -44,7 +44,6 @@ krb5_encrypt_tkt_part(context, srv_key, dec_ticket)
     const krb5_keyblock *srv_key;
     register krb5_ticket *dec_ticket;
 {
-    krb5_encrypt_block eblock;
     krb5_data *scratch;
     krb5_error_code retval;
     register krb5_enc_tkt_part *dec_tkt_part = dec_ticket->enc_part2;
@@ -57,64 +56,12 @@ krb5_encrypt_tkt_part(context, srv_key, dec_ticket)
 #define cleanup_scratch() { (void) memset(scratch->data, 0, scratch->length); \
 krb5_free_data(context, scratch); }
 
-    krb5_use_enctype(context, &eblock, srv_key->enctype);
-
-    dec_ticket->enc_part.ciphertext.length =
-       krb5_encrypt_size(scratch->length, eblock.crypto_entry);
-    /* add padding area, and zero it */
-    if (!(scratch->data = realloc(scratch->data,
-                                 dec_ticket->enc_part.ciphertext.length))) {
-       /* may destroy scratch->data */
-       krb5_xfree(scratch);
-       return ENOMEM;
-    }
-    memset(scratch->data + scratch->length, 0,
-         dec_ticket->enc_part.ciphertext.length - scratch->length);
-    if (!(dec_ticket->enc_part.ciphertext.data =
-         malloc(dec_ticket->enc_part.ciphertext.length))) {
-       retval = ENOMEM;
-       goto clean_scratch;
-    }
-
-#define cleanup_encpart() {\
-(void) memset(dec_ticket->enc_part.ciphertext.data, 0,\
-            dec_ticket->enc_part.ciphertext.length); \
-free(dec_ticket->enc_part.ciphertext.data); \
-dec_ticket->enc_part.ciphertext.length = 0; \
-dec_ticket->enc_part.ciphertext.data = 0;}
-
-    /* do any necessary key pre-processing */
-    if ((retval = krb5_process_key(context, &eblock, srv_key))) {
-       goto clean_encpart;
-    }
-
-#define cleanup_prockey() {(void) krb5_finish_key(context, &eblock);}
-
     /* call the encryption routine */
-    if ((retval = krb5_encrypt(context, (krb5_pointer) scratch->data,
-                              (krb5_pointer) dec_ticket->enc_part.ciphertext.data,
-                              scratch->length, &eblock, 0))) {
-       goto clean_prockey;
-    }
-
-    dec_ticket->enc_part.enctype = srv_key->enctype;
-
-    /* ticket is now assembled-- do some cleanup */
-    cleanup_scratch();
-
-    if ((retval = krb5_finish_key(context, &eblock))) {
-       cleanup_encpart();
-       return retval;
-    }
-
-    return 0;
+    retval = krb5_encrypt_helper(context, srv_key,
+                                KRB5_KEYUSAGE_KDC_REP_TICKET, scratch,
+                                &dec_ticket->enc_part);
 
- clean_prockey:
-    cleanup_prockey();
- clean_encpart:
-    cleanup_encpart();
- clean_scratch:
     cleanup_scratch();
 
-    return retval;
+    return(retval);
 }
index 3694d2cd07495109c5bc5d8c69a51c8c0ec35834..4b3cd6fe6ac9e8576a3a3139c0d56d5d821c18c6 100644 (file)
@@ -38,71 +38,15 @@ krb5_generate_seq_number(context, key, seqno)
     const krb5_keyblock *key;
     krb5_int32 *seqno;
 {
-    krb5_pointer random_state;
-    krb5_encrypt_block eblock;
-    krb5_keyblock *subkey = 0;
+    krb5_data seed;
     krb5_error_code retval;
-    struct tval {
-       krb5_int32 seconds;
-       krb5_int32 microseconds;
-    } timenow;
-    krb5_octet *intmp = 0, *outtmp = 0;
-    int esize;
 
-    if (!valid_enctype(key->enctype))
-       return KRB5_PROG_ETYPE_NOSUPP;
-
-    krb5_use_enctype(context, &eblock, key->enctype);
-
-    if ((retval = krb5_init_random_key(context, &eblock, key, &random_state)))
+    seed.length = key->length;
+    seed.data = key->contents;
+    if ((retval = krb5_c_random_seed(context, &seed)))
        return(retval);
-       
-    if ((retval = krb5_random_key(context, &eblock, random_state, &subkey))) {
-       (void) krb5_finish_random_key(context, &eblock, &random_state);
-       return retval;
-    }  
-    /* ignore the error if any, since we've already gotten the key out */
-    if ((retval = krb5_finish_random_key(context, &eblock, &random_state))) {
-       krb5_free_keyblock(context, subkey);
-       return retval;
-    }
-
-    esize = krb5_encrypt_size(sizeof(timenow), eblock.crypto_entry);
-    intmp = (krb5_octet *)malloc(esize);
-    if (!intmp) {
-           retval = ENOMEM;
-           goto cleanup;
-    }
-    outtmp = (krb5_octet *)malloc(esize);
-    if (!outtmp) {
-           retval = ENOMEM;
-           goto cleanup;
-    }
-    if ((retval = krb5_process_key(context, &eblock, subkey))) {
-       goto cleanup;
-    }
 
-    if ((retval = krb5_us_timeofday(context, &timenow.seconds,
-                                   &timenow.microseconds))) {
-       goto cleanup;
-    }
-    memcpy((char *)intmp, (char *)&timenow, sizeof(timenow));
-
-    retval = krb5_encrypt(context, (krb5_pointer)intmp, (krb5_pointer)outtmp,
-                         sizeof(timenow), &eblock, 0);
-    (void) krb5_finish_key(context, &eblock);
-    if (retval)
-           goto cleanup;
-
-    memcpy((char *) seqno, (char *)outtmp, sizeof(krb5_int32));
-    
-cleanup:
-    if (subkey)
-           krb5_free_keyblock(context, subkey);
-    if (intmp)
-           krb5_xfree(intmp);
-    if (outtmp)
-           krb5_xfree(outtmp);
-    return retval;
+    seed.length = sizeof(*seqno);
+    seed.data = (char *) seqno;
+    return(krb5_c_random_make_octets(context, &seed));
 }
-
index 89e21a1b79a236468dc272c09104c6504532cda3..861d61e722c2988669f2654401d4a70ab9c56fe9 100644 (file)
@@ -32,24 +32,21 @@ krb5_generate_subkey(context, key, subkey)
     const krb5_keyblock *key;
     krb5_keyblock **subkey;
 {
-    krb5_pointer random_state;
-    krb5_encrypt_block eblock;
     krb5_error_code retval;
+    krb5_data seed;
 
-    if (!valid_enctype(key->enctype))
-       return KRB5_PROG_ETYPE_NOSUPP;
+    seed.length = key->length;
+    seed.data = key->contents;
+    if ((retval = krb5_c_random_seed(context, &seed)))
+       return(retval);
 
-    krb5_use_enctype(context, &eblock, key->enctype);
+    if ((*subkey = (krb5_keyblock *) malloc(sizeof(krb5_keyblock))) == NULL)
+       return(ENOMEM);
 
-    if ((retval = krb5_init_random_key(context, &eblock, key, &random_state)))
-       return(retval);
-    if ((retval = krb5_random_key(context, &eblock, random_state, subkey))) {
-       (void) krb5_finish_random_key(context, &eblock, &random_state);
+    if ((retval = krb5_c_make_random_key(context, key->enctype, *subkey))) {
        krb5_xfree(*subkey);
-       return retval;
-    }  
-    /* ignore the error if any, since we've already gotten the key out */
-    (void) krb5_finish_random_key(context, &eblock, &random_state);
-    return 0;
-}
+       return(retval);
+    }
 
+    return(0);
+}
index 3a1ec526b7482228fbadacf126aa46684d2cd6dc..37f2bb5a93fafd08fc2f7d959a9d6b0b7584da86 100644 (file)
@@ -160,12 +160,6 @@ krb5_get_credentials_val_renew_core(context, options, ccache,
     krb5_creds **tgts = 0;
     krb5_flags fields;
 
-    retval = krb5_get_credentials_core(context, options, ccache, 
-                                      in_creds, out_creds, 
-                                      &mcreds, &fields);
-
-    if (retval) return retval;
-
     switch(which) {
     case INT_GC_VALIDATE:
            retval = krb5_get_cred_from_kdc_validate(context, ccache, 
@@ -219,3 +213,104 @@ krb5_get_credentials_renew(context, options, ccache, in_creds, out_creds)
                                               in_creds, out_creds, 
                                               INT_GC_RENEW));
 }
+
+static krb5_error_code
+krb5_validate_or_renew_creds(context, creds, client, ccache, in_tkt_service,
+                            validate)
+     krb5_context context;
+     krb5_creds *creds;
+     krb5_principal client;
+     krb5_ccache ccache;
+     char *in_tkt_service;
+     int validate;
+{
+    krb5_error_code ret;
+    krb5_creds in_creds; /* only client and server need to be filled in */
+    krb5_creds *out_creds;
+    krb5_creds **tgts;
+
+    memset((char *)&in_creds, 0, sizeof(krb5_creds));
+
+    in_creds.server = NULL;
+    tgts = NULL;
+
+    in_creds.client = client;
+
+    if (in_tkt_service) {
+       /* this is ugly, because so are the data structures involved.  I'm
+          in the library, so I'm going to manipulate the data structures
+          directly, otherwise, it will be worse. */
+
+       if (ret = krb5_parse_name(context, in_tkt_service, &in_creds.server))
+           goto cleanup;
+
+       /* stuff the client realm into the server principal.
+          realloc if necessary */
+       if (in_creds.server->realm.length < in_creds.client->realm.length)
+           if ((in_creds.server->realm.data =
+                (char *) realloc(in_creds.server->realm.data,
+                                 in_creds.client->realm.length)) == NULL) {
+               ret = ENOMEM;
+               goto cleanup;
+           }
+
+       in_creds.server->realm.length = in_creds.client->realm.length;
+       memcpy(in_creds.server->realm.data, in_creds.client->realm.data,
+              in_creds.client->realm.length);
+    } else {
+       if (ret = krb5_build_principal_ext(context, &in_creds.server,
+                                          in_creds.client->realm.length,
+                                          in_creds.client->realm.data,
+                                          KRB5_TGS_NAME_SIZE,
+                                          KRB5_TGS_NAME,
+                                          in_creds.client->realm.length,
+                                          in_creds.client->realm.data,
+                                          0))
+           goto cleanup;
+    }
+
+    if (validate)
+       ret = krb5_get_cred_from_kdc_validate(context, ccache, 
+                                             &in_creds, &out_creds, &tgts);
+    else
+       ret = krb5_get_cred_from_kdc_renew(context, ccache, 
+                                          &in_creds, &out_creds, &tgts);
+   
+    /* ick.  copy the struct contents, free the container */
+
+    *creds = *out_creds;
+    krb5_xfree(out_creds);
+
+cleanup:
+
+    if (in_creds.server)
+       krb5_free_principal(context, in_creds.server);
+    if (tgts)
+       krb5_free_tgt_creds(context, tgts);
+
+    return(ret);
+}
+
+KRB5_DLLIMP krb5_error_code KRB5_CALLCONV
+krb5_get_validated_creds(context, creds, client, ccache, in_tkt_service)
+     krb5_context context;
+     krb5_creds *creds;
+     krb5_principal client;
+     krb5_ccache ccache;
+     char *in_tkt_service;
+{
+    return(krb5_validate_or_renew_creds(context, creds, client, ccache,
+                                       in_tkt_service, 1));
+}
+
+KRB5_DLLIMP krb5_error_code KRB5_CALLCONV
+krb5_get_renewed_creds(context, creds, client, ccache, in_tkt_service)
+     krb5_context context;
+     krb5_creds *creds;
+     krb5_principal client;
+     krb5_ccache ccache;
+     char *in_tkt_service;
+{
+    return(krb5_validate_or_renew_creds(context, creds, client, ccache,
+                                       in_tkt_service, 0));
+}
index 45a076246f82155d60f1ced199bee58c9aa25843..c517062f8648d826afe9814c4b4cc9aa01eea095 100644 (file)
@@ -16,7 +16,6 @@ krb5_get_as_key_password(context, client, etype, prompter, prompter_data,
     krb5_data *password;
     krb5_error_code ret;
     krb5_data defsalt;
-    krb5_encrypt_block eblock;
     char *clientstr;
     char promptstr[1024];
     krb5_prompt prompt;
@@ -35,11 +34,6 @@ krb5_get_as_key_password(context, client, etype, prompter, prompter_data,
        as_key->length = 0;
     }
 
-    if (!valid_enctype(etype))
-       return(KRB5_PROG_ETYPE_NOSUPP);
-
-    krb5_use_enctype(context, &eblock, etype);
-
     if (password->data[0] == '\0') {
        if (prompter == NULL)
            return(EIO);
@@ -70,7 +64,7 @@ krb5_get_as_key_password(context, client, etype, prompter, prompter_data,
        defsalt.length = 0;
     }
 
-    ret = krb5_string_to_key(context, &eblock, as_key, password, salt);
+    ret = krb5_c_string_to_key(context, etype, password, salt, as_key);
 
     if (defsalt.length)
        krb5_xfree(defsalt.data);
index 7373f62f19dd72d322e131f094d670bdca760fd3..e03883e9d77445615dfd5c7c647834ecc2b72248 100644 (file)
@@ -47,15 +47,9 @@ pwd_keyproc(context, type, salt, keyseed, key)
     krb5_keyblock ** key;
 {
     krb5_error_code retval;
-    krb5_encrypt_block eblock;
     krb5_data * password;
     int pwsize;
 
-    if (!valid_enctype(type))
-       return KRB5_PROG_ETYPE_NOSUPP;
-
-    krb5_use_enctype(context, &eblock, type);
-    
     password = (krb5_data *)keyseed;
 
     if (!password->length) {
@@ -73,8 +67,9 @@ pwd_keyproc(context, type, salt, keyseed, key)
     if (!(*key = (krb5_keyblock *)malloc(sizeof(**key))))
        return ENOMEM;
 
-    if ((retval = krb5_string_to_key(context, &eblock, *key, password, salt)))
+    if ((retval = krb5_c_string_to_key(context, type, password, salt, *key)))
        krb5_xfree(*key);
+
     return(retval);
 }
 
index daa9fd95f8184fdd2c2ce9905697bee7ccce99c5..2285b0f4213c8d18ecf5f4a8a6c875ffea6c3e52 100644 (file)
  * krb5_init_contex()
  */
 
+/*
+ * Copyright (C) 1998 by the FundsXpress, INC.
+ * 
+ * All rights reserved.
+ * 
+ * Export of this software from the United States of America may require
+ * a specific license from the United States Government.  It is the
+ * responsibility of any person or organization contemplating export to
+ * obtain such a license before exporting.
+ * 
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of FundsXpress. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  FundsXpress makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
 #include "k5-int.h"
 #include <ctype.h>
 #include "brand.c"
@@ -37,6 +63,8 @@ krb5_init_context(context)
 {
        krb5_context ctx = 0;
        krb5_error_code retval;
+       krb5_timestamp now;
+       krb5_data seed;
        int tmp;
 
        /* Initialize error tables */
@@ -70,6 +98,14 @@ krb5_init_context(context)
        if ((retval = krb5_os_init_context(ctx)))
                goto cleanup;
 
+       /* initialize the prng (not well, but passable) */
+       if ((retval = krb5_timeofday(ctx, &now)))
+               goto cleanup;
+       seed.length = sizeof(now);
+       seed.data = (char *) &now;
+       if ((retval = krb5_c_random_seed(ctx, &seed)))
+               goto cleanup;
+
        ctx->default_realm = 0;
        profile_get_integer(ctx->profile, "libdefaults", "clockskew",
                            0, 5 * 60, &tmp);
@@ -197,26 +233,27 @@ krb5_set_default_in_tkt_ktypes(context, ktypes)
     return 0;
 }
 
-krb5_error_code
-krb5_get_default_in_tkt_ktypes(context, ktypes)
-    krb5_context context;
-    krb5_enctype **ktypes;
+static krb5_error_code
+get_profile_etype_list(context, ktypes, profstr, ctx_count, ctx_list)
+     krb5_context context;
+     krb5_enctype **ktypes;
+     char *profstr;
+     int ctx_count;
+     krb5_enctype FAR *ctx_list;
 {
-    krb5_enctype * old_ktypes;
+    krb5_enctype *old_ktypes;
 
     if (context->in_tkt_ktype_count) {
-      /* application-set defaults */
-      if ((old_ktypes = 
-          (krb5_enctype *)malloc(sizeof(krb5_enctype) *
-                                 (context->in_tkt_ktype_count + 1)))) {
-       memcpy(old_ktypes, context->in_tkt_ktypes, sizeof(krb5_enctype) * 
-              context->in_tkt_ktype_count);
-       old_ktypes[context->in_tkt_ktype_count] = 0;
-      } else {
-       return ENOMEM;
-      }
+       /* application-set defaults */
+       if ((old_ktypes = 
+            (krb5_enctype *)malloc(sizeof(krb5_enctype) *
+                                   (ctx_count + 1)))) {
+           memcpy(old_ktypes, ctx_list, sizeof(krb5_enctype) * ctx_count);
+           old_ktypes[ctx_count] = 0;
+       } else {
+           return ENOMEM;
+       }
     } else {
-       /* taken directly from krb5_get_tgs_ktypes... */
         /*
           XXX - For now, we only support libdefaults
           Perhaps this should be extended to allow for per-host / per-realm
@@ -228,9 +265,9 @@ krb5_get_default_in_tkt_ktypes(context, ktypes)
        int i, j, count;
        krb5_error_code code;
 
-       code = profile_get_string(context->profile,
-                                 "libdefaults", "default_tkt_enctypes", NULL,
-                                 "des-cbc-md5 des-cbc-crc",
+       code = profile_get_string(context->profile, "libdefaults", profstr,
+                                 NULL,
+                                 "des3-hmac-sha1 des-cbc-md5 des-cbc-crc",
                                  &retval);
        if (code)
            return code;
@@ -279,6 +316,16 @@ krb5_get_default_in_tkt_ktypes(context, ktypes)
     return 0;
 }
 
+krb5_error_code
+krb5_get_default_in_tkt_ktypes(context, ktypes)
+    krb5_context context;
+    krb5_enctype **ktypes;
+{
+    return(get_profile_etype_list(context, ktypes, "default_tkt_enctypes",
+                                 context->in_tkt_ktype_count,
+                                 context->in_tkt_ktypes));
+}
+
 krb5_error_code
 krb5_set_default_tgs_ktypes(context, ktypes)
        krb5_context context;
@@ -317,80 +364,40 @@ krb5_get_tgs_ktypes(context, princ, ktypes)
     krb5_const_principal princ;
     krb5_enctype **ktypes;
 {
-    krb5_enctype * old_ktypes;
-
-    if (context->tgs_ktype_count) {
-
-       /* Application-set defaults */
-
-       if ((old_ktypes =
-            (krb5_enctype *)malloc(sizeof(krb5_enctype) *
-                                   (context->tgs_ktype_count + 1)))) {
-           memcpy(old_ktypes, context->tgs_ktypes, sizeof(krb5_enctype) * 
-                  context->tgs_ktype_count);
-           old_ktypes[context->tgs_ktype_count] = 0;
-       } else {
-           return ENOMEM;
-       }
-    } else {
-       /*
-          XXX - For now, we only support libdefaults
-          Perhaps this should be extended to allow for per-host / per-realm
-          session key types.
-        */
-
-       char *retval;
-       char *sp, *ep;
-       int i, j, count;
-       krb5_error_code code;
+    return(get_profile_etype_list(context, ktypes, "default_tgs_enctypes",
+                                 context->tgs_ktype_count,
+                                 context->tgs_ktypes));
+}
 
-       code = profile_get_string(context->profile,
-                                 "libdefaults", "default_tgs_enctypes", NULL,
-                                 "des-cbc-md5 des-cbc-crc",
-                                 &retval);
-       if (code)
-           return code;
+krb5_error_code
+krb5_get_permitted_enctypes(context, ktypes)
+    krb5_context context;
+    krb5_enctype **ktypes;
+{
+    return(get_profile_etype_list(context, ktypes, "permitted_enctypes",
+                                 context->tgs_ktype_count,
+                                 context->tgs_ktypes));
+}
 
-       count = 0;
-       sp = retval;
-       while (sp) {
-           for (ep = sp; *ep && (*ep != ',') && !isspace(*ep); ep++)
-               ;
-           if (*ep) {
-               *ep++ = '\0';
-               while (isspace(*ep))
-                   ep++;
-           } else
-               ep = (char *) NULL;
+krb5_boolean
+krb5_is_permitted_enctype(context, etype)
+     krb5_context context;
+     krb5_enctype etype;
+{
+    krb5_enctype *list, *ptr;
+    krb5_boolean ret;
 
-           count++;
-           sp = ep;
-       }
-       
-       if ((old_ktypes =
-            (krb5_enctype *)malloc(sizeof(krb5_enctype) * (count + 1))) ==
-           (krb5_enctype *) NULL)
-           return ENOMEM;
-       
-       sp = retval;
-       j = 0;
-       i = 1;
-       while (1) {
-           if (! krb5_string_to_enctype(sp, &old_ktypes[j]))
-               j++;
+    if (krb5_get_permitted_enctypes(context, &list))
+       return(0);
 
-           if (i++ >= count)
-               break;
+    
+    ret = 0;
 
-           /* skip to next token */
-           while (*sp) sp++;
-           while (! *sp) sp++;
-       }
+    for (ptr = list; *ptr; ptr++)
+       if (*ptr == etype)
+           ret = 1;
 
-       old_ktypes[j] = (krb5_enctype) 0;
-       free(retval);
-    }
+    krb5_xfree(list);
 
-    *ktypes = old_ktypes;
-    return 0;
+    return(ret);
 }
index e9431aef94c4d8c2926d1d7ee2d0fef837edbc3a..a9cbcf39bb36d4a1fbed007e84452d54b5a6ab5f 100644 (file)
@@ -41,12 +41,15 @@ krb5_kdc_rep_decrypt_proc(context, key, decryptarg, dec_rep)
     krb5_kdc_rep * dec_rep;
 {
     krb5_error_code retval;
-    krb5_encrypt_block eblock;
     krb5_data scratch;
     krb5_enc_kdc_rep_part *local_encpart;
+    krb5_keyusage usage;
 
-    if (!valid_enctype(dec_rep->enc_part.enctype))
-       return KRB5_PROG_ETYPE_NOSUPP;
+    if (decryptarg) {
+       usage = *(const krb5_keyusage *) decryptarg;
+    } else {
+       usage = KRB5_KEYUSAGE_AS_REP_ENCPART;
+    }
 
     /* set up scratch decrypt/decode area */
 
@@ -55,30 +58,16 @@ krb5_kdc_rep_decrypt_proc(context, key, decryptarg, dec_rep)
        return(ENOMEM);
     }
 
-    /* put together an eblock for this encryption */
-
-    krb5_use_enctype(context, &eblock, dec_rep->enc_part.enctype);
+    dec_rep->enc_part.enctype;
 
-    /* do any necessary key pre-processing */
-    if ((retval = krb5_process_key(context, &eblock, key))) {
+    if ((retval = krb5_c_decrypt(context, key, usage, 0, &dec_rep->enc_part,
+                                &scratch))) {
        free(scratch.data);
        return(retval);
     }
 
-    /* call the decryption routine */
-    if ((retval = krb5_decrypt(context, (krb5_pointer) dec_rep->enc_part.ciphertext.data,
-                              (krb5_pointer) scratch.data,
-                              scratch.length, &eblock, 0))) {
-       (void) krb5_finish_key(context, &eblock);
-       free(scratch.data);
-       return retval;
-    }
 #define clean_scratch() {memset(scratch.data, 0, scratch.length); \
 free(scratch.data);}
-    if ((retval = krb5_finish_key(context, &eblock))) {
-       clean_scratch();
-       return retval;
-    }
 
     /* and do the decode */
     retval = decode_krb5_enc_kdc_rep_part(&scratch, &local_encpart);
index 17c4f8c7f7155f52e0785c2508ecfee5baadc5ab..87eeca961953a4e04da5e3ae1f711ad2a256c269 100644 (file)
@@ -148,6 +148,16 @@ krb5_free_checksum(context, val)
     return;
 }
 
+KRB5_DLLIMP void KRB5_CALLCONV
+krb5_free_checksum_contents(context, val)
+    krb5_context context;
+    register krb5_checksum *val;
+{
+    if (val->contents)
+       krb5_xfree(val->contents);
+    return;
+}
+
 KRB5_DLLIMP void KRB5_CALLCONV
 krb5_free_cred(context, val)
     krb5_context context;
@@ -572,3 +582,4 @@ krb5_free_unparsed_name(context, val)
        krb5_xfree(val);
     return;
 }
+
index 23545fb612b224c26417906d1841b35e9c991d9a..cdda80d062cd2eaf9a0e3d80f04e76fd9c29aeb2 100644 (file)
@@ -28,12 +28,8 @@ encrypt_credencpart(context, pcredpart, pkeyblock, pencdata)
     krb5_enc_data      * pencdata;
 {
     krb5_error_code      retval;
-    krb5_encrypt_block           eblock;
     krb5_data          * scratch;
 
-    if (pkeyblock && !valid_enctype(pkeyblock->enctype))
-       return KRB5_PROG_ETYPE_NOSUPP;
-
     /* start by encoding to-be-encrypted part of the message */
     if ((retval = encode_krb5_enc_cred_part(pcredpart, &scratch)))
        return retval;
@@ -49,47 +45,11 @@ encrypt_credencpart(context, pcredpart, pkeyblock, pencdata)
            return 0;
     }
 
-    /* put together an eblock for this encryption */
-
-    pencdata->kvno = 0;
-    pencdata->enctype = pkeyblock->enctype;
-
-    krb5_use_enctype(context, &eblock, pkeyblock->enctype);
-    pencdata->ciphertext.length = krb5_encrypt_size(scratch->length, 
-                                                   eblock.crypto_entry);
-
-    /* add padding area, and zero it */
-    if (!(scratch->data = (char *)realloc(scratch->data,
-                                          pencdata->ciphertext.length))) {
-       /* may destroy scratch->data */
-       krb5_xfree(scratch);
-       return ENOMEM;
-    }
-
-    memset(scratch->data + scratch->length, 0,
-           pencdata->ciphertext.length - scratch->length);
-    if (!(pencdata->ciphertext.data =
-          (char *)malloc(pencdata->ciphertext.length))) {
-       retval = ENOMEM;
-       goto clean_scratch;
-    }
-
-    /* do any necessary key pre-processing */
-    if ((retval = krb5_process_key(context, &eblock, pkeyblock))) {
-       goto clean_encpart;
-    }
-
     /* call the encryption routine */
-    if ((retval = krb5_encrypt(context, (krb5_pointer)scratch->data,
-                              (krb5_pointer)pencdata->ciphertext.data, 
-                              scratch->length, &eblock, 0))) {
-       krb5_finish_key(context, &eblock);
-       goto clean_encpart;
-    }
-    
-    retval = krb5_finish_key(context, &eblock);
+    retval = krb5_encrypt_helper(context, pkeyblock,
+                                KRB5_KEYUSAGE_KRB_CRED_ENCPART,
+                                scratch, pencdata);
 
-clean_encpart:
     if (retval) {
        memset(pencdata->ciphertext.data, 0, pencdata->ciphertext.length);
         free(pencdata->ciphertext.data);
@@ -97,7 +57,6 @@ clean_encpart:
         pencdata->ciphertext.data = 0;
     }
 
-clean_scratch:
     memset(scratch->data, 0, scratch->length); 
     krb5_free_data(context, scratch);
 
index 7986e185620bfd05a0b50664697528f0c14e2ead..2e7f2ce255b1a9bafa3e4317273459896607d90e 100644 (file)
@@ -41,13 +41,10 @@ krb5_mk_priv_basic(context, userdata, keyblock, replaydata, local_addr,
     krb5_data          * outbuf; 
 {
     krb5_error_code    retval;
-    krb5_encrypt_block         eblock;
     krb5_priv          privmsg;
     krb5_priv_enc_part         privmsg_enc_part;
-    krb5_data          *scratch1, *scratch2;
-
-    if (!valid_enctype(keyblock->enctype))
-       return KRB5_PROG_ETYPE_NOSUPP;
+    krb5_data          *scratch1, *scratch2, ivdata;
+    size_t             blocksize, enclen;
 
     privmsg.enc_part.kvno = 0; /* XXX allow user-set? */
     privmsg.enc_part.enctype = keyblock->enctype; 
@@ -66,52 +63,42 @@ krb5_mk_priv_basic(context, userdata, keyblock, replaydata, local_addr,
        return retval;
 
     /* put together an eblock for this encryption */
-    krb5_use_enctype(context, &eblock, keyblock->enctype);
-    privmsg.enc_part.ciphertext.length = krb5_encrypt_size(scratch1->length,
-                                               eblock.crypto_entry);
-    /* add padding area, and zero it */
-    if (!(scratch1->data = realloc(scratch1->data,
-                                 privmsg.enc_part.ciphertext.length))) {
-       /* may destroy scratch1->data */
-       krb5_xfree(scratch1);
-       return ENOMEM;
-    }
+    if ((retval = krb5_c_encrypt_length(context, keyblock->enctype,
+                                       scratch1->length, &enclen)))
+       goto clean_scratch;
 
-    memset(scratch1->data + scratch1->length, 0,
-         privmsg.enc_part.ciphertext.length - scratch1->length);
+    privmsg.enc_part.ciphertext.length = enclen;
     if (!(privmsg.enc_part.ciphertext.data =
          malloc(privmsg.enc_part.ciphertext.length))) {
         retval = ENOMEM;
         goto clean_scratch;
     }
 
-    /* do any necessary key pre-processing */
-    if ((retval = krb5_process_key(context, &eblock, keyblock)))
-        goto clean_encpart;
-
     /* call the encryption routine */
-    if ((retval = krb5_encrypt(context, (krb5_pointer) scratch1->data,
-                              (krb5_pointer) privmsg.enc_part.ciphertext.data,
-                              scratch1->length, &eblock, i_vector))) {
-       krb5_finish_key(context, &eblock);
-        goto clean_encpart;
+    if (i_vector) {
+       if ((retval = krb5_c_block_size(context, keyblock->enctype,
+                                       &blocksize)))
+           goto clean_encpart;
+
+       ivdata.length = blocksize;
+       ivdata.data = i_vector;
     }
 
+    if ((retval = krb5_c_encrypt(context, keyblock,
+                                KRB5_KEYUSAGE_KRB_PRIV_ENCPART,
+                                i_vector?&ivdata:0,
+                                scratch1, &privmsg.enc_part)))
+       goto clean_encpart;
+
     /* put last block into the i_vector */
+
     if (i_vector)
        memcpy(i_vector,
               privmsg.enc_part.ciphertext.data +
-              (privmsg.enc_part.ciphertext.length -
-               eblock.crypto_entry->block_length),
-              eblock.crypto_entry->block_length);
+              (privmsg.enc_part.ciphertext.length - blocksize),
+              blocksize);
           
-    if ((retval = encode_krb5_priv(&privmsg, &scratch2)))  {
-       krb5_finish_key(context, &eblock);
-        goto clean_encpart;
-    }
-
-    /* encode private message */
-    if ((retval = krb5_finish_key(context, &eblock)))
+    if ((retval = encode_krb5_priv(&privmsg, &scratch2)))
         goto clean_encpart;
 
     *outbuf = *scratch2;
index 45784284c31ede38755dee407593bb42a673b0fc..f0398475f5d7b6cfa4bf58b0fb361caec76b829b 100644 (file)
@@ -45,14 +45,11 @@ krb5_mk_rep(context, auth_context, outbuf)
     krb5_error_code      retval;
     krb5_enctype         enctype;
     krb5_ap_rep_enc_part  repl;
-    krb5_encrypt_block           eblock;
     krb5_ap_rep          reply;
     krb5_data          * scratch;
     krb5_data          * toutbuf;
 
-    /* verify a valid enctype is available */
-    if (!valid_enctype(enctype = auth_context->keyblock->enctype))
-       return KRB5_PROG_ETYPE_NOSUPP;
+    enctype = auth_context->keyblock->enctype;
 
     /* Make the reply */
     if (((auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_DO_SEQUENCE) ||
@@ -72,49 +69,16 @@ krb5_mk_rep(context, auth_context, outbuf)
     if ((retval = encode_krb5_ap_rep_enc_part(&repl, &scratch)))
        return retval;
 
-    /* put together an eblock for this encryption */
-    krb5_use_enctype(context, &eblock, enctype);
-    reply.enc_part.enctype = enctype;
-    reply.enc_part.kvno = 0;           /* XXX user set? */
-
-    reply.enc_part.ciphertext.length = krb5_encrypt_size(scratch->length,
-                                                        eblock.crypto_entry);
-    /* add padding area, and zero it */
-    if (!(scratch->data = realloc(scratch->data,
-                                 reply.enc_part.ciphertext.length))) {
-       /* may destroy scratch->data */
-       krb5_xfree(scratch);
-       return ENOMEM;
-    }
-    memset(scratch->data + scratch->length, 0,
-         reply.enc_part.ciphertext.length - scratch->length);
-    if (!(reply.enc_part.ciphertext.data =
-         malloc(reply.enc_part.ciphertext.length))) {
-       retval = ENOMEM;
+    if ((retval = krb5_encrypt_helper(context, auth_context->keyblock,
+                                     KRB5_KEYUSAGE_AP_REP_ENCPART,
+                                     scratch, &reply.enc_part)))
        goto cleanup_scratch;
-    }
-
-    /* do any necessary key pre-processing */
-    if ((retval = krb5_process_key(context, &eblock, auth_context->keyblock)))
-       goto cleanup_encpart;
-
-    /* call the encryption routine */
-    if ((retval = krb5_encrypt(context, (krb5_pointer) scratch->data,
-                              (krb5_pointer) reply.enc_part.ciphertext.data,
-                              scratch->length, &eblock, 0))) {
-       krb5_finish_key(context, &eblock);
-       goto cleanup_encpart;
-    }
-
-    if ((retval = krb5_finish_key(context, &eblock)))
-       goto cleanup_encpart;
 
     if (!(retval = encode_krb5_ap_rep(&reply, &toutbuf))) {
        *outbuf = *toutbuf;
        krb5_xfree(toutbuf);
     }
 
-cleanup_encpart:
     memset(reply.enc_part.ciphertext.data, 0, reply.enc_part.ciphertext.length);
     free(reply.enc_part.ciphertext.data); 
     reply.enc_part.ciphertext.length = 0; 
index 726bb434b03a02eef49b4bf2d350dba7553f5f5d..1530f79616e910ccb13d2abf2094eecb2eef116e 100644 (file)
@@ -84,7 +84,6 @@ krb5_mk_req_extended(context, auth_context, ap_req_options, in_data, in_creds,
 
     krb5_ap_req request;
     krb5_data *scratch = 0;
-    krb5_encrypt_block eblock;
     krb5_data *toutbuf;
 
     request.ap_options = ap_req_options & AP_OPTS_WIRE_MASK;
@@ -98,12 +97,6 @@ krb5_mk_req_extended(context, auth_context, ap_req_options, in_data, in_creds,
     if ((retval = decode_krb5_ticket(&(in_creds)->ticket, &request.ticket)))
        return(retval);
     
-    /* verify a valid enctype is available */
-    if (!valid_enctype(in_creds->keyblock.enctype)) {
-       retval = KRB5_PROG_ETYPE_NOSUPP;
-       goto cleanup;
-    }
-
     /* verify that the ticket is not expired */
     if ((retval = krb5_validate_times(context, &in_creds->times)) != 0)
        goto cleanup;
@@ -135,27 +128,18 @@ krb5_mk_req_extended(context, auth_context, ap_req_options, in_data, in_creds,
                                           &(*auth_context)->local_subkey)))
            goto cleanup;
 
-
     if (in_data) {
        if ((*auth_context)->req_cksumtype == 0x8003) {
            /* XXX Special hack for GSSAPI */
            checksum.checksum_type = 0x8003;
            checksum.length = in_data->length;
            checksum.contents = (krb5_octet *) in_data->data;
-       } else  {
-           /* Generate checksum, XXX What should the seed be? */
-           checksum.length =
-               krb5_checksum_size(context, (*auth_context)->req_cksumtype);
-           if ((checksum.contents = (krb5_octet *)malloc(checksum.length)) == NULL) {
-               retval = ENOMEM;
-               goto cleanup;
-           }
-           if ((retval = krb5_calculate_checksum(context, 
-                                       (*auth_context)->req_cksumtype, 
-                                       in_data->data, in_data->length,
-                                       (*auth_context)->keyblock->contents,
-                                       (*auth_context)->keyblock->length,
-                                       &checksum)))
+       } else {
+           if ((retval = krb5_c_make_checksum(context, 
+                                              (*auth_context)->req_cksumtype,
+                                              (*auth_context)->keyblock,
+                                              KRB5_KEYUSAGE_AP_REQ_AUTH_CKSUM,
+                                              in_data, &checksum)))
                goto cleanup_cksum;
        }
        checksump = &checksum;
@@ -188,43 +172,12 @@ krb5_mk_req_extended(context, auth_context, ap_req_options, in_data, in_creds,
     (*auth_context)->authentp->checksum = NULL;
     (*auth_context)->authentp->authorization_data = NULL;
 
-    /* put together an eblock for this encryption */
-
-    krb5_use_enctype(context, &eblock, in_creds->keyblock.enctype);
-    request.authenticator.enctype = in_creds->keyblock.enctype;
-    request.authenticator.kvno = 0;
-    request.authenticator.ciphertext.length =
-       krb5_encrypt_size(scratch->length, eblock.crypto_entry);
-    /* add padding area, and zero it */
-    if (!(scratch->data = realloc(scratch->data,
-                                 request.authenticator.ciphertext.length))) {
-       /* may destroy scratch->data */
-       retval = ENOMEM;
-       goto cleanup_cksum;
-    }
-    memset(scratch->data + scratch->length, 0,
-         request.authenticator.ciphertext.length - scratch->length);
-    if (!(request.authenticator.ciphertext.data =
-         malloc(request.authenticator.ciphertext.length))) {
-       retval = ENOMEM;
-       goto cleanup_cksum;
-    }
-
-    /* do any necessary key pre-processing */
-    if ((retval = krb5_process_key(context, &eblock, &(in_creds)->keyblock)))
-       goto cleanup;
-
     /* call the encryption routine */
-    if ((retval = krb5_encrypt(context, (krb5_pointer) scratch->data,
-                              (krb5_pointer) request.authenticator.ciphertext.data,
-                              scratch->length, &eblock, 0))) {
-        krb5_finish_key(context, &eblock);
+    if ((retval = krb5_encrypt_helper(context, &in_creds->keyblock,
+                                     KRB5_KEYUSAGE_AP_REQ_AUTH,
+                                     scratch, &request.authenticator)))
        goto cleanup_cksum;
-    }
 
-    if ((retval = krb5_finish_key(context, &eblock)))
-       goto cleanup_cksum;
-    
     if ((retval = encode_krb5_ap_req(&request, &toutbuf)))
        goto cleanup_cksum;
 #ifdef HAVE_C_STRUCTURE_ASSIGNMENT
index 1a44a75e5987b3849e8fc2f0b0934a6875249bcc..0d5a4908045fb7bf718b23dd1a8167ac57cbb6d6 100644 (file)
@@ -90,18 +90,11 @@ krb5_mk_safe_basic(context, userdata, keyblock, replaydata, local_addr,
     if ((retval = encode_krb5_safe(&safemsg, &scratch1)))
        return retval;
 
-    safe_checksum.length = krb5_checksum_size(context, sumtype);
-    if (!(safe_checksum.contents = (krb5_octet *) malloc(safe_checksum.length))) {
-
-       retval = ENOMEM;
-       goto cleanup_scratch;
-    }
-    if ((retval = krb5_calculate_checksum(context, sumtype, scratch1->data,
-                                         scratch1->length,
-                                         (krb5_pointer) keyblock->contents,
-                                         keyblock->length, &safe_checksum))) {
+    if ((retval = krb5_c_make_checksum(context, sumtype, keyblock,
+                                      KRB5_KEYUSAGE_KRB_SAFE_CKSUM,
+                                      scratch1, &safe_checksum)))
        goto cleanup_checksum;
-    }
+
     safemsg.checksum = &safe_checksum;
     if ((retval = encode_krb5_safe(&safemsg, &scratch2))) {
        goto cleanup_checksum;
index c106dd15a39f497e66a55035b71d9c45755d5a6f..ab1432fdb02314624452508f89227ee679e6c47c 100644 (file)
@@ -160,6 +160,10 @@ krb5_error_code krb5_obtain_padata(context, preauth_to_use, key_proc,
 
     for (pa = preauth_to_use, size=0; *pa; pa++, size++) {
        if ((*pa)->pa_type == KRB5_PADATA_ETYPE_INFO) {
+           /* XXX use the first one.  Is there another way to disambiguate? */
+           if (etype_info)
+               continue;
+
            scratch.length = (*pa)->length;
            scratch.data = (char *) (*pa)->contents;
            retval = decode_krb5_etype_info(&scratch, &etype_info);
@@ -219,6 +223,8 @@ krb5_error_code krb5_obtain_padata(context, preauth_to_use, key_proc,
     }
 
 cleanup:
+    if (etype_info)
+       krb5_free_etype_info(context, etype_info);
     if (f_salt)
        krb5_xfree(salt.data);
     if (send_pa_list)
@@ -294,9 +300,6 @@ obtain_enc_ts_padata(context, in_padata, etype_info, def_enc_key,
     krb5_data *                        scratch;
     krb5_enc_data              enc_data;
     krb5_pa_data *             pa;
-    
-
-    enc_data.ciphertext.data = 0;
 
     retval = krb5_us_timeofday(context, &pa_enc.patimestamp, &pa_enc.pausec);
     if (retval)
@@ -305,8 +308,11 @@ obtain_enc_ts_padata(context, in_padata, etype_info, def_enc_key,
     if ((retval = encode_krb5_pa_enc_ts(&pa_enc, &scratch)) != 0)
        return retval;
 
-    if ((retval = krb5_encrypt_data(context, def_enc_key, 0, scratch,
-                                   &enc_data)))
+    enc_data.ciphertext.data = 0;
+
+    if ((retval = krb5_encrypt_helper(context, def_enc_key,
+                                     KRB5_KEYUSAGE_AS_REQ_PA_ENC_TS,
+                                     scratch, &enc_data)))
        goto cleanup;
 
     krb5_free_data(context, scratch);
index 0a154f6e14b390584fa536ae74eb9c9d126a2ec8..86d325d7b9a7a21a51ad2fcd8b15e4730aafbb47 100644 (file)
@@ -117,12 +117,16 @@ krb5_error_code pa_enc_timestamp(krb5_context context,
     if (ret = encode_krb5_pa_enc_ts(&pa_enc, &tmp))
        return(ret);
 
-    ret = krb5_encrypt_data(context, as_key, 0, tmp, &enc_data);
+    ret = krb5_encrypt_helper(context, as_key,
+                             KRB5_KEYUSAGE_AS_REQ_PA_ENC_TS,
+                             tmp, &enc_data);
 
     krb5_free_data(context, tmp);
 
-    if (ret)
+    if (ret) {
+       krb5_xfree(enc_data.ciphertext.data);
        return(ret);
+    }
 
     ret = encode_krb5_enc_data(&enc_data, &tmp);
 
@@ -215,7 +219,6 @@ krb5_error_code pa_sam(krb5_context context,
     char                       banner[100], prompt[100], response[100];
     krb5_data                  response_data;
     krb5_prompt                        kprompt;
-    krb5_encrypt_block         eblock;
     krb5_data                  defsalt;
     krb5_sam_challenge         *sam_challenge = 0;
     krb5_sam_response          sam_response;
@@ -281,13 +284,6 @@ krb5_error_code pa_sam(krb5_context context,
            as_key->length = 0;
        }
 
-       /* XXX the server uses this fixed enctype, so we will, too. */
-
-       if (!valid_enctype(ENCTYPE_DES_CBC_MD5))
-           return(KRB5_PROG_ETYPE_NOSUPP);
-
-       krb5_use_enctype(context, &eblock, ENCTYPE_DES_CBC_MD5);
-
 #if 0
        if ((salt->length == -1) && (salt->data == NULL)) {
            if (ret = krb5_principal2salt(context, request->client,
@@ -305,8 +301,11 @@ krb5_error_code pa_sam(krb5_context context,
        salt = NULL;
 #endif
            
-       ret = krb5_string_to_key(context, &eblock, as_key,
-                                    &response_data, salt);
+       /* XXX the server uses this fixed enctype, so we will, too. */
+
+       ret = krb5_c_string_to_key(context, ENCTYPE_DES_CBC_MD5,
+                                  &response_data, salt, as_key);
+
        if (defsalt.length)
            krb5_xfree(defsalt.data);
 
index 7537ac990adc3aa8c4a786dca7788ecf3b29decf..86c5ccf7272614186d4c0cc616639f33d9a07f6b 100644 (file)
@@ -19,7 +19,6 @@ decrypt_credencdata(context, pcred, pkeyblock, pcredenc)
     krb5_cred_enc_part         * pcredenc;
 {
     krb5_cred_enc_part  * ppart;
-    krb5_encrypt_block           eblock;
     krb5_error_code      retval;
     krb5_data            scratch;
 
@@ -28,28 +27,9 @@ decrypt_credencdata(context, pcred, pkeyblock, pcredenc)
        return ENOMEM;
 
     if (pkeyblock != NULL) {
-       if (!valid_enctype(pcred->enc_part.enctype)) {
-           free(scratch.data);
-           return KRB5_PROG_ETYPE_NOSUPP;
-       }
-
-       /* put together an eblock for this decryption */
-       krb5_use_enctype(context, &eblock, pcred->enc_part.enctype);
-    
-       /* do any necessary key pre-processing */
-       if ((retval = krb5_process_key(context, &eblock, pkeyblock)))
-           goto cleanup;
-    
-       /* call the decryption routine */
-       if ((retval = krb5_decrypt(context, 
-                          (krb5_pointer) pcred->enc_part.ciphertext.data,
-                          (krb5_pointer) scratch.data,
-                          scratch.length, &eblock, 0))) {
-           (void)krb5_finish_key(context, &eblock);
-           goto cleanup;
-       }
-
-       if ((retval = krb5_finish_key(context, &eblock)))
+       if ((retval = krb5_c_decrypt(context, pkeyblock,
+                                    KRB5_KEYUSAGE_KRB_CRED_ENCPART, 0,
+                                    &pcred->enc_part, &scratch)))
            goto cleanup;
     } else {
        memcpy(scratch.data, pcred->enc_part.ciphertext.data, scratch.length);
index c4e1ed0b6fe010f51f94672028312cfe871469d1..f08975f221fb8131fbbe5df52e0459ecb6798d59 100644 (file)
@@ -66,8 +66,9 @@ krb5_rd_priv_basic(context, inbuf, keyblock, local_addr, remote_addr,
     krb5_error_code      retval;
     krb5_priv          * privmsg;
     krb5_data            scratch;
-    krb5_encrypt_block           eblock;
     krb5_priv_enc_part  * privmsg_enc_part;
+    size_t               blocksize;
+    krb5_data            ivdata;
 
     if (!krb5_is_krb_priv(inbuf))
        return KRB5KRB_AP_ERR_MSG_TYPE;
@@ -76,43 +77,33 @@ krb5_rd_priv_basic(context, inbuf, keyblock, local_addr, remote_addr,
     if ((retval = decode_krb5_priv(inbuf, &privmsg)))
        return retval;
     
-    if (!valid_enctype(privmsg->enc_part.enctype)) {
-       retval = KRB5_PROG_ETYPE_NOSUPP;
-       goto cleanup_privmsg;
+    if (i_vector) {
+       if ((retval = krb5_c_block_size(context, keyblock->enctype,
+                                       &blocksize)))
+           goto cleanup_privmsg;
+
+       ivdata.length = blocksize;
+       ivdata.data = i_vector;
     }
-                          
-    /* put together an eblock for this decryption */
-    krb5_use_enctype(context, &eblock, privmsg->enc_part.enctype);
+
     scratch.length = privmsg->enc_part.ciphertext.length;
-    
     if (!(scratch.data = malloc(scratch.length))) {
        retval = ENOMEM;
        goto cleanup_privmsg;
     }
 
-    /* do any necessary key pre-processing */
-    if ((retval = krb5_process_key(context, &eblock, keyblock)))
+    if ((retval = krb5_c_decrypt(context, keyblock,
+                                KRB5_KEYUSAGE_KRB_PRIV_ENCPART, 
+                                i_vector?&ivdata:0,
+                                &privmsg->enc_part, &scratch)))
        goto cleanup_scratch;
 
-    /* call the decryption routine */
-    if ((retval = krb5_decrypt(context, 
-                              (krb5_pointer) privmsg->enc_part.ciphertext.data,
-                              (krb5_pointer) scratch.data,
-                              scratch.length, &eblock, i_vector))) {
-       krb5_finish_key(context, &eblock);
-        goto cleanup_scratch;
-    }
-
     /* if i_vector is set, put last block into the i_vector */
     if (i_vector)
        memcpy(i_vector,
               privmsg->enc_part.ciphertext.data +
-              (privmsg->enc_part.ciphertext.length -
-               eblock.crypto_entry->block_length),
-              eblock.crypto_entry->block_length);
-
-    if ((retval = krb5_finish_key(context, &eblock)))
-        goto cleanup_scratch;
+              (privmsg->enc_part.ciphertext.length - blocksize),
+              blocksize);
 
     /*  now decode the decrypted stuff */
     if ((retval = decode_krb5_enc_priv_part(&scratch, &privmsg_enc_part)))
index d4d559d14afb67f8fcbfe2ff61c9c0d8669ea50d..411a61ddbb6817b8a197baee4b2cd6d53a684999 100644 (file)
@@ -47,7 +47,6 @@ krb5_rd_rep(context, auth_context, inbuf, repl)
 {
     krb5_error_code      retval;
     krb5_ap_rep        * reply;
-    krb5_encrypt_block           eblock;
     krb5_data            scratch;
 
     if (!krb5_is_ap_rep(inbuf))
@@ -60,35 +59,15 @@ krb5_rd_rep(context, auth_context, inbuf, repl)
 
     /* put together an eblock for this encryption */
 
-    if (!valid_enctype(reply->enc_part.enctype)) {
-       krb5_free_ap_rep(context, reply);
-       return KRB5_PROG_ETYPE_NOSUPP;
-    }
-    krb5_use_enctype(context, &eblock, reply->enc_part.enctype);
-
     scratch.length = reply->enc_part.ciphertext.length;
     if (!(scratch.data = malloc(scratch.length))) {
        krb5_free_ap_rep(context, reply);
        return(ENOMEM);
     }
 
-    /* do any necessary key pre-processing */
-    if ((retval = krb5_process_key(context, &eblock,
-                                  auth_context->keyblock))) {
-       goto errout;
-    }
-
-    /* call the encryption routine */
-    if ((retval = krb5_decrypt(context, 
-                              (krb5_pointer) reply->enc_part.ciphertext.data,
-                              (krb5_pointer) scratch.data,
-                              scratch.length, &eblock, 0))) {
-       (void) krb5_finish_key(context, &eblock);
-       goto errout;
-    }
-
-    /* finished with the top-level encoding of the ap_rep */
-    if ((retval = krb5_finish_key(context, &eblock)))
+    if ((retval = krb5_c_decrypt(context, auth_context->keyblock,
+                                KRB5_KEYUSAGE_AP_REP_ENCPART, 0,
+                                &reply->enc_part, &scratch)))
        goto clean_scratch;
 
     /* now decode the decrypted stuff */
index 0c62c19df1760faf45ffbb0dd5e879e767f2e339..cdbdc81dff349f0fea791af508f31162dc44db23 100644 (file)
@@ -57,7 +57,8 @@
  */
 
 static krb5_error_code decrypt_authenticator
-       PROTOTYPE((krb5_context, const krb5_ap_req *, krb5_authenticator **));
+       PROTOTYPE((krb5_context, const krb5_ap_req *, krb5_authenticator **,
+                  int));
 
 #define in_clock_skew(date) (labs((date)-currenttime) < context->clockskew)
 
@@ -119,8 +120,12 @@ krb5_rd_req_decoded_opt(context, auth_context, req, server, keytab,
            return retval;
     }
 
+    /* XXX this is an evil hack.  check_valid_flag is set iff the call
+       is not from inside the kdc.  we can use this to determine which
+       key usage to use */
     if ((retval = decrypt_authenticator(context, req, 
-                                       &((*auth_context)->authentp))))
+                                       &((*auth_context)->authentp),
+                                       check_valid_flag)))
        goto cleanup;
 
     if (!krb5_principal_compare(context, (*auth_context)->authentp->client,
@@ -243,14 +248,66 @@ krb5_rd_req_decoded_opt(context, auth_context, req, server, keytab,
       }
     }
 
+    /* check if the various etypes are permitted */
+
+    if ((*auth_context)->auth_context_flags & KRB5_AUTH_CONTEXT_PERMIT_ALL) {
+       /* no etype check needed */;
+    } else if ((*auth_context)->permitted_etypes == NULL) {
+       /* check against the default set */
+       if ((!krb5_is_permitted_enctype(context,
+                                       req->ticket->enc_part.enctype)) ||
+           (!krb5_is_permitted_enctype(context,
+                                       req->ticket->enc_part2->session->enctype)) ||
+           (((*auth_context)->authentp->subkey) &&
+            !krb5_is_permitted_enctype(context,
+                                       (*auth_context)->authentp->subkey->enctype))) {
+           retval = KRB5_NOPERM_ETYPE;
+           goto cleanup;
+       }
+    } else {
+       /* check against the set in the auth_context */
+       int i;
+
+       for (i=0; (*auth_context)->permitted_etypes[i]; i++)
+           if ((*auth_context)->permitted_etypes[i] ==
+               req->ticket->enc_part.enctype)
+               break;
+       if (!(*auth_context)->permitted_etypes[i]) {
+           retval = KRB5_NOPERM_ETYPE;
+           goto cleanup;
+       }
+       
+       for (i=0; (*auth_context)->permitted_etypes[i]; i++)
+           if ((*auth_context)->permitted_etypes[i] ==
+               req->ticket->enc_part2->session->enctype)
+               break;
+       if (!(*auth_context)->permitted_etypes[i]) {
+           retval = KRB5_NOPERM_ETYPE;
+           goto cleanup;
+       }
+       
+       if ((*auth_context)->authentp->subkey) {
+           for (i=0; (*auth_context)->permitted_etypes[i]; i++)
+               if ((*auth_context)->permitted_etypes[i] ==
+                   (*auth_context)->authentp->subkey->enctype)
+                   break;
+           if (!(*auth_context)->permitted_etypes[i]) {
+               retval = KRB5_NOPERM_ETYPE;
+               goto cleanup;
+           }
+       }
+    }
+
     (*auth_context)->remote_seq_number = (*auth_context)->authentp->seq_number;
     if ((*auth_context)->authentp->subkey) {
        if ((retval = krb5_copy_keyblock(context,
                                         (*auth_context)->authentp->subkey,
                                         &((*auth_context)->remote_subkey))))
            goto cleanup;
-    } else
+    } else {
        (*auth_context)->remote_subkey = 0;
+    }
+
     if ((retval = krb5_copy_keyblock(context, req->ticket->enc_part2->session,
                                     &((*auth_context)->keyblock))))
        goto cleanup;
@@ -322,52 +379,34 @@ krb5_rd_req_decoded_anyflag(context, auth_context, req, server, keytab,
 }
 
 static krb5_error_code
-decrypt_authenticator(context, request, authpp)
+decrypt_authenticator(context, request, authpp, is_ap_req)
     krb5_context context;
     const krb5_ap_req *request;
     krb5_authenticator **authpp;
+    int is_ap_req;
 {
     krb5_authenticator *local_auth;
     krb5_error_code retval;
-    krb5_encrypt_block eblock;
     krb5_data scratch;
     krb5_keyblock *sesskey;
 
     sesskey = request->ticket->enc_part2->session;
 
-    if (!valid_enctype(sesskey->enctype))
-       return KRB5_PROG_ETYPE_NOSUPP;
-
-    /* put together an eblock for this encryption */
-
-    krb5_use_enctype(context, &eblock, request->authenticator.enctype);
-
     scratch.length = request->authenticator.ciphertext.length;
     if (!(scratch.data = malloc(scratch.length)))
        return(ENOMEM);
 
-    /* do any necessary key pre-processing */
-    if ((retval = krb5_process_key(context, &eblock, sesskey))) {
+    if ((retval = krb5_c_decrypt(context, sesskey,
+                                is_ap_req?KRB5_KEYUSAGE_AP_REQ_AUTH:
+                                KRB5_KEYUSAGE_TGS_REQ_AUTH, 0,
+                                &request->authenticator, &scratch))) {
        free(scratch.data);
        return(retval);
     }
 
-    /* call the encryption routine */
-    if ((retval = krb5_decrypt(context, 
-                              (krb5_pointer)request->authenticator.ciphertext.data,
-                              (krb5_pointer)scratch.data,
-                              scratch.length, &eblock, 0))) {
-       (void) krb5_finish_key(context, &eblock);
-       free(scratch.data);
-       return retval;
-    }
 #define clean_scratch() {memset(scratch.data, 0, scratch.length); \
 free(scratch.data);}
-    if ((retval = krb5_finish_key(context, &eblock))) {
 
-       clean_scratch();
-       return retval;
-    }
     /*  now decode the decrypted stuff */
     if (!(retval = decode_krb5_authenticator(&scratch, &local_auth))) {
        *authpp = local_auth;
index 5f0fcd6ca6c01c0673e7730d2de2e8039c390761..1c5aca21cafdf84bc35b2994a48ed5d4b5595172 100644 (file)
@@ -59,6 +59,7 @@ krb5_rd_safe_basic(context, inbuf, keyblock, recv_addr, sender_addr,
     krb5_checksum our_cksum, *his_cksum;
     krb5_octet zero_octet = 0;
     krb5_data *scratch;
+    krb5_boolean valid;
 
     if (!krb5_is_krb_safe(inbuf))
        return KRB5KRB_AP_ERR_MSG_TYPE;
@@ -122,14 +123,14 @@ krb5_rd_safe_basic(context, inbuf, keyblock, recv_addr, sender_addr,
 
     message->checksum = his_cksum;
                         
-    retval = krb5_verify_checksum(context, his_cksum->checksum_type,
-                                 his_cksum, scratch->data, scratch->length,
-                                 (krb5_pointer) keyblock->contents,
-                                 keyblock->length);
+    retval = krb5_c_verify_checksum(context, keyblock,
+                                   KRB5_KEYUSAGE_KRB_SAFE_CKSUM,
+                                   scratch, his_cksum, &valid);
+
     (void) memset((char *)scratch->data, 0, scratch->length);
     krb5_free_data(context, scratch);
     
-    if (retval) {
+    if (!valid) {
        retval = KRB5KRB_AP_ERR_MODIFIED;
        goto cleanup;
     }
index b06ef2bfc737d5483ef22ae335c66d270ad50d33..19de14e1aa6ad0f64d520ab1c34ca0dc377c9b43 100644 (file)
@@ -55,21 +55,15 @@ krb5_send_tgs_basic(context, in_data, in_cred, outbuf)
     krb5_checksum         checksum;
     krb5_authenticator           authent;
     krb5_ap_req          request;
-    krb5_encrypt_block           eblock;
     krb5_data          * scratch;
     krb5_data           * toutbuf;
 
     /* Generate checksum */
-    checksum.length = krb5_checksum_size(context, context->kdc_req_sumtype);
-    if ((checksum.contents = (krb5_octet *) malloc(checksum.length)) == NULL)
-        return(ENOMEM);
-
-    if ((retval = krb5_calculate_checksum(context, context->kdc_req_sumtype,
-                                         in_data->data, in_data->length,
-                                         (krb5_pointer) in_cred->keyblock.contents,
-                                         in_cred->keyblock.length,
-                                         &checksum))) {
-        free(checksum.contents);
+    if ((retval = krb5_c_make_checksum(context, context->kdc_req_sumtype,
+                                      &in_cred->keyblock,
+                                      KRB5_KEYUSAGE_TGS_REQ_AUTH_CKSUM,
+                                      in_data, &checksum))) {
+       free(checksum.contents);
        return(retval);
     }
 
@@ -102,43 +96,11 @@ krb5_send_tgs_basic(context, in_data, in_cred, outbuf)
        /* Cleanup scratch and scratch data */
         goto cleanup_data;
 
-    /* put together an eblock for this encryption */
-    krb5_use_enctype(context, &eblock, in_cred->keyblock.enctype);
-    request.authenticator.enctype = in_cred->keyblock.enctype;
-    request.authenticator.ciphertext.length =
-        krb5_encrypt_size(scratch->length, eblock.crypto_entry);
-
-    /* add padding area, and zero it */
-    if (!(scratch->data = realloc(scratch->data,
-                                  request.authenticator.ciphertext.length))) {
-        /* may destroy scratch->data */ 
-        krb5_free_ticket(context, request.ticket);
-        retval = ENOMEM;
-        goto cleanup_scratch;
-    }
-    memset(scratch->data + scratch->length, 0,
-          request.authenticator.ciphertext.length - scratch->length);
-
-    if (!(request.authenticator.ciphertext.data =
-          malloc(request.authenticator.ciphertext.length))) {
-        retval = ENOMEM;
-        goto cleanup_ticket;
-    }
-
-    /* do any necessary key pre-processing */
-    if ((retval = krb5_process_key(context, &eblock, &(in_cred)->keyblock)))
-        goto cleanup;
-
     /* call the encryption routine */ 
-    if ((retval=krb5_encrypt(context, (krb5_pointer) scratch->data,
-                            (krb5_pointer)request.authenticator.ciphertext.data,
-                            scratch->length, &eblock, 0))) {
-        krb5_finish_key(context, &eblock);
-        goto cleanup;
-    }
-    
-    if ((retval = krb5_finish_key(context, &eblock)))
-        goto cleanup;
+    if ((retval = krb5_encrypt_helper(context, &in_cred->keyblock,
+                                     KRB5_KEYUSAGE_TGS_REQ_AUTH,
+                                     scratch, &request.authenticator)))
+       goto cleanup_ticket;
 
     retval = encode_krb5_ap_req(&request, &toutbuf);
     *outbuf = *toutbuf;
@@ -185,6 +147,7 @@ krb5_send_tgs(context, kdcoptions, timestruct, ktypes, sname, addrs,
     krb5_timestamp time_now;
     krb5_pa_data **combined_padata;
     krb5_pa_data ap_req_padata;
+    size_t enclen;
 
     /* 
      * in_creds MUST be a valid credential NOT just a partially filled in
@@ -212,50 +175,21 @@ krb5_send_tgs(context, kdcoptions, timestruct, ktypes, sname, addrs,
 
     if (authorization_data) {
        /* need to encrypt it in the request */
-       krb5_encrypt_block eblock;
 
        if ((retval = encode_krb5_authdata((const krb5_authdata**)authorization_data,
                                           &scratch)))
            return(retval);
-       krb5_use_enctype(context, &eblock, in_cred->keyblock.enctype);
-       tgsreq.authorization_data.enctype = in_cred->keyblock.enctype;
-       tgsreq.authorization_data.kvno = 0; /* ticket session key has */
-                                           /* no version */
-       tgsreq.authorization_data.ciphertext.length =
-           krb5_encrypt_size(scratch->length, eblock.crypto_entry);
-       /* add padding area, and zero it */
-       if (!(scratch->data = realloc(scratch->data,
-                             tgsreq.authorization_data.ciphertext.length))) {
-           /* may destroy scratch->data */
-           krb5_xfree(scratch);
-           return ENOMEM;
-       }
-       memset(scratch->data + scratch->length, 0,
-              tgsreq.authorization_data.ciphertext.length - scratch->length);
-       if (!(tgsreq.authorization_data.ciphertext.data =
-             malloc(tgsreq.authorization_data.ciphertext.length))) {
-           krb5_free_data(context, scratch);
-           return ENOMEM;
-       }
-       if ((retval = krb5_process_key(context, &eblock,
-                                      &in_cred->keyblock))) {
-           krb5_free_data(context, scratch);
-           return retval;
-       }
-       /* call the encryption routine */
-       if ((retval = krb5_encrypt(context, (krb5_pointer) scratch->data,
-                  (krb5_pointer) tgsreq.authorization_data.ciphertext.data,
-                                  scratch->length, &eblock, 0))) {
-           (void) krb5_finish_key(context, &eblock);
+
+       if ((retval = krb5_encrypt_helper(context, &in_cred->keyblock,
+                                         KRB5_KEYUSAGE_TGS_REQ_AD_SESSKEY,
+                                         scratch,
+                                         &tgsreq.authorization_data))) {
            krb5_xfree(tgsreq.authorization_data.ciphertext.data);
            krb5_free_data(context, scratch);
            return retval;
-       }           
-       krb5_free_data(context, scratch);
-       if ((retval = krb5_finish_key(context, &eblock))) {
-           krb5_xfree(tgsreq.authorization_data.ciphertext.data);
-           return retval;
        }
+
+       krb5_free_data(context, scratch);
     }
 
     /* Get the encryption types list */
index 5705b711fc6c9feb46229f1583203395bc9ea986..42b9bfeb6469faf58bfe58bad6c44607ac7a5ea6 100644 (file)
@@ -56,7 +56,6 @@ krb5_error_code krb5_ser_authdata_init KRB5_PROTOTYPE((krb5_context));
 krb5_error_code krb5_ser_address_init KRB5_PROTOTYPE((krb5_context));
 krb5_error_code krb5_ser_authenticator_init KRB5_PROTOTYPE((krb5_context));
 krb5_error_code krb5_ser_checksum_init KRB5_PROTOTYPE((krb5_context));
-krb5_error_code krb5_ser_encrypt_block_init KRB5_PROTOTYPE((krb5_context));
 krb5_error_code krb5_ser_keyblock_init KRB5_PROTOTYPE((krb5_context));
 krb5_error_code krb5_ser_principal_init KRB5_PROTOTYPE((krb5_context));
 
@@ -95,17 +94,20 @@ krb5_auth_context_size(kcontext, arg, sizep)
      */
     kret = EINVAL;
     if ((auth_context = (krb5_auth_context) arg)) {
-       required = sizeof(krb5_int32)*8;
-
        kret = 0;
+
        /* Calculate size required by i_vector - ptooey */
-       if (auth_context->i_vector && auth_context->keyblock)
-           required += (size_t)
-               krb5_enctype_array[auth_context->keyblock->enctype]->
-                   system->block_length;
+       if (auth_context->i_vector && auth_context->keyblock) {
+           kret = krb5_c_block_size(kcontext, auth_context->keyblock->enctype,
+                                    &required);
+       } else {
+           required = 0;
+       }
+
+       required += sizeof(krb5_int32)*8;
 
        /* Calculate size required by remote_addr, if appropriate */
-       if (auth_context->remote_addr) {
+       if (!kret && auth_context->remote_addr) {
            kret = krb5_size_opaque(kcontext,
                                    KV5M_ADDRESS,
                                    (krb5_pointer) auth_context->remote_addr,
@@ -226,18 +228,25 @@ krb5_auth_context_externalize(kcontext, arg, buffer, lenremain)
            (void) krb5_ser_pack_int32((krb5_int32) auth_context->safe_cksumtype,
                                       &bp, &remain);
 
+           kret = 0;
+
            /* Now figure out the number of bytes for i_vector and write it */
-           obuf = (!auth_context->i_vector) ? 0 : (krb5_int32)
-               krb5_enctype_array[auth_context->keyblock->enctype]->
-                   system->block_length;
-           (void) krb5_ser_pack_int32(obuf, &bp, &remain);
+           if (auth_context->i_vector) {
+               kret = krb5_c_block_size(kcontext,
+                                        auth_context->keyblock->enctype,
+                                        &obuf);
+           } else {
+               obuf = 0;
+           }
+               
+           if (!kret)
+               (void) krb5_ser_pack_int32(obuf, &bp, &remain);
 
            /* Now copy i_vector */
-           if (auth_context->i_vector)
+           if (!kret && auth_context->i_vector)
                (void) krb5_ser_pack_bytes(auth_context->i_vector,
                                           (size_t) obuf,
                                           &bp, &remain);
-           kret = 0;
 
            /* Now handle remote_addr, if appropriate */
            if (!kret && auth_context->remote_addr) {
@@ -555,8 +564,6 @@ krb5_ser_auth_context_init(kcontext)
        kret = krb5_ser_authenticator_init(kcontext);
     if (!kret)
        kret = krb5_ser_checksum_init(kcontext);
-    if (!kret)
-       kret = krb5_ser_encrypt_block_init(kcontext);
     if (!kret)
        kret = krb5_ser_keyblock_init(kcontext);
     if (!kret)
index 20b3da67269086cab5f317e45627be289a2c8e52..04e21faab5e850f3c6b748c3c7ade79901eed961 100644 (file)
@@ -22,6 +22,8 @@
  *
  */
 
+#if 0 /* i don't believe this is used anywhere --marc */
+
 /*
  * ser_eblk.c - Serialize a krb5_encblock structure.
  */
@@ -249,3 +251,5 @@ krb5_ser_encrypt_block_init(kcontext)
 {
     return(krb5_register_serializer(kcontext, &krb5_encrypt_block_ser_entry));
 }
+
+#endif
index 6346aef2345fffa1139043ea73353178484d56c4..b30638d4fbcb5bcaad64d11f5b4ba3cd25cb7be9 100644 (file)
  *
  * String decoding:
  * ----------------
- * krb5_string_to_enctype()    - Convert string to krb5_enctype.
  * krb5_string_to_salttype()   - Convert string to salttype (krb5_int32)
- * krb5_string_to_cksumtype()  - Convert string to krb5_cksumtype;
  * krb5_string_to_timestamp()  - Convert string to krb5_timestamp.
  * krb5_string_to_deltat()     - Convert string to krb5_deltat.
  *
  * String encoding:
  * ----------------
- * krb5_enctype_to_string()    - Convert krb5_enctype to string.
  * krb5_salttype_to_string()   - Convert salttype (krb5_int32) to string.
- * krb5_cksumtype_to_string()  - Convert krb5_cksumtype to string.
  * krb5_timestamp_to_string()  - Convert krb5_timestamp to string.
  * krb5_timestamp_to_sfstring()        - Convert krb5_timestamp to short filled string
  * krb5_deltat_to_string()     - Convert krb5_deltat to string.
 /*
  * Local data structures.
  */
-struct enctype_lookup_entry {
-    krb5_enctype       ktt_enctype;            /* Keytype              */
-    const char *       ktt_specifier;          /* How to recognize it  */
-    const char *       ktt_output;             /* How to spit it out   */
-};
-
 struct salttype_lookup_entry {
     krb5_int32         stt_enctype;            /* Salt type            */
     const char *       stt_specifier;          /* How to recognize it  */
     const char *       stt_output;             /* How to spit it out   */
 };
 
-struct cksumtype_lookup_entry {
-    krb5_cksumtype     cst_cksumtype;          /* Checksum type        */
-    const char *       cst_specifier;          /* How to recognize it  */
-    const char *       cst_output;             /* How to spit it out   */
-};
-
 struct deltat_match_entry {
     const char *       dt_scan_format;         /* sscanf format        */
     int                        dt_nmatch;              /* Number to match      */
@@ -83,21 +67,6 @@ struct deltat_match_entry {
  * Local strings
  */
 
-/* Keytype strings */
-static const char enctype_des_in[]             = "des";
-static const char enctype_null_in[]            = "null";
-static const char enctype_descbccrc_in[]       = "des-cbc-crc";
-static const char enctype_descbcmd4_in[]       = "des-cbc-md4";
-static const char enctype_descbcmd5_in[]       = "des-cbc-md5";
-static const char enctype_des3cbcsha_in[]      = "des3-cbc-sha";
-static const char enctype_descbcraw_in[]       = "des-cbc-raw";
-static const char enctype_null_out[]           = "Null";
-static const char enctype_descbccrc_out[]      = "DES cbc mode with CRC-32";
-static const char enctype_descbcmd4_out[]      = "DES cbc mode with RSA-MD4";
-static const char enctype_descbcmd5_out[]      = "DES cbc mode with RSA-MD5";
-static const char enctype_des3cbcsha_out[]     = "DES-3 cbc mode with NIST-SHA";
-static const char enctype_descbcraw_out[]      = "DES cbc mode raw";
-
 /* Salttype strings */
 static const char stype_v5_in[]                = "normal";
 static const char stype_v4_in[]                = "v4";
@@ -112,24 +81,6 @@ static const char stype_olrealm_out[]       = "Version 5 - Realm Only";
 static const char stype_special_out[]  = "Special";
 static const char stype_afs3_out[]     = "AFS version 3";
 
-/* Checksum type strings */
-static const char cstype_crc32_in[]    = "crc32";
-static const char cstype_md4_in[]      = "md4";
-static const char cstype_md4des_in[]   = "md4-des";
-static const char cstype_descbc_in[]   = "des-cbc";
-static const char cstype_md5_in[]      = "md5";
-static const char cstype_md5des_in[]   = "md5-des";
-static const char cstype_sha_in[]      = "sha";
-static const char cstype_hmacsha_in[]  = "hmac-sha";
-static const char cstype_crc32_out[]   = "CRC-32";
-static const char cstype_md4_out[]     = "RSA-MD4";
-static const char cstype_md4des_out[]  = "RSA-MD4 with DES cbc mode";
-static const char cstype_descbc_out[]  = "DES cbc mode";
-static const char cstype_md5_out[]     = "RSA-MD5";
-static const char cstype_md5des_out[]  = "RSA-MD5 with DES cbc mode";
-static const char cstype_sha_out[]     = "NIST-SHA";
-static const char cstype_hmacsha_out[] = "HMAC-SHA";
-
 /* Absolute time strings */
 static const char atime_full_digits[]  = "%y%m%d%H%M%S";
 static const char atime_full_digits_d[]        = "%y.%m.%d.%H.%M.%S";
@@ -184,20 +135,6 @@ static const char dt_output_hms[]  = "%d:%02d:%02d";
  * Lookup tables.
  */
 
-static const struct enctype_lookup_entry enctype_table[] = {
-/* krb5_enctype                input specifier         output string           */
-/*-------------                ----------------------- ------------------------*/
-{ ENCTYPE_NULL,                enctype_null_in,        enctype_null_out        },
-{ ENCTYPE_DES_CBC_MD5, enctype_des_in,         enctype_descbcmd5_out   },
-{ ENCTYPE_DES_CBC_CRC, enctype_descbccrc_in,   enctype_descbccrc_out   },
-{ ENCTYPE_DES_CBC_MD4, enctype_descbcmd4_in,   enctype_descbcmd4_out   },
-{ ENCTYPE_DES_CBC_MD5, enctype_descbcmd5_in,   enctype_descbcmd5_out   },
-{ ENCTYPE_DES3_CBC_SHA,        enctype_des3cbcsha_in,  enctype_des3cbcsha_out  },
-{ ENCTYPE_DES_CBC_RAW, enctype_descbcraw_in,   enctype_descbcraw_out   }
-};
-static const int enctype_table_nents = sizeof(enctype_table)/
-                                      sizeof(enctype_table[0]);
-
 static const struct salttype_lookup_entry salttype_table[] = {
 /* salt type                   input specifier         output string     */
 /*-----------------------------        ----------------------- ------------------*/
@@ -211,21 +148,6 @@ static const struct salttype_lookup_entry salttype_table[] = {
 static const int salttype_table_nents = sizeof(salttype_table)/
                                        sizeof(salttype_table[0]);
 
-static const struct cksumtype_lookup_entry cksumtype_table[] = {
-/* krb5_cksumtype         input specifier      output string           */
-/*----------------------- ---------------------        ------------------------*/
-{ CKSUMTYPE_CRC32,        cstype_crc32_in,     cstype_crc32_out        },
-{ CKSUMTYPE_RSA_MD4,      cstype_md4_in,       cstype_md4_out          },
-{ CKSUMTYPE_RSA_MD4_DES,  cstype_md4des_in,    cstype_md4des_out       },
-{ CKSUMTYPE_DESCBC,       cstype_descbc_in,    cstype_descbc_out       },
-{ CKSUMTYPE_RSA_MD5,      cstype_md5_in,       cstype_md5_out          },
-{ CKSUMTYPE_RSA_MD5_DES,  cstype_md5des_in,    cstype_md5des_out       },
-{ CKSUMTYPE_NIST_SHA,     cstype_sha_in,       cstype_sha_out          },
-{ CKSUMTYPE_HMAC_SHA,    cstype_hmacsha_in,    cstype_hmacsha_out      }
-};
-static const int cksumtype_table_nents = sizeof(cksumtype_table)/
-                                        sizeof(cksumtype_table[0]);
-
 static const char * const atime_format_table[] = {
 atime_full_digits_Y,   /* yyyymmddhhmmss               */
 atime_full_digits_Yd,  /* yyyy.mm.dd.hh.mm.ss          */
@@ -403,30 +325,6 @@ strptime(buf, format, tm)
 }
 #endif /* HAVE_STRPTIME */
 \f
-/*
- * String to internal datatype routines.
- *
- * These routines return 0 for success, EINVAL for invalid entry.
- */
-KRB5_DLLIMP krb5_error_code KRB5_CALLCONV
-krb5_string_to_enctype(string, enctypep)
-    char               FAR * string;
-    krb5_enctype       FAR * enctypep;
-{
-    int i;
-    int found;
-
-    found = 0;
-    for (i=0; i<enctype_table_nents; i++) {
-       if (!strcasecmp(string, enctype_table[i].ktt_specifier)) {
-           found = 1;
-           *enctypep = enctype_table[i].ktt_enctype;
-           break;
-       }
-    }
-    return((found) ? 0 : EINVAL);
-}
-
 KRB5_DLLIMP krb5_error_code KRB5_CALLCONV
 krb5_string_to_salttype(string, salttypep)
     char       FAR * string;
@@ -446,25 +344,6 @@ krb5_string_to_salttype(string, salttypep)
     return((found) ? 0 : EINVAL);
 }
 
-KRB5_DLLIMP krb5_error_code KRB5_CALLCONV
-krb5_string_to_cksumtype(string, cksumtypep)
-    char               FAR * string;
-    krb5_cksumtype     FAR * cksumtypep;
-{
-    int i;
-    int found;
-
-    found = 0;
-    for (i=0; i<cksumtype_table_nents; i++) {
-       if (!strcasecmp(string, cksumtype_table[i].cst_specifier)) {
-           found = 1;
-           *cksumtypep = cksumtype_table[i].cst_cksumtype;
-           break;
-       }
-    }
-    return((found) ? 0 : EINVAL);
-}
-
 KRB5_DLLIMP krb5_error_code KRB5_CALLCONV
 krb5_string_to_timestamp(string, timestampp)
     char               FAR * string;
@@ -544,33 +423,6 @@ krb5_string_to_deltat(string, deltatp)
  * These routines return 0 for success, EINVAL for invalid parameter, ENOMEM
  * if the supplied buffer/length will not contain the output.
  */
-KRB5_DLLIMP krb5_error_code KRB5_CALLCONV
-krb5_enctype_to_string(enctype, buffer, buflen)
-    krb5_enctype       enctype;
-    char               FAR * buffer;
-    size_t             buflen;
-{
-    int i;
-    const char *out;
-
-    out = (char *) NULL;
-    for (i=0; i<enctype_table_nents; i++) {
-       if (enctype ==  enctype_table[i].ktt_enctype) {
-           out = enctype_table[i].ktt_output;
-           break;
-       }
-    }
-    if (out) {
-       if (buflen > strlen(out))
-           strcpy(buffer, out);
-       else
-           out = (char *) NULL;
-       return((out) ? 0 : ENOMEM);
-    }
-    else
-       return(EINVAL);
-}
-
 KRB5_DLLIMP krb5_error_code KRB5_CALLCONV
 krb5_salttype_to_string(salttype, buffer, buflen)
     krb5_int32 salttype;
index bb8ea349b092634fc244d4e111ab055b2faf06b1..85a8465030975202066e62d2c5516c6959761416 100644 (file)
@@ -68,12 +68,7 @@ krb5_verify_init_creds(krb5_context context,
    krb5_creds in_creds, *out_creds;
    krb5_auth_context authcon;
    krb5_data ap_req;
-   int keytab_key_exists, rd_req_succeeds, nofail;
    
-   keytab_key_exists = 0;
-   rd_req_succeeds = 0;
-   nofail = 0;
-
    /* KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN */
 
    server = NULL;
@@ -103,11 +98,31 @@ krb5_verify_init_creds(krb5_context context,
         goto cleanup;
    }
 
-   if (ret = krb5_kt_get_entry(context, keytab, server, 0, 0, &kte))
-      goto cleanup;
+   if (ret = krb5_kt_get_entry(context, keytab, server, 0, 0, &kte)) {
+       /* this means there is no keying material.  This is ok, as long as
+         it is not prohibited by the configuration */
+
+       krb5_error_code ret2;
+       int nofail;
+
+       if (options &&
+          (options->flags & KRB5_VERIFY_INIT_CREDS_OPT_AP_REQ_NOFAIL)) {
+          if (options->ap_req_nofail)
+              goto cleanup;
+       } else if ((ret2 = krb5_appdefault_boolean(context,
+                                                 &creds->client->realm,
+                                                 "verify_ap_req_nofail",
+                                                 &nofail))
+                 == 0) {
+          if (nofail)
+              goto cleanup;
+       }
+
+       ret = 0;
+       goto cleanup;
+   }
 
    krb5_kt_free_entry(context, &kte);
-   keytab_key_exists = 1;
 
    /* If the creds are for the server principal, we're set, just do
       a mk_req.         Otherwise, do a get_credentials first. */
@@ -166,61 +181,37 @@ krb5_verify_init_creds(krb5_context context,
                         NULL, NULL))
       goto cleanup;
 
-   rd_req_succeeds = 1;   
-
-cleanup:
-   /* I could test the error case first, but then there would be a
-      chance that the verification would succeed when there was
-      actually a significant failure (some transient condition could
-      make rd_req fail, and this would not be a problem if nofail was
-      not set */
-
-   if (!keytab_key_exists) {
-      krb5_error_code ret2;
-
-      if (options &&
-         (options->flags & KRB5_VERIFY_INIT_CREDS_OPT_AP_REQ_NOFAIL))
-        nofail = options->ap_req_nofail;
-      else if ((ret2 = krb5_appdefault_boolean(context, &creds->client->realm,
-                                              "verify_ap_req_nofail",
-                                              &nofail))
-              == 0)
-           ;
-      else
-        nofail = 0;
-   }
-
-   if ((keytab_key_exists && rd_req_succeeds) ||
-       (!keytab_key_exists && !nofail)) {
-      ret = 0;
+   /* if we get this far, then the verification succeeded.  We can
+      still fail if the library stuff here fails, but that's it */
 
-      if (ccache_arg && ccache) {
-        if (*ccache_arg == NULL) {
-           krb5_ccache retcc;
+   if (ccache_arg && ccache) {
+       if (*ccache_arg == NULL) {
+          krb5_ccache retcc;
 
-           retcc = NULL;
+          retcc = NULL;
 
-           if ((ret = krb5_cc_resolve(context, "MEMORY:rd_req2", &retcc)) ||
-               (ret = krb5_cc_initialize(context, retcc, creds->client)) ||
-               (ret = krb5_cc_copy_creds_except(context, ccache, retcc,
-                                                creds->server))) {
+          if ((ret = krb5_cc_resolve(context, "MEMORY:rd_req2", &retcc)) ||
+              (ret = krb5_cc_initialize(context, retcc, creds->client)) ||
+              (ret = krb5_cc_copy_creds_except(context, ccache, retcc,
+                                               creds->server))) {
               if (retcc)
-                 krb5_cc_destroy(context, retcc);
-           } else {
+                  krb5_cc_destroy(context, retcc);
+          } else {
               *ccache_arg = retcc;
-           }
-        } else {
-           /* if this returns an error, then that's the return
-              from this function */
-           ret = krb5_cc_copy_creds_except(context, ccache, *ccache_arg,
-                                           server);
-        }
-      }
+          }
+       } else {
+          ret = krb5_cc_copy_creds_except(context, ccache, *ccache_arg,
+                                          server);
+       }
    }
 
-   if (!server_arg)
+   /* if any of the above paths returned an errors, then ret is set
+      accordingly.  either that, or it's zero, which is fine, too */
+
+cleanup:
+   if (!server_arg && server)
       krb5_free_principal(context, server);
-   if (!keytab_arg)
+   if (!keytab_arg && keytab)
       krb5_kt_close(context, keytab);
    if (ccache)
       krb5_cc_destroy(context, ccache);
@@ -233,6 +224,3 @@ cleanup:
 
    return(ret);
 }
-
-
-   
index 0ee4a7192f678aa4bec9985885730b3b77c14239..84f0dec670390c780933ea4d95615749eee274e3 100644 (file)
@@ -1,3 +1,16 @@
+1998-10-27  Marc Horowitz  <marc@mit.edu>
+
+       * c_ustime.c, localaddr.c: moved here from lib/crypto
+
+       * ktdefname.c (krb5_kt_default_name): there is code in the tree
+       (notably, the admin server code) which uses globals to set the
+       keytab which will be used by gssapi.  this is gross, and we need a
+       better answer.  However, even that didn't work if there was an env
+       var or krb5.conf variable, since those override krb5_defkeyname.
+       Add a new global, krb5_overridekeyname, which really does override
+       all the other keytab locators.  While I'm at it, make the buffer
+       overflow checks sane.
+
 Fri Sep 25 22:32:16 1998  Theodore Y. Ts'o  <tytso@mit.edu>
 
        * ccdefname.c: We shouldn't try to use the CCache API on Unix
index 9e132dbc86924f3714dd11810d3bba743d0ccaf7..56edfac36bcbb5b0581420dba88d7efb573da3b4 100644 (file)
@@ -12,6 +12,7 @@ PROG_RPATH=$(KRB5_LIBDIR)
 
 STLIBOBJS= \
        an_to_ln.o      \
+       c_ustime.o      \
        def_realm.o     \
        DNR.o   \
        ccdefname.o     \
@@ -54,6 +55,7 @@ STLIBOBJS= \
 
 OBJS= \
        an_to_ln.$(OBJEXT)      \
+       c_ustime.$(OBJEXT)      \
        def_realm.$(OBJEXT)     \
        DNR.$(OBJEXT)   \
        ccdefname.$(OBJEXT)     \
@@ -96,6 +98,7 @@ OBJS= \
 
 SRCS= \
        $(srcdir)/an_to_ln.c    \
+       $(srcdir)/c_ustime.c    \
        $(srcdir)/def_realm.c   \
        $(srcdir)/DNR.c \
        $(srcdir)/ccdefname.c   \
similarity index 99%
rename from src/lib/crypto/os/c_ustime.c
rename to src/lib/krb5/os/c_ustime.c
index e790acc956af139a6f5b4b998161f86e8828b17f..350c1aa5c74dbe58112f663b4d47183bdeda5a33 100644 (file)
@@ -27,7 +27,7 @@
 #define        NEED_SOCKETS
 #include "k5-int.h"
 
-#ifdef macintosh
+#ifdef _MACINTOSH
 
 /* We're a Macintosh -- do Mac time things.  */
 
index c645635ab016ecc61d53e0e3750f917945b92025..0493244f611056f7b51f77bf331112e5457096ab 100644 (file)
@@ -30,6 +30,9 @@
 
 extern char *krb5_defkeyname;
 
+/* this is a an exceedinly gross thing. */
+char *krb5_overridekeyname = NULL;
+
 KRB5_DLLIMP krb5_error_code KRB5_CALLCONV
 krb5_kt_default_name(context, name, namesize)
     krb5_context context;
@@ -40,19 +43,24 @@ krb5_kt_default_name(context, name, namesize)
     krb5_error_code code;
     char *retval;
 
-    if ((context->profile_secure == FALSE) &&
+    if (krb5_overridekeyname) {
+       if ((size_t) namesize < (strlen(krb5_overridekeyname)+1))
+           return KRB5_CONFIG_NOTENUFSPACE;
+       strcpy(name, krb5_overridekeyname);
+    } else if ((context->profile_secure == FALSE) &&
        (cp = getenv("KRB5_KTNAME"))) {
-       strncpy(name, cp, namesize);
-       if (strlen(cp) >= (size_t) namesize)
+       if ((size_t) namesize < (strlen(cp)+1))
            return KRB5_CONFIG_NOTENUFSPACE;
+       strcpy(name, cp);
     } else if (((code = profile_get_string(context->profile,
                                           "libdefaults",
                                           "default_keytab_name", NULL, 
                                           NULL, &retval)) == 0) &&
               retval) {
-       strncpy(name, retval, namesize);
-       if ((size_t) namesize < strlen(retval))
+       if ((size_t) namesize < (strlen(retval)+1))
            return KRB5_CONFIG_NOTENUFSPACE;
+       strcpy(name, retval);
+       free(retval);
     } else {
 #if defined (_MSDOS) || defined(_WIN32)
        {
@@ -66,9 +74,9 @@ krb5_kt_default_name(context, name, namesize)
            sprintf(name, krb5_defkeyname, defname);
        }
 #else
-       strncpy(name, krb5_defkeyname, namesize);
-       if ((size_t) namesize < strlen(krb5_defkeyname))
+       if ((size_t) namesize < (strlen(krb5_defkeyname)+1))
            return KRB5_CONFIG_NOTENUFSPACE;
+       strcpy(name, krb5_defkeyname);
 #endif
     }
     return 0;
index cb204b597ebef3e221a3ef6e2aaba2e0670e8b1d..9f33e5d98b5b6bda7656f79852ff2f81089b2fdb 100644 (file)
  * this software for any purpose.  It is provided "as is" without express
  * or implied warranty.
  * 
- * Just a stub that calls krb5_crypto_os_localaddr().
  *
+ * Return the protocol addresses supported by this host.
+ *
+ * XNS support is untested, but "Should just work".
  */
 
+#define NEED_SOCKETS
 #include "k5-int.h"
 
+#if !defined(HAVE_MACSOCK_H) && !defined(_MSDOS) && !defined(_WIN32)
+
+/* needed for solaris, harmless elsewhere... */
+#define BSD_COMP
+#include <sys/ioctl.h>
+#include <sys/time.h>
+#include <errno.h>
+
+/*
+ * The SIOCGIF* ioctls require a socket.
+ * It doesn't matter *what* kind of socket they use, but it has to be
+ * a socket.
+ *
+ * Of course, you can't just ask the kernel for a socket of arbitrary
+ * type; you have to ask for one with a valid type.
+ *
+ */
+#ifdef HAVE_NETINET_IN_H
+
+#include <netinet/in.h>
+
+#ifndef USE_AF
+#define USE_AF AF_INET
+#define USE_TYPE SOCK_DGRAM
+#define USE_PROTO 0
+#endif
+
+#endif
+
+#ifdef KRB5_USE_NS
+
+#include <netns/ns.h>
+
+#ifndef USE_AF
+#define USE_AF AF_NS
+#define USE_TYPE SOCK_DGRAM
+#define USE_PROTO 0            /* guess */
+#endif
+
+#endif
+/*
+ * Add more address families here.
+ */
+
+/*
+ * BSD 4.4 defines the size of an ifreq to be
+ * max(sizeof(ifreq), sizeof(ifreq.ifr_name)+ifreq.ifr_addr.sa_len
+ * However, under earlier systems, sa_len isn't present, so the size is 
+ * just sizeof(struct ifreq)
+ */
+#ifdef HAVE_SA_LEN
+#ifndef max
+#define max(a,b) ((a) > (b) ? (a) : (b))
+#endif
+#define ifreq_size(i) max(sizeof(struct ifreq),\
+     sizeof((i).ifr_name)+(i).ifr_addr.sa_len)
+#else
+#define ifreq_size(i) sizeof(struct ifreq)
+#endif /* HAVE_SA_LEN*/
+
+
+
+extern int errno;
+
+/*
+ * Return all the protocol addresses of this host.
+ *
+ * We could kludge up something to return all addresses, assuming that
+ * they're valid kerberos protocol addresses, but we wouldn't know the
+ * real size of the sockaddr or know which part of it was actually the
+ * host part.
+ *
+ * This uses the SIOCGIFCONF, SIOCGIFFLAGS, and SIOCGIFADDR ioctl's.
+ */
+
 KRB5_DLLIMP krb5_error_code KRB5_CALLCONV
 krb5_os_localaddr(context, addr)
     krb5_context context;
     krb5_address FAR * FAR * FAR *addr;
 {
-    return krb5_crypto_os_localaddr(addr);
+    struct ifreq *ifr, ifreq;
+    struct ifconf ifc;
+    int s, code, n, i;
+    char buf[1024];
+    krb5_address *addr_temp [ 1024/sizeof(struct ifreq) ];
+    int n_found;
+    int mem_err = 0;
+    
+    memset(buf, 0, sizeof(buf));
+    ifc.ifc_len = sizeof(buf);
+    ifc.ifc_buf = buf;
+    
+    s = socket (USE_AF, USE_TYPE, USE_PROTO);
+    if (s < 0)
+       return errno;
+
+    code = ioctl (s, SIOCGIFCONF, (char *)&ifc);
+    if (code < 0) {
+       int retval = errno;
+       closesocket (s);
+       return retval;
+    }
+    n = ifc.ifc_len;
+    
+n_found = 0;
+    for (i = 0; i < n; i+= ifreq_size(*ifr) ) {
+       krb5_address *address;
+       ifr = (struct ifreq *)((caddr_t) ifc.ifc_buf+i);
+
+       strncpy(ifreq.ifr_name, ifr->ifr_name, sizeof (ifreq.ifr_name));
+       if (ioctl (s, SIOCGIFFLAGS, (char *)&ifreq) < 0)
+           continue;
+
+#ifdef IFF_LOOPBACK
+       if (ifreq.ifr_flags & IFF_LOOPBACK) 
+           continue;
+#endif
+
+       if (!(ifreq.ifr_flags & IFF_UP)) 
+           /* interface is down; skip */
+           continue;
+
+       /* ifr->ifr_addr has what we want! */
+       switch (ifr->ifr_addr.sa_family) {
+#ifdef HAVE_NETINET_IN_H
+       case AF_INET:
+           {
+               struct sockaddr_in *in =
+                   (struct sockaddr_in *)&ifr->ifr_addr;
+               
+               address = (krb5_address *)
+                   malloc (sizeof(krb5_address));
+               if (address) {
+                   address->magic = KV5M_ADDRESS;
+                   address->addrtype = ADDRTYPE_INET;
+                   address->length = sizeof(struct in_addr);
+                   address->contents = (unsigned char *)malloc(address->length);
+                   if (!address->contents) {
+                       krb5_xfree(address);
+                       address = 0;
+                       mem_err++;
+                   } else {
+                       memcpy ((char *)address->contents,
+                               (char *)&in->sin_addr, 
+                               address->length);
+                       break;
+                   }
+               } else mem_err++;
+           }
+#endif
+#ifdef KRB5_USE_NS
+           case AF_XNS:
+           {  
+               struct sockaddr_ns *ns =
+                   (struct sockaddr_ns *)&ifr->ifr_addr;
+               address = (krb5_address *)
+                   malloc (sizeof (krb5_address) + sizeof (struct ns_addr));
+               if (address) {
+                   address->magic = KV5M_ADDRESS;
+                   address->addrtype = ADDRTYPE_XNS; 
+
+                   /* XXX should we perhaps use ns_host instead? */
+
+                   address->length = sizeof(struct ns_addr);
+                   address->contents = (unsigned char *)malloc(address->length);
+                   if (!address->contents) {
+                       krb5_xfree(address);
+                       address = 0;
+                       mem_err++;
+                   } else {
+                       memcpy ((char *)address->contents,
+                               (char *)&ns->sns_addr,
+                               address->length);
+                       break;
+                   }
+               } else mem_err++;
+               break;
+           }
+#endif
+       /*
+        * Add more address families here..
+        */
+       default:
+           continue;
+       }
+       if (address)
+           addr_temp[n_found++] = address;
+       address = 0;
+    }
+    closesocket(s);
+
+    *addr = (krb5_address **)malloc (sizeof (krb5_address *) * (n_found+1));
+    if (*addr == 0)
+       mem_err++;
+    
+    if (mem_err) {
+       for (i=0; i<n_found; i++) {
+           krb5_xfree(addr_temp[i]);
+           addr_temp[i] = 0;
+       }
+       return ENOMEM;
+    }
+    
+    for (i=0; i<n_found; i++) {
+       (*addr)[i] = addr_temp[i];
+    }
+    (*addr)[n_found] = 0;
+    return 0;
+}
+
+#else /* Windows/Mac version */
+
+/*
+ * Hold on to your lunch!  Backup kludge method of obtaining your
+ * local IP address, courtesy of Windows Socket Network Programming,
+ * by Robert Quinn
+ */
+#if defined(_MSDOS) || defined(_WIN32)
+static struct hostent *local_addr_fallback_kludge()
+{
+       static struct hostent   host;
+       static SOCKADDR_IN      addr;
+       static char *           ip_ptrs[2];
+       SOCKET                  sock;
+       int                     size = sizeof(SOCKADDR);
+       int                     err;
+
+       sock = socket(AF_INET, SOCK_DGRAM, 0);
+       if (sock == INVALID_SOCKET)
+               return NULL;
+
+       /* connect to arbitrary port and address (NOT loopback) */
+       addr.sin_family = AF_INET;
+       addr.sin_port = htons(IPPORT_ECHO);
+       addr.sin_addr.s_addr = inet_addr("204.137.220.51");
+
+       err = connect(sock, (LPSOCKADDR) &addr, sizeof(SOCKADDR));
+       if (err == SOCKET_ERROR)
+               return NULL;
+
+       err = getsockname(sock, (LPSOCKADDR) &addr, (int FAR *) size);
+       if (err == SOCKET_ERROR)
+               return NULL;
+
+       closesocket(sock);
+
+       host.h_name = 0;
+       host.h_aliases = 0;
+       host.h_addrtype = AF_INET;
+       host.h_length = 4;
+       host.h_addr_list = ip_ptrs;
+       ip_ptrs[0] = (char *) &addr.sin_addr.s_addr;
+       ip_ptrs[1] = NULL;
+
+       return &host;
+}
+#endif
+
+/* No ioctls in winsock so we just assume there is only one networking 
+ * card per machine, so gethostent is good enough. 
+ */
+krb5_error_code
+krb5_os_localaddr (krb5_context context, krb5_address ***addr) {
+    char host[64];                              /* Name of local machine */
+    struct hostent *hostrec;
+    int err;
+
+    *addr = calloc (2, sizeof (krb5_address *));
+    if (*addr == NULL)
+        return ENOMEM;
+
+#ifdef HAVE_MACSOCK_H
+    hostrec = getmyipaddr();
+#else /* HAVE_MACSOCK_H */
+    err = 0;
+    
+    if (gethostname (host, sizeof(host))) {
+        err = WSAGetLastError();
+    }
+
+    if (!err) {
+           hostrec = gethostbyname (host);
+           if (hostrec == NULL) {
+                   err = WSAGetLastError();
+           }
+    }
+
+    if (err) {
+           hostrec = local_addr_fallback_kludge();
+           if (!hostrec)
+                   return err;
+    }
+#endif /* HAVE_MACSOCK_H */
+
+    (*addr)[0] = calloc (1, sizeof(krb5_address));
+    if ((*addr)[0] == NULL) {
+        free (*addr);
+        return ENOMEM;
+    }
+    (*addr)[0]->magic = KV5M_ADDRESS;
+    (*addr)[0]->addrtype = hostrec->h_addrtype;
+    (*addr)[0]->length = hostrec->h_length;
+    (*addr)[0]->contents = (unsigned char *)malloc((*addr)[0]->length);
+    if (!(*addr)[0]->contents) {
+        free((*addr)[0]);
+        free(*addr);
+        return ENOMEM;
+    } else {
+        memcpy ((*addr)[0]->contents,
+                hostrec->h_addr,
+                (*addr)[0]->length);
+    }
+       /* FIXME, deal with the case where gethostent returns multiple addrs */
+
+    return(0);
 }
+#endif
index c0ccf7e38ce911dab6dc60e4403dee879e5c87e2..d8187ac3a666b69665ae0b64b6b63680b68392bc 100644 (file)
@@ -46,7 +46,7 @@ krb5_locate_kdc(context, realm, addr_pp, naddrs, master_index, nmasters)
     const char *realm_kdc_names[4];
     char **masterlist, **hostlist, *host, *port, *cp;
     krb5_error_code code;
-    int i, j, out, count;
+    int i, j, out, count, ismaster;
     struct sockaddr *addr_p;
     struct sockaddr_in *sin_p;
     struct hostent *hp;
@@ -103,6 +103,9 @@ krb5_locate_kdc(context, realm, addr_pp, naddrs, master_index, nmasters)
     }
     
     if (master_index) {
+        *master_index = 0;
+       *nmasters = 0;
+
        realm_kdc_names[0] = "realms";
        realm_kdc_names[1] = host;
        realm_kdc_names[2] = "admin_server";
@@ -113,10 +116,7 @@ krb5_locate_kdc(context, realm, addr_pp, naddrs, master_index, nmasters)
 
        krb5_xfree(host);
 
-       if (code) {
-           *master_index = 0;
-           *nmasters = 0;
-       } else {
+       if (code == 0) {
            for (i=0; masterlist[i]; i++) {
                host = masterlist[i];
 
@@ -138,11 +138,10 @@ krb5_locate_kdc(context, realm, addr_pp, naddrs, master_index, nmasters)
        krb5_xfree(host);
     }
 
-    /* at this point, is master is non-NULL, then either the master kdc
+    /* at this point, if master is non-NULL, then either the master kdc
        is required, and there is one, or the master kdc is not required,
        and there may or may not be one. */
 
-
 #ifdef HAVE_NETINET_IN_H
     if (sec_udpport)
            count = count * 2;
@@ -175,10 +174,15 @@ krb5_locate_kdc(context, realm, addr_pp, naddrs, master_index, nmasters)
            continue;
        }
 
-       if (masterlist)
-           for (j=0; masterlist[j]; j++)
-               if (strcasecmp(hostlist[i], masterlist[j]) == 0)
+       ismaster = 0;
+       if (masterlist) {
+           for (j=0; masterlist[j]; j++) {
+               if (strcasecmp(hostlist[i], masterlist[j]) == 0) {
                    *master_index = out;
+                   ismaster = 1;
+               }
+           }
+       }
 
        switch (hp->h_addrtype) {
 
@@ -211,7 +215,7 @@ krb5_locate_kdc(context, realm, addr_pp, naddrs, master_index, nmasters)
        default:
            break;
        }
-       if (masterlist)
+       if (ismaster)
            *nmasters = out - *master_index;
 
        /* Free the hostlist entry we are looping over. */
@@ -219,6 +223,11 @@ krb5_locate_kdc(context, realm, addr_pp, naddrs, master_index, nmasters)
        hostlist[i] = 0;
     }
 
+    if (masterlist) {
+       for (i=0; masterlist[i]; i++)
+         free(masterlist[i]);
+       free(masterlist);
+    }
 
     free ((char *)hostlist);
 
index 7db853923107687f18d7f9618ad4b30e2f7ad8c9..50ec692cba34ffb6bf789d5d563bf191e0fb6dac 100644 (file)
@@ -1,3 +1,12 @@
+1998-10-27  Marc Horowitz  <marc@mit.edu>
+
+       * svc_auth_gssapi.c, auth_gssapi.h: fix the set_name prototype,
+       add a new unset_names function
+
+Sun Jul 26 18:13:39 1998  Sam Hartman  <hartmans@utwig.mesas.com>
+
+       * Makefile.in (LIBMAJOR): bump libmajor
+
 Wed Apr 15 18:07:38 1998  Tom Yu  <tlyu@mit.edu>
 
        * Makefile.in (SHLIB_EXPDEPS): 
index 1340d3ffd4467d0eb5b7f648adb3af63a4b76420..a03ef026f06743467e07c2b57a6d9c41000408a8 100644 (file)
@@ -6,7 +6,7 @@ CFLAGS = $(CCOPTS) $(DEFS) -DGSSAPI_KRB5 -DDEBUG_GSSAPI=0
 ##DOSLIBNAME=libgssrpc.lib
 
 LIB=gssrpc
-LIBMAJOR=2
+LIBMAJOR=3
 LIBMINOR=0
 STOBJLISTS=OBJS.ST
 SHLIB_EXPDEPS= \
index 218b5cb9d318637dd1866d988389a7d3be67bdbf..2cdd20f2fe397af178c5b27bd59c48ecf8a97119 100644 (file)
@@ -111,8 +111,10 @@ PROTOTYPE((CLIENT *clnt, char *service_name));
 void auth_gssapi_display_status
 PROTOTYPE((char *msg, OM_uint32 major,
           OM_uint32 minor)); 
-bool_t _svcauth_gssapi_set_name
-PROTOTYPE((char *name, gss_OID name_type));
+bool_t _svcauth_gssapi_set_names
+PROTOTYPE((auth_gssapi_name *names, int num));
+void _svcauth_gssapi_unset_names
+PROTOTYPE(());
 
 void _svcauth_set_log_badauth_func
 PROTOTYPE((auth_gssapi_log_badauth_func func,
index 2a3233ee9302a94430e7e706dce9d7a09a44dc0b..df59859f0d2a18222da13ea894a601714ceae03b 100644 (file)
@@ -887,7 +887,7 @@ done:
 }
 
 /*
- * Function: _svcauth_gssapi_set_name
+ * Function: _svcauth_gssapi_set_names
  *
  * Purpose: Sets the list of service names for which incoming
  * authentication requests should be honored.
@@ -916,6 +916,13 @@ bool_t _svcauth_gssapi_set_names(names, num)
      if (server_name_list == NULL)
          goto fail;
      
+     for (i = 0; i < num; i++) {
+         server_name_list[i] = 0;
+         server_creds_list[i] = 0;
+     }
+
+     server_creds_count = num;
+     
      for (i = 0; i < num; i++) {
          in_buf.value = names[i].name;
          in_buf.length = strlen(in_buf.value) + 1;
@@ -939,19 +946,41 @@ bool_t _svcauth_gssapi_set_names(names, num)
          }
      }
 
-     server_creds_count = num;
-     
      return TRUE;
 
 fail:
-     /* memory leak: not releasing names/creds already acquired */
-     if (server_creds_list)
+     _svcauth_gssapi_unset_names();
+
+     return FALSE;
+}
+
+/* Function: _svcauth_gssapi_unset_names
+ *
+ * Purpose: releases the names and credentials allocated by
+ * _svcauth_gssapi_set_names
+ */
+
+void _svcauth_gssapi_unset_names()
+{
+     int i;
+     OM_uint32 minor_stat;
+
+     if (server_creds_list) {
+         for (i = 0; i < server_creds_count; i++)
+              if (server_creds_list[i])
+                   gss_release_cred(&minor_stat, &server_creds_list[i]);
          free(server_creds_list);
-     if (server_name_list)
+     }
+
+     if (server_name_list) {
+         for (i = 0; i < server_creds_count; i++)
+              if (server_name_list[i])
+                   gss_release_name(&minor_stat, &server_name_list[i]);
          free(server_name_list);
-     return FALSE;
+     }
 }
 
+
 /*
  * Function: _svcauth_gssapi_set_log_badauth_func
  *
diff --git a/src/mac/TestTrack/ChangeLog b/src/mac/TestTrack/ChangeLog
deleted file mode 100644 (file)
index ac6e964..0000000
+++ /dev/null
@@ -1,24 +0,0 @@
-Tue Jul  7 17:00:00 1998  Miro Jurisic <meeroh@mit.edu>
-
-  * initTestTrackGlue.c renamed to ShlibTestTrack.c. removed CFM initialization code from
-    there, since we are calling ShlibTestTrack from CFM initializers in *.CFM.c. Also updated
-    to fix the bug where we were closing application's resource fork (oops).
-
-Fri Dec 20 12:35:32 1996  Marshall Vale  <mjv@mit.edu>
-
-       * GSSforSAP.r: Moved resources for the timebomb out to Rez 
-               format for easier CVSing
-       * macSAPglue.c (__initializeSAPglue): Added new conditions to the
-               timebomb code so that it can identify individual applications
-               and not just fail globally.
-               
-Tue Dec 17 13:53:36 1996  Theodore Y. Ts'o  <tytso@mit.edu>
-
-       * GSSforSAP.r: Fix expire time in the text resource to be June 1,
-               1997.
-
-Fri Dec 13 14:58:20 1996  Theodore Y. Ts'o  <tytso@mit.edu>
-
-       * macSAPglue.c (__initializeSAPglue): Change the timebomb date to
-               be June 1, 1997.
-
diff --git a/src/mac/TestTrack/MITAthenaLib b/src/mac/TestTrack/MITAthenaLib
deleted file mode 100644 (file)
index d7ae71a..0000000
+++ /dev/null
@@ -1 +0,0 @@
-(This file must be converted with BinHex 4.0)\r:$%e*9%&dD'9ZB8aTBJ"cD'aL2j!%!*!%b$d!!!*A#-K+EhNKF'9QCQdf1'X!!!!\r"XG%Hb!#3$3-!!J#3$NXd!!",0!!!5c3!!!#8!!%#!*!%"3#3"LFJ!!!R)!!!"GJ\r!!%[)!J%#!*!%$J#3$J9)!!"4S!3"!J"0B@PZ!#9"09G[FQaN!%a[B@4PFJ#3"#T\r46PErp#m0F!%[!$!mUQi[!#*YrC3J@8k3!#TZrr!Y32rdF!%[!$!mU'i[!#*YrC3\rJ@8k3!#TZrr#`V[rdCJB`2!)!B!3`2!3!6Pj1GBp1G@e8EfpXBQpi9(*KF(-!!#T\r46PErq$!Z!!S#J!!!#!"Q"(!!B!*`!8jH6R3!")Y(CA48FQ&`9(P`C3!!+P&19[r\rd51FB"$BZ!!S[!f(rN!6%'!!-"!!"CK*Krj!%@!*$"rqf3'd%0MbSRbm%,`-LEIf\r8)&P1N!!UE[r`,8$rp(!",`!`2+LI,`!LEIf8)&P1N!!UE[r`X+lrp&E!4!"*`%c\rI!"K1ANjd!!5+9(*KF%9iDA0dF`!!!#T46PErj#m05'lrk(!",`!LEIcB)&P1N!!\rUE[rJ5'lrj#mZ!!`[,J!)-#lrpLm!)Qhmc#"C6T!!+Qlri%M!C``JEJ!)3P!JEJ!\r-3T!!6Pj1G!!)MdGPG&0jFh4PE8C[E'4PFJ!!+P&19[rd51F30#CZ!!JNEJ!-GJ!\r`2+'Y,`"Krj!%#%S!Caa)E[rd,caQEfaN)QhpN!!J@8k3!#TZrr")`'B#GJ&+!fB\r-,`S[#f(rN!4@B#J[#Lm,F!![!#mmBh4bE$!mJ!![!#*YrB`J@8k3!#TZrr")`'F\r%3P0#NNcI$!K1ANjd!!L24f9d3e"KEQ9X4QpXC'9b!!!U88j@rRa)jam%,Li!##`\rZ!!`k,J!5+#i!&%+ZriT"l[jq,8MrN!!p4Iq8,86rVMem!!(rQQ"F[UlrRQC1[+l\rrSQC)F!%[!%KZrRi["#m&)QhpV#"C6T!!+QlqH$B!F!%[!#mmC'jbF#*YrA`J@8k\r3!#TZrRK+J'B3,`-LEIeB)&P1N!!UE[jiB!3`!f!H8QlrQLe%rkj)E[pq)Qhmr#"\rC6T!!+QlqH%M!Cj!!F2p-h`$i6Pj1G!!3Ne0PBA*MD%C[E'4PFNC[FN418P!!!#T\r46PErm#m$5'lrmNKZrrCKrrrrrT3[,[rb-#lrpLm!,cakG'0`,caMC'9fBIq3"!`\rf!!a$rrpR"$!$B'j)E[rb5'lrpQ(rrrrpr#mZrr)`,[rf,`![2'edBh![2'0NCAC\rKrrrrrYBf!!a$rrpR"$!$B$K)E[rb5'lrpQ(rrrrq+#mZrr)`,[rf,`![2'edBh!\r[2'0NCACKrrrrrU!f!!a$rrpR"$!$B!*`rbBI6Pj1GBP2F'9Z6h9b8NB!!#T46PE\rrq%MR%!4+VISSC`C`!'!!!04Krj!%,$B!F!%[!#mmC'jbF#*YrA`J@8k3!#TZrr3\rV32SN5Uhk*'B3)QhpL#"C6T!!+Qlrp'!!!*`[,ISN)Qhp##"C6T!!+Qlrp!a$rrp\rR$Lm$)Qhp@#"C6T!!+Qlrp#mYqL3LEIc8)&P1N!!UE[rd,bhk*#*YrE`J@8k3!#T\rZrr3JEISN+e$k+#mZ!!K)H!!"5(J$i5mYqLJLEIcX)&P1N!!UE[rd0J!`!dM!6qm\r!%'FN,bhk*#*Yr0`J@8k3!#TZrr3[,ISN)QhpZ#"C6T!!+Qlrp%+YqLJ`!bBI6Pj\r1G!!%M%p`C@j5CA0[E(CPFJ!!!#T46PErq#m05Uhk+'B%F14J+LmZ!"3[,J!3,bi\r!$#mZ!!K)H!!$,c`!!2rK,bhk+#*Yr1`J@8k3!#TZrr41ANjd!"#*8h4b9'p"C'4\rb!!!U88j@rrK)EIT)5'hk6#mZ!!KKr`!!!SK+J'F%F!"J-N(YqNJV52T!3Uhk4%(\rYqN`V52SX3Uhk-(!#+d$k0(!%+d$k1%(YqN!V52Sm3Hhk,#!)6Pj1G!!%M@GPG'K\r[Fh4LH@jKE@8!!#T46PErp#m05'hl6%KYr[`LEIcS)&P1N!!UE[r`5-!Y32rd)#l\rrp%jH6R@,Eh"PEPpNFQPfCA)!!#T46PErq#m05Uhl8'F1)Qhl8#"C6T!!+Qlrp'!\r#F!"1ANjeMh9cCA*IB@*[FR4IC'PcF!!!+P&19[ri51F3*#4Z!!Kf!!a5!!&R"M!\r55-"J('(rN!5`*J"R"#!$B!iLEIe`)&P1N!!UE[rdB0K-h`3)6Pj1G!!%L(GKDA4\rICQpb!!!!+P&19[ri51F3"%TYqdaQ%Q(rN!3f*J"+JfF')!0J!!#`5(J!CN+R5'h\rla#*YrM3J@8k3!#TZrr3lEIY-qp`lI!!QqpiVEJ!)qq!EI!!Hqq4#,I[P'hcr`2[\rQ5'hla#*Yr@`J@8k3!#TZrr4)EI[8BIq3"%3Q!%Ki!'C#TdKYqm3LEIid)&P1N!!\rUE[rd1fhl62[F1h`!+[[H+fi!#2[J5'hla#*YrC`J@8k3!#TZrr4+EI[8CK![,I[\rN)QhqQ#"C6T!!+Qlrp%U$CJBf,I[85--J!bBI6Pj1G!!%N!"dBh"IBfa[Ff9IFh4\rbC@&Y!!!!+P&19[ri51F3"%TYqdaQ%'(rrrrq5LB!5S0R"(!!B&C)H!"Q3UG)EIY\rH)Qhq0#"C6T!!+Qlrp$YYqdclGMYm!#MlH#YZ!!MlHNKYqeiLEIeX)&P1N!!UE[r\rd5'hlEQ(rrrrqDLB!5S0R"(!!B!T+EIZD9X"%!%R!*Kp1ANjd!!5,G'0`Af0KER*\rPB@3!!#T46PErq%MR%$3QEJ!-5Uhl9'BN5'hr!L*Yr[JJ@8k3!#TZrr4)`#B!5S0\rR"L!$B!!!RR!"+d$l9(!3,`")H!2!,bhqk#*Yr8JJ@8k3!#TZrr3N3$Ym!!(lA%K\rYqe`[#LmYrZ`[,J!))Qhqp#"C6T!!+Qlrp#"YrZ`-N!$rrkAqCK")EIYFBIrrrrf\ri)'hql##!,`SLEIdS)&P1N!!UE[rd)'hql%U3!'F))'hql#!3B#)JEIlX)Qi!%#+\rS!33J#fF3)%XLEIlX3qN!"#!)%0PQr(!!60m-#%jH6R3!$)pZFepbCA0[E(CPAfj\rKE@8!!#T46PErq#"Z!!JLEJ!--UJ!!NjH6R3!#)abCA0[E(CPAh"bEf-!!!!U88j\r@rrK)j`!N$'i!!3!1CKJNEJ!3,bS!##mZ!"!LDJ!%)&P1N!!UE[rd*&p1ANjd!"#\r+G@4`Afj[G'PQH3!!!#T46PEr[%MR%$3QEJ!)GJ"+EIY-CK*Krrrrr'BQ!%U$C`B\rJ!f!!!-4)H!!k3UG)E[qq)Qhq0#"C6T!!+QlrZ%Ki!!`LEIkF)&P1N!!UE[qi*%!\rJ#QB'F!aJ!!#52A`!&2rB2@hl62r@,@i!%2rH,@i!&2rL5Uhl@'BFF"![!%Ki2X!\r[,IlN)Qhp5#"C6T!!+QlrZ#Y!qeJYEIYBrqBp8rrU,8Vrl%KZrliLEIeX)&P1N!!\rUE[qi5QlrcQF@,`SLEIkB)&P1N!!UE[qi-#lrcNM!B"`NV[rD*@i!(!!%*@i!$!!\r))'i!'##+0UlrkL!$60m-#%jH6R3!')aeC("IFQ9RDA0dCA)!!!!U88j@rkJ[$8K\ri!$T#TdKZrliLEIid)&P1N!!UE[qN2@i!'[qb,@i!&2qd3QlrZ#eZ!!MrUMem!"I\rrf$eYqdcreL"ZrkSY82rD,@i!$2rJ2@i!%[rN(A`!!IrU3HlrXLe)rqC)E[qq)Qh\rpE#"C6T!!+QlrT%KZrmjKrrrrqfiY32qZ)#lrVNjH6R3!&)jeC("IFf9ZC&pNCh*\rKE3!!!#T46PEr[%MR'#3S,J!B5(J!1N+R5'lr[L*YrM3J@8k3!#TZrlJNEJ!)2A`\r!&IrB2@hl62r@,9,rfR!!%#hl6Me!rpj)E[qq)QhpE#"C6T!!+QlrZ%KZrmjKrrr\rrq[)Q!%U$C`3J!f"dF!!`,[rUZ)"X"#!%B!C`!$!ZrqSLEJ!8)'lrjR)JX)&P"+)\rZB!j+J'F+)JN5f&1!C[SL3A!!-#lrkL"Z!"`JJ#"Z!!`JV[rJ)'i!%$#Zrq3pI!!\r@rpK)E[qq)QhpE#"C6T!!+QlrZ%KZrmjKrrrrqRJQ!#!$60m%'%jH6R3!')eeC("\rICf9dAf4RFQ&Y!!!U88j@rlK)j`!N5(J!1N+R5'lr[L*YrM3J@8k3!#TZrl3NEJ!\r)2A`!'2rB2@hl62r@,9,rfNKZrliLEIeX)&P1N!!UE[qd5'lrcQ(rrrrk$#e!rlS\r[#L*YrTJJ@8k3!#TZrl3NAdjH6R3!")YeC("IFQ9XC@&cC3!!+P&19[r851F3"(B\r!5Qhl6'B-BIrrrrPJ*J"+JfC!5(J!*%+R5'lre#*YrM3J@8k3!#TZrp!pI!!2rqi\rpEIY-rqa)E[r8)QhpE#"C6T!!+Qlrd%TZrq4Q##"Z!!JJV[r`*Kp1ANjd!!51Cf9\rdAfejAfP`Af&NC()!!!!U88j@rrK1ANjeL'jPG&pTC'aP!!!!+P&19[ri51F3"%U\rYr#TR"(!!B'4)H!N!)QhqR#"C6T!!+Qlrp#Y!r#T+VI`UCK"`$#Y!m%JlI!!-r,j\r`rf!k5(J*!%+R,bhm+L*YrM3J@8k3!#TZrr4f!'!B)!-'J!!!!)"b5%`$'!!JEI`\rU)B!B"&+$F##fJ'hLF!!Q(djH6R@+BfKPBfYID@jTG!!!!#T46PErq#m$BIq3"'a\r+J'F%F!"J-(B!B#4`5%`$#!!JEI`U#$!!"`J!CK"`5%`$#!!JEI`UdF!J#'!+8S0\r`),D!EGC`!#BI6Pj1GC&RCA4IG@jeFf9NAh0[BfYPG!!!+P&19[ri*#i!#()!B#*\r`5%`"#!!JEI`UY,!)"'B3F%K-!3J!)'hm+Y(!)!KJ#P+"F##bJ'hBF!"1ANjd!!5\r,CQPZC&pcEf0VCA3!!#T46PErq%MR!#3NEJ!)5(J!"%+R,`SLEIid)&P1N!!UE[r\rd3US!1%UU!$4R%#mU!$3LEIkB)&P1N!!UE[rd3US!0%+U!$!NAdjH6R3!")jbC@a\rPBA0PAh0[BfYPG!!!!#T46PErq%MR(#3Q,J!)+Li!$#JZ!""`!VD!CJT+K'FBF!+\riJ'F5F"BV32")1h`!&[bqF2pJ!!#bF!+kJ'FBF!'kJ'F5F"BV32")1h`!&[bqF2p\rJ!!#8BIrrrrkJ*%!J#QB3F!`V32")1h`!$2bqF2pJGM9$!!Je3`!B08-!+$9%!#S\rP43!X5US!0'Bb5(J)!#*YrT`J@8k3!#TZrr3P3!!d*A`!!!J!!$"+UJ!dCK"`$#Y\r!m%JlI!!-r,j`rf!U5(J!"%+R,`SLEIid)&P1N!!UE[rd!")!J!*5J(m#+J$[!!&\r#UJ!i)#S!"%cI"$K1ANjd!!b'FfpMDf9d!!!!+P&19[ri51F!*#4Z!!`)%J!(CK"\r)EIm))Qhp4#"C6T!!+Qlrp1R5!%K531r5!%JNAdjH6R3!#*4cEf0VCA4ICACPER4\rID'&ZC'aPFJ!!!#T46PErq%MR'$JS,J!3+'i!'#mZ!!KKrrrrrIBN3#!+CK*`&LY\r!m%JlI!!@r,j`rf!!!-*`!V#U!#aQ#!aU!!)!#'F5F"BV32")1h`!&[bqF2pJ!!#\rJ5US!1'C),bhqi%KU!$J[+J!`,bS!0#m+5'S!#Q(rrrrj&LB!5S0R&Lm+BIrrrrh\rBF"NV32")1d2m[R$rB'")DJ!-BIrrrr[k!#S!%!!"F"#`VJ!FCJB-9!!#Ca"`&LY\r!m%JlI!!@r,j`rf!b*N`["#mZ!!``+`!#,`![+`!%,bS!1'(rrrrjY#B!5S0R$R!\rC+d$`5$Y$r,j`rf!#)!4-ha`B6Pj1G!!BKR0PEQ4dE`!!!#T46PErp%MR%$!QEJ!\rF,bi!#'(rrrrmmL4!)!TQ%R!@+d$`5$Ym!"Em[R$rB!!!LR!#X+S!,'B)$'S!!J!\r)Ca"`&LY!m%JlI!!@r,j`rf"SF"#`Nf-3F"BV32")1h`!&[bqF2pJ8R!3*S!QEJ!\rB0V`!!NKZrr3[,J!3,bi!$%KV!!*)D`!%,bS!1'(rrrrjPLB!kG)!5'F+kG)!5&0\r!lp)!5%U$CJBJ,[rdB!a`'5Y!m%Jl3rbqF2p-h``)6Pj1G!!BL(*PBhCQFQpY!!!\r!+P&19[ri51FI2#SZ!!JSEJ!-*Qi!%#iZ!"3NEJ!B)!TQ"(cqB#3LEId3)&P1N!!\rUE[rdFMa-%K!!dS!J+J!%6(`!N!4"'Y#",!")H!!J3UG)EIb1)Qhq0#"C6T!!+Ql\rrp%Ki!#"#TdKYr'iLEIid)&P1N!!UE[rd5(J!)%+R5'hm6L*YrM3J@8k3!#TZrr4\r)H!!J3UG)EI`Z)Qhq0#"C6T!!+Qlrp(J!)!aQ"%RYr#iJ#fB%4qhm,NU(CJC"lI`\rZ,JKf!'!!!+)J!qU))J0d(m+#G!(MUX5c$!"R(L!$FKr!JA)"iDNJ!qU)3HhmEN(\r`$!!J%)#"))"5K#!$kSJL!h3I`S*d!H1Ua,3-!'GBF)$3Jh)JX)&Z6Lm$BIrrrrX\rJ*%!J#QG!#")!"fFkkG)!5'B@F!'`UJ!XCL`[+J!mBIrrrr5D5S"R(L!$FKr!JA)\r"iDNJ!qU)3HhmMN(`$!!J%)#"))"5K&+$YS9Y!2pF5S4Q*#*YrA!J@8k3!#TZrr4\rKrrrrqESLEId3)&P1N!!UE[rdX)CP!2mZ)!9HJ#B!j)2JLq#,i)[ULpD!jS0`),D\r!B`*f)#*-3HhmML!$FL#`J@8%SLjJ$NU!C`SL#4,B8i"QqL*")NY"lIaZ)!0b),#\r"C35L,Q!15S"R#L)*%YK6J'Ek)N%L4d(Yr%iJ!h)JX)&P"+)ZB!j+J'F+)JN5f&1\r!C[SL35!%60mFq%jH6R3!&)CcC@aPBh3!!!!U88j@rrK)ja!N*Li!#!b$!!!!J'`\r5,`-LEIh3)&P1N!!UE[rdB!!!RLm$BIrrrrRS*%!J#QB'F!"J!!#+)!TR$JJ5!!G\rR#!aU!!)!+'F3F"BV32")1h`!&[bqF2pJCL!U!#a6J'F'8i"R,Q!q5US!2'G),bS\r!2'(rrrrb6LB!5S0R1(!C+d$`5$Y$r,i[#Q(rrrrjd($rB#a+UJ!iCa`[+J!iBIr\rrrrH!B""`&LY!m%JlI!!@r,j`rf!+,`TKrrrrqD*`!%cI"!K1ANjd!!5-FfpMDf9\rdAf0XEh0P!!!!+P&19[ri,`e+VIbZCK4)H!,))QhqR#"C6T!!+Qlrp#Y!r+j+VIb\rbCK4)H!!8)QhqR#"C6T!!+Qlrp#Y!r,*1ANjeLh4dAf&XE'pMBA4P!!!U88j@rrJ\r[$8UYr+jR%#mYr+iLEIkB)&P1N!!UE[rd3UhmVNUYr,*R%#mYr,)LEIkB)&P1N!!\rUE[rd3UhmXNjH6R@(G(4ICR*PC3!!+P&19[[S,`e"l[[i)Qi!%#!)%0PQr%KZqrJ\rLEIeN)&P1N!!UE[[N5'llkNKZqr4)E[[b-#i!$Lm!,bi!##*Yr43J@8k3!#TZqq4\r)E[[i,bllp#*Yr63J@8k3!#TZqq41ANjd!!b3!(4dAh0PG&pTG'9YAh4PH(3!!!!\rU88j@qqJ[$8KZqqT)E[[d5'llmM!Z!!i[!#mZ!!JLEId8)&P1N!!UE[[N5'llq#m\rZqr3LEIdN)&P1N!!UE[[N5'llq#*Yr33J@8k3!#TZqq3JEJ!33qllq#!)%0PQr%j\rH6R3!$*!!G(4ICf9dAfPdC@eIG'9iG!!!!#T46PErj%MR%$`SEJ!)*'i!$#CZ!""\r`!$!59i"R$R!!-"*EJ'F'F!"J!!$Z*LS!!J+$!!!!r`b$!!!!!fF8$)-!!!!0C``\r-J`!!!"YRCQ!!!-Bf[!!"5'lrkNKZrr4)E[rbF!%[!#m-)Qhp&#"C6T!!+Qlri(!\r+,`![,[rd)Qhp'#"C6T!!+Qlri%KZrqC)H!!))Qhp$#"C6T!!+Qlri(!!,`![,[r\rd)Qhp'#"C6T!!+Qlri(!"B'3f[!!#5'lrkNKZrr4)E[rbF!)[!#m-)Qhp&#"C6T!\r!+Qlri(!+,`![,[rd)Qhp'#"C6T!!+Qlri%KZrqC)H!!))Qhp$#"C6T!!+Qlri(!\r!,`![,[rd)Qhp'#"C6T!!+Qlri(!"B!*`!%cI(!K1ANjd!!b0G(4ICA9TAfCTE(4\rPFJ!!+P&19[p),`e#V[p@3UlrA%KZrdSLEIeJ)&P1N!!UE[p%5N"R"($rB#j#V[q\r+3QlrQMeZrf$rP%+Zrj!!5'lrIL*Yr2!J@8k3!#TZrd4+3'F%F2pJ"#!Zrja1ANj\reQ(4dAfGPG&pfEfaIBh*PBA4TEfjIC'&dC3!!!#T46PErj%MR!$`SEJ!)3QlrpNK\rirrp#Tc!m"%`[!#*Yr5`J@8k3!#TZrq!Q3#!,CJC`rf!!!9SJ9%)3)&4#+!"N,a4\r`"#m!,`YKrrrrr53J9%KS!'4`"Lm!,`YKrrrrr4*`%#m!5(J2d#mYrYJLEIe))&P\r1N!!UE[rJ*%")E[rU)Qhp9#"C6T!!+Qlri#m,)Qhp6#"C6T!!+Qlri%KZrqj)E[r\rN5'lrk(!",`![#b*Yr43J@8k3!#TZrq"`!bm!F!-[!#*YrE!J@8k3!#TZrq"`r#m\r!F2`[!%KZrqiLEIh!)&P1N!!UE[rJF"![!(!3,`")E[rZ)Qhmb#"C6T!!+Qlri%K\rZrrB[#L*Yr13J@8k3!#TZrq!-EJ!"rrCR#!aZ!!,rpQEH,`SLEIdS)&P1N!!UE[r\rJ$'i!!IrfCL`[&(!%,`![#f(rrrrmU#"85'J!C(!',`![#f(rrrrmPQ(rrrrq1#"\r8)8!!b#m,)QhpH#"C6T!!+Qlri#m-)QhpD#"C6T!!+Qlri#m-)QhpY#"C6T!!+Ql\rri$!ZrrC)`%cI(!"1ANjd!!54G(4IC@4TG&peFf9bAfPZCQm!!#T46PErq%MR!#3\r`2!4-,`![2(4dG@NLEIdm)&P1N!!UE[rd*%"+J'C85(J!c#*Yr3!J@8k3!#TZrr3\rN3%KYre)`2!4-,`![2(4dG@N[#L*Yr6!J@8k3!#TZrr4)H!$-3UF[%L*YrM3J@8k\r3!#TZrr3[#Q(rrrrpjP1!CbT`rf"D$#i!!3!2C`jKrrrrr9SJ8V#S!-KR%#m+BIr\rrrrh!8i"R"($rB$3LEJ!))&)J2!!!!-ab),#"C35L,Q!15S"R#L)*%YK6J'Ek)N%\r[#L*YrB!J@8k3!#TZrr4`!#4I6Pj1G!!)N!"dG&pRCA4IGA0PFPpTEQC[!!!!+P&\r19[rN,`e)E[rSF!%[!#*Yr0JJ@8k3!#TZrq!p32rQCb)`,[rQ5-![!%KYrfB[,J!\r))Qhpp#"C6T!!+Qlri%r[!!aJ8$!Zrr4)`#m!F!!3,[ra,`"`!"!Zrr![!$!Zrqj\r)`#m!-#lrl%M!,`!`,[rU5-![!$!ZrqK)`#m!5'hrK#mZ!!JLEIhd)&P1N!!UE[r\rJ6qm!*%jH6R3!"*0dG&pRCA4IFhPcAf9ZGQPbEfjc!!!U88j@rr4)j`!N-$`%6#m\r!,ca$8e45)Qhp2#"C6T!!+Qlrm#4!5S"R4Lm+)Qhp[#"C6T!!+Qlrm#m5BIrrrqS\r5,8$rp'F1)'lrp#"S!"!J8#Y3r,B[#L*Yr0`J@8k3!#TZrr![#L*YrB!J@8k3!#T\rZrr!NAdjH6R@8G(4ICf9dAh0PFRCPFPpTF'&NC()!!!!U88j@q"K)jam%&Li!&bJ\rZ!"Kk!(i!)QhpU#"C6T!!+Qli&$e!rYi`,Ibm,`!LEIcd)&P1N!!UE[J8F!'iJ'm\rD)Qhp%#"C6T!!+Qli&%a%!!&+J@F'F!"J!!*L5UhmYQB5BIq3""C+VIbfCJC`!'!\r!!NT)E[VHBIrrrrj3GJ"+!fFX%#i!%bm!5'lqp'(rrrrp5%U!Cb3`,[lH,`!LEIc\rd)&P1N!!UE[J8F2pJ!!)13Llqp%)ZreK#V[qmBIrrrrK#5(J#b%+R,bhmVL*YrM3\rJ@8k3!#TZq"3JEIbZ-,`!!5"Yr+iaI!!"!!)JEIbZ-A`!!3!%5J0R"(!"B!*`!#"\rYr+ia3!!')Qhp%#"C6T!!+Qli&#"Yr+iK3!!)5'lkhNKZreK)E[ld5'hrd%KZq#)\rLEIhd)&P1N!!UE[J8)'hmXL#Z!!JJEIbb)@i!$!!%3HhrfL*Yr,)M5!!)3Hhr8#*\rYr,)M5!!-3Hli)L*Yr,)M5!!3,bhmXLmYr+jKr`!!!PiX!%+R5(J!!NKi!!*Krrr\rrm9)Q!$em!!,r`$em)66r`LeYr,Era%Ki!"")E[r!3UF["LmYr+i[!f(rrrrbF(S\r!6qm!&%Ki!#"#TdKZrp!LEIid)&P1N!!UE[J8)!0b(m#"FJ(KU5!$kSK"l[r33I!\r-!#!3J)%JJ(!&,8$rm%+Zrr4)E[r`3UG#TdKZrp")H!%!BIrrrr2Z+!"+K'BB5(J\r!%%KZrm"#Tbm',bhmVLm$BIrrrr(k5S4Q#&+&F!1kJ'f%F!'iJ'C@F"!Y32JH5'l\ri(NKZrm"#TdKi!XJ[,IbZ,`0KrrrrmY!S!#"Yr+i-D!!%!!CQ+%KZrZ![,IbZBIm\r!!!#L)'lql"!35F!%J!!!!&*R!Q!#I[mYE[l`q"S[!f(rrrreK'(rrrrfUM!ZrYi\r[!#*Yr23J@8k3!#TZq"3J"dcI!2K1ANjd!"5+G'9cG&pdFQ&MD`!!!#T46PErq#m\r-)'i!##*Z!!`SEJ!3)Li!&'!++-Lab@3%5KKQq#!"8i&+J'EZ+&p1ANjd!"#3!(C\rIF'&bFf9IF'YdAf4KG'%!!!!U88j@rrK)H!!&,bi!$#"Z!!K)D!,()'i!#%KS!!a\rKrj!%QNjH6R3!#)YfAh"KFR0PAh"VG!!!+P&19[ri51FB2#4Z!!JSEJ!-*Qi!%#B\rZ!"3S#Q!f5T0Q"%)DB"BJ6*(+,`J[%bm+)Qhpm#"C6T!!+Qlrp%+R,`SLEIhS)&P\r1N!!UE[rd)%"5L#4)@)XJ!e1$5S"Q`L"+NF3J#%cI("K1ANjd!"#6GPpKFh0PE@*\rXC9p`Dh4IC'&dB3!!+P&19[ri,`0f"5m$,bi!$#"Z!!K"k!,)NF0)8#"Z!!K)D!!\r-BIq3"&Tb$0#"*Kp1ANjd!!L1GPpKFh0PE@*XC9p`Dh3!!!!U88j@rrK)jaJN*'i\r!#(B!BIm!!!&`)QhpU#"C6T!!+Qlrp$J!F2mV32bkF!'`UJ!-CM"`!5m!,bS!%#*\rYrD3J@8k3!#TZrr4)`#Y!r,T`rl#Yr,TQ$L*YrBJJ@8k3!#TZrr3f!#m%)Qhmp#"\rC6T!!+Qlrp$!$60m%'%jH6R3!"*&IAfPZDA4TB@aTHQ9I9&466!!!+P&19[ri,`e\r`rl#Yr,TQ%M!Yr,`[!#*Yr9JJ@8k3!#TZrr4Kr`!!!2a1ANjeN!"IAh4PFQeTEQ&\rdC9p89&0-!!!!+P&19[ri-#hm[NjH6R@3!%GPG%*64%eKBdp64A*bEh)!!!!U88j\r@rrK`!%jH6R3!")j*ER0dB@aX3fpZFfpXC3!!!#T46PErq%jH6R@08Q9YEhCP3fp\rZFfpXC3!!+P&19[riF!"1ANjd!!L69h*TG'9$D'&bFe4[3fpZFfpXC3!!+P&19[r\riF!"1ANjd!!L88Q9KC%0SBA*c4R*[E80[ER0[E'8!!!!U88j@rrK1ANje+P&19[r\ri,`dJ$5m!,bhqa#*YrV3J@8k3!#TZrr3V32c!BIq3"0C`!%jH6R3!"#T46PErq#m\r0)Qhq[#"C6T!!+Qlrp#mYr-!LEIk`)&P1N!!UE[rd6Pj1G5T46PErq%MR!#4J'L"\rYrX!JNR$r,`![+J!))QS!"#"C6T!!+Qlrp#"YrX!N8#!+CY`NAdjH6R8U85m-+'m\r!##*[!!a`!#"YrVKJ%%U3!'B)))`K53!%B!j5J&#)$)!!!!#!EHK`rbKI6R3!##T\r4)Lm!"%U"E4J-J3!!!)"X%#!"jiJJEIkidF"#N!"#U!!%6R3!"#"[!!4`!*!!V`!\r-)8!!"(!!)Lm!#*'"))"1G!!-)'m!"#![!!b3!+m!&#&!!!3J,`!))Lm!%*'"))"\r1G!!86PErk%MR(cJU,J!)*'i!$#KZ!"!QEJ!85T*Q#%UU!!4R!!$@GJ"i!#"&,"!\rYD!!%rr3Y8[rX,@S!"2rSIJ"k!%+Zrr"J!!#8eS-J"!+!J!!!!'F%F!''J0L%)!B\r#J)!!!!"R"(!"L)$FKL!Zrr3#J)!!!!"R"(!"M)!J,[rdd)!Y32rdhSFJ"3+!J!!\r!!'F%F!'1J0U&YUlrl')-YUlrl'BdZ+lrk'8ZF!'+J#e$rrJY42rm,bS!"#mU!!!\r[,[rm,blrq%KZrrKKrj!%&LBZrrJS,[rm8Ulrm("!X+lrm'i!rfBJ$'F'+)FT43!\r%)!YR"LD$*d3!"%cI(2K1ANjd!""19J!!,`SNEJ!)3UF[#NKZ!"4)EJ!-BIrrrrl\rQ)!SNAdjH6R3!&%j@!!![#L4Z!!J[#N+R5'i!&%KZ!!aKrrrrrX!J#L4I6Pj1G!!\r8)#m!",#[!!aR#'85F!&1G!!3)#m!#,#[!""R#'6ZF2p1G!!3F!"1G!!3*#m!##!\r[!!3L,`!-P+m!%*'"C`TY"R!"6R3!%($r6R3!%#"[!!3J,`!))8!!"!J!!"pR#($\rr))"1G!!)F!!JJ%jd!!JU88j@rrK)j`!N5(J!!5*YrR!J@8k3!#TZrr3JEIkN5T!\r!CKJ[,IkJ)Qhq)#"C6T!!+Qlrp#"YrU4`!5#!,bi!##mYrU!LEIiF)&P1N!!UE[r\rd*%")H!!")QhqE#"C6T!!+Qlrp#!+*&p1ANjd!!3U88j@rrJ[$5"YrU4+N!"R0%K\ri!!%LEIj`)&P1N!!UE[rd,bi!##mYrU!LEIiB)&P1N!!UE[rd5(J!!5*YrQ`J@8k\r3!#TZrr41ANjd!!3U88j@rrK)ja!d*'i!##CZ!"!Q,J!83T)PEJ!-!!3#+J!I!!J\r#+J$[!!K#+J!-3LS!$8+U!"*+JfFB,`0)H!!#,`X[#L*YrR`J@8k3!#TZrr4J&%+\rR3UG#Tbm+)QhqI#"C6T!!+Qlrp#9U!"B!(N+U!#,TkJ(#!!46J'F'9B"R('!`*@h\rq8!!b*@hq@!!f*@hq9!!k*@hq6!!qB"C#UJ!b*@hph!!f*@hpf!!k*@hpe!!q3US\r!3NcI$!K1ANjd!"!U88j@rrK)ja!N5(J!!L*YrR!J@8k3!#TZrr4f!#4YrYaJ)ZR\rU!F)!"'F8,`SLEIjN)&P1N!!UE[rd!QVqI`!%8S0`4YA!F#1fJ'hB5(J!!L*YrQ`\rJ@8k3!#TZrr4-h`3)6Pj1G5T46PErq%MR'#4i!(B!*'hqh'!LkHS"`J!%Ca3[#L*\rYrQ!J@8k3!#TZrr4+J'F#H2p5Jh"'eF"`)lD!EGJJ"%cI""K1ANje+P%[$#K[!!J\rLE`!-)%`L%@!B$"!!$@B'%,`!#Q!+$"!!#QB%%,`!$9+))!&6J8U!CZ!SAdjd!!J\rU85"[!!3KD!!@!"iKD!!D!#)J+!!5`+J!*T'S!#)KD!!5!#j1G!!%+P&19[ri51F\r30#4Z!!JQEJ!-)'S!(T(U!"BQ#%U$Ce3P3`!L##S!"J!&CK4)DJ!L,bS!&L*YrSJ\rJ@8k3!#TZrr3[+J"#5'S!)LmU!"B[%L*U!$SJ@8k3!#TZrr3Q!#!,C`3QUJ!L5S0\rR"#!$B"JJ+J!LdDS!%Lm+)QhqK#"C6T!!+Qlrp(!!60m-#%jH6R3!##T46PErq%M\rR($3NEJ!)*Qi!$#BZ!"!S,J!8kHT4`J!%kHS!!`!)CJ4+K@B'F2pJ!!$+5S0R%R!\r"YS"R$(!#YS"R"R$rB!!!Y%UU!"CR'!JU!!3!#'F3,bS!&L*YrTJJ@8k3!#TZrr6\r[kM&#!!3#+J$[!!JJ5P#)A)JP5!!@)%T3L&b)*8J!(R!"*8!!'N+U!#*#UJ!Q5S0\rR"R!"Z)"N#L"U!"j#%(!!B&)J#fBH,`3LEIkF)&P1N!!UE[rd*N"+J'B%F2pJ0J!\rU!"!!##9,!"BPDJ!@!"iP4!!D3US!*ZRU!F)!"&1!CK)J"!+!!!!"rfB)*A`!!!(\rr!#C`!%cI$$K1ANjd!"!U88j@rrK)jaJN+#i!##4Z!!cTkM(#!!4#UJ!L5LS!$@B\r%5S0Q"R$rB!!"%(!#YS"Q$#*YrL3J@8k3!#TZrr6TkJ!$!!KQ81RU!)-!"()#`)&\rR41RU!)-!"()%`)&R(NKi!!*#Tbm+)Qhq1#"C6T!!+Qlrp%U!C`C`!'!!!-!#+J!\rI!!J!+J!J!!J[#L*YrS3J@8k3!#TZrr6TkJ!$!!K6!'F3&A`!!3!03US!)R$rB!!\r!M1RU!8)!"&8!C`iJDJ!HNHS!&V(U!"TQ)N+R,`SLEIk!)&P1N!!UE[rd5S"R$K9\rm!!%!$8+U!#*`rf"38kS!)L"U!"j5UJ!H%)6TkJ&#!!49!'FdkHS"3J!%C`C`#VL\r!CL*#Tbm+)QhqJ#"C6T!!+Qlrp%U!C`i9I!!"!!e#UJ!LF2pJ#%+U!#*`!"!%60m\r%'%jH6R3!##T46PErq%MR%!4f!#"YrR4`!E#3!'B%F!&JCNKi!!-LEIj`)&P1N!!\rUE[rd)'hqG%U3!'Bm)Qhq*#"C6T!!+Qlrp(!!,`!LEIl8)&P1N!!UE[rd5N"R#L"\rYrR4`!L#!B")JEIkS)+hqd#"YrR4`!5#!GJ&)H!!$)QhqE#"C6T!!+Qlrp#!$*Kp\r1ANje+P&19[ri51F!*#4Z!""Krj!%E%U!CJ4`!@!d)'hqh%KS!%BLEIjJ)&P1N!!\rUE[rd,a)[,J!-)Qhqb#"C6T!!+Qlrp#5!F2q`NQB%F!&J!R!!*&p1ANjd!"!U88j\r@rrK)j`!N*'i!%'(rN!385S"Q"(!"B#![%LmZ!!`LEIl-)&P1N!!UE[rd*)"`rl#\r5CJ4`!@!#F!!NAdjH6R3!%#T4F!"1G!!%+P&1G!!%+P&1G!!%+P&19[rd51FI2#K\rZ!!JX,J!-+#i!%#4Z!"3Q"N`%-!"+JfF15LS!$@B)kHS"`J!%CJC`!'!!!LETkJ(\r#!!49J'B-)Qhq*#"C6T!!+Qlrm!JU!!B!"@FLkHS"`J!%9i"R'1RU!8)!"&8!C`l\rTkJ&#!!46!'F%F!"J!R!"+J$TkJ!$!!KQ81RU!)-!"()#`)&R41RU!)-!"()%`)&\rR(NKi!!*#Tbm+)Qhq1#"C6T!!+Qlrm%U!C`C`!'!!!D3#+J!I!!J!+J!J!!J[#L*\rYrS3J@8k3!#TZrr$TkJ!$!!K6!'F3&A`!!3!03US!)R!!B!!"F#C-H!"+JfF!!2!\rJDJ!HXHS!&QB'5S9R!!$J)'S!(T(U!"BJ+J!DN!#)*8!!)TR-,@S!)[rdYUlrp'3\r%,82rp1RU!8)!"&-!CLa+V[rdCbB[,[rd5(J!#Lm,)Qhq,#"C6T!!+Qlrm#K!5S"\rR#L"-8SL4bbe)rr4+V[rdCciLDJ!H)%XJ,[rdFL#`J@8%SLjJ$NU!C`SL#4,B8i"\rQqL*"eqlrp0LZrr5@V[rd)#lrp0'U!"iJ,[rdNDS!)NUU!#*R$#!-CJMTkJ&#!!4\rQ*%+R,`SLEIk!)&P1N!!UE[r`,J"+KfF1&A`!!3!03US!)RB!B!T+JfF'5S9Q!2m\rf5S0R@NU&CPBSDJ!@+LS!'L9,!"BP3`!D)%[4`b9)!"j)E[rd,`SLEIk!)&P1N!!\rUE[r`5S"R#K9m!!%!$8+U!#,BV[rd*8`!&L9&!"S[#L*YrS3J@8k3!#TZrr"#UJ!\rLkHS"3J!%93"R"%+U!#)J"0#'8i"-4J!!60mFq%jH6R3!%#T46PErq%MR'#3NEJ!\r))!TQ"($rB&VTkJ(#!!4Q"(!!B%i[#L*YrQ!J@8k3!#TZrr3Q!#m5)QS!2L"C6T!\r!+Qlrp#J!!QVqI`!%3T))+J!%!!KR%#mU!"BLEIkB)&P1N!!UE[rd5S0Q"%U%C`4\r`rf!#F!"-h`3B6Pj1G!!%+P&19[ri51F3*#4Z!!JJ#QB3)QhqM#"C6T!!+Qlrp'!\r!!+"++J!0CJMTkJ(#!!4Q"R$rB!!!M1RU!!-!#!`!!!0P$!)U!"m!#!!U!%!!#1R\rU!!-!#&8!CJ4#UJ!LkHS!!`!)8`"R#J)U!"m!#(!!B&$TkJ(#!!46J'B5,`SLEIj\r!)&P1N!!UE[rd*J"J!RB!3UF[#L*YrS!J@8k3!#TZrr4+J'F1&A`!!3!03US!)R$\rrB"!#+J!I!!JP3`!53US!)R!!60m%#%jH6R3!"#T40#m!"R)!)'hqA'!1Y&"Q"#!\r)B!j5JA")dF"`)l+!EHa`!%jd!!3U88j@rm4)ja!m*Li!##KZ!!`NEJ!3*Qi!&%+\rZrp)p3rrH,8crjLe5rqT#E[rb)!YR*%KZrmBLEIc3)&P1N!!UE[r!B!SL5b"C6T!\r!+Qlr`%TZrpCZm'!35'lraL*Yr1!J@8k3!#TZrm!NV[rZ$'lrfIr@CJa+NQF%F!"\rJ%(!#B!a+E[r@CJ4`!'!#F!&-ha`)6Pj1G!!3+P&19[r%51F32#BZ!!JSEJ!-*'i\r!%#CZ!"4#V[r5282rhLe-rqBY8[rU3QlrmL!,Cb4)E[r')QhpA#"C6T!!+Qlr`'!\r+)NXJ@8k3!#TZrm"+E[r@E["J%%KZrmBLEIfJ)&P1N!!UE[r!*+lrlNTZrpCQ"(!\r!B!*`!8cI(!K1ANjd!"!U88j@rm4)ja`d+Li!##CZ!!`S,J!3*'i!&%+Zrp)p4Ir\rH)!4R$P@!C`*J%$em!!,rmQ!12A`!!IrbB!C`!@!!!4!Y8rrd)!TR*%KZrmBLEIf\r%)&P1N!!UE[r!B!SL5L"C6T!!+Qlr`%TZrpCZm'!35'lraL*YrCJJ@8k3!#TZrm!\rJ%j!!V[rd*J"+J'm!!,BJ,[rdd)-Y32rL)!TR*%KZrmBLEIe!)&P1N!!UE[r!B!S\rL5L"C6T!!+Qlr`%TZrpCZm'!35'lraL*Yr2JJ@8k3!#TZrm"+E[r@CJ4`!'!#F!&\r+J'CL3UlrdMe&rpiJ"'F19B"R!Q!32A`!![rbB!`pI!!"rr*J"(!"B%`Y8rrd)!T\rR*%KZrmBLEIf%)&P1N!!UE[r!B!SL5L"C6T!!+Qlr`%TZrpCZm'!35'lraL*YrCJ\rJ@8k3!#TZrm!QV[rd5QlreQB%F!"J!R!"60m-1%jH6R3!%#T46PErI%MR%#3Q,J!\r),`0Krrrrr9SN3$e$rjC)E[pq)Qhp8#"C6T!!+QlrH$B!CLSJ#QFQ)%T3L#e)rj!\r!2@S!![q8,@S!"2qZ5'lrIL*YrA3J@8k3!#TZrhJf!#!+C`*#8NT$CJ4`!'!#F!&\r-h`3)6Pj1G!!%+P%LE`!%kHN4`J!%$!%!!@F'$!%!!QB'5LN!$@F-)'hq5(!M))"\r`rf!dkHN!!`!)CJBJ+3!5B#BJD3!HNHN!&L)T!#l5L1RT!!-!#!`!!!0P#ZRT!!-\r!#&@!NS!J!8jd!!3U88j@rrJ[$5mZ!!JLEIj%)&P1N!!UE[rd6Pj1G!!%+P&19[r\ri51FB0#4Z!!JQ,J!3kHT"`J!%$!3!!@B'5LS!$@F1)'hq5(!M))"`rf!!!4ETkJ!\r$!!K6!'BX3UF[#L*YrS!J@8k3!#TZrr4+J'FB&A`!!3!03US!)L"YrNK`)b#!F2p\rJ!!$JF!'fJ'B@GJ![#L*YrN3J@8k3!#TZrr3S!0QZ!!a`!VD!CfETkJ#$!!4A!'G\rFkHS!!`!)93"R#ZRU!!-!#&F!CNJJ,J!-X+S!%Q3+)#i!$,#U!#jN#!)U!"m!#'!\rb)#i!$*!!UJ!Z)'S!&Y(!*8J!(L!U!"+3!+i!$#9!!#)#+J!I!!J!+J"!!!KJ"J)\rU!"m!#1RU!!-!#'C'*QS!-L!,Cc![+J"#,`0)EJ!-,a)L5b"C6T!!+Qlrp%U!CaB\r9I!!"!!e#UJ!L)'hq5(!M))"`rf!33LS!$#9Z!!`!%N+U!#*`!%cI$"K1ANjd!!`\rU88j@rrK)ja`N*'i!##SZ!!`S,J!3*J8["#m$,`SLEIim)&P1N!!UE[rd60m%1%j\rH6R3!$#T46PErq%MR'#3NEJ!)+#i!$#BZ!"![!bm%,`SLEIiS)&P1N!!UE[rd)!T\r-h`3B6Pj1G!!-+P%[#bC[!!JN,`!-)#m!%")#)NY5J'!-XKPQ##"*8iJJ#'!'8i"\rQm(!!*Pp1G!!-+P%LE`!%*#m!##![!!`5!L"*dF"5J'!)XL"Q"#!)B!C6J'EdF!"\r1G!!-+P&)ja`!)'m!%#J[!"3U,`!BGJ!@"(!JZS"PAR!$+!K%K-L!5S4R#*U%%-0\r6K'Ek5S0R&L!$FK$MU#)$G"MPUB+!)!2KL)#"KS!S"HU-5S4R&#$$)--J`b$$)--\rJ`b$$)-06K'EXH"r)KH5-5S4R"L$$8i4QqR!$bS"+K@F'%-06K@Ek60m!1%jd!!`\rU85"YrU`JVIk3!%je+P%[#b*[!!JQ58+V!!3J5eL)*dJ!$#G)!!JQL#0YrK3!%#0\rYrK!!&#0m!!#!!!!B3UN!(%+T!#"#U3!N*Pp1G!!%+P&19[ri51FF2#4Z!!JQ,J!\r-+%T+JfF'F2LfJ'-'F!"J!!$D@)0`r#)$9S(#J#B"YUS!''9!5US!%'Fk5US!('B\rdH"$BJbm+,`3LDJ!3)&P1N!!UE[rd+J![#Lm%,`9Kr`!!!9JQ3#!,CJC`!'!!!)j\rfr-D6B(*`%,D!C!*f%#m$,`aKr`!!!I)Q3#!,C``[#bm-BIm!!!'bB%"+UJ!3Cc+\rfUJ!BBJKi%0LU!"KJ"(J3f)-[#Lm%)QS!%#"C6T!!+Qlrp#S!,`S["#m&BIm!!!$\rX*N!J#fB%F!"J)Lm$,`X[$'(r!!!"`LB!F!%L%i+!*S&`!S'c1!!J5eL))!K-ha`\ri6Pj1G!!)+P&19[ri51FB2#KZ!!JQEJ!-+!`J#fF!!)iN5eQ+F2iL%X+!*)&fr-D\r5*NVA`h$p)K2#J#D"*d2rr#m+,`4Kr`!!!ISN3(EmaT)Q5YI$5U`!&'G)F!,!NQC\r#5UVrr'`m5T0X1#C+8BYCLdU6C`SJ8b&V!!3!"'!'+@X!"!!J5UX!"'F')'X!"##\r6,``[#b*X!"3J@8k3!#TZrr4J#Lm+,`4Kr`!!!(*-ha`B6Pj1G!!)+P&)j`!B*#m\r!$#)[!"!SE`!85S*Q"(!!B%!L3R!3NS!Q58UX!#"R"L"X!#!JLd+6*f`!)!!%+8X\r!)&#*F2`LJ&L*)S%J!9Q!dm!LJ9L*F2`LJ#"#8)KBL#!)60mB!%jd!!`U85m,)Qm\r!##C[!!`J59L)*dJ!"#GT!!`!##"T!!`K5`!%)dX!$#CI6R3!##T4,`XQE`!))Qm\r!$,26CJBJ8bDS!!JJD3!))@N!"!!%)'N!"#&T!!J!##CI6R3!##T4,``LE`!))Lm\r!$#"4+%K`r-#3!,#"C3BLL#!)B!SJD!!)XFaQkR!!+&p1G!!)+P&)jami*Qm!+#B\r[!#a`r#)$9S(#J#B"+K0qr-k&+!HBJb4,eFFX%NU'E4a`!F#'CKB[#Lm[!#KKrj!\r%DRlmcSEBKpA(B!T`%,L!C!3J"f"#F!2!KB#$*S!S5pR$F!(!K@B%+82rr(!"`)9\r+J'F%F!*J!R!!J)3SJ#9%rra`r5)5`S!NJ5m-,bm!+'(rrrrqkL!$60mFq%jd!!`\rU88MR($JSE`!F*'m!)(Mmb*)Q5YI%+K0fr-D&5S9Y'R!"`)9Q&#m,,`aKrrrrrYc\rBJh!$`*+!K#5!*LVrr(!#`**Q"%U$E!BPK%MmB"iQ5TI$,`X[$'(rrrrqX0D%F!2\r!Ni#$*S!RJcMm*%XJ#NcI($K1G!!)+P&19[ri,`d[,J!))Qhpa#"C6T!!+Qlrp%j\rH6R3!##T46PErq#m0,bi!##*Yr4`J@8k3!#TZrr41ANjd!!JU88MR'$K2lrr`*Lm\r!+#K[!#`QE`!`*%-II!!"!!*#,`!$3Lm!"%)[!!9#,`!'3Um!#%+[!!a5LK!55F!\rQ!()PX)&Q("p$!!G"l`!#3p-Lf#,B)YJbf#"+8SJJ#'!!!U*i!5!$")!!!!!JCb"\rAJ'FX8B"R%&@!C`CAJ'FSB$4#,`!#B$!II!!"!!0J+!`[!!%!!fFJ(h`!!J!$B"J\rII!!"!!9J%%S[!!*R#Kpm!!)!!Q!#H!"+K'F)8SS@%NR$B+"`+VD!CMjBP#"8,fM\rrr!!)5UMrr'`13Lm!!L![!!K%J#p!!!K5LKB55F0J+R!+6#m)!!!)FY$5Jp+!,d%\r!#&++&K**`h!!%!-JEIl`%$!)!()3`)&QeJb[!!!"r3!)EaiII!$r!!G"l`!#3p-\rLf#,B)YJbf#"+8SJJ#'!!!F4`,VD!CPSII!!"!!45LK!55F!Q!()UX)&Q0&L8)&3\r[D2rm!!a+U2rmE!4#,`!%8SS@%NR$B#T`#N`[#!!!$(,3dS25J#p"!!a5LKB55F0\r`!"!$)'hqm"!`#!"b%-#"CYCi!3b$!!!!D'F5$)-!!!"XCa)-J`!!!%aR%Q!B(h`\r!!3!'B")II!!#!!CJ#Kpm!!3!"Q!#H!"+K'F'8SS@%NR$(d-!"b!$")!!!!"&C`!\r!L&@!ChB%J!!!!"&R2&'!9i"R!!#d8i"R-&1!CfT6J'GQ8i"R9P@!Cb"EJ'F!!,a\r6J'F@8i"RGPH!C`!!S&@!C`KAJ'F%B!!!XJ`[!!3!"QB'(h`!!`!'5Lm!"'B+F!%\r[3!!-B!!!QJ`[!!)!!QB!!*!!(h`!!3!#B!!!KNU[!!aQ"R!",d!!$!`[!!%!"QF\r)$#m!!J!'CJJII!$r!!GJB%S[!!4Q@R!',d!!$'"5(h`!!J!'(h`!!3!&(h`!H!!\r(F!J[3!!-B$K+,`!%CJC+,`!'Cb`II!$r!!GJ*%S[!!CR(Kpm!2m!"f!@$#m!"!!\r'CJiII!!$!!CJ"Kpm!2m!"d([!!*$db,B)YJLf$,B)%T5L#!)6qm!%%cI("K1G!!\r-+P&)jam`+#m!)#C[!#4q!#S%*%Y#)R`!5S4Q'NU[!$*Q&%S[!#YR#!`[!'m!,@F\r')!TJ!!%JF!!3,`!Y")!!!!"BCc44J&Q!Ca*EJ'F1AB"R&Pf!CaTAJ'FHB#*f#NU\r%E"a%KAi"B"Cf#%)[!#PJ$RB+3Lm!+@!'GK"#,`!T)!9-3`!"+!&-3e!&F!UiJ'`\r'F$$BJ'!@F!UBJ!`[!(J!,@B'F'(BJ'!%F%(BJ"8%8SC+K@E+F!LfJ'B55Lm!+fF\r-$")!-'F'&6`!-&+'$#m!!J!SCL3[E`!Z!$*+KfB'5Lm!+@F%8km!-R!3YS"Q#NS\r[!#YR"&@[!$)J5j(+)#m!-Y#)$)!!!!(pE`T`!'"'&6`!-&+'[+m!-QhdF"#fJ'B\r15Lm!+fF)&5m!,48m!$"+KfF'&6`!,@!D$#m!!3!TCJB92!!VB!`-,`!#!#PQ""8\rm!#!J#NcI$2K1G!!B+P&)ja``6qrrk#C[!$Kk!#p[!$!!##p[!$3!$#4,3L*i!%+\rR3UF[,`!m,bm!2'(rrrrQC%T!CKT+V`"'CK4+,`!rC`J-,`"[!%&R"L!+B!!"hR!\r!%#m!335!!!!!@'Gd8B"CJ'F5@i"R$Pf!Cd*GJ'G39i"RAQ"X3Um!%#pm!!!!#J!\r83UG#Tbm[!$`[,`!mBIrrrqBX5N"X5Lm[!!`[,`!-5'm!%'(rrrrNBRS"B$4#V`!\r3,h`!!!!)!"4#,`!pB#*#V`!3,h`!!!!+!"4#,`!pB""#V`!3,h`!!!!3!"4#,`!\rp,bm!&#m[!"3[,`!8,bm!&%K[!""KrrrrjA3Q+!!%,bm!&#m[!"3[,`!8,bm!&%K\r[!"KKrrrrj6"`#VD!E!C`-0D!B"C`#TD!$#m!H!""CJC`BGD!B!4`3GD!&305K%+\rR3UF[,`!8,bm!&'(rrrrP4%T!CSa)H!!)3UF[,`!F,bm!('(rrrrP,%T!CK*+,`!\rrC``-%J!`C`B92!!`8S3-,`!#!$aQ0Lp[!%)!4NU&CJC+,`!pC`46V`"'5(J!%%+\rR,bm!(#m[!"aKrrrrj1C+3'B+5Lm!2fF%9Dm!4L",NFSJ,`"'d)J-J!!!!Ie[#R!\r!B&J92!!`8S5iV`"'EI4)H!!33UF[,`!F,bm!('(rrrrNSNT!CJj+,`!rC`J9,`"\r"&6`!-%U&C`B92!!YB"S-,`!"!$eQ"K8m!#YJ$!`[!!)!2@B%&6`!)#!+6qm!'%c\rI$$K1G!!F+P&)ja`i*'m!(#B[!#"+Jf`@3K*#DJ!#&A`!!3!%&A`!-!!&B!!!VR!\r!%#S!",D!E!!!SLC+@S[A`e+,'#0*a(,3f)%-"!!&CLa`!"!U!!3S5PU-f-"6M,R\r,B`B-&!!`Cr5jbfB+%#[rrh)"`)&J!R!"+J"J1J`%!!9H`%3!5F!U!'!X'#0*a(,\r3f)(BK3`%!!PH`%3!5F!U!'B%5J4Q"&1$B!`3"%R!FM$3J4D!B!4+JfE35S9R%P*\rU!!)9I!!"!!39I!!a!!9J#NU$C`$r4"9$!!4-ha`i6R3!##T46PEra%MR($3QEJ!\r8$+i!!!(p!#*["R!!B!!$`%)ZrmipI!!Jrp")E[r5,bi!%#mZ!!`[,J!)5'lrcL*\rYrF`J@8k3!#TZrm"`!"!ZrpC&l[r5@SV8`'!)8blreP*Zrp3-,J!"rpCM"J`L!$"\rRkR!!%#lre`5!!!!!-'F1")!!!!!CCa"EJ'G3B'4#,[r53Qlre'"D3Ulra%+ZrmK\r#E[r-5'lra%KZ!!Jr2!!)UHYX%L4,@iSJ5L*YrJ`J#"$CC[aJ%#4,@BSJ5L*YrJJ\rJ#"$CC[`J#Q!!!`BN5eQ+)%SLEIi%)!J3f@Em)!TJ!!,`F!!3,[r@8i$4E[r8*%Y\r#)R!!%#i!(35!!!!!4@F!!,49J'FB")!!!!!HC`!!TP1!C`!"RP1!C`4J!!+bF!!\r3,[r@X+i!)Qm1,bi!)NKZrp*KrrrrrHB-E[rmrp4Y$$!Zrp4)`,#Z!#*Y-%SZ!"Y\rR"P1Z!#*J$(!!%#lreP1!,8!!)J`Z!'F!(@B)(A`!C3!GB%!GI!"&!"eJ1%SZ!"Y\rR%$!Zrp4)`&+!NDi!)Q!!!5)`,[r85-"5J()!%LlreT+!,8%!)NU"E!!"#%+Z!#*\rJ!!%!)#i!)P+!FJ!5,[r@XS"[%L!Z!#*5J#m!5'lrdQ(rrrrp5$JZrp4)a(SV5S4\rX"%5%HLef!'!D)!4-I!J"!!!!#R!`dS!9!8am5!3!!!!+8S0+K'ELF!+fJ'hF&38\r9,J!G)%Z4bL!Z!#,3L!b!!!!"r@m'F!"J!!'Q)#i!)P+!FJ!5,[r@XS"X'(!!%#l\rreLJZ!#*8K*L!B!392!!`8i4Qq(J!'#lreR!!%!4(l[r5@S[@`'!#&506K'Ek5Ui\r!)QB'5Li!'fF%&6`!,K8ZrpG+,[r5C`J92!!YB!!"3!`Z!!%!'@B)&6`!+f!!!6!\r-,J!#!"PQ!!%Q&6`!)'!!!4j`!"!ZrpBb,[r85-&%JG+!8i%S!8U"E!*i!,LZ!#*\r[0#!%N!#Z!#*b!")ZrpD5J#m"5'lrdQ(rrrrm-R!!%#lreM)Zrp4)`85"dS"6J5J\r"5S&X!RJ!-#lre%M!8S!U!%U!E!*k!#!&d)3-J!!!!Ie["R!!B!!!UR!!%#lreNI\rZrp*DLpE!GJ"J"K8m!$"5Jb!Z!#+3!)5fJ'h`GJ"J""8M8S1fK'`5F!!3,[r@YS"\rYlQ!'&6`!-&+$YS4YpNUZ!#*Q"NSZ!"YR""8m!#j+K@FNGJ"J"K8m!$"5Jh!!%#l\rreL)&NS#fJ@hXB!39)e+$YS9Yq'!%&6`!-%SZrp*R"K8m!#eJ'J`Z!!%!'@B'&6`\r!+f!-$#i!!J!CCJ392!!J)!T-h``i6Pj1G!!J+P&19[h-51FI2#CZ!!JNEJ!-IL!\rS5RJ!B!!&%%Ki!#8[$#*YrH`J@8k3!#TZrFJX!'Bf)%a`re+!5KKQqLB!f)0+JfF\r!"1`[#dKi!!%[!bm-)QhqD#"C6T!!+Qlpb%U!CJ!%d($rB!!%c#"'NF`Q#0L$5S0\rR)#m,5(J!!5m$,``LEIjS)&P1N!!UE[h)5S"Q"R$rB!!%S#K'5'lrkNKZ!"![$'(\rrrrrcr#K!F!!3,[r[")!!!!!PC`!$&J5!!!!!)'F!!ET9J'F!!E3%J!!!!"&R!!$\rm8B"AJ'F!!Z"6J'G#8i"R!!'B8i"R!!'58i"R!!'-9B"R,&Z!C`!#I&1!C`!!cPQ\r!C`!"rP@!C`!!`PH!C`!![!5!!!!!KfF!!VjJ!!+k$#i!![rZCJjBVJ!3)'i!%#S\rSrraJ+J`Z!!2rlQB@8+i!%#"Z!"!YD2rirH)YD2rmrHCJ$&LZ!"!JEJ!3+LMrr!`\rZ!!(rlQB%-%8U#!`Z!!2rlQBS3HlrqLmJ,b![)#mJ5'lrkLmZrHB[,[hLBIrrrrG\ri*%"+J'BNB!!#2N(ZrrS[)#mJ,b![)%KZrqS["@(rrrreqL4!5S"R!!)H3HlpkN(\rS!Iq4bLB)B!!#4J`Z!!,rlQB1@+i!%#"Z!"!U+2rmB#S-,J!$rqjQ&P#Z!"!JEJ!\r3,@Mrq2hL,@Mrr2hQB!aBVJ!3)'i!%#SSrr`-,J!"rqjQ"R!!-!8U!!`Z!!2rlQB\rS3HlrqLmJ,b![)#mJ5'lrkLmZrHB[,[hLBIrrrrE+*%"+J'BNB!!"N!""l[rk,b!\r[)#mJ,b")E[rU,`9Krrrrp8`N3%U!C`!"F%(ZrHT"k!(rNFSQ#'!!!CJ-,J!%rqj\rQ(R!+dDi!%#"Z!"!YD2rfrGJYD2rkrG`pD2rqrH"J+&#Z!"!JEJ!35'Mrq%KZrFi\rr2!J1UHXYE[h1rGJYE[h5rG`pE[h@rH""l[rk,b![)#mJ,b")E[rU,blpi#mZrG`\r[,[hBBIrrrrNf*%"+J'F!!1K"l[hU3HJ"rj(+*JKJ!!%3@+i!%#"Z!"!ND2rm)!T\rQ"#4YrJ"+,[rYCaaf!"BD5Llrl'F!!1UfV[rdE`!!iLBZrr4J!!$D5Llrl'FQ*Ll\rrp#m$3UF[#L*YrM!J@8k3!#TZrFJX!'F!!,JJ4T(+*JKJ!!#Z)%T`re+!5KKQqLB\r!B!!!RPLZ!"!JEJ!3*'Mrr(!!%#lrlQF38i"R%P1!Ca46J'F@B!!"P#5%B!!"MM5\r%B!!"L#5%B!!"JLm%,`TKrrrrh$4J!!&d4HlpkPLZ!"!JEJ!3&+MrrhB"B%4&l[h\rU&,`!*AB"B$JJ4R$r8S"+''Ek*J$BJdU$Cb![#dKi!!%[!bm')QhqD#"C6T!!+Ql\rpb%U!CJC`rf!!!5SJ"'!!!53X!dSZrqTR!!#Q$#i!![rUCJ4`-'!#F#!H!!`5!#Y\rR#!`5!#eQ!!##$!F!-'Ck)#X!)P1V!#*+J'F3)'X!(P+V!"i3NR!!%"*J&#m,%"*\r*`#m!)QhqH#"C6T!!+Qlpb&+!CJC`rf!!!,a5LP1$B$SJ+`!L8kX!)NU!Ca!JD`!\rH8UX!(K#(F!!3"f!8,`X3"dR!,`!LEIji)&P1N!!UE[h)8S"Q"($rB(a5KVbZrr"\rY`%U$Cai[#dKi!!%[!bm+)QhqD#"C6T!!+Qlpb%U!CJ4`rf"55LlrkQC#B$SJ+`!\rL8kX!)NU!Ca)JD`!H8UX!(K#m!#"`!(!JB")[#dKi!#!LEIji)&P1N!!UE[h)8S"\rQ"($rB"*5KVbZrr"Y`0L'5K4Q!2VZ)!4-haci6Pj1G!!-+P&19[q`51F32#4Z!!J\rSEJ!-*Qi!%%Ki!!&)H2rr,`T)E[qb)Qhpi#"C6T!!+QlrV#m,,`a)E[qb)Qhpr#"\rC6T!!+QlrV#B!5S0Y"%)b1!!J!dcI(!K1ANjd!!`U88j@rrJ[$8KZ!"![,J!-,bi\r!##*YrIJJ@8k3!#TZrr41ANje+P%[$#K[!!JJE`!-)#m!%#*))%a5J'!1%0PQ#Q!\r#3KK6J'EkB!46J'EZ)!`SAdjd!!`U88MR'$!QE`!8+#m!'#4,&J4J$,J$CJJJ5P1\r))!KJ%KJDC["+!fF%NFKJ"#"+8iJJ#%cI$"K1G!!)+P&)jaJ`*Qm!&#J[!"JN5jI\r,&J4J#,J$CJ3Q5P1,'"TQp#!,C`3J#f!15J0R"*()B!3J5P1))!K-h``B6R3!##T\r46PErq%MR'$3NEJ!)*Qi!$#JZ!"!Q,J!8,`3[#b"YrH3[%#m+)QhqP#"C6T!!+Ql\rrp1rU-!-!##m+)QhqK#"C6T!!+Qlrp(!!60m-'%jH6R3!%#T4F!*1G!!3+P&`!%j\rd!"!U8A!!6R3!"#T46PEr3%MR'!3S,J!)5S4Y#R!#Z)"Z"(!!B(T#E[pF286r@%+\rZre*)E[p!)Qhp1#"C6T!!+Qlr2$B!-!0)`'Bm2@lr9[q8286rPNKZrhiLEIe3)&P\r1N!!UE[mm0J!`!dM!CKT#V[q3!$eZreErP%KZrhiLEIdJ)&P1N!!UE[mm-!0)`'F\r+-!0)`#"YrNJJJ%T$CJ4`!'!#F2p-h`!B6Pj1G!!%+P&2lrrd,fm!&!!#,fm!'!!\r'2fm!(!!+,bm!)%K[!!B[,`!B,aF[,`!),bm!%$mm!!ZTke"2@%p2l`!-6R3!&!J\rN!4q"K!)K!3%LK"J#)3%")S3B!L%"!5+!Z!)N!4q(k)B#!3X!$#)5&!)K!3-L%K3\r@)L3i!L)N-!)L*#J))4-6)K%8!L%"!b)4&"BL*$J#)L3`!L)N+!JK%4-L%"3#)3%\r$)K!8&L)N1!)L*$!#)L3S!*&%))&r!C!*!T!&!C!5"!L3$c#3#JL3"k#3"S#3&!L\r3"Q#3"N#3&!L3"!'!N!G!N"N)N!G!#*!'J)!)N!j!3!L3#i#3"%!)N!K!J!L3"%"\r!#*!&J*!,#)#3"!L3#J%N,8PZCJ)M5@jQ!501B8i$)Kh!!+Y3)L-)JJ*,)a!M'#-\rJ)bJM-#-i#XJM3#0))e!M@#0J)fJ+aJV##Vi+Z#0`)hJMJ#1))j!!)jJMS#1S)l!\rMZ#2!)mJMd#2B%aJMi#2S)r!Mq"-F*!!N##33*"JN)"-8*%!N5#43*&JNB#4S*(!\rNH#5!*)J2l!rS$q32i#53!#5B#q!NS"q8*4JNU#5`*,JN`#6S!#BNm#6i*3!+c!Q\ri*3JR*4!%,NP38!%J-39SEh0dFbGcEf0VCA4ICACPER4ID'&ZC'aPFMSJFfpMDf9\rd)'j[G#"TEL"eFf@UrJF,)YIe!5%3!5%%!L)Ni!JK2`%J-408CA0d9(*KBfXJ9A0\rPFL"*EQC[4A*bEh)J*@3J4f9dG'PZCb"6HA-J4@jfDA*[ER-")%T&ERC@CA)J*@3\rJE@&MD&4jF'8J*@3JFhPc9Q9b)#9N)("bEf-J*@3J4P"9)#9N)%0[E'pb883J*@3\rJDf*N)#9N)'&d9Q9bFb!PC!)S*A-k*A-k*A-#*8eKBdp6!51UrJF-)58")4!")33\r#)L6)!#SL2c`")`DTm!)Lrrd5)L,3JJ+""NVd)Y"+9#,35N`Ld%T%)Y"+2#,35HS\rLd%QU)Y"*F#,356iLd%ND)Y")`#,33i3Ld$J#)Y!hj#,306BLd$3`)Y!clL,3-q)\rLd$0@)Y!c,#,3-[`Ld$,))Y!bP#,3-83Ld$%Q)Y!`a#,3-&!Ld#lf)Y!ZGL,3,H)\rLd#c`)Y!XGL,3+K!Ld#S+)Y!U"#,3+I`Ld#Qi)Y!TB#,3*jBLd#D5)Y!Q"#,3*G`\rLd#@N)Y!PAL,3*2`Ld#3q)Y!Mp#,3)iSLd#&X)Y!K1#,3)3)Ld#"m)Y!J@#,3)$i\rLd#!H)Y!Ir#,3(l`Ld"mX)Y!E%L,3&C!!)Y!1jL,3#(`Ld!K8)Y!%JL,3!i)Ld##\rB5c3#D!(J%L%"!5%-"#&H"b5+!3--!b-""J%")4`$*3&S!@%-!bB"r2rrh6J#)J,\r%!5)"%!-P!i)"!3J$)`5#!B%$"`J!!!63!!J!!!8i!3`!!!9`!3J!!#8&T!%K#!-\rP"I)"!3J$*3EH!3%)!b8(DJ&K#!-L#&3'*3Km!5!)!b8)[!&K4!-M#F!"!5&B!b8\r+A!%M4!-P#e!")%J$*3['!3%X!b)-2JBP$&3"!3J$)JcJ!5)"#!-L$8!'*3f-!5!\r)!b80kJ%R#!-P$ZB")!J$)Jmd!5,M#!-L%$`")Q%-!b84#J(r#!-P%bi")3J$)a3\r-!3%K#!-M&&S"!5%)!bB8T2rrh6i#*K8DrrrG4!)P&C!!!H%F!bB@`[rrh8S#*4F\ri!H!F!b8Bj!%J#!-M'GB"!5%F!b8DKJ%J$!-Q'a,rrpe3!L)GiJBL(LS#)3J$*4j\rL!H-)!b)Hj!%L!3J$*4mX!5-)!b-I[!%")3J$)Krm"L-JV!%")3J$)b$D!3%K#!-\rP)3)")!J$)L%i"L)KcS%$"[mB!!!Ld#!!!!!LpL!!!!!M(![rN!3!N!F"!!!Nf!!\r!!!%!!#63!!!!!3!!!%!!!!!"!!!"A!!!!C3!!!8)!!!!!3!!!!3!N!p!!*!)!J!\r!$3)!!"`#!!!Q!J!!-J)!!$S#!!"'!J!!6J)!!&N#!!"P!J!!F!)!!))#!!#5!J!\r!R3)!!+S#!!#k!J!!a!)!!-X#!!$D!J!!i!)!!1S#!!$i!J!""J)!!4%#!!%J!J!\r"-J)!!8X#!!&B!J!"C!)!!AB#!!'(!J!"N`)!!D%#!!'U!J!"[`)!!FF#!!(6!J!\r"f`)!!HJ#!!(e!J!#!`)!!JS#!!)D!J!#+3)!!M3#!!*#!J!#8!)!!Pm#!!*[!J!\r#IJ)!!SF#!!+5!J!#QJ)!!US#!!+i!J!#aJ)!!Y)#!!,K!J!#l!)!![N#!!-"!J!\r$$`)!!ad#!!-M!J!$,3!"!*!&(!#3"!4"S!!!2%)!!F1!)8)!S!!!JN)!!F1!)8)\r!S!!!b%)!!F1J!"qB5Mp#6!q"S!!L&%)!J1p'38)!5@jdCA*QB@0P6'PL!%CbB@e\rP8QpeEQ45C@0d!%GPG&G%5@jQE`"33P*PB@4"FhPZB`"0EhCP5%KT!&0jFd9ZGQP\rbEfjc!%K9EQa[BfX!8%*5C@&N8hPZB`"0Ef4KE%4TB@a[C`"2F'9Z4(*TGQ9b!%0\rKE'a9EQPfCA*cB@a3FQpM!&"#5%GPG&C*EQC[8hPZB`"9Ff95CA0'D@aP!&"#8f9\rd48p'8hPZB`"33NK(CA4'5@jQEe0jEQ-!6Q9h5'&ZC'aP!(!bBh0dFJ"%CA4KBfK\r5CA0[GA*MC3"%C@aKH3"8D@0V3fpeER3!4f9d4'PKE'pR5A4PE3")D@aTG'9$Efj\rdFQpX!%4TFh"[Ff93G()!8%*'E(9cD&C[E&0jEQ-!4f9d4'PKE'pR5A4PE94PH(3\r!4'PcF'pcC9*[GA4TEQ9%CA0MFQP`G'pb!%GPG%jPGd4TB@a[C`""C'45CA0[GA*\rMC3"6CA4%D@&XEfG*G'9Y9'9iG!"33NGPG%C$3NPZCQp6H@jM!%GPG&*PFfpeFQ0\rP!&"#8f9d48p'3A0jEQ-!4'9LG@G6G()!6Q9h8QpeG'PZC84PFf0bDA"dEh)!8f9\rd8'pbG!"33N0XEh0P8hPZB`"(CA43Eh*d!%0XEh0P8Q9c4QPXC3"33PGbDA4P3A0\rjEQ-!8%*)4f9d9QpX8hPZB`"M-R"cG()!3fKKEQGPC&*PFfpeFQ0P!&"#3fpZG(*\r[E%&cH@jM!&0jFh4PE94KFfX!8%*)4'9XCA4P8hPZB`"%DA0`Eh0P4'PKE'pR!%G\rPG%PZC&*PFfpeFQ0P!&*PE'9KFf95CA0[GA*MC3"33P0PG%C3Eh0"FhPZB`"5CA0\r&FR*[FJ"'D@jN4QpXC'9b!%GPFh4KE(3!6NGPG&4bBA""C'4bCA0c!&"#8f9d4P"\r[Fe0jEQ-!8%*$EfjdFQpX8hPZB`"33PGbDA4P8hPZB`"'8h"2F'9Z8Q9c4QPXC3"\r$GA*5CA0'D@aP!%K2F'9Z8Q9c4QPXC3"3C@j6DATP!&GbDA4P8Q9cEh9bBf8!4'P\rcF'pcC8KKEQ4XC3")6'pMD`"*ER0PG&*PBh3!6Q9h8(4b!%GPG%*64%eKBdp64A*\rbEh*(E(9P!%GPG%*64%eKBdp64A*bEh)!G'9cG&pdFQ&MDdGXG@8!G'9cG&pdFQ&\rMD`!!#!!!!!J!!J!8a+F!%$dd!!jkQJ!+TjN"!!-d!!!LX!!"!J!$53!!*-J!!3%\r!!eS!!#)!!!%#!!0T!!!Ni!!"!*!)5Qpj)A"PCQC`Gh"M!!!!!E(413S!N!d$!!)\r!N!6rN!3!N!CR+!!!CbJ!!'FS!!!'!!!%"!$rN!3!N!BP&!!!%2%!!!3G!!"Y-!)\r""!$rN!3!N!i&H!!!!)!%"!3!N!ArN!3!N!F"!!!#H!!!!!%!!!*`!!!!!J!!!%)\r!!!!"!!!"I!!!!DJ!!!8i!!!!!3!!!!3!N!p"!*!,$3#3#`%!!!""!*!%!J!!&3)\r!!#3#!!!Z!J!!1J)!!%)#!!"1!J!!9J)!!'%#!!"Y!J!!H!)!!)S#!!#D!J!!T3)\r!!,)#!!$#!J!!c!)!!0-#!!$L!J!!k!)!!2)#!!%!!J!"$J)!!4N#!!%S!J!"1J)\r!!9-#!!&J!J!"E!)!!Ai#!!'2!J!"Q`)!!DN#!!'b!J!"a`)!!Fm#!!(E!J!"i`)\r!!I!#!!(q!J!##`)!!KN#!!)J!J!#-!)!!Mm#!!*+!J!#@!)!!QB#!!*e!J!#K3)\r!!T3#!!+G!J!#U!)!!V!#!!,!!J!#cJ)!!Y`#!!,S!J!#p`)!!`3#!!-2!J!$&`)\r!!b8#!!-V!J!$13)!!d-#!!0+!!%!N!89!*!%5N&#&%!"3J&!!8)IJ&0'&35"#S%\r#!3""!8-"`3""!8-"`3""!81+!d#'!!"*ER4PFQCKBf9-D@)!6@&dD%aTBJ"'FQ&\rYC9*[G@jN8Q9MG!"(CA4A4%PZCQm!8%*5C@&N3A0jEQ-!6@pfC8K)D3"6HA0&ERC\rTFQpZF`")9@jXEf0V!&"#8Q9KC&0jEQ-!6@pNB@a%D@&XEfF!6h"PEN4bDACPFJ"\r$B@aX9@jTGQ9bFf&X8(*[B`"33NK(CA4@5@jQEe0jEQ-!9A0P8Q9c4QPXC3"33P0\rPG%924P0jEQ-!8%*)4f9d4NPZCQp6H@jM!%jPGdKKEQ4XC3"`-Q0cG()!4'9dB@0\rS8Q9cEh9bBf8!4'9XBAN!9'PMDd0[G@jd!%GPG%4TB@a[CdPdC@d!5'PXDA4P3fp\rZG(*[E!"%DA0`Eh0P8(4b!&"#4QaeFfK@Efa6H@jM!%GPG%4TB@a[CdPdC@e8CAK\rd!%4TFh"[Ff95Eh9dD@jP4'9cBh*TF(4[FJ"(CA41CAG%D@&XEfF!3@4N8Q9cEh9\rbBf8!8f9d4'PKE'pR5A4PE94PH(3!8%*(CA4'3d**EQC[8hPZB`"(CA45CA0[GA*\rMC3"33P0PG%924N&cH@jM!%4PBR9R8h4b!%jPGe*[GA4TEQ9%CA0MFQP`G'pb!&0\rPG&"[FR3!8%*$E'pcC90jEQ-!4f9d8'pbG!"$E'pcC9*PFdCTE'8!3Qa[BfY0EhC\rP4'&dB3"33PGbDA4P3A0jEQ-!8%*)4f9d9QpX8hPZB`"M-R"cG()!3fKKEQGPC&*\rPFfpeFQ0P!&"#3fpZG(*[E%&cH@jM!&0jFh4PE94KFfX!8%*)4'9XCA4P8hPZB`"\r%DA0`Eh0P4'PKE'pR!%GPG%PZC&*PFfpeFQ0P!&*PE'9KFf95CA0[GA*MC3"33P0\rPG%C3Eh0"FhPZB`"5CA0&FR*[FJ"'D@jN4QpXC'9b!%GPFh4KE(3!6NGPG&4bBA"\r"C'4bCA0c!&"#8f9d4P"[Fe0jEQ-!8%*$EfjdFQpX8hPZB`"33PGbDA4P8hPZB`"\r'8h"2F'9Z8Q9c4QPXC3")6h"PEP*PFdCTE'8!3h9b8Q9c4QPXC3"3C@j6DATP!&G\rbDA4P8Q9cEh9bBf8!5%a[BfX!4'PcF'pcC8KKEQ4XC3"*ER0PG&*PBh3!6Q9h8(4\rb!'jeE6*NC@-!4f9d3P0%6@&M6e0&FR*[FNGPG%*64%eKBdp64A*bEh*(E(9PG'9\rcG&pdFQ&MDh4PFh4IG(*KBfY(E(9P!!!!#!!!!!J!!J!3263!&-5R!!URQ3!1HTS\r#!!05!!!#J!!"!3!$BJ!!!pJ!!3)!!hB!!!*S!!%"!!1!!!!$,!!"!*!)I!J#TT!\r!!3!)P#(r`$JK!%#!!3!)I!J$TNk!!#"m#!+QNq(rr*!!!3!)P#(r`$aJ!!%iBkT\rZ1)!!!8J!Ab'!33!8I(mEH$aJ!!%iBkKZ1)!!!8J!A`Q!33!8I!2i3%##!!`iB!)\r!5!!!#$KJ"!#!!3")1#%!3(`)!kD$iIrm6S!!)&4N"5P!JJ!-1'!!!%k!!#!iB!!\r"6S!!)(`)!UD6iIrmNm(rq*1Krr53!!%!#*3Krl"mIaYiIq2lH%[rrmPmIKYiIm-\r(G#`$!!&!JJ!J5rrr8AaM"c4Ar`9qIq3(0(`%'!""J!!)1q#SRhrMqhKra20i5!"\rHDB""!"4mI4Yi2'!!!6KMU*miJ!!"5!"H8B""!"4m!qK!I+!!*P5P(rjSS`!"J!%\r!@$JK!&"m#!1QJq(rr)2"rrL$SIrd6S!!)(`)!UD6iIrmNm(rq*!!!3!)P#(rS(a\rq'hKmRb0i1'!!!6L"!$a)!&iTJ%%!&+KK!%Tra20iIqAlH$M"!$K)!&iTJ%%!&(a\rM"c9"JJ!81'!!!,"q!!!iJ!!!N!#I!!#!!3"S1#%!B(`)!kD$iIrmJm(rq%k!!#"\rm#!+QNq(rr*2"rrL6SIrdN!!"!!L8)Iq`I(dEH(bH)hJli!!!1'#KV8[rrX&8B`B\rr3B)!*$aJCQmiBfaN1)%!1%J!AB'!33!8I'-(08##!!Jli!!"9q-'2d##!"4rSqY\riIm6cH%[rrbP)!!!m1'#!!$b!Bh3iK(*X1+!!!(qQkhKrar0i5!"GKB""!"4mB`F\re3B)!&$L!!!#`R3!!1+!!!*!![J!!J!%!@$JK!&"m#!1QJq(rr)2"rrL$SIrd6S!\r!)(`)!UDrBIrXN!!"!!L8)Ii`I(XEH(bF)hKm[5YiI0icH$KJ!!#3!'%"4$L"!$L\r3!)%"5V1K!8k6`3&S1+!!!E#K!94)!!"mJ-%"@(`'f%"!JJ"JJ1%"A(`(i%"!JJ"\r8Ik2VH(r%mhJiS3!i1-!!!8J!A2@!33!8I(mEH$aJC'iiBh*`1)!!!8J!A2@!33!\r8+!-!!%##!"4rirYi5!"EmB""!"4)!!!-Iq2lH%J!!#bT!3&813J!!E%"!956`3&\rS1'%"1%J!A0'!33!8I'-(08'#rhJiB2rrJ!%"f$JK!G"m#!1QZf(rl%k!!#"m#!+\rQNq(rr*!!!3!)P#(rX$KK!$`iJ3!i5rrq36aJBf3iBf9f2)"kG$L%Bh#SS3!mJ-%\r!1%[rrZ9mIaYiIq-(0#`$rrp"JJ!-Iq2lH%J!!)JiB3!m1)%!1%[rrBdmB'0N1'0\rPGMb!EA3iK'0`U+%!2)$"!$K,rrkPI(mEH(rN"c3X"2rr3B)!$(rMqhK)!!")1'%\r!2$L"!$K,rrh"2'"MC$KMCABmJ'ed1)4MF+LK!$b!`3!i5rrqCAar'hKrj3Fd,!A\rrrd'#!!arirYi5!!!#$KJrrq!!3"B1#%!8(`)!kD$iIrm6S!!)(`)!UD6iIrmNm(\rrq*!!!3!)P#(r`*!!B3"BJ')"p#J$!!""JJ!-1'!!!%J!!-a,rrlYI(mEH$aJC'i\riBh*`1)!!!8J!@fQ!33!8N!"L!IL!JJ(i+!3!!%##!"")!&SaJ%%!&%J!!*5!BJ(\ri5!"EFB""!"4rj3Fd,!Arrd'#!""rirYi5!"D1B""!"5!BJ(i5!"ECB""!"5!BJ(\ri5!"DDB""!"5!`J(iJ-B!!*!!`J(dJ')"p$L!!q%iS!!"J-%!@%J!@df!33!8I(i\rEH(r("c9"JJ!NJ')"q%J!@df!33!8J')"q%J!@eQ!33!813!!!*%#!I4r`r0iJ!%\r!5$JK!%"m#!1QJq(rr)2"rrK1J!!JI!J#TT!!!3!)P#(r`*!!B3"BN!#"!&b3!+%\r!B*!!`3"NJ')"p#J$!!"!JJ!-1'$rj%J!!#b!BJ(d2)!!!6L%rq%iS!!$J-%!@)$\rK!&b"!3"JJ5%!C%J!@Uf!33!8J!%!5$JK!%"m#!1Q6S!!)(`)!UD6iIrmNm(rq*!\r!!3!)P#(r`*!!B3"B1q)4r$[#%I5!B3"B1))3mB#L!Aa)!!-CB!!!!#`$!!""JJ!\r-1'!!!%J!!$b!BJ&mN!"q!!!iJ!!!N!#H!!3iSK$aN!#r!!!i`!!!N!$I!!3ii!!\r#N!$r!!Jj!!!%N4m!$*2I!""rirYiJ!%!5$JK!%"m#!1QJq(rr)2"rrK1J!!JI!J\r#TT2Krrb3!!%!#*3Krm!iBJ,i1))#$NJ!AI'!33!8I(m(0(rMqhL!!3")1#%!3(`\r)!kD$iIrm6S!!)(`)!UD3!!%!#*3Krm#!BJ))+!-!!%'#!"5"JJ))5!"H+B""!"4\r)!!!)1'!!!)!"!%Ji)3"!I!J$TNk!!#"m#!+QNq(rr*2"rrL3!!%!#*3Krm"mIKY\riU(i!!#`$!!&"JJ!-U(i!!%J!!#4,rrqCI(mEH8'#!!arirYi5!!!%%J!@DQ!33!\r85rrrd)!"!%Ji)3"!I!J$TS2Krrb$`Iri6S!!)(`)!UD6iIrmNm(rq*1Krr53!!%\r!#*3Krl"mI4Yi1q)5%+KL!JiX!`!!3))!(%[rr[PmIKYi,"i!!%'#!!ar`r0i5!!\r!Z(rMqhJiJ!!!1+!!CNJ!-lPJ!!!!U))#$V#I!"JiS!!QX,m!'T1r!"`i`!!HQ0m\r!)$MJ!!#Br`!K13$r`*NI!#*rirYi5!"F[B""!"3iI`!35rrr#Aaq'hKrirYi1)!\r!!$LJ!'C)!$0KB!!!!+NL!Jka2`!B18!!+V&I!"U6[`!FIq2lH%J!A-@!33!8UAm\r!%#`,!!"!JJ!3J(m!)%J!(M9J!!!!,"i!!%##!!LVh`!3Im2cH)!"!&Ji)3"3I!J\r$TS2Krrb$`IriJk(rp%k!!#"m#!+QNq(rr*2"rrL3!!%!#*3Krm#3!'%!@$[L%RL\rSBJ)1,!-!!%##!"a,rrhTI(iEH#`H!!""JJ!-1'!!!%J!!'arirYi1)!!!$LJ!'C\r)!$+TB!!!!+L#!Jk`R`!B1+!!+,#r!"U!`3"BN!$I!"arirYi5!"E`B""!"3iI`!\r35rrq$Aaq'hJX(J!!3B)!$$KJ!!")!!!BS2m!2#J(!!"p!!!Q93JIrQN$!!'!!3"\r)1#%!3(`)!kD$iIrmJm(rq%k!!#"m#!+Q[f(rl*!!!3!)P#(rX*!!B3"SI*XMH*!\r!S3"`1q)5i)2#!Bb!BJ)%,!-!!%##!#`iBJ,p5rrl&@!!!!"mI3Fd,"d!!%'#!!a\rrSqYi5!!!T$L!!!'3!))#")"L!C!!1)!$`$LJ!!&)!&FeJ%%!&(am'hJiS!!"X,i\r!!)"K!'Krj2YiIiAMH(r'mhK,rr[0B!!!!)$I!!!X"UAq3))!%(r$mhK,rrdTN!"\rr!!"rJq0i5!"A(B""!"5!r`!!,!F!!%'#!!b!I`!!5!!!,)%I!35")3"`N3N!!#J\rE!!""JJ!8If2EH$LI!!4)!%mYB!!!!$KJ!!#!!3"B1#%!8(`)!kDlBIrX6S!!))#\rM!!#`T!!!6S!!)(`)!UD6iIrmNm(rq*!!!3!)P#(r`,#"!&jm[LYiS'%!ALJ$!!&\r!JJ!FIprcH(r$mhL!R`!)JCm!"%J!@SQ!33!8J!%!5$JK!%"m#!1QJq(rr)2"rrK\r1J!!JI!J#TT2Krrb6`IriNk(rp*1"rr#3!!%!#*3Krh"mI"YiN!#"!+b3!+%!X*!\r!`3#dN!$K!,L4!3#m1k)6p$[!!!#SBJ)1,!-!!%##!"a,rrZKI(iEH#`H!!""JJ!\r-Im2cH%J!!1JiB3!i1)!!!$LJ!$T)!$"KB!!!!$KJ!!a)!"VGB!!!!(ar'hJS(`!\r!3))!$$KJ!!a)!!#d1)!!&,#"!&+SSJ)1X+%!8)$"!,#3!-%!@)$K!,53!1%!A)%\rG!!!S#!!!3))!()"L!B3iJ$l!1+!!!8J!9@@!33!8N!"p!!#"23!!N5%!B+&F!!#\ra33"NNq%!CMKK!$K)!&NCJ%%!&+PK!%JX#`!!3B)!'(rMqhK)!"V4B!!!!+KK!%K\r)!!!`JB%!9*'I!!#!B3#mN!"r!!5!J3#XN!#I!!L!S3#iNq8!!+$"!'5`h!!!Im2\rcH)!"!*Ji)3#3!(`)!kD$iIrmJm(rq)1Krr5$JIr`6S!!)(`)!UD6iIrmNm(rq*!\r!!3!)P#(rF*!!B3#SN!#"!+b`S3#bN!$"!,53!1%!Z$KK!%3iJ!!!1+!!1NJ!,c9\rJ!!!!J'%!Z,"K!$L!J3#dN!#"!$SiS!!!X+%!2S2K!+Ji`!!AX-%!AUML!Jk`i3"\rFJ4m!!*%"!'#")3#XN5%!CU&"!,+a33"U1@!!!CPK!(!jJ3!iNB%!E$KK!%4)!&J\r4J%%!&$KK!&4,rrTGI(iEH(r$mhL!!3#B1#%!N!"m#!1QJq(rr)2"rrK1J!!JI!J\r#TT2Krrb6`IriNk(rp*!!!3!)P#(rF*!!B3#SN!#"!+b3!+%!X*!!`3#dI2dlH*%\r"!,`iB3!i1)!!!$LJ!$T)!#jTB!!!!)2"!+JiB!!9X'%!8UL#!Jk`J3"3J,i!!*!\r!S3"8L-)#$,$"!&JiB3!i5!"AGB""!"3iB3")5rrj`Aar'hJX(`!!3B)!$(rMqhK\r)!!"dJ'%!Y)#"!'#Ji3"NI"di!%#!!!arTHYi5!!!#+#K!'4)!#fjB!!!!+%"!'5\r")3#mN3N!!)&"!&U"B3#XN8X!!+'"!&k!B3#`XB-!!$L!!"D`J3"51'%!1%J!9[Q\r!33!81'%!5%[rq89mIaYiIq2lH)!"!*Ji)3#3!(`)!kD$iIrmJm(rq)1Krr41J!!\rJI!J#TT2Krrb3!!%!#*3Kri#3!'%!Q$KK!$`iJ!!!1+!!1NJ!,@PJ!!!!Jq%!Q$K\rJ!"L`B3"@U))#$V#"!&5![`!!N!#K!&JiB3!m5!"@IB""!"3iB3"-5rribC!!B3!\riIq2lH%J!'$9J!!!!J!%!L$JK!)"m#!1QJq(rr%k!!#"m#!+QNq(rr*!!!3!)P#(\rrN!#3!'%!L+KL!JiX!`!!3))!&%[rq!PmIaYi,"m!!%##!%`iB3!i1)!!!$LJ!#4\r)!#c4B!!!!$L!!!q`J3"5U+)#$V#K!&!iB3!i5!"9mB""!"5S`3"),!B!!%##!"#\r!i3"8J3%!L*!!k!!!J!%!H$JK!("m#!1QJq(rr%k!!#"1J!!JI!J#TT2Krrb3!!%\r!#*3Krm#!BJ)3+!-!!%'#!!`iB!!!5!!!J$KJ#3")!"EGB!!!!*!!BJ)3J))#%#J\r%!!"!JJ!N1+!!$$M#&l#3!+B!!$MJ!!`j!K4iX1J!!$KJrrp)!!"%J')#%$L!!!!\riS!N!5!!X%@!!!!!li!!!5!!!($Nr!)#"3J)3(Am!5$P+!!4p+PNZ1rm!!5`I!#"\r"J2rN1'!!!)!"!%Ji)3"!I!J$TS2Krra1J!!JI!J#TT2Krrb3!!%!#*3Krm",rrm\rp,!-!!%'#!!`iB!!!5!!!3$[J!!")!!!XJ')#%"bI!%KmBb#Z9'22rd##!"5!SJ)\r3(0m!5(aP-K4)!!!81rm!!5`I!#""J2r81'!!!)!"!%Ji)3"!I!J$TS2Krra1J!!\rJNq(rr$[J!!")!!!`J))#%"br!%JiK!!%I)3S,R`$)!"!JJ!8J-)#%"cr!%KmCMS\r85!!!&$[r!!%X(`!J3B$rd$KJ!!#$iIrm6S!!)(`)!UD6iIrmN!!"!!L8)Ir!I(m\rEH(rMqhJiJ!!!1+!!"%J!+ZPJ!!!!1'!!!*!!I`!iJ*m!0#J%!!""JJ!3J(m!0%J\r!&G9J!!!!1+!!!*!![`!d1-!!!*!!h`!`J!%!5$JK!%"m#!1QJq(rr%k!!#"m#!+\rQ[d(rk*!!!3!)P#(rX(am'hKmQL0iI,XVH$ZL&(Jl`KH`,"`!!N##!"3X'`!!3B)\r!*#`E!!*"JJ!F1'!!&T!!IJ!!1)!!&V#G!!!iB2rr5!!"!#`D!!*"JJ!N,"S!!8'\r#!"`iS!!@N!#q!!!i`!!@X0d!!$KJrrp)!!$B5rrq@Aar'hJS(`!!3))!($MJ!!b\r3!2i!!$N!!!ba(3!!1'$rrdJ!!,#cR`!)Xjm!',1I!#LcI`!UNem!,)%r!$3S#3!\r!3))!3$KJ#!")!"4GB!!!!*!!I`!d18!)!*&I!$#"I`!d+!X!!%##!"`jJ!!-NCi\r!!$KJ!!b`I3!!1'$rrdJ!!&4rirYi1)!!!$LJ!!4)!#Q4B!!!!$L!!!')[`!!8)8\rq-*Lr!!!i`!!!S2m!!&$(2(#`r`!!13!!!)Nr!!&4#5EfQ6m!!6P!!!#4A`!iJ(m\r!")!"!&Ji)3"3I!J$TVY"rqK1J!!JI!J#TT2Krrb3!!%!#*3Krm#3!)%!A)2K!&b\r)I`!!9'22rd##!"!iBJ-$5!"5(B""!"5JR`!!9)A12MLP!!&3T$a`X*m!!)!"!%J\ri)3"!I!J$TS2Krra1J!!JI!J#TVm"rq#3!!%!#*3Krk#3!'%!H*!!J3"mI,JVH(c\rj1hL4!3#-1k)8H$[#&l#!B3"i5rrpAAar'hJS(`!!3))!($KJ!"D3!(i!!$L!!"D\r`R3!!1'$rrdJ!!4L![`!X,!8!!N##!"#Jh`!)+!B!!N'#!"`ii!!@N!$q!!!j!!!\r@X4d!!$KJrrp)!!$SJ6m!1#J*!!"!JJ"S1(m!#RrNqhL![`!dJ0m!-$Mr!$L"!J'\ri5rrhD@!!!!"mHKYi,"S!!%'#!#"rirYi5rrp&6P!!"Q4AJ!!Xed!!$KJrrp)!!#\r81(m!$%[rq[9J!!!!1@!!!BQI!!&4E#EfQCm!!B"K!)`S!`!33))!%+#C!!!S"!!\r#3B)!($LJ!"D3!,i!!$M!!"D`h3!!1'$rrdJ!!%Kr2-YiJ(m!1)#F!!5J[!!#J-%\r!I(m(`hK,rrJjB!!!!(al'hJX'`!!3B)!'$MJ!"Q3!2i!!,0p!!!iB2rr5!!!#(m\r$`hL!!3"S1#%!B(`)!kDl!IrJ6S!!)(`)!UDr3IrSN!!"!!L8)IqJN!"K!(L3!)%\r!I*!!S3#!N!$K!)Kp'N0i1k)8H$[#&l#!B3"i5rrlhAar'hJS(`!!3))!($KJ!"D\r3!(i!!$L!!"D`R3!!1'$rrdJ!!0#![`!X,!8!!N##!"#Jh`!)+!B!!N'#!"`ii!!\r@N!$q!!!j!!!@X4d!!$KJrrp)!!#JJ6S!!#J*!""!J!!F18!!&T&H!!!jB!!@XAd\r!!$KJrrp)!!"m1B!!%*'D!!#$J3#)1'!!!V"m!!#!I`!i1*`!"$Lm!!+!`3"mJ1%\r!J$N"!$K,rrIPB!!!!(al'hLJR`!!9)612d'#!"LJ[`!!9+E12MM'rrp3a6a`X,m\r!!#`E!!"!JJ!-J'%!1%J!!"3ii!!CN!$q!!#cI3!!1'$rri!"!'Ji)3"JI!J$TVY\r"rqK1J!!JI!J#TVjKrmb3!!%!#*3Krj!!I(JEH(bE)hKm[#YiI0-cH(cd1hJkSK4\rB1b)8'$Y#%rJS&!!!3))!$$VJrrj)!!!S5!"*cB""!"5!P!!!()3!2)#d!!3i`%%\rDI+8cPRaM+K4qj"S8Id26H$L!!!!iS!!J5!!PZ@!!!!"r)mYi1)!!!$LJ!#")!#@\rPB!!!!$KL&$JiJ!!!1+!!)%J!*C&J!!!!IU1VH$L!!!!iS!!J5!!PI@!!!!!lS!!\r!+"X!!%##!!KqZkYi+"`!!%##!!Kq[+Yi+"-!!%##!!KqXkYi1q!!!%J!!0Jii!!\r"9qJ'rRcR3$"AkHMkI6a),RcR5$P"JJ!N18!!!9IV"[jp5PJ`9qcSqRajB#jmBe0\riI(PK,MZp!!%iJ!!"9q8'rRb%+$"AjZMkI0X`,Rb%-$P"JJ"m12rrJ#`(!#""J3"\r`Iq2lH%[rqBPmIKYi+"i!!%'#!&b*(J!!93M2rd'#!&#K2J!!95R12d##!#5"AJ!\rX,!S!!8##!$L!IJ!m5rraX@!!!!!X!`!!3B)!*$PJ!!&Al!EqI@YJ-&IMk2TmQKJ\rZI)4EH(bD'5il[3!"1rm!!A`I`!""J2mS,"d!!%##!#4)!%RGJ%%!&%[rppPJ!!!\r!5!")0B""!"4m!lK!3B$qq$Li!!GmYKj`IYB"P#J@!#"!J3!)1X!!)(pMfhKr400\riIX@cH%J!)q&J!!!!Ii2MH(mNbhKqaE0i5!!Mc@!!!!"qBjYi1))81(l&XhK)!#1\rjB!!!!(qMkhL!!3"i1#%!F(`)!kDkBIr-6S!!)(`)!UDrBIrXN!!"!!L8)Iq`I(X\rEH$ZL&(Jl`KH`,"X!J%#!!"4rBpYi5!"#m@!!!!")!!$dIf2EH%[rq%PmIaYi+"m\r!!%##!!`iB!!!5!!!f#JI!!""JJ!FL(m!!&4Mcrp"JJ!3S*m!+#J%!!*"JJ!F1+!\r!&T!![J!!1-!!&V$G!!!iB2rr5!!!S)$r!#`X"`!#3B)!9%#!!'`X"`!"3)!!#%J\r!!'#"(`!m+!J!!%'#!'b!I`!m5rr['@!!!!"mI"Yi,"`!!%'#!&3j)!!CN6i!!,1\rG!!"rirYi5rrhp6KJrrp)!!"%J9m!1#J+!!""JJ!XJ(m!1%[rp9PJ!!!!5!!!($P\rJ!"D4IJ!!1B!!&V'G!!!iB2rr5!!!%(rMqhK,rrHa1'!!!)!"!&Ji)3"3I!J$TVY\rKrqa1J!!JI!J#TT!!!3!)P#(r`)"L!L!S!`!!3))!&$KJ!XK)!!d*B!!!!*!!BJ)\rJJ))#(#J%!!"!JJ!81'!!&%J!$1eJ!!!!N!"L!Kb!!3")1#%!3(`)!kC1J!!JI!J\r#TT!!!3!)P#(r`)"L!L!S!`!!3B)!%)"L!L")!!djB!!!!$L!!!#3!))#))#L!K`\rS"3!!3B)!%)"L!Ka)!!dCB!!!!$M!!!#3!-)#()!"!%Ji)3"!I!J$TNk!!#"m#!+\rQN!!"!!L8)IZ`N!"K"'L`J34ZN!#K"(!iB3!iJ)%%F%J!2kPJ!!!!1'%!1%J!54f\r!33!8J'%%D+L""'iiS34!1-%%4$MK"$K)!%NCJ%%!&)"K"%3iJ3!i5!"*)B""!"5\r!!34B1#%%8(`)!kC1J!!JI!J#TT!!!3!)P#(lX*!!B34SX)%%ET!!S34`J'%%D+L\r""'iiS34!1-%%4$MK"$K)!%M&J%%!&)"K"%3iJ3!i5!"*TB""!"3iB3!i5!"*XB"\r"!"5!B34`1)%!1%J!2`&J!!!!J!%%@$JK"&"m#!1Q6S!!)(`)!UD6iIrmNm(rq*1\rKrr56JIr`N!!"!!L8)IqJI(`EH(bH)hKm[5YiS(i!!#`$!!0"JJ!BS*i!!#`%!!9\r"JJ!-1'!!!%J!!1b![J!#9,m'2L`I!!e"JJ!J3)!!%#`I!!0"JJ!85!!!b#`I!"Y\r"JJ"N5!!![$M!!!'`h3!!Ii2MH$L!!!%iS3")1-%!2$MK!%")!%IaJ%%!&)"K!$`\riJ!!+5!")%B""!"3iB!!)1)%!1%J!5"Q!33!8J'%!2$L!!!")!%IaJ%%!&$KJ!!&\r)!!"N11!!!V$p!!"rJq0i1)!!!MLK!%Ji`3!m11%!3%J!4j@!33!8J'%!2$L!!!T\r)!%HeJ%%!&$KJ!!JiJ3!i5!"([B""!"5!B3!m1)!!!%J!4j@!33!81'!!!8J!!!J\riB!!!J!%!D$JK!'"m#!1QJq(rr)2"rrL$SIrdJi(rm%k!!#"m#!+QN!!"!!L8)Im\r31'!!!*!!B3"%1)!!!*!!J3"+1'%!1%J!5$'!33!8I'-(08'#!!`iB2rr5!!!4$L\rJ!!#3!+%!H$M!!!#``3#)U1%!6V$K!))j!!!!N3%!IMKK!'a)!%J0J%%!&(aM"c9\r"JJ!-1'$rrdJ!!!L!B3#+J!%!q$JK!2"m#!1Q6S!!)(`)!UD6iIrmNm(rq*1Krr5\r3!!%!#*3Krk"mI4Yi1'!!!,"K!%`iB!4-1)!!!$LJrrp)!%C*J%%!&(aq'hJS(J!\r!3))!$$KJrrp)!!&F1)!!!)#p!!#BK3!!1-!!!)$p!!#Ba`"NIm2cH$L!!!5![3!\r!5rrmfAr$mhJiJ!!'J4d!!$LS!'4,rrc&J')"d$L!$p!iS!!"5!"%"B""!"4mIaY\ri1'%!5%J!4Q@!33!8Im2cH%J!4R'!33!8Im2cH$L!!!%iS3"%1-%!1$MK!$a)!%A\rGJ%%!&$KJ!!-iJ!!$5!"'AB""!"3iB3!m1)$rr$LJrra)!%CKJ%%!&$KK!$`iJ!!\r31+!!%%J!4Q@!33!8Iq2lH$L"!%a)!%CYJ%%!&+NK!%`X#3!"3B)!%+P"!%`X#J!\r#3),rh(rMqhK)!%14J%%!&+PK!%`X#`!"3))!0(r$mhJiJ!!%J,d!!%[rr'&r`r0\ri1)!!"S'G!!!iV!"N5rrm68[rrJQ!R3!!N!"N!-Kr`r0i5!"'HB""!"4rSqYi5!"\r'KB""!"4rSqYi5!"'NB""!"5SB3"-J!%!D$JK!'"m#!1QJq(rr)2"rrL$SIrd6S!\r!)(`)!UD6iIrmN!!"!!L8)Ir!N!"K!&LBJ3"I2'"dG$KMG@NiJ!4-5!""6B""!"4\rmIaYi+"m!!%##!&`iB!$-5!"%6B""!"4mIaYiIq2lH$b!G(3iK(9T1+!%6$M#!da\r)!%4&J%%!&)"r!!!iJ!!!1+!!c%J!(39J!!!!Iq2lH%[rrF8X!`!"3B)!4$KJrrp\r)!!"JL'%!AbJ$!!&"JJ!B5rrp(B#I!!#!K!$)I!3B!%'#!"arirYi5rrpM5`$!!&\r"JJ!-1'$rrdJ!!#L!B3"BJ*m!!$LJ!-a)!"aPB!!!!(rMqhK)!%*"J%%!&$KJ!!#\r!!3")1#%!3(`)!kD$iIrm6S!!)(`)!UD6iIrmNm(rq*!!!3!)P#(rS(aq'hJiB!!\r"1)%!3%J!3,'!33!8I(mEH(rM"c9"JJ!FIm2cH$L#!f"rj3Fd5!!jV@!!!!")!!!\rdU)%!6*!!J3!iIm2cH$L#!hkSS3"!U-%!3UMK!%5T!3"'L5%!5)P"!%P)!$PjB!!\r!!)!"!'Ji)3"JI!J$TS2Krrb$`Iri6S!!)(`)!UD6iIrmNm(rq*!!!3!)P#(r`$a\rJ3e-iBe451)!%6%J!2lf!33!8I(mEH#JI!!""JJ"3Iq2lH%J!2lf!33!8J(m!!%[\rrjL9J!!!!I(iEH#JH!!""JJ!8J(i!%)"M!!#!B`!!N!"L!KKrirYi5!"!UB""!"4\rrirYi5!""&B""!"5!!3")1#%!3(`)!kD$iIrmJm(rq%k!!#"m#!+Q[`(ri*!!!3!\r)P#(h`*!!B3KBN!#"#&bBS3KMI2JlH$YJ!!")!$k4J%%!&(ak'hJiJK4mJ'3!!%J\r!2X@!33!8,"J!!8#"!#4)!$lPJ%%!&(bM`jCmTF(@I+8B88'#!!`iB!!!5!!#i)$\r#!KJX"J!!3))!(%[rr[@!iJ)B,!F!!%##!!`iB!!!5!!#[$KK!`K,rrj&1b!!!&F\rS"Mp"JJ!X1'%(6)L"#'0,rrdY,!-!!%'#!$"r3p0i5!!q4B""!"3iB2rr5!!#J$N\rJ!!#C)3G-18!!!*P""l!jB!!!N@%)&%[rpmf!BJ)J1)!!!$LJ!XK)!"TCB!!!!$Q\r!!!'!BJ)JXB-!!$L!!!'!SJ)JX)8!!MM!!!'!iJ)JX-F!"&FS"Mp"JJ!-15!!!8J\r!!!Jj)!!!95N'2S&#!L#a+J!'5!!pmB""!"5"BJ)JN!"V!!JiB3"-1))$b6LK"d`\ri`3H`11%$#%J!0f&J!!!!JB%)@)"L!Kb4J`!!J)%)A)#L!Kb3!)8!"$M#!p+!iJ)\rFN!$(!!Jj!J)8J5)#(*%*!!`j33"-J@)#(*&,!"#!BJ)JJ))#(%J!!V9J!!!!I(`\rEH$KJ!!)iJ!!#1+!!!%[rlZPJ!!!!I(mEH$Q!!!+aJ3!m1'!K0,"K!$k!JJ)BN!#\r"!%"rirYiJ))#)(q&ihJi`!!!11%!2$N!!"",rr"TB!!!!$ZJ!!!iB3F)1)!!!$L\rJ!#")!"NaB!!!!$LJ!!&AjJEqI+8`-&IRk2Sj!3F)I5Ji,RdT+hKp+$NZ18!!"C&\r""b`jB!!!N@%(-$KJ!3!iJ3F)1+!!!$M!!!!ii3FX5rrb[@!!!!"mIKYi,"i!!%#\r#!#4rirYiJ))#)(q&ihJi`!!!11%!2$N!!"",rqrCB!!!!#`H!!"!JJ!31ld!!5`\rG!!0"J2pN,"i!!8##!(3jJ!!3NB%!1(rMqhL!JJ)J1+!#b$M!!!!ii3!m13%!1%[\rrm49J!!!!N!"K"bJX!`!!J))#)+#%!!BX"!!%3))!0)"L!L!iJ3Fi5!!!N@!!!!#\r!S3G%L+8!!#`&!&*"JJ!)5!!!#$YJrrq!`3G)N!$""c4rirYi5rrd6@!!!!",rrA\r4Id26H%J!1m@!33!8If2EH)!"#%Ji)3K!I!J$TVX"rq"1J!!J5!!!**!!C3!!1+8\r!"(`$)%"!J!!8L1-!!$KM!!&mj`Ge3),rl#`'!!!ia[rr3),rf%k!!#"m#!+QNq(\rrr*!!!3!)P#(r`(ar'hL3!)%!A$Kr!!`iR`,(J+%!A$M!!!9,rrqPJ!%!5$JK!%"\rm#!1QJq(rr%k!!#"m#!+Q[f(rl*!!!3!)P#(rX(ar'hKmR#0iI,iVH(cG-hKrqrY\ri5!!!6)"q!!!S!`!!3))!&$L!!!#BR`!!1rm!!8J!!"KrirYiJ*i!!(bri&")!$8\rPB!!!!(rMqhJiJ!!!5!!eM@!!!!!li`!"1pi!"#`G!!!l[Irr3),rX(alq&#!!3"\rB1#%!8(`)!kDlBIrX6S!!)(`)!UD6iIrmNm(rq*!!!3!)P#(r`(aq'hL3!)%!A$[\rJ!!8iIJ!-1,i#b(bI+&#!S3"FIqElH%[rrcNiB`!-J!%!5$JK!%"m#!1QJq(rr)2\r"rrK1J!!JI!J#TT2Krrb6`IriNk(rp*1"rr#3!!%!#*3Krl"mI"Yi1q)8I$[!!!"\r)!$GpB!!!!%J!1G'!33!8I(dEH$KJrrq3!(m!!)#F!!`X"!!"3))!0)"m!"!iJ!!\r"5!!j`B""!"4mB`FdN!"r!!#![`!!,!Arrd##!"")!$QpJ%%!&(aq'hKrSqYi5!!\rjaB""!"4r`r0iJ!%!@$JK!&"m#!1QJq(rr)2"rrL$SIrdJi(rm%k!!#"m#!+QN!!\r"!!L8)Ir!1')8I)"M!!!X!rrr3))!&$L#&(b!C!!!5!!jMB""!"4)!$FKB!!!!)!\r"!%Ji)3"!I!J$TNk!!#!iBK4iU'-!!%k!!#!iB!!!6S!!)%k!!#!iB!!!6S!!)$K\rJ!!"1J!!JI!J#TT2Krrb6`IriN!!"!!L8)Ir!I(iEH$[L&)JiB!!"5!!)l@!!!!#\r!!J)N,!!!!%##!"KrirYi5!!@P@!!!!!i!!!"N!!#!L4rirYiIm6cH%J!&X&J!!!\r!I(mEH$KJ!!&)!!LaB!!!!(rMqhL!!3")1#%!3(`)!kD$iIrmJm(rq%k!!#"m#!+\rQNq(rr*!!!3!)P#(r`(ar'hL!!J)N,!!!!%'#!#`iB!!"5!!)C@!!!!!iBK5)Iq6\rlH%J!&q&J!!!!1'!!!8J!#%eJ!!!!J!%!5$JK!%"m#!1QJq(rr%k!!#"m#!+QNq(\rrr*!!!3!)P#(r`(ar'hL3!)%!A$MJ!!#3!2m!!)!"!&`S"J!!N!!I!!5)(`!)81!\rZ0*JI!!L)(`!)81!QpTJI!!LBr`!-Q2m!$C!!r`!83B)!((bN+hKrirYi1+!!!NJ\r!!ZeJ!!!!5!!!((rMqhKmj$YiI18lH(cQ1hK)!!,4B!!!!)!I!"JiB!!!N!!I!##\r3!(m!*+!I!!48!-qq,!!!!N'#!'"!J!!3,!!!!8#!!"4)!!"3,!!!"%#!!%K)!!!\rSJ')"0)!#!6#3!(m!0)"L!5b3!"m!1)!#!5L3!(m!2*!!(`"!5!!!))!#!553!(m\r!0)"L!5#3!"m!1)!#!4b3!(m!2*!!(`"!1!!!!*!!(`"%J!%!5$JK!%"m#!1QJq(\rrr%k!!#"m#!+QNq(rr*2"rrL6SIrdN!!"!!L8)Iq`1'!!!NJ!"[9J!!!!1k)$q$[\r!!!!li!!%S"d!"&3!clp"JJ!FIk2VH%J!#HeJ!!!!S"d!"&2J2I#`(3!%1pi!!6Z\rp!%JX(J!M3B$rd$KJ!!*)!!DYB!!!!)!"!&Ji)3"3I!J$TS2Krrb$`IriJk(rp%k\r!!#"m#!+QNq(rr*2"rrL6SIrdN!!"!!L8)Iq`1m!!!$ZL!rKrhr0iS"d!"&3!clp\r"JJ!FIk2VH%J!#M9J!!!!,!-!!%'#!!Jl`2rr1rm!!6Zp!%JX(`!M3B$rd(r$mhL\r!!3"B1#%!8(`)!kD$iIrmJm(rq)1Krr41J!!JJ-3!!$L!!!Si!!!05!!!+)LM!!!\rS"3!03))!$*L$!!")!!!3+!8!#N##!!LB!`!!1'-!!5J'!!!ia[rr3),re%k!!##\r!!`!BN!!$!##!!`!FN!!$!#5!S`!8J)-!+)!$!#4mT#!iI!3!8*!!!`!NJ!-!&*!\r!!`!`6S!!)(`)!UD6iIrmNm(rq*!!!3!)P#(r`(aq'hKmRb0iJ(i!')!H!#"m!`"\r43B)!D*!!(J!NL"i!"93!erp!JJ!3J(i!'$LH!#4,rrp&J(i!!)#H!"L!hJ"%JCi\r!2$Lq!#4)!$Y"J%%!&#JI!!""JJ!-J"i!**!!(`!!,!-!!%'#!!K)!!!JJ(i!*)!\rH!"4m!"S8N!!H!"4r`r0i5rrr16KJ!!#!!3")1#%!3(`)!kD$iIrmJm(rq%k!!#"\rm#!+Q[f(rl*!!!3!)P#(rX(aq'hKmQb0iI,`VH(cI-hL)(J!)S(i!"&3!hhp8Bmq\rq3))!$#`$!!"!JJ!-1'$rrdJ!!4!X(!!!3B)!(#`F!!&"JJ!8,"`!!N'#!!`iB2r\rr5!!!m)"q!"JS!`!!3B)!')JH!!K8!1Ir3B)!$%[rqpeJ!!!!L"i!"$L!!!"6J!p\rmQ"i!")Kq!!Ji(J!38)-QpTKq!!L3!"i!'*!!(J!J1k!!!C1q!"b3!*i!*#`F!!#\r3!*i!+%'#!!`S(`!"3)!!')#H!#!i!!!!I!-$H*J%!!")!!"d+"X!!%##!$"rirY\ri5rrkk@!!!!"mHaYi+"X!!%##!!`iB2rr5!!!6)JH!!K6S#EfQ"i!#*0q!"L!IJ!\rB1!!!!*!!IJ!JNri!(*!!(J!SS"i!"&3!cliX!!!"3))!&&IJ"Ip!JJ!-1!!"rj!\r!(J!S1'!!!)!"!&Ji)3"3I!J$TVYKrqa1J!!JI!J#TT2Krrb6`IriN!!"!!L8)Ir\r!I(iEH(bI)hLJI`!%1!!!!*!!(`!NL"m!$94McliS!!!!3))!$#`$!!"!JJ!-1'$\rrrdJ!!A3X!`!#3))!$%J!%0eJ!!!!L"m!#&3!hhp!JJ"FL"m!"&3$lhj8B!Hp3B)\r!6&4J"hY"JJ!SIq2lH$L!!!!iS!!#5!!2"@!!!!!X!`!!3B)!$$KJ!!")!!%FL"m\r!#$KJ!!&3B#idIq2lH*JI!!K,rrd"B!!!!)JI!!K8!0pq+!!!!8'#!"`i!!!"Q"m\r!$6J!!!#3!"m!*$KJrrp)!!$BL"m!"&3!rliS!!!#3B)!()"r!"L!(`!JJ*m!((`\r$!&"m"!"!3))!0(rMqhJiJ!!!5rrme@!!!!!X!`!!3B)!($J!!!'B(`!01!!!!*!\r!(`!N1'$rrdJ!!)#!I`!N1!2rrj!!(`!NJ(m!)$J$!!'3!"m!)*[$!!#)(`!%9!2\rr[P4J"MiS!!!#3B)!6&4J"Mp"JJ!-,"i!#N##!$4rirYi1)!!!%[rr'9J!!!!,!-\r!!%'#!"`i!!!"Q"m!$6J!!!#3!"m!*$KJrrp)!!!31!!!!*!!(`!N9m-'2S!"!%J\ri)3"!I!J$TS2Krrb$`Iri6S!!)(`)!UD6iIrmN!!"!!L8)Ir!J!)#+$[J!!!X!!!\r"3))!$$KJ!!&)!!"X1'!!!dJ!!B&J!!!!J!)#+#`!!!"!JJ"%5!!2(@!!!!"rirY\ri5rri1@!!!!"mB!Fe3B)!%$J!!!+3!!)#+%J!!"b!JJ%m1')8J$J!!!'3!)-!!(`\rI!hL3!!)#+$KJ!!0)!!%YB!!!!(rMqhL!!3")1#%!3(`)!kD$iIrm6S!!)(`)!UD\r6iIrmNm(rq*!!!3!)P#(r`(bH)hKm[bYi5rrr35`$!!"!JJ!-1'!!!8J!!%3iBJ2\ri1'-!5%J!",9J!!!!Im2cH)#I!!",rrHYB!!!!*!!I`!!J(m!!$J!rrpm!`"!3))\r!$$KJ!!&)!!!)1'!!!)!"!%Ji)3"!I!J$TS2Krrb$`Iri6S!!)(`)!UD6iIrmNm(\rrq*!!!3!)P#(r`(bH)hKm[bYi5rrqZ5`$!!"!JJ!-1'!!!8J!!$4r`r0iJ*m!!%[\rrpbeJ!!!!N!"r!!#!I`!!1!$rrh`$!%"!JJ!-1'!!!8J!!!JiB!!!J!%!5$JK!%"\rm#!1QJq(rr)2"rrK1J!!J1'!!!%k!!#"1J!!J6S!!)(`)!UDr)IrNN!!"!!L8)Iq\rJI(XEH(bC)hKmfM0iIlNTed'#!"b)'J!0+!!!!%##!"#JHJ!%9'$2[d##!!`iB!!\r!5!!#`&4JcliX!!!#3))!$%J!$9PJ!!!!L"S!"6[J!!"8!0Ir3B)!,+!D!!48!-q\rq,!!!!d'#!"b)'J!%9!$r[LJ!!!*"JJ!-+!!!!8##!!Jli!!"L"S!#&3!hhp!JJ"\rFL"S!"&3$lhj8B!Hp3B)!6&4J"hY"JJ!SId26H$L!!!!iS!!#5!!,4@!!!!!X!`!\r!3B)!$$KJ!!")!!)SL"S!#$KJ!!&3B#idId26H*JD!!K,rrP"B!!!!)JD!!K8!0p\rq+!!!!8'#!"`iB!!"1!!!!*Kk!!em!`0iN!!D!#4)!!(N+"d!!(pqfhJlJ!!!3B)\r"2)"k!##!'J!BI!-!3%##!!`X(`!!3B)"*)#D!"L!HJ!JJ"S!((aN'&"m!`"3N!!\rD!#5!'J!N1f!!!*!!!3!iJ!%!1(`!k%"!J3!)Nk%!1)JD!!48!2qq+!!!!8##!$L\r!S3!i+!8!!%'#!#ar`r0i1)!!#NJ!#bPJ!!!!I(XEH#JE!!""JJ!31"X!!A`H!&#\r3!!%!1)#K!$JS"3!!3B)!3)"k!#"ra20i5!!+9@!!!!#!J3!iJ"S!)(rH)K4m!#)\r8N!!D!##!B3!iJ"S!*(qF)K4m!`"3N!!D!#4rT1K3J"S!*#J!!!""JJ!B+"X!!%#\r#!"#)'J!%9!$r[d##!$4r3p0i1)!!!%[rq$9J!!!!,!-!!%'#!"`iB!!"1!!!!*K\rk!!em(30iN!!D!#4)!!!8+"d!!%'#!!`X(`!!3),qr#JG!!""JJ"`,"m!!%##!'L\r$HJ!BJrS!((`HkK56fJ!BNlS!((p$dhL3!"S!)$L"!$K,rrI0B!!!!#`$!!""JJ!\r81!!!!CJD!!di!!!!N!!D!#5!!3!iId26H*0k!"L6qJ!FIj`#&%[rpf9J!!!!1!!\r!!*!!'J!NL"S!"&3!rliS!!!#3B)!$$J!!!#3!"S!*$JCrrpm(!)8I'$,PS!"!'J\ri)3"JI!J$TVXKrq41J!!JI!J#TT2Krrb6`IriNk(rp*!!!3!)P#(rX(ap'hJS(3!\r!3))!$$KJrrp)!!#%S"d!"&3!clp!JJ!-1'!!!%J!!("rSqYi5!!!K@!!!!"mIaY\riJ(d!!)'G!%")!$+9J%%!&+!G!!3iJ!!!8)!pm,!G!!53!*d!!)JG!!KmIKYi9!$\rRrd'#!"#!I3!B5rrce@!!!!!X(`!!3))!$#`H!!""JJ!-1'$rrdJ!!!JiB!!!J!%\r!@$JK!&"m#!1QJq(rr)2"rrL$SIrd6S!!)(`)!UD6iIrmNm(rq*!!!3!)P#(r`(a\rr'hJS(`!!3))!%%[rpAPJ!!!!5!!!q)JI!!dS!!!!3))!%+!I!!48!-qr3))!$$K\rJrrp)!!$BL(m!#&4JhhiS!!!$3B!!&(aJ'hJiB!!#8'!Z0*JI!!L)(`!)9!$IILJ\r!!!*!JJ!-1!!!!*!!(`!NL*m!#&5!hhiS!!!"3B)!'$KJ!!"mJ#0i8'!Z0*JI!!K\r)!!"mS"m!"&3!cliX!!!"3))!((rMqhK)!!9KB!!!!(aq'hJS(J!!5!!!#$[!!!"\rrirYi1)!!!%[rpDeJ!!!!,!-!!%'#!"`i!!!"Q"m!$6J!!!#3!"m!*$KJrrp)!!!\rJL"m!#$L!!!"3J#idQ"m!#*2I!"4mJb0iN!#I!#5!!3")1#%!3(`)!kD$iIrmJm(\rrq%k!!#!iSKHd1!!!)h`*!kDSK3!!I'!(0(`%!!"!JJ!-I+-VH%k!!#!iT3")3J$\rrj$KJ!!"1J!!JI!J#TT2Krrb6`IriN!!"!!L8)Iq!I,iVH(cI-hJiS!!!N!#K!%5\r`B3"3N!#"!&L!(J!!+"m!!*!!!3"FX+%!C%'#!$!iB3!i5!!Y,B""!"4)!!!3Iqc\rlH%J!-'@!33!8U!%!5#`!!!""JIrX5!!!%$KK!$K)!#dCJ%%!&)!"!'#3!"i!!+J\r"!%JX!2rC3))!))!H!!!S!!!!3B)!$$KJ!!")!!!J1'!!!NJ!!"JX!!!!3))!$$K\rJ!!")!!!)1'!!!B!"!)Ji)3#!I!J$TS2Krrb$`Iri6S!!)(`)!UD6iIrmNm(rq*!\r!!3!)P#(rJ(bq+hKmhc0i1+!!!*!!S3"%X'%!8*!!J3"BJ"i!!#JI!!#3!!%!A,#\rK!'4"JJ!`1'%!1%J!,)Q!33!85!!!%(rXqhK)!#q4J%%!&+J"!%JX!!!!3B(rl%J\r!!"!iB3!i5!!XGB""!"5!!3"JN!!H!!#S!3"),!!!!%##!!`iB!!!5!!!#$KJ!!'\r!!3#)1#%!J(`)!kD$iIrmJm(rq%k!!#"m#!+QNq(rr*2"rrL6SIrdNi(rm*!!!3!\r)P#(rJ(am'hKmRL0iI,dVH(cI-hJi!!!!N!!"!%3X(3!"Xi%!8%'#!$4!J!!3,"d\r!!%#!!"a)!!!N,"d!!d#!!"`i!!!#X!%!C%J!!"Ji!!!"X!%!C%J!!!`iB!!"5!!\r"H)!H!!!S(`!!N!!"!'C"JJ!`1'%!1%J!+`'!33!85!!!%(rXqhK)!#kCJ%%!&+J\r"!%JX!!!!3B(rl%J!!"!iB3!i5!!UlB""!"5!B3"QJ"i!!(`$!&&!J3%!+"m!!(`\r$!K53!!%!9%'#!$!iB3!i5!!UfB""!"4)!!!3IqclH%J!,N'!33!8U!%!5#`!!!"\r"JIrX5!!!%$KK!$K)!#V&J%%!&+J"!%JX!!!!3))!$$J!!!")!!!)1!!!!5`!!!"\r!JJ#B1!!!!*!!!3"%,"d!!E1"!&""JJ!d3)!!%#`G!!"!J!!F5!!!*#`G!!0!J!!\rF1!!!!V!"!'4)!!!B1!!!!E!"!'4)!!!-1'!!!8J!!'b!(J!!+"m!!*!!!3"Q3B)\r!-$KK!$K)!#ReJ%%!&%J!!""rl2Yi5!!YMB""!"5S!3"),!!!!%'"rqa)!!!31'%\r!1%J!+H'!33!8J!%!CT!!(J!!U!%!5#`!!!"!JJ!-1'!!!%J!!!JiB!!"J!%!L$J\rK!)"m#!1QJq(rr)2"rrL$SIrdJi(rm%k!!#"m#!+QNq(rr*2"rrL3!!%!#*3Krd"\rmIKYiIm2cH%[rr#&mIaYiXm%!8$KK!$K)!#S9J%%!&(aJ"c9!JJ!`+"m!!%'#!#J\ri(`!)N!!"!%US(`!#1'%!1,!"!%k!(`!%N!!"!'K)!#RjJ%%!&#JI!!""JJ!-1!!\r!!,!I!!"mB!Fe3))!$$KJ!!")!!!)1'!!!B!"!-Ji)3$!I!J$TS2Krrb$`Iri6S!\r!)+!$!!48!-qq+!!!!8'#!!`S!!!#3))!%)J$!!dS!!!!3B)!'$KL&l!i!!!MN!!\r$!!!iB2rr6S!!))J$!!K8"Ypq9-!'2d##!!b!B`!86S!!)&6!"Mk!S`!BJ)-!)#J\r!!!1!B`!`I!8J8(aM!K40J!!J1!ErrRaJ'&"1J!!JI!J#TT!!!3!)P#(r`%[rrhQ\r!!3")1#%!3(`)!kC1J!!JI!J#TT2Krrb6`IriNk(rp*!!!3!)P#(rX(ap'hKm[LY\riN!#"!'bJ(3!%1q)AX&3!cliS!!!"3))!%)JG!!dS!!!!3B)!&$J!!#13!"m!!$K\rJrrp)!!'%L"d!#&3!hhiS!!!"3))!2(qMkhJiJ!!!5rr[i@!!!!!X!`!!3B)!*$J\r!!!'B(3!01!!!!*!!(3!N1!!!)j!!(`!!1'$rrdJ!!6`X(J!"3))!)$[!!!"rSqY\ri5rrqZB!"!'`S!`!!I!!D&*!!!3"X,"i!!N'#!*!!L"d!"&3!lhiS!!!$3B)!J)J\rG!!K8!0pq+!!!!N'#!!`S!!!$3))!D)#"!'b!(3!8I!3!3%#!!"#!(3!`I!3!3%#\r!!"L)(3!)1'!!!&"J,M5B(3!)5!!!5)"p!"Km!#"3I!-#&*!!(3!JJ)%!E)!G!"3\riB!!#I!3!8*!!(3!NL"d!#&"J,M5B(3!)5!!!&)JG!!JiB!!!8'!Z0*JG!!L)(3!\r)9!$IId##!'5"R3!d+!`!!%'#!%5!I3!!J0d!4(r&mhJiJ3"X5!!UAB""!"3X!`!\r!3B)!*$J!!!'B(3!01!!!!*!!(3!N1!!!)j!!(`!!1'$rrdJ!!"`iB!!!Q(d!$)!\r"!'b3!"d!&*!!I3!N1'!!!)!"!&Ji)3"3I!J$TS2Krrb$`IriJk(rp%k!!#"m#!+\rQN!!"!!L8)Ir!5rrq"B!"!%Ji)3"!I!J$TNk!!#"m#!+QNq(rr*!!!3!)P#(r`(a\rr'hKmJb0iIq6lH%J!*`@!33!8Iq2lH)!"!%Ji)3"!I!J$TS2Krra1J!!JI!J#TT2\rKrrb3!!%!#*3Krm"mIaYiIq2lH%J!!(PJ!!!!Iq2lH)!"!%Ji)3"!I!J$TS2Krra\r1J!!J1'2rrcLP!!&)!!!8M!-!!A`!)%"!JJ!)6S!!)$5Prrp!J[rX1'!!!%k!!#"\rmBbS81+8!!8J!!"5-!rrrI!!J3%##!!K1J!!J0+Arrd##rq`iB!!!6S!!)#J&!#"\r8KJBq112rrd'!!*!!I!F!d&3!"lp"JJ!8I+!S8*c(!!%d!2rr3),rq#J'!!""JJ!\rF9-2!$P6!J"j8a%!ZI'!$H(b!!hKmaJ0i9+$CIcMRrre"JJ!XP-F!"*6(!!58a`!\r%P-F!"*6(!!58a`!%P-F!"*6(!!3d!2rr3),rh&5Jphp"JJ!3P-F!"$3!rrp!J[r\ri11F!!e5P"liS"3!!6B)!)*c(!!%dTIrr3),rq%k!!##!!J&%1')8K*!!!`!!6S!\r!)$M!!!#3!--!"$J$!!53!!-!$*!!!`!)2)!!!B#L!9#3!!-!!)!#!8b3!+-!%*!\r!!`!81)5!!*!!J`!BN!$$!"b3!--!)*!!``!N6S!!)(`)!UD6iIrmNm(rq*1Krr5\r6JIr`N!!"!!L8)Iq`I(`EH#J%!!"rRq0i3B)!%$J!rr4m"!"!3)%!$$KJ!!")!!%\rX1'3!#i!F!"K8I3!iI"d!3%'!!&b"R!!3+!`!!%'#!&#!(!!F,!!!!%##!%3lh3!\r3Im2cH(q%ihK)!#H0J%%!&(r%mhKrKH0i5!!##Aaq'hJS(J!!3))!$$KJ!!")!!$\r-J"i!!&3G!$T)!!#N+"d!%%#!!!JlS!!3Iq2lH(qNkhK)!!+&I(iEH#JH!!""JJ!\r8Iq2lH(r%mhK)!!)p5!!!A)!F!"!S!!!!3B)!3)"m!"Km(4K!3B%!$$[$!"")!!!\r)1pd!%)'F!""r`r0iIi6MH%J!*[@!33!8Im6cH(q&ihK)!!&aI(iEH#JH!!"!JJ!\r-1'!!!%J!!$4rirYiIm6cH(qPkhK)!!)pI(dEH)!H!!!iIJ!%B!!!!C!!(J!!I"l\rS,Q!!!!*m(ZNZJ!%!@$JK!&"m#!1QJq(rr)2"rrL$SIrdJi(rm%k!!#"m#!+QNq(\rrr*2"rrL3!!%!#*3Krm"mIaYi+!3!!(rqqhK"JJ$31+6rr)!&!!"r`r0i9!!!2*!\r!"3!!J!8!!(bN+hK8"`!kI-8k&)!'!!"8!!IkN!!'!!#3!1Err%J!!R9mC4YiJ"m\r!&)"P!!!S!!!!9'F!1Rc&1K4"JJ"`9'!([8##!'L!"Irm,!!!!%#!!&b!"J!!,!!\r!!%#!!&!iCIrdJ)-!!#J%!!""JJ!3J!-!"*!!"!!%5!!!$)!$!!53!"m!))#$!!3\rS"!!!3B)!$)!$!!#3!!3!!)'I!"4rj2Yi5!!PTB""!"4)!!!3Im2cH(bN+hK)!!#\r"J!%!5$JK!%"m#!1QJq(rr)2"rrK1J!!J+!-!!%##!!`iB!!!6S!!))$&!#"mCaY\ri+!B!!(cS1hJj*2r`3B)!#*%'!!!i!!!!N!!)!!#!"3!J1)$rr*!!#!!%N38!)*5\r(!!L9*`!%1!Rrr(cR!K54*`!!P)F!"$KM!!a1J!!J1!-!"*!!"!!%J!-!$*!!"!!\r)J+-!$*!!K3!%N!#$!!a1J!!JJ+-!!(`%+%"!JJ!-J!8!#*!!!`!!J!3!")"N!!L\r3!!-!")!%!!L!C!!%N!!$!!K1J!!JI'BEH)#Q!!"mSbYiJ!8!!&3!!$Tm!#"!3B!\r!%(bM+hL3!+B!!%k!!##!T3!)I!8B3%##rp`iB!!!6S!!)(`)!UDr)IrNN!!"!!L\r8)IqJI(mEH(bC)hL$f3!!1!8!"eI$!$TrH4S8JlX!!&3D!$JX(3!!IjSB8%'!!#K\rAS!Ir3))!)(rMqhKrC0Yi5rrr59HJ!$TrR!)8IhX#&%J!!"!S(!!33)!!#%J!!&K\rA`!HqId-$H&I!"rq3!(N!!(bCdK4!JJ!)Nd6rr&I!"rp"JJ!-1!!!!NJ!!!Ji!!!\r!Ii!$H*!!"!!!Nj[rr)!E!!"rirYi9!!(qT!!'`!!5rrq[Ap$dhL!!3"S1#%!B(`\r)!kDl)IrN6S!!)(`)!UDrBIrXN!!"!!L8)Iq`I(XEH(bF)hL!(!!!9"i!1RrmmK5\r!(`!!,!!!!&3G!$T"J!!X9!!(rd##!#4rBpYiIq6lH%[rrRf!(!!!IplU&&3!"lj\rr`!0iN!!F!!#!(!!!Jlcrr&3!"le!JJ!-,"d!!%#!!"!i([rmIp`",NJ!!$4rrH"\r3If2EH(rNqhK,rrieJ"m!!(qpmK48!!HqIk!$H*!!(`!!1"hrr(rmqhKr[`%ZIi2\rMH)!"!&Ji)3"3I!J$TVYKrqa1J!!JI!J#TT!!!3!)P#(r`%J!(`@!33!8J!%!5$J\rK!%"m#!1Q6S!!)(`)!UD3!!%!#*3Krm")!"ljJ%%!&)!"!%Ji)3"!I!J$TNk!!#!\ri!!!"Q!(rm$J!!!#B!IraQ!(rmTJ"rr1B!IrdN!!"rrL3!!(rr$M$!!'*"J!!1')\r0d(d)"h3X#!!P3))!-*N"rr@!JIr`J!(rp$KQ!!'3!)8!!*!!"3!%J)(rq)!"rrb\r3!)8!#*!!"3!-6S!!)$J)rq!S!!!315!!!8'"!'3iiJqJ9!!31RcR!#jmk31Q6S!\r%)$J!!!#B!Ir`5!!!5*NKrr&)!!"!L!(rm5J!!!&"JJ!d1!!!!TJ"rr&)!!!SQ5(\rrmdJ!!##)!Ir`+!!!!%'#!"3i!!!#Q!(rm%J!!!Jj)!!!,!N!!%'#!"#0"J!"I3J\r(G%[rrh`X#!!U3))!B)$N!!!ij`!%N!$N!!#!"rrm,!!!!*!!!Iri3)!!'$J!!!#\rB!Ir`J!(rq(`!!0#3!!(rq)d'!!&p#!Gd5!!!0%J!!##!!Iri(!!!#RcS!K3i"rr\r3N!!"rrL0"J!"I3J(G&8!"Mjm!`#Z9!!'pd##rpL!!Iri,!!"r8#"!$3i!!$rQ!(\rrpB#"rr#!!Ird1'B!!C!!K3!!N!!&!!5!JIriJ!(rr*!!K3!)N!!&!!a1J!!J,!J\r!,N##!(`i!!!"Q!(rmSd'!!&p#!Gd,!J!+N##!&5!C!!!1'-!"*!!C!!!J!2rr#`\r!!!#3!!(rr%#!!!`i!!!!Q!(rmSd'!!&p#!Gd5!!!0%J!!##!!Irm(!!!#Rb)!K3\ri"2r3N!!"rrb0"J!"I3J(G&8!"Mjm!`#Z9!!'pd##rpJX#!"S15!!!8'#!#"!J!!\r3,!J!6%'#!#K)!!!`,!J!E%'#!"")!!!NQ5(rp%J!!#!i!!!#Q!(rp%J!!"3i!!!\r%Q!(rp%J!!!Jj)!!!,!N!!%'#!!b0"J!"I3J(G$J)rlXS!!!cQ3(rp8'"!5!iBJl\r39!!31RaM!#jmD31Q6S!%))J"rr3S!!!%3))!$$J!!!1B!IrdL!(rmLJ!!!"!JJ!\r31!!!!C!!!Irm5!!!k)J"rr!S!!!#3))!h$J!!!'B!Ir`5!!!d)!"rr`X!!!!3))\r!$$J!!!'3!!(rr)J"rr3S!!!"3B)!$#J!!!*!JJ!31!!!rjJ"rr9)!!#FL!(rmLJ\r!!!"!JJ#3!$J!!!D3!!(rr%J!!)3i!!!#Q!(rp$J!!!'B!Irc1!!!H*J"rr8i!!!\r)N!!"rra)!!"JL!(rmLJ!!!"!JJ!3L!(rp#J!!!""JJ")1!!!rjJ"rr9)!!!mL!(\rrp#J!!!""JJ!`1!!!rjJ"rr9)!!!NL!(rp#J!!!4!JJ!B1!!!!jJ"rr4)!!!-1!!\r!rjJ"rr@!JIr`J!(rp$KQ!!'3!)8!!*!!"3!%J)(rq)!"rrb3!)8!#*!!"3!-6S!\r!)*!!S3!JN!$"!#53!1%!+*%"!#`X!`!!11!!!$LNrrpmDKYiI1BlH*MP!!"!JJ!\r`J3%!,#`)!!"!JJ!NL3%!)bJ)!!""JJ!3L3%!*5J)!'p"JJ!-I+-VH%k!!##*!3!\rP15MrU#J*!#""J3"F13)2j&8T%$Tp#%JZI3N$TNk!"#!X!`!!1!!!#N#!!$ap5J$\r311!!!8J!!$!i!!!!Q!%!)6J!!!K)!!!J1!!!!*J"!#%i!!!+5!!!%$J!!!#B!3!\rK1!!!%(d+!jCp#!(@I3K38(e+!jBX#!!+3)!!$$N)!$")!!!JL'%!*6N)rrBS!`"\ri3))!$$N)!'&)!!!)13J!35J+!!#G"Irr1-B!!8##rlJS!!!)3))!+)KK!#-S!`!\r!3B)!()KP!!!X!`!`3B)!%$KJ!$#FCIrr1-B!!BKK!#!S!`!#3))!6)"K!#JX"`!\r!N!"K!#a!JJ!3L'%!)5J$!!""JJ!3J'%!,$KMrrq3!'%!,#J!!""!JJ!FL'%!)bJ\r$!!""JJ!3J'%!,$KMrrk3!'%!,)%"!#amC5"3I'JD&#`$!Ie!J3!-1'!!!%k!!#!\riJ!!`5!!!$*b&rrmiaJ!"J'%!,(`''!""J2r`+!!!%%##!##)!3!M+!!!!%'#!"5\r)!3!PR!ArrcJ!!$#F"Irr,!F!!%'#!"!i!!!YR!ArrdJ!!#b)!3!K+!!!!8##!"!\ri!!!VR!ArrdJ!!"3S!!!#3))!$$J!!##F"IrrI+-VH%k!!#"m#!+Q[Z(rh*!!!3!\r)P#(rS*!!`3#%N!$K!)L4!3#-I,JVH*%K!*!!1b!!!(mJrR"mKFTiI'!#H$Yirrp\rmS!0jI*iMH(ar'hKr1XYiQcX!!%##!$#!!3#3!#`!!!"!JJ!NL!%!KbJ!!!""JJ!\r3L!%!L5J!!'p"JJ!-If2EH%J!!Nb)S3#*1!ArU#J!!#""J3"i1+)3D&3!%$TmT3!\rZI+N$TNk!"#!lS!!!E'@!!'qMJ!"m(5!3I'-T%(aP+4"mB`$41i!!#N'#!%!MhJ!\r!Irm"N!!l)!!"5!!!-$ZJ!!#ES3#&1i!!#%J!!#!lS!!!Qk%!K6Z!!!T)!!!31k!\r!!*ZK!)8lJ!!3Iq2lH(r%mhKrTHYiIiEMH%J!&(PmPb0iIq2lH(r%mhKrTHYiIiE\rMH%J!%h8X&`!+I*iMH(ar'hK!J!!-1[F!-%J!!##)!3#*1[IrpLJ!!(K!JJ!-1[F\r!B8J!!!Jkp`""1)!!!(r$)RKri#*iI'!$HCllrrml@J!"3),rL$J!!!KrJ`*iIk!\rLH(aJ!hP!JJ!SL!%!KbJ!!!""JJ!FL"X!!#`!!$""JJ!31!!!-*`Errml@J!"L!%\r!K#J!!!*!JJ"FJ!%!M#`C!!#3!!%!N!"!JJ!3L!%!K5J!!!""JJ!3J'%!N!!i!rr\rrN!!"!*!!1'!!%$J!!!"rJaTiIk!#H(aJ!hP!JJ!FL!%!KbJ!!!""JJ!3J'%!N!!\ri!rrqN!!"!*!!J'%!N!"m'm"3I!-#&#`!!Ie!J3!-1'!!!%J!!*3iB!!`5!!!$*a\rlrrml@J!"J!%!N!"m'J!!3B$rm$KJ!"!i!!!!Ii-DH(qJ!RKmB!0j3))!))J"!)F\rS!!!!3B)!&)J"!)QF'rrr1!!!-*`ErrmX'3!!3B)!%$J!!#fF'rrr5!!!,)J"!)8\rS!!!"3))!%$J!!#ZF'rrr5!!!&#J!!!*!JJ!-1!!!)*`ErrprBpYiJ!%!D$JK!'"\rm#!1QZZ(rh%k!!#!X"!!!3)!!*$J!!!#B!`!!X!-!!MJ!!!'B!`!%1!!!-*J$!!9\r1J!!JL--!"(`%-!"-J!!JI+-L&$MP!!D-Trrr1+Ard(bJ"h3X!!!&3))!3(bM-K3\riT3!&1+Arrh`&1%"!J3!3L!8!!#`!!$""J[rXI!8i3%##!"#)"rrr9!B(rNJ!!&3\ri`!!"5!!!6(`!!#C8"KIq5!!!3)`(rrpmS$)81+Ard(bJ"h3X!!!*I!!!*P3'&rp\r!JJ!-I+!(G8##!!`iK2rr5!!!%$J&!$#B"`!!5!!!$#`%!!"!J[r!,!B!!%'#!#5\rSJ`!#1!!!!6L%!!'`J`!#Q!-!"$J!!$'B!`!&6S!!)#`%!!""J[m!Q)-!"%k!!#"\rm#!+Qfq(rq*2Krqb6`IrSN!!"!!L8)Iq!N!$"!+6ri!L3!*!!i3#SN3%!V(bq+hL\r4)3#`J!%!X#`!!Ie!J3!-1'!!!%J!"36m)2L3!$J!!!#B!3!i1!!!),!"!$SiB3!\ri1-%!2%J!&E'!33!8L!%!3$[K!%&rr`)85!!!()KK!%!i!rrrQ!%!3+KK!$ii!`!\r"X!%!2SJ"!%!S!!!"3)%!%)`IrrmX!!!`3B,re)J"!%%X!!"*3B)!-%#!!"!X!!!\r`3B)!&%J!!(`X!!"13B)!@%J!!(!i!!!!Q!%!2,!"!$j)!!"Jb!)#12`I!%"!J!!\rF1rlrqcL#%1arirYi5!!,q@!!!!")!!!B1rlrr(rMqhJiJJ)X5!!,i@!!!!"rirY\ri5!!%+$[qrrarirYi1))#-%J!#m9J!!!!Iq2lH%J!"!b)B3"!U!%!2MKMrrpm!"S\r8X!%!2M[qrrmi!!!!Q"m!!)J"!+NX!!"P3B)!p%#!!#JX!!"'3B)$d%#!!"!X!!"\r&3)!!h%J!!m!X!!")3)!$Z%J!!"3X!!"R3B)!$%#!!kK)!!))L!%!3)#"!,"m!#!\r!3)%!$$KK!$a,rrdjU)%!2L`%rra"J!!3J'%!X(`%'!""J!"3L!%!TbJ!!!""JJ!\r8J'%!X$J$rrq3!!%!X%J!!"#)B3"!1!2rrj!!!3#`L!%!U5J!!'G!JJ!31!!!CCJ\r"!+P)!!"-1!!!4CJ"!+P)!!"!L!%!TbJ!!!""JJ!81!3!!A`!'&#3!!%!X%J!!A#\r)!3"!1'3!!A`$!&'3!!%!X%#!!9`i!!!!N!!"!,")!!&3J'%!X)J"!%!iJ`!"I!!\rJ!%#"!!`iB3!m5rrmIDLK!$iii!!V,!8!!%#!!!amT3$311!!,6M!!!!iJ!!+5!!\r!)(aP)pCmBb(@I'-S8(bP)pBi!`!`R"rrrcM'!!%X"3!!3),ri#`'!!*"J2rBR2r\rrriJ"!+QF(rrrJ)%!X(`Im&"m"!)8,!!"r8#"!!`iB!!!5!!#A)KK!%!i"!!"I!-\r!!%#!!#!i"!!#I+-!8$J!!$")!!!)R"rrrc5Prrp!J[riL+%!3$L"!%&mK#S85!!\r!$)`%rrqF(rrr0+Arrd##rr5!!3#`,!!!!%##!"#)!3#R+!!!!%'#!!`i!!!ZR"r\rrriJ"!%'F(rrrL!%!2(`!"h9"JJ!31!!!,C`Irrp)!!(-L!%!T5J!!!&!JJ!31!!\r!+j`Irrp)!!'d+!!!!N##!D`i!!!JR"rrrdJ!!D#S!3!qL'%!3(`!!0!iirrrI1!\rk&8#!!!Jii!!!J'%!X(`('!"!J3!dL!%!3(b$1&!iB3!mI)3!8%[rqa'S!3!qL'%\r!3(`!!0!iirrrI1!k&8#!!!Jii!!!U!%!2M5J!!&!J!!)1+!!!(`&1K3X!!(p3)%\r!$$KJ!!")!!%SL!%!3$L"!%&mK!)81-!!!$KJ!$")!!!-R(rrrcM'!!'!!3#`I!F\r!8(`'!!""J2rX1-!!!%J!!"#-"2rr1-B!!C`Irrpm"MJ!3)!!%)J"!%"m"J!!3B$\rrj$J!!$")!!!-R"rrrcM'!!&m"MJ!3B$rp)!"!,!X!!!!3))!%)J"!+FS!!!!3B)\r!$$J!!#kF(rrr,!8!!%'#!%3i`!!!1'!!-%J!!!bFIrrr1-B!!BJ"!%"m!#K3I!B\r!!%'!rqa)!!!3M!6rrcM'!!'F(rrrI!BS!%'!rr")!!!-1!!!-*`Irrq)!3!mI!!\r(G8'#!"!i!!!YR"rrrdJ!!#b)!3#P+!!!!8##!"!i!!!VR"rrrdJ!!"3S!!!#3))\r!$$J!!##F(rrrIq2lH)!"!)Ji)3#!bq(rq(`)!kD$iIrXJm(rk%k!!#"m#!+Q[U(\rre*!!!3!)P#(pJ(ae'hL3!+%#S(bE)hJlS!!!1q%#0dJ!"QarBpYi1)!!*8J!"m&\rJ!!!!I(`EH#JF!!"!JJ"%If2EH%J!"bPJ!!!!I(iEHAqpmK4"JJC%If2EH(r%mhK\rqTUYi1+!!!8[rh19J!!!!+!-!!%##"L3iB2rr5!!')(rEi&&r[I)83B)!,(pMfhK\rra20iIUDVH$LJ!!&,rpbaB!!!!#J$!!"!JJ!-1'$rrdJ!"HarQq0iIf2EH$L"!U!\riS3)i5rr[kBJ"!MemHaYi,!!!D8'#!+4!J!"B,!!!@%'#!@4!J!!S,!!!48'#!L4\r!J!!3,!!!*8'#!j!!5!!$S#`!!%G"JJ)-5!!$P#`!!'4"JJ"S3)!!%#`!!'0!J!0\r-5!!$I#`!!'K!J!0d5!!"j#`!!(9"JJ%33)!!+#`!!'p"JJ%%3)!!%#`!!'j!J!+\ri5!!$6#`!!(0"JJ)85!!$3#`!!2p"JJ-i3)!$0#`!!(K"JJ$85!!$+)J"!M`S!!!\r#3))!')"K!U!iB`!%N!"K!U#$3rrm5!!!0#J!!!0!JJ!FJ'%#S$KM!!L3!'%#S)-\r$rrb$)rri5!!!&)"K!U!iB`!%N!"K!U#$3rrmL!%#2#J!!!&!JJ!)IeS(0)J"!M`\rS!!!$3))!0)$"!ML!i3)mJ3%#3)%K!N4r)mYiI`6$H$LK!MK,rr5aI(FEH#JA!!"\r"JJ+3!%J!!#b!S3)iJ-%#2)$K!N#"!3*%Id26H$L"!MK,rr*CI(FEH#JA!!""JJ*\rNIpIi8%J!!U5)!3)m+!!!!N##!"L!B3+J1'-!"*!!B3+JJd2rr%J!!$3S!!!$3))\r!()"K!U!iB`!)N!"K!U#$!rrmJb2rq%J!!"5!B3+J1'-!"*!!B3+JJd2rr)J"!M`\rS!!!"3))!#&GD"$k)!3)m+!!!!d##!$5!`3)iJ1%#2)%"!N#")3*%Ib2,H(m%`hJ\riS3)i5rrcjAah'hJS&`!!3B)"a%J!!#b!S3)iJ-%#2)$K!N#"!3*%Id26H$L"!MK\r,rr'0I(FEH#JA!!""JJ'BIpIi8%J!!GL)!3)m+!!!"%##!"L!B3+J1'-!#*!!B3+\rJb#2rq%J!!"5!B3+J1'-!#*!!B3+Jb#2rq)$"!ML!i3)mJ3%#3)%K!N3iS3)i5rr\rh5Aah'hJS&`!!3B)"2(rAq&")!!&mJ'%#S$KM!!53!'%#S),Mrr`S&`!!3))!#$V\rL!M5)!3)l+!!!!%'#!#b)!3)kLpF!!#J!!!!kp`!"3B)"3)!"!N4m(J!!3)%"0(`\rH!hK)!!%XL!%#1LJ!!!""JJ!XJm%#4(lMZhKraI0i1)!!!%[rjK&J!!!!+!-!!%'\r#!3"reaK35!!!q(lMZhK)!!0jB!!!!(aq'hK)!!$NJ'%#S)J"!M`iB`!%N!"K!U!\rX!!!#JZ2rr%'#!$4!J!!8,!!!!%'#!"K!J!!F5!!#A#`!!!4!J!*85!!!(*1h!!"\r)!!*)XlF!!%J!!N#6Y`!!5!!#1*1h!!4rS2j`N!!A!!")!!)SJ'%#S$VK!$JiB`!\r%N!"K!U#!!rrm1m!!!CJA!!")!!"J1Z%!1$J!!#@B&`!!1m!!!8J!!%arJq0i5!!\r#c@!!!!"mIKYjIlhb&%'#!#arJq0iIm6cH(kQUhJiS!!"5rrBL@!!!!!S!`!!3))\r!$$KJrrp)!!(%Ik2VH%J!!Eb)!3)iIpccH#J!!!""JJ$i+!!!!N##!!`k`!!`5!!\r!#$V!!##)&`!!I!!(G#`!!#Y"JJ!-,!!!,8##!-"q`!Gd,!!!-%##!,5!G3!N+!-\r!!$J$rrq3!"8!*%'#!##!G3!JL*F!!$J$!!'3!"8!)*L$!!"8J`Bq5!!!')Kh!!"\rqT+YiI'-(G%[re'&J!!!!,!2rrd##!!`iB2rr5!!")$Vh!!%lh[rr5!!!9)"e!#3\rS!`!!1!2rrj!!&3!N3B)!()#9!#"@``Bq1!3!!C!!&3!JQX3!!%J!!"4q``GdIU5\rVH%[re!PJ!!!!,!2rrd##!!`iB2rr5!!!b$ZF!!'!!3*!I"`!!%'!rkJX(J!!3B)\r!,(lMZhKra20iIUDVH$LJ!!&,rpG0B!!!!#J$!!"!JJ!-1'$rrdJ!!)L)!3)i+!!\r!!%##!'Jk`!!J5!!!9)"e!#3S!`!!1!2rrj!!&3!N3B)!()#9!#"@``Bq1!3!!C!\r!&3!JQX3!!%J!!"3iB!!JIU5VH%[rdfPJ!!!!,!2rrd##!!`iB2rr5!!!+$ZF!!'\r!!3*!I"`!!%'!rkKr[H)8L"X!!(`!"h9!J[Q3!(qMkhL!!3+)1#%#J(`)!kDkSIr\r86S!!)(`)!UD6iIrmNm(rq*1Krr53!!%!#*3Krh"mI4YiI*iMH(br+hKrT1Yi1'%\r!1$LJrrmi`!!"5!!"L@!!!!"ra20iIqAlH$KK!$K,rrN&,!-!!%'!!!`i!!!!I"d\rCVS!"!*Ji)3#3!(`)!kD$iIrmJm(rq)1Krr41J!!JI!J#TT!!!3!)P#(r`*!!S3"\rJN!$"!'53!1%!D*%"!'b4)3"`N8%!G*!!J3"FJ)%!A$LK!'",rrpCJ!%!5$JK!%"\rm#!1Q6S!!)$L!rrmiBrrrM!-!!6L%!!%S!!!!3),rp(b$)hK1J!!J1+6rrcM$rrq\r-K3!"9)!'2jb'!!&!J[rd6S!!)$M%rrmiirrr1+8!!8J!!#b-KJ!"9)!'2jb(!!&\r!JJ!F1!!!!%J!!!LF"`!"0+Arrd##rrK1J!!J0+Arrd##rp41J!!J1'2rre5%"Mj\r)!!!3I!!J3%##!!K1J!!JM!-!!93!"Mp!J[rX+!3!!%f#!#!iB!!!6S!!)$LMrrp\r8K!Bq1'!!!%J!!""m!#"!3))!#(bM+hL-"3!"9!!'2d##rq`S!`!!3B)!#%k!!#!\rS"!!!3B)!$$KJ!!"1J!!JI+-VH%k!!#"m#!+QNq(rr*2"rrL3!!%!#*3Krm"mIKY\riI)FMH(bJ+hKmhc0iJ))#3(r$mhKmj6YiI!B$H%[rc(PJ!!!!L"i!#(r$mhK6i#i\rdQ"i!#%[rcX9J!!!!1'!!!)!"!%Ji)3"!I!J$TS2Krrb$`Iri6S!!)$KJ!!*1J!!\rJ1'!!!%k!!#!iB!!!6S!!)(`)!UD6iIrmNm(rq*1Krr53!!%!#*3Kr["mI4Yi,"d\r!!%'!!"3X(3!#3B%!$$KJ!!")!!#3!$[J!!#ci3"8Xk%!8*2K!%SiB3!i5!!*bB"\r"!"4mIKYiIm!(08##!%#S!3"11'%!H,!"!)kcS3#3!%J!"`@!33!8I(iEH(r!"c9\r!JJ!FU!%!6T2K!)U`!3#11'%!H%J!#CQ!33!8Im!(08'#!"!iBKH`Im!(0*!!!`!\r!Im!(08##!!`iB!!!5!!!#$KJrrq!!3%B1#%"%(`)!kD$iIrmJm(rq)1Krr41J!!\rJ18)KM$PJ!!!i!!!JI!N$TS!+!!JS!!!!3))!+*!!DJ!)N!#+!!b3!+S!%*!!bJ!\r8N!$U!!#4#J!%I@0EH*%U!"K1J!!J1@X!!6P+!"a#!2r)1'$rrdk!!#!X!`!!6B!\r!)#`$!#"-J!!J('-!($L#)B`i!!!!I'3D&*!!!`!)N!!$!!b3!!-!%*!!!`!8N!!\r$!!#3!!-!"*!!!`!B6S!!)(`)!UD6iIrmN!!"!!L8)Ir!1q)P$%J!!##!"3!!1)$\rrrj!!(`!!J'8!#)'&!!4)!!LpJ%%!&)#r!!!S"3!!3),rh)!"!%Ji)3"!I!J$TS2\rKrra1J!!JI%-6H%k!!#"m#!+QN!!"!!L8)Ir!5rrrlAaT'hL!BJ&`J))"E$LL!!!\ri`L83J1)"B)%#!9a,rrlPB!!!!)##!I#3!'3!!%[rSiPJ!!!!1'!!!)!"!%Ji)3"\r!I!J$TNk!!#"m#!+QN!!"!!L8)Ir!5rrr3@!!!!#!BJ(`J'-!!%[rr[&J!!!!J!%\r!5$JK!%"m#!1Q6S!!)#`$!!"mB!!dI)N!0%##!!Ji#3!J,!8!!(bT!$4mbJ!d3))\r!#$NU!#"m!%J!)8!!3%'"!,!j+3!")5N!3(`!5K4p+9"3I5N$TL`*!#!ikIrJ3B!\r!%(aS2$!ii!!!5!!!'(b)6$!Jk3!JI'Fi-(d)1hKmCd``,!!!)$%Jrq""J!!3I)0\r)-$L!!!")!!!BI'-!-#%J!#"mL8``I'0,H(b%!$!j32rr-1F!!(b%)44mBaN8I3K\r"&(cR144m"N!3I58j%8'!!""m#!0iI5G,H$!+!!&#!2rBI)3K&(aM'441J!!J1)!\r!!$KJ!!"1J!!J,!-!!(aJ!$4mL3!d3))!#$J*!#!X"3!!I+N!0(c+!$4!JJ!)15S\r!)(`!5!!K3!"!3B%!X$NT!!%K+3"!I!"+&(dT8&"p+31Q,!N!)$MTrq""J!!3I'J\rm-$MJ!!")!!!BI)K--#$T!#"mCcJ`I3JlH(aR6$!X!!!J-5$ri%'!!""mJdJ`1)!\r!!%J!!"KmB`!`)5!!)(b*6$"mBdYiI)3!-$P!rrm`j`!!I)3K&(aM'44p#%%8I1F\rj&(`'3""p*6N43B!!%(`)!hKp*dYi-!S!!8)!rpKp"%0iI1-lH%k!!#"1J!!JJB)\r!k*!!33!8J!`!!)"-!!4m#31Q6S!%))'#!1#3!%%!&)!-!!#!6!!%I!N$TNk!"##\r"JJ$%N!""!"5!$!!!J%`!"(`*!kC1J!3JJB)!,*!!33!8J!`!!)"-!!4m#31Q6S!\r%))'#!*!!N!""!"5!$!!!J%`!"(`*!kC1J!3JJB)!5*!!33!8J!`!!)"-!!4m#31\rQ6S!%))'#!(53!%%!&)!-!!#!6!!%I!N$TNk!"##"JJ$dN!""!"5!$!!!J%`!"(`\r*!kC1J!3JJB)!d*!!33!8J!`!!)"-!!4m#31Q6S!%))'#!-b3!%%!&)!-!!#!6!!\r%I!N$TNk!"##"JJ!3N!""!"5!$!!!J%`!"(`*!kC1J!3JJB)!"*!!33!8J!`!!)"\r-!!4m#31Q6S!%))'#!-L3!%%!&)!-!!#!6!!%I!N$TNk!"##"JJ$NN!""!"5!$!!\r!J%`!"(`*!kC1J!3JJB)!Z*!!33!8J!`!!)"-!!4m#31Q6S!%))'#!$53!%%!&)!\r-!!#!6!!%I!N$TNk!"##"JJ"!N!""!"5!$!!!J%`!"(`*!kC1J!3JJB)!$*!!33!\r8J!`!!)"-!!4m#31Q6S!%))'#!#53!%%!&)!-!!#!6!!%I!N$TNk!"##"JJ!8N!"\r"!"5!$!!!J%`!"(`*!kC1J!3JJB)!q*!!33!8J!`!!)"-!!4m#31Q6S!%))'#!)#\r3!%%!&)!-!!#!6!!%I!N$TNk!"##"JJ#XN!""!"5!$!!!J%`!"(`*!kC1J!3JJB)\r!B*!!33!8J!`!!)"-!!4m#31Q6S!%))'#!,b3!%%!&)!-!!#!6!!%I!N$TNk!"##\r"JJ%!N!""!"5!$!!!J%`!"(`*!kC1J!3JJB)!9*!!33!8J!`!!)"-!!4m#31Q6S!\r%))'#!-#3!%%!&)!-!!#!6!!%I!N$TNk!"##"JJ$8N!""!"5!$!!!J%`!"(`*!kC\r1J!3JJB)!H*!!33!8J!`!!)"-!!4m#31Q6S!%))'#!$#3!%%!&)!-!!#!6!!%I!N\r$TNk!"##"JJ!)N!""!"5!$!!!J%`!"(`*!kC1J!3JJB)!'*!!33!8J!`!!)"-!!4\rm#31Q6S!%))'#!*L3!%%!&)!-!!#!6!!%I!N$TNk!"##"JJ$FN!""!"5!$!!!J%`\r!"(`*!kC1J!3JJB)!L*!!33!8J!`!!)"-!!4m#31Q6S!%))'#!,#3!%%!&)!-!!#\r!6!!%I!N$TNk!"##"JJ#8N!""!"5!$!!!J%`!"(`*!kC1J!3JJB)""*!!33!8J!`\r!!)"-!!4m#31Q6S!%))'#!$L3!%%!&)!-!!#!6!!%I!N$TNk!"##"JJ"SN!""!"5\r!$!!!J%`!"(`*!kC1J!3JJB)!C*!!33!8J!`!!)"-!!4m#31Q6S!%))'#!+#3!%%\r!&)!-!!#!6!!%I!N$TNk!"##"JJ"-N!""!"5!$!!!J%`!"(`*!kC1J!3JJB)!E*!\r!33!8J!`!!)"-!!4m#31Q6S!%))'#!&#3!%%!&)!-!!#!6!!%I!N$TNk!"##"JJ"\r%N!""!"5!$!!!J%`!"(`*!kC1J!3JJB)!M*!!33!8J!`!!)"-!!4m#31Q6S!%))'\r#!)53!%%!&)!-!!#!6!!%I!N$TNk!"##"JJ$XN!""!"5!$!!!J%`!"(`*!kC1J!3\rJJB)!r*!!33!8J!`!!)"-!!4m#31Q6S!%))'#!!#3!%%!&)!-!!#!6!!%I!N$TNk\r!"##"JJ!FN!""!"5!$!!!J%`!"(`*!kC1J!3JJB)!A*!!33!8J!`!!)"-!!4m#31\rQ6S!%))'#!$b3!%%!&)!-!!#!6!!%I!N$TNk!"##"JJ#FN!""!"5!$!!!J%`!"(`\r*!kC1J!3JJB)!+*!!33!8J!`!!)"-!!4m#31Q6S!%))'#!,53!%%!&)!-!!#!6!!\r%I!N$TNk!"##"JJ#NN!""!"5!$!!!J%`!"(`*!kC1J!3JJB)!m*!!33!8J!`!!)"\r-!!4m#31Q6S!%))'#!(b3!%%!&)!-!!#!6!!%I!N$TNk!"##"JJ!JN!""!"5!$!!\r!J%`!"(`*!kC1J!3JJB)!U*!!33!8J!`!!)"-!!4m#31Q6S!%))'#!(#3!%%!&)!\r-!!#!6!!%I!N$TNk!"##"JJ"BN!""!"5!$!!!J%`!"(`*!kC1J!3JJB)!f*!!33!\r8J!`!!)"-!!4m#31Q6S!%))!-!!#3!%%!&(`*!kD!6!!%6S!%)!!!!"b!!!"N#!#\r3"TL!!!#N'!#3"3%mJ!!!G"!!N!8"X)!!!-!B!*!&!R#!!!$S+!#3"30BJ!!!k!J\r!N!8%3)!!!3`3!*!&"8b!!!"S!*!'"E5!!!#8%!#3"3C)J!!!2!J!N!8'K)!!!$`\r!N!B'`)!!!'33!*!&"b5!!!%8'!#3"3JiJ!!!`"!!N!8)q)!!!33S!*!&#JL!!!"\rB%!#3"3TJJ!!"C#!!N!8,a)!!!-33!*!&$)L!!!%F'!#3"3fNJ!!!I!J!N!81))!\r!!)`)!*!&$V#!!!#d#!#3"3pNJ!!!G!J!N!83*)!!!'`)!*!&%*!!J!!"C$!!N!8\r4p)!!!&J)!*!&%Nb!!!'!3!#3"42-J!!"1$!!N!89")!!!P4S!*!&&eL!!!%i+!#\r3"4L3!)!!!&3!N!BBj)!!!&`!N!BC3)!!!(!!N!BCX)!!!(!!N!BD))!!!9!J!*!\r&'h#!!!#)!*!''rL!!!(!'!#3"4fiJ!!"!!J!N!8HZ)!!!*33!*!&(db!!!#B%!#\r3"4rNJ!!$@%!!N!8MF)!!!%!)!*!&)l#!!!#8+!#3"54%J!!!9"!!N!8NQ)!!!,!\rJ!*!&*8L!!!"%!*!'@q#!!!"8#!#3"9`mJ!!!@!#3"Pb8J!!!0!#3$B)+)K2dJJ)\rA&(JAX"4m&)J#i!,S![!#X!,!!XJ#Z!2i!SJ8J!+3!"5%!Y!#f!h3*3aR+'6F*4!\r%)QFS"L)4r))#(a(d!I`3m3*)%Z!#!!*3![d5H!,i%K!8@"3i&"J6q!-$!PJ$dJ2\r*!hi$B!0-!Q!AY"$X%'J2j!l3$k!KM!*%(L%r&b0*EQB")djK6JdL(F!))JS)KJ)\r8#I`4p"SJ(q3P5#5B*B`PS#H`,VJZ3#fi0k!eP$6N0""#"%(J@QKDB#*D@!3J-`3\rZ59"3"@K[Fh4c*h0[BfYPG&pPGQ9ZG&pSB@jNE'9b1L"cEf0VCA3JEQpd)'PZ)(9\rcC3%MU[i(#b,Ap3%K!3%K"!)L!QJ))$%69'9cG&4bB@0V)&9cCA)J5@jQEd9bFQp\rb)#9N)%GPG(4TEQFJ8hPc)%9ZGQPbEfjc!5"+4@jf9Q9b)#9N)'eKBfK8HA"P)#9\rN)(0jFeCPFL!PC#"`FQpM)#9N)%C395!PC#"$Efa[FP&%)#9N)'YLC#!PC#"KG&C\rPFR-J*@3"+#9c1L9c1L9c!590B@028`%MU[i($#%P!5%"!5%%!L)#J!`K#a8L&,!\r#)3%$)K5`&L)#U!)L!U!#)J+B##%6&5)9X!)K!3-L&E!@)J+S!L)#S!)L!TJ))4%\r9)KD`!L%"!b)@X"BL!UJ#)J+J!L)#Q!#5"##"I`'3#3+3"3'3%J3)N!m`N!S)N!H\rJN!D!N"3)N!CJN!C!N"3)N!3"J*!(3*!C#*!(3!L3"S#!#*!13%!)N!Z!N!4!#*!\r)3)!)N!4!3!L3"B#3#`L!N!3)N!S$)N8JJJ+""8A343a&d%A34G"&d%A34G"&d%A\r34G"&d%A34G"&d%A34G"&d%6)4G"&d%A34G"&d%A34G"&d%A34G"&I%6)45"&)%8\r-4G"%b%A34G"&d%A34EK%b%9B4G"&d%@J4G"%b%A34G"%b%,)3`"$!%,J3`"$!%-\r!3`"$!%-!3`"#`%-!3V4$!%-!3ZK'Y%E!4X"'`%E!4X"'`%E!4X"'`%E!4X"'I%E\r!4X"'`%E!4Ra'`%E!4X"'`%E!4T4'`%E!4X"'`%E!4U4'`%E!4V4*)%NX55a*,%N\rX55a*,%NX55a*,%NX55a)c%NX55a*,%NX5-a*,%NX55a*,%NX53"*,%NX55a*,%N\rX54"*,%NX*NNJ,8PZCJ'j&J!!!3!!!!(p!!!!r3!!!&S!N2-4GQ9bFfP[ER-ZE@P\rd,Q9NG3#3"%J!3B!!!!!&-#id,M%l-#id,M%X)%0[F(PbD@GSG#!a16Nh)%eKFh0\rKBfKeFf9dG(-J5@jcG'PdGA4P)'pQ)&4PBfKZEfa[ChN!!!#B!*!,!3#3%`*Y0MK\rV!*!6!3#3"PES!*!*2"&0594IT94PFh48FQ&MDdaTBR"hF'-!N"-"!!"@m!!!F8d\r!N!Nm%8e*9&qP9'9cG&4bB@0V6'PL!!!"!!!!!Id!!!$p!!!!@JG,jj!!64i!!!!\rF!&S!!N069&)!!!!DGQ9bF`!!!#CMCR*R!!!!-J4-rrm!N!N"rrm!!!!9!*!'rrm\r!!!"K"e'ZQ+%S:\r
\ No newline at end of file
diff --git a/src/mac/TestTrack/ShlibTestTrack.c b/src/mac/TestTrack/ShlibTestTrack.c
deleted file mode 100644 (file)
index 01c69f6..0000000
+++ /dev/null
@@ -1,115 +0,0 @@
-/*
- *   Copyright (C) 1997 by the Massachusetts Institute of Technology
- *   All rights reserved.
- *
- *   For copying and distribution information, please see the file
- *   COPYRIGHT.
- */
-
-short MacOSErr;
-
-#include <CodeFragments.h>
-#include <Processes.h>
-/* sarac 02/19/98, added Sound.h for SysBeep() */
-#include <Sound.h>
-
-#include "TestTrackLib.h"
-
-#define TBALERTID      135
-#define TB30ALERTID    136
-
-struct VersionResourceRecord {
-               Byte majorRev;                                                                  /* Major revision in BCD*/
-               Byte minorRev;                                                                  /* Minor vevision in BCD*/
-               Byte releaseStage;
-               Byte nonReleaseRev;                                                             /* Non-final release #  */
-               short countryCode;                                                              /* Region code                  */
-               Str255 shortVersNumStr;                                                 /* Short version number */
-               Str255 longVersNumStr;                                                  /* Long version number  */
-};
-
-typedef struct VersionResourceRecord VersionResourceRecord, *VersionResourcePtr, **VersionResourceHandle;
-
-OSErr ShlibTestTrack(CFragInitBlockPtr ibp);
-
-OSErr ShlibTestTrack(CFragInitBlockPtr ibp)
-{
-       OSErr                                   err = noErr;
-       short                                   fileRefNum, saveRes, processResFile;
-       ProcessSerialNumber             thePSN;
-       ProcessInfoRec                  thePIR;
-       FSSpec                                  currAppSpec;
-       VersionResourceHandle   versResource;
-       char versionString[256];
-       char processSignature[5];
-       short len, i;
-       
-       if ( (Ptr) test_track != (Ptr) kUnresolvedCFragSymbolAddress ) {
-               /* Start our hack by saving the current resource ref*/
-               
-               saveRes = CurResFile();
-               
-/*             if (ibp->fragLocator.where == kDataForkCFragLocator)
-               { 
-                       fileRefNum = FSpOpenResFile(ibp->fragLocator.u.onDisk.fileSpec, fsRdPerm);
-               
-                       if ( fileRefNum == -1 )
-                               err = ResError();
-               }*/
-               
-               /* We assume that the current process is the one calling us. Good bet */
-               err = GetCurrentProcess( &thePSN );
-               
-               if ( err == noErr )
-               {
-                       /* fill in required fields for the ProcessInfoRec */
-                       thePIR.processInfoLength = sizeof(ProcessInfoRec);
-                       thePIR.processName = nil;
-                       thePIR.processAppSpec = &currAppSpec;
-                       
-                       GetProcessInformation( &thePSN, &thePIR );
-                       
-                       /* copy the processSignature into a string */
-                   BlockMoveData (&(thePIR.processSignature),&processSignature,sizeof(OSType));
-                       processSignature[4] = '\0';
-                       
-/*                     processResFile = FSpOpenResFile(&currAppSpec, fsRdPerm);
-                       err = ResError();*/
-                       
-                       if (err == noErr)
-                       {
-                               versResource = (VersionResourceHandle)GetResource('vers',1);
-                               
-                               if (versResource != nil)
-                               {
-                                       /* Make a local C-string copy of the short version number string (a Pascall string) */
-                                       HLock((Handle)versResource);
-                                       len = ((**versResource).shortVersNumStr)[0];
-                                       for (i = 1; i <= len; i++)
-                                               versionString[i-1] = ((**versResource).shortVersNumStr)[i];
-                                       versionString[len] = '\0';
-                                       HUnlock((Handle)versResource);
-                                       
-                                       ReleaseResource((Handle)versResource);
-                               }
-                       }
-                       
-                       if ( thePIR.processType == 'APPL' )
-                       {
-                               if (test_track(processSignature, versionString, true, true, 0) == -1) {
-                                       SysBeep(10);
-                                       SysBeep(10);
-                                       
-                                       ExitToShell();
-                               }
-                       }
-               }
-               /*if ( fileRefNum != -1 )
-                       CloseResFile( fileRefNum );*/
-                       
-               UseResFile( saveRes );
-       
-       }
-               
-       return err;
-}
diff --git a/src/mac/TestTrack/ShlibTestTrack.h b/src/mac/TestTrack/ShlibTestTrack.h
deleted file mode 100644 (file)
index 12e656b..0000000
+++ /dev/null
@@ -1,19 +0,0 @@
-/*
- *   Copyright (C) 1997 by the Massachusetts Institute of Technology
- *   All rights reserved.
- *
- *   For copying and distribution information, please see the file
- *   COPYRIGHT.
- */
-
-#ifndef __SHLIB_TESTTRACK__
-#define __SHLIB_TESTTRACK__
-
-#include <CodeFragments.h>
-
-/*     Special version of TestTrack for shared libraries -- uses calling application's
-       version information */
-
-OSErr ShlibTestTrack(CFragInitBlockPtr ibp);
-
-#endif /* __SHLIB_TESTTRACK__ */
\ No newline at end of file
diff --git a/src/mac/TestTrack/TestTrackLib.h b/src/mac/TestTrack/TestTrackLib.h
deleted file mode 100644 (file)
index b005b1c..0000000
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- *   Copyright (C) 1992 by the Massachusetts Institute of Technology
- *   All rights reserved.
- *
- *   For copying and distribution information, please see the file
- *   COPYRIGHT.
- */
-/*
- * Function prototypes for testtrack routines - shared library version
- */
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#if GENERATINGCFM
-
-#define InitializeMacAthenaLib()
-#define TerminateMacAthenaLib()
-
-       #if defined(__CFM68K__)
-               #pragma import on
-
-               extern int test_track(char *appl_name, char *appl_vers, Boolean edit_flag,
-                              Boolean do_logging, int check_probability);
-               extern short GetBSDMacOSError( void );
-
-               #pragma import reset
-       #else
-
-               int test_track(char *appl_name, char *appl_vers, Boolean edit_flag,
-                              Boolean do_logging, int check_probability);
-               short GetBSDMacOSError( void );
-
-       #endif                  /* endif __CFM68K__ */
-
-#else                  /* else GENERATINGCFM */
-
-       typedef int (*test_trackProcPtr) (char *appl_name, char *appl_vers, Boolean edit_flag,
-                      Boolean do_logging, int check_probability);
-       typedef short (*GetBSDMacOSErrorProcPtr) (void);
-
-       extern test_trackProcPtr                gtest_trackGlue;
-       extern GetBSDMacOSErrorProcPtr  gGetBSDMacOSErrorGlue;
-
-       #define test_track(appl_name, appl_vers, edit_flag, do_logging, check_probability)\
-                       ((gtest_trackGlue)(appl_name, appl_vers, edit_flag, do_logging, check_probability))
-       #define GetBSDMacOSError()\
-                       ((gGetBSDMacOSErrorGlue)())
-        
-       OSErr InializeMacAthenaLib (void);
-       OSErr TerminateMacAthenaLib (void);
-
-#endif                 /* endif GENERATINGCFM */
-
-
-#ifdef __cplusplus
-}
-#endif
diff --git a/src/mac/TestTrack/testtrack.h b/src/mac/TestTrack/testtrack.h
deleted file mode 100644 (file)
index 167340b..0000000
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- *   Copyright (C) 1992 by the Massachusetts Institute of Technology
- *   All rights reserved.
- *
- *   For copying and distribution information, please see the file
- *   COPYRIGHT.
- */
-/*
- * Function prototypes for testtrack routines
- */
-
-
-OSErr tt_open_MacTCP(short *drvrRefNum);       /* Pass NULL if you feel like it*/
-
-
-/* function prototypes from tt.c */
-void tt_acknowledge(char *control, ...);
-void tt_fatal_error(char *control, ...);
-void tt_ensure(OSErr errcode, char *message);
-int tt_edit_user_info(struct tt_user_info **user);
-void tt_install_callback (int (*callback)(struct v_pkt *));
-int test_track(char *appl_name, char *appl_vers, Boolean edit_flag,
-              Boolean do_logging, int check_probability);
-
-
-/* function prototypes from vlib.c */
-void v_parse_pkt (struct v_pkt *pkt, struct v_info *info);
-int v_read_pkt (int sock, struct v_pkt *pkt, struct v_info *info,
-               struct sockaddr *sa, int *sockaddr_len);
-int v_assemble_pkt (struct v_pkt *pkt, struct v_info *info);
diff --git a/src/mac/libraries/CCache API/bin/CCacheGlobalsLib.68K b/src/mac/libraries/CCache API/bin/CCacheGlobalsLib.68K
deleted file mode 100644 (file)
index c876252..0000000
+++ /dev/null
@@ -1 +0,0 @@
-(This file must be converted with BinHex 4.0)\r:&%0$B@0SC8GXEf*KE(0-D@)Z0MK,!(0SE')rN!3!N!3"#J!!!CBl&%T[H5&`C@C\rQE6BiD`!!!!'b#cB`!*!0!`!#!*!EP!!"!J#3"!8!N!G)!!!!5!!!!!m!!!#8!J%\r#!*!%$J#3$fB!!!#N"!%#!%eKD@i!*8%e9fpbE'3!6'pKC'9b!*!&+L)r2!%M"UR\r`!L,rr443rj!%!*!%rj!%!*!%rj!%!*!2!3!!!%3!!!"%!!!!8!!!!!%!!!!"!!%\r!N!TR3fjdFQa#E'pMD`!!"!#3"3%!#eP3!3#3"J3!!Ble!!!"!!!!!@3!!!"N!!!\r!-J#31'!!!!""F("X!*"!B!!!!%e06%)!N#"-D@)J5@e`Eh*d)&"33`#3&Ne36%B\r!N#0J!*!,!3#3%`&Y0MKV!*!6!3#3%8!968P8Ak9$3f&MD'9(E'pLB@ac6'PL!!!\r"!!!!!@3!!!"N!!!!-J9@1G!cb!!!!"`!-J!!BfCbC`!!!!S!!2rr!*!)q0d:\r
\ No newline at end of file
diff --git a/src/mac/libraries/CCache API/bin/CCacheGlobalsLib.PPC b/src/mac/libraries/CCache API/bin/CCacheGlobalsLib.PPC
deleted file mode 100644 (file)
index 67940ed..0000000
+++ /dev/null
@@ -1 +0,0 @@
-(This file must be converted with BinHex 4.0)\r:&%0$B@0SC8GXEf*KE(0-D@)Z8&"$!(0SE')rN!3!N!A`!!!"PU")5Qpj)A"PCQC\r`Gh"M!!!!!E*6cT3!N!d$!!)!N!6rN!3!N"2`!!3%!2q3"!#3"`J!N![`!J3%!2q\r3"!#3$fB!!!#!"!3%!*!&rj!%!*!%rj!%!*!%rj!%!*!2!3!!!%3!!!"%!!!!8!!\r!!!%!!!!"!!%!N!TR3fjdFQa#E'pMD`!!"!#3"3%!#eP3!3#3#!%!N!T+,`!!!3!\r!!!&N!!!!C!!!!$)!N%`3!!!!,`)!!!!#!!!6!!F"!!%!N"!(!3!"!*!3!3%!N!S\r(!3!"!3!"!3!!!!%!!!d!!3#3"4&KER0TAh"bC@CTH#jYB@-ZD!#3%!%"!!!!!3!\r!!!%!N!3"!*!&"3'3"`#3"J%!!!P0CA*R!!!!B!#3#`%!N"-"F(G`B`#3%`%!N"&\r!&8e*9&qP3d0KBfKP4fa[BQ&XFdaTBJ!!!3!!!!&N!!!!C!!!!$)&9MR30#B!!!!\rF!$)!!'0QFQF!!!!+!!$rr`#3"!9EF&$%G`:\r
\ No newline at end of file
diff --git a/src/mac/libraries/CCache API/bin/CCacheLib.68K b/src/mac/libraries/CCache API/bin/CCacheLib.68K
deleted file mode 100644 (file)
index ba927ec..0000000
+++ /dev/null
@@ -1 +0,0 @@
-(This file must be converted with BinHex 4.0)\r:$80$B@0SC8aTBLif1%X!FfKXBN0"*%J"!!!!(ei!!!'5RAj+EhNKF'9QCQdf1'X\r!!!!"XJXf03#3$3-!!J#3$KM+!!!BbJ!!'-S!!!#8!!%#!*!%"3#3"J*i!!!#H!!\r!!D-!!"PJ!J%#!*!%$J#3$J4D!!!E"!3"!J"0B@PZ!#9"09G[FQaN!%a[B@4PFJ#\r3"#T451FB1#4[!"JS,`!F*Lm!)#K[!#3JEIpi*P!J#fBb5(J!%'(r!!!-1#5!*P)\rJ#fB%F!CJ2N+V!!3J8N+3!#"53UJ!##"53UJ!$#"YrhJJNQ!#*)Y`!EL!E`4`#@!\r@5S0R"L"$F!%JJ#!-C`BJEIrm+*!!F!"-ha`B6R3!%#T451F!-#4[!!`J#QFB*P)\rJ#fF5,`YKr`!!&L![%Q(r!!!+Z'!%F!TJ"%+5F!"-h``!6R3!"#T451FH1#C[!#!\rQ,`!N,#m!+#K[!#`U,`!`+#m!0#!,CJC`#Q!!!0C+K'B'F!aJ!!$-5(J#*Q(r!!!\r,G#4!)!TQ"R!'B!!!YNU$Ca)J3h$r8S"+''Ek$)!!!!$rC3C`!@!!!*SJ5L*$)!J\r3f@Em)!aR%L"-F2p5J%SBC[S-J!!!!2pP"(!-B(4"kJ%%)N`J#"$CC[`P43)-3QS\r#"#9'!3!9I!!#!K"`C#9!!K)[#Q(r!!!,1L9!!JK+UJ))CJ4`"Q!k5UX!#'B33US\r#)N+U!KiQLLG+!!4J&L"V!!3K5J)H*@X!"!)L3US#(LG+!!45U`!)8UX!$#"%))T\r`!%cI((K1G!!B+P&19[ri51FH2#SZ!!JSEJ!-+#i!%#CZ!"Kf!%U&CJC`#Q!!!*S\rJ#fB'F!aJ!!#3!#!-CN`JEIq),""`!Eb!CKj`!5m!5(J!UbmYrr3[,Iri)QhrM#"\rC6T!!+Qlrp'!LF!5mJ'BFF!%[!%Ki!+X[,Ird,bhrq#*Yri`J@8k3!#TZrr3J454\r3B#)[#Lm-)QhrJ#"C6T!!+Qlrp%U!CJUiUJ%!CJ4f!@!%*'S#(L!+C`4+!fI@5J0\rR"LD+F!"J"%+6F!T-haai6Pj1G!!8+P&19[ri51F32#KZ!!JNEJ!-)!aQ"(!+B(`\rJ#QB%F!aJG%U5CN`JEIq)*K"`!ED!CKj`!5m!5(J!c5mYrr3[,Ir`)QhrM#"C6T!\r!+Qlrp'!LF!5fJ'BFF!%[!%Ki!-d[,Ird,bhrm#*Yri`J@8k3!#TZrr3Q8J`V!!%\r#%'F%F!jJ&Lm,,`aKr`!!%&3[#f(r!!!)5%+5F!"-ha`)6Pj1G!!)+P&19[ri51F\rB2#CZ!!JSEJ!-)!YQ"R!+B!!!hL!-CJC`$'!!!04+P'C-)'hrL#B3F!'fJ'BHF!%\r[!%Ki!1X[,Ird,bhrm#*Yri`J@8k3!#TZrr4J)R!%YS"Q((!",`")H!$V,bhrp#m\rYrr!LEIq-)&P1N!!UE[rd*&4`C,#U!K*R%#m+BIm!!"155J"Q"(!)B'K+UJ)LCK!\rQUJ)H*LS#(QF')%0#U!)L5US#(QB5*fS#)J!%*LS#)QF')%0#U!)H+#S#)QF@*LS\r#(QF3)%-K4!)L)'S#)L&U!Ki#(K9m!!%#%#m-,`XLEIrX)&P1N!!UE[rd*J"5U`!\r-)!0-ha`B6Pj1G!!)+P%LE`!%)'m!##!*CJ4`#Q!1)!KR###T!!a`!'!#F!a1G!!\r)+P&)ja!`*Qm!%#4[!"3J#fB%F!TJ5#!+CJ4`#Q"!*LS#%R"NYS"R&R"QYS"Q$#m\r+BIm!!"+q5J"Q"(!)B#![,`!F,bm!(#m+BIm!!!dJ*J"+JfB%8UX!#&+V!!`J!dc\rI$!K1G!!3+P&)ja!`*Qm!%#4[!"3J#fF%)!TQ"(!+B$BQ+J)5F'5fJ'F@F'DfJ'B\r-,`TKr`!!%Pa+!'B%F!KJ&Lm[!"`[,`!F,`TKr`!!$E*5U`!-F!"-h``)6R3!%#T\r46PErq%MR'$`QEJ!)*'i!$#JZ!"!SEJ!8)!YR"#!+CJC`#Q!!!*JJ$'C-)'hrL#B\r3F!'fJ'BHF!%[!%Ki!@X[,Ird,bhrj#*Yri`J@8k3!#TZrr4J)R!%YS"Q((!",`"\r)H!&V,bhrp#mYrq3LEIq-)&P1N!!UE[rd*LS#%R"NYS"R&R"QYS"Q$#m+BIm!!"'\rQ5J"Q"(!)B#DiUJ%!C`4`#Q!F5(J!rbm-5'S""#*Yrh`J@8k3!#TZrr45U`!-F!"\r-ha`B6Pj1G!!3+P&)j`!i*'m!&#C[!"JJ#QB%F!TJ3("QX+S#%QB3,`TKr`!!%8K\r+!'B%F!KJ+#!,Cb*)H!$rBIm!!!88*S!S8b!-CJ4`"Q!1)%a$kJ%%)!J3f@EmF!"\r-ha`!6R3!$#T451F!-#4[!"!QE`!8)!TQ"(!+B#C`CV#U!K*Q%#m+BIm!!"$U5J"\rQ"(!)B!iJ#fB%F!CJ"LDU!3"`!%cI$!"1G!!-+P&)j`!`*'m!%#C[!"3J#QB%F!T\rJ0("QX+S#%QB3,`TKr`!!%+C+!'B%F!KJ(#!,CaC)H!$rBIm!!!4b*S!J8b*+)!J\r3f@EmF!"-h``!6R3!$#T451FB1#J[!"JSE`!F*'m!)#!-C`JJ#QF%5S4Q"(!+B%K\r+NQBD5(J!#'(r!!!%,#5!*K*Q"(!'B$!J4#*$)T!!)&)Q%'B3,a*Kr`!!"%a#NN+\r8F!0J&#m-,`0Kr`!!$GSQ8L"6*UJ#(R!!60mF'%jd!!`U88MR($K46bB[!#3QE`!\rS+'m!,#4[!$!J#fF))!TR"%U$CJC`#Q!!!6`J$'B'F!CJ!!%bF'D`U`)5CK)[#f(\rr!!!2a%S!CJC`#'!!!4K+NQBN5(J!#'(r!!!$ML5!*K*Q"R!'B!!!rL"$3UJ!"'!\r')%05U!!%1LX#"$!&5-!Q%L"$+#J!",L!E")J"1@))'X###"`#!"`Bl#3!'I8-!9\r)`,L!E4)[%Q(r!!!$I%+83T*`!f!!!,!J"1@))'X###S`#!!J45B3F!'fJ'CS5(J\r!#'(r!!!$&#L!5T4Q"R!'B!!!K%Ki(AjKr`!!![iJ9#&!!!3J9#BS!!4Q"(!'B'B\rJ8L!S!!6PL#"V!JJJF!J!)'J!"#*$)$`!!"eqFL#`J@8%SLjJ$NU!C`SL#4,B8i"\rQqL*"B#K`!VD!CK`[D!!%!!4`!Lk!,``[,`!),bm!#'(r!!!(KQ!'3T4`%'!))&*\r5U!!%F!"36dcI($K1G!!3+P&19[ri51FB2#KZ!!JNEJ!-H!!J$'B'F!TJ!!#F)!T\rQ"R!'B!!!NL!X!!K5J1@),`!LEIqX)&P1N!!UE[rd*)"+NQB%F!CJF#C8B'K)H!)\r#)QhrV#"C6T!!+Qlrp#"5)B!i!#K55V3i!'B%F!CJ5L"d1!!L5b!)%0PQr#"5)(!\ri!%(S!2p$k`%%)!J3f@Em)&)JF$J!)@X"!!(q*QX#(P+%@)-J#fDQ)!6PL#"53V!\r)!(!!B!4f!'$U60mF'%jH6R3!##T4,`SNE`!-)!TQ"(!'B!S[#Q(r!!!"i(!!*&p\r1G!!)+P%[#L4[!!`J#QB%F!CJ#Lm+BIm!!!(!F!!NAdjd!!JU85m+*'m!$#!+CJ4\r`#Q!8,a*Kr`!!$MJ[%Q(r!!!"Q%+5F!!NAdjd!!JU88j@rrK)jaJd*'i!$#!+CJ4\r`#Q!iH!"J-#mc1!!LEIqF)&P1N!!UE[rd8S4BJbC55V-i!'EN,a)LEIqF)&P1N!!\rUE[rd3T*`!'!%GJ"Ji%cI$"K1ANjd!!JU88j@rqa)ja!N*'i!$#BZ!"!J#QB'F!a\rJ!!$15'lrm#*YrkJJ@8k3!#TZrqK`C,#U!K*R'%KZrqp)DJ)@5'lrm#*Yrk3J@8k\r3!#TZrqJJ!e1!C`a6J'F58i"R0Q!!!)C`C#9!!K*J!!#!*LS#%R"NYS"Q&("P*8!\r#%L9Zrr!#&L9Zrr3#'Q"JF'DfJ'CDF!KJ@#BU!K*`C,D!CK4`CL9!!K)PE[r`!KB\rPE[rd!KTJ1("QYS"Q#NSZrqpQ"(!)B#T`CED!CL*+,[r[Ca4`CL9!!K)PE[r`!KB\rPE[rd!KTJ#(!)B!C`$'!#F!"-h`3)6Pj1G!!-+P&19[ri51F3*#BZ!!J[!b*Yrk`\rJ@8k3!#TZrr3N3#!+Ca![!bm+)QhrQ#"C6T!!+Qlrp#!+60m%#%jH6R3!"#T46PE\rrq%MR'#3NEJ!),`SLEIqJ)&P1N!!UE[rd*J!J#QC-)'hrL#J3F!'iJ'BHF!%[!%K\ri!#F[,IrB,bhrh#*Yri`J@8k3!#TZrr4J)R!%Z)"Q((!",`")H!!R,bhrf#mYrp`\rLEIq-)&P1N!!UE[rd5S0Z6#"YriJS%(!"Z)"Q(R!",`")H!!S,bhrf#mYrp3LEIq\r-)&P1N!!UE[rdB#*`",L!CKa`!5m!5(J!+#mYrpJ[,Ir8)QhrM#"C6T!!+Qlrp#m\r$3UF[#L*Yri3J@8k3!#TZrr3[!d+R,`SLEIq%)&P1N!!UE[rd,`-[#L*Yrj3J@8k\r3!#TZrr3[#L*Yrj`J@8k3!#TZrr4-h`3B6Pj1G!!%+P&19[ri51F3*#BZ!!J[!b*\rYrj!!)&P1N!!UE[rd*%!J#QF3,`-[#L*YrjJJ@8k3!#TZrr3J#NcI"!K1ANjd!!3\rU88j@rrK)ja!N*'i!##!+CN`JEIq)*K"`!ED!CKj`!5m!5(J!8#mYrpJ[,Ir3)Qh\rrM#"C6T!!+Qlrp'!LF!5fJ'BFF!%[!%Ki!&![,IrB,bhrd#*Yri`J@8k3!#TZrr4\r#DJ)%0A`!#J)'5(J!+'(rN!4@*8!###!U!JK-h`3)6Pj1G!!%+P&19[ri51F30#4\rZ!!JJ#QC-)'hrL#B3F!'fJ'BHF!%[!%Ki!&i[,IrB,bhrc#*Yri`J@8k3!#TZrr4\rJ)R!%YS"Q((!",`")H!"H,bhrf#mYrm`LEIq-)&P1N!!UE[rd*+i!$#9Z!"!!"%U\rZ!"4Q#%+U!!K`!'!q,bi!%'(rrrrqa#9!!!JQDJ!))!YQ"(!'B#3L5b"Z!"3J,J!\r3FL#`J@8%SLjJ$NU!C`SL#4,B8i"QqL*"F!"-h``)6Pj1G!!3+P&19[ri51FH2#K\rZ!!JNEJ!-H!!J#QC-)'hrL#S3F!'kJ'BHF!%[!%Ki!(3[,IrB,bhrb#*Yri`J@8k\r3!#TZrr4J)R!%ZS"Q((!",`")H!"d,bhrf#mYrmJLEIq-)&P1N!!UE[rd*N`J$'B\r)3T*J!!'`8S4+QfEk)!45J1@),`"KrrrrrJ)NJ#S!5S9Q6#"YriJX%(!"[)"Q(R!\r",`")H!"m,bhrf#mYrm3LEIq-)&P1N!!UE[rdB#*`",b!CKa`!5m!5(J!I#mYrpJ\r[,Ir%)QhrM#"C6T!!+Qlrp%U&C`!"3LC-B!!"+NKi!!aKrrrrrCJJ8L#!)&*+N!"\rQ6#"YriJX%(!"[)"Q(R!",`")H!#$,bhrf#mYrm!LEIq-)&P1N!!UE[rdB#*`",b\r!CKa`!5m!5(J!JbmYrpJ[,Ir!)QhrM#"C6T!!+Qlrp#"5,""R!!$8)NBJ9(!-FL#\r`J@8%SLjJ$NU!C`SL#4,B8i"QqL*")&)J8#mS!!4Krrrrr3iJ8L"3)8!!##"5)&"\r+U!!)CN`JEIq),""`!Eb!CKj`!5m!5(J!LbmYrpJ[,Iqm)QhrM#"C6T!!+Qlrp'!\rLF!5mJ'BFF!%[!%Ki!)X[,IrB,bhr[#*Yri`J@8k3!#TZrr3J8L"3,#J!#'Fq*K3\rJ3b!S!!3L4L"$)'J!#()JX)&P"+)ZB!j+J'F+)JN5f&1!C[SL39L+@)Y+NfB!rY3\rJ"1@))%9#X!J!*)9-haai6Pj1G!!)+P&19[ri51F!2#KZ!"!QEJ!-)!aQ"R!'B!!\r"%%Ki!!KKrrrrr$JSJ%U8CJC`"Q!!!2T)H!"-BIrrrr`L*%!J#QB'F!CJ!!$N5(J\r%iQ(rrrrm$#5!5T*Q"R!'B!!!cNKi"1*KrrrrqrBP3!!%5US!"'B'F!CJ!!#d5(J\r%hbm6,a)LEIpm)&P1N!!UE[rd5(J%hbmV!!3[+J!%)QhrI#"C6T!!+Qlrp#mV!"!\r[+`!-,bX!#%KU!!KKrrrrr'BPD`!8!"3PD`!B!"JPD`!F!"`PD`!J!#!PD`!N!#3\rPD`!S!#K)DJ!X,bX!,'(rrrrmmLmV!$J[+`!d,bX!-%KU!$"Krrrrr"i[+`"%,bX\r!3#mV!$a)DJ!mBIrrrr`)3US!5#"8F!)JJ#"8)8S!"(!!60mF!%jH6R3!$#T451F\r!-#4[!"3J#QB%F!CJ@NKi!!KKrrrrq`iNJ#C5)!YQ"(!'B%4`!5D!5(JGIQ(rrrr\rkp#C!)!YQ"(!'B#`L5b"[!"!J2!!!(Ajb),#"C35L,Q!15S"R#L)*%YK6J'Ek)N%\rJ8L&,!!4`!%cI$!"1G!!-+P&)j`!`@8mNE`!33TFJ#QB'F!TJ!!$8F!'`V`!8C`j\r`!V#[!"4R"R!3B!!![P*U!J3`+J)%X'S#"QCL-#S#"Y"!08!#"M!U!JC)`1@),`"\rKrrrrqQ!Q3#!,CJC`"Q!!!)S`+J)'5-"-I!J!N!3#jBJL5b"U!JKb),#"C35L,Q!\r15S"R#L)*%YK6J'Ek)N%[+J))BIrrrrN5*8X##(!"X+m!&'B55&F[,`!F,bm!('(\rrrrrqh'!HF!+`V`!8CK*)9bm[!"`[,`!FBIrrrrf1B!4`%'!8-#S#"%M!8i$PL#"\rU!JJKP`J!F!"B6dcI$!"1G!!-+P&)ja`i*'m!(#!+CJC`#Q!!!*af!'!!!*)[,`!\rN,bm!*#"U!JJJF%J!,bJ!"#mS!!"Kr`!!!6a+!'G8)!2PL#"U!JJSF!J!,`aKr`!\r!"3![$'(rrrriB#J$B%JQDJ)))!45J1@)*l-)!&J!8S4BK6!U!J4)`&1!*J#iJ'h\rH)!2PL#"U!JK#X!J!8fS#"'!38S0BK$!U!J4)`,D!E3$rI(!!B!SU!q@0B-Ci!'$\rQ60mF1%jd!!`U88j@rr4)jaJd*Qi!##4Z!!a#V[rd)!TQ6#"YriJQ%(!"YS"Q(R!\r",`")H!&),bhrf#mYrlJLEIq-)&P1N!!UE[r`B#*`",D!CKa`!5m!5(J"5#mYrpJ\r[,Iqi)QhrM#"C6T!!+Qlrm#!+CJ4`$'"!H!"J1#"U!JJYF$J!rr4)E[rd,`XLEIr\rJ)&P1N!!UE[r`8S4BJc!U!J4)`,L!EGB[+J))BIrrrrGFF!"J"(B!B14-h``B6Pj\r1G!!)+P&19[ri51F!0#4Z!!`J#QF)*Qi!&#!,CJC`!'!!!,`J,J!)X+i!%'F'F!"\rJ!!#XF!'`VJ!)CPT)D`!"5'S!!5*Yri!J@8k3!#TZrr4+J'Bq5'X%idKU"1-LEIq\r!)&P1N!!UE[rd5S"Q*NKV%iP)DK1*)QhrJ#"C6T!!+Qlrp%U!CJiJ+KKmX+XBI'B\r%F!&J6(!!B%K`!V#Z!!KQ2Lm6,a)LEIq!)&P1N!!UE[rd5S"Q*LmV!!3[+J!%)Qh\rrJ#"C6T!!+Qlrp%U!CJiJ+J!BX+X!''B%F!&J"R!!B!*`!%cI$!"1ANjd!"!U88M\rR($JQE`!F+'m!)#!-CJC`"Q!!!@j)H!)QBIrrrrB'+)!N9#!+CJC`"Q!!!9BJ5L*\r,)!J3f@Em*@X"!!%!3HS""%2V!33J#"$CC[`eD`)%!J3eD`)'!JB9I!!"!K!`+J)\r'5-$PL#m!BIrrrr@i*8!##%UU!JKQ"R!'B!!""RJ!B!!!r#"V!JJSF$J!+K4`!EU\r!CJ!!K%Ki!!KKrrrrpBBJDJ)))B!i!#"U!JJSF$J!)!aQ"R!'B!!!bR!"+)")H"e\rqBIrrrr9H)'S###"`1!!K3!!%)'S###"`1!!SD!!%)!aQ"R!'B!!!QL*-)'X###"\r`1!!JD!!%)$`!!"eqFL#`J@8%SLjJ$NU!C`SL#4,B8i"QqL*"B%T`!VU!CKJJDJ)\r)5(!i!#mX!!3[,!!!BIrrrrRLB#a`BlU!CLC)H!!)BIrrrr6J)'S###'!1!!JDJ)\r)+(!i!#!-CJ4`"Q!NF'-SJ&+%@)-`+J)%5-#iJ'd!ra4#UJ)L3US#(R!!B!4f!'$\rN60mF1%jd!!JU88MR!$JSE`!3*%`J$'B1B"S[+`!)BIrrrr5q@)SQ8L!,CZi[$'(\rrrrrdVNcI(!"1G!!%+P&19[ri51F3*#4Z!!JJ#QCH)'hrL#B3F!'fJ'BHF!%[!%K\ri!F)[,IrB,bhrY#*Yri`J@8k3!#TZrr4J0(!%YS"Q,R!",`")H!(#,bhrf#mYrl3\rLEIq-)&P1N!!UE[rdB"![#Lm+)Qhrk#"C6T!!+Qlrp%U5CZa`!%cI"!K1ANjd!!3\rU88j@rqa)ja!N*'i!##!+CN`JEIq)*K"`!ED!CKj`!5m!5(J"dLmYrpJ[,Ir3)Qh\rrM#"C6T!!+Qlrk'!LF!5fJ'BFF!%[!%Ki!G)[,IrB,bhrd#*Yri`J@8k3!#TZrqK\r)E[rZ)QhrU#"C6T!!+Qlrk$B!-!0)`'F%F!"J0("NX+S#%QFN5'lrpdKU!KC)E[r\rZ)QhrT#"C6T!!+Qlrk$B!-!0)`'F)F!"J#%)ZrrF3,[rh60m%#%jH6R3!"#T46PE\rrq%MR%$`QEJ!))!YQ6#"YriJQ%(!"YS"Q(R!",`")H!(R,bhrf#mYrl!LEIq-)&P\r1N!!UE[rdB#*`",D!CKa`!5m!5(J"jbmYrpJ[,Iq`)QhrM#"C6T!!+Qlrp(!#X*0\rQCL4V!!3[%Q(rrrrbrLmU!!4Krrrrm[4+UJ!3C`S[+J!3BIrrrr,N5US!1'F+,bS\r!1'(rrrrbe%UU!%4R#LmU!%4KrrrrmX3SDJ"))!aR##m-BIrrrrhJ+'S!,#!-C`J\r[$'(rrrrpd#mV!!4KrrrrmTT`!%cI(!K1ANjd!!4PF`3Z68P8)%N[8b"0B@0%CAB\r&,J3-)5KZB@eP)#%p)$!T!5N)3d0KBfKP,Q-")$d2)5JUD'&ZC'aP)#%p)$!T%5%\rSF(*TEQ0TF'&X)#%p)$!T$5%SFf&QC9!J)6dJ-#N-3d0KBfKP9A4TE#jM!5d-)5K\rcDATP)$iJ-%`T!5X+)5KZBb!K25!`+3%j#b%SEf*U)#%p)$!T$#%SC'9cG#!K25!\r`+3%r$h*PG'4PFh3J26dJ6P9-6!iU+Q4PFh3J26dJ6P9-6!%h&LJU+Q4PFh3T,6j\rNBA4K)$dp)%j96%`"+`TZBb!p25"198a-!6-5)5KMER4bE%*XEf0V)#%p)$!T!5i\r0)5KMFQ9NFb!K25!`+3!l)IU#!K-!jJ$D!-)!XJ#L!*3!L!"m!'i!B!"5!GJ!3!*\r!!NJ!-!!Q!"J!&!!J)Mmm!5-'UI!#)[rp$L)+)S)#*`'3!!R+!C!!#D!"N!!*J!'\r3!!PJ!C!!#*i"N!!(-!'3!!Dq!C!!"Q`"N!!'+!'3!!A+!C!!"3)"N!!%UJ'3!!4\r%!C!!"#!"N!!$(J'3!!*q!C!!!EB"N!!!XJ'3!!"m!C!!"#)"N!!)C2q3"!#3"2q\r3"!#3"2q3"!#3"`3!!!!1!!!!!3!!!0`!!!$S!!!#p!!!!!3!!!!9!*!2!3#3#b)\r!N!X$!!!!!3#3"d8!!!!"!!!!!3!!!!)!!!!%!*!(FJ#3#`J!!!!'!*!%!3!!&J)\r!!#m#!!!h!J!!2J%!!&F#!!"N!J!!I`)!!)N#!!#@!J!!S3)!!+`#!!#h!J!!``)\r!!08!!3#3"3B!N!3"3B$[5Je#%i!h4K40594IT80$B@0SC8GXEf*KE(0-D@)!Cd0\rZG(*X3Qa[BfX!68P8Ak90594$6'PL!(0dFQjMF(N!Fh4bBfe`!'ePEA0PG!"0594\rIT84PBR9RCfPZCdaTBJ"R4'9LG@G6D@GZB@`!3@aPFR46D@GZB@a"G!"*ER4PFQC\rKBf9-D@)!6Q9h8(4b8hPc!&9ZD'pXC%ePE@pbH3")EfaN6@9YEh*j!%4TFh"[Ff9\r3G()!4f9d8(4b8fPkC3"6B@eP8(*[Bf9cF`"(CA4$GA*bC@jd8(*[Bf9cF`"1CAG\r3G()!Bf0ICf9dAf0bC@4IGQ9bFfP[EJ"MBepQFQ9PAdj$AfPZCQm!Bf0ICf9dAf0\rSB@jRC9pdD@eP!'0MAf4PFh4bEhN!Bf0IBfa[Ff8!Bf0IBh*PBA4P!'0MAfCbC@9\rIBh*PC(-!Bf0ICf9dAfjKE@8!Bf0ICR*PC9p`FQPZBfP`B@`!Bf0IFQ9YEhCPAf0\rbC@3!Bf0IEh"PEJ"MBepRCA4I6N0ID@jQE`"MBepcCA&ICQ9dBfKI6N0c!'0MAh0\rPG&p`FQPZBfP`B@`!Bf0IFfKeG'4[Gfi!Bf0IFf9aAfCPG'0SAf0bC@4c!'0MAfG\rPG&p`FQPZBfP`B@`!Bf0ID@jTG'PKE'PkC3"MBepcG'pbC3"MBepXEf0VAh*PFA9\rPFh3!Bf0ICR*PC9pZB@eP!*!*"!!!!!`!!3!)!!3!!!!'!!J!"J!)!!J!!!!+!!3\r!#J!!!!X!%!!,!!`!$`!!!")!"!!5!!!!%`!)!"-!%qq*!!mc9`!569F!#TVI!!J\rQc`!*6#%!$Fk[!!XfqJ!4q!B!$ZC6!!F66!!1ZFB!%)+a!"#-#J!,2Ad!%JKH!"$\r-#`!0b18!##F0!!mB(J!-CeS#!!$F!!!#%!!"!J!!m!!!!G!!!3)!!3!!!!)i!!%\r#!!%6!!!#3!!"!J!"(J!!!NJ!!3)!!5F!!!*B!!%#!!%a!!!"f!!"!J!"2`!!!JJ\r!!3)!!8X!!!(S!!%#!!&G!!!#+!!"!J!"E!!!!P!!!3)!!A3!!!(`!!%#!!'$!!!\r#!!!"!J!"P!!!!L!!!3)!!D8!!!*J!!%#!!'a!!!"q!!"!J!"a!!!!KJ!!3)!!G8\r!!!*S!!%#!!(M!!!#-!!"!J!"l!!!!FJ!!3)!!I`!!!(J!!'qG3!!!3!!!!&J!!!\r!B!!!!$)[Fh*M,feKBbpdC@aZCA30Eh9d)'CPC5"TFb"SCA*PBRNJCh*KER4PC#`\rJF(*[GQPNC@3JG'KKG#"dD'8JB@*[GQ8JBfp`HA*TCfKd$5!U)'j[G'PMC5"KF("\rPBA)JD@iJB@aX)'0[F'PPFb"KEQ3JG'KKG#"LEh4S)(4SBA3JBfp`HA*TCfKd)'j\r[G'PMC5"KEQ30)#SJG'KTFb"`CA*YDA0cD@pZ)'j[G'PMC5"KF("PBA)JD@iJFh9\r`F'pbG'PZCb"NEf0eE@9ZG'&dD@pZ,#"KEQ3JG'KKG!dJ+L"dD'8JEQ&YC5"[CL"\r0,NNZ9#i!!!"F!*!,!3#3%`&Y0MKV!*!6!3#3%6`168P8Ak9$3f&MD'9-D@)!N!8\r"!!!!!@!!!!"J!!!!-J9@1G!cb!!!!"`!-J!!BfCbC`!!!!S!!2rr!*!)H,J:\r
\ No newline at end of file
diff --git a/src/mac/libraries/CCache API/bin/CCacheLib.68K.debug b/src/mac/libraries/CCache API/bin/CCacheLib.68K.debug
deleted file mode 100644 (file)
index 36bdabc..0000000
+++ /dev/null
@@ -1 +0,0 @@
-(This file must be converted with BinHex 4.0)\r:%d0$B@0SC8aTBLif1%XZC'9LG@F!FfKXBN0"*%J"!!!!*fB!!!'@B"K+EhNKF'9\rQCQdf1'X!!!!"XJXf-3#3$3-!!J#3$L!B!!!J'!!!)"J!!!#8!!%#!*!%"3#3"J,\r`!!!#m!!!!G%!!##X!J%#!*!%$J#3$J6Q!!!LJ!3"!J"0B@PZ!#9"09G[FQaN!%a\r[B@4PFJ#3"#T46PErq%MR!$JNEJ!)+'i!%#CZ!"3JEIpJ5T!!CM*)H!!3BIm!!!p\r`*)"+NQB%F!CJ4#"53UJ!"#"53T!!)&*#U!!))&*#U!!-)'hrB##5B!BJEIpJ**!\r!F!'`VJ!-E!4`#@!8)!aR"(!"+)!J#fF')'hrr#D3!(!!60mF!%jH6R3!%)eMBep\rTEQPdD@&XDATP!!!U88j@rrJ[#L4Z!!JJ#QF@5T*R%Lm5BIm!!"[),a*Kr`!!$9K\rJ"(!+B!4#NR!!*&p1ANjd!!5,Bf0IFfKeG'4[Gfi!!#T46PErq%MR'$JQEJ!)*Li\r!$#KZ!"3S,J!FPFSJ#fB'F!TJ!!$D5S4Q"R!-B!!!d%Ki!LCKr`!!$SSN3#!+CJC\r`"Q!!!,T+JfF5)%0`re+!5KKQqJb!!!!!rf8'F!&J!!#H)%SL3b!)%0PQr#!-Ca)\rJ6($r8S"+''Ek$)!!!!$rC34`$'"i3HS""#*-)!J3f@Em*@i!'!)-3QS#"#9Z!"!\r"!"9m!!)#%("N*8!#%Lm+BIm!!!jD*8!##%UU!JKQ"(!'B$T+U`!)CK"#UJ)L3US\r#(LD+*dS!"'!@)'X!"#&+!KiPD`!%!L*#UJ)H*dS!"&+V!!K5U`!-)%3JLR!!60m\rF'%jH6R3!')PMBepMFQ9KG'8!!#T46PErq%MR($`U,J!)*Qi!$#JZ!"!SEJ!BPFT\rf!%U&CJC`#Q!!!0)J$'B'F!aJ!!$))!YQ!!#%)'hrM(!"X*!!CKj`!#m!5(J!Ubm\rYrr3[,Iri)QhrN!!J@8k3!#TZrr4J@L"Yria`!V#3!'B5,bhrq#*YrhJJ@8k3!#T\rZrr4J2L"Yria`!l#3!'B1)QhrC#"C6T!!+Qlrp'!Q)'hrM(!%X*!!CKa`!5m!5(J\r!UbmYrr3[,Iri)QhrN!!J@8k3!#TZrr3J4543B#)[#Lm,)QhrQ#"C6T!!+Qlrp%U\r!CJUiUJ%!CJ4f!@!%*'S#(L!+C`4+!fI@5J0R"LL+F!"J"%+8F!T-ha`i6Pj1G!!\r8Kf0MAfp`C@i!!#T46PErq%MR!$`SEJ!)*'i!$*I,)!aQ"R!+B!!!ZL!+CJC`$'!\r!!,"+NQB!!)3JEIq-F!'`N!"Q(R!!,`")H!$0,bhrp#mYrr!LEIq3!#"C6T!!+Ql\rrp'"D)'hrM(!#X*!!CK)[,Ir`)QhrH#"C6T!!+Qlrp'!q)'hrM(!$X*!!CJiLEIp\rN)&P1N!!UE[rdB#BJEIq-F!5`N!"Q((!",`")H!$0,bhrp#mYrr!LEIq3!#"C6T!\r!+Qlrp#"5$#J!!3)3C`4`$Q!B*P)[#bm-BIm!!"5i,`YKr`!!#NC#NR!!60mF!%j\rH6R3!#)KMBepME'pcC3!!!#T46PErq%MR%$`SEJ!)*Qi!$*A+)!aQ"R!+B!!"(L!\r,CJC`$'!!!44+NfB!!)3JEIq-F!'`N!"Q(R!!,`")H!$V,bhrp#mYrr!LEIq3!#"\rC6T!!+Qlrp'"D)'hrM(!#X*!!CK)[,Ir`)QhrH#"C6T!!+Qlrp'!q)'hrM(!$X*!\r!CJiLEIpN)&P1N!!UE[rdB#BJEIq-F!5`N!"Q((!",`")H!$V,bhrp#mYrr!LEIq\r3!#"C6T!!+Qlrp#46F'5`UJ)5Ca![#Q(r!!!BPNS!CJ4`#'"`5US#)QB5++S#(NU\rU!KjR##"U!Kj#U!)L5US#(QB8+@S#)J!%5US#)QF))'S#)N+S!Kj+UJ)LCaT+UJ)\rHCa3JDJ)H)@S#)J)L)'S#)L&U!Ki#(K9m!!%#%#m,,``LEIrX)&P1N!!UE[rd*J"\r5V!!-)!0-ha`)6Pj1G!!)LQ0MAf4PFh4bEhN!!!!U88j@rrK+VJ!)CJ4`#Q!B5Ui\r!$'F3)'i!##*Z!!`LU!!-F!"J!R!-6Pj1G!!)NQ0MAfGPG&pMD'&ZCf9IG'PYC3!\r!!#T46PErq%MR%$!QEJ!)*'i!$(B!)!YQ"(!+B%JJ#QB%F!TJ3("NX+S#%QFBF'D\r`UJ)5CJ`[#Q(r!!!AKNS!CJ4`#'!J,bi!&#mZ!"![#Q(r!!!3e#B!5S0Q"&+V!!K\r5U`!-)!0-h``)6Pj1G!!3L'0MAh0dEh*P!!!!+P&19[rd51F!-#CZ!!JNEJ!-3Ul\rrp#!,C`3J#QB%F!TJ0R"NX+S#%QFBF'D`UJ)5CJ`[#Q(r!!!A$NS!CJ4`#'!@,bi\r!&#mZ!"![#Q(r!!!4GP+V!!a`!%cI$!"1ANjd!"#1Bf0IFQ9YEhCPAf0bC@3!!!!\rU88j@rrK)j`!m+'i!##CZ!!`NEJ!8)!aR"#!,CJC`#Q!!!03J#QB!!)3JEIq-F!'\r`N!"Q(R!!,`")H!&V,bhrp#mYrq3LEIq3!#"C6T!!+Qlrp'"D)'hrM(!#X*!!CK)\r[,IrN)QhrH#"C6T!!+Qlrp'!q)'hrM(!$X*!!CJiLEIpN)&P1N!!UE[rdB#BJEIq\r-F!5`N!"Q((!",`")H!&V,bhrp#mYrq3LEIq3!#"C6T!!+Qlrp("NX+X#%QFBF'D\r`U`)5CJ`[#f(r!!!@%%S!CJ4`#'!U)#X"!,#Z!""R"(!+B"a)H!$r,`T)D`%%)Qh\rrP#"C6T!!+Qlrp&+X!!a`!%cI(!"1ANjd!"#3!'0MAh0PG&p`FQPZBfP`B@`!!!!\rU88j@rrK)j`!`*Qi!$#4Z!"!J#fB%F!TJ2R"QX+X#%QB3,`YKr`!!&CC+!'B%F!K\rJ*L!+Cb")H!$rBIm!!!B+*)"+NQB%F!CJ$L"53qX""#!)%0PQr(!!60m-!%jH6R3\r!$*!!Bf0ICf9dAh"bD@jMDA"KE!!!!#T46PErq#m+*'i!$#!+CJ4`#Q!XF'D`UJ)\r5CK![#Q(r!!!9*NS!CJ4`#'!85Ui!%'B%F!CJ#L"Z!"!JUJ%!F!!NAdjH6R3!$*0\rMBepRCA4IBh*PC&pfCA*cD@pZ!!!U88j@rrK)j`!`*'i!$#CZ!"!J#QB%F!TJ0("\rQX+S#%QB3,`TKr`!!&-*+!'B%F!KJ(#!,CaC)H!$rBIm!!!8f*S!J8b*+)!J3f@E\rmF!"-h``!6Pj1G!!-Lf0MAfGPG&pZB@eP!!!U88j@rrK)j`!i+'i!##CZ!!`NEJ!\r3)!YR##!+C`3J$'B%F!TJ5NU5CKK)H!!)BIm!!!6F*)"+NQB%F!CJ-L"5)*3J8NU\r3!'B3,a*Kr`!!"3T#NN+6F!0J'#m,)&)[%'(r!!!49L"5)&!L8L+S!Kj`!%cI(!"\r1ANjd!!b3!'0MAh0PF9pQCA4MD&p13h-!!!!U88j@rr")ja!i*Qi!$#KZ!"!NEJ!\r8)!YR#L!+C`C+VJ!)CJC`#Q!!!9!J$'B'F!CJ!!&'F'D`U`)5CK)[#f(r!!!6Y%S\r!CJC`#'!!!5a+NQBN5(J!#'(r!!!%*L5!5T*Q"R!'B!!"%L"53UJ!"'!')&*5U!!\r%-#X#"%M!)&+`U!!%Ea3J8L*V!JJJ+!!%)R%-!("MX*&Rf$!V!J4)`#"5X+J!"'i\r5,a*Kr`!!""j#P%+5F!0J!!$#)&)LD`)))#J!"#*a$!!Q%A!"YS"QDNKi!!KKr`!\r!!kSSJ%U8CJC`"Q!!!*C)H"eqBIm!!!18)&3K3!!%)&4+U!!%CJ4`"Q"i)&)LD`)\r))#J!"#*a$!!JD3!%)P3LD3!%)$`!!"eqFL#`J@8%SLjJ$NU!C`SL#4,B8i"QqL*\r"B$K`!VD!CL`J8L*V!JJJ+!!%)R%-!#eT!!6rp(!#,8$rm#m-,blrp#mZrr"Kr`!\r!#LCJ"N+8F""J##"58UJ!"(!!60mF#%jH6R3!%**MBepcCA&ICQ9dBfKIBh*PC(-\r!!!!U88j@rrK)ja!m+'i!##CZ!!af!*A+)!aQ"R!+B!!!NL!,CJC`"Q!!!)JJ,!!\r)8S$PL#m!)QhrL#"C6T!!+Qlrp#D!5T0Q"(!'B'BN9'"@5(J#!L*YriJJ@8k3!#T\rZrr3J8b'!2!!J8dU`2!"Q"(!'B%!J8b"`2!!L5L!)%0PQr#"6)(!m!%(S!2p$kJ%\r%)!J3f@Em)&-JF$`!)@S"!!(q*'S#(P+$)!TQTL"63V!m!(!!60mF#%jH6R3!#)j\rMBepRCA4I6N0ID@jQE`!!!#T46PErq%UZ!!aQ"(!'B!`[,J!-BIm!!!*1F!"1ANj\rd!!L4Bf0ICR*PC9p`FQPZBfP`B@`!!#T46PErq%UZ!!aQ"(!'B!`[,J!-BIm!!!)\rBF!"1ANjd!!L-Bf0ICR*PC9pZB@eP!!!!+P&19[ri,`SNEJ!-)!TQ"(!+B"3[%Q(\rr!!!5$Lm5BIm!!!(F3T*`!#4I6Pj1G!!)M@0MAfCbC@9IBh*PC(-!!#T46PErq%M\rR%#3NEJ!-)!TQ"(!+B$4f!'!8)&)[-$`!)QhrG#"C6T!!+Qlrp&+$)&*+X$`!CZ3\r[%L*Yrh3J@8k3!#TZrr4#NTA+F!"-h`3)6Pj1G!!)Mf0MAfCbC@9I6N0ID@jQE`!\r!+P&19[rX51F!*#4Z!!`J#QB'F!aJ!!$D5'lrm#*Yri3J@8k3!#TZrqJp32rXF'5\r`UJ)5Caa)E[r[5'S#&NKZrr!LEIq!)&P1N!!UE[rS28$rl#!Z!""6J'F-8i"R%P1\r!CcCJ!!#)F'3P3!)5B!!!JR"NX+S#%QB8F'8P3!)5*@lrm!)@*@lrp!)DB'4`CV#\rU!K*QA(!)B&T`C,#U!K*Q&("Q*8!#%L9Zrr!#&L9Zrr3#'Q!mF'D`UJ)5CJT+,[r\r[CJ4`#'!XF'@`UJ)5CL*+,[r[Ca4`CL9!!K)PE[r`!KBPE[rd!KTJ#(!)B!C`$'!\r#F!!NAdjH6R3!$)pMBepXEf0VAh*PFA9PFh3!!#T46PErq%MR!#3[,J!))QhrL#"\rC6T!!+Qlrp#4!)!TR%LmZ!!J[#L*Yrh!J@8k3!#TZrr3J#L4I6Pj1G!!%LNjPGe0\rKCQ93G()!!!!U88j@rrK)ja!N*'i!##m+)QhrI#"C6T!!+Qlrp#B!)!TQ!!#%)'h\rrM(!"X*!!CKj`!#m!5(J!*bmYrpJ[,IrF)QhrN!!J@8k3!#TZrr4J@L"Yria`!V#\r3!'B5,bhrh#*YrhJJ@8k3!#TZrr4J2L"Yria`!l#3!'B1)QhrC#"C6T!!+Qlrp'!\rQ)'hrM(!%X*!!CKa`!5m!5(J!*bmYrpJ[,IrF)QhrN!!J@8k3!#TZrr4+Jfi!!)3\rJEIq-F!'`N!"Q(R!!,`")H!!S,bhrf#mYrp3LEIq3!#"C6T!!+Qlrp'"D)'hrM(!\r#X*!!CK)[,Ir8)QhrH#"C6T!!+Qlrp'!q)'hrM(!$X*!!CJiLEIpN)&P1N!!UE[r\rdB#BJEIq-F!5`N!"Q((!",`")H!!S,bhrf#mYrp3LEIq3!#"C6T!!+Qlrp#m$3UF\r[#L*Yrj`J@8k3!#TZrr3[!d+R,`SLEIqF)&P1N!!UE[rd,`-[#L*Yrf`J@8k3!#T\rZrr3[#L*Yrh3J@8k3!#TZrr4-h`3)6Pj1G!!%MN4TFh"[Ff96B@CP8(4b!!!!+P&\r19[ri51F!*#mZ!!JLEIpS)&P1N!!UE[rd*%!J#QF5,bi!##m+)QhrF#"C6T!!+Ql\rrp#!+*&p1ANjd!!506Q9h8f&QC9"dFP0jF`!!+P&19[ri51F!*#4Z!!JJ#QB!!)3\rJEIq-F!'`N!"Q(R!!,`")H!"3,bhrf#mYrp!LEIq3!#"C6T!!+Qlrp'"D)'hrM(!\r#X*!!CK)[,Ir3)QhrH#"C6T!!+Qlrp'!q)'hrM(!$X*!!CJiLEIpN)&P1N!!UE[r\rdB#BJEIq-F!5`N!"Q((!",`")H!"3,bhrf#mYrp!LEIq3!#"C6T!!+Qlrp%*U!J3\reI!!+!JC)H!!SBIq3""!P3!)))#S###4I6Pj1G!!%M@jPGd0bC@4#G@CQCA)!!#T\r46PErq%MR!#3NEJ!))!TQ!!#%)'hrM(!"X*!!CKj`!#m!5(J!ALmYrpJ[,Ir-)Qh\rrN!!J@8k3!#TZrr4J@L"Yria`!V#3!'B5,bhrc#*YrhJJ@8k3!#TZrr4J2L"Yria\r`!l#3!'B1)QhrC#"C6T!!+Qlrp'!Q)'hrM(!%X*!!CKa`!5m!5(J!ALmYrpJ[,Ir\r-)QhrN!!J@8k3!#TZrr3NVJ!-*@i!%!!%5Ui!&'B)3US!#(!!B$i[,J!3BIrrrri\ri*8!!#%UU!!KQ"(!'B#BLDJ!))'i!&#!Z!""b),#"C35L,Q!15S"R#L)*%YK6J'E\rk)N&`!#4I6Pj1G!!3Lf0[F(P%BA4K6f*U!!!U88j@rrK)jaJm+'i!##4Z!!ai!*I\r,GJ!J#QB!!)3JEIq-F!'`N!"Q(R!!,`")H!"d,bhrf#mYrmJLEIq3!#"C6T!!+Ql\rrp'"D)'hrM(!#X*!!CK)[,Ir))QhrH#"C6T!!+Qlrp'!q)'hrM(!$X*!!CJiLEIp\rN)&P1N!!UE[rdB#BJEIq-F!5`N!"Q((!",`")H!"d,bhrf#mYrmJLEIq3!#"C6T!\r!+Qlrp#C-)!YQ#%+5B!!#@P+%5TYQqL!%8S$PL#m!BIrrrrdZ*)!Q!%U$CJ!!K#"\rYria`!E#3!'BHF!![!%Ki!(`[,IrB,bhra#*Yrj!!)&P1N!!UE[rdB&SJEIq-F!+\r`N!"Q%LmYrm3LEIpi)&P1N!!UE[rdB$iJEIq-F!1`N!"Q$L*Yrf3J@8k3!#TZrr4\rJ*L"Yria`",#3!'BFF!%[!%Ki!(`[,IrB,bhra#*Yrj!!)&P1N!!UE[rd5S0R!!'\rd*NaJ!!'J5(J!$'(rrrrmM#"5))!J8NU3!'B!!)3JEIq-F!'`N!"Q(R!!,`")H!#\r$,bhrf#mYrm!LEIq3!#"C6T!!+Qlrp'"D)'hrM(!#X*!!CK)[,Ir!)QhrH#"C6T!\r!+Qlrp'!q)'hrM(!$X*!!CJiLEIpN)&P1N!!UE[rdB#BJEIq-F!5`N!"Q((!",`"\r)H!#$,bhrf#mYrm!LEIq3!#"C6T!!+Qlrp#"55T!!C`!"$L*5)P%J9(!-FL#`J@8\r%SLjJ$NU!C`SL#4,B8i"QqL*")&)J8#mS!!4KrrrrqmJJ8L"3)8!!##"5)&"+U!!\r)CJ!!K#"Yria`!E#3!'BHF!![!%Ki!)X[,IrB,bhr[#*Yrj!!)&P1N!!UE[rdB&S\rJEIq-F!+`N!"Q%LmYrl`LEIpi)&P1N!!UE[rdB$iJEIq-F!1`N!"Q$L*Yrf3J@8k\r3!#TZrr4J*L"Yria`",#3!'BFF!%[!%Ki!)X[,IrB,bhr[#*Yrj!!)&P1N!!UE[r\rd)&)J8%US!!KR2L"8)#J!"#*5)P%LD3!))&3JD!!)FL#`J@8%SLjJ$NU!C`SL#4,\rB8i"QqL*"@)TBLdU6CJ$qAL"$3V"-!#5$60mF'%jH6R3!#)eMEh"j4'&dB8&bFQ&\rj!!!U88j@rrK)j`!m+'i!%*A+PmXQEJ!-)!aQ"R!'B!!"%%Ki!!KKrrrrqUBSJ%U\r8CJC`"Q!!!2T)H!"-BIrrrrU3!#4!)!TQ"R!'B!!!j%Ki"1*KrrrrqRSNJ%U5CJC\r`"Q!!!-j)H!6LBIrrrrTN*8!!"%UU!!4Q"R!'B!!!Y%Ki"0m[%bm5)QhrP#"C6T!\r!+Qlrp%Ki"0m[+`!%,bS!"#*Yrj3J@8k3!#TZrr3[+`!3,bX!$#mV!!K)DJ!)BIr\rrrrXS*@X!&!!8*@X!'!!B*@X!(!!F*@X!)!!J*@X!*!!N*@X!+!!S5'S!,#mV!#a\rKrrrrqrJ[+`!i,bX!0#mV!$")DJ!`BIrrrrVJ,bX!4#mV!%![+`!m5'S!2'(rrrr\rkbN+U!%JJ9(!#))!J9#&+!!4`!%cI(!"1ANjd!!b+Bfp`H9Be3h*PC!!!!#T46PE\rrq%MR!$!QEJ!3PFSJ#fB%F!CJ@NKi!!KKrrrrq@JQJ%U6CJ4`"Q"')&0`!5#!5(J\rGIQ(rrrrj6L4!)!TQ"(!'B#`L5L"Z!!`J2!!!(Ajb),#"C35L,Q!15S"R#L)*%YK\r6J'Ek)N%J8b&+!!4`!%cI$!"1ANjd!!b+Bfp`H9Bd3h*PC!!!!#T46PErp%MR!$!\rNEJ!)PmY#V[rd)!TQ"R!+B!!!i(!"X+i!$'F1F!+`VJ!-C`C`%'!!!-T5DJ)%-#S\r#","U!JCQDM!U!JE33$9!!JB`+J)'5-$PL#m!BIrrrrLN*N!J#fB'F!CJ!!#@-#S\r#"NM!)J$JLH#*i)RZLG+!iS(PL5!")NXJDJ))FL#`J@8%SLjJ$NU!C`SL#4,B8i"\rQqL*",bS##'(rrrrfc#9,!JK`!E#Z!!aQ&%KZrr3[,J!3,bi!$'(rrrrqYQ!JF!+\r`VJ!-CK4)E[rd,bi!%#mZ!!aKrrrrr94J"(!3B"3`+J)%5-"6J#"U!JJKV[rd$!"\r`!%cI$!"1ANjd!!b3!'0bC@4#G@CQCA**ER0PFR3!!!!U88j@rrK)jaJ`*'i!#*I\r,)!TQ"R!+B!!!L(J!B(B[,J!3,bi!$#"U!JJJF%`!,bJ!"#mS!!"Kr`!!!B4+!'G\r5)'S###C`6!![#f(r!!!'0#m,BIrrrrB#*J4J&#!$8S!JDJ)))QS###1`$!!m!&+\r$-#S#"%M!8i#fJ'hJ-#S#"%M!8i!JDJ))3V!-!&0U!J4J$&+%-#S#"%M!Z)"YJ(!\r!60m-'%jH6R3!$*!!Bh*PC%*eCQCPFP*PE@pfC3!!!#T46PErp%MR%$3QEJ!)*'i\r!$%+Zrr3J#QB!!)3JEIq-F!'`N!"Q(R!!,`")H!&),bhrf#mYrlJLEIq3!#"C6T!\r!+Qlrm'"D)'hrM(!#X*!!CK)[,Iqi)QhrH#"C6T!!+Qlrm'!q)'hrM(!$X*!!CJi\rLEIpN)&P1N!!UE[r`B#BJEIq-F!5`N!"Q((!",`")H!&),bhrf#mYrlJLEIq3!#"\rC6T!!+Qlrm#!+CJ4`$'!iGJ"J(L"U!JJYF$`!rr4)E[rd,`XLEIrJ)&P1N!!UE[r\r`8S-`+J)%5-#fJ'hB,bS##'(rrrrd`(!!60m-#%jH6R3!#*&NDA0`Eh0P3h*PC%*\reCQCPFJ!!+P&19[ri51F!0%UZ!!aR"NUZ!"4Q"R!!B!!!c#!Z!!L`VJ!3C`C`!'!\r!!,a`!E#Z!!KQBL4Z!!`QEJ!85'X!!8KU!!%LEIqB)&P1N!!UE[rd5S"Q2NKV"10\r)DJ6M)QhrQ#"C6T!!+Qlrp%U!CLC)Da1*5'S6L5*YrjJJ@8k3!#TZrr4+J'B1)#S\rBI,#V'(aQ"(!"B&4`!'"3F!+`VJ!)CNBNEJ!-*Qi!&#m6,a)LEIqB)&P1N!!UE[r\rd5S"Q*LmV!!3[+J!%)QhrQ#"C6T!!+Qlrp%U!CJiJ+J!BX+X!''B%F!&J"R!!B!*\r`!%cI$!"1ANjd!"#(Bh*PC'0YF!!!+P&19[ri51F31#CZ!!JSEJ!-PFSJ$'B'F!C\rJ!!'3!%Ki!LCKrrrrmc3SJ%U8CJC`"Q!!!ASN9#"+)NXJ#"$CC[`PD`%!!3""kJ%\r%3qX""#!)%0PQr$9V!J3#"$9V!JB#"K9m!!%#%$!U!JC)`1@),`"KrrrrmZBP3!)\r)5US##'B'F!CJ!!%SGJ"J!!%-)'X###"`2!"`!E#3!'B!!**)H!!)BIrrrr+f)'S\r###'!2!!JDJ))5V!m!'B'F!CJ!!$`)'S###"`2!"`!5#!5(JGIQ(rrrrbL#"U!JJ\rJF$`!)8!!"#"U!JJJF$`!5UJ!"'B'F!CJ!!#k)QS###*a2!!LD3!%)'X###"`2!!\rJD!!%)$`!!"eqFL#`J@8%SLjJ$NU!C`SL#4,B8i"QqL*"B'JJD`)))(!m!(!#X*!\r!CL!JDJ))5(!m!#"V!JJJF$`!,bJ!"#mS!!"Krrrrq4"J1L"V!JJJF$`!F'1`N!"\rQ,%Ki!!KKrrrrmHSJDJ)))B!m!#"U!JK+X$`!CJ4`"Q!N)'S###"`2!"`Bb#!8S-\r`+J)%5-#fJ'd!rZa#UJ)L3US#(R!!60mF#%jH6R3!#)9NGA"13`!!+P&19[ri,`S\rNEJ!))!TR(Q!1)&)[+!!)BIrrrr(+@)T+NQEZ,bi!#'(rrrraZL4I6Pj1G!!%N!"\rNDA0`Eh0P4'&dB8&bFQ&j!!!!+P&19[ri51F!*#4Z!!JJ#QB!!*BJEIq-F!'`N!"\rQ(R!!,`")H!(#,bhrf#mYrl3LEIq3!#"C6T!!+Qlrp'"X)'hrM(!#X*!!CK)[,Iq\rd)QhrH#"C6T!!+Qlrp'"3)'hrM(!$X*!!CJiLEIpN)&P1N!!UE[rdB$JJEIq-F!5\r`N!"Q,R!",`")H!(#,bhrf#mYrl3LEIq3!#"C6T!!+Qlrp'!3,`S[#L*YrqJJ@8k\r3!#TZrr4+NQEXF!!NAdjH6R3!")TQFQ9P6N0-DA0d!!!!+P&19[rX51F3*#4Z!!J\rJ#QB!!)3JEIq-F!'`N!"Q(R!!,`")H!(5,bhrf#mYrp!LEIq3!#"C6T!!+Qlrk'"\rD)'hrM(!#X*!!CK)[,Ir3)QhrH#"C6T!!+Qlrk'!q)'hrM(!$X*!!CJiLEIpN)&P\r1N!!UE[rSB#BJEIq-F!5`N!"Q((!",`")H!(5,bhrf#mYrp!LEIq3!#"C6T!!+Ql\rrk%KZrqiLEIq%)&P1N!!UE[rS0J!`!dM!C`4`!'!dF'5`UJ)5Cb4)E[rh5'S#&NK\rZrqiLEIq!)&P1N!!UE[rS0J!`!dM!C`K`!'!)3Llrpa!ZrrG-h`3)6Pj1G!!%LQP\rc6'pMDdpeFR-!!!!U88j@rrK)j`!d*Qi!##!,CJ!!K#"Yria`!E#3!'BHF!![!%K\ri!HF[,IrB,bhrX#*Yrj!!)&P1N!!UE[rdB&SJEIq-F!+`N!"Q%LmYrl!LEIpi)&P\r1N!!UE[rdB$iJEIq-F!1`N!"Q$L*Yrf3J@8k3!#TZrr4J*L"Yria`",#3!'BFF!%\r[!%Ki!HF[,IrB,bhrX#*Yrj!!)&P1N!!UE[rdF!+`NfCQ*'X!"#m5BIrrrqmd,bS\r!"'(rrrr[+NUU!""R#LmU!""KrrrrlaT+UJ!iC`S[+J!iBIrrrqm+5US!4'F+,bS\r!4'(rrrrZqNUU!%KR#LmU!%KKrrrrr3K+UJ!XC`S[+J!XBIrrrrci,bX!"'(rrrr\rZd(!!60m-!%jH6R3!"*CMBepQFQ9PAf0bC@4ID@jdCA*ZB@ac!!!!+P&19[ri,`0\rf!#mZ!!KKr`!!!&if!$!$5-"R"$!$B!JJEIpJ3T!!-!-Q(djH6R3!"***EQPdD@&\rXDATP3f&MD'9-D@)!!!!U88j@rrKKr`!!!%j1ANjeN94PFQeTEQ&dC80KBfKP6'P\rL!!"1G5T46PErq#m0)!d[!#mYrk`LEIqN)&P1N!!UE[rd+d$rA'(rN!6FF!"1ANj\rd!!3U88j@rrJ[$5mYre`LEIqJ)&P1N!!UE[rd6Pj1G3JZ68P8)%N[8b"0B@0%CAB\r&,JJ-)5KZB@eP)#%p)$!T!5N)3d0KBfKP,Q-")$d2)5JUD'&ZC'aP)#%p)$!T%5%\rSF(*TEQ0TF'&X)#%p)$!T$5%SFf&QC9!J)6dJ-#N-3d0KBfKP9A4TE#jM!5d-)5K\rcDATP)$iJ-%`T!5X+)5KZBb!K25!`+3%j#b%SEf*U)#%p)$!T$#%SC'9cG#!K25!\r`+3%r$h*PG'4PFh3J26dJ6P9-6!iU+Q4PFh3J26dJ6P9-6!%h&LJU+Q4PFh3T,6j\rNBA4K)$dp)%j96%`"+`TZBb!p25"198a-!6-5)5KMER4bE%*XEf0V)#%p)$!T!5i\r0)5KMFQ9NFb!K25!`+3"1)J(SJJ)9!UJ!rJ$U!0i!aJ#f!+B!Q!#-!)!!FJ"N!&B\r#%!"%!RJ#J!!d!#S!(!!B!#!L2c`")`DTm!)Lrrd5)J'`JJ)X(kJ"X"pL!E!-XJ'\r`$%`"X!`-!E!,fJ'`#k3"X!VB!E!*3!'`#,)"X!K-!E!(lJ'`"hJ"X!CN!E!&m!'\r`"AB"X!8b!E!$i!'`![3"X!(S!E!!e!'`!*!!!E!%)J'`JJ)%!9JJ'!%B!#!B)ar\r1!3%K#!-M(r`"!5%)!b)J'!`!!!$rN!3!N!F"!!!"q!!!!!%!!!(`!!!!"3!!!")\r!!!!"!!!""!!!!43!!!1!!!!!"!!!!"8!N!m"!*!,)J#3#`S!!!!"!*!(RJ!!!!%\r!!!!"!!!!!J!!!!X!N!I4!*!,!`!!!!d!N!Ik!*!,!J!!!"!!N!3"!!!@!J!!,`)\r!!$J#!!"#!J!!6`)!!&S#!!"P!J!!EJ)!!(N#!!#&!J!!P`%!!,B#!!$$!J!!j!)\r!!1`#!!$c!J!"%`)!!5N!!3#3"3F!N!3"JB$c5K&#&B!h4KG#!!!!68P8Ak9$3f&\rMD'9(E'pLB@ac6'PL!'G$ER4bE%*XEf0V!%PZG'9bCQ&MC8aTBJ"6HA0#FQ9KD`"\r1CAG3G(*6HA-!9@jSEfaN6@9YEh*j!%K[E'40C@e[FRN!4'PcF'pcC9"dFJ"%C@*\reCe0dFJ"(CA43G(*6DATP!&0KE@93FQpMCA0c!%GPG%0eFR*PER43FQpMCA0c!%j\rPGe"dFJ"0594IT84PBR9RCfPZCdaTBLjNC@*eC`"R4'9LG@G6D@GZB@`!3@aPFR4\r6D@GZB@a"G!"0594IT8e*9%0-D@)ZC'9LG@F!Fh4bEQ0`H3"cG(*MEA!!E@9YFf9\rd!%e*9&qP68P88R9ZG'PYC8aTBLjNC@*eC`"IAh9ZFQ9RDA0dCA*ICR*KCfePER3\r!AepbC@GTFh4PFPpQFQ&RE@9ZG!"MBepRCA4IBh*PC&pfCA*cD@pZ!'0MAfCbC@9\rI6N0ID@jQE`"MBepRCA4IBfKKEQGPAh4TE@8!Bf0IC'9cG(*[H3"MBepME'pcC3"\rMBepMFQ9KG'8!Bf0ICR*PC9pMFQ9NF`"MBepRCA4IEQ&YC3"MBepQFQ9PAh"bD@j\rMDA"KE!"MBepbC@e[GQ9IBh*PC!"MBep[F'9Z!'0MAfGPG&p13epTEQC[!'0MAh0\rPF9pQCA4MD&p13h-!Bf0IFf9dAh"bD@jMDA"KE!"MBepcD(9dC'phEJ"MBepcCA&\rICQ9dBfKIBh*PC(-!Bf0ICf9dAh"bD@jMDA"KE!"MBepTEQPdD@&XDATP!'0MAh0\rdEh*P!'0MAfa[BfYIFQ9aG@9cG!"MBepQFQ9PAfjKE@8!N!J%!!!!$!!"!!J!"!!\r!!!B!#!!'!!J!#!!!!!S!"!!+!!!!#`!3!!X!$!!2!!!!%J!%!")!!!!6!!J!%`!\r6liN!$c0A!"*09`!+QYm!##E2!!P-)3!0cUm!#cEk!"(i"J!1jP-!"a0-!!kjaJ!\r3JV%!%)`+!!XpI3!5#&i!%-`,!!h)j3!)*`d!$aJH!!aR@J)!!6d!!!*)!!%#!!&\r4!!!##!!"!J!"B3!!!R!!!3)!!A3!!!*i!!%#!!&r!!!#J!!"!J!"L!!!!T!!!!%\r#!!'5!!!#%!!"!J!"S!!!!N!!!3)!!D`!!!)J!!%#!!'q!!!#B!!"!J!"c3!!!SJ\r!!3)!!G8!!!)S!!%#!!(N!!!#1!!"!J!"p3!!!PJ!!3)!!JB!!!+B!!%#!!)5!!!\r#-!!"!J!#*3!!!P!!!3)!!MB!!!+J!!%#!!*%!!!#D!!"!J!#63!!!J!!!3)!!Pd\r!!!)B!!%Bd`!!!3!!!!&N!!!!C!!!!$)!N20J!*!,!3#3%`&Y0MKV!*!6!3#3%8!\r868P8Ak9$3f&MD'9-D@)ZC'9LG@F!!!!"!!!!!@3!!!"N!!!!-J9@1G!cb!!!!"`\r!-J!!BfCbC`!!!!S!!2rr!*!)5'8:\r
\ No newline at end of file
diff --git a/src/mac/libraries/CCache API/bin/CCacheLib.PPC b/src/mac/libraries/CCache API/bin/CCacheLib.PPC
deleted file mode 100644 (file)
index 98e6657..0000000
+++ /dev/null
@@ -1 +0,0 @@
-(This file must be converted with BinHex 4.0)\r:$80$B@0SC8aTBLj38%-!FfKXBN0"*%J"!!!!-#J!!!'5'R*+EhNKF'9QCR"hF'-\r!!!!"XP21U`#3$3-!!J#3"2q3"!#3"LPX!!!TE!!!+@`!!!93!!3%!2q3"!#3"J*\rK!!!#A3!!!@J!!#l!!J%%!2q3"!#3$J6'!!!!J!3%"!#3"Iq3"!#3"`%!!!&J!!!\r!!3!!!9J!!!!&!!!!%`!!!!%!!!%)!!!"'!!!!f!!!!!%!!!!&3#3$`J!N!X0!*!\r,!3!!!!J!N!FM!*!,"J!!!!N!N!F`!*!,!J!!!!m!N!G$!!!!!3!!!!%!!!!#!!!\r!%3#3"!)!!&8#!!"I!J!!E!)!!(F#!!##!J!!M3)!!*N#!!#V!3!!XJ)!!,i#!!$\r&!J!!c!)!!03#!!$E!J!!iJ)!!1N#!!$r!3!"%`)!!5!!!3#3"3J!N!4+%N!"3J&\r!!8)33J#!!dB@5@jdCA*QB@0P6'PL!%e*9&qP3d0KBfKP4fa[BQ&XFdaTBJ"0594\rIT8e*9%0-D@)!68P8Ak905945G@jdD@eP6'PL!%e*9&qP4'9LG@GRD@jR6'PL!%j\rPGe"dFP0jF`"9EQK[E'40C@e[FRN!5'pXC%ePE@pbH3"%DA0`Eh0P8(4b!%GPG&"\rdFP0THQ8!8f&YC9"bEf0PFh-!4f9d3h9bFQ9ZG&"bEf0PFh-!6Q9h8(4b!'G$ER4\rbE%*XEf0V!(0dFQ0YF!"YC@eMF(N!Fh4bEQ0`H3"cG(*MF(N!Fh4bE'9Z!'ePEA0\rPG!"IAh9ZFQ9RDA0dCA*ICR*KCfePER3!AepbC@GTFh4PFPpQFQ&RE@9ZG!"R4'9\rLG@G6D@GZB@`!3@aPFR46D@GZB@a"G!"MBepRCA4IBh*PC&pfCA*cD@pZBf0IC'9\rcG(*[H@0MAfGPG&pMD'&ZCf9IG'PYC@0MAfCbC@9I6N0ID@jQEf0MAf0bC@&dC@0\rMAf0XEh0PBf0ICf9dAfjKE@9MBepQFQ9PAf0bC@4cBf0IFQ9YEhCPAf0bC@4MBep\rQFQ9PAh"bD@jMDA"KE'0MAfp`C@jMBepcD(9dC'phEQ0MAh0PG&p`FQPZBfP`B@a\rMBepcCA&ICQ9dBfKI6N0cBf0ICf9dAdj$AfPZCQpMBepTEQPdD@&XDATPBf0ICf9\rdAh"bD@jMDA"KE'0MAh0PF9pQCA4MD&pMFQ9NFf0MAh0dEh*PBf0ICR*PC9pZB@e\rPBf0IE'pMDepbCA&eCA0d!*!("!!!!!`!!3!)!!3!!!!'!!J!"J!)!!J!!!!+!!3\r!#J!!!!X!%!!,!!`!$`!!!")!"!!5!!!!%`!)!"-!%qq*!!UDh`!569F!$c0A!!P\r-)3!)*Xm!#cEk!!h1V`!1jP-!%IJ'!!F66!!,2Ad!%)`+!"##X3!1ZFB!$FMP!"$\r-#`!5#&i!##F0!!aR@J!2'"i#!!%Z!!!!q!!"!J!"33!!!5J!!3)!!8X!!!%J!!%\r#!!&G!!!!Z!!"!J!"E!!!!8!!!3)!!A8!!!%`!!%#!!&p!!!!m!!"!J!"L!!!!-!\r!!3)!!C8!!!%3!!%#!!'M!!!!d!!"!J!"Y!!!!6J!!3)!!EX!!!&)!!%#!!('!!!\r"#!!"!J!"eJ!!!1J!!3)!!HB!!!$B!!%#!!(d!!!"8!!"!J!#!3!!!3!!!3)!!K%\r!!!$J!!%#!!)M!!!"'!!"!J!#+`!!!-J!!3)!!MF!!!#`!!%!N!Tm#!+QN!!"!!L\r8)Ir!1#%!3)!"!!Km#!1Q6S!!)(`)!UDrBIrXN!!"!!L8)Iq`I(XEH(bF)hKm[5Y\riI0icH)2L!##!(`!!+!!!!%##!&3iB!!35!!9*@!!!!#3!(X!!)"l!!!S!`!!3))\r!$$KJ!!C)!!"S1!!!!*!!!`!%J(X!!*!!!`!!J(X!!*!!!`!)J(X!!*!!!`!-J"X\r!!*!!(`!!5!!!#*!!'`!!,"`!!8#"!!`iB!!*5!!!+#JG!!""JJ!-1!!!!C!!(3!\r!+"i!!%'#!!b!!J#SN!!H!!!iB!!!J!%!@$JK!&"m#!1QZf(rl%k!!#!!N!BJ3B!\r&!*!&c!!1,Q0MAfPZDA4TB@aTHQ9m#!+QNq(rr*!!!3!)P#(r`(ar'hJS(`!!3B)\r!+)"r!!!S!`!!3B)!(%J!)T9J!!!!J(m!!%J!%ZeJ!!!!5!!!$$KJ!!T)!!!-1'!\r!!*!!I`!!J!%!5$JK!%"m#!1QJq(rr%k!!#!!N!BJ3B!"!*!&C!!-,Q0MAh0SGA4\rNEhGZ!!"m#!+Q[b(rj*!!!3!)P#(rS(aj'hKmQL0iI,XVH(cF-hKmrcYiI4e$H#J\rC!!"!JJ!-1'!!#NJ!!6JS(3!!3))!$$KJ!!a)!!%S1'!#+%J!%jeJ!!!!I(iEH#J\rH!!"!JJ!-1'!!"NJ!!3JS'J!!3B)!'(p$dhK)!#FpJ%%!&#J$!2p"J!!-1'!!!8J\r!!14r`r0iId66H%J!*Sf!33!8+"`!!%'#!"KrJq0i5!!R#B""!"3S!`$r3B!!$$K\rJ!!a)!!#`1(i""(q%ihK)!#CCJ%%!&*2q!J`li!!!Xri#"*0q!3!i!!!#Q"i#%$J\r!!'53!"i#&(r$mhK)!"0PB!!!!*!!IJ))J"i###J!!!"!JJ!-1'!!"NJ!!&b!'3!\r),!!!!%##!"L6rJ)NNri#)*2C!!#6f3!%5!!!()"j!!56``)JJ"N!"*!!(J)NNri\r#)*2C!!5!H3!)1!-!!C!!'3!)J(N!$$J$!!'3!"N!$*2G!!!iB!!!J!%!D$JK!'"\rm#!1QZb(rj%k!!#!!N!BJ3B!(!*!%!B!!#LjMBepMFQ9KG'9m#!+Q[d(rk*!!!3!\r)P#(rX(ak'hKmQb0iI,`VH(cp1hJiJJ'%1')"Gi#L!%3li!!!IrllH#JD!!"!JJ!\r-1'!!#NJ!!,`S(3!!3))!$$KJ!!a)!!#X+"X!!%##!$b!"3!!,!!!!8##!"JiS!#\rV1-!!!8J!**f!33!85!!!(#`!!!4!JJ!81+!!UcM!!!&)!#5"J%%!&)2k!!")!!!\rdIf2EH(rNqhK)!#9CJ%%!&#`$!!"!JJ!BJ"m"!(`F!!"!JJ!-1m!!!8J!!!L$r`)\rJ+"m!!%'#!!ar`!Ge3B,ra(r!"h9"JJ!3Nrd!!$KJ!!")!!!31!!!!*!!(3!!1'!\r!#S!"!&Ji)3"3I!J$TVY"rqK1J!!J!*!')%'!"J#3"!%3!!JZBf0IEh"PEJ!!I!J\r#TVqKrr53!!%!#*3Krl"mI4YiI*iMH$KL!BdiJJ'%J+)!4#JG!!"!JJ!-1'!!#NJ\r!!*JS(J!!3))!$$KJ!!a)!!#)J"i!!#J!!!"!JJ!mJ!8!!#`!!!&!JJ!B1+!!c6M\r!!!&)!#0pJ%%!&%J!!"`X!!!%3))!&$LJ!-di`!!"5!!MBB""!"5!IJ!!L!-#%#`\r!!!&"JJ!-1'!!$NJ!!#amIaYiIk2VH(rNqhK)!"S*B!!!!(rMqhK)!!mGB!!!!$K\rJ!!#3!(i!!)!"!&Ji)3"3I!J$TVZKrr41J!!J!*!')%'!!`#3"G`!#5jMBepME'p\rcC3"m#!+Q[k(rp*!!!3!)P#(rX(aq'hKmRb0i1')"M6L#!B5!SJ"%+"i!!%##!!`\riB!!+5!!"(#JI!!"!JJ!-1'!!$%J!!3b!(`!!+!!!!%##!$b!"3!!,!!!!8##!"J\riS!$V1-!!!8J!)S@!33!85!!!(#`!!!4!JJ!81+!!kcM!!!&)!#*TJ%%!&)1r!!#\r!(3)8,!!!C%'#!#"rSqYi5!!HP@!!!!"mB!Ge3))!$$KJ!!K)!!#FJ"d#*#J!!!"\r!JJ!JJ"d#)*!!(J!!J(d#)#J$!!""JJ!-1!!!!*!!!`)NJ"d#)#J!!!"!JJ!JJ"d\r#**!!(J!%J(d#*#J$!!""JJ!-1!!!!*!!!`)JJ"d#*#J!!!""JJ!JJ(d#)#J$!!"\r"JJ!8N!!$!L5!(3)JJ(d#**!!!`)J1!!!!CJG!K"r`r0iIq6lH%[rrFf!RJ!-1!3\r!!C!!(J!-J!%!@$JK!&"m#!1QZk(rp%k!!#!!N!BJ3B!$!*!%!@!!#bjMBepNCA0\rdFQpj!!!!+!-!!%##!!`iB!!+6S!!)#J%!!""JJ!8J!-!$*!!"!!!1'!!!%k!!#!\riB!!-6S!!)!#3"L"!!*!(-!!6,Q0MAfGPG&pMD'&ZCf9IG'PYC3!!!(`)!UDr`Ir\riN!!"!!L8)Ir!I(iEH(bI)hL3!+%!B*!!`3"N+"i!!%##!!`iB!!+5!!!H#JI!!"\r!JJ!-1'!!#NJ!!'L!(`)8,!!!C%'#!#JX!!"Q3))!'(rMqhK)!"d"B!!!!(aJ"h9\r!JJ!-1'!!#%J!!$KrirYiJ)%!B)#K!'4)!"6eB!!!!#`$!!"!JJ!3J*i!#$J%!!'\r3!"i!#)#H!!`i"!!"N!!H!!b!!3")1#%!3(`)!kDl`Iri6S!!)!#3"L""J!)!N!@\ri!!NZBf0IFh4[FQ8!I!J#TVr"rrL3!!%!#*3Krm"mIKYiI*mMH*!!S3"JN!$"!'3\rS(J!!3B)!$#JI!!"!JJ!-1'!!#NJ!!&L!(`)8,!!!C%'#!#JX!!"Q3))!'(rMqhK\r)!"`eB!!!!(aJ"h9!JJ!-1'!!#%J!!#KrirYiJ)%!B)#K!'4)!"9jB!!!!)"q!!`\ri!`!"N!!H!!`iB!!!J!%!5$JK!%"m#!1QZm(rq%k!!#!!N!BJ3B!#!*!&S!!2,Q0\rMAh*PE@pfC9pMFQ9N!!!!I!J#TVq"rr#3!!%!#*3Krl"mI"YiI*dMH(bq+hKmhc0\ri1')"R6L#!B5!SJ"%+"`!!%'#!!`S(3!!3))!$$KJ!!T)!!#X+"m!!%##!$b!"3!\r!,!!!!8##!"JiS!&V1-!!!8J!(aQ!33!85!!!(#`!!!4!JJ!81+!"DcM!!!&)!"l\rpJ%%!&)!G!K3X!!"N3B)!+#`!!'C!JJ!BIk2VH%J!'b9J!!!!I'!(G8##!!`iB!!\r)5!!!2)!G!3"m!2!!3B)!$$KJ!!T)!!!S1(d""(rNqhJiS!$r5!!IIB""!"5!I!!\r-1!-!!C!!(!!-1'!!!)!"!&Ji)3"3I!J$TVZ"rr"1J!!J!*!')%'!"!#3"!%!!"%\rZBf0IFf9dAh"bD@jMDA"KE!"m#!+Q[m(rq*!!!3!)P#(r`(bH)hKm[bYi+"i!!%#\r#!!`iB!!+5!!!D)!H!K3X!!"Q3))!)(r$mhK)!"TPB!!!!(aJ"h9!JJ!-1'!!#%J\r!!%!S(`!!3B)!0$KJ!2p)!!PpB!!!!*!!I`!!J(m!!#J$!!"!JJ!-1'!!"NJ!!"3\riRJ%%5!!H6B""!"3iB!!!J!%!5$JK!%"m#!1QZm(rq%k!!#!!N!BJ3B!#!*!&S!!\r4,Q0MAfGPG&p`FQPZBfP`B@`!I!J#TVr"rrL3!!%!#*3Krm"mRL0iI,mVH#JH!!"\r!JJ!-1'!!#NJ!!%L!(J)8,!!!CN##!#"r`r0i5!!CS@!!!!"mB!Ge3))!$$KJ!!K\r)!!!J+"m!!%##!!`iB!!'5!!!%)!H!3#3!"m!!$KJ!!#!!3")1#%!3(`)!kDl`Ir\ri6S!!)!#3"L""J!)!N!@!!"3ZBf0ICf9dAf0bC@4IGQ9bFfP[EJ!!I!J#TVr"rrL\r3!!%!#*3Krm"mRL0iI,mVH#JH!!"!JJ!-1'!!#NJ!!&L!(J)8,!!!CN##!#"r`r0\ri5!!Bq@!!!!"mB!Ge3))!$$KJ!!K)!!!`+"m!!%'#!#3iB!$r5!!)%@!!!!#3!(m\r!!)"r!!"ra20i5!!FmB""!"3iB!!!J!%!5$JK!%"m#!1QZm(rq%k!!#!!N!BJ3B!\r#!*!&N!!!$#jMBepRCA4IEQ&YC3!!I!J#TVqKrr53!!%!#*3Krl"mI4YiI*iMH(b\rr+hJS(J!!3B)!&#JI!!""JJ!-+"d!!%##!!`iB!!+5!!!M)!I!!!S!!!!3))!-$K\rJ!!K)!!GaB!!!!*!!I`!!J(m!!#J$!!"!JJ!-1'!!"NJ!!&b!(3!!N!!$!!#!I`!\r!J!-!!#J!!!"!JJ!J5!!(U@!!!!!i!!!!N!!I!!#3!"i!!$KJ!!0)!!!SI!-$H(r\r%mhK)!"5eB!!!!)#I!!#!C!!!J!-#)*!!"!!!1'!!!)!"!&Ji)3"3I!J$TVZKrr4\r1J!!J!*!')%'!!`#3"GJ!%5jMBepcCA&ICQ9dBfKI6N0c!(`)!UDrSIrdN!!"!!L\r8)Iq`I*dMH(bq+hKmhc0i+"d!!%'#!"3S(`!!3B)!$#J$!!"!JJ!-1'!!#NJ!!FJ\rS(J!!3))!$$KJ!!C)!!'iJ"d#&#`!!'C!JJ!JIk2VH%J!&bPJ!!!!I'!(G8##!!`\riB!!)5!!"N!#!(`!!+!!!!%##!%3iB!!)5!!'2@!!!!#3!(m!!)"r!!!S!`!!3))\r!$$KJ!!C)!!&J1!!!!*!!!`!%5!!!&)#I!!#!C!!%1!-!!C!!"!!%J(m!!)#$!!5\rS(3)%I!3!!%#!!"b!I3))9)!31RaM!#k!!`!!,!!!Bd'#rmL!I`!!J)-!"+JG!J4\rm"!!!3B!!)%J!"M&J!!!!1!!!!*!!(J!!N!!I!!!iB!!$5!!!k)"p!JK8J"!kI'-\r!,S!$!!!X!!!"3))!I$KJ!!K)!!@*B!!!!*!!IJ!!J"i!!#J!!!"!JJ!-1'!!"NJ\r!!+`iB"f!5!!&C@!!!!#!RJ!!N!"N!!5!IJ!!J'-!"#J$!!"!JJ!-1'!!"NJ!!)#\r![3))J*m!!)!%!!48!"!kI)8!,S#%!!3iS"f!5!!D4B""!"4)!!"%,!!!!N##!#b\r!!`!%N!!"!$`i!!!#N!!"!$L!B3!iJ)%!2(r&mhK)!!YYB!!!!%J!!"3i!!!!N!!\rH!!!iB!!35!!!')#I!!#!C!!%1!-!!C!!"!!%1'!!!)!"!&Ji)3"3I!J$TVZKrr4\r1J!!J!*!')%'!!`#3"!)8!"-ZBf0IFf9aAfCPG'0SAf0bC@4c!!!!I!J#TVpKrqb\r3!!%!#*3Krl"mI"YiI*XMH$ZJ!!"r[qYi+"`!!%##!!`iB!!+5!!!d#JE!!"!JJ!\r-1'!!"NJ!!-#!I!!)1!-!!93$%$T)!"N9J%%!&*!!H`!!J"X!!#J!!!"!JJ!-1'!\r!"NJ!!*5$R!!!5!!!G$KJ!J4)!"MTJ%%!&)#E!!"rr[YiI'6a,S"l!!"mBr!Z+!-\r!!%##!!`iB!!'5!!!A(q%ihK)!"M4J%%!&)"l!!"mBr!Z1'-!rcLF!34)!"LjJ%%\r!&)!F!3#!H`!!I'2`,T!!!`)!Jj`#)$Zp!!%lr`!%+"`!!%##ri`iB!!!J*X!!&H\rJ%$TmC!%ZJ!%!@$JK!&"m#!1QZf(rl%k!!#!!N!BJ3B!&!*!%!4!!$bjMBepRCA4\rI6N0ID@jQE`!!!(`)!UD3!!%!#*3Krm!S"!!!3))!$$KJ!!C)!!!8I)-MH%J!!k&\rJ!!!!1'!!!)!"!%Ji)3"!I!J$TNk!!#!!N!BJ3B!!N!Bm!")ZBf0ICR*PC9p`FQP\rZBfP`B@am#!+QN!!"!!L8)Ir!+!3!!%##!!`iB!!'5!!!&(b$)hK)!!0"B!!!!$K\rJ!!#!!3")1#%!3(`)!kC1J!!J!*!')%'!!*!'2!!0,Q0MAfCbC@9IEQ&YC3"m#!+\rQNq(rr*!!!3!)P#(r`(bI)hJS(`!!3))!$$KJ!!T)!!!NJ(m!!%J!&"eJ!!!!J(m\r!!%J!!Y&J!!!!1'!!!*!!I`!!J!%!5$JK!%"m#!1QJq(rr%k!!#!!N!BJ3B!"!*!\r&@!!1,Q0MAfCbC@9IBh*PC(0m#!+Q[m(rq*!!!3!)P#(r`(bH)hJS(J!!3))!$$K\rJ!!T)!!"%1!!!!(`I!hK)!!!BJ(i!!(aMq#j)!"C*J%%!&$[r!!5!IJ!!I!2i,LJ\r!!!"!J[rJ5!!@,B""!"3iB!!!N!"q!!#!!3")1#%!3(`)!kDl`Iri6S!!)!#3"L"\r"J!)!N!9i!"!ZBf0ICR*PC9p13epTEQC[!!"m#!+Q[m(rq*!!!3!)P#(rX(bI)hK\rm[LYi+"m!!%##!!`iB!!-5!!"*$KK!$K)!"@*J%%!&)!I!K3X!!"N3B)!'$KK!$J\riR`)B1+%!3%J!&B'!33!8,"i!!N'#!#a!J!!3,"i!!8#!!"4)!!$8,"i!"%#!!-a\r)!!")1!!!C*!!(`)85!!!a)!I!K3X!!"N3))!)$J!!'@3!"m#&)"K!$L!!3!mN!"\rr!KL3!"m#(%J!!*`X!!"Q3))!P$KJ!!K)!!#3!)!I!K3X!!"N3))!)$J!!'D3!"m\r#&)"K!$L!!3!mN!"r!KL3!"m#(%J!!'3X!!"Q3))!')J"!%!S!!!!3))!$$KJ!!K\r)!!"-J"m#&#`!!'9!JJ!mL!%!3#J!!!""JJ!J1!!!CT!!(`)8J'%!1)!"!$b3!(m\r#'*!!(`)F5!!!&$KJ!!K)!!!31'!!$%J!!!JiB!!!J!%!@$JK!&"m#!1QZm(rq%k\r!!#!!N!BJ3B!#!*!%!9`!%#jMBepXEf0VAh*PFA9PFh3!!(`)!UDr`IriN!!"!!L\r8)Ir!I(iEH%J!&-Q!33!8I(mEH#JI!!""JJ!8Iq2lH(r%mhK)!"6GJ%%!&(rMqhL\r!!3")1#%!3(`)!kDl`Iri6S!!)!#3"L""J!)!N!93!!XZ6Q9h8f&QC9"dFJ!!!(`\r)!UDr3IrSN!!"!!L8)Iq`I(SEH$Z#!FSlSJ'p1m)"Vi2L!%4)!"3"J%%!&(al'hJ\rS'J!!3))!6)!I!!!X!!!"3))!)(r$mhKrT1Yi1+!!*cM!!!&)!"1jJ%%!&%J!!#3\rX!!!%3))!((r$mhKrT1Yi1+!!*cM!!!&)!"19J%%!&#`E!!""J3"-J"m!!#`!!!&\r!JJ!JIi2MH(qNkhJiS!!S1-!!!8J!%fQ!33!85!!!*#`!!!4!JJ!FIi2MH(qNkhJ\riS!!S1-!!!8J!%d@!33!8Id26H$L!!!"rCGYi5!!6BB""!"4r3p0i1)!!!(pPfhK\r)!"00J%%!&(p$dhKrC0Yi5!!69B""!"4r3p0i5!!5kB""!"5!!3"B1#%!8(`)!kD\rl3IrS6S!!)!#3"L""J!B!N!3"+!!2,N4TFh"[Ff96B@CP8(4b!!!!I!J#TVr"rrL\r3!!%!#*3Krm"mIKYi5!!6EB""!"4mIaYi+"m!!%'#!"4rirYiIm6cH%J!%b'!33!\r8Iq2lH)!"!%Ji)3"!I!J$TV["rrK1J!!J!*!')%'!!J#3"9!!$Lj1CAG6B@CP8(4\rb8hPcI!J#TT2Krrb3!!%!#*3Krm"mIaYi1')"ecL#!Ef!SJ"%+"m!!%##!$b!"3!\r!,!!!!8##!"JiS!"31-!!!8J!%K@!33!85!!!(#`!!!4!JJ!81+!!8$M!!!&)!"(\rjJ%%!&$J!!!#`(`)%1!!!#V!I!JBiB!!S5rrr(C!!I`))J(m##)!"!%Ji)3"!I!J\r$TS2Krra1J!!J!*!')%'!!3#3"C3!$LjZCAG$FQ9N3R9QCQ9bI!J#TT2Krrb3!!%\r!#*3Krm"mIaYiN!#"!&b3!+%!B*!!`3"N1')"iML#!Ef!SJ"%+"m!!%##!$b!"3!\r!,!!!!8##!"JiS!"H1-!!!8J!%9@!33!85!!!(#`!!!4!JJ!81+!!AMM!!!&)!"%\rjJ%%!&)!"!&b3!"m!!)!"!'#3!"m!")!"!'3S!!!!3))!%$KJ!!#3!(m!#%J!!$L\r!B3"J5rrq4C!!I`!)J(m!##J$!!"!JJ!-1'!!"NJ!!"L!J3"NJ+%!B%J!%BQ!33!\r81'!!!)!"!%Ji)3"!I!J$TS2Krra1J!!J!*!')%'!!3#3"G`!$#jMEh"j4'&dB8p\rLDJ!!I!J#TVl"rpL3!!%!#*3Krk"mGaYiI*JMH$Z#!KSlSJ),1X)"qcKL!Hil`J'\rpJq)!4$YJ!!!S'!!!3))!4)!I!!!X!!!"3))!((r%mhJiS!"d1-!!!8J!%%f!33!\r85!!!)#`!!!4!JJ!BIm6cH$LJ!(3i`!!"5!!3,B""!"4qqVYi+"S!!%##!"Ji!!!\r!N!!B!!")!!(F5!!!#$Yl!!'!'J!!1eS!"#J!!!"!J[r`1"X!!93$%$T,rrdYN!"\ri!!"mH4Yi+"N!!%##!%b!(`!!,!!!!8##!#"q`l0iIm6cH$LJ!(`i`!!"5!!2[B"\r"!"4)!!!N,!!!"%##!"aq`l0iIm6cH$LJ!(`i`!!"5!!2QB""!"3S'3!!3B)"@(l\rkZhK)!!%d1'!!$%[rr,f!Q!!!N!"N!!#!H!!!J!-!!#J!!!"!JJ"-J"m!!#`!!!&\r!JJ!JIk2VH(r%mhJiS!#$1-!!!8J!$d@!33!85!!!*#`!!!4!JJ!FIk2VH(r%mhJ\riS!#$1-!!!8J!$b'!33!8J(J!!)"M!!!S!`!!3B)!f)#A!!!iS!!-5!!2UB""!"5\r!H!!!J'-!!)"M!!4,rr`YJ*J!!)#%!!#3!'3!#)"i!!#!B`!!J!-!##J!!!"!JJ"\r-J"m!!#`!!!&!JJ!JIi2MH(r%mhJiS!#,1-!!!8J!$Uf!33!85!!!*#`!!!4!JJ!\rFIi2MH(r%mhJiS!#,1-!!!8J!$SQ!33!8J(J!!)"M!!#!B`!)+!-!!%'#!$b!Y`!\r!J)8!#)#P!!4)!!m*J%%!&$XB!!3l@J!%J"S!!#J!!!"!J[l)1'!!!&GJ%$TmH3%\rZNcJ!!)!"!'Ji)3"JI!J$TVV"rpK1J!!J!*!')%'!#J#3"!+!!!iZBfp`H84KG'&\r"FR*KHA`)!UDrSIrdN!!"!!L8)Iq`N!"K!'L3!)%!E(bp+hL$`3"X+"d!!%##!!`\riB!!'5!!"2$KJ!!K,rrX0N!"p!!#!(3!!+!!!!%##!!`iB!!'5!!"($KJ!%a,rrV\rYI(mEH#JI!!"!JJ!-1'!!"NJ!!3!iB!6L5rrkdC!!I`!!J"m!!#J!!!"!JJ!-1'!\r!"NJ!!1!iB!6L5rrkXC!!I`!%J"m!"#J!!!"!JJ!-1'!!"NJ!!-#!I`!!J*i!!$L\rJ"0p)!!iKJ%%!&)"r!!5!RJ!%1+!%hdJ!$Jf!33!81(m!#)#H!!L![J!-J0i!%%[\rrqi'!(J!8N!!I!"5!(J!BN!!I!"L!(J!FN!!I!"b!(J!JN!!I!##!(J!NN!!I!#5\r!(J!SN!!I!#L!IJ!X1*m!,%[rr%%iI`!`J*i!-)#q!$5!hJ!i5rrl-6Kr!$b!RJ!\rmJ,i!3)$H!%4,rrXG1'!!!*!!I`")1!!!!S#G!!#3!!3!!)#G!!#6j!!%J!%!@$J\rK!&"m#!1QZk(rp%k!!#!!N!BJ3B!$!*!%!A`!#bjMEh"j9M9$FQ9N!!!!I!J#TVr\r"rrL3!!%!#*3Krm#3!'%!@*!!J3"FI,iVH#JH!!"!JJ!-1'!!"NJ!!'JiB!!)5rr\rjGC!!IJ!!J(i!!#J$!!"!JJ!-1'!!"NJ!!%Ji!!!"N!!$!!!iB"f!5rrj6Aar'hJ\rS(`!!3))!$$KJ!!C)!!!NIq2lH)#"!&`iS"f!5!!-NB""!"5!IJ!!Nq-!"$KJ!!#\r!!3")1#%!3(`)!kDl`Iri6S!!)!#3"L""J!)!N!@N!!XZBfp`H9Bd3h*PC!!!!(`\r)!UDr`IriN!!"!!L8)Iq`I(iEH*!!J3"XN!#K!(!li!!!Nq%!1#JH!!"!JJ!-1'!\r!#NJ!!1L!!3"X,!!!!8'#!"3X!!!#3B)!$$KJ!"")!!$-U(i#"$J$!!'`(J)%U(i\r#"+JH!JCm!`!!3))!@&3!#$b`(J)'U"i#"P3$%$T,rrKPI(mEH#JI!!"!JJ!-1'!\r!"NJ!!)KrirYiJ*i##+JH!JCm!!j`I!!"P&3&%$T)!!ZGJ%%!&)"q!JK,rrEGNri\r##)"K!'`X!`!"3))!&)#"!(!iS3!i5rrqD8J!!#3X!`!#3))!&)#"!(!iS3!i5rr\rmY8J!!!`iB!!35!!!))#K!$L!RJ))U(i#"$J$rrp8!"!kI+3",MKJ!!#!!3"B1#%\r!8(`)!kDl`Iri6S!!)!#3"L""J!)!N!3",!!4,Q0bC@4#G@CQCA**ER0PFR3!I!J\r#TVqKrr53!!%!#*3Krl"mIaYiN!#"!'b3!+%!F$[!!!!S(`!!3))!$$KJ!!T)!!$\r!IphcH%J!!+L!I`))I)2`,S"N!!#!K!!%J+%!E)$"!(")!!(4B!!!!(aJ"h9"JJ"\riJ(m##(r$m#jr`r0i5!!('@!!!!"r`r0i5rrecAqPkhK8Sa!k5!!!))#I!JJi"3!\r"9!!31R`%!#jm""NZ1+8!!6KM!!5SR`)%1!6rrh`&!!""J2rB1)!!!)"r!JK8!"!\rkI)-",UKr!J3i!rrrX"m#"%J!!"Jl[3!"1pi!"+JI!J4m(3!!3B$r9$KJ!!#!!3"\rB1#%!8(`)!kDlSIrd6S!!)!#3"L""J!-!N!3"!!!4,Q0bC@4#G@CQCA*5C@e[GQ8\r!I!J#TVq"rr#3!!%!#*3Krl"mI"YiI*dMH$KL!M%iJJ'pJ+)!4$J!!!#3!!%!1#J\rG!!"!JJ!mJ!8!!#`!!!&!JJ!B1+!"5$M!!!&)!!MPJ%%!&%J!!"`X!!!%3))!&$L\rJ!8Ji`!!"5!!)bB""!"3S(3!!3))!$$KJ!!a)!!"-1m!!!(rImhK)!!!SJ(d##(`\r$q#k3!!%!1(q$ihJiJ3!i5rraJ@!!!!!lhJ!"1rm!"+JG!J4m(J!!3B$re)"p!JK\r,rr4P1'!!!)!"!&Ji)3"3I!J$TVZ"rr"1J!!J!*!')%'!"!#3"GJ!%LjNDA0`Eh0\rP3h*PC%*eCQCPFR`)!UDr`IriN!!"!!L8)Ir!N!"K!&L3!)%!A*!!S3"JN!$"!'5\r$`3"F+"i!!%'#!"#$i3"N+"m!!%##!!`iB!!!5!!!k)"K!&L!!3"JI!-!!%'#!!`\riB!!!5!!!d#`$!!&!JJ"X1(i!!6LI!!&)!!LjJ%%!&#`$!!"!JJ"-1(i%icLI"10\r)!!LKJ%%!&#`$!!"!JJ!d1(i6L6LI%iP)!!L*J%%!&#`$!!"!JJ!FJ(iBI)!I'(a\rm!`!!3))!$$KJ!!&)!!"S1'!!!%J!!'!X!`!#3))!9)"q!!#!R`!!5!!)5B""!"3\rX!`!!3))!0)"q!!5!R`!%5!!)-B""!"3X!`!!3))!()"q!"L!(`!BI!-!!%##!!`\riB!!"5!!!%$KJ!!")!!!)1'!!!)!"!%Ji)3"!I!J$TV["rrK1J!!J!*!')%'!!J#\r3"!%i!!JZBh*PC'0YF!!!I!J#TVq"rr#3!!%!#*3Krl"mI4YiI*`MH#JF!!"!JJ!\r-1'!!"NJ!!C`iB!)S5rrb0C!!I!!!J"`!!#J!!!"!JJ!-1'!!"NJ!!Aam(`0iIq2\rlH(qNkhK)!!F"J%%!&)!G!3#3!"m"!$Kr!33iR3%%5!!'kB""!"5S(3)%X"m#"+J\rG!JD`(`)'1!!!!CJI!K#S(`)'9!-31N[rmFf3!(m##)!I!JJS!!!!3))!$$KJ!!C\r)!!%81m!!!(rFmhK)!!$`J(d##(b$i#k!C!!!,!-!!8##!)!iB!!)5rraMB#I!JK\rmC1%ZJ(m##(aMi#iS!`!!3))!$$KJ!!C)!!$-1!!!!C!!!`!!1'!GJ%[rm9f!R`)\r)I)6J,T!!C!!%J(m##(aMi#k!B`!%+!-!!%##!!`iB!!'5!!!P)#G!JKmK1!ZJ)3\r!"$LJ(B")!!C&J%%!&%J!!&JX!`!#3))!')#%!!5!(`))I+$L&%[rphe)!!!m,!-\r!Bd##!$3iB!!)5rr`lB#I!JKmC1%ZJ(m##(aMi#iS!`!!3))!$$KJ!!C)!!!X1!!\r!Bj!!!`!!1pi!!6ZF!!5S(`)%I"i!!%'!r``iB!!!N!"r!L53!(m#))!"!&Ji)3"\r3I!J$TVZ"rr"1J!!J!*!')%'!"!#3"!(8!!BZC(9`6N0m#!+Q[m(rq*!!!3!)P#(\rr`(aq'hKrhr0i+"m!!%'#!#a)!!!8J(m!!)"M!!K,rr#j1rm!")!I!!!S!!!!3),\rrk(r$mhK,rr#KJ!%!5$JK!%"m#!1QZm(rq%k!!#!!N!BJ3B!#!*!&A!!4,Q4TFh"\r[Ff9%BA4K3A*bBAN!I!J#TT2Krrb3!!%!#*3Krm"mIaYi1')#2$L#!Ef!SJ"%+"m\r!!%##!&#!"3!!,!!!!8##!"JiS!(#1-!!!8J!"$@!33!85!!!-#`!!!4!JJ!S1+!\r"`MM!!!&)!!3CJ%%!&%J!!"4rirYiIq6lH%[ri4eJ!!!!J"m!!#J!!!"!J[rS1'!\r!!)!"!%Ji)3"!I!J$TS2Krra1J!!J!*!')%'!!3#3"CJ!#bjQFQ9P6N0-DA0d!!!\r!I!J#TT2Krrb3!!%!#*3Krl"mIaYi1')"ecL#!Ef!SJ"%+"m!!%##!$b!"3!!,!!\r!!8##!"JiS!(51-!!!8J!!hf!33!85!!!(#`!!!4!JJ!81+!"dMM!!!&)!!0KJ%%\r!&$KK!$K)!!-0J%%!&(aJ"c9"JJ!-1'!!!%J!!%#!(`)8,!!!C%'#!#JiB3!i1*m\r#'$LK!%")!!,eJ%%!&(aJ"c9"JJ!81'!!!%J!!"!i!!!!Q!%!3)KK!%#!!3"B1#%\r!8(`)!kD$iIrm6S!!)!#3"L""J!%!N!A-!!XZDA0-Ef0V6h9bF`!!!(`)!UDr`Ir\riN!!"!!L8)Ir!I(iEH$KL!NmiJJ'pJ+)!4#JH!!"!JJ!mJ!8!!#`!!!&!JJ!B1+!\r"jcM!!!&)!!+4J%%!&%J!!"`X!!!%3))!&$LJ!HFi`!!"5!!#GB""!"5!(J!!,!!\r!!N##!'L$rJ!%J(m!!%[rlNf!I`!%5rrZ4B"r!"!S!`!!3B)!#%[rlM@!I`!i+!-\r!!%'#!!K,rqiPJ(m!4#J$!!""JJ!)5rrZ&B"r!%JS!`!!3B)!#%[rr5'!I`!X+!-\r!!%'#!!K,rrd4J(i!"%[rlHdiB!!!J!%!5$JK!%"m#!1QZm(rq%k!!#!!N!BJ3B!\r#!*!&m!!A,Q0MAfCbC@9IBh*PC&pTER4PFQjKE(-!!!"m#!+QN!!"!!L8)Ir!5!!\r!U@!!!!"mB!Fe3B)!#%J!!"!i!!!!J))!)*!!"!!!J!%!5$JK!%"m#!1Q6S!!)!#\r3"L""J!#3"M`!%bj*EQPdD@&XDATP3f&MD'9-D@)!!!"m#!+QN!!"!!L8)Ir!5!!\r!R@!!!!#!!3")1#%!3(`)!kC1J!!J!*!')%'!!*!'*!!5,P4PFQeTEQ&dC80KBfK\rP6'PLI%-6H%k!!#"m#!+QN!!"!!L8)Ir!5rrrlAaT'hL!BJ"JJ))!A$LL!!!i`J*\rGJ1)!8)%#!%a)!!"CJ%%!&)##!+53!'3!!%[rf)eJ!!!!1'!!!)!"!%Ji)3"!I!J\r$TNk!!#"m#!+QN!!"!!L8)Ir!J')!T)"M!!")!!!aJ%%!&)!"!%Ji)3"!I!J$TNk\r!!##"JJ"!N!""!"5!$!!!J%`!"(`*!kC1J!3JJB)!2*!!33!8J!`!!)"-!!4m#31\rQ6S!%))'#!"L3!%%!&)!-!!#!6!!%I!N$TNk!"##"JJ!8N!""!"5!$!!!J%`!"(`\r*!kC1J!3JJB)!$*!!33!8J!`!!)"-!!4m#31Q6S!%))'#!%L3!%%!&)!-!!#!6!!\r%I!N$TNk!"##"JJ!3N!""!"5!$!!!J%`!"(`*!kC1J!3JJB)!1*!!33!8J!`!!)"\r-!!4m#31Q6S!%))'#!!53!%%!&)!-!!#!6!!%I!N$TNk!"##"JJ!FN!""!"5!$!!\r!J%`!"(`*!kC1J!3JJB)!-*!!33!8J!`!!)"-!!4m#31Q6S!%))'#!!L3!%%!&)!\r-!!#!6!!%I!N$TNk!"##"JJ!SN!""!"5!$!!!J%`!"(`*!kC1J!3JJB)!!*!!33!\r8J!`!!)"-!!4m#31Q6S!%))'#!#b3!%%!&)!-!!#!6!!%I!N$TNk!"##"JJ!NN!"\r"!"5!$!!!J%`!"(`*!kC1J!3JJB)!0*!!33!8J!`!!)"-!!4m#31Q6S!%)!!!*cL\r!!!"B!*!'*j!!J!!!,!#3#8iL+@`#)LP8!L)#ABB#!5PX)J'GJJ)4!Bd"K!&h!Nm\r#2!)a!KS##`(l!Hi"iJ(A!FS"[3'[!+`"D!3L%ML'!K84R"%N%-J3D!md$2J,r!Y\r-#U3*i!Lm"rJ(*!E-"8`%9!-S!B`"#!!F*ZJL*S3%,Ne*9#"*,e-J6@&M4'9f!5#\r"CJ`K+'jKE@8J)6dJ-#N)3d0KBfKP,Q-2)5JUD'&ZC'aP)#%p)$!T%5%SF(*TEQ0\rTF'&X)#%p)$!T$5%SFf&QC9!J)6dJ-#N-3d0KBfKP9A4TE#jM$#%SFfPkC5!q)$"\r-+3SK+'jM)#%p)$!T#b%SEf*U)#%p)$!T$#%SC'9cG#!K25!`+3pbCA4NCA0d)$d\rp)%j96%`1+LTNCA0d)$dp)%j96%`@+#SUC'9cG#NY2Q4KG'%J26dJ6P9-6!TZBb!\rp25"198a-%L%SBfjdFQa#E'pMDb!K25!`+3dK+'0bC@4c)#%p)$!TFGB!!!%!!!!\r"B!!!!'!!!!!b!,V"!*!%2S!!CL!!ZZ%!N!3qK3#X)!$p1`#3"B!!E!!!Z[d!N!@\r!!(J!!,X2!*!%2S$rr`!!Zam!N!3qMIrr!!#l3`#3"$k-rrm!!,Yr!*!%2SArr`!\r!qmF!N!3qJ2rr!!#lZ`#3"$k0rrm!!,[[!*!%2Scrr`!![#-!N!3qKIrr!!$lN`#\r3"$k!!))J!,aA!*!%2S!!M3!![&m!N!8"rrm!!2Xr!*!%2SArr`!!r*d!N!Err`!\r!r@N$VL"F!d0@8`T8BA0V)%jKE@9c$%0A3eC6)&"KEQ9XF`i!!!"F!*!,!3#3%`&\r`Gh"M!*!6!3#3%6`168P8Ak9$3f&MD'9-D@)!N!8"!!!!!@!!!!"J!!!!-J9@1G!\rd*J!!!"`!-J!!BfCbC`!!!!S!!2rr!*!%"9Bi[&YF:\r
\ No newline at end of file
diff --git a/src/mac/libraries/CCache API/bin/CCacheLib.PPC.debug b/src/mac/libraries/CCache API/bin/CCacheLib.PPC.debug
deleted file mode 100644 (file)
index c72e54a..0000000
+++ /dev/null
@@ -1 +0,0 @@
-(This file must be converted with BinHex 4.0)\r:%d0$B@0SC8aTBLj38%-ZC'9LG@F!FfKXBMq3"!#3"$LS!!!"PV5C5Qpj)A"PCQC\r`Gh"M!!!!!E*6cTi!N!d$!!)!N!6rN!3!N!Ba`!!!-F!!!$(!!!!&J!!%"!$rN!3\r!N!B#D3!!!Q8!!!&S!!!h3!)%"!$rN!3!N!i%mJ!!!)!%"!3!N!ArN!3!N!F"!!!\r"D!!!!!%!!!&J!!!!"3!!!"8!!!!"!!!"%!!!!5!!!!1-!!!!"!!!!"8!N!m+!*!\r,$3#3#`%!!!!+!*!()`!!!!%!!!!"!!!!!J!!!!X!N!Fl!*!,!J!!!!d!N!G8!*!\r,"J!!!!m!N!3#!!"R!J!!F!)!!(S#!!#(!J!!NJ)!!*d#!!#Q!J!!X3)!!,d#!!$\r2!3!!eJ%!!1)#!!$[!J!!r3)!!4-#!!%R!J!",J)!!68#!!%p!J!"4!)!!8X!!3#\r3"3J!N!4+&%!"3J&!!8)33J#!!dB@5@jdCA*QB@0P6'PL!%e*9&qP3d0KBfKP4fa\r[BQ&XFdaTBJ"0594IT84PBR9RCfPZCdaTBLjNC@*eC`"0594IT8e*9&*eER4TE@9\r-D@)ZC'9LG@F!68P8Ak90594$6'PL,Q4PBR9R!&0jFd*bC@&V!%jPGe"dFP0jF`"\r9EQK[E'40C@e[FRN!5'pXC%ePE@pbH3"%DA0`Eh0P8(4b!%4PBR9R8h4b!%GPG&"\rdFP0THQ8!8f&YC9"bEf0PFh-!4f9d3h9bFQ9ZG&"bEf0PFh-!6Q9h8(4b!'G$ER4\rbE%*XEf0V!'G%C@*eCe0TCfjKE!""E'9bG&0TCfjKE%&d!&pIG@jbC@GTFh4PFPp\rQFQ&RE@9ZG!"IAh*PCfPcG'9bAfCbB@GYC@jd!(0dFQ0YF!"YC@eMF(N!Fh4bEQ0\r`H3"cG(*MF(N!Fh4bE'9Z!'ePEA0PG!"MBepRCA4IBh*PC&pfCA*cD@pZBf0IC'9\rcG(*[H@0MAfGPG&pMD'&ZCf9IG'PYC@0MAfCbC@9I6N0ID@jQEf0MAf0bC@&dC@0\rMAf0XEh0PBf0ICf9dAfjKE@9MBepQFQ9PAf0bC@4cBf0IFQ9YEhCPAf0bC@4MBep\rQFQ9PAh"bD@jMDA"KE'0MAfp`C@jMBepcD(9dC'phEQ0MAh0PG&p`FQPZBfP`B@a\rMBepcCA&ICQ9dBfKI6N0cBf0ICf9dAdj$AfPZCQpMBepTEQPdD@&XDATPBf0ICf9\rdAh"bD@jMDA"KE'0MAh0PF9pQCA4MD&pMFQ9NFf0MAh0dEh*PBf0ICR*PC9pZB@e\rPBf0IE'pMDepbCA&eCA0d!*!("!!!!!`!!3!)!!3!!!!'!!J!"J!)!!J!!!!+!!3\r!#J!!!!X!%!!,!!`!$`!!!")!"!!5!!!!%`!)!"-!%qq*!!UDh`!569F!$c0A!!P\r-)3!)*Xm!#cEk!!h1V`!1jP-!%IJ'!!F66!!,2Ad!%)`+!"##X3!1ZFB!$FMP!"$\r-#`!5#&i!##F0!!aR@J!2'"i#!!&5!!!"!!!"!J!"C3!!!6!!!3)!!@m!!!%S!!%\r#!!'"!!!!`!!"!J!"N!!!!!&)!!%#!!'C!!!"1!!"!J!"S3!!!2J!!3)!!D`!!!$\r)!!%#!!'j!!!"'!!"!J!"a`!!!0J!!3)!!GJ!!!&!!!%#!!(I!!!"8!!"!J!"kJ!\r!!4!!!3)!!IS!!!$`!!%#!!)+!!!!i!!"!J!#'!!!!9J!!3)!!L8!!!%)!!%#!!)\re!!!!k!!"!J!#4`!!!5!!!3)!!Nm!!!$3!!%#!!*E!!!!Z!!"!*!1I!J#TT!!!3!\r)P#(r`$JK!%#!!3!)I!J$TNk!!#"m#!+QNq(rr*2"rrL6SIrdNi(rm*!!!3!)P#(\rrX(ar'hL3!)%!E(bm+hKmh60iJm)!+)"q!!!S!`!!3))!B$KJ!"")!"PeB!!!!*!\r!I`!!J*m!!#J%!!"!JJ!-1'!!"NJ!!(`iS!!!J0m!!*!!TJ!%J2m!!*!!T`!!13!\r!!)%r!!#4#3!)18!!!)&r!!#45`!-JCm!!*'H!!")!!!-J(i!!*!!I`!!J)%!E#`\r%!!&!J3!-1'!!#8J!!#JS(!!!3B)!$$LJ!!'3!,`!!#JG!!""JJ!-J-)!X*!!h3!\r!1'!!!)!"!&Ji)3"3I!J$TS2Krrb$`IriJk(rp)1"rr"1J!!J!*!')%'!"!#3"IJ\r!$LjMBepTEQPdD@&XDATPI!J#TT2Krrb3!!%!#*3Krm"mIaYi+"m!!%'#!#b!I`!\r!+!-!!%'#!##!I`!!5!!U)@!!!!#!I`!!5!!@T@!!!!")!!!-1'!!#NJ!!"!iJ!!\r!N!#I!!!iB!!!J!%!5$JK!%"m#!1QJq(rr%k!!#!!N!BJ3B!"!*!&E!!-,Q0MAh0\rSGA4NEhGZ!!"m#!+Q[f(rl*!!!3!)P#(rX(aq'hKmR#0iN!#K!("mh60iN!$K!(K\rp'd0i1q!!!#JH!!"!JJ!-1'!!#NJ!!8JS'`!!3))!$$KJ!!a)!!%i1'!#+%J!&m&\rJ!!!!I(mEH#JI!!"!JJ!-1'!!"NJ!!4JS(!!!3B)!'(q$ihK)!#pCJ%%!&#J$!2p\r"J!!-1'!!!8J!!24rirYiIi6MH%J!,UQ!33!8+"d!!%'#!"KrSqYi5!![*B""!"3\rS!`$r3B!!$$KJ!!a)!!$!1(m""(qNkhK)!#jeJ%%!&)"K!(L3!(m#$$L!!!#`R`)\r%J+%!F*!![`%!1-!!!TMI!K!ii!"NN!$r!K4rirYi5!!AM@!!!!#3!(m##)%I!JJ\rS#!!!3))!$$KJ!!C)!!"NJ6i!##`*!!"!JJ!F18!!!*&I!L54A`)JNri!!*2q!!4\r)!!!JJAi!"*2V!L#"RJ!%NCm#*$KJ!!#3!(m#)*2q!!5!RJ!)1)3!!C!!RJ!)J,i\r!$$LP!!'3!,i!$*2l!!!iB!!!J!%!@$JK!&"m#!1QZf(rl%k!!#!!N!BJ3B!&!*!\r%!C3!#LjMBepMFQ9KG'9m#!+Q[Z(rh*!!!3!)P#(rS(ah'hKmQL0iI,NVH(ci1hJ\rlSJ'-1m)"Ii2L!#`lJ!!!1f!!!#JA!!"!JJ!-1'!!#NJ!!3`S'!!!3))!$$KJ!!a\r)!!$m+"S!!%##!)5!I`!!,!-!!8##!#"r`r0iIk6VH$LJ!+Xi`!!!5!!XFB""!"4\r)!!"FJ*m!!#`%!!*!JJ!8Im2cH%J!,'f!33!85!!!3)#r!!!X"3!$3))!%%J!,'f\r!33!85!!!+)$I!!!X"J!%3))!((r$mhKrT1Yi1+!!UcM!!!&)!#`9J%%!&)1A!!"\r)!!!dId26H(q%ihK)!#dGJ%%!&#`$!!"!JJ!BJ2`"!(`C1!"!JJ!-1f!!!8J!!!L\r$R!)J+"`!!%'#!""rD!Gd,!J!!%'#rm"rD3Gd,!N!!%'#!"#6Q!!!1'!!!%J!!"!\rj3!!!N9J!!$KJ!!U!!3"S1#%!B(`)!kDkiIrF6S!!)!#3"L""J!N!N!3"B!!),Q0\rMAfp`C@i!!(`)!UDr3IrSN!!"!!L8)Iq`I(SEH(bF)hJl`J'91k)"M)2L!#`lB!!\r!+"S!!%##!!`iB!!+5!!!k#JF!!"!JJ!-1'!!$%J!!0L!I!!!+!-!!%##!)5!R`!\r!,!3!!8##!#"r`r0iIk6VH$LJ!-di`!!!5!!UrB""!"4)!!"FJ,m!!#`&!!*!JJ!\r8Im2cH%J!+[Q!33!85!!!3)$I!!!X"J!$3))!%%J!+[Q!33!85!!!+)$r!!!X"`!\r%3))!((r$mhKrT1Yi1+!!c6M!!!&)!#UKJ%%!&)%F!!#*#!)3I3J(G#`)!!&"JJ!\r-1'!!$NJ!!$#$I!!!Id26H(pNfhK)!"r0B!!!!(pMfhK)!")GB!!!!$NJ!!#42!!\r!1'!!!)!"!&Ji)3"3I!J$TVY"rqK1J!!J!*!')%'!"J#3"!%`!!NZBf0IBfa[Ff8\r!I!J#TVmKrq53!!%!#*3Krk"mHKYiI*XMH$[#!C8lSJ'-Jq)!,$Z!!!!S'J!!3))\r!$$KJ!!T)!!'!+"X!!%##!!`iB!!-5!!"F)"l!!!S!`!!3))!K)#I!!!X"!!"3))\r!)(r$mhKrT1Yi1+!!kcM!!!")!#QaJ%%!&%J!!&b![`!!,!8!!N##!"4r`r0i5!!\rTVB""!"4)!!"!J0m!!#`'!!0!JJ!35!!TVB""!"4)!!!SJ2m!!#`(!!4!JJ!FIm2\rcH(qNkhJiS!$V1-!!!8J!+9@!33!8JjX!!)%F!K3X#!"N3B)!*(q$ihK)!#9jB!!\r!!(aM"h3X!`!!3))!$$KJ!!K)!!#dJ6`#*#J*!!"!JJ!NJ9`#)*&D!!#"I!)J+!X\r!!%'#!"!jJ!!!J(`#)*'$!L5!R!)J+!3!!%##!#5![!)NN!#k!!5!h!)N+!B!!%'\r#!"!ii!!!J4`#**!!k!)JJ6`#*#J*!!""JJ!SJ9`#)#J+!!""JJ!FJA`#*)'F!L#\r4E!)NJ(`#))#F!L53!'3#)$LJ!!'B[!)3Id26H(pNfhK,rrdCI(NEH)$D!!`iaJ!\r"N!$D!!ar)mYiJ!%!D$JK!'"m#!1QZb(rj%k!!#!!N!BJ3B!(!*!%!FJ!#bjMBep\rNCA0dFQpj!!!!+!-!!%##!!`iB!!+5!!!)#J%!!""JJ!8J+-!$*!!T!!!1'!!!%J\r!!!JiB!!-6S!!)!#3"L"!!*!(-!!6,Q0MAfGPG&pMD'&ZCf9IG'PYC3!!!(`)!UD\r6iIrmNm(rq*1Krr53!!%!#*3Krl"mI4YiI*mMH*!!S3"`N!$"!(3l`!!!+"d!!%#\r#!!`iB!!+5!!!L#JI!!"!JJ!-1'!!#NJ!!(L!I`)8,!-!C%'#!$#!R`)8,!3!CN#\r#!"arirYi5!!MZ@!!!!"mB`Gd,!-!!%##!!`iB!!)5!!!3(rMqhL!J3"`J+%!G%J\r!'HeJ!!!!I(iEH#`H!!"!JJ!3J,d!#$LP!!'3!,d!#)$G!!`iaJ!"N!$G!!ar`r0\riJ!%!@$JK!&"m#!1QJq(rr)2"rrL$SIrd6S!!)!#3"L""J!-!N!AF!!NZBf0IFh4\r[FQ8!I!J#TT2Krrb6`IriN!!"!!L8)Iq`I(iEH(bI)hL3!+%!F*!!`3"d1'!!!*!\r!B3!i+"i!!%'#!!`S(`!!3))!$$KJ!!T)!!"JJ*m#&#`%!'4"JJ!`J,m#&#`&!'C\r!JJ!FIq2lH%J!)XPJ!!!!I'-(G#`$!!"!JJ!-1'!!#%J!!#KrirYiJ)%!F)#K!(4\r)!"TaB!!!!)$H!!`iaJ!"N!$H!!`iB!!!J!%!@$JK!&"m#!1QJq(rr)2"rrK1J!!\rJ!*!')%'!!J#3"EJ!$bjMBepbC@e[GQ9IBh*PC!!!!(`)!UDr3IrSN!!"!!L8)Iq\r`I(SEH(bE)hL3!+%!F(cF-hJl`J'P1k)"M)2L!#`S'J!!3B)!$#JE!!"!JJ!-1'!\r!#NJ!!3!S(!!!3))!K)"r!!!X!`!"3))!)(r$mhKrT1Yi1+!"DcM!!!")!#@PJ%%\r!&%J!!&b!R`!!,!3!!N##!"4r`r0i5!!PSB""!"4)!!"!J,m!!#`&!!0!JJ!35!!\rPSB""!"4)!!!SJ0m!!#`'!!4!JJ!FIm2cH(qNkhJiS!&V1-!!!8J!*8Q!33!8J2X\r#&#`(!'4"JJ!`J4X#&#`)!'C!JJ!FIf2EH%J!)@9J!!!!I'-(G#`$!!"!JJ!-1'!\r!#%J!!%#"1`%!J8%!F(`*8!""JJ!-1'!!#NJ!!#JiH`%%Ii6MH$LJ!2p)!#AYJ%%\r!&)&k!!`jD`!"NAS!$$KJ!!#!!3"B1#%!8(`)!kDl3IrS6S!!)!#3"L""J!B!N!3\r"9!!4,Q0MAh0PG&p`FQPZBfP`B@`!I!J#TT2Krrb6`IriN!!"!!L8)Ir!I*iMH(b\rr+hJS(J!!3))!$$KJ!!T)!!"`J(i#&#`$!'C!JJ!NIm2cH%J!)*PJ!!!!I'-(G#`\r$!!"!JJ!-1'!!#%J!!%3S(`!!3B)!1$KJ!2p)!!YYB!!!!*!!I`!!J*m!!#J%!!"\r!JJ!-1'!!"NJ!!"L!I`!!1*i""%J!*,'!33!81'!!!)!"!%Ji)3"!I!J$TS2Krrb\r$`Iri6S!!)!#3"L""J!)!N!@`!"%ZBf0ICf9dAh"bD@jMDA"KE!"m#!+QNq(rr*2\r"rrL3!!%!#*3Krm"mRb0iI,iVH#JI!!"!JJ!-1'!!#NJ!!%b!I`)8,!-!CN##!#4\rrirYi5!!Ia@!!!!"mB`Gd,!-!!%##!!`iB!!)5!!!)#JH!!"!JJ!-1'!!"NJ!!"#\r!R`%!N!#H!!!iB!!!J!%!5$JK!%"m#!1QJq(rr)2"rrK1J!!J!*!')%'!!J#3"B`\r!&#jMBepRCA4IBh*PC&pfCA*cD@pZ!!"m#!+QNq(rr*2"rrL3!!%!#*3Krm"mRb0\riI,iVH#JI!!"!JJ!-1'!!#NJ!!&b!I`)8,!-!CN##!#4rirYi5!!I%@!!!!"mB`G\rd,!-!!%##!!`iB!!)5!!!-#JH!!""JJ!N1'!!rdJ!#H9J!!!!N!"q!!#!IJ!!Iq6\rlH%J!)cf!33!81'!!!)!"!%Ji)3"!I!J$TS2Krrb$`Iri6S!!)!#3"L""J!)!N!@\rF!!`ZBf0ICf9dAfjKE@8!!(`)!UD6iIrmNm(rq*1Krr53!!%!#*3Krl"mI4YiI*i\rMH(br+hJS(J!!3B)!&#JI!!""JJ!-+"d!!%##!!`iB!!+5!!!S)"r!!!S!`!!3))\r!0$KJ!!K)!!NjB!!!!*!!I`!!J*m!!#J%!!"!JJ!-1'!!"NJ!!(#![3!!J0m!!*!\r!TJ!!J2m!!)$R!!!S"`!!3))!+)"r!!")!!PeB!!!!$N!!!#4(`!!15!!!*%q!!!\riB!!$5!!!-)&I!!#!DJ!!Im6cH%J!'E&J!!!!JAm!!)&V!!#"D`)JJCm!!*&X!!!\riB!!!J!%!@$JK!&"m#!1QJq(rr)2"rrL$SIrd6S!!)!#3"L""J!-!N!Am!"%ZBf0\rIFf9aAfCPG'0SAdj$F`"m#!+QNq(rr*2"rrL6SIrdNi(rm*!!!3!)P#(rX*!!B3"\rSI*iMH(bp+hKmhc0i+"i!!%'#!"JS(`!!3B)!%)"K!'JS!`!!3))!$$KJ!!T)!!)\r%+"d!!%##!!`iB!!'5!!"p)#H!K3X"!"Q3))!*(r$mhK)!"d"B!!!!(aM"h3X!`!\r!3))!$$KJ!!K)!!()J,m!!#J&!!"!JJ")1'!!#%J!"p&J!!!!N!"r!!#!h`!!+!B\r!!%##!!`iB!!'5!!"Q$MJ!!#"(`!!N!$S!!4)!!!8J6m!!)&*!!3j5J!"N8N!")&\rr!!#"D`!%UCi#"(`,B!"!J!!NJ(i##)#I!!#!K!!%9)331RaM)#k!B`!!,!-!Bd'\r#rm#![`!!J+8!"+MH!J4m"6!!3B!!+)"r!!")!!I"B!!!!$MJ!!#3!2d!!$N!!!#\r4(`!!1'!!!dJ!!3b"2J))J9m!!)&+!!495K!kI5P3,S1*!!!X(!!"3))!K$KJ!!K\r)!!F"B!!!!*!!I3!!JAd!!#J,!!"!JJ!-1'!!"NJ!!-JiB"f!5!!'h@!!!!#"R3!\r!N!"X!!5!I3!!J'-!"#J$!!"!JJ!-1'!!"NJ!!*b!R3!!J'3!")#q!JL!h`!!J-B\r!"&6'%$TmT6!ZJ)8!"$LJ(B")!#!YJ%%!&%J!!&JX(!!#3))!3)$q!JL"(`!!J3J\r!"&8)%$Tmjd!ZJ1F!"*!!i3!m15!!!T%K!$L!B3!iJ)%!2(qPkhK)!!mKB!!!!%J\r!!"3j3!!!N9d!!$KJ!"")!!!BJAm!!)',!!3jM!!"NBX!"$KJ!!#!!3"B1#%!8(`\r)!kD$iIrmJm(rq)1Krr5$JIr`6S!!)!#3"L""J!3!N!3#F!!6,Q0MAh0PF9pQCA4\rMD&pMFQ9NF`!!!(`)!UD6iIrmNm(rq*1Krr56JIr`N!!"!!L8)Iq`I(`EH(bG)hJ\rli!!!1m!!!#JF!!"!JJ!-1'!!#NJ!!1JS(3!!3))!$$KJ!!C)!!$BJ*`!#$L%!!&\r8Ja!k5!!HdB""!"53!(d!!)#p!!!S"3!!3))!$$KJ!!C)!!#XJp`!!%J!!)JiB!)\r%5!!HTB""!"5!h3!!9qF31RaQ15k"(3!!9qN31Rd)5#iS#!!!3))!$$KJ!!C)!!"\r`J9d!!&IV%$TmDPJZIm6cH%J!(Rf!33!8JCd!!&IN%$TpM#!Z1'`!rcLH!34)!"j\rKJ%%!&)#q!3#!h3!!9qF31Rc'1#k3!+B#!)2H!L!lr`!"+"i!!%##rhJj!!!!J6d\r!!&IU%$Tp#9%Z1'!!!)!"!&Ji)3"3I!J$TS2Krrb$`IriJk(rp)1"rr"1J!!J!*!\r')%'!"!#3"!&!!!mZBf0ICf9dAdj$AfPZCQm!!!"m#!+QNq(rr*!!!3!)P#(r`(b\rI)hJS(`!!3))!$$KJ!!C)!!!8Iq2lH%J!"-9J!!!!1'!!!)!"!%Ji)3"!I!J$TS2\rKrra1J!!J!*!')%'!!3#3"8J!%LjMBepQFQ9PAh"bD@jMDA"KE(`)!UD6iIrmN!!\r"!!L8)Ir!I*mMH#JI!!"!JJ!-1'!!"NJ!!"4rirYi5!!%@@!!!!!iB!!!J!%!5$J\rK!%"m#!1QJq(rr%k!!#!!N!BJ3B!"!*!&5!!0,Q0MAfCbC@9IEQ&YC3"m#!+QNq(\rrr*!!!3!)P#(r`(bI)hJS(`!!3))!$$KJ!!T)!!!SJ(m!!%J!'EeJ!!!!J(m!!%J\r!!q9J!!!!1'!!!*!!I`!!1'!!!)!"!%Ji)3"!I!J$TS2Krra1J!!J!*!')%'!!3#\r3"9`!$LjMBepQFQ9PAf0bC@4cI!J#TT2Krrb6`IriN!!"!!L8)Ir!I*iMH#JH!!"\r!JJ!-1'!!#NJ!!&3li!!!5!!!()#H!!"Aj4!kI'3S,NJ!'j'!33!81rm!!B$H!!"\rAja!kI-Bi,LJ'!!"!J[rBJ(i!!%J!'ff!33!813!!!*%H!!!l`!!!1'!!!)!"!%J\ri)3"!I!J$TS2Krrb$`Iri6S!!)!#3"L""J!)!N!@3!!!3,Q0MAfCbC@9I6N0ID@j\rQE`!!I!J#TT2Krrb6`IriN!!"!!L8)Iq`I*mMH*!!S3"`+"m!!%##!!`iB!!-5!!\r"1$KK!$K)!"UjJ%%!&(aq'hL!I`)8,!-!C%'#!"`iB3!i1*m#'$LK!%")!"UYJ%%\r!&(aq'hL!J3"`,!3!!N'#!#a!J!!3,!3!!8#!!"4)!!$F,!3!"%#!!04)!!"-1+!\r!C*!![`)85!!!c)$I!K3X"J"N3))!)$MJ!'@3!2m#&)%"!$L")3!mN4m#'*%r!Ka\r)!!#NJ9m#&#`+!'C!JJ#B1'!!#%J!!*5"I`)8,!X!C%##!#!jJ!"QNCm#&)"K!$L\r!J3!mN!"r!KL3!*m#(%J!!'L![`)8,!8!CN##!"L)`3"!+!B!!%##!!`iB!!)5!!\r!6)$r!K3X"`"P3))!2)N"!%!S#!!!3B)!)$NJ!'D42`)8J8%!1)&K!$b4A`)BNAm\r#(%J!!"3iB!!)5!!!%$KJ!!a)!!!)1'!!!)!"!&Ji)3"3I!J$TS2Krrb$`Iri6S!\r!)!#3"L""J!)!N!3"H!!3,Q0MAfa[BfYIFQ9aG@9cG!!!I!J#TT2Krrb3!!%!#*3\rKrm#3!'%!@$[J!!#!B3"B5!!BI@!!!!"mIaYiIq-(0#`$!!""JJ!-Iq2lH%J!!"3\riJ!!!J+)!+*!!K3!!Iq2lH)!"!%Ji)3"!I!J$TS2Krra1J!!J!*!')%'!!3#3"@!\r!%bj*EQPdD@&XDATP3f&MD'9-D@)!!!"m#!+QN!!"!!L8)Ir!5!!BA@!!!!#!!3"\r)1#%!3(`)!kC1J!!J!*!')%'!!*!'*!!5,P4PFQeTEQ&dC80KBfKP6'PLI!J#TT2\rKrrb6`IriN!!"!!L8)Ir!I(iEH(r$mhK)!"NjJ%%!&(ar'hJS(`!!3B)!&(rMqhK\rra20i5!!C6B""!"4rirYiJ!%!5$JK!%"m#!1QJq(rr)2"rrK1J!!J!*!')%'!!J#\r3"9`!#bj1CAG6B@CP8(4b!!!!I!J#TVp"rqL3!!%!#*3Krl"mHaYi1i)"dM[#!F8\rlSJ'hJq)!,(pMfhK)!"KTJ%%!&(ak'hJS'`!!3))!K)"r!!!X!`!"3))!)(qMkhK\rra20i1+!!*cM!!!")!"IaJ%%!&%J!!&b!R`!!,!3!!N##!"4rSqYi5!!AlB""!"4\r)!!"!J,m!!#`&!!0!JJ!35!!AlB""!"4)!!!SJ0m!!#`'!!4!JJ!FIk2VH(r%mhJ\riS!!R1-!!!8J!&j@!33!8,"S!!%'"!)5!r`!!,!F!!8##!#"rJq0iIm6cH$LJ!#J\ri`!!!5!!ADB""!"4)!!"FJ4m!!#`)!!*!JJ!8Ii2MH%J!&f@!33!85!!!3)%r!!!\rX#3!$3))!%%J!&f@!33!85!!!+)&I!!!X#J!%3))!((q$ihKra20i1+!!+$M!!!&\r)!"F0J%%!&(pMfhJiJ!!!IdA6H%J!&eQ!33!8If2EH$L!!!"r4G0i5!!A4B""!"4\rrBpYiId66H%J!&df!33!8If2EH%J!&V'!33!8J!%!@$JK!&"m#!1QZd(rk%k!!#!\r!N!BJ3B!'!*!%!C`!$bj%DA0`Eh0P8f&QC9"dFJ!!!(`)!UD6iIrmNm(rq*!!!3!\r)P#(r`(aq'hKr`r0i5!!AAB""!"4mIaYi+"m!!%'#!"4rirYiIm6cH%J!&a'!33!\r8Iq2lH)!"!%Ji)3"!I!J$TS2Krrb$`Iri6S!!)!#3"L""J!)!N!9F!!iZ6Q9h8f&\rQC9"dFP0jFh`)!UD6iIrmNm(rq*1Krr56JIr`N!!"!!L8)Iq`I(`EH$[#!GmlSJ(\r&Jq)!,#JF!!"!JJ#%J(m!!#`$!!&!JJ!JIm2cH(qNkhJiS!"31-!!!%J!&Ef!33!\r85!!!A)#I!!!X"!!#3))!&(r$mhK)!"@jJ%%!&%J!!%#![`!!,!8!!d##!"")!"@\rjJ%%!&%J!!#L!h`!!,!B!"%##!"ar`r0iIk6VH$LJ!&!i`!!"5!!9BB""!"3ii!!\r!X2`#"$N!!!Ua(!)'1'!!+%[rrVf3!(`##)"m!JL!!3"B1#%!8(`)!kD$iIrmJm(\rrq)1Krr5$JIr`6S!!)!#3"L""J!3!N!Ad!!iZEQ9h3h*PC%*eCQCPFR`)!UD6iIr\rmNm(rq*1Krr56JIr`N!!"!!L8)Iq`I(`EH*!!J3"XN!#K!(#3!-%!G$[#!HSlSJ(\r&Jq)!,#JF!!"!JJ#%J(m!!#`$!!&!JJ!JIm2cH(qNkhJiS!"H1-!!!%J!&*f!33!\r85!!!A)#I!!!X"!!#3))!&(r$mhK)!"5CJ%%!&%J!!%#![`!!,!8!!d##!"")!"5\rCJ%%!&%J!!#L!h`!!,!B!"%##!"ar`r0iIk6VH$LJ!&ii`!!"5!!83B""!"5!i3"\rXN!$m!!#"!3"`N4`!")%K!(3S#3!!3))!&$P!!!#4A!!)1'!!!%J!!$b!B3"`5rr\rpJC!!I!!)JA`!##J,!!"!JJ!-1'!!"NJ!!"b!I!!)J)%!G)#K!(")!"5jJ%%!&$K\rJ!!#!!3"B1#%!8(`)!kD$iIrmJm(rq)1Krr5$JIr`6S!!)!#3"L""J!3!N!3"4!!\r-,Q0[F(P%BA4K6f*U!!"m#!+Q[U(re*!!!3!)P#(rN!"mGaYiI*XMH$Z#!L)lSJ)\r61b)#!cY#!IBl`J(&Jq)!,$UJ!!!l!!!!1X!!!#JE!!"!JJ#%J(m!!#`$!!&!JJ!\rJId26H(r%mhJiS!"d1-!!!%J!%c@!33!85!!!A)#I!!!X"!!#3))!&(p$dhK)!"-\raJ%%!&%J!!%#![`!!,!8!!d##!"")!"-aJ%%!&%J!!#L!h`!!,!B!"%##!"ar3p0\riIm6cH$LJ!(3i`!!"5!!5fB""!"4qq,Yi+"J!!%##!"3ii!!!N!$l!!")!!+B1V8\r!!B%B!!!l'!!%+!J!!%##rr!j03!"95-31N[rr"@3!(X!!(af'hJS&J!!3))!K)&\rI!!!X#J!"3))!)(mMbhKra20i1+!!I$M!!!")!"*YJ%%!&%J!!&b"I`!!,!X!!N#\r#!"4r)mYi5!!5DB""!"4)!!"!JCm!!#`-!!0!JJ!35!!5DB""!"4)!!!SJ(m!!#`\r$!!4!JJ!FIb2,H(r%mhJiS!"m1-!!!8J!%K'!33!8+"B!!%'#!H"qq,Yi5!!"[$K\rJ!!a,rrYYJ*X!!*!!C!!!J,X!!)#P!!!S"3!!3))!K)$I!!!X"J!"3))!)(qMkhK\rra20i1+!!JcM!!!")!"'pJ%%!&%J!!&b!r`!!,!F!!N##!"4rSqYi5!!4ZB""!"4\r)!!"!J4m!!#`)!!0!JJ!35!!4ZB""!"4)!!!SJ6m!!#`*!!4!JJ!FIk2VH(r%mhJ\riS!#$1-!!!8J!%@'!33!8J9X!!)&+!!!S#J!!3B)"+)&l!!#!D`!!J*F!!$LJ!!a\r)!")4J%%!&)'E!!#"M!!!J'`!"%[rqTf!Q`!!J)3!!*!!C!!)J,X!!)#P!!#!T3!\r)+!8!!%##!)5!h`!!,!B!!8##!#"rJq0iIm6cH$LJ!)Xi`!!!5!!3jB""!"4)!!"\rFJ2m!!#`(!!*!JJ!8Ii2MH%J!%1'!33!85!!!3)%I!!!X#!!$3))!%%J!%1'!33!\r85!!!+)%r!!!X#3!%3))!((q$ihKra20i1+!!LcM!!!&)!"#*J%%!&)&E!!#"5J!\r!J8S!##J+!!""JJ"-JAX!!)&V!!#!D`!)JCF!!)#-!!L!e`!!J+B!"%J!%5Q!33!\r81hX!"$XB!!5!q!!!+!F!!%##rN!j!!!!9UN31Rd@55k5f`!!J!%!H$JK!("m#!1\rQZU(re%k!!#!!N!BJ3B!,!*!%!i3!$LjMEh"j4'&dB8&bFQ&jI!J#TT2Krrb6`Ir\riNk(rp*!!!3!)P#(rX*!!B3"SN!#"!'am[5Yi1q!!!$[!!!#$`3"X+"d!!%##!!`\riB!!'5!!"3$KJ!!K,rrNPN!"p!!#!I3!!+!-!!%##!!`iB!!'5!!")$KJ!%a,rrN\r&I(mEH#JI!!"!JJ!-1'!!"NJ!!33iB!6L5rrikC!!I`!!J*m!!#J%!!"!JJ!-1'!\r!"NJ!!13iB!6L5rribC!!I`!%J,m!"#J&!!"!JJ!-1'!!"NJ!!-5!I`!!J*i!!$L\rJ"0p)!"!aJ%%!&)"r!!5!RJ!%1+!%hdJ!%"f!33!81(m!#)#H!!L![J!-J0i!%%[\rrqJ@!hJ!8N!$I!"5!rJ!BN!$r!"L"(J!FN4m!()%q!##42`!JJ9i!**&I!#5"IJ!\rSNAm!+)"q!#`iR`!X5rrl,6Kr!$#!RJ!`J,i!0)$H!$K,rrQe1(m!2)#H!$b![J"\r!J0i!4%[rqD%jJ!!!NCm!5$KJ!!+!R3!!N!"N!!#![3!!Nq8!"$KJ!!#!!3"B1#%\r!8(`)!kD$iIrmJm(rq)1Krr41J!!J!*!')%'!!`#3"!'B!!XZBfp`H9Be3h*PC!!\r!!(`)!UD6iIrmNm(rq*!!!3!)P#(r`*!!B3"BN!#"!&am[LYi1q!!!#JH!!"!JJ!\r-1'!!"NJ!!'`iB!!)5rrhHC!!IJ!!J(i!!#J$!!"!JJ!-1'!!"NJ!!%`iJ!!"J,i\r!!*!!K3!!1'!GJ%[rpdemIaYi+"m!!%##!!`iB!!'5!!!*(rMqhL!J3"F1+!GJ%J\r!$SQ!33!8J0i!!*2Q!!3iB!!!J!%!5$JK!%"m#!1QJq(rr)2"rrK1J!!J!*!')%'\r!!J#3"E3!#bjMEh"j9M4$FQ9N!!!!I!J#TT2Krrb6`IriN!!"!!L8)Iq`I(mEH*!\r!J3"XN!#K!(!l`!!!1'!!!*!!B3!i+"m!!%##!!`iB!!+5!!"!)#"!'`X"!!"3B)\r!')#K!'`X"3!#3B)!$$KJ!"")!!$JU0m#"$M'!!'`h`)%U2m#"(cR"c5T(`)'I!G\r!!%##!&bT2`)'95N)2,%r!JDTA`)'98-31N[rpNemIKYi+"i!!%##!!`iB!!'5!!\r!P(r$mhL!R`))UAm#"ReV$R"pD`'89@831NJ!$Af!33!8J(m##%[rp&'6h`))JB%\r!E#`-!!&!JJ!BJ'%!E)#"!(!iS3!i5rrq38J!!#b!B3"X,!-!!N##!"L!B3"XJ)%\r!F$LK!$K,rraT5!!!$$KJ!"")!!!JJ)%!1)#r!JLSh`)%1-Erre6'%$TmK6%Z1'!\r!!)!"!&Ji)3"3I!J$TS2Krrb$`Iri6S!!)!#3"L""J!)!N!3"8!!4,Q0bC@4#G@C\rQCA**ER0PFR3!I!J#TT2Krrb6`IriNk(rp*1"rr#3!!%!#*3Krl"mIKYiN!#"!'b\r3!+%!F$Z!!!!S(J!!3))!$$KJ!!T)!!$31k!!!%J!!,L!IJ))9k331RaM)#k!J`!\r%J'-!!)#K!'b!`3"`5!!#,@!!!!"mB`Gd,!-!!%'#!)5![J))9kB31Rq&-#jrJq0\ri5!!)m@!!!!"rJq0i5rrc'AqrkhK)!!!NJ2i##$NI!!&9#"!kI1G!,S%q!JKAkK!\rkI1P4,M[r!!'TIJ)%1@[rrh`I@!""J2r81B!!!)"q!JLSRJ)%1)6rre5%%$TpJb%\rZU,i#"$LPrrq`[J)%5!!!&$Zp!!'ShJ)%I"d`!%'!rd3iB!!!J!%!@$JK!&"m#!1\rQJq(rr)2"rrL$SIrdJi(rm%k!!#!!N!BJ3B!%!*!%!5J!%5jMFQ9N3R9QCQ9b8Q9\rYEhCP!(`)!UDr3IrSN!!"!!L8)IqJI(SEH(bF)hJl`J)j1k)"aB2L!#`iB!!!N!"\rK!$JS(!!!3))!K)#I!!!X"!!"3))!)(r$mhKrT1Yi1+!"5$M!!!")!!T9J%%!&%J\r!!&b![`!!,!8!!N##!"4r`r0i5!!+8B""!"4)!!"!J0m!!#`'!!0!JJ!35!!+8B"\r"!"4)!!!SJ2m!!#`(!!4!JJ!FIm2cH(qNkhJiS!&)1-!!!8J!#IQ!33!8+"`!!%#\r#!!`iB!!-5!!!5$YJ!!")!!!SJ4`##&GT%$Tp#%JZN3%!1(p$dhJiJ3!i5rrYB@!\r!!!!lH`!"U9`#"(`E8!""J2r8J(`##%[rm9diB!!!J!%!D$JK!'"m#!1QZd(rk%k\r!!#!!N!BJ3B!'!*!%!4`!%LjNDA0`Eh0P3h*PC%*eCQCPFR`)!UD6iIrmNm(rq*1\rKrr56JIr`N!!"!!L8)Iq`N!"K!'L3!)%!E*!!S3"`N!$"!(5!B3"X+!-!!%'#!"#\r!J3"d+!3!!%##!!`iB!!!5!!"!)#K!'L!`3"`I!8`!%'#!!`iB!!!5!!!k)$K!'J\rX"`!"3))!G)2K!'b$`3"d1(m!!6LH!!&)!!S&J%%!&#`$!!"!JJ"-1(m%icLH"10\r)!!RYJ%%!&#`$!!"!JJ!d1(m6L6LH%iP)!!R9J%%!&#`$!!"!JJ!FJ4mBI)%q'(a\rm#%J!3))!$$KJ!!&)!!"d1'!!!%J!!'b"33"S,!S!!N##!&b$S3"XJi%!G)"p!!#\r!R!!!5!!*LB""!"3X!`!!3))!0)"p!!5!R!!%5!!*FB""!"3X!`!!3))!()&p!"L\r"R!!BI!YJ!%##!!`iB!!"5!!!%$KJ!!")!!!)1'!!!)!"!&Ji)3"3I!J$TS2Krrb\r$`IriJk(rp)1"rr"1J!!J!*!')%'!"!#3"!&S!!JZBh*PC'0YF!!!I!J#TT2Krrb\r6`IriNk(rp*1"rr#3!!%!#*3Krl"mI4YiI*`MH$[!!!!S(!!!3))!$$KJ!!C)!!)\r81'!#+%[rlZ'3!(`!!)"m!!!S!`!!3))!$$KJ!!C)!!(dJp`!!(r$mhKrT1Yi5!!\r)*B""!"5!R3%!N!#H!3!iIJ%%1*d""%J!#!f!33!8U,d#",#q!J5Sh3)'X0i#"MM\rJ!!'BrJ)3U4i#"P8$%$T,rqjjN!"q!JL"2J))+!N!!%##!!`iB!!'5!!"M$[J!!"\r)!!&SJ9d##&IV%$Tp5PJZJ8S!!#`+!!&!JJ#`1'!!#%[rlMQ"RJ))9q331RaX)5k\r![J))9qB31RbP-#iS"3!!3))!$$KJ!!C)!!%m11!!!B%H!JKAk4!kI3K),T!!k!!\r!1'!GJ%[rlI@"AJ))9qX31Re+@#k3!'S!")'H!JKAia!kIB`B,S'-!!3S$!!!3))\r!$$KJ!!C)!!$`J*i##&IP%$TmK#JZJ'3!")$G!JKAja!kI-Bi,S#'!!3iS"f!5!!\r(1B""!"4)!!#JJ4d##&IT%$Tp#%JZJ3J!!#`)!!*!JJ!XJ9d##&IV%$Tp5PJZJ'S\r!!)#+!!5"RJ))9qB31RbX-K4,rrBY5!!!B)$p!JKAk"!kI1G!,S$R!!!X"`"M3))\r!5$KJ!!K,rqdeJ6i##&IU%$TmD9%ZJAi##&IX%$TpDf!Z+!X!!%##!!`iB!!'5!!\r!1$KJ!'1!RJ))9q831Rb%+#k3!'3!!$[r!!'ShJ)%I"m`!%'!rT3ii!!!N!$q!L5\r3!2i#)$KJ!!#!!3"B1#%!8(`)!kD$iIrmJm(rq)1Krr5$JIr`6S!!)!#3"L""J!3\r!N!3#D!!',Q4eF%j$I!J#TT2Krrb6`IriN!!"!!L8)Ir!I(iEH(rImhJS(`!!3B)\r!,%J!!"5!R`!!J'3!#%[rl1Nlr`!%J,m!!#J&!!"!J[rSIm2cH%[rl0'!!3")1#%\r!3(`)!kD$iIrmJm(rq%k!!#!!N!BJ3B!#!*!&C!!4,Q4TFh"[Ff9%BA4K3A*bBAN\r!I!J#TT2Krrb6`IriNk(rp*1"rr#3!!%!#*3Krl"mI"Yi1m)#4$ZL!F@$iJ!X+"`\r!!%##!*L!I`!!,!-!!8##!#"r`r0iIk6VH$LJ!F)i`!!!5!!%LB""!"4)!!"`J*m\r!!#`%!!*!JJ!8Im2cH%J!")@!33!85!!!9)#r!!!X"3!$3))!%%J!")@!33!85!!\r!2)$I!!!X"J!%3))!-(r$mhKrT1Yi1+!"`MM!!!&)!!3YJ%%!&%J!!"4rJq0iIi6\rMH%[rfIPJ!!!!J2`!!#J(!!"!J[rS1'!!!)!"!&Ji)3"3I!J$TS2Krrb$`IriJk(\rrp)1"rr"1J!!J!*!')%'!"!#3"IJ!#bjQFQ9P6N0-DA0d!!!!I!J#TVpKrqb3!!%\r!#*3Krk"mI"Yi1m)"hcZL!F@$iJ!X+"`!!%##!)5!I`!!,!-!!8##!#"r`r0iIk6\rVH$LJ!G)i`!!!5!!$IB""!"4)!!"FJ*m!!#`%!!*!JJ!8Im2cH%J!!hQ!33!85!!\r!3)#r!!!X"3!$3))!%%J!!hQ!33!85!!!+)$I!!!X"J!%3))!((r$mhKrT1Yi1+!\r"dMM!!!&)!!-KJ%%!&$KK!$K)!!,0J%%!&(al'hKrC`Fd,!F!!%'#!!`iB!!!5!!\r!5)%F!K3X#!"N3B)!-$KK!$JiR!)B1+%!3%J!!Uf!33!8I(XEH(pT"c3X#3!!3B)\r!&$KJ!!")!!!318!!!*P"!%#)B3"!J!%!D$JK!'"m#!1QZf(rl%k!!#!!N!BJ3B!\r&!*!%!53!#bjTFda[BfY2GA*c!!!!I!J#TVpKrqb3!!%!#*3Krl"mHaYi1m)#9cZ\rL!F@$iJ!X+"X!!%##!)5!I`!!,!-!!8##!#"r`r0iIk6VH$LJ!HFi`!!!5!!#1B"\r"!"4)!!"FJ*m!!#`%!!*!JJ!8Im2cH%J!!M@!33!85!!!3)#r!!!X"3!$3))!%%J\r!!M@!33!85!!!+)$I!!!X"J!%3))!((r$mhKrT1Yi1+!"jcM!!!&)!!(GJ%%!&)$\rl!!!X"`!#3))!I)1E!!5!I!!!5rrTHB"m!!4,rqPaJ4`!%#J)!!""JJ!-J(`!%%[\rrk9f"2!!i+!N!!%'#!!b!I!!i5rrT5B&F!%3S#J!!3B)!$)"m!%4,rqNeJA`!5#J\r,!!""JJ!-J(`!5%[rr!Q"R!!X+!`!!%'#!!b!I!!X5rrlpB"l!!4,rqN&1'!!!)!\r"!&Ji)3"3I!J$TVYKrqa1J!!J!*!')%'!"3#3"!&-!"FZBf0ICR*PC9pMFQ9NAfP\rZG'9bEQ&XF`!!!(a$%hK1J!!JI!J#TT!!!3!)P#(r`%[rrqemD4YiJ')!D)##!'3\riSJ!!1-)#CB$L!&L"!J"85!!!@B""!"5!JJ#XN!"N!!",rp"TB!!!!$KJ!!#!!3"\r)1#%!3(`)!kC1J!!JI!J#TT!!!3!)P#(r`)"L!+b!B`!!5!!!-B""!"5!!3")1#%\r!3(`)!kC1J!!JJB)!1*!!33!8J!`!!)"-!!4m#31Q6S!%))'#!$53!%%!&)!-!!#\r!6!!%I!N$TNk!"##"JJ!JN!""!"5!$!!!J%`!"(`*!kC1J!3JJB)!(*!!33!8J!`\r!!)"-!!4m#31Q6S!%))'#!"#3!%%!&)!-!!#!6!!%I!N$TNk!"##"JJ!`N!""!"5\r!$!!!J%`!"(`*!kC1J!3JJB)!&*!!33!8J!`!!)"-!!4m#31Q6S!%))'#!!#3!%%\r!&)!-!!#!6!!%I!N$TNk!"##"JJ!BN!""!"5!$!!!J%`!"(`*!kC1J!3JJB)!8*!\r!33!8J!`!!)"-!!4m#31Q6S!%))'#!!L3!%%!&)!-!!#!6!!%I!N$TNk!"##"JJ!\rNN!""!"5!$!!!J%`!"(`*!kC1J!3JJB)!5*!!33!8J!`!!)"-!!4m#31Q6S!%))'\r#!!b3!%%!&)!-!!#!6!!%I!N$TNk!"##"JJ"!N!""!"5!$!!!J%`!"(`*!kC1J!3\rJJB)!"*!!33!8J!`!!)"-!!4m#31Q6S!%))'#!%53!%%!&)!-!!#!6!!%I!N$TNk\r!"##"JJ!mN!""!"5!$!!!J%`!"(`*!kC1J!3JJB)!6*!!33!8J!`!!)"-!!4m#31\rQ6S!%)!!!,eb!!!"B!*!',l5!!!!X!*!&9L)a`!)L-DJ#)J*PKJ)"-F!L!D@#!K%\r"P3'-!Am#9`*%!MN#)J)6!J-"pJ(U!Gm"dJ(&!EF!Y!&`"#)9+)B#&44d%rJ6N!!\r6*"(!$bJ1#!e-$*J,a!T-#A!)H!JJ"MJ%l!0`!F!"0!!F&d`L&X3%,Ne*9#"*,e-\rJ6@&M4'9f!5#"CJ`K+'jKE@8J)6dJ-#N)3d0KBfKP,Q-2)5JUD'&ZC'aP)#%p)$!\rT%5%SF(*TEQ0TF'&X)#%p)$!T$5%SFf&QC9!J)6dJ-#N-3d0KBfKP9A4TE#jM$#%\rSFfPkC5!q)$"-+3SK+'jM)#%p)$!T#b%SEf*U)#%p)$!T$#%SC'9cG#!K25!`+3p\rbCA4NCA0d)$dp)%j96%`1+LTNCA0d)$dp)%j96%`@+#SUC'9cG#NY2Q4KG'%J26d\rJ6P9-6!TZBb!p25"198a-%L%SBfjdFQa#E'pMDb!K25!`+3dK+'0bC@4c)#%p)$!\rT1k3!!!%!!!!"C!!!!'3!!!!bC@*eCcSf1%XJ3fpNC8GPEJ"0593J8R9ZG'PYC9"\r33b"%6%`ZC'9LG@Fk0MK,)%4TFf&cFf9YBQaPFJ"0593J8R9ZG'PYC9"33b"%6%`\rZC'9LG@Fk0MK,)%GXEf*KE#"2F(4TE@PkCA)!68P8)&*eER4TE@938%-J4%a-,Q4\rPBR9R1MBi5b"-D@jVCA)!68P8)&*eER4TE@938%-J4%a-,Q4PBR9R1MBi5b"3FQp\rUC@0d!%e*9#"5G@jdD@eP8&"$)%4-6#jNC@*eCcT$,d-V+b"$Efe`D@aPFJ"0593\rJ8R9ZG'PYC9"33b"%6%`ZC'9L!!!!B!#3#`%!N"-"F(G`B`#3%`%!N"&!&%e*9&q\rP3d0KBfKP6'PL,Q4PBR9R!!!!!3!!!!&N!!!!C!!!!$)&9MR30#B!!!!F!$)!!'0\rQFQF!!!!+!!$rr`#3"!9EF&b1RJ:\r
\ No newline at end of file
diff --git a/src/mac/libraries/CCache API/include/CCache.h b/src/mac/libraries/CCache API/include/CCache.h
deleted file mode 100644 (file)
index f758c14..0000000
+++ /dev/null
@@ -1,350 +0,0 @@
-/*************************************************************
- *
- *     Header file for Credential Cache API for MacOS
- *
- *     -as defined by the document found at http://www.umich.edu/~sgr/v4Cache/
- *     -definitions borrowed from a windows implementation found at
- *      /afs/umich.edu/user/s/g/sgr/Public/TsoCacheDll shell/
- *
- *     Revision 1: Frank Dabek, 6/4/98
- *                             added missing calls from revision four of the API
- *                             deleted some WIN specific Information
- *                             added some misssing definitions
- *                             renamed to CCache.h
- **************************************************************/
-#ifndef _CCache_h_
-#define _CCache_h_
-
-#if defined(__CFM68K__) && !defined(__USING_STATIC_LIBS__)
-#      pragma import on
-#endif
-
-#include "Processes.h"
-/*
-** The Official Error Codes
-*/
-#define        CC_NOERROR      0
-#define CC_BADNAME     1
-#define CC_NOTFOUND    2
-#define CC_END         3
-#define CC_IO          4
-#define CC_WRITE       5
-#define CC_NOMEM       6
-#define CC_FORMAT      7
-#define CC_LOCKED      8
-#define CC_BAD_API_VERSION     9
-#define CC_NO_EXIST    10
-#define CC_NOT_SUPP    11
-#define CC_BAD_PARM 12
-#define CC_ERR_CACHE_ATTACH 13
-#define CC_ERR_CACHE_RELEASE 14
-#define CC_ERR_CACHE_FULL  15
-#define CC_ERR_CRED_VERSION  16
-
-#define CRED_TYPE_IN_UNION
-
-typedef int cc_int32;
-typedef cc_int32 cc_time_t;
-typedef cc_int32 cc_nc_flags;
-//typedef short cc_cred_vers;
-       
-enum StringToKey_Type { STK_AFS = 0, STK_DES = 1};
-
-enum {  MAX_V4_CRED_LEN = 1250, 
-               KRB_PRINCIPAL_SZ = 1250, 
-               KRB_INSTANCE_SZ = 1250,
-               KRB_REALM_SZ = 1250,
-               KRB_SERVICE_SZ = 1250,
-               ADDR_SZ = 16  };
-
-// V4 Credentials
-typedef struct _V4Credentials {
-       unsigned char   kversion;
-    char                       principal[KRB_PRINCIPAL_SZ];
-    char                       principal_instance[KRB_INSTANCE_SZ];
-    char                       service[KRB_SERVICE_SZ];
-    char                       service_instance[KRB_INSTANCE_SZ];
-    char                       realm[KRB_REALM_SZ];
-    unsigned char      session_key[8];
-    cc_int32           kvno;
-    enum StringToKey_Type      str_to_key;
-    long                       issue_date;  
-    cc_int32           lifetime;          
-    char                       address[ADDR_SZ];       // IP Address of local host
-    cc_int32           ticket_sz;    
-    unsigned char      ticket[MAX_V4_CRED_LEN];
-    unsigned long      oops;
-} V4Cred_type;
-
-// version indentfiers
-// extend to authentication schemes beyond Kerberos?
-enum cc_cred_vers {  
-    CC_CRED_VUNKNOWN = 0,       // For validation
-    CC_CRED_V4 = 1,
-    CC_CRED_V5 = 2,
-    CC_CRED_VMAX = 3,            // For validation
-    CC_INVALID_RECORD = 99
-};
-
-#define NC_MAX_NAME_LENGTH 255
-typedef struct _infoNC  {
-       char name[NC_MAX_NAME_LENGTH];
-       char principal[NC_MAX_NAME_LENGTH];
-       enum cc_cred_vers vers;
-} infoNC;
-
-
-typedef struct _cc_data {
-       cc_int32                type; // should be one of above
-       cc_int32                length;
-       unsigned char*  data;
-} cc_data;
-
-typedef struct _cc_creds {
-       char*           client;
-       char*           server;
-       cc_data         keyblock;
-       cc_time_t       authtime;
-       cc_time_t       starttime;
-       cc_time_t       endtime;
-       cc_time_t       renew_till;
-       int                     is_skey;
-       cc_int32        ticket_flags;
-       cc_data     **addresses;
-       cc_data         ticket;
-       cc_data         second_ticket; //????
-       cc_data     **authdata;
-} cc_creds;
-
-//union of v4, v5 pointers
-typedef union cred_ptr_union_type {
-    V4Cred_type* pV4Cred;
-    cc_creds*    pV5Cred;
-} cred_ptr_union;
-
-//version 4 and version 5 union data type
-typedef struct cred_union_type {
-#ifdef CRED_TYPE_IN_UNION
-    enum cc_cred_vers cred_type;
-#endif
-    cred_ptr_union cred;
-} cred_union;
-
-#define kInitialCredBufferSize 10
-#define kLocalCopyNCType 1
-#define kMasterRecordNCType 2
-#define kUnlocked 100
-#define kReadLock 101
-#define kWriteLock 102
-typedef struct _ccache_p {
-       char                                    name[NC_MAX_NAME_LENGTH + 1]; 
-       enum cc_cred_vers                       vers;
-       char                                    principal[NC_MAX_NAME_LENGTH + 1];
-       short                                   numCreds;
-       short                                   maxCreds;
-       cred_union**                    creds; //self-growing array of pointers
-       int                                             cc_flags;
-       char                                    typeFlag; //master or local copy
-       long                                    lock;
-       ProcessSerialNumber             lockOwner;
-       struct _ccache_p                *next;
-       struct _ccache_p                *prev;
-} ccache_p;
-
-
-typedef struct _ccache_it {
-       ccache_p *prevNC;
-       int               lastCredOffset;
-} ccache_it;
-
-typedef struct _apiCB {
-       ccache_p* listHead;
-       ccache_p* listTail;
-       int               numNCs;
-       cc_time_t         changeCount;
-} apiCB;
-
-
-// --- Globals -------------
-extern apiCB *gCntrlBlock;
-
-
-/*
-** The official (externally visible) API
-*/
-
-#define CC_API_VER_1   1
-
-// -- Main cache routines ------
-
-/* Initialize the Credentials Cache, return a control structure in cc_ctx,
-       This should be the entry point of the shared library, or called from
-       the entry point */
-int
-cc_initialize(apiCB ** cc_ctx,         // < SL's primary control structure. 
-                                                                       //   returned here, passed everywhere else 
-                         int   api_version,    // > ver supported by caller (use CC_API_VER_1)
-                         int*  api_supported,  // < if ~NULL, returned max ver supported by DLL
-                         char** vendor);               // < if ~NULL, returns read only C string, vendor name */
-
-/* Termination routine */
-int
-cc_shutdown(apiCB** cc_ctx);                   // <> SL's primary control structure. NULL after call. 
-
-
-/* Open a name cache within the ccache designated by name and version? 
-       Returns a control struture pointer to the NC in *handle */
-int
-cc_open(apiCB * cc_ctx,                                // > SL's primary control structure
-               char * name,                            // > name of pre-created cache
-               const enum cc_cred_vers vers,   // > version of credentials held in this NC 
-               int cc_flags,                           // > options
-               ccache_p ** handle);            // < named cache control structure 
-
-/* Close and deallocate memory assoicated with the named cache pointed to by *handle */
-int
-cc_close(apiCB* cc_ctx,                                // > DLL's primary control structure
-                ccache_p** handle);            // <> named cache control structure. NULL after call. 
-
-/* Create a new named cache in the cache cc_ctx.
-Specify the cache by: a name, a principal, a version
-return a pointer to the control structure for the cache via handle */
-int
-cc_create(apiCB* cc_ctx,                       // > DLL's primary control structure
-                 char* name,                           // > name of cache to be [destroyed if exists, then] created
-                 const enum cc_cred_vers vers, // > version of credentials to be held in cache
-                 char* principal,                      // > name of principal associated with named cache
-                 int cc_flags,                         // > options
-                 ccache_p** handle);           // < named cache control structure 
-
-/* Seems remarkably similiar to cc_close ???? */
-int
-cc_destroy(apiCB* cc_ctx,                      // > DLL's primary control structure
-                  ccache_p** handle);          // <> named cache control structure. NULL after call.
-
-/* Get the global last changed time variable for the CCache 
-   Replace this with a change counter instead of an actual time?*/
-int
-cc_get_change_time(apiCB* cc_ctx,        // > DLL's primary control structure
-                                  cc_time_t* time); // < time of last change to named cache
-
-// -- Named Cache routines ---------
-
-/* store the credentials (tickets) in cred in the named cache pointed 
-to by handle.  Maybe the last argument should be more general? */
-int
-cc_store(apiCB* cc_ctx,                                // > DLL's primary control structure
-                const ccache_p* ccache_pointer,                        // > named cache control structure
-                const cred_union cred);                        // > credentials to store in cache named
-
-/* Remove the credentials pointed to by cred from the Named Cache pointed to
-by handle. */
-int
-cc_remove_cred(apiCB* cc_ctx,          // > DLL's primary control structure
-                          ccache_p* ccache_pointer,    // > named cache control structure
-                          const cred_union cred);              // > credentials to remove from named cache
-
-/* set the principal of the NC *ccache_pointer to principal,
-       principal should be a null terminated C string */
-int
-cc_set_principal(apiCB* cc_ctx,                                                // > cs 
-                               const ccache_p* ccache_pointer,         // > NC
-                           const enum cc_cred_vers vers,                       // > version: to check pointer?
-                           const char* principal);                             // > new principal name
-
-/* Get the name of the principal associated with the NC handle */
-int
-cc_get_principal(apiCB* cc_ctx,                // > DLL's primary control structure
-                                ccache_p * ccache_pointer,     // > named cache control structure
-                                char** principal);     // < name of principal associated with named cache
-                                                                       //   Free via cc_free_principal()
-
-/* Get version of credentials stored in the NC pointed to by ccache_pointer */ 
-int
-cc_get_cred_version(apiCB* cc_ctx,                                     // > cs
-                                       const ccache_p* ccache_pointer, // > the named cache
-                                       enum cc_cred_vers* vers);                       // <> the version of credentials in the NC
-
-/* Return the name of the NC specified by ccache_p */
-int
-cc_get_name(apiCB* cc_ctx,                                             // > control struct
-                       const ccache_p* ccache_pointer,         // > NC
-                       char** name);                                           // <> name                                      
-
-
-//  - Search routines ----
-
-/*
-Sequentially open every NC in the CCache. 
-To use (?): initially set handle and itCache to NULL
-after each call set itCache to handle,
-repeated calls will return all currently held NC's
-*/
-int
-cc_seq_fetch_NCs(apiCB* cc_ctx,                        // > DLL's primary control structure
-                                  ccache_p** ccache_pointer,   // <> named cache control structure (close, then open next)
-                              ccache_it** itCache);// <> iterator used by DLL, set to NULL before first call
-                                                                               //    Also NULL for final call if loop ends before CC_END
-
-/* Sequentially fetch every set of credentials in the Named Cache handle
-use similiarly to cc_seq_fetch_NCs */
-int
-cc_seq_fetch_creds(apiCB* cc_ctx,                      // > DLL's primary control structure
-                                  ccache_p* ccache_pointer,            // > named cache control structure
-                              cred_union** creds,                      // < filled in by DLL, free via cc_free_creds()
-                              ccache_it** itCreds);    // <> iterator used by DLL, set to NULL before first call
-                                                                                       //    Also NULL for final call if loop ends before CC_END
-
-/* a wrapper for cc_seq_fetch_NCs.
-       Returns: a null terminated list (array) of pointers to infoNC structs
-       if this works, maybe we should hide that seq call...
-       */
-int
-cc_get_NC_info(apiCB *cc_ctx,          // > control structure
-                        infoNC*** ppNCi);              // <> info about the NC (yes.. three asterisks...)
-
-                               
-// -- Memory recovery ---------
-
-/* just a wrapper for free() ??? */
-int
-cc_free_principal(apiCB* cc_ctx,               // > DLL's primary control structure
-                                 char* principal);// <> principal to be freed, returned as NULL
-                                                                       //   (from cc_get_principal())
-/* another wrapper? */
-int
-cc_free_name(apiCB* cc_ctx,                    // > DLL's primary control structure
-                        char* name);                   // <> name to be freed, returned as NULL
-                                                                       //   (from cc_seq_fetch_cache())
-
-/* free storage associated with cred_union** */
-int
-cc_free_creds(apiCB* cc_ctx,                   // > DLL's primary control structure
-                         cred_union** creds);          // <> creds (from cc_seq_fetch_creds()) to be freed
-                                                                               //    Returned as NULL.
-
-/* Free that nasty array we created above */
-int 
-cc_free_NC_info(apiCB *cc_ctx,         // > control structure
-                               infoNC*** ppNCi);       // <> pointer to free
-                                                        
-
-// -- Locking ----------
-
-#define CC_LOCK_UNLOCK  1
-#define CC_LOCK_READER  2
-#define CC_LOCK_WRITER  3
-#define CC_LOCK_NOBLOCK        16
-
-/* Place a lock on the Named Cache handle, lock types are above 
-NB: API indicates that this call is not implemented*/
-int
-cc_lock_request(apiCB* cc_ctx,         // > DLL's primary control structure
-                               ccache_p* ccache_pointer,               // > named cache control structure
-                               int lock_type);         // > one (or combination) of above defined lock types
-                          
-#if defined(__CFM68K__) && !defined(__USING_STATIC_LIBS__)
-#      pragma import reset
-#endif
-
-#endif /* Krb_CCacheAPI_h_ */
diff --git a/src/mac/libraries/CCache API/include/CCacheUtil.h b/src/mac/libraries/CCache API/include/CCacheUtil.h
deleted file mode 100644 (file)
index 23426fc..0000000
+++ /dev/null
@@ -1,28 +0,0 @@
-#include "CCache.h"
-
-#define kCredsMatch 1
-#define kCredsDiffer 0
-
-// ----- Prototypes for Private Functions ------------------
-cred_union **  newCredBuffer(ccache_p *nc);
-int credBufferInsert(ccache_p* nc,  cred_union creds);
-int credBufferRemove(ccache_p* nc, const cred_union cred_to_remove);
-
-char credcmp (cred_union a, cred_union b);
-
-char isLockOurs(const ccache_p *nc);
-
-int copyDataObj(cc_data *obj, cc_data src);
-int copyV5Cred(cred_union src, cred_union **dest);
-int copyV4Cred(cred_union src, cred_union **dest);
-int dupNC(ccache_p* src, ccache_p** dest);
-void copyDataArray(cc_data **src, cc_data ***dest);
-
-void disposeDataArray(cc_data **base);
-int cc_free_cred_internals(cred_union *creds);
-int freeNCList(apiCB *cntrlBlock);
-int disposeCredBuffer(apiCB *cc_ctx, ccache_p *nc);
-
-Ptr NewSafePtr(long size);
-Ptr NewSafePtrSys(long size);
-void DisposeSafePtr(Ptr safeP);
diff --git a/src/mac/libraries/CodeWarrior Dependencies/Pro2.prj b/src/mac/libraries/CodeWarrior Dependencies/Pro2.prj
deleted file mode 100644 (file)
index 82cced3..0000000
Binary files a/src/mac/libraries/CodeWarrior Dependencies/Pro2.prj and /dev/null differ
diff --git a/src/mac/libraries/CodeWarrior Dependencies/Pro4.prj b/src/mac/libraries/CodeWarrior Dependencies/Pro4.prj
deleted file mode 100644 (file)
index 445248d..0000000
Binary files a/src/mac/libraries/CodeWarrior Dependencies/Pro4.prj and /dev/null differ
diff --git a/src/mac/libraries/DES/bin/deslib.68K b/src/mac/libraries/DES/bin/deslib.68K
deleted file mode 100644 (file)
index eb4f909..0000000
+++ /dev/null
@@ -1 +0,0 @@
-(This file must be converted with BinHex 4.0)\r:#Q4PFfaTBLif1%X!FfKXBMq3"!#3")8`!!!"MQI+5Qpj)A"PCQCY0MKV!!!!!E*\r@K3m!N!d$!!)!N!j8UJ!!9+S!!&5U!!!!P!!"!J#3"!8!N!BZB!!!,Q!!!#VF!!"\r93!)"!J#3"!i!N!i&&!!!J"`%!3)!6@&TEJ!P369AEh*XC!"-Ef&NCA)!N!41G5T\r46PErq#m0)!d[!#mYre`LEIp))&P1N!!UE[rd+d$r$'(rN!6FF!"1ANjd!!3U88j\r@rrJ[$5mYr``LEIp%)&P1N!!UE[rd6Pj1G5T46PErq%MR%!4f!#mZ!!JLEIpB)&P\r1N!!UE[rd0J!`!dM!C`3`!f!#-!-Q(djH6R3!"*0IAfPZDA4TB@aTHQ9IC'9cE'P\rL!!!U88j@rrJ[$5*Yre3J@8k3!#TZrr41ANjeNPpIG'9bE@PZBA4PAf4PFfaTBJ!\r!!#T46PEri%MR(c`X,J!)*Li!$#iZ!"!SEJ!B*'i!&%UZ!"aR!!8@*Nak!"SEFKM\rMVA!!%"Yb%11SLS"`!"!EiBL+J(!!%"Z+J(J!'"Yb'11XF!!3'h)3ikL)J(!!%"[\rKL)L!F!!3'iL!*NBS3f!!"-*`#,k!EAT`!"!E!S!!!!$rFKMMU,'&F!!3'`+!!!!\r!rh)3ikLaKA!!%"X#J!!!!2rKL,'&F!!3'`+!!!!!rl'&F!!3'`+!!!!!rh)BikL\raK(!!%"X#J!!!!2pb%11SXB4`!"!E!S!!!!$riBLaK(!!%"X#J!!!!2qaK&'(B!!\r!NYI()!F-J!!!!!GL!!##-$X#"Nll!!)!H!"S!&J!5J!q!#i!(J!3F!!3)`+!!!!\r!rq')XB4`!"!M!S!!!!$rFK$MU,'%F!!3)`+!!!!!rh)BikLaK(!!%#-#J!!!!2q\raKA!!%#-#J!!!!2rKL,'&F!!3)`+!!!!!rh)3ikLaKA!!%#-#J!!!!2pb'11SXB9\rq!#!%!S#UN!6LL#B&!S1UN!5'J#!%!S"9N!3L"3+"9C!%dS'#J#J"+J4b%1+Y!S8\r!!!$r)'hrr#S`A!$DK5)%G"MNU3+"!!!!rb"Yrrb+X"`!)J6JL3+"!!!!rb"Yrr`\rL-"`!jBQ#K5S%!S8!!!$r)'hrr#S`A!$RMBU"+!0b%1+X!S3!!!$r)'hrr#J`6!$\rBK#)$G"MNU3+"!!!!rb"Yrrb)X"`!)J2JL3+"!!!!rb"Yrr`L-"`!jBQ#K#J$!S3\r!!!$r)'hrr#J`6!$RM)L"I!"J!!'B*J4b&H1V)J4d#q5TJS-Q'V1$F$mL!h3Bj+R\r#J#"YrrK`2b3$,8$ri(!3i+V%V[rJjBSLEIridm)J+3%!J,!F!()r*!2JLX5"jBS\rJEIridF+!U!)!FMr#Jq@*)'hrq0("J+J$!,'&*J4b#H1V)J4d&q5TJS-Q'V1$F$m\rL!h33j+R#J1@*)'hrq0("F$mL!h3Bj+R#J1@*)Qhrq02")#N%!)#S"3"b2b3$i)V\r%JH@+)'hrq0(#J+J'!()r`S2PL5"YrrM4`B#S"`#aK5B&FKAMUb)&G![NUB+$*KU\rcJh!r)J0d'15T`S!JEIriF$mN!be!rq"`%1#Ua+lri1@+)Qhrq02#)#N"!)#`(!"\rb2b3$i)V%JH@+)'hrq0(#J+J#!()r`S2PL5"YrrM4`B#S!`#aK#B&FJRMUb)&G"I\rNUB+$*KUcJh!r)J0d%15T`S$PL5"YrrM4`A!r)J0d'15T`S$PL5*YrrM6`5!T"!#\r!U!8!FMmN!q#+a)(PLL"YrrM4`S#S"J"b2m+$jBNJEIridF'!U!F!XB45KR!)[)"\rY!2jN)!8#J2#3"1L)*J3#Jr#3")D!)!8#J!q3"#)%!S%2N!6TLB+!+!%U"()3iUd\r#K3!!!2mJEIrd+M"F!1Q0)J4d'15T!S%!!!$r)'hrp#)`(!$YLB+&+J6JM3+&!!!\r!rb"Yrr3U-&`!jBf+J5)%!S%!!!$r)'hrp)U`(!!S!h)3iU`#K!!!!2mJEIrd+$"\r-!1Q-)J0d'15T!S%!!!$r)'hrp#)`(!$YLB+%+!2JM!+%!!!!rb"Yrr3S-%`!jBb\r)J5)$!S%!!!$r)'hrp)L`(!"&k[q!)!9b'1+S!S!!!!$r'-!J"A)3iUJ#J!!!!2m\rB`#!&i)J#J!!!!2mB`#!&!S!!!!$r'-!J"()BiUJ#J!!!!2mB`#!%FK$LU!+!!!!\r!raM!)!6JL!+!!!!!raM!)!3#J!!!!2mB`%U(EJ$l2'!!"6j+Kfi'F!"J!!8f*Na\r`!"!EFKMMU#e!rr4`!"!EFK$MU)'Zrr4`!"!EiBL"V[rdF!!3'i'Zrr4`!"!EFKM\rMU#e!rr"`!"!EFK$MU)'Zrr"`!"!EiBL"V[r`F!!3'i'Zrr!Q4LK$HJ!D'h)Bike\r`!"!EFK$MU)U!F!!3'q')LS"`!"!ELS"i!"JEFKMMV(!!%"Yb%11SL)"`!"!EiBL\r)J(!!%"Z)J#e&rq`Y42rS)!3#J+U3"1+)*J8#JkU3")D!)!3#J&@3"#)&!S&9N!6\r5JB+!+!%U"()3iUd#K3!!!2mJEIrm+M"F!0U&)J4d'15T!S%!!!$r)'hrr)U`(!!\rL"1#*!S%!!!$r)'hrr#)`(!$PLB+&+J3#K3!!!2mJEIrm+M"F!1H0LS%S!h)3iU`\r#K!!!!2mJEIrm+$"-!0L%)J0d'15T!S%!!!$r)'hrr)L`(!!L!q#*!S%!!!$r)'h\rrr#)`(!$PLB+%+!-#K!!!!2mJEIrm+$"-!1H-L)&&kJ#!I!"J!!()*J4b#H1V)J4\rd&q5TJS-Q)V1$F$mL!q#*`S$PL5"YrrM4`A!r`)2PL#*YrrM6`#!T"`#!U!B!FMm\rN!be!rq"`%1#Ua)(PLL"YrrM4`L!S"3#!V[rJFMmN!be"rq4b'1+Ua+lrj1@+)'h\rrq0(#J+J%!,'&*J4b&H1V)J4d#q5TJS-Q)V1$F$mL!h3Bj+R#J#"YrrK`2b3$i)V\r%J1@+)Qhrq02#F$r!Jq@))M!F!#"YrrM4`#!S!`#!U3)!G$mY32rN)!-Y3IrJFK$\rLU-##jBJJEIridF!J+!%!J+lrj)#Zrq#aK5B&FJRMUb)&G"INUB+$*L+cJh!r)J2\rJLF+!jBNJEIridF&`2m#$jBJLEIridm!J+3F!J+J'!()r*!-Y32rNF"$JUX5"jBS\rJEIridF)J+!8!J+lrj()r*!-Y3IrJFKMLUX5Zrq$PLL"YrrM4`S#S"!#aK#B&FKA\rMUb)&G![NUB+$*L+cJh!r)J0d'15T`S!JEIriF$mN!q#+a)$PLL*YrrM6`R!r`)2\rPL#)`(!!JEIridF!J+!-!J+N#!(3r,8$rj#!$,8(ri()3iUM!JZ@))'hrq0(!)#J\r"!)#Zrq5!V[rJXB45KR!)[)"Y!2id)!8#J2#3"1L)*J3#Jr#3")D!)!8#J!q3"#)\r%!S%2N!6TLB+!+!%U"()3iUd#K3!!!2mJEIrd+M"F!1Q0)J4d'15T!S%!!!$r)'h\rrp#)`(!$YLB+&+J6JM3+&!!!!rb"Yrr3U-&`!jBf+J5)%!S%!!!$r)'hrp)U`(!!\rS!h)3iU`#K!!!!2mJEIrd+$"-!1Q-)J0d'15T!S%!!!$r)'hrp#)`(!$YLB+%+!2\rJM!+%!!!!rb"Yrr3S-%`!jBb)J5)$!S%!!!$r)'hrp)L`(!!J,[rdXB8J,[r`XB4\r`#,k!EhC4Kb!&FKMLU!+!!!!!raM!)!9b%1+S!S!!!!$r'-!J"H#)!S!!!!$r'-!\rJ"3+!!!!!raM!)!4b'1+S!S!!!!$r'-!J"()3iUJ#J!!!!2mB`#!%i)J#J!!!!2m\rB`#!%!S!!!!$r'-!YE[rXrr3YE[rSrr"J!2ZffFFJ"`b!!!!!#')!!)!`1`)'6[X\r!!J"f!'J!@J"1!%3!0J!S!"`!%L!%!S!!!!$r'3!J"1#)!S!!!!$r'3!J"()3iUJ\r#J!!!!2mC!#!%FKMLU!+!!!!!raN!)!8#J!!!!2mC!#!&i)J#J!!!!2mC!#!&FK$\rLU!+!!!!!raN!)!9b'1+S!S!!!!$r'3"`!%cI(2K1ANjd!"L2C'9cAf0LBepPEQ0\rbHA"d!!!U88j@rr4)jamm+'i!&#CZ!"Kk!"SEFKMMVA!!%"Yb%11SLS"`!"!EiBL\r+J(!!%"Z+J(J!'"Yb'11XF!!3'h)3ikL)J(!!%"[KL)L!F!!3'iL!*Qi!##iZ!""\rJ!!4JF!LqJ'ekF!!3'`+!!!!!rh)BikLaKA!!%"X#J!!!!2pb%11SXB9`!"!E!S!\r!!!$riBLaKA!!%"X#J!!!!2qaKA!!%"X#J!!!!2pb'11SXB4`!"!E!S!!!!$rFK$\rMU,'%F!!3'`+!!!!!rq')XB4`!"!E!S!!!!$rXB44Kf!!!*,Aab!($)!!!!!(BJ!\r!JM!l!JC1q`!#!(J!D!"B!%S!2J!Z!"i!%(!!%#-#J!!!!2rKL,'%F!!3)`+!!!!\r!rh)3ikLaK(!!%#-#J!!!!2pb'11SXB4`!"!M!S!!!!$rXB9`!"!M!S!!!!$riBL\raKA!!%#-#J!!!!2pb%11SXB9`!"!M!S!!!!$rFKMMU,'&IJ!N6#!%!S#UN!6LL#B\r&!S1UN!5'J#!%!S"9N!3L"3+"9C!%dS'#J#J"+J4b%1+Y!S8!!!$r)'hrr#S`A!$\rDK5)%G"MNU3+"!!!!rb"Yrrb+X"`!)J6JL3+"!!!!rb"Yrr`L-"`!jBQ#K5S%!S8\r!!!$r)'hrr#S`A!$RMBU"+!0b%1+X!S3!!!$r)'hrr#J`6!$BK#)$G"MNU3+"!!!\r!rb"Yrrb)X"`!)J2JL3+"!!!!rb"Yrr`L-"`!jBQ#K#J$!S3!!!$r)'hrr#J`6!$\rRM)L"I!"J!!'B*J4b&H1V)J4d#q5TJS-Q'V1$F$mL!h3Bj+R#J#"YrrK`2b3$,8$\rrp(!3i+V%V[rdjBSLEIridm)J+3%!J,!F!()r*!2JLX5"jBSJEIridF+!U!)!FMr\r#Jq@*)'hrq0("J+J$!,'&*J4b#H1V)J4d&q5TJS-Q'V1$F$mL!h33j+R#J1@*)'h\rrq0("F$mL!h3Bj+R#J1@*)Qhrq02")#N%!)#S"3"b2b3$i)V%JH@+)'hrq0(#J+J\r'!()r`S2PL5"YrrM4`B#S"`#aK5B&FKAMUb)&G![NUB+$*KUcJh!r)J0d'15T`S!\rJEIriF$mN!be!rr4`%1#Ua+lrp1@+)Qhrq02#)#N"!)#`(!"b2b3$i)V%JH@+)'h\rrq0(#J+J#!()r`S2PL5"YrrM4`B#S!`#aK#B&FJRMUb)&G"INUB+$*KUcJh!r)J0\rd%15T`S$PL5"YrrM4`A!r)J0d'15T`S$PL5*YrrM6`5!T"!#!U!8!FMmN!q#+a)(\rPLL"YrrM4`S#S"J"b2m+$jBNJEIridF'!U!F!XB45KR!)[)"Y!2jN)!8#J2#3"1L\r)*J3#Jr#3")D!)!8#J!q3"#)%!S%2N!6TLB+!+!%U"()3iUd#K3!!!2mJEIrd+M"\rF!1Q0)J4d'15T!S%!!!$r)'hrp#)`(!$YLB+&+J6JM3+&!!!!rb"Yrr3U-&`!jBf\r+J5)%!S%!!!$r)'hrp)U`(!!S!h)3iU`#K!!!!2mJEIrd+$"-!1Q-)J0d'15T!S%\r!!!$r)'hrp#)`(!$YLB+%+!2JM!+%!!!!rb"Yrr3S-%`!jBb)J5)$!S%!!!$r)'h\rrp)L`(!"&k[q!5SGZ!2ZH*Qi!$#!&FKMLU!+!!!!!raE!)!9b%1+S!S!!!!$r&X!\rJ"H#)!S!!!!$r&X!J"3+!!!!!raE!)!4b'1+S!S!!!!$r&X!J"()3iUJ#J!!!!2m\r@`#!%i)J#J!!!!2m@`#!%!S!!!!$r&X!J"%cI(2K1ANjd!"50C'9cAf0LBepMDh0\reE3!!+P&19[r`51FH-#CZ!"!NEJ!)HJ!D'R)Bike`!"!DFK$MU)U!F!!3'Z')LS"\r`!"!DLS"i!"JDFKMMV(!!%"Tb%11SL)"`!"!DiBL)J(!!%"U)J#!%!S#UN!6LL#B\r&!S1UN!5'J#!%!S"9N!3L"3+"9C!%dS'#J#J"+J4b%1+Y!S8!!!$r)'hrr#S`A!$\rDK5)%G"MNU3+"!!!!rb"Yrrb+X"`!)J6JL3+"!!!!rb"Yrr`L-"`!jBQ#K5S%!S8\r!!!$r)'hrr#S`A!$RMBU"+!0b%1+X!S3!!!$r)'hrr#J`6!$BK#)$G"MNU3+"!!!\r!rb"Yrrb)X"`!)J2JL3+"!!!!rb"Yrr`L-"`!jBQ#K#J$!S3!!!$r)'hrr#J`6!$\rRM)L"5Ui!&'F!!D`N5h`!B!!"Q#B%FKAMUb)%G![NUB+$*KUcJh!r)J0d'15T`S!\rJEIriF$mN!be!rr"`%1#Ua+lrm1@+)Qhrq02#)#N"!)#`(!"b2b3$i)V%JH@+)'h\rrq0(#J+J#!()r`S2PL5"YrrM4`B#S!`#aK5B%FJRMUb)%G"INUB+$*KUcJh!r)J0\rd%15T`S$PL5"YrrM4`A!r)J0d'15T`S$PL5*YrrM6`5!T"!#!U!8!FMmN!q#+a)(\rPLL"YrrM4`S#S"J"b2m+$jBNJEIridF'!U!F!XB8Q"A)9ikXL"A3,j+Q#JbBDXi0\r`2b)$G"MNUF+!)'hrq(!r*!-Y32r`F"$JUX5Zrr$PLL*YrrM6`L!T!3#!X"`!FMm\rN!q#+a)(PLL"YrrM4`S#S!J"b2m+$jBNJEIridF'!U!-!XB3Q"A)*ikXL"A3Aj+Q\r#JbBDXi0`2b)$G"$NUF+!jBNJEIridF&`2b)$G"MNUF+!jBNLEIridm%J+33!J+J\r&!()r*!2JLX5"jBSJEIridF+!U!B!FMr#Jq@*)'hrq0("J+J(!,'%8SC`#,b!E3$\rqC'!!!G`N5dAU!)"m!'!!!FJQ"()*ikXL"(3Aj+Q#JbBLXi0`2b)$i)R#J1@*)'h\rrq0("F$r!Jq@))Qhrq02!)#N(!)#S"J"b2b3$,8$rm(!3i+V%JH@+)'hrq0(#)#J\r&!)#Zrr"b2b3$,8(rp()BiUV%V[rdjBSJEIridF+!U!3!XB8Q"()9ikXL"(3,j+Q\r#JbBLXi0`2b)$G"MNUF+!)'hrq(!r*!2JLX5!jBSLEIridm*`2m#$jBJL-"`!)'h\rrq0(!)#J$!)#T!J"d2be!rr3J!be"rr"b%1+S`),PL#"YrrM4`#!S!3#!V[rdJ+l\rrm,'&*J9b#H1V)J9d&q5TJS-Q)V1$F$mL!q#*`S$PL5"YrrM4`A!r`)2PL#*YrrM\r6`#!T"`#!U!B!FMmN!be!rr4`%1#Ua)(PLL"YrrM4`L!S"3#!V[rdFMmN!be"rr"\rb'1+Ua+lrm1@+)'hrq0(#J+J%!,'%*J9b&H1V)J9d#q5TJS-Q)V1$F$mL!h3Bj+R\r#J#"YrrK`2b3$i)V%J1@+)Qhrq02#F$r!Jq@))M!F!#"YrrM4`#!S!`#!U3)!G$m\rY32rd)!-Y3Ir`FK$LU-##jBJJEIridF!J+!%!J+lrp)#Zrr#aK&+'F!LmJ'd!rM3\rJ"3+!m*!%k)JQ"!+$m*!%KS!J"3+!$j!%)J3#J3q3"1Q*JS!S!5S%FK$LV3+&!!!\r!rb"Yrr3U-&`!kBdL"(3Bj+N#J3!!!2mJEIrd)M!F!1f*JS8U"1#0!S8!!!$r)'h\rrp#S`A!$PMBU")J3#J3!!!2mJEIrdLV!F!#J$FK$LV!+%!!!!rb"Yrr3S-%`!kB`\rL!h3Bj+N#J3!!!2mJEIrd)M!F!1f*JS3S!q#-!S3!!!$r)'hrp#J`6!$PM)L")J-\r#J3!!!2mJEIrdL,!F!#4Z!!`J"A)BiUJ#J!!!!2m8`#!&FK$LU!+!!!!!ra6!)!A\rJL!+!!!!!ra6!)!8#J!!!!2m8`#!%FKMLU!+!!!!!ra6!)!4b%1+S!S!!!!$r&-!\rJ"1#)!S!!!!$r&-!J"!+!!!!!ra6!F!"-h`ai6Pj1G!!3Mf4PFepPBf*IC@jMFRP\r`G!!!+P&19[rF,`-JEJ!)GJ"J!!$+!M!!rMJ!F!&b!h32,8$rh(!!%$!i!1L!`))\r8-$J!!S)!!!!2XB,NJX5"F!0b$be"rq"b!")`1!$SJF+Zrq!Y3[rN&$!i!!+#!!!\r!$l1#a)!J,[rNXB,LJX5Zrpa`!A)$,8$rk(!!%$!i!1L!!S!!!!!2,8(rl")`1!!\r#J3!!!!qaJH5"`Ulrl(!$,8,rm(3!&$!i!1L#!S)!!!!2,8$rp"!`1!!#J!!!!!q\reJ-#Zrr5cJ-#ZrqJL,[r`Xi!+J!!!!!'"-$J!8S0`#,D!C3$r-LBI6Pj1G!!%P'4\rPFepQDAKeF&pVCAPIF'&bDA4j!!!!+P&19[rB,`-JEJ!)GJ"J!!$dF!&b!h32,8$\rrf"!`1!!#J!!!!2lSJ-##G!mY3IrF%M!i!!+"!!!!rX+#XB(NJF+Zrpa`!h32,8,\rri"3`1!!#JJ!!!2lSJX5Zrq!Y32rN%$!i!!+!!!!!rJ+!!!!!$l@!`+lrj,1!iS$\r!V[rBFJ&d!be"rqJ5-$J!!S%!!!$qk)%#J3!!!!mY3[rX&$!i!!+#!!!!rJ+#!!!\r!$l1#j),%V[rXFJ-Y32r`%$!i!!+!!!!!rZL!!S!!!!!2,8(rp")`1!!#J3!!!2i\r#J3!!!!qaJF+Zrr5eJF+ZrqJJ,[r`XB%3-$J!G!(!JV#"CJ4`!'!-8S0`#,D!C3$\rr#(!"*Kp1ANjd!!58C'9cAf0SC@0VAfYPH9p`BA*TG(N!!!!U88j@rq")jamm,#i\r!##BZ!!`SEJ!B*'i!&%UZ!"aR!!8@*Nak!"SEFKMMVA!!%"Yb%11SLS"`!"!EiBL\r+J(!!%"Z+J(J!'"Yb'11XF!!3'h)3ikL)J(!!%"[KL)L!F!!3'iL!*NBS3f!!"-"\r`#,#Z!""X@Ri!(KYb'11[F!!3'h)3ikL1J(!!%"[KL)k!F!!3'ik!F!!3'h)BikJ\rY32rdF!!3'h)3ikL"V[rdF!!3'q')JDlrp(!!%"Z"V[rd[i8J,[rdXB44VJ!3B!!\r!TYIZ!"!J,J!3$)!!!!!)BJ!!N!!`1`)'6[X!!J#'!(B!CJ"B!%`!2!!X!"i!%R!\r!%#-#J!!!!2qaK(!!%#-#J!!!!2rKL,'%F!!3)`+!!!!!rh)3ikLaK(!!%#-#J!!\r!!2pb'11SXB4`!"!M!S!!!!$rXB9`!"!M!S!!!!$riBLaKA!!%#-#J!!!!2pb%11\rSXB9`!"!M!S!!!!$rFKMMU,'&3Ui!%#!%!S#UN!6LL#B&!S1UN!5'J#!%!S"9N!3\rL"3+"9C!%dS'#J#J"+J4b%1+Y!S8!!!$r)'hrr#S`A!$DK5)%G"MNU3+"!!!!rb"\rYrrb+X"`!)J6JL3+"!!!!rb"Yrr`L-"`!jBQ#K5S%!S8!!!$r)'hrr#S`A!$RMBU\r"+!0b%1+X!S3!!!$r)'hrr#J`6!$BK#)$G"MNU3+"!!!!rb"Yrrb)X"`!)J2JL3+\r"!!!!rb"Yrr`L-"`!jBQ#K#J$!S3!!!$r)'hrr#J`6!$RM)L"I!"J!!'B*J4b&H1\rV)J4d#q5TJS-Q'V1$F$mL!h3Bj+R#J#"YrrK`2b3$,8$ri(!3i+V%V[rJjBSLEIr\ridm)J+3%!J,!F!()r*!2JLX5"jBSJEIridF+!U!)!FMr#Jq@*)'hrq0("J+J$!,'\r&*J4b#H1V)J4d&q5TJS-Q'V1$F$mL!h33j+R#J1@*)'hrq0("F$mL!h3Bj+R#J1@\r*)Qhrq02")#N%!)#S"3"b2b3$i)V%JH@+)'hrq0(#J+J'!()r`S2PL5"YrrM4`B#\rS"`#aK5B&FKAMUb)&G![NUB+$*KUcJh!r)J0d'15T`S!JEIriF$mN!be!rq"`%1#\rUa+lri1@+)Qhrq02#)#N"!)#`(!"b2b3$i)V%JH@+)'hrq0(#J+J#!()r`S2PL5"\rYrrM4`B#S!`#aK#B&FJRMUb)&G"INUB+$*KUcJh!r)J0d%15T`S$PL5"YrrM4`A!\rr)J0d'15T`S$PL5*YrrM6`5!T"!#!U!8!FMmN!q#+a)(PLL"YrrM4`S#S"J"b2m+\r$jBNJEIridF'!U!F!XB45KR!)[)"Y!2jN)!8#J2#3"1L)*J3#Jr#3")D!)!8#J!q\r3"#)%!S%2N!6TLB+!+!%U"()3iUd#K3!!!2mJEIrd+M"F!1Q0)J4d'15T!S%!!!$\rr)'hrp#)`(!$YLB+&+J6JM3+&!!!!rb"Yrr3U-&`!jBf+J5)%!S%!!!$r)'hrp)U\r`(!!S!h)3iU`#K!!!!2mJEIrd+$"-!1Q-)J0d'15T!S%!!!$r)'hrp#)`(!$YLB+\r%+!2JM!+%!!!!rb"Yrr3S-%`!jBb)J5)$!S%!!!$r)'hrp)L`(!"&k[q!)!9b'1+\rS!S!!!!$r'-!J"A)3iUJ#J!!!!2mB`#!&i)J#J!!!!2mB`#!&!S!!!!$r'-!J"()\rBiUJ#J!!!!2mB`#!%FK$LU!+!!!!!raM!)!6JL!+!!!!!raM!)!3#J!!!!2mB`,q\r&)#lrp,'%5Ui!%'i!qcaJ!!8q5Ui!%'i'F!"J!!8d*Naq!"iEFKMMVh!!%"Yb%11\rSMS"`!"!EiBL1J(!!%"Z1J(!!%"Yb'11S,8$rm(!!%"Yb%11SJDlrm(!!%"[KL)'\rZrr"`!"!EJDlrm#C'+%0k!"SEFKMMVA!!%"Yb%11SLS"`!"!EiBL+J(!!%"Z+J(J\r!'"Yb'11XF!!3'h)3ikL)J(!!%"[KL)L!F!!3'iL!,8Arl#e%rqJJ"!+!UT!%iSJ\rQ"3+$UT!%KS!J"!+!9C!%)J8#J9@3"0+"JS!S!5S%FK$LV3+&!!!!rb"Yrr`U-&`\r!fS8L"(3Bj+N#J3!!!2mJEIrmLV!F!#)%i)N#J3!!!2mJEIrm)M!F!1@*JS8U"!+\r&!!!!rb"Yrr`U-&`!jif+J5J$FK$LV!+%!!!!rb"Yrr`S-%`!f)3L!h3Bj+N#J3!\r!!2mJEIrmL,!F!#)$i)N#J3!!!2mJEIrm)M!F!1@*JS3S!`+%!!!!rb"Yrr`S-%`\r!jib)J8AU!)"m!'!!!FJQ"()*ikXL"(3Aj+Q#JbBLXi0`2b)$i)R#J1@*)'hrq0(\r"F$r!Jq@))Qhrq02!)#N(!)#S"J"b2b3$,8$ri(!3i+V%JH@+)'hrq0(#)#J&!)#\rZrq"b2b3$,8(rj()BiUV%V[rNjBSJEIridF+!U!3!XB8Q"()9ikXL"(3,j+Q#JbB\rLXi0`2b)$G"MNUF+!)'hrq(!r*!2JLX5!jBSLEIridm*`2m#$jBJL-"`!)'hrq0(\r!)#J$!)#T!J"d2be!rq3J!be"rq"b%1+S`),PL#"YrrM4`#!S!3#!V[rNJ+lri,'\r&*J9b#H1V)J9d&q5TJS-Q)V1$F$mL!q#*`S$PL5"YrrM4`A!r`)2PL#*YrrM6`#!\rT"`#!U!B!FMmN!be!rq4`%1#Ua)(PLL"YrrM4`L!S"3#!V[rNFMmN!be"rq"b'1+\rUa+lri1@+)'hrq0(#J+J%!,'%*J9b&H1V)J9d#q5TJS-Q)V1$F$mL!h3Bj+R#J#"\rYrrK`2b3$i)V%J1@+)Qhrq02#F$r!Jq@))M!F!#"YrrM4`#!S!`#!U3)!G$mY32r\rN)!-Y3IrJFK$LU-##jBJJEIridF!J+!%!J+lrj)#Zrq#aK&+'F!LmJ'd!rM3J"3+\r!m*!%k)JQ"!+$m*!%KS!J"3+!$j!%)J3#J3q3"1Q*JS!S!5S%FK$LV3+&!!!!rb"\rYrr3U-&`!kBdL"(3Bj+N#J3!!!2mJEIrd)M!F!1f*JS8U"1#0!S8!!!$r)'hrp#S\r`A!$PMBU")J3#J3!!!2mJEIrdLV!F!#J$FK$LV!+%!!!!rb"Yrr3S-%`!kB`L!h3\rBj+N#J3!!!2mJEIrd)M!F!1f*JS3S!q#-!S3!!!$r)'hrp#J`6!$PM)L")J-#J3!\r!!2mJEIrdL,!F!,q&)#lrm,'%F!L`VJ!3E(a4VJ!3)!9b'1+S!S!!!!$r'-!J"A)\r3iUJ#J!!!!2mB`#!&i)J#J!!!!2mB`#!&!S!!!!$r'-!J"()BiUJ#J!!!!2mB`#!\r%FK$LU!+!!!!!raM!)!6JL!+!!!!!raM!)!3#J!!!!2mB`#iZrqblKb!ZrqLjJ#e\r!rr"J!2ZbfHi!%#!Z!"!-J!!!!!KL!!#!-$X#"Nll!!)!GJ"S!&S!6J"%!$B!+!!\rF!")J"!+!!!!!raN!)!6JL!+!!!!!raN!)!4b%1+S!S!!!!$r'3!J"()BiUJ#J!!\r!!2mC!#!&!S!!!!$r'3!J"H#)!S!!!!$r'3!J"A)3iUJ#J!!!!2mC!#!&FKMLU!+\r!!!!!raN!F!"-haci6Pj1G!!BN!"NCA0IF'0LBepPEQ0bHA"d!!!!+P&19[rS51F\rI%#*Z!!Kk!"SCFKMMVA!!%"Pb%11SLS"`!"!CiBL+J(!!%"Q+J(!(*J9d&H5VaS!\rJEIrN*M!m!0D$F!FN"5e!rqK`(H#Ua+lrk#"Yrq5'X#`!F!FN"5e$rqaf$HDUa)!\rJEIrN*$!X!1@+K+lrl(!(*JAULmD!)'hrj#B`2!$RLiD#F!mS"A34j+c)J#"Yrq!\rS-%`!f)4`$b3&,8$rl(!Ci+V%V[rX)'hri)L`,!"`$b3&,86rk(J*k+V%J#"Yrq!\rN-#`!jBU%V[rSF!mS"H+-b)!JEIrJ+$"-!1H-L)*k!"SCFKMMVA!!%"Pb%11SLS"\r`!"!CiBL+J(!!%"Q+J(!2)J9d&15T`S!JEIrF)M!F!0+"F!mN"5e!rqa`(1#Ua+l\rrl#"Yrpb#X#`!F!mN"5e"rqKb$1+Ua)!JEIrF*$!X!1@+K+lrk(!2)JASLF+!)'h\rrh#)`(!$RLB+#KS&`"b)&G"(NUF+!)'hrf#)`(!$5JA!(*!8Y32rXF"RJUX5Zrq`\rJEIrBJV!X!(!(*!8Y3IrSFJRLUX5!)'hrf#3`,!$PLS5ZrqK`"b)&iSR#J#"YrpJ\rL-"`!jiQ#JSL")Qi!$#im!!"qr(!3*N"J!!'#F!(!KfFU)!0b'Z+S)J2PL3+"$rr\rrr)+!*J%J"()DiUJL"1@*!S%2rrrmJS!S!@!S)!0b'q+S)J25J3+"$rrrrS+!*J%\rJ"()EiUJL"0+"!S%2rrrqJS!S!H+(HMmL!h3@j+R#K5"Yrp4k-#3$,8Arl(S3kUV\r%V[rXHJmYF"`!rqJL!be#rr"d$q5T`S@#V[r`jBNJEIr8dF%U+!%!LUlrk()m*!-\rY4IrdHJRUUX5"HJ-L!qL*`S@#JZ@*)'hre0("+LJ#!)UZrr4b1#3$k)V%JA)(`S1\r#JZ@*)'hre0("LUJ$!(`r)J4d&Z5T`SBJEIr3I$!N"#e'rr4m$qbUa+lrp(`2,A!\rF!2r`)J3Y3[rXG!lNUF+'JUlrl1@*)'hrd0(",#J"!)bZrr"b2b3%lSV%JH@+)'h\rrd0(#M+J#!()m*!6LLX5"FJ2#K)+#jBNJEIr3dF'-U!-!)!B#J2m!!2mL"3+"!2r\rr!)+!)X%J"J+!!2rr!#)&!S(r!!$rJS!L`91,Y[`!!'i!rRT`!%cI#2K1ANjd!!L\r1E@&VC9pVCAPIFf0SC@3!!!!U88j@rrK)j`!N*'i!##mZ!!`[#L*Yrm`J@8k3!#T\rZrr3[#L*YrqJJ@8k3!#TZrr4+J'B%F2pJ'#m+)QhrJ#"C6T!!+Qlrp%U!C`4`rQ!\r#F!!NAdjH6R3!#)eNCA0IDf9jAh0MD'9N!!!U88j@rrK)j`!N*'i!##m+)QhrX#"\rC6T!!+Qlrp#m+)Qhrl#"C6T!!+Qlrp#m+)QhrJ#"C6T!!+Qlrp%U!CY*`!#4I6Pj\r1G!!%NQ4PFepZCAGIFQ&ZC'pYAfYPH3!!!#T46PEri#m0)Qhr6#"C6T!!+Qlrh#e\r!rqJLEIp-)&P1N!!UE[rF,8$rl#mZ!!JLEIqi)&P1N!!UE[rF5'lrk#*Yrl3J@8k\r3!#TZrpa)E[r`)Qhra#"C6T!!+Qlrh%KZrr!LEIqi)&P1N!!UE[rF5'lri#*YrcJ\rJ@8k3!#TZrpa)E[rN)Qhr1#"C6T!!+Qlrh#mYrcJLEIqd)&P1N!!UE[rF5'lrm#*\rYrm3J@8k3!#TZrpa)E[r`)QhrZ#"C6T!!+Qlrh%jH6R3!")!JC'9cAfPZDA4IFQ&\rZC'pYAfjeE@*PFPpRC@jPFQ&dEh)!!#T46PErq%MR%!3[,Ir!,bi!##*YrmJJ@8k\r3!#TZrr4f!'!+)'hr[%)`1!"5Jh!)YS"Ym#BI6Pj1G!!%R@4PFepcCA4IFQ&ZC'p\rYAfGPEQ9bBA4[FPpcC@9N!!!U88j@rrJLEIqm)'i!#(!)FL#`J@8%SLjJ$NU!C`S\rL#4,B8i"QqL*"6Pj1G!!%Pf4PFepcCA4IFf9aG@9ZBf9IER9YBQ9b!!!U88j@rrK\r)ja!%5(J!!5mYrm![,J!),bhr[#*Yrr!J@8k3!#TZrr4f!'!Q)'hr[(!!%$!i!&+\r!!S!!!!$r)'hr["'!1!!JEIqm5M!i!'B)8S0`#,D!EG3Q(djH6R3!"*PNCA0ICf9\rZCA*KG'9IFQ&ZC'pYAf*XEf0V!!!U88j@rrK)jami+'i!$#4Z!"J[#Q(r!!!!p#`\r!5'S!"'(r!!!!k#i!)!aQ"R!",8!!&(!"*N"JE#JZ!"!NEJ!)B&4`!EL!EaB[#Q(\rr!!!!K()!-J$5KLB"9)T9K'!)GJ!@'YD'H!!U"b!&6!8!!#)$6!-3!0+!6(`3!(r\rrrrmX!#!&"S!%r(-Y6!-!!%am!!&rrrrr,J&+K'DS)!aR"#M'+-G5Lh!%Ym"Z"VI\rZ!"4[L#!'60mFq%jH6R3!&)jNCA0IFA9KC&pMDh0eE3!!!#T46PErp#"Z!!JGD!!\r"rrBJEJ!)(9$rpc!ZrrC1ANjd!!59G(G[Af*jG'9cAhCKH&pdEepZCA4c!!!U88j\r@rr3JEJ!)(@J!!rrd(@J!![re(@J!!Irf(9$rpb!Zrr41ANjd!!5@CQpeFPpLHA4\rPFepfBAKIG'pIEQ9dF`!!!#T46PErm%MR(M`SEJ!)*%`Q6%KZrr!LEImi)&P1N!!\rUE[rX)Qhr6#"C6T!!+Qlrl#)Zrr#aJ5"Yrk`J%&+3!,1!,`!LEImS)&P1N!!UE[r\rX)Qhr-#"C6T!!+Qlrl#e!rr3L5d(Zrr4`"()JX)&P"+)ZB!j+J'F+)JN5f&1!C[S\rL39L,)Qhr-#"C6T!!+Qlrl#e!rr3L5d(Zrr4`"()JX)&P"+)ZB!j+J'F+)JN5f&1\r!C[SL3A`!B$4i!(B!&K*k!'!+iSY`!F#$XB45KA!'ZS"[m%U%CJS3%J!!!!%8J'!\r)%")#!!$q&)"5LP+'F!HmJ'r'F!"-haai6Pj1G!!%MQ4PFepbB@jNEfeIDf9j!!!\r!+P&19Zri51F3"#mZ!"![,J!-5(J3!%KZlrJLEIqF)&P1N!!UEZrd*J"+JfB8,bi\r!#%KZlrJLEIqB)&P1N!!UEZrd5(J3!%+R5'l[q#*Yrd!J@8k3!#TZlr3J!bBI6Pj\r1G!!-N@4PFepbC@&NAh"KFh0hEh*N!!!U88j@lrK)ja`m*Qi!##JZ!!`SEJ!3+Li\r!&(B!$)3!!"!!E`!"+R$rB!!"I#m-)Qhr'#"C6T!!+Ql[p#"Yra")D!"')Qhr)#"\rC6T!!+Ql[p#mYra!["#m,)Qhr&#"C6T!!+Ql[p%U!@%pQ&#mYra!LEImF)&P1N!!\rUEZrdB!!!e%Ki!!S[#b*Yrb3J@8k3!#TZlr3N3%U!C`*#%NU&C`!!XLm-,bhrU#*\rYraJJ@8k3!#TZlr3JEIm35'J!4L*Yrb!J@8k3!#TZlr3[,Im35(J3!%KZlrJLEIm\r8)&P1N!!UEZrd5S"36fB5,bhr%#*Yra`J@8k3!#TZlr4JA%Ki!!T)EZri)Qhr*#"\rC6T!!+Ql[p#4!5S"R!N)55'l[q#m,)Qhr,#"C6T!!+Ql[p%U!CbJ[,IqN)Qhr'#"\rC6T!!+Ql[p#"Yra")D!"')Qhr)#"C6T!!+Ql[p&K2B!*f!8U$C`$qfNU$CK)["%+\rR,`XLEIp!)&P1N!!UEZrd,bhrS#*YraJJ@8k3!#TZlr4+K9K2CaC)H"!!3UG)EZr\ri)Qhr3#"C6T!!+Ql[p#!%8i"#-`J!)!0A`%3!5F"-ha`i6Pj1G!!3NQ4PFepbC@&\rNAh"hAh0dFQPZC`!!!#T46PEr0%MR(c`QEJ!)+'i!$#e,rc4k!8AZrlJJ5h$r8S"\r+''Ek,J")H!"!3UG)E[qi)Qhr3#"C6T!!+Qlr-(`"B$S@'dR$H!"J'NU&C`SJ!h)\r"`)'a'Q!))!0b!F#"X5,LLe+%F!DiJ'rJF!I!KQB+)!9A`%3!5F!U!&+'[)GM`NA\rZrlJQ6(`!B"jf!(J!B!iJ"&+!%KT*`H'TKS&5K(!'Z)"[l"E$8SC`"lb!Bp`[$#*\rYrq`J@8k3!#TZrc")E[mi,``LEIr))&P1N!!UE[m`,`a)E[mi,`F[$#mZrc4Krrr\rrh%T)H!#!3UG)E[mi)Qhr3#"C6T!!+Qlr-#m-)Qhrl#"C6T!!+Qlr-(!!60mFq%j\rH6R3!#*&NCA0IFh4bD@jRAh4[AfYPH3!!+P&19[ri51F30#4Z!!`QEJ!)GJ![,Iq\r8,`SLEImm)&P1N!!UE[rd8%pJ0R!!%"X[!#mYrj!!,`SLEImm)&P1N!!UE[rdF!L\rfJ%r[!!aX&#mYri`[#L*Yrc`J@8k3!#TZrr436b!$8S0b#,#"EF![,Iq),`SLEIm\rm)&P1N!!UE[rd8%p-h``)6Pj1G!!)P@4PFepMBQa[BfYIF(*TER4ICQPXC3!!+P&\r19[ri51F30#CZ!!JNEIq%GJ"J)NKi!!J[#b"+8)T)8#*Yrc3J@8k3!#TZrr4+J'B\r%F!&J#P+$F"#fJ'ABF!"-h``)6Pj1G!!%Mf4PFepTFephC@&VAfYPH3!!+P&19[r\rF51FI2#`Z!!`Q,J!J*'i!&#CZ!"JSEJ!F5Ui!*'F!$)`Z!b"(8SGk!"S3FKMMV5"\r(8SG`!"!3FK$MU)U!)%G5Kh!!%"$KL)U!)%G5Kh!!%"#+J#"(8SGi!"J3FKMMV#"\r(8SG`!"!3FK$MU)L!)%G5Kh!!%"$KL)L!)%G5Kh!!%"#)J#iZ!!JY4[rdB!!-%R!\r)X+i!%'i!!*iJ4e+(F!!3%!+!!!!!rh)BikLaK5"(8SG`!"!3!S!!!!$rFK$MU,'\r&)%G5Kh!!%"!#J!!!!2rKL,'&)%G5Kh!!%"!#J!!!!2qaK5"(8SG`!"!3!S!!!!$\rrFKMMU,'%)%G5Kh!!%"!#J!!!!2pb%11SXB3J4e+(F!!3%!+!!!!!rq')XB3J4e+\r(F!!3%!+!!!!!rl'%8Di!%'!!!,6HVJ!3)#i!%!b!!!!!"f)!!*i`1`)'6[X!!J#\r8!)!!E!"D!%S!0J!L!""6Kb"(F!!3%!+!!!!!rq')XB46Kb"(F!!3%!+!!!!!rh)\r3ikLaK&1()%G`!"!3!S!!!!$rFKMMU,'%8iFJ4h!!%"!#J!!!!2qaK91()%G`!"!\r3!S!!!!$riBLaK91()%G`!"!3!S!!!!$rFK$MU,'&8iFJ4h!!%"!#J!!!!2pb'11\rSXB9#VJ!3)!3#J+U3"1+)*J8#JkU3")D!)!3#J&@3"#)&!S&9N!65JB+!+!%U"()\r3iUd#K3!!!2mJEIrm+M"F!0U&)J4d'15T!S%!!!$r)'hrr)U`(!!L"1#*!S%!!!$\rr)'hrr#)`(!$PLB+&+J3#K3!!!2mJEIrm+M"F!1H0LS%S!h)3iU`#K!!!!2mJEIr\rm+$"-!0L%)J0d'15T!S%!!!$r)'hrr)L`(!!L!q#*!S%!!!$r)'hrr#)`(!$PLB+\r%+!-#K!!!!2mJEIrm+$"-!1H-L)&m!'!!!CJQ"()9ikXL"(3,j+Q#JbBDXi0`2b)\r$G"MNUF+!)'hrq(!r*!-Y32rFF"$JUX5ZrpcPLL*YrrM6`L!T!3#!X"`!FMmN!q#\r+a)(PLL"YrrM4`S#S!J"b2m+$jBNJEIridF'!U!-!XB8Q"()*ikXL"(3Aj+Q#JbB\rDXi0`2b)$G"$NUF+!jBNJEIridF&`2b)$G"MNUF+!jBNLEIridm%J+33!J+J&!()\rr*!2JLX5"jBSJEIridF+!U!B!FMr#Jq@*)'hrq0("J+J(!,'&*J9b&H1V)J9d#q5\rTJS-Q'V1$F$mL!h3Bj+R#J#"YrrK`2b3$,8$rh(!3i+V%V[rFjBSLEIridm)J+3%\r!J,!F!()r*!2JLX5"jBSJEIridF+!U!)!FMr#Jq@*)'hrq0("J+J$!,'%*J9b#H1\rV)J9d&q5TJS-Q'V1$F$mL!h33j+R#J1@*)'hrq0("F$mL!h3Bj+R#J1@*)Qhrq02\r")#N%!)#S"3"b2b3$i)V%JH@+)'hrq0(#J+J'!()r`S2PL5"YrrM4`B#S"`#aK&+\r'F!LmJ'd!rQ3J"3+!m*!%k)JQ"!+$m*!%KS!J"3+!$j!%)J3#J3q3"1Q*JS!S!5S\r%FK$LV3+&!!!!rb"Yrr3U-&`!kBdL"(3Bj+N#J3!!!2mJEIrd)M!F!1f*JS8U"1#\r0!S8!!!$r)'hrp#S`A!$PMBU")J3#J3!!!2mJEIrdLV!F!#J$FK$LV!+%!!!!rb"\rYrr3S-%`!kB`L!h3Bj+N#J3!!!2mJEIrd)M!F!1f*JS3S!q#-!S3!!!$r)'hrp#J\r`6!$PM)L")J-#J3!!!2mJEIrdL,!F!%AUri!J"!+!UT!%iSJQ"3+$UT!%KS!J"!+\r!9C!%)J8#J9@3"0+"JS!S!5S%FK$LV3+&!!!!rb"Yrr`U-&`!fS8L"(3Bj+N#J3!\r!!2mJEIrmLV!F!#)%i)N#J3!!!2mJEIrm)M!F!1@*JS8U"!+&!!!!rb"Yrr`U-&`\r!jif+J5J$FK$LV!+%!!!!rb"Yrr`S-%`!f)3L!h3Bj+N#J3!!!2mJEIrmL,!F!#)\r$i)N#J3!!!2mJEIrm)M!F!1@*JS3S!`+%!!!!rb"Yrr`S-%`!jib)J8IV!)"m!'!\r!!FJQ"()*ikXL"(3Aj+Q#JbBMXi0`2b)$i)R#J1@*)'hrq0("F$r!Jq@))Qhrq02\r!)#N(!)#S"J"b2b3$,8$rh(!3i+V%JH@+)'hrq0(#)#J&!)#Zrpab2b3$,8(ri()\rBiUV%V[rJjBSJEIridF+!U!3!XB8Q"()9ikXL"(3,j+Q#JbBMXi0`2b)$G"MNUF+\r!)'hrq(!r*!2JLX5!jBSLEIridm*`2m#$jBJL-"`!)'hrq0(!)#J$!)#T!J"d2be\r!rq!J!be"rpab%1+S`),PL#"YrrM4`#!S!3#!V[rJJ+lrh,'&*J9b#H1V)J9d&q5\rTJS-Q)l1$F$mL!q#*`S$PL5"YrrM4`A!r`)2PL#*YrrM6`#!T"`#!U!B!FMmN!be\r!rq"`%1#Ua)(PLL"YrrM4`L!S"3#!V[rJFMmN!be"rpab'1+Ua+lrh1@+)'hrq0(\r#J+J%!,'%*J9b&H1V)J9d#q5TJS-Q)l1$F$mL!h3Bj+R#J#"YrrK`2b3$i)V%J1@\r+)Qhrq02#F$r!Jq@))M!F!#"YrrM4`#!S!`#!U3)!G$mY32rJ)!-Y3IrFFK$LU-#\r#jBJJEIridF!J+!%!J+lri)#ZrpbaK&+'F!LmJ'd!rM3J"3+!m*!%k)JQ"!+$m*!\r%KS!J"3+!$j!%)J3#J3q3"1Q*JS!S!5S%FK$LV3+&!!!!rb"Yrr3U-&`!kBdL"(3\rBj+N#J3!!!2mJEIrd)M!F!1f*JS8U"1#0!S8!!!$r)'hrp#S`A!$PMBU")J3#J3!\r!!2mJEIrdLV!F!#J$FK$LV!+%!!!!rb"Yrr3S-%`!kB`L!h3Bj+N#J3!!!2mJEIr\rd)M!F!1f*JS3S!q#-!S3!!!$r)'hrp#J`6!$PM)L")J-#J3!!!2mJEIrdL,!F!#!\r%!S#UN!6LL#B&!S1UN!5'J#!%!S"9N!3L"3+"9C!%dS'#J#J"+J4b%1+Y!S8!!!$\rr)'hrr#S`A!$DK5)%G"MNU3+"!!!!rb"Yrrb+X"`!)J6JL3+"!!!!rb"Yrr`L-"`\r!jBQ#K5S%!S8!!!$r)'hrr#S`A!$RMBU"+!0b%1+X!S3!!!$r)'hrr#J`6!$BK#)\r$G"MNU3+"!!!!rb"Yrrb)X"`!)J2JL3+"!!!!rb"Yrr`L-"`!jBQ#K#J$!S3!!!$\rr)'hrr#J`6!$RM)L"I!"J!!'B*J4b&H1V)J4d#q5TJS-Q(,1$F$mL!h3Bj+R#J#"\rYrrK`2b3$,8$ri(!3i+V%V[rJjBSLEIridm)J+3%!J,!F!()r*!2JLX5"jBSJEIr\ridF+!U!)!FMr#Jq@*)'hrq0("J+J$!,'&*J4b#H1V)J4d&q5TJS-Q(,1$F$mL!h3\r3j+R#J1@*)'hrq0("F$mL!h3Bj+R#J1@*)Qhrq02")#N%!)#S"3"b2b3$i)V%JH@\r+)'hrq0(#J+J'!()r`S2PL5"YrrM4`B#S"`#aK5B&FKAMUb)&G![NUB+$*KbcJh!\rr)J0d'15T`S!JEIriF$mN!be!rq"`%1#Ua+lri1@+)Qhrq02#)#N"!)#`(!"b2b3\r$i)V%JH@+)'hrq0(#J+J#!()r`S2PL5"YrrM4`B#S!`#aK#B&FJRMUb)&G"INUB+\r$*KbcJh!r)J0d%15T`S$PL5"YrrM4`A!r)J0d'15T`S$PL5*YrrM6`5!T"!#!U!8\r!FMmN!q#+a)(PLL"YrrM4`S#S"J"b2m+$jBNJEIridF'!U!F!XB45KR!)[)"Y!2j\rN)!8#J2#3"1L)*J3#Jr#3")D!)!8#J!q3"#)%!S%2N!6TLB+!+!%U"()3iUd#K3!\r!!2mJEIrd+M"F!1Q0)J4d'15T!S%!!!$r)'hrp#)`(!$YLB+&+J6JM3+&!!!!rb"\rYrr3U-&`!jBf+J5)%!S%!!!$r)'hrp)U`(!!S!h)3iU`#K!!!!2mJEIrd+$"-!1Q\r-)J0d'15T!S%!!!$r)'hrp#)`(!$YLB+%+!2JM!+%!!!!rb"Yrr3S-%`!jBb)J5)\r$!S%!!!$r)'hrp)L`(!"*l2q!)!9b'1+S!S!!!!$r)'lrp&+Zrr33J#!&FK$LU!+\r!!!!!rb"Zrr45V[rd%)!J"H#)!S!!!!$r)'lrp&+Zrr33J#!&!S!!!!$r)'lrp&+\rZrr33J#!%FKMLU!+!!!!!rb"Zrr45V[rd%)!J"()3iUJ#J!!!!2mJE[rd8Ulrp"#\r!)!6JL!+!!!!!rb"Zrr45V[rd%)!J"!+!!!!!rb"Zrr45V[rd%)"+VJ!3EJ$ckQ!\r!$0C+VJ!3E`!-cLi$)%G5Kh!!%""b'11S,8$rm#"(8SG`!"!3FK$MU)'Zrr!J4e+\r(F!!3%1')JDlrm#"(8SG`!"!3JDlrm#"(8SG`!"!3FKMMU#e!rq`J4e+(F!!3%()\r3ikL"V[rX)%G5Kh!!%"$KL)'Zrq`J4e+(F!!3%)'Zrq`Z,J!),8Erp#"(8SGk!"S\r3FKMMV5"(8SG`!"!3FK$MU)U!)%G5Kh!!%"$KL)U!)%G5Kh!!%"#+J#"(8SGi!"J\r3FKMMV#"(8SG`!"!3FK$MU)L!)%G5Kh!!%"$KL)L!)%G5Kh!!%"#)J#e&rqJY42r\rN)!3#J+U3"1+)*J8#JkU3")D!)!3#J&@3"#)&!S&9N!65JB+!+!%U"()3iUd#K3!\r!!2mJEIrm+M"F!0U&)J4d'15T!S%!!!$r)'hrr)U`(!!L"1#*!S%!!!$r)'hrr#)\r`(!$PLB+&+J3#K3!!!2mJEIrm+M"F!1H0LS%S!h)3iU`#K!!!!2mJEIrm+$"-!0L\r%)J0d'15T!S%!!!$r)'hrr)L`(!!L!q#*!S%!!!$r)'hrr#)`(!$PLB+%+!-#K!!\r!!2mJEIrm+$"-!1H-L)&*l!#!I!"J!!()*J4b#H1V)J4d&q5TJS-Q*,1$F$mL!q#\r*`S$PL5"YrrM4`A!r`)2PL#*YrrM6`#!T"`#!U!B!FMmN!be!rq"`%1#Ua)(PLL"\rYrrM4`L!S"3#!V[rJFMmN!be"rpab'1+Ua+lrh1@+)'hrq0(#J+J%!,'&*J4b&H1\rV)J4d#q5TJS-Q*,1$F$mL!h3Bj+R#J#"YrrK`2b3$i)V%J1@+)Qhrq02#F$r!Jq@\r))M!F!#"YrrM4`#!S!`#!U3)!G$mY32rJ)!-Y3IrFFK$LU-##jBJJEIridF!J+!%\r!J+lri)#ZrpbaK5B&FJRMUb)&G"INUB+$*L5cJh!r)J2JLF+!jBNJEIridF&`2m#\r$jBJLEIridm!J+3F!J+J'!()r*!-Y32rJF"$JUX5"jBSJEIridF)J+!8!J+lri()\rr*!-Y3IrFFKMLUX5ZrpcPLL"YrrM4`S#S"!#aK#B&FKAMUb)&G![NUB+$*L5cJh!\rr)J0d'15T`S!JEIriF$mN!q#+a)$PLL*YrrM6`R!r`)2PL#)`(!!JEIridF!J+!-\r!J+N#!(3r,8$ri#!$,8(rh()3iUM!JZ@))'hrq0(!)#J"!)#Zrq#!V[rFXB45KR!\r)[)"Y!2id)!8#J2#3"1L)*J3#Jr#3")D!)!8#J!q3"#)%!S%2N!6TLB+!+!%U"()\r3iUd#K3!!!2mJEIrd+M"F!1Q0)J4d'15T!S%!!!$r)'hrp#)`(!$YLB+&+J6JM3+\r&!!!!rb"Yrr3U-&`!jBf+J5)%!S%!!!$r)'hrp)U`(!!S!h)3iU`#K!!!!2mJEIr\rd+$"-!1Q-)J0d'15T!S%!!!$r)'hrp#)`(!$YLB+%+!2JM!+%!!!!rb"Yrr3S-%`\r!jBb)J5)$!S%!!!$r)'hrp)L`(!!J"!+!UT!%iSJQ"3+$UT!%KS!J"!+!9C!%)J8\r#J9@3"0+"JS!S!5S%FK$LV3+&!!!!rb"Yrr`U-&`!fS8L"(3Bj+N#J3!!!2mJEIr\rmLV!F!#)%i)N#J3!!!2mJEIrm)M!F!1@*JS8U"!+&!!!!rb"Yrr`U-&`!jif+J5J\r$FK$LV!+%!!!!rb"Yrr`S-%`!f)3L!h3Bj+N#J3!!!2mJEIrmL,!F!#)$i)N#J3!\r!!2mJEIrm)M!F!1@*JS3S!`+%!!!!rb"Yrr`S-%`!jib)JA`!B!!"Q#B%FKAMUb)\r%G![NUB+$*KZcJh!r)J0d'15T`S!JEIriF$mN!be!rq"`%1#Ua+lri1@+)Qhrq02\r#)#N"!)#`(!"b2b3$i)V%JH@+)'hrq0(#J+J#!()r`S2PL5"YrrM4`B#S!`#aK5B\r%FJRMUb)%G"INUB+$*KZcJh!r)J0d%15T`S$PL5"YrrM4`A!r)J0d'15T`S$PL5*\rYrrM6`5!T"!#!U!8!FMmN!q#+a)(PLL"YrrM4`S#S"J"b2m+$jBNJEIridF'!U!F\r!XB8Q"A)9ikXL"A3,j+Q#JbBEXi0`2b)$G"MNUF+!)'hrq(!r*!-Y32rJF"$JUX5\rZrq$PLL*YrrM6`L!T!3#!X"`!FMmN!q#+a)(PLL"YrrM4`S#S!J"b2m+$jBNJEIr\ridF'!U!-!XB3Q"A)*ikXL"A3Aj+Q#JbBEXi0`2b)$G"$NUF+!jBNJEIridF&`2b)\r$G"MNUF+!jBNLEIridm%J+33!J+J&!()r*!2JLX5"jBSJEIridF+!U!B!FMr#Jq@\r*)'hrq0("J+J(!,'%8SC`#,b!E3$qC#!&!S$`N!6SL#B%!S2`N!5'J#!&!S!2N!3\rL"!+"$j!%kBQ#J#J"+J4b%1+Y!S8!!!$r)'hrp#S`A!$TM5)%G"MNU3+"!!!!rb"\rYrr3L-"`!lBQ#K5S%i)d#K3!!!2mJEIrd+M"F!1@0LS%L"!+"!!!!rb"Yrr5+X"`\r!+!0b%1+X!S3!!!$r)'hrp#J`6!$TM#)$G"MNU3+"!!!!rb"Yrr3L-"`!lBQ#K#J\r$i)`#K!!!!2mJEIrd+$"-!1@-L)%L!`+"!!!!rb"Yrr5)X"`!4q[rJ#!%!S#UN!6\rLL#B&!S1UN!5'J#!%!S"9N!3L"3+"9C!%dS'#J#J"+J4b%1+Y!S8!!!$r)'hrr#S\r`A!$DK5)%G"MNU3+"!!!!rb"Yrrb+X"`!)J6JL3+"!!!!rb"Yrr`L-"`!jBQ#K5S\r%!S8!!!$r)'hrr#S`A!$RMBU"+!0b%1+X!S3!!!$r)'hrr#J`6!$BK#)$G"MNU3+\r"!!!!rb"Yrrb)X"`!)J2JL3+"!!!!rb"Yrr`L-"`!jBQ#K#J$!S3!!!$r)'hrr#J\r`6!$RM)L"4HS!J(`!B!!"b#B%FJRMUb)%G"INUB+$*L+cJh!r)J2JLF+!jBNJEIr\ridF&`2m#$jBJLEIridm!J+3F!J+J'!()r*!-Y32rJF"$JUX5"jBSJEIridF)J+!8\r!J+lri()r*!-Y3IrFFKMLUX5ZrpcPLL"YrrM4`S#S"!#aK5B%FKAMUb)%G![NUB+\r$*L+cJh!r)J0d'15T`S!JEIriF$mN!q#+a)$PLL*YrrM6`R!r`)2PL#)`(!!JEIr\ridF!J+!-!J+N#!(3r,8$ri#!$,8(rh()3iUM!JZ@))'hrq0(!)#J"!)#Zrq#!V[r\rFXB8Q"A)*ikXL"A3Aj+Q#JbBLXi0`2b)$i)R#J1@*)'hrq0("F$r!Jq@))Qhrq02\r!)#N(!)#S"J"b2b3$,8$ri(!3i+V%JH@+)'hrq0(#)#J&!)#Zrq"b2b3$,8(rh()\rBiUV%V[rFjBSJEIridF+!U!3!XB3Q"A)9ikXL"A3,j+Q#JbBLXi0`2b)$G"MNUF+\r!)'hrq(!r*!2JLX5!jBSLEIridm*`2m#$jBJL-"`!)'hrq0(!)#J$!)#T!J"d2be\r!rq!J!be"rpab%1+S`),PL#"YrrM4`#!S!3#!V[rJJ+lrh,'%8SC`#,b!E3$q0#!\r&!S$`N!6SL#B%!S2`N!5'J#!&!S!2N!3L"!+"$j!%kBQ#J#J"+J4b%1+Y!S8!!!$\rr)'hrp#S`A!$TM5)%G"MNU3+"!!!!rb"Yrr3L-"`!lBQ#K5S%i)d#K3!!!2mJEIr\rd+M"F!1@0LS%L"!+"!!!!rb"Yrr5+X"`!+!0b%1+X!S3!!!$r)'hrp#J`6!$TM#)\r$G"MNU3+"!!!!rb"Yrr3L-"`!lBQ#K#J$i)`#K!!!!2mJEIrd+$"-!1@-L)%L!`+\r"!!!!rb"Yrr5)X"`!)#lrm,'&)#lrl,'%F!L`VJ!3E!!!ZP'Z!"!J"A)BiUJ#J!!\r!!2mJE[rd8Ulrp"#!)!9b%1+S!S!!!!$r)'lrp&+Zrr33J#!&i)J#J!!!!2mJE[r\rd8Ulrp"#!)!8#J!!!!2mJE[rd8Ulrp"#!)!4b'1+S!S!!!!$r)'lrp&+Zrr33J#!\r%FK$LU!+!!!!!rb"Zrr45V[rd%)!J"1#)!S!!!!$r)'lrp&+Zrr33J#!%!S!!!!$\rr)'lrp&+Zrr33J#eZrqMrm#eZrq6rl'!!p)JJ,J!3dDlrp#!Z!"!-J!!!!!KL!!$\r!-$X#"Nll!!)!YJ#J!)S!GJ"N!%i!1!!N!")J"!+!!!!!re1Zrr3JE[rd%)!J"1#\r)!S!!!!$r8klrp#"Zrr33J#!%FK$LU!+!!!!!re1Zrr3JE[rd%)!J"()BiUJ#J!!\r!!2p6V[rd)'lrp"#!)!8#J!!!!2p6V[rd)'lrp"#!)!AJL!+!!!!!re1Zrr3JE[r\rd%)!J"A)3iUJ#J!!!!2p6V[rd)'lrp"#!)!9b'1+S!S!!!!$r8klrp#"Zrr33J%c\rI(2K1ANjd!##3!'4PFemcBf*MAf9ZBh*jF(3!!!!U88j@rpK)jam`*Qi!$#4Z!!K\rf!"BDF!!3'Z')KS"`!"!DFK$MU)D!F!!3'R)BikL'J(J!'"T`!"!DiBL)J(!!%"T\rb%11SL)"`!"!DFKMMU)L!,!6SMVH'!SB2N!5pJb!'kBLaK#`$FK,MVVH'!SE-c!!\r!)!1pJ#)'G",NUE'"*J%X"()5ikkjKJ+'c-`!!#!%[B!L"R35j+QaJ5J",!6LMVH\r'!SC9N!5pJb!'d)#aK#`$i)kjKJ+'!2m!rlf%)!EKL,'$,!6LMVH'!SC9N!5pJb!\r'd)#aK#!%!S!!!2m!)J3#J3!!!2pd%1@TJS!J"!+!!2m!!(33j+L!J5)$!S(`!!!\r!k)Q#J#J"!S-2rrrrIJ"J!!(#)'hrI%U`I!"R(L!$FKVMU#)$j)Q#J#B")!4b'Z1\rS)J6NLB+!+!&J(#!$FK[MU#)$iSQ#J#B")!4b'q1S)J6LLB+!+!%#J`rrrrm#K!r\rrrrp`2m#$)'hrH()m*!2ZLX5"FJ-YF!`!rpJJ!qb)`)'!JZ@))'hrH0(!)#J"!)#\rZrpKb-#3$,8(rh()1iUV%V[rFFJmY3[rJ*!-Y32rNF!hJUX5"K+lri1@+)'hrH0(\r#)#J#!)#Zrq4b"L3$,8(rk()9iUV%V[rSFJ%Y3[rX*!-Y32r`F"6JUX5"K+lrl(!\ri)J-Y3[rdG"ENUF+!JUlrp1@*)'hrH0(")#J$!)#Zrr!N3(`m)J6JLF+'I!-N"1k\r+a)D%JH@+)'hrH0(#I$r-K1@1)QhrH02',#N%!)bS"3"b2b3%,8Erp(`2l+V%JH@\r+)'hrH0(#,#J'!)bZrr4b-#3%,8(rm()@iUV%V[r`FJmY3[rX*!3Y4[rSI"AXUX5\r"K+lrl1@+)'hrH0(#,#J(!)bZrqJJ#J+!!!$rrbS'G"$PVBU!)!APL#)&G"lNUG+\r!*X%J"J+!rrm!!#S+G"$NVBU!)!AYL#)&G"VNUG+!*X&5Kh!3[S"Y!2ikF!"-h`c\ri6Pj1G!!)Lf4PFepcCA4IDf9j!!!U88j@rrJ[$5mYrh![,J!-,bi!##*Yrf3J@8k\r3!#TZrr3J,Ip`6Pj1G!!)L@4PFepMFRP`G!!!+P&19[pF51FI2#KZ!!JS,J!-*'i\r!%%IZrqiJ4%S3CJ4`3@!')%33%%R!&)"*`#B!)'hrE(S!'M!i!1@0)%4++!!"CJ4\r`3@!))%33+!!"5F!93!!"5F!Q!#"Yrfam!"``1!$YMRi!B"BB(%S%Cb*`!"!%d)"\r"l[rQ%B"i!&+(F!LqJ'ANB!T"l[rQ3M"i!&+(F!LqJ'A`5'lrANKZrqBLEIpd)&P\r1N!!UE[pB,`B["8KZrej)E[rHBIm!!!$Q*LlrhL!$!S!!!!$r&X!J!q#)!S!!!!$\rr&X!J!h)3iUJ#J!!!!2m@`#!$FKMLU!+!!!!!raE!*LlriL!$!S!!!!$r&X!J!q#\r)!S!!!!$r&X!J!h)3iUJ#J!!!!2m@`#!$FKMLU!+!!!!!raE!I!!@2!#!3LlrpRi\r#B%*i!(S!B#EB"(!!%!0"l[rZFJ!5-'J!`S"R"!!%!!(L#dS$CJC5KKBm!)"5KA!\r'ZS"Pe(!!%!3JEIpS&E!!!(J!8SG`$Ek!CEK#+J!0)!T-haci6Pj1G!!-LQ4PFep\rQBh*jF(3!!!!U88j@rma)j`mB)QhrB(S!I!!SEJ!-,@i!%2r8,@i!&2r33Ulrc'!\r!"%#Abf!!"#JJ"R33j+JN"V'#+!,)V[r8a+lrd#i%FK$MVb!')M5m!,1!XB5rK#i\r#FK$MVb!,8S!L"L!d$!#aJE1#[i)J"1#!,8$rp#i%!SF!!!$m!Ui!!!$mrr3J!R)\rFikJL!ZL*dS!N!A!3i+`J-AJ!XB8J5G(Zrr3J+!)!XB8J"1#),8$rm#i%!SF!!!$\rm!Ui!!!$mrr!J5G(()#J%!,'&)%R4l[r`)#J'!,'&)!,JJ#e!rr3Z!J+(!!!!r!+\rZ!!!!r2rdF"$JUL"*dFFJ+!%!XB8J5G(Zrr3J+!-!XB8J!Z#!,8$rm#i#!SF!!!$\rm!Ui!!!$mrr!J5G(()#J&!,'&)%R4l[r`)#J(!,'&)!9d%15S*!@aJLJ#b+lre-5\rZrp!Z"()3ikmJ#e5!)J8J0!`!XB'cK,q%,J*b%11[)!Y@J#)&)$3-!,'"Xi+rJL!\r%i)!Y32rX,J3#K`!!!2`#VJ!!!2crl#!#FKcMU#)#k)R5J#3"F"$JV#!aH!#aKL"\r*dHlrl#!S!J#aKL!%i)JY32rS,J3#K`!!!2`#VJ!!!2crk#"*dFFJ+!3!XBBJ5G(\rZrqJJ+!B!XBBJ!Z#!,8$rl#i#!SF!!!$m!Ui!!!$mrqa`%1#U)%R4ab!S!3#aKL"\r*dHlrl#!S!`#aKL!#i)!Y32rS,J)#K`!!!2`#VJ!!!2crk#"*dFFJ+!8!XBBJ5G(\rZrqJJ+!F!XBBJ"R33j+JN"V'#+!,)V[r8a+lrd#i%FK$MVb!,@)!L"L!d$!#aJE1\r%[i3Z!R)3ikmJ#eU!)JBJ0!`!XB'cJVq#)!6JJ#e!rq3Z"!+(!!!!r!+Z!!!!r2r\rN)!*b(11S)J,SLG+!*!&`%1#X)$&i!,'&)%R4l[rN)#J#!,'&)!6JL#e!rq!Z"!+\r(!!!!r!+Z!!!!r2rJ)%R4ab!S"!#aK5"*dHlri#!S"J#aK5!#i)!Y32rN,J)#K`!\r!!2`#VJ!!!2crj(!3i+SJ5G(()#J"!,'&)%R4l[rN)#J$!,'&)!,JJ#e!rq!Z!J+\r(!!!!r!+Z!!!!r2rJ)%R4ab!S"3#aK5"*dHlri#!S"`#aK5!&G"$NU#3&XB)S!XL\rZrp6%V[r3,J4b%11[)!YFJ#)&)$3-!,'"Xi5rK#i#FK$MVb!,AS!L"5!d$!#aJE1\r#[i)J"1#!,8$rh#i%!SF!!!$m!Ui!!!$mrp`J!R)FikJL!ZL*dS!N!A!3i+`J-AJ\r!XBBJ5G(Zrp`J+!)!XBBJ"1#),8$rf#i%!SF!!!$m!Ui!!!$mrpJJ5G(()#J%!,'\r')%R4l[rB)#J'!,'')!,JJ#e!rp`Z!J+(!!!!r!+Z!!!!r2rFF"$JUL"*dFFJ+!%\r!XBBJ5G(Zrp`J+!-!XBBJ!Z#!,8$rf#i#!SF!!!$m!Ui!!!$mrpJJ5G(()#J&!,'\r')%R4l[rB)#J(!,''8)Y`),I!E3$le#3&+JBX!P+Zrma`'E#ZrmaZ!2Zk)!9b(H1\rS)JAQLG+!+J%J"R)GikJL"ZD*dS!X!53&iSUpJJ+#9C!%YBBJ!Y#!XB8N"Z#+Zi)\r#JJ$r!2qeK5!#iBLaKL3&j)UpJJ+#-j!%YBBJ!Z@)XB8N"R)3iUUlJJ+#!!$rrl@\r&)!*b%11SXBBN"HL+[B)#JJq3",@')!,TL,'&)'i!###')'i!##&&!!4-haM`6Pj\r1G!!3LfCMFRP`G&pLEf4j!!!U88j@rrK)ja`m+Li!##4Z!!`S,J!3+'i!&#CZ!"J\rQ,J!F5S0R4Lm$,`3[#Lm&)Qhrm#"C6T!!+Qlrp#!$9m"%!%R!,`![$#m+,`SLEIr\r`)&P1N!!UE[rd,`-[#bm+,`SLEIr`)&P1N!!UE[rdB%3[!bm,,`S["5*Yrr!J@8k\r3!#TZrr3J!eI!4!"*`#m!,``[#Lm+)Qhrm#"C6T!!+Qlrp#m$,`3[#Lm+)Qhrm#"\rC6T!!+Qlrp%cI($K1ANjd!"L3!'4PFemcC@0LAf9ZBh*jF(3!!!"PC!dK%)%$"J!\r3!!!3%"!!!"!!%"!3!"!3%!3K%!3K%!)L%"!%)4#"!`X3!"!!%*!&!!!"%!!"!"!\r"%"!"!!!4%!!4!"!4%"!4"L%"!L%"!b)"!3%K!3-K!3%K!3%L!3%#*!'3"!-K!3)\rL!3%")3%")3%"*!'3"!)L!3%"*!'3"53"N!3%)3%%)3%#)J%""#%"!5%"!5%"!L)\r"!3%M!3%"##%%J3-0!3!!!3!%!!3!!!3%!33!!33%!!!J!!!N!3!J!3!N!!3J!!3\rN!33J*!%%*!%$)3%#)`3"!3)L!3%")J3"!5%%!5%"!58%"!%""!%P!3%%"!%#)L!\r"!L-N!3%")b!"!3%L*!%")`3J!3%U"#3"!33J!3%%*)%$$`)!!!)!"!-!!!-!"!)\r%!!)%"!-%!!-%"!)!)!)!*!-!)!-!*!)%)!)%*!-%)#8$"#3"!J)L!3)")`3"!`)\rL!3-"*!3"!J3"*`%#"!3"!`3"*J%$"!3"!J%M)!%#!5-N!3-")b!"!`%a*!%#"#!\r"!J3N!3-%)!%$"#3%)3)&)3J")3)")3J#)3J#)J))!b))#!%M!JJ)"#)"!J)K!3)\rM#!%#!5))!3%K#!%M!3))!5%"!5F)#!%##!J"!L%"J3-(!J!"!!!*!J!*!!J"!JJ\r"!!J*!JJ*!L-"!3)")J%"!L-*!3)")JN"!5F)!3%##!%"!5J)#3%##!N"%!-K%J-\rK%!%K#!%K%J%K#!%L%!J#)K))!L-3#!J")a))#!%K%!)L!4)#)J%3!5-)!4)"*!J\r"%!J")`%5#!%U!4!)#!%5#!J"%!%K!B%$"a)!!4!!#4)!#4!)!4))!4!)#4))#5%\r3!5-"!4)")`%"%!%M#3%5!6)*!4!)!3%5#!%"%!J*!4))#3%&)33%)5##!J3%)"!\r!&!!3)#)8))%$##!!!#!%!#!!)#!%)#!3!#!8!#!3)#!8)!-K#)%$"J3!#!!J#!3\rJ#"!!#"3!#"!J##38)!JJ!L-))!3")JJJ!5JJ##!%)!JJ%!%M##!8!5N))"!J##!\r8)!L"!`FJ!!!N!!!J)!!N)!!`!!!d!!!`)!!L0##"!`JJ)!!J*!!JN!3N)#!`!#!\rd!#!`)#!d)!%K)!%K#)%$"L3!##!J##3J#$!!#$3!#$!J##8d)!JJ)!%M##!N!5X\r))#!J##!N)!JJ-!%M##!d!5N))$!J##!d)!J()K!)J3-r!!!)!"!!!J!!!K!)!J!\r)!K!!!!)!!"))!!))!")!!J)!!K))!J))!K)%!!!%!"!-!!!-!"!%!J!%!K!-!J!\r-!K!%!!)%!")-!!)-!")%!J)%!K)-!J)-!K)!%!!!%"!)%!!)%"!!%J!!%K!)%J!\r)%K!!%!)!%"))%!))%")!%J)!%K))%J))%K)%%!!%%"!-%!!-%"!%%J!%%K!-%J!\r-%K!%%!)%%")-%!)-%")%%J)%%K)-%J)-%K)!!!!#!b%#!L)#!J3K!3%K!J%K!3)\rL!J%")`)#!33L#!)#)3J")3)")`J#!J%K#!)M!3J#!5)"#!%R!J%)!J)"#!%K)!)\rL!L!$)5)#)J)L!b)J!3%M!L!"!L)L!3%M!L)"!L%J!5-)!L!")3J")5)")`J#)J%\rK#!%R)!%)!L!"#!%R)J%)!L)"#!)K!S%$"`)!!J!#N!8!!!-#!!-!!J-#!J-#)`)\r)!J%L!JJ"*`)##!)#!JJ#)`-)!J%L!`J"*`)$#!)#!`J")L!#J3-(!L!#!#)#!L)\r#!#!$!L!$!#)$!L)$!5FJ!JJ#)!))!5FL!JJ#)J))!5FJ!`J#)!-)!5FL!`J#)J-\r)"L%3"#%J!L)3)!%K%!-L%"!#)4!")5!"*"!3)!J$)3J")4!")3J#)L!)!533)!J\r3!L-)%"!")JJ3!58J#"!3))%$"`!!"!!3"!!!*!!3*"!!""!3""!!*#33%#3)!L)\r%#!%M%!3)!L)N#!%N%#3)%!%R"!J3%!3)%!%P*!J3%#5"!`F!"!!!&!!!"#!!&#!\r3"!!3&!!3"#!N%"3J#!%K"!%K#!%K&!%K#!%M"#!)!588)!J3"!%M#"!8!5J)%!3\rJ#"!8))%$"`!%"!!8"!!%*!!8*"!%""!8""!%*#33&#3)!5-%"!J")a3%#!%M"#3\r)!6)8*!J3"!3)%"3%#"!%*!J3&#3%)4!%)3%#)K!""5)#%!)K!J%K!3%M!K!"!5%\r#!L%J!5%3!5%J!L)")!%M%!%J!b-J!K!")L!#!5F")!)3!5!#!5%%J3-(!"!%!!!\r&!"!&!!!%!K!%!J!&!K!&)3)")J3J!5-3"#!#)J8J!5-3"5!#*`3J!K!%)!)"+!8\rJ!K!&)!)J!b%`!b)J!3)L-!%#)5!#)J)`!L-#)!%")`)`!3%L!L!")5!")6!")5!\r")b!")!%M-!%J!5%J!5-J!M!",#!#)!%J!M!")!)J")%$"`!`"!!J"3!`"3!J"!)\r`"!)J"3)`"53#)!3J!5-`"#!")b!&)!%M-!8J!6!J"#!#-!3J!L!&)!)`"5!#"#%\r%"L)""))#$!%"!!8!!3%&!3!3""!!%334!4!&%!%4"5%4!5%)J3-2!!3)!!!)!33\r)!3%)!!8)!!%)!38)!3!)%!3)%!!)%33)%3%)%!8)%!%)%38))4%#)3J")35"!`i\r)!!!)!33)!3%)!!8)!!%)!38)!3!)%!3)%!!)%33)%3%)%!8)%!%)%38L#"%")JJ\r)!5-%#!J#+JJ)!33)#!%"#!J")`8)#!%S!3J)!38)#!%"*`J)%!3)#"!"0`J)%33\r)#"%"#!J3"3J)%!%)#"%&#!J4"b%3JJ)0!!%!%4!!%"!3!4!4!3!"%!%"!4%4!"%\r3%3%L%4'"!bm3!!!3!"!3!!%3!"%3%!!3N!8"%"!4%!%!%!%3%!%"%!%4%"%!%"%\r3%"%"%"%4!3!!!3!3!3!"!3!4!4!!!4!3!4!"!4!4!3%!!3%3!C!&%3%4!!%4%!%\r4!3%4%4%!!"%!%"%!!4%!%4%3!"%3%"%3!4%3%4%"!"%"%"%"!4%"%4%4!"%4%"%\r4!534%4%3J3-2!!!3!"!3!!%3!"%3%!!3N!8"%"!4%!%!%!%3%!%"%!%4%"%!%"%\r3%"%"%#34%4!3!L)3%!%M%"!3!5-"%"!"*"%3%"!",a#3"`%3%"!4%"!"!5m3%!%\r3%"!"!4!3!4%3%"%",K!3%4!3%"%"%"!4%4!"!L)3!3%M%"!"!5-"%!%"*"%3!4!\r",a!"%"!3!4!"%!%3%4!"!3%[%!%"%"!"!3%3!3%4%!%4!5i3!4%3%!%4!4!"%4%\r3%3)L%"%")a!3%3%M!4!4!534%"%3!5m3%4!3%"%3!4!4%"%3%3%",a!4!4!3%3%\r"%"%"%4!4%3%Y%"%4%"!4%3%3%4%4!B%$$`!!!3!3!3!"!3!4!4!!!4!3!4!"!4!\r4!3%!!3%3!C!&%3%4!!%4%!%4!3%N%4%"%!)L!4!")a!"%!%M!3%3!534!4!3!5m\r"%"!3!4!3!3%3%"%"%!%",`%3!4!"%!%"!4!"%3%3%3%Z!4!4%!%3%3%"%"%4!3%\r#)J%"!5-3!3%")`'3"#34!3%3!5m"!4!3!3%3!3%"%"%"N!3[!3%"%!'3"a%"!4%\r",J%"%4!"!4%"!3%4%3%4!L)"%3%M%!%4!5-"!4%"*"%"%4!",`%4%"!"%4!"!4%\r3%3%4!3%[!4%"%!%4!3%"%3%4!4%4!5d"%4%3!4%4!3%4N!5"!`m!!"%!%"%!!4%\r!%4%3!"%3%"%3!4%3%4%"!"%"%"%"!4%"%4%4!"%4%"%4!4%N%4%4%!)L%4!")a!\r4%!%M!4%3!534%4!3!5m4%"!3%4!3!4%3%"%4%!%",a%3!4!4%!%"%4!"%4%3%3%\rZ%4!4%"%3%3%4%"%4%3%#)K%"!5-3%3%")`%4!3%N%4%"%!%[%3%3%"%"%!%4!4!\r4%3%"!5m4!3%3%3%"!4%"!4%4!4%",K%"%4!4!4%"%3%4N!3#)K%4!5-3%4%")`%\r4%3%N%4%4%!%[%4%3%"%4%!%4%4!4%4%"!5m4%3%3%4%"!4%4!4'3"!%X%4%4%"%\r4%3%4N!3%)3)%)3)#)J)#"#%#!5%#!5%#!L)#!J%M!J)#"#)#!J)K!J%K!J%M!J)\r#!5%#!L-#!J)")J)#!5J#N!F"!b%$!b)"!J)L!`)#)3%")3)")3-")3)")`%#!J%\rM!`)#!5%"!L)#!`)M!J%#!5-#!`)")J)"!5-#!J-"+J)#!3)#!J-#!J)")3%#)J)\r"!b%$!L)#!`-L!3)")`)"!J)L!`)")`)$!J)K!3%M!J)"!5%#!5%$!5-#!J-")3)\r"*`%#!J)"!J)"+3-#!J)$!J)"!3)L!`%#)J%$!L)$!`)M!3%#!5-$!3)")`%$!J%\rM!`-#!5)"!3%M!J-"!5-#!3-")`)$!`%a!J%"!J)$!3)#!3-#!J-$!J)#)3'"!`F\r#!!%!!J%#!J%!!!-#!!-!!J-#!J-#)`%#!J%L!3)"*`)"!J)#!3)#)`-#!J%L!`)\r"+!)$!J)#!`)"!5%"J3-(!`!"!3)"!`)"!3!$!`!$!3)$!`)$)3%")`%#!`%V!3)\r"!J%#!`)"!J%")`-#!`%U!`)"!J-#!`)$!J%L!3'"!`F#!3%!!`%#!`%!!3-#!3-\r!!`-#!`-"*`%"!J)"!3)"*`-"!J)$!3)"*`%$!J)"!`)"+J-$!J)$!`)"!3'"!`F\r$!3%"!`%$!`%"!3-$!3-"!j!&)#!"!3%#!`%"!J%$!3)$!`%#!3%$!J-"!`)"!`-\r#!`-$!J-L!3)#)3%")3)")`%#!J%K!3)M!J%#!5)#!3%R!J)"!J)#!3-L!`)#)3-\r")3)")`-#!J%K!`)M!J-#!5)#!`%S!J)$!J)#!`%#)J%$!L-"!3)")`%$!J%L!3%\r")`)"!`%V!J%"!J)"!`)#!3%#)J-$!L-$!3)")`-$!J%L!`%")`)$!`%U!J-"!J)\r$!`)#!`%K!3%M!3)"!5%"!5%$!5-"!J-")3%"*`%#!3)"!J%"*`-#!3)$!J%")3%\r")`-#!3%K!`%K!`%M!`)$!5%$!5F"!J-#!3)$!5N$!J-#!`)$!3%")`%$!3%M!3%\r$!5-"!`-"-`%"!3)"!`%#!3%$!J%$!`)"N!3M!`-"!5-$!3-")`-$!`%a!`%"!J-\r$!3)$!3-#!`-$!J-#)`%"!J%L!3%"*`)"!3)#!3%#)`-"!J%L!`%"*`)$!3)#!`%\r#)`%$!J%L!3-"*`)"!`)#!3-#)`-$!J%L!`-"+!)$!`)#!`-"!5-"!3-"+`%"!3)\r"!3-#!C!%)`-"!`%V!`%"!J-"!`)$!3%")`%$!`%V!3-"!J%$!`)"!`%")`-$!`%\rU!`-"!J-$!`)$!`%R!3%"!J'3"#F$!3%#!`%"!5F"!`%#!3-"!5F$!`%#!`-"!5F\r"!3-#!3%$!5F$!3-#!`%$!5F"!`-#!3-$!5"(!`-$!J-$!`'3"!-"N!3$!3%$!`'\r3"!-"!`%$!3%$!`%$!`-"N!3$!`%"!`%$!3-$!`%$!3%$!`-"!`-"!j!(!5%3!L)\r#%!%L!3)")J3""L%%!5%#!5)%!3%Q%!3"!K!%!53#%!3"!5%3"L%#!L%"!b)"!J-\rL!K!")3%#)`3"!J%K"!)M%!3"!5%3!5)"!J%K"!%K!J)M!3)3!L-#%!3#)4!")`%\r#%!3K"!-Q"!%#%!3"!5)3"!3L!3)%)K!%!5%#"#)3"!)K%!)K!J%M"!%#!53%!3)\r3!5-"!K!")3%$)3%")4!")J%#!b%#!5%%!L%3!L-#%!3$)J3"!5B3"!%#%!3$)`3\r"!J)R!3)3"!%#%!-L%!3)*3%#%!3""583"!%#%!3K"!%K!J)L!3)")33$)33#)4!\r")3%")S##"b'!!L1!JJ+"!aL!J!)!JJ)!!!)!J!!!!J#!JJ#!JJ)!!J#!!J+!J!+\r!!*!%!J!#!S!#!)!#!!##!!##!)#!!)#!!)!#!J#!!S!!!S!!!J#!!J8L!J+"!ad\r!JJ+!!!!!J!#!JJ)!!!+!J!#!JJ#!!!#!!!!!!J#!J!)!J!!!JJ#!!!)!!J!!!!+\r!!J)!JJ+!JJ)!J!+!J!#!!J+!!!)!!J)!JJ+!JJ!!!J+!!J#!!J!&)S!#!L'#"L1\r!J!)#*3%%"!%""5)%!3%L"!3")3%'*!%""!3")3%#)3%")J3%!L)%"!)K"!%K!3)\rN"!%""!%K!3%M"!3""#-""!3'*!3%!3%$)3%#)J%"!5)%!3)L"!%")33"*!%""!3\r")J%%!5)"!3)K!3)K"!%L!33$*33%!3%%!L%"!5%%!b-%!3%")33%)3%")33#)J%\r%!5%"!L-%!3%")33")3%()3%#)3%"*J3%!3%%"!%K!3%K"!)K"!)K!38L"!%")J3\r%!5)""!%K!3)K"!-N"!%""!-K"!%M!3%%!5)"!3%K"!)M"!3"!L%%!5)""!)N!33\r%!3-M!3%%!b-%"!%")33")J%""#1!!33")i!""!)K)3)KJ!%K"!8LJ#!$)J%%J3-\r,!#!%J!!%!!%!J#!%J#%!J#%%!!!%J#!!!!%!!#!%!#!%"5%J!L1!)35"!aq!)35\r!!3#!)33!)!#!!!!!)3!!!35!!3!!)3!!!!5!!!3!)3#!!!#!!3!!)!!!!33!)3#\r!)!5!!3#!)!!!)33!!35!)!5!!!#!!3!!)33!)35!!!5!)3!!)35!!33&)L!%!L%\rK"#%%!5+!!3)LJ#!#)B!")33')L!%!L)""!%LJ#!#*)#!3"!")B!")a"!J!%L%%!\r$)8!"*8!33)"!!50!J%!#)B!")4!')N!3!L*!%!%PJ%!33)!#)8!&)8!")d#!3!)\rKJ!8K%!)K3!)MJ%!3"#&!!5&!!L'!!5%3!b333)"!!5*!J!8L%%!")8!")8!#)4!\r#+%!33)"!%%#!!L&!!5&!!50!J%!$)N!3!5@!3""!J!)K3!NL3"!$)K"!!5&!!50\r!J%!")N#!!b1!3"!")B!")a"!J!%L%%!$*N#!3""!J!)L3)!&)4!")S"!!L'!!5%\r3!L9!%%#!3!%L3)!")4!$)K"!!5&!!L1!3"!%)8!")8!%)4!#*%!33"!#)`J3)!3\rK)!%Q%#!J#"!J"58)%#!J#!%K)!)K%!%K)!)M)#!)!5%J!L%3!L%)!5%J!5))%!%\rK)!%K%!8L)!J&)5!")JJ3!5)J#!)K)!)L)#!")4!")L!)!b-)%#!")`J3)!%K#!8\rQ)#!)%#!J!b)J#!%L)#!")a!J)!%K%!-K%!%K)!3M#"!J!5%)!5)J)!%N%#!J#!%\rK)!3M)!J3!L%)!5%J!L%3!5%J!5%3"5-J#"!#*3J3)#!)!5)J)!%L%#!$*L!J#"!\rJ)!8L%#!")3J$)3J#)5!")K!J!b-J)!J#)5!#)5!")JJ3!5)J#!3M%#!J!5%3"#%\rJ!5))%!%M)!J)!5)))!)K#!)K!J)P#!)))!J$)3J")JJJ!b)J#!3K!J%M)!J#!L3\r)!JJJ!5)##!%M#!))!L-###!#)3J%)b!)!J)K#!)L)!J")3J$)JJJ!5)##!)K!J%\rM)!J#!53J#!))!b)))!JL#!)")L!)!L)J#!%K#!)M!JJJ!5%#!b-###!")3)#)`J\r##!-K#!3M)!J#!5%J!L%)!L3###!)!5%)"#)J#!)M)!J#!L))!J%L)!J%)3)#)3J\r")JJJ"#3)!JJJ!5%#!5)J#!)M)!J#!L%)!5%)!5%)!5)))!3N#!)))!%L!JJ#)J)\r)!b)))!)L##!")3)")L!)!b-)!JJ"*8!)3""!!5&!!b&!!L-)3"!")3J&)a"!#!%\rL%%!")d!33!)S%%!)3""!#%!")8!$)8!")8!#)3J&)a"!#!%K%!%L#%!#)3J")K"\r!!5*!%!3K3!8K3!)P#%!33!J$)3J")K"!!L%3"5))3!-P3""!#%!")N!)"#*!%!8\rP#%!33!J")4!")3J#)8!"*%!33!J#)d!)3!-K3!%L3!J#)8!")8!%*4"!#%!3!5-\r)3"!$)4!#)8!")8!&*8!33!K!!L%)!L&!!L%3!5%)!5)33!%M3""!!L%3!5%)!5%\r3!5))3!8K3!%K3!-M3""!!b*!#!%P%%!)3"!")JK!!53"!C!!#!)q#PCPFQPQH@P\rZCb`JF'aPBA0P)(*P,@9ZG'9b)#9c!MJ+"`G0DA0YBA4MD#!Y)(4bH5"KCf&TEJS\r#)3S"*!(RN!!)!L3"ri$-!LBJ-(JJHb!#)L9i!L)X)!)L)(d#))%!!C!)rT!)(j!\r%$T!%i*!%mC!%!Ii"rJ(q!Ilq!Ii"rJ(q!4rJ(q!1m3lai"rJ(r%1m3i"i!(J!I%\r"mH!"i!(a!I%"(riIrJlq$[lq(riIrJlq$J%I!4m"$J%1(`%I!3i"$J(JrZ$qmIl\rar[lJrZ$qmIla#b%"JJ)&!!%!!3!"!!%!!38K!B)#"3!"!!%!!3!"!!%#)#l5dp6\r9eYIBfGVEh0hHhq$KiZ2NjHERk1RUkqcYlZr`mI,cp2AfprMjq[[mrIlr!5#"&3%\r#!`3&"JF)#3S,"3B(#!N+#``0$Jm3%4)6&"8@&aJC'KXF(4iI)#%L)b3P)#%L)b3\rP*LFS+5SV,#dZ,c!a-M-d06Bh1$Nk1c`p2Mp!38*$4#i[-$%b-c3e0MFi18&#3d4\r&4NG)58T,6%e16e"48P0899CA@&PDB@*MC'9QCfKTDQYXE@j[F(&bFh4eGRGiHAS\r"ri#N#5)3)!-K)!)K%!%K!3-K!3%M%#!"!L)J!3%K%!)K#!-M#"!J!5%)!5%J!5)\r)%!%L!3J#*J%)%#!"#!%N)!%)%!-K)!-L-#!#)L!J!L%`!5%"!5%J!5%"!5-`)!%\r")b!J!3%K-!)L##!#)`J`)!%M##!J!5))-!%M!3JJ!5X"#$!J!3JJ)!%)-!%K#)%\r$"`!!#"!J#!!J#"!!#3!!#4!J#3!J#5%3!5))#!)Q#!J3)!J)!53J#!J3!5)*#!)\rQ#3J3)!N)!53J#3J3!5%)J3-()!!)-#!))#!)-!!*)!!*-#!*)#!*)6!")`J))!%\rV#!J`)!J))#!)#$!")`N))!%V#3J`)!N))#!*#$!%)3)&)5!")3)")5!#)5!#)J)\rJ!b)J)!%M!L!J"#)%!J)K"!)M)!3#!5)J"!%K)!%M"!)J!5%%!5FJ)!3#)#!%!L%\r%J3-(!J!%!!!N!J!N!#!%!L!%!#!N!L!N!L-%"!)")J3%!L-N"!)")L3%!5FJ"!3\r#)!3%!5JJ*!3#)#3%%!-K%J-K%!%K)!%K%J%K)!%L%#!#)K)J!L-3)#!")a)J)!%\rK%!)L"")#)J33!5-J"")"*#!%%#!")`35)!%U""!J)!35)#!%%!%K")%$"a)!""!\r!*")!*"!J"")J""!J*")J*#%3!5-%"")")`3%%!%M*!35!6)N""!J"!35)!3%%#!\rN"")J*!3()3%")35"!`d!!!3"!3!!!3!"!33!!33"!!!#!!!$!!3#!!3$!3!#!3!\r$!33#!33K!`)K!J-L!J%")J3#!L3%!J%"!5%#!5%"!58#!3%%!J%N!33#!3)L!J)\r#)J)$!5-%!J)"*!3#!`%")`)#!3%V!J-""!)#!33#!`J$)3J#)`%)")%$$3!)"!%\r*!!!*!!%*"!!*"!%)!!))!!-)"!))"!-*!!)*!!-*"!)*"#)$#!%K!J%K#!%P!J%\r)"!)"*3J%!J%*!5%#!5%*!58#!3N%!J%P#33#!3J")`)##!%V!J-)"!)##!3#!`N\r")`)##3%U!J-*"!)##33#!`8K%!3K!3)L%!%%)3L"!`S3!!J!!3J3!3J!%!!3%!!\r!%3!3%3!!%!J3%!J!%3JN%"%)"!-L""!#)33")3%")`33!3%K"!)M#!33!5))"!%\rR!3J%%!%)"!%K%!%M""!3!5%%!5%4!5-%%"%")33"*a!)""!3#!3"*K%)""!4#)%\r$$`)!!")!!!)"!")"!!)!#")!#!)"#")"#!)3!")3!!)4!")4!!)3#")3#!)4##8\r5%3J%!J)L"")#)`3#!3%M"")"!5)%!J%M#!35!5`)"!)"#!35!3J%!K!")`35%!%\rM"!)4!5-%%K%"-!3#%!J%%K!)"!)4#!35%3J%)4!%)3%#)K!""5)%%!)K"!%K!B%\r$'333!33J!!!`!!!J!3!`!3!J!!3`!!3J!33`!33!%!!3%!!!%3!3%3!!%!33%!3\r!%333%33J%!!`%!!J%3!`%3!J%!3`%!3J%33`%5%%!L%3!5%3!5%3!L)"%!%M%!%\r3!b-3""!")K!%!5J"%!33!4!%)!%K%!%K-!%K%!%M)!%3!5-`!4!")5!")a!%-!%\rU%!3J!4!%-!%3"!%L%"!")a!3%!)L%4!")a!4%!)R%"!%%"!3"!%U%4!%%"%3"#!\r3%!%M-"!3!5-J%4!")c!4%!%`)"!3"$!3%!3J%4!%-"%3"!3K#!BL#!J#)3J#)33\r")3J")33$)`3)#!%L"!J")3)#)JJ#!b%#!5-)#!)")3J")J)%!5-)!J3#*`)%#!J\r#"!J$)J%)J3-'!!%!!!N)!!N!"!%)"!%!"!N))J3*!5%#!5-"#!)")3%")3)")`N\r)!J%K#3%R!J3"#!)%!3%S!J3*#!)%#3+"!`F!!!S!!!)!#!S!#!)%!!S%!!)%#!S\rN"!J#!J)L#J)#)J)#!5-)#J)"*!J#!J3")`S#"!%T!J)%#!S#"!J#J3-(!!%+!!%\r#!!N+!!N#"!%+"!%#"!N+*!3*!J)")`%+!J%M!3)#!5-*#J)"-3N#!J3"#J)%!3)\r#"!N+!J3*"L%"J3-'!!J!!!J"!3!!!3!"!3J!!3J"!b%3!L)"%!%K#!%K%!%N#!%\r3!3)L%!%"*!%3!3J"*4!"#!%3!5%J!b)J!B%$"J!S!!!S!3%J!!%J!3%S!!%S!3%\rK)!%K%!%M)!%3!5%S!5%3!58S!4!")!%R%!%J!4!"+!%P%!%S!4!#)3+"!`F!!!-\r!#!)!#!-"!!)"!!-"#!)"#!-#)J)3!L)$%!%M#!)3!53)!a!"!5-#%!%"+J-3!3J\r#%!%)!a!")L!#J3-(!#!$!#J#!#J$!5!#!5!$!5J#!5J$!5-J!K!")b!$%!%M+!)\r3!6-S!a!")!)3!5!$%!%S!K!"+!-3"#%%"#%%!L)%"!8L!J3#)3)")33")`)%"!%\rK!J)K)!%K"!%K)!)L"#!")`3%)!-M)!)%!5)J!J%R"#!#"!3J!J-L)!3#)5!")33\r")b!%"!%K)!-L)J3#)5)")33")b)%"!%K)J)M)#!%!5)J)!%R"#!J"!3J)!)M)#)\r%!5)J)J%R"#!L"!3J)J)K#!%K"!%K#!)L"!J")`3%#!-M#!)%!5))!J%R"!J#"!3\r)!J)K+!%K"!%K+!)L"#J")`3%+!-M+!)%!5)S!J%R"#J#"!3S!J)M##!%!5)))!%\rR"!JJ"!3))!)M##)%!5)))J%R"!JL"!3))J)M+#!%!5)S)!%R"#JJ"!3S)!)M+#)\r%!5)S)J%U"#JL"!3S)J))#!)K#!)K!J)Q!J))#!)#"#-)#!)")3J")J)#!L%#!5B\r)#!)##!J")J))"#-)!J)")`J#!JJK#!%K!J%K#!8L!J)")3J#)JJ)!5B##!J#!JJ\r%)`J#!J%K#!3K!J)K#!)L#!J")J))!5%#!L%)!5%#!53)!J))!5%###8##!J#!J%\rK#!)K#!%N!J))#!)K#!3M#!)#!5%)!5)##!%K!J)K#!)L#!J")3)#)3)")`J)!J-\rL!J)#)`)##!)N!JJ)!J%L#!J")J))!L%#!5-)!J)&)JJ#!5%)!5%#"5%)!L%#!b%\r#!58)!J))#!3M!J))!5%#!L%)!LF)#!*!%)!3"5)3J!%L3"!#)8!#)4!#)i!33!%\rKJ!)L%)!$)B!")N!3!5%3!b)33!%KJ!)K%!%N%%!3J!%L3"!&)4!")4!#)8!"*)!\r33"!")4!#)B!#*"#!%%!))4!")K"!!5+!%!%Q%)!33"#!!5&!!L)33!3K%!3QJ""\r!%)!3!5%3!5333"#!!5&!!5'!!LF3J""!%)!3!5%3!5)33!)K%!3K3!8LJ"!")4!\r#)N!3!5%3!L'!!5&!"#33J""!!5@!%%!3J!-KJ!8K3!)K%!-P%%!3J"!")K#!!5*\r!%!)L3"!")4!")4!%)i!33!%KJ!%K3!%LJ"!$)a"!%!-L%)!")33#*!%%"!%$)3%\r")33")J%"!5%%!5)""!-K"!%L!3%")J3"!5%%!5%"!L%%!L)%"!8P!33%!3%#)J%\r"!b-""!3")3%&)33"*!%%"!%$)3%$*J%""!3"!3%K"!)K"!)M!33%!5)""!%K!3)\rP"!%""!3$)J3""5%%"#B%!3%%"!%$)3%%)3%")33%)J%"!5%%!5-""!3#)33")J%\r""#-%"!%#)J3"!5)%"!%K!3%K"!%L!33$*!3%!3%$)3%"*!3"!33#)J%%!b3%"!%\r"!5%%!L%%!5%"!5%%!5)"!3%L"!%")33")3%&)J3%!5%"!L-"!33#)3%")`3"!3)\rK!3%L"!3$*%!3#"!")4!%*3J33"!)"#)33!)K%!%L%!J")8!"*!J33"!")4!#)JJ\r3"5-3#"!#)3J")d!3#!%K3!)K%!-L%%!")3J")N!3!b%3"#%)!5*!%!%K%!%N%!J\r33!3K%!-L%!J&)8!"*!J33"!")4!")4!")K"!!58)%%!3#!%K3!)L%%!")3J#)K!\r)!5&!!L%3!L%)!5*!%!%K%!%K%!3M#""!!L%3!5)3#!BK%!)K3!%K#!3L%%!"*!J\r33"!$)4!")4!$*""!%!J")d!3#!%K3!)N%%!3#!-L#"!")4!#)d!3#!%K3!%K#!%\rL3"!")K"!!L%3!5)3#!)M%!J3!b%3!L3)%%!3!5%)"#%""#%%!5B)!33J#!%")L!\r)!5%%!L8""#!)!3-K!38L)!J#)5!")J%%!5%)!53%)!J"!53J#!%%"L)""!%K#!3\rK!3%K)!)M"#!)!5%%!L-""#!%)3J#)5!$)L!)!5B%)!J""#!")3%")b!)!33K"!-\rP"#!)!33")`J""!%K#!%L"#!")3%")b!)!3-K!38L)!J#)L!)!5%%!5%)"#)""!%\rN#!%%)!8N!33J#!8K"!)K!3%L)!J")J3J!L%%"5B)!33J#!%"*#!)!33$)J3J!5%\r"!b)""!%L#!%")L!)!5%%!b)%)!-K)!%P!33J#!%#)3J#)L#!!L&!!5%J!5&!"#1\r!)#!#)5!")8!#)5!")B!")L"!!5%J"#BJ3)!J)%!")L!J!5'!!b'!!5%J!5'!!L0\r!J#!$)b!J3!%K)!)KJ!%N)%#!)!%K3!BK)!3N3)!J)!%LJ#!"*d#!)#"!J#!#)B!\r&)L"!!b&!!5)J)!)N)#"!J!%K)!-M)%#!!b'!!5%J!LBJ)%#!)#!#)5!")8!%)B!\r")5!")B!&)5!")S!J!5&!!5%J!b%J!59!J#!J3!%L)#!%*8#!)#"!!5)J)!)K)!)\rKJ!%M)%#!!L0!J#!$)b!J3!BK)!%KJ!)L3)!"*5"!J#!J!5+!)!3L)%!$)d#!)!%\rK3!)K3!-K!J%K!B%$(3)!!3!%!8)%!%!%!%)!N!3"!!!"!J3!!J3"3!!!!!3"3J!\r"3!!!!J3"!J3!3!!!3!3"3J3!!!!"!J!"!!3!3J!"3!3!3J3"3J!!!!3!3J3"3!3\r!!J!""#0#"!'"!`T!!!&!"!!#"!"!!!!#!!%!!!&!"!%#"!"#"!"#!!!%)3)")3'\r"!a)!"!!!"!%#!*!%!3)%!3)!!%)!!!)%!%!!!8)%!3!!!8)!!!!%!%!%!8)%!3!\r%!8)!!8!!!#4!"##!J3-HJ###!!!#J!!!!#!#!!#!J##!!###J!!!J#!!!!##!!!\r#J!##J#!#J#!!J##!!!!#!!##J!#!J#!#!###J#!!J!#3"))!)!!!!)!!)!+!))#\r!!)!!!!)!)))%)B!")B!$)3)#)5!#)i!JJJ%KJ!%K!J%LJ#!))B)#)L#!!51!)!)\r")i!J!J-KJ!%MJ###"5'!!5'!J3-*J#!#!###J!#!!##!!#!!J!##!!!#J#!#J##\r!"#1!))+"!`F!!)+!!!!!)!!!))#!!!)!!)+!!!!!J@%L,(L#!LXXJ#b),@JLVLb\rB'QJCk#Xq,+JDVKQS,,JC+"NN'5!C("N8,-JXd"N''1`Bc#Xk,2!Xq#d!+V)UZLd\r3,4JY)!6'!-B!TJ"Q!#B!"Ld`,6JY3!c'%-B)aJ!J)Mmm!5-'UI!#)[rp%L)X3))\r#2J!`,%!!!La!8p`X3%dN,%"-lLa!5I3X3$"5,%![pLa!,eBX3#i`,%!XDLa!+rB\rX3#VX,%!TS#a!+5BX3#MH,%!SK#a!*k)X3#G',%!Qi#a!)fBX3"M8,%!ATLa!&U3\rX3"#F,%!,9La!!-)X3!#8,%!!6#a!+j!!9+S"5!$3'5)#!3%K#!3L-!%")3J%*%`\r"!3J%)T3"!5%)"#(#"L8Qi!%J#!-P*dB")!J$)bHL!3%K)!-P+)3"!3J$)LMH!L%\r)!b8T*J%"#!-L+D!")[m)!b)UEJBP+Z`"la!$*L[frrrXKJ)Q,'Vrrqc)!LBZ-2r\rrl-i#*5p@!@%)!b8[pJ&K#!-L-&)')dcZ!3%K#!-Q656rrqjS!L*1`!BP8p`"j`J\r$)P5U$2q3"!#3"`%!!#eJ!!!!!3!!,9J!!!!$!!!!%!!!!!%!!!$-!!!!h!!!!fJ\r!!!!%!!!!'J#3$`d!N!YQ!*!,!J!!!!d!N!HM!*!,!3!!!!m!N!3"!!!0!J!!&3)\r!!"X#!!!L!J!!+`)!!$)#!!!j!J!!2`)!!%B#!!",!J!!8J)!!&F#!!"I!J!!H3)\r!!)m#!!#`!!%!N!8(!*!%S!!V8%S23LZ!0dBG3J!!!%e*9&qP68P83daTBJ"IAfC\rTE'9c!'CRCA4c!("bD@jdCJ"ME'9KFQ9bFJ"QCQaeFfJ!Fh4bBfKb!(0bB@jN!(0\rdFQ0YF!"bB@jN!'ePE@0YF!"dD@eP!'C`FQPZG'B!E@9YFf9d!%e*9&qP68P88R9\rZG'PYC8aTBJ"IAh9ZFQ9RDA0dCA*ICR*KCfePER3!AepbC@GTFh4PFPpQFQ&RE@9\rZG!"*ER4PFQCKBf9-D@)!9'PMDd0[G@jd!'4PFepNC@*eC`"NCA0IFQ9KC&p`BA0\rcGfpbC!"NCA0IFf9dAh0PFA9PEQ0PAfjeE@*PFJ"NCA0IFf9dAfYPH3"NCA0IDA0\rIGf9KDepVCAN!C'9cAh0dFQPZCepdEepVCAN!C'9cAfjPGepbB@jNEfeIDf9j!'4\rPFepMBQa[BfYIF(*TER4ICQPXC3"NCA0ICQ0bHA"d!'4PFepMD'9MDepVCAPIF'&\rbDA4j!'4PFepQDAKeF&pVCAPIF'&bDA4j!'4PFepbB@jNEfeIDf9j!'4PFepMFRP\r`G!"NCA0IFQ9KC&p`GepcG(*TEQF!C'9cAfPZDA4IFQ&ZC'pYAfjeE@*PFPpRC@j\rPFQ&dEh)!C'9cAc0PBf*IC@jMFRP`G!"NCA0I-f0LBepPEQ0bHA"d!'4PFepcCA4\rIFQ&ZC'pYAfGPEQ9bBA4[FPpcC@9N!'4PFepVCAPIFf0SC@3!C'9cAh&eB@4IBfY\rcG@d!E@&VC9pVCAPIFf0SC@3!C'9cAf9MBPpPEQ0bHA"d!'4PFepMBQ0IC@jMFRP\r`G!"NCA0ICf9ZCA*KG'9IFQ&ZC'pYAf*XEf0V!'4PFep`Bf*MAf9ZBh*jF(3!C'9\rcAf0LBepMDh0eE3#3"J`!!!!-!!-!"!!'!!3!"`!-!!J!"!!,!!3!$!!!!!d!#!!\r0!"!!$`!)!"-!!!!9!!J!&3!!!"F!$!!A!!P&c3!4Ne3!&qjR!!X54J!2A8B!%@Z\rE!"+dQJ!92mJ!#SY3!"5G&!!8G43!$TIE!!P&F!!5*$S!)-,&!""&S!!38U!!(A6\r'!!e6#J!1K8m!$SX,!!pR`3!2I-%!'4$K!"!kT3!0A`m"!!#k!!!UVJ!"!J!!a!!\r!,0J!!3)!!0B!!#ci!!%#!!$Z!!!XU!!"!J!!qJ!!,,J!!3)!!3S!!#c)!!%#!!%\rF!!!Y%!!"!J!",`!!,-!!!3)!!88!!#bB!!%#!!&3!!!Y-!!"!J!"C3!!,6J!!3)\r!!AS!!#cJ!!%#!!'*!!!XS!!"!J!"N`!!,0!!!3)!!DB!!#d)!!%#!!((!!!XN!!\r!!3)!!GJ!!#b`!!%#!!(T!!!Y!!!"!J!#"`!!,4J!!3)!!K8!!#cS!!%#!!)N!!!\rY)!!"!J!#-`!!,8!!!3)!!N-!!#e3!!%#!!*6!!!Xm!!"!J!#E3!!,5J!!3)!!Ri\r!!#e)!!'Y-`!!!3!!!!&F!!!!A!!!!$)*H6d`1`S*G6d`H$J`1`S*BQ*E1&dp-$X\r+#@C[FL!SD6db1b"T2$%c1b"T+bXT#JN*H`S*#@-p-$X+#3PQEh)J+'Sp-$XJDM`\rf1b"U+bXT#JN*#AX+#3N*Bc`m26%l#JN*#@PQ)#KLBPYjA5!Q)(8T)'0m26%l#JN\r*#A8q2Mda1`S*#3PTCL!S)A8T#JQ3"(X+#C!%H5XV1`S*N!4e26"i1$!l#JQ3"(d\r+#3N*I3S*#A*PG&YTA6eMEhCI-Q0SBA*EBedl#JN*I3S*FQ9d@c%cA6dRA$!R1`S\r*FQ9dGA*Z+(*PG#Nl#Rd+#Jb+D!!!!&J!N!X"!*!6!@df1'X!N"-"!*!41!Y0594\rIT@4PFfaTBJ#3"!%!!!!"A!!!!&`!!!!b"Q)H3&b+!!!!(!!b!!"MCR*R!!!!#J!\r!rrm!N!Kaa!:\r
\ No newline at end of file
diff --git a/src/mac/libraries/DES/bin/deslib.68K.debug b/src/mac/libraries/DES/bin/deslib.68K.debug
deleted file mode 100644 (file)
index 92bb24e..0000000
+++ /dev/null
@@ -1 +0,0 @@
-(This file must be converted with BinHex 4.0)\r:%'4PFfaTBLif1%XZC'9LG@F!FfKXBMq3"!#3")8m!!!"NUpB5Qpj)A"PCQCY0MK\rV!!!!!E*@K4N!N!d$!!)!N!j8UJ!!9+S!!&5U!!!!P!!"!J#3"!8!N!BZB!!!,Q!\r!!#VF!!"93!)"!J#3"!i!N!i&)!!!J"`%!3)!6@&TEJ!P369AEh*XC!"-Ef&NCA)\r!N!41G5T46PErq#m0)!d[!#mYre`LEIp))&P1N!!UE[rd+d$r$'(rN!6FF!"1ANj\rd!!3U88j@rrJ[$5mYr``LEIp%)&P1N!!UE[rd6Pj1G5T46PErq%MR%!4f!#mZ!!J\rLEIpB)&P1N!!UE[rd0J!`!dM!C`3`!f!#-!-Q(djH6R3!"*0IAfPZDA4TB@aTHQ9\rIC'9cE'PL!!!U88j@rrJ[$5*Yre3J@8k3!#TZrr41ANjeNPpIG'9bE@PZBA4PAf4\rPFfaTBJ!!!#T46PEri%MR(cJX,J!)*Li!$#iZ!"!SEJ!B*'i!&%UZ!"aR!!8@*Na\rk!"SEFKMMVA!!%"Yb%11SLS"`!"!EiBL+J(!!%"Z+J(J!'"Yb'11XF!!3'h)3ikL\r)J(!!%"[KL)L!F!!3'iL!*NBS3f!!"-*`#,k!EAT`!"!E!S!!!!$rFKMMU,'&F!!\r3'`+!!!!!rh)3ikLaKA!!%"X#J!!!!2rKL,'&F!!3'`+!!!!!rl'&F!!3'`+!!!!\r!rh)BikLaK(!!%"X#J!!!!2pb%11SXB4`!"!E!S!!!!$riBLaK(!!%"X#J!!!!2q\raK&'(B!!!NYI()!F-J!!!!!GL!!##-$X#"Nll!!)!H!"S!&J!5J!q!#i!(J!3F!!\r3)`+!!!!!rq')XB4`!"!M!S!!!!$rFK$MU,'%F!!3)`+!!!!!rh)BikLaK(!!%#-\r#J!!!!2qaKA!!%#-#J!!!!2rKL,'&F!!3)`+!!!!!rh)3ikLaKA!!%#-#J!!!!2p\rb'11SXB9q!#!%!S#UN!6LL#B&!S1UN!5'J#!%!S"9N!3L"3+"9C!%dS'#J#J"+J4\rb%1+Y!S8!!!$r)'hrr#S`A!$DK5)%G"MNU3+"!!!!rb"Yrrb+X"`!)J6JL3+"!!!\r!rb"Yrr`L-"`!jBQ#K5S%!S8!!!$r)'hrr#S`A!$RMBU"+!0b%1+X!S3!!!$r)'h\rrr#J`6!$BK#)$G"MNU3+"!!!!rb"Yrrb)X"`!)J2JL3+"!!!!rb"Yrr`L-"`!jBQ\r#K#J$!S3!!!$r)'hrr#J`6!$RM)L"I!"J!!'B*J4b&H1V)J4d#q5TJS-Q'V1$F$m\rL!h3Bj+R#J#"YrrK`2b3$,8$ri(!3i+V%V[rJjBSLEIridm)J+3%!J,!F!()r*!2\rJLX5"jBSJEIridF+!U!)!FMr#Jq@*)'hrq0("J+J$!,'&*J4b#H1V)J4d&q5TJS-\rQ'V1$F$mL!h33j+R#J1@*)'hrq0("F$mL!h3Bj+R#J1@*)Qhrq02")#N%!)#S"3"\rb2b3$i)V%JH@+)'hrq0(#J+J'!()r`S2PL5"YrrM4`B#S"`#aK5B&FKAMUb)&G![\rNUB+$*KUcJh!r)J0d'15T`S!JEIriF$mN!be!rq"`%1#Ua+lri1@+)Qhrq02#)#N\r"!)#`(!"b2b3$i)V%JH@+)'hrq0(#J+J#!()r`S2PL5"YrrM4`B#S!`#aK#B&FJR\rMUb)&G"INUB+$*KUcJh!r)J0d%15T`S$PL5"YrrM4`A!r)J0d'15T`S$PL5*YrrM\r6`5!T"!#!U!8!FMmN!q#+a)(PLL"YrrM4`S#S"J"b2m+$jBNJEIridF'!U!F!XB4\r5KR!)[)"Y!2jN)!8#J2#3"1L)*J3#Jr#3")D!)!8#J!q3"#)%!S%2N!6TLB+!+!%\rU"()3iUd#K3!!!2mJEIrd+M"F!1Q0)J4d'15T!S%!!!$r)'hrp#)`(!$YLB+&+J6\rJM3+&!!!!rb"Yrr3U-&`!jBf+J5)%!S%!!!$r)'hrp)U`(!!S!h)3iU`#K!!!!2m\rJEIrd+$"-!1Q-)J0d'15T!S%!!!$r)'hrp#)`(!$YLB+%+!2JM!+%!!!!rb"Yrr3\rS-%`!jBb)J5)$!S%!!!$r)'hrp)L`(!"&k[q!)!9b'1+S!S!!!!$r'-!J"A)3iUJ\r#J!!!!2mB`#!&i)J#J!!!!2mB`#!&!S!!!!$r'-!J"()BiUJ#J!!!!2mB`#!%FK$\rLU!+!!!!!raM!)!6JL!+!!!!!raM!)!3#J!!!!2mB`%U(EJ$l2'!!"6j+Kfi'F!"\rJ!!8f*Na`!"!EFKMMU#e!rr4`!"!EFK$MU)'Zrr4`!"!EiBL"V[rdF!!3'i'Zrr4\r`!"!EFKMMU#e!rr"`!"!EFK$MU)'Zrr"`!"!EiBL"V[r`F!!3'i'Zrr!Q4LK$HJ!\rD'h)Bike`!"!EFK$MU)U!F!!3'q')LS"`!"!ELS"i!"JEFKMMV(!!%"Yb%11SL)"\r`!"!EiBL)J(!!%"Z)J#e&rq`Y42rS)!3#J+U3"1+)*J8#JkU3")D!)!3#J&@3"#)\r&!S&9N!65JB+!+!%U"()3iUd#K3!!!2mJEIrm+M"F!0U&)J4d'15T!S%!!!$r)'h\rrr)U`(!!L"1#*!S%!!!$r)'hrr#)`(!$PLB+&+J3#K3!!!2mJEIrm+M"F!1H0LS%\rS!h)3iU`#K!!!!2mJEIrm+$"-!0L%)J0d'15T!S%!!!$r)'hrr)L`(!!L!q#*!S%\r!!!$r)'hrr#)`(!$PLB+%+!-#K!!!!2mJEIrm+$"-!1H-L)&&kJ#!I!"J!!()*J4\rb#H1V)J4d&q5TJS-Q)V1$F$mL!q#*`S$PL5"YrrM4`A!r`)2PL#*YrrM6`#!T"`#\r!U!B!FMmN!be!rq"`%1#Ua)(PLL"YrrM4`L!S"3#!V[rJFMmN!be"rq4b'1+Ua+l\rrj1@+)'hrq0(#J+J%!,'&*J4b&H1V)J4d#q5TJS-Q)V1$F$mL!h3Bj+R#J#"YrrK\r`2b3$i)V%J1@+)Qhrq02#F$r!Jq@))M!F!#"YrrM4`#!S!`#!U3)!G$mY32rN)!-\rY3IrJFK$LU-##jBJJEIridF!J+!%!J+lrj)#Zrq#aK5B&FJRMUb)&G"INUB+$*L+\rcJh!r)J2JLF+!jBNJEIridF&`2m#$jBJLEIridm!J+3F!J+J'!()r*!-Y32rNF"$\rJUX5"jBSJEIridF)J+!8!J+lrj()r*!-Y3IrJFKMLUX5Zrq$PLL"YrrM4`S#S"!#\raK#B&FKAMUb)&G![NUB+$*L+cJh!r)J0d'15T`S!JEIriF$mN!q#+a)$PLL*YrrM\r6`R!r`)2PL#)`(!!JEIridF!J+!-!J+N#!(3r,8$rj#!$,8(ri()3iUM!JZ@))'h\rrq0(!)#J"!)#Zrq5!V[rJXB45KR!)[)"Y!2id)!8#J2#3"1L)*J3#Jr#3")D!)!8\r#J!q3"#)%!S%2N!6TLB+!+!%U"()3iUd#K3!!!2mJEIrd+M"F!1Q0)J4d'15T!S%\r!!!$r)'hrp#)`(!$YLB+&+J6JM3+&!!!!rb"Yrr3U-&`!jBf+J5)%!S%!!!$r)'h\rrp)U`(!!S!h)3iU`#K!!!!2mJEIrd+$"-!1Q-)J0d'15T!S%!!!$r)'hrp#)`(!$\rYLB+%+!2JM!+%!!!!rb"Yrr3S-%`!jBb)J5)$!S%!!!$r)'hrp)L`(!!J,[rdXB8\rJ,[r`XB4`#,k!EhC4Kb!&FKMLU!+!!!!!raM!)!9b%1+S!S!!!!$r'-!J"H#)!S!\r!!!$r'-!J"3+!!!!!raM!)!4b'1+S!S!!!!$r'-!J"()3iUJ#J!!!!2mB`#!%i)J\r#J!!!!2mB`#!%!S!!!!$r'-!YE[rXrr3YE[rSrr"J!2ZffFFJ"`b!!!!!#')!!)!\r`1`)'6[X!!J"f!'J!@J"1!%3!0J!S!"`!%L!%!S!!!!$r'3!J"1#)!S!!!!$r'3!\rJ"()3iUJ#J!!!!2mC!#!%FKMLU!+!!!!!raN!)!8#J!!!!2mC!#!&i)J#J!!!!2m\rC!#!&FK$LU!+!!!!!raN!)!9b'1+S!S!!!!$r'3"`!%cI(2K1ANjd!"L2C'9cAf0\rLBepPEQ0bHA"d!!!U88j@rr4)jami+'i!&#CZ!"Kk!"SEFKMMVA!!%"Yb%11SLS"\r`!"!EiBL+J(!!%"Z+J(J!'"Yb'11XF!!3'h)3ikL)J(!!%"[KL)L!F!!3'iL!*Qi\r!##iZ!""J!!4JF!LqJ'ekF!!3'`+!!!!!rh)BikLaKA!!%"X#J!!!!2pb%11SXB9\r`!"!E!S!!!!$riBLaKA!!%"X#J!!!!2qaKA!!%"X#J!!!!2pb'11SXB4`!"!E!S!\r!!!$rFK$MU,'%F!!3'`+!!!!!rq')XB4`!"!E!S!!!!$rXB44Kf!!!*,Aab!($)!\r!!!!(BJ!!JM!l!JC1q`!#!(J!D!"B!%S!2J!Z!"i!%(!!%#-#J!!!!2rKL,'%F!!\r3)`+!!!!!rh)3ikLaK(!!%#-#J!!!!2pb'11SXB4`!"!M!S!!!!$rXB9`!"!M!S!\r!!!$riBLaKA!!%#-#J!!!!2pb%11SXB9`!"!M!S!!!!$rFKMMU,'&IJ!N6#!%!S#\rUN!6LL#B&!S1UN!5'J#!%!S"9N!3L"3+"9C!%dS'#J#J"+J4b%1+Y!S8!!!$r)'h\rrr#S`A!$DK5)%G"MNU3+"!!!!rb"Yrrb+X"`!)J6JL3+"!!!!rb"Yrr`L-"`!jBQ\r#K5S%!S8!!!$r)'hrr#S`A!$RMBU"+!0b%1+X!S3!!!$r)'hrr#J`6!$BK#)$G"M\rNU3+"!!!!rb"Yrrb)X"`!)J2JL3+"!!!!rb"Yrr`L-"`!jBQ#K#J$!S3!!!$r)'h\rrr#J`6!$RM)L"I!"J!!'B*J4b&H1V)J4d#q5TJS-Q'V1$F$mL!h3Bj+R#J#"YrrK\r`2b3$,8$rp(!3i+V%V[rdjBSLEIridm)J+3%!J,!F!()r*!2JLX5"jBSJEIridF+\r!U!)!FMr#Jq@*)'hrq0("J+J$!,'&*J4b#H1V)J4d&q5TJS-Q'V1$F$mL!h33j+R\r#J1@*)'hrq0("F$mL!h3Bj+R#J1@*)Qhrq02")#N%!)#S"3"b2b3$i)V%JH@+)'h\rrq0(#J+J'!()r`S2PL5"YrrM4`B#S"`#aK5B&FKAMUb)&G![NUB+$*KUcJh!r)J0\rd'15T`S!JEIriF$mN!be!rr4`%1#Ua+lrp1@+)Qhrq02#)#N"!)#`(!"b2b3$i)V\r%JH@+)'hrq0(#J+J#!()r`S2PL5"YrrM4`B#S!`#aK#B&FJRMUb)&G"INUB+$*KU\rcJh!r)J0d%15T`S$PL5"YrrM4`A!r)J0d'15T`S$PL5*YrrM6`5!T"!#!U!8!FMm\rN!q#+a)(PLL"YrrM4`S#S"J"b2m+$jBNJEIridF'!U!F!XB45KR!)[)"Y!2jN)!8\r#J2#3"1L)*J3#Jr#3")D!)!8#J!q3"#)%!S%2N!6TLB+!+!%U"()3iUd#K3!!!2m\rJEIrd+M"F!1Q0)J4d'15T!S%!!!$r)'hrp#)`(!$YLB+&+J6JM3+&!!!!rb"Yrr3\rU-&`!jBf+J5)%!S%!!!$r)'hrp)U`(!!S!h)3iU`#K!!!!2mJEIrd+$"-!1Q-)J0\rd'15T!S%!!!$r)'hrp#)`(!$YLB+%+!2JM!+%!!!!rb"Yrr3S-%`!jBb)J5)$!S%\r!!!$r)'hrp)L`(!"&k[q!5SGZ!2ZH*Qi!$#!&FKMLU!+!!!!!raE!)!9b%1+S!S!\r!!!$r&X!J"H#)!S!!!!$r&X!J"3+!!!!!raE!)!4b'1+S!S!!!!$r&X!J"()3iUJ\r#J!!!!2m@`#!%i)J#J!!!!2m@`#!%!S!!!!$r&X!J"%cI(2K1ANjd!"50C'9cAf0\rLBepMDh0eE3!!+P&19[r`51FH-#CZ!"!NEJ!)HJ!D'R)Bike`!"!DFK$MU)U!F!!\r3'Z')LS"`!"!DLS"i!"JDFKMMV(!!%"Tb%11SL)"`!"!DiBL)J(!!%"U)J#!%!S#\rUN!6LL#B&!S1UN!5'J#!%!S"9N!3L"3+"9C!%dS'#J#J"+J4b%1+Y!S8!!!$r)'h\rrr#S`A!$DK5)%G"MNU3+"!!!!rb"Yrrb+X"`!)J6JL3+"!!!!rb"Yrr`L-"`!jBQ\r#K5S%!S8!!!$r)'hrr#S`A!$RMBU"+!0b%1+X!S3!!!$r)'hrr#J`6!$BK#)$G"M\rNU3+"!!!!rb"Yrrb)X"`!)J2JL3+"!!!!rb"Yrr`L-"`!jBQ#K#J$!S3!!!$r)'h\rrr#J`6!$RM)L"5Ui!&'F!!D`N5h`!B!!"Q#B%FKAMUb)%G![NUB+$*KUcJh!r)J0\rd'15T`S!JEIriF$mN!be!rr"`%1#Ua+lrm1@+)Qhrq02#)#N"!)#`(!"b2b3$i)V\r%JH@+)'hrq0(#J+J#!()r`S2PL5"YrrM4`B#S!`#aK5B%FJRMUb)%G"INUB+$*KU\rcJh!r)J0d%15T`S$PL5"YrrM4`A!r)J0d'15T`S$PL5*YrrM6`5!T"!#!U!8!FMm\rN!q#+a)(PLL"YrrM4`S#S"J"b2m+$jBNJEIridF'!U!F!XB8Q"A)9ikXL"A3,j+Q\r#JbBDXi0`2b)$G"MNUF+!)'hrq(!r*!-Y32r`F"$JUX5Zrr$PLL*YrrM6`L!T!3#\r!X"`!FMmN!q#+a)(PLL"YrrM4`S#S!J"b2m+$jBNJEIridF'!U!-!XB3Q"A)*ikX\rL"A3Aj+Q#JbBDXi0`2b)$G"$NUF+!jBNJEIridF&`2b)$G"MNUF+!jBNLEIridm%\rJ+33!J+J&!()r*!2JLX5"jBSJEIridF+!U!B!FMr#Jq@*)'hrq0("J+J(!,'%8SC\r`#,b!E3$qC'!!!G`N5dAU!)"m!'!!!FJQ"()*ikXL"(3Aj+Q#JbBLXi0`2b)$i)R\r#J1@*)'hrq0("F$r!Jq@))Qhrq02!)#N(!)#S"J"b2b3$,8$rm(!3i+V%JH@+)'h\rrq0(#)#J&!)#Zrr"b2b3$,8(rp()BiUV%V[rdjBSJEIridF+!U!3!XB8Q"()9ikX\rL"(3,j+Q#JbBLXi0`2b)$G"MNUF+!)'hrq(!r*!2JLX5!jBSLEIridm*`2m#$jBJ\rL-"`!)'hrq0(!)#J$!)#T!J"d2be!rr3J!be"rr"b%1+S`),PL#"YrrM4`#!S!3#\r!V[rdJ+lrm,'&*J9b#H1V)J9d&q5TJS-Q)V1$F$mL!q#*`S$PL5"YrrM4`A!r`)2\rPL#*YrrM6`#!T"`#!U!B!FMmN!be!rr4`%1#Ua)(PLL"YrrM4`L!S"3#!V[rdFMm\rN!be"rr"b'1+Ua+lrm1@+)'hrq0(#J+J%!,'%*J9b&H1V)J9d#q5TJS-Q)V1$F$m\rL!h3Bj+R#J#"YrrK`2b3$i)V%J1@+)Qhrq02#F$r!Jq@))M!F!#"YrrM4`#!S!`#\r!U3)!G$mY32rd)!-Y3Ir`FK$LU-##jBJJEIridF!J+!%!J+lrp)#Zrr#aK&+'F!L\rmJ'd!rM3J"3+!m*!%k)JQ"!+$m*!%KS!J"3+!$j!%)J3#J3q3"1Q*JS!S!5S%FK$\rLV3+&!!!!rb"Yrr3U-&`!kBdL"(3Bj+N#J3!!!2mJEIrd)M!F!1f*JS8U"1#0!S8\r!!!$r)'hrp#S`A!$PMBU")J3#J3!!!2mJEIrdLV!F!#J$FK$LV!+%!!!!rb"Yrr3\rS-%`!kB`L!h3Bj+N#J3!!!2mJEIrd)M!F!1f*JS3S!q#-!S3!!!$r)'hrp#J`6!$\rPM)L")J-#J3!!!2mJEIrdL,!F!#4Z!!`J"A)BiUJ#J!!!!2m8`#!&FK$LU!+!!!!\r!ra6!)!AJL!+!!!!!ra6!)!8#J!!!!2m8`#!%FKMLU!+!!!!!ra6!)!4b%1+S!S!\r!!!$r&-!J"1#)!S!!!!$r&-!J"!+!!!!!ra6!F!"-h`ai6Pj1G!!3Mf4PFepPBf*\rIC@jMFRP`G!!!+P&19[rF,`-JEJ!)GJ"J!!$+!M!!rMJ!F!&b!h32,8$rh(!!%$!\ri!1L!`))8-$J!!S)!!!!2XB,NJX5"F!0b$be"rq"b!")`1!$SJF+Zrq!Y3[rN&$!\ri!!+#!!!!$l1#a)!J,[rNXB,LJX5Zrpa`!A)$,8$rk(!!%$!i!1L!!S!!!!!2,8(\rrl")`1!!#J3!!!!qaJH5"`Ulrl(!$,8,rm(3!&$!i!1L#!S)!!!!2,8$rp"!`1!!\r#J!!!!!qeJ-#Zrr5cJ-#ZrqJL,[r`Xi!+J!!!!!'"-$J!8S0`#,D!C3$r-LBI6Pj\r1G!!%P'4PFepQDAKeF&pVCAPIF'&bDA4j!!!!+P&19[rB,`-JEJ!)GJ"J!!$dF!&\rb!h32,8$rf"!`1!!#J!!!!2lSJ-##G!mY3IrF%M!i!!+"!!!!rX+#XB(NJF+Zrpa\r`!h32,8,ri"3`1!!#JJ!!!2lSJX5Zrq!Y32rN%$!i!!+!!!!!rJ+!!!!!$l@!`+l\rrj,1!iS$!V[rBFJ&d!be"rqJ5-$J!!S%!!!$qk)%#J3!!!!mY3[rX&$!i!!+#!!!\r!rJ+#!!!!$l1#j),%V[rXFJ-Y32r`%$!i!!+!!!!!rZL!!S!!!!!2,8(rp")`1!!\r#J3!!!2i#J3!!!!qaJF+Zrr5eJF+ZrqJJ,[r`XB%3-$J!G!(!JV#"CJ4`!'!-8S0\r`#,D!C3$r#(!"*Kp1ANjd!!58C'9cAf0SC@0VAfYPH9p`BA*TG(N!!!!U88j@rq"\r)jami,#i!##BZ!!`SEJ!B*'i!&%UZ!"aR!!8@*Nak!"SEFKMMVA!!%"Yb%11SLS"\r`!"!EiBL+J(!!%"Z+J(J!'"Yb'11XF!!3'h)3ikL)J(!!%"[KL)L!F!!3'iL!*NB\rS3f!!"-"`#,#Z!""X@Ri!(KYb'11[F!!3'h)3ikL1J(!!%"[KL)k!F!!3'ik!F!!\r3'h)BikJY32rdF!!3'h)3ikL"V[rdF!!3'q')JDlrp(!!%"Z"V[rd[i8J,[rdXB4\r4VJ!3B!!!TYIZ!"!J,J!3$)!!!!!)BJ!!N!!`1`)'6[X!!J#'!(B!CJ"B!%`!2!!\rX!"i!%R!!%#-#J!!!!2qaK(!!%#-#J!!!!2rKL,'%F!!3)`+!!!!!rh)3ikLaK(!\r!%#-#J!!!!2pb'11SXB4`!"!M!S!!!!$rXB9`!"!M!S!!!!$riBLaKA!!%#-#J!!\r!!2pb%11SXB9`!"!M!S!!!!$rFKMMU,'&3Ui!%#!%!S#UN!6LL#B&!S1UN!5'J#!\r%!S"9N!3L"3+"9C!%dS'#J#J"+J4b%1+Y!S8!!!$r)'hrr#S`A!$DK5)%G"MNU3+\r"!!!!rb"Yrrb+X"`!)J6JL3+"!!!!rb"Yrr`L-"`!jBQ#K5S%!S8!!!$r)'hrr#S\r`A!$RMBU"+!0b%1+X!S3!!!$r)'hrr#J`6!$BK#)$G"MNU3+"!!!!rb"Yrrb)X"`\r!)J2JL3+"!!!!rb"Yrr`L-"`!jBQ#K#J$!S3!!!$r)'hrr#J`6!$RM)L"I!"J!!'\rB*J4b&H1V)J4d#q5TJS-Q'V1$F$mL!h3Bj+R#J#"YrrK`2b3$,8$ri(!3i+V%V[r\rJjBSLEIridm)J+3%!J,!F!()r*!2JLX5"jBSJEIridF+!U!)!FMr#Jq@*)'hrq0(\r"J+J$!,'&*J4b#H1V)J4d&q5TJS-Q'V1$F$mL!h33j+R#J1@*)'hrq0("F$mL!h3\rBj+R#J1@*)Qhrq02")#N%!)#S"3"b2b3$i)V%JH@+)'hrq0(#J+J'!()r`S2PL5"\rYrrM4`B#S"`#aK5B&FKAMUb)&G![NUB+$*KUcJh!r)J0d'15T`S!JEIriF$mN!be\r!rq"`%1#Ua+lri1@+)Qhrq02#)#N"!)#`(!"b2b3$i)V%JH@+)'hrq0(#J+J#!()\rr`S2PL5"YrrM4`B#S!`#aK#B&FJRMUb)&G"INUB+$*KUcJh!r)J0d%15T`S$PL5"\rYrrM4`A!r)J0d'15T`S$PL5*YrrM6`5!T"!#!U!8!FMmN!q#+a)(PLL"YrrM4`S#\rS"J"b2m+$jBNJEIridF'!U!F!XB45KR!)[)"Y!2jN)!8#J2#3"1L)*J3#Jr#3")D\r!)!8#J!q3"#)%!S%2N!6TLB+!+!%U"()3iUd#K3!!!2mJEIrd+M"F!1Q0)J4d'15\rT!S%!!!$r)'hrp#)`(!$YLB+&+J6JM3+&!!!!rb"Yrr3U-&`!jBf+J5)%!S%!!!$\rr)'hrp)U`(!!S!h)3iU`#K!!!!2mJEIrd+$"-!1Q-)J0d'15T!S%!!!$r)'hrp#)\r`(!$YLB+%+!2JM!+%!!!!rb"Yrr3S-%`!jBb)J5)$!S%!!!$r)'hrp)L`(!"&k[q\r!)!9b'1+S!S!!!!$r'-!J"A)3iUJ#J!!!!2mB`#!&i)J#J!!!!2mB`#!&!S!!!!$\rr'-!J"()BiUJ#J!!!!2mB`#!%FK$LU!+!!!!!raM!)!6JL!+!!!!!raM!)!3#J!!\r!!2mB`,q&)#lrp,'%5Ui!%'i!qcaJ!!8q5Ui!%'i'F!"J!!8d*Naq!"iEFKMMVh!\r!%"Yb%11SMS"`!"!EiBL1J(!!%"Z1J(!!%"Yb'11S,8$rm(!!%"Yb%11SJDlrm(!\r!%"[KL)'Zrr"`!"!EJDlrm#C'+%0k!"SEFKMMVA!!%"Yb%11SLS"`!"!EiBL+J(!\r!%"Z+J(J!'"Yb'11XF!!3'h)3ikL)J(!!%"[KL)L!F!!3'iL!,8Arl#e%rqJJ"!+\r!UT!%iSJQ"3+$UT!%KS!J"!+!9C!%)J8#J9@3"0+"JS!S!5S%FK$LV3+&!!!!rb"\rYrr`U-&`!fS8L"(3Bj+N#J3!!!2mJEIrmLV!F!#)%i)N#J3!!!2mJEIrm)M!F!1@\r*JS8U"!+&!!!!rb"Yrr`U-&`!jif+J5J$FK$LV!+%!!!!rb"Yrr`S-%`!f)3L!h3\rBj+N#J3!!!2mJEIrmL,!F!#)$i)N#J3!!!2mJEIrm)M!F!1@*JS3S!`+%!!!!rb"\rYrr`S-%`!jib)J8AU!)"m!'!!!FJQ"()*ikXL"(3Aj+Q#JbBLXi0`2b)$i)R#J1@\r*)'hrq0("F$r!Jq@))Qhrq02!)#N(!)#S"J"b2b3$,8$ri(!3i+V%JH@+)'hrq0(\r#)#J&!)#Zrq"b2b3$,8(rj()BiUV%V[rNjBSJEIridF+!U!3!XB8Q"()9ikXL"(3\r,j+Q#JbBLXi0`2b)$G"MNUF+!)'hrq(!r*!2JLX5!jBSLEIridm*`2m#$jBJL-"`\r!)'hrq0(!)#J$!)#T!J"d2be!rq3J!be"rq"b%1+S`),PL#"YrrM4`#!S!3#!V[r\rNJ+lri,'&*J9b#H1V)J9d&q5TJS-Q)V1$F$mL!q#*`S$PL5"YrrM4`A!r`)2PL#*\rYrrM6`#!T"`#!U!B!FMmN!be!rq4`%1#Ua)(PLL"YrrM4`L!S"3#!V[rNFMmN!be\r"rq"b'1+Ua+lri1@+)'hrq0(#J+J%!,'%*J9b&H1V)J9d#q5TJS-Q)V1$F$mL!h3\rBj+R#J#"YrrK`2b3$i)V%J1@+)Qhrq02#F$r!Jq@))M!F!#"YrrM4`#!S!`#!U3)\r!G$mY32rN)!-Y3IrJFK$LU-##jBJJEIridF!J+!%!J+lrj)#Zrq#aK&+'F!LmJ'd\r!rM3J"3+!m*!%k)JQ"!+$m*!%KS!J"3+!$j!%)J3#J3q3"1Q*JS!S!5S%FK$LV3+\r&!!!!rb"Yrr3U-&`!kBdL"(3Bj+N#J3!!!2mJEIrd)M!F!1f*JS8U"1#0!S8!!!$\rr)'hrp#S`A!$PMBU")J3#J3!!!2mJEIrdLV!F!#J$FK$LV!+%!!!!rb"Yrr3S-%`\r!kB`L!h3Bj+N#J3!!!2mJEIrd)M!F!1f*JS3S!q#-!S3!!!$r)'hrp#J`6!$PM)L\r")J-#J3!!!2mJEIrdL,!F!,q&)#lrm,'%F!L`VJ!3E(a4VJ!3)!9b'1+S!S!!!!$\rr'-!J"A)3iUJ#J!!!!2mB`#!&i)J#J!!!!2mB`#!&!S!!!!$r'-!J"()BiUJ#J!!\r!!2mB`#!%FK$LU!+!!!!!raM!)!6JL!+!!!!!raM!)!3#J!!!!2mB`#iZrqblKb!\rZrqLjJ#e!rr"J!2ZbfHi!%#!Z!"!-J!!!!!KL!!#!-$X#"Nll!!)!GJ"S!&S!6J"\r%!$B!+!!F!")J"!+!!!!!raN!)!6JL!+!!!!!raN!)!4b%1+S!S!!!!$r'3!J"()\rBiUJ#J!!!!2mC!#!&!S!!!!$r'3!J"H#)!S!!!!$r'3!J"A)3iUJ#J!!!!2mC!#!\r&FKMLU!+!!!!!raN!F!"-haci6Pj1G!!BN!"NCA0IF'0LBepPEQ0bHA"d!!!!+P&\r19[rS51FI%#*Z!!Kk!"SCFKMMVA!!%"Pb%11SLS"`!"!CiBL+J(!!%"Q+J(!(*J9\rd&H5VaS!JEIrN*M!m!0D$F!FN"5e!rqK`(H#Ua+lrk#"Yrq5'X#`!F!FN"5e$rqa\rf$HDUa)!JEIrN*$!X!1@+K+lrl(!(*JAULmD!)'hrj#B`2!$RLiD#F!mS"A34j+c\r)J#"Yrq!S-%`!f)4`$b3&,8$rl(!Ci+V%V[rX)'hri)L`,!"`$b3&,86rk(J*k+V\r%J#"Yrq!N-#`!jBU%V[rSF!mS"H+-b)!JEIrJ+$"-!1H-L)*k!"SCFKMMVA!!%"P\rb%11SLS"`!"!CiBL+J(!!%"Q+J(!2)J9d&15T`S!JEIrF)M!F!0+"F!mN"5e!rqa\r`(1#Ua+lrl#"Yrpb#X#`!F!mN"5e"rqKb$1+Ua)!JEIrF*$!X!1@+K+lrk(!2)JA\rSLF+!)'hrh#)`(!$RLB+#KS&`"b)&G"(NUF+!)'hrf#)`(!$5JA!(*!8Y32rXF"R\rJUX5Zrq`JEIrBJV!X!(!(*!8Y3IrSFJRLUX5!)'hrf#3`,!$PLS5ZrqK`"b)&iSR\r#J#"YrpJL-"`!jiQ#JSL")Qi!$#im!!"qr(!3*N"J!!'#F!(!KfFU)!0b'Z+S)J2\rPL3+"$rrrr)+!*J%J"()DiUJL"1@*!S%2rrrmJS!S!@!S)!0b'q+S)J25J3+"$rr\rrrS+!*J%J"()EiUJL"0+"!S%2rrrqJS!S!H+(HMmL!h3@j+R#K5"Yrp4k-#3$,8A\rrl(S3kUV%V[rXHJmYF"`!rqJL!be#rr"d$q5T`S@#V[r`jBNJEIr8dF%U+!%!LUl\rrk()m*!-Y4IrdHJRUUX5"HJ-L!qL*`S@#JZ@*)'hre0("+LJ#!)UZrr4b1#3$k)V\r%JA)(`S1#JZ@*)'hre0("LUJ$!(`r)J4d&Z5T`SBJEIr3I$!N"#e'rr4m$qbUa+l\rrp(`2,A!F!2r`)J3Y3[rXG!lNUF+'JUlrl1@*)'hrd0(",#J"!)bZrr"b2b3%lSV\r%JH@+)'hrd0(#M+J#!()m*!6LLX5"FJ2#K)+#jBNJEIr3dF'-U!-!)!B#J2m!!2m\rL"3+"!2rr!)+!)X%J"J+!!2rr!#)&!S(r!!$rJS!L`91,Y[`!!'i!rRT`!%cI#2K\r1ANjd!!L1E@&VC9pVCAPIFf0SC@3!!!!U88j@rrK)j`!N*'i!##mZ!!`[#L*Yrm`\rJ@8k3!#TZrr3[#L*YrqJJ@8k3!#TZrr4+J'B%F2pJ'#m+)QhrJ#"C6T!!+Qlrp%U\r!C`4`rQ!#F!!NAdjH6R3!#)eNCA0IDf9jAh0MD'9N!!!U88j@rrK)j`!N*'i!##m\r+)QhrX#"C6T!!+Qlrp#m+)Qhrl#"C6T!!+Qlrp#m+)QhrJ#"C6T!!+Qlrp%U!CY*\r`!#4I6Pj1G!!%NQ4PFepZCAGIFQ&ZC'pYAfYPH3!!!#T46PEri#m0)Qhr6#"C6T!\r!+Qlrh#e!rqJLEIp-)&P1N!!UE[rF,8$rl#mZ!!JLEIqi)&P1N!!UE[rF5'lrk#*\rYrl3J@8k3!#TZrpa)E[r`)Qhra#"C6T!!+Qlrh%KZrr!LEIqi)&P1N!!UE[rF5'l\rri#*YrcJJ@8k3!#TZrpa)E[rN)Qhr1#"C6T!!+Qlrh#mYrcJLEIqd)&P1N!!UE[r\rF5'lrm#*Yrm3J@8k3!#TZrpa)E[r`)QhrZ#"C6T!!+Qlrh%jH6R3!")!JC'9cAfP\rZDA4IFQ&ZC'pYAfjeE@*PFPpRC@jPFQ&dEh)!!#T46PErq%MR%!3[,Ir!,bi!##*\rYrmJJ@8k3!#TZrr4f!'!+)'hr[%)`1!"5Jh!)YS"Ym#BI6Pj1G!!%R@4PFepcCA4\rIFQ&ZC'pYAfGPEQ9bBA4[FPpcC@9N!!!U88j@rrJLEIqm)'i!#(!)FL#`J@8%SLj\rJ$NU!C`SL#4,B8i"QqL*"6Pj1G!!%Pf4PFepcCA4IFf9aG@9ZBf9IER9YBQ9b!!!\rU88j@rrK)ja!%5(J!!5mYrm![,J!),bhr[#*Yrr!J@8k3!#TZrr4f!'!Q)'hr[(!\r!%$!i!&+!!S!!!!$r)'hr["'!1!!JEIqm5M!i!'B)8S0`#,D!EG3Q(djH6R3!"*P\rNCA0ICf9ZCA*KG'9IFQ&ZC'pYAf*XEf0V!!!U88j@rrK)jami+'i!$#4Z!"J[#Q(\rr!!!!p#`!5'S!"'(r!!!!k#i!)!aQ"R!",8!!&(!"*N"JE#JZ!"!NEJ!)B&4`!EL\r!EaB[#Q(r!!!!K()!-J$5KLB"9)T9K'!)GJ!@'YD'H!!U"b!&6!8!!#)$6!-3!0+\r!6(`3!(rrrrmX!#!&"S!%r(-Y6!-!!%am!!&rrrrr,J&+K'DS)!aR"#M'+-G5Lh!\r%Ym"Z"VIZ!"4[L#!'60mFq%jH6R3!&)jNCA0IFA9KC&pMDh0eE3!!!#T46PErp#"\rZ!!JGD!!"rrBJEJ!)(9$rpc!ZrrC1ANjd!!59G(G[Af*jG'9cAhCKH&pdEepZCA4\rc!!!U88j@rr3JEJ!)(@J!!rrd(@J!![re(@J!!Irf(9$rpb!Zrr41ANjd!!5@CQp\reFPpLHA4PFepfBAKIG'pIEQ9dF`!!!#T46PErm%MR(M`SEJ!)*%`Q6%KZrr!LEIm\ri)&P1N!!UE[rX)Qhr6#"C6T!!+Qlrl#)Zrr#aJ5"Yrk`J%&+3!,1!,`!LEImS)&P\r1N!!UE[rX)Qhr-#"C6T!!+Qlrl#e!rr3L5d(Zrr4`"()JX)&P"+)ZB!j+J'F+)JN\r5f&1!C[SL39L,)Qhr-#"C6T!!+Qlrl#e!rr3L5d(Zrr4`"()JX)&P"+)ZB!j+J'F\r+)JN5f&1!C[SL3A`!B$4i!(B!&K*k!'!+iSY`!F#$XB45KA!'ZS"[m%U%CJS3%J!\r!!!%8J'!)%")#!!$q&)"5LP+'F!HmJ'r'F!"-haai6Pj1G!!%MQ4PFepbB@jNEfe\rIDf9j!!!!+P&19Zri51F3"#mZ!"![,J!-5(J3!%KZlrJLEIqF)&P1N!!UEZrd*J"\r+JfB8,bi!#%KZlrJLEIqB)&P1N!!UEZrd5(J3!%+R5'l[q#*Yrd!J@8k3!#TZlr3\rJ!bBI6Pj1G!!-N@4PFepbC@&NAh"KFh0hEh*N!!!U88j@lrK)ja`m*Qi!##JZ!!`\rSEJ!3+Li!&(B!$)3!!"!!E`!"+R$rB!!"I#m-)Qhr'#"C6T!!+Ql[p#"Yra")D!"\r')Qhr)#"C6T!!+Ql[p#mYra!["#m,)Qhr&#"C6T!!+Ql[p%U!@%pQ&#mYra!LEIm\rF)&P1N!!UEZrdB!!!e%Ki!!S[#b*Yrb3J@8k3!#TZlr3N3%U!C`*#%NU&C`!!XLm\r-,bhrU#*YraJJ@8k3!#TZlr3JEIm35'J!4L*Yrb!J@8k3!#TZlr3[,Im35(J3!%K\rZlrJLEIm8)&P1N!!UEZrd5S"36fB5,bhr%#*Yra`J@8k3!#TZlr4JA%Ki!!T)EZr\ri)Qhr*#"C6T!!+Ql[p#4!5S"R!N)55'l[q#m,)Qhr,#"C6T!!+Ql[p%U!CbJ[,Iq\rN)Qhr'#"C6T!!+Ql[p#"Yra")D!"')Qhr)#"C6T!!+Ql[p&K2B!*f!8U$C`$qfNU\r$CK)["%+R,`XLEIp!)&P1N!!UEZrd,bhrS#*YraJJ@8k3!#TZlr4+K9K2CaC)H"!\r!3UG)EZri)Qhr3#"C6T!!+Ql[p#!%8i"#-`J!)!0A`%3!5F"-ha`i6Pj1G!!3NQ4\rPFepbC@&NAh"hAh0dFQPZC`!!!#T46PEr0%MR(c`QEJ!)+'i!$#e,rc4k!8AZrlJ\rJ5h$r8S"+''Ek,J")H!"!3UG)E[qi)Qhr3#"C6T!!+Qlr-(`"B$S@'dR$H!"J'NU\r&C`SJ!h)"`)'a'Q!))!0b!F#"X5,LLe+%F!DiJ'rJF!I!KQB+)!9A`%3!5F!U!&+\r'[)GM`NAZrlJQ6(`!B"jf!(J!B!iJ"&+!%KT*`H'TKS&5K(!'Z)"[l"E$8SC`"lb\r!Bp`[$#*Yrq`J@8k3!#TZrc")E[mi,``LEIr))&P1N!!UE[m`,`a)E[mi,`F[$#m\rZrc4Krrrrh%T)H!#!3UG)E[mi)Qhr3#"C6T!!+Qlr-#m-)Qhrl#"C6T!!+Qlr-(!\r!60mFq%jH6R3!#*&NCA0IFh4bD@jRAh4[AfYPH3!!+P&19[ri51F30#4Z!!`QEJ!\r)GJ![,Iq8,`SLEImm)&P1N!!UE[rd8%pJ0R!!%"X[!#mYrj!!,`SLEImm)&P1N!!\rUE[rdF!LfJ%r[!!aX&#mYri`[#L*Yrc`J@8k3!#TZrr436b!$8S0b#,#"EF![,Iq\r),`SLEImm)&P1N!!UE[rd8%p-h``)6Pj1G!!)P@4PFepMBQa[BfYIF(*TER4ICQP\rXC3!!+P&19[ri51F30#CZ!!JNEIq%GJ"J)NKi!!J[#b"+8)T)8#*Yrc3J@8k3!#T\rZrr4+J'B%F!&J#P+$F"#fJ'ABF!"-h``)6Pj1G!!%Mf4PFepTFephC@&VAfYPH3!\r!+P&19[rF51FI1#`Z!!`Q,J!J*'i!&#CZ!"JSEJ!F5Ui!*'F!$)`Z!b"(8SGk!"S\r3FKMMV5"(8SG`!"!3FK$MU)U!)%G5Kh!!%"$KL)U!)%G5Kh!!%"#+J#"(8SGi!"J\r3FKMMV#"(8SG`!"!3FK$MU)L!)%G5Kh!!%"$KL)L!)%G5Kh!!%"#)J#iZ!!JY4[r\rdB!!-%R!)X+i!%'i!!*iJ4e+(F!!3%!+!!!!!rh)BikLaK5"(8SG`!"!3!S!!!!$\rrFK$MU,'&)%G5Kh!!%"!#J!!!!2rKL,'&)%G5Kh!!%"!#J!!!!2qaK5"(8SG`!"!\r3!S!!!!$rFKMMU,'%)%G5Kh!!%"!#J!!!!2pb%11SXB3J4e+(F!!3%!+!!!!!rq'\r)XB3J4e+(F!!3%!+!!!!!rl'%8Di!%'!!!,6HVJ!3)#i!%!b!!!!!"f)!!*i`1`)\r'6[X!!J#8!)!!E!"D!%S!0J!L!""6Kb"(F!!3%!+!!!!!rq')XB46Kb"(F!!3%!+\r!!!!!rh)3ikLaK&1()%G`!"!3!S!!!!$rFKMMU,'%8iFJ4h!!%"!#J!!!!2qaK91\r()%G`!"!3!S!!!!$riBLaK91()%G`!"!3!S!!!!$rFK$MU,'&8iFJ4h!!%"!#J!!\r!!2pb'11SXB9#VJ!3)!3#J+U3"1+)*J8#JkU3")D!)!3#J&@3"#)&!S&9N!65JB+\r!+!%U"()3iUd#K3!!!2mJEIrm+M"F!0U&)J4d'15T!S%!!!$r)'hrr)U`(!!L"1#\r*!S%!!!$r)'hrr#)`(!$PLB+&+J3#K3!!!2mJEIrm+M"F!1H0LS%S!h)3iU`#K!!\r!!2mJEIrm+$"-!0L%)J0d'15T!S%!!!$r)'hrr)L`(!!L!q#*!S%!!!$r)'hrr#)\r`(!$PLB+%+!-#K!!!!2mJEIrm+$"-!1H-L)&m!'!!!CJQ"()9ikXL"(3,j+Q#JbB\rDXi0`2b)$G"MNUF+!)'hrq(!r*!-Y32rFF"$JUX5ZrpcPLL*YrrM6`L!T!3#!X"`\r!FMmN!q#+a)(PLL"YrrM4`S#S!J"b2m+$jBNJEIridF'!U!-!XB8Q"()*ikXL"(3\rAj+Q#JbBDXi0`2b)$G"$NUF+!jBNJEIridF&`2b)$G"MNUF+!jBNLEIridm%J+33\r!J+J&!()r*!2JLX5"jBSJEIridF+!U!B!FMr#Jq@*)'hrq0("J+J(!,'&*J9b&H1\rV)J9d#q5TJS-Q'V1$F$mL!h3Bj+R#J#"YrrK`2b3$,8$rh(!3i+V%V[rFjBSLEIr\ridm)J+3%!J,!F!()r*!2JLX5"jBSJEIridF+!U!)!FMr#Jq@*)'hrq0("J+J$!,'\r%*J9b#H1V)J9d&q5TJS-Q'V1$F$mL!h33j+R#J1@*)'hrq0("F$mL!h3Bj+R#J1@\r*)Qhrq02")#N%!)#S"3"b2b3$i)V%JH@+)'hrq0(#J+J'!()r`S2PL5"YrrM4`B#\rS"`#aK&+'F!LmJ'd!rQ3J"3+!m*!%k)JQ"!+$m*!%KS!J"3+!$j!%)J3#J3q3"1Q\r*JS!S!5S%FK$LV3+&!!!!rb"Yrr3U-&`!kBdL"(3Bj+N#J3!!!2mJEIrd)M!F!1f\r*JS8U"1#0!S8!!!$r)'hrp#S`A!$PMBU")J3#J3!!!2mJEIrdLV!F!#J$FK$LV!+\r%!!!!rb"Yrr3S-%`!kB`L!h3Bj+N#J3!!!2mJEIrd)M!F!1f*JS3S!q#-!S3!!!$\rr)'hrp#J`6!$PM)L")J-#J3!!!2mJEIrdL,!F!%AUri!J"!+!UT!%iSJQ"3+$UT!\r%KS!J"!+!9C!%)J8#J9@3"0+"JS!S!5S%FK$LV3+&!!!!rb"Yrr`U-&`!fS8L"(3\rBj+N#J3!!!2mJEIrmLV!F!#)%i)N#J3!!!2mJEIrm)M!F!1@*JS8U"!+&!!!!rb"\rYrr`U-&`!jif+J5J$FK$LV!+%!!!!rb"Yrr`S-%`!f)3L!h3Bj+N#J3!!!2mJEIr\rmL,!F!#)$i)N#J3!!!2mJEIrm)M!F!1@*JS3S!`+%!!!!rb"Yrr`S-%`!jib)J8I\rV!)"m!'!!!FJQ"()*ikXL"(3Aj+Q#JbBMXi0`2b)$i)R#J1@*)'hrq0("F$r!Jq@\r))Qhrq02!)#N(!)#S"J"b2b3$,8$rh(!3i+V%JH@+)'hrq0(#)#J&!)#Zrpab2b3\r$,8(ri()BiUV%V[rJjBSJEIridF+!U!3!XB8Q"()9ikXL"(3,j+Q#JbBMXi0`2b)\r$G"MNUF+!)'hrq(!r*!2JLX5!jBSLEIridm*`2m#$jBJL-"`!)'hrq0(!)#J$!)#\rT!J"d2be!rq!J!be"rpab%1+S`),PL#"YrrM4`#!S!3#!V[rJJ+lrh,'&*J9b#H1\rV)J9d&q5TJS-Q)l1$F$mL!q#*`S$PL5"YrrM4`A!r`)2PL#*YrrM6`#!T"`#!U!B\r!FMmN!be!rq"`%1#Ua)(PLL"YrrM4`L!S"3#!V[rJFMmN!be"rpab'1+Ua+lrh1@\r+)'hrq0(#J+J%!,'%*J9b&H1V)J9d#q5TJS-Q)l1$F$mL!h3Bj+R#J#"YrrK`2b3\r$i)V%J1@+)Qhrq02#F$r!Jq@))M!F!#"YrrM4`#!S!`#!U3)!G$mY32rJ)!-Y3Ir\rFFK$LU-##jBJJEIridF!J+!%!J+lri)#ZrpbaK&+'F!LmJ'd!rM3J"3+!m*!%k)J\rQ"!+$m*!%KS!J"3+!$j!%)J3#J3q3"1Q*JS!S!5S%FK$LV3+&!!!!rb"Yrr3U-&`\r!kBdL"(3Bj+N#J3!!!2mJEIrd)M!F!1f*JS8U"1#0!S8!!!$r)'hrp#S`A!$PMBU\r")J3#J3!!!2mJEIrdLV!F!#J$FK$LV!+%!!!!rb"Yrr3S-%`!kB`L!h3Bj+N#J3!\r!!2mJEIrd)M!F!1f*JS3S!q#-!S3!!!$r)'hrp#J`6!$PM)L")J-#J3!!!2mJEIr\rdL,!F!#!%!S#UN!6LL#B&!S1UN!5'J#!%!S"9N!3L"3+"9C!%dS'#J#J"+J4b%1+\rY!S8!!!$r)'hrr#S`A!$DK5)%G"MNU3+"!!!!rb"Yrrb+X"`!)J6JL3+"!!!!rb"\rYrr`L-"`!jBQ#K5S%!S8!!!$r)'hrr#S`A!$RMBU"+!0b%1+X!S3!!!$r)'hrr#J\r`6!$BK#)$G"MNU3+"!!!!rb"Yrrb)X"`!)J2JL3+"!!!!rb"Yrr`L-"`!jBQ#K#J\r$!S3!!!$r)'hrr#J`6!$RM)L"I!"J!!'B*J4b&H1V)J4d#q5TJS-Q(,1$F$mL!h3\rBj+R#J#"YrrK`2b3$,8$ri(!3i+V%V[rJjBSLEIridm)J+3%!J,!F!()r*!2JLX5\r"jBSJEIridF+!U!)!FMr#Jq@*)'hrq0("J+J$!,'&*J4b#H1V)J4d&q5TJS-Q(,1\r$F$mL!h33j+R#J1@*)'hrq0("F$mL!h3Bj+R#J1@*)Qhrq02")#N%!)#S"3"b2b3\r$i)V%JH@+)'hrq0(#J+J'!()r`S2PL5"YrrM4`B#S"`#aK5B&FKAMUb)&G![NUB+\r$*KbcJh!r)J0d'15T`S!JEIriF$mN!be!rq"`%1#Ua+lri1@+)Qhrq02#)#N"!)#\r`(!"b2b3$i)V%JH@+)'hrq0(#J+J#!()r`S2PL5"YrrM4`B#S!`#aK#B&FJRMUb)\r&G"INUB+$*KbcJh!r)J0d%15T`S$PL5"YrrM4`A!r)J0d'15T`S$PL5*YrrM6`5!\rT"!#!U!8!FMmN!q#+a)(PLL"YrrM4`S#S"J"b2m+$jBNJEIridF'!U!F!XB45KR!\r)[)"Y!2jN)!8#J2#3"1L)*J3#Jr#3")D!)!8#J!q3"#)%!S%2N!6TLB+!+!%U"()\r3iUd#K3!!!2mJEIrd+M"F!1Q0)J4d'15T!S%!!!$r)'hrp#)`(!$YLB+&+J6JM3+\r&!!!!rb"Yrr3U-&`!jBf+J5)%!S%!!!$r)'hrp)U`(!!S!h)3iU`#K!!!!2mJEIr\rd+$"-!1Q-)J0d'15T!S%!!!$r)'hrp#)`(!$YLB+%+!2JM!+%!!!!rb"Yrr3S-%`\r!jBb)J5)$!S%!!!$r)'hrp)L`(!"*l2q!)!9b'1+S!S!!!!$r)'lrp&+Zrr33J#!\r&FK$LU!+!!!!!rb"Zrr45V[rd%)!J"H#)!S!!!!$r)'lrp&+Zrr33J#!&!S!!!!$\rr)'lrp&+Zrr33J#!%FKMLU!+!!!!!rb"Zrr45V[rd%)!J"()3iUJ#J!!!!2mJE[r\rd8Ulrp"#!)!6JL!+!!!!!rb"Zrr45V[rd%)!J"!+!!!!!rb"Zrr45V[rd%)"+VJ!\r3EJ$ckQ!!$0C+VJ!3E`!-cLi$)%G5Kh!!%""b'11S,8$rm#"(8SG`!"!3FK$MU)'\rZrr!J4e+(F!!3%1')JDlrm#"(8SG`!"!3JDlrm#"(8SG`!"!3FKMMU#e!rq`J4e+\r(F!!3%()3ikL"V[rX)%G5Kh!!%"$KL)'Zrq`J4e+(F!!3%)'Zrq`Z,J!),8Erp#"\r(8SGk!"S3FKMMV5"(8SG`!"!3FK$MU)U!)%G5Kh!!%"$KL)U!)%G5Kh!!%"#+J#"\r(8SGi!"J3FKMMV#"(8SG`!"!3FK$MU)L!)%G5Kh!!%"$KL)L!)%G5Kh!!%"#)J#e\r&rqJY42rN)!3#J+U3"1+)*J8#JkU3")D!)!3#J&@3"#)&!S&9N!65JB+!+!%U"()\r3iUd#K3!!!2mJEIrm+M"F!0U&)J4d'15T!S%!!!$r)'hrr)U`(!!L"1#*!S%!!!$\rr)'hrr#)`(!$PLB+&+J3#K3!!!2mJEIrm+M"F!1H0LS%S!h)3iU`#K!!!!2mJEIr\rm+$"-!0L%)J0d'15T!S%!!!$r)'hrr)L`(!!L!q#*!S%!!!$r)'hrr#)`(!$PLB+\r%+!-#K!!!!2mJEIrm+$"-!1H-L)&*l!#!I!"J!!()*J4b#H1V)J4d&q5TJS-Q*,1\r$F$mL!q#*`S$PL5"YrrM4`A!r`)2PL#*YrrM6`#!T"`#!U!B!FMmN!be!rq"`%1#\rUa)(PLL"YrrM4`L!S"3#!V[rJFMmN!be"rpab'1+Ua+lrh1@+)'hrq0(#J+J%!,'\r&*J4b&H1V)J4d#q5TJS-Q*,1$F$mL!h3Bj+R#J#"YrrK`2b3$i)V%J1@+)Qhrq02\r#F$r!Jq@))M!F!#"YrrM4`#!S!`#!U3)!G$mY32rJ)!-Y3IrFFK$LU-##jBJJEIr\ridF!J+!%!J+lri)#ZrpbaK5B&FJRMUb)&G"INUB+$*L5cJh!r)J2JLF+!jBNJEIr\ridF&`2m#$jBJLEIridm!J+3F!J+J'!()r*!-Y32rJF"$JUX5"jBSJEIridF)J+!8\r!J+lri()r*!-Y3IrFFKMLUX5ZrpcPLL"YrrM4`S#S"!#aK#B&FKAMUb)&G![NUB+\r$*L5cJh!r)J0d'15T`S!JEIriF$mN!q#+a)$PLL*YrrM6`R!r`)2PL#)`(!!JEIr\ridF!J+!-!J+N#!(3r,8$ri#!$,8(rh()3iUM!JZ@))'hrq0(!)#J"!)#Zrq#!V[r\rFXB45KR!)[)"Y!2id)!8#J2#3"1L)*J3#Jr#3")D!)!8#J!q3"#)%!S%2N!6TLB+\r!+!%U"()3iUd#K3!!!2mJEIrd+M"F!1Q0)J4d'15T!S%!!!$r)'hrp#)`(!$YLB+\r&+J6JM3+&!!!!rb"Yrr3U-&`!jBf+J5)%!S%!!!$r)'hrp)U`(!!S!h)3iU`#K!!\r!!2mJEIrd+$"-!1Q-)J0d'15T!S%!!!$r)'hrp#)`(!$YLB+%+!2JM!+%!!!!rb"\rYrr3S-%`!jBb)J5)$!S%!!!$r)'hrp)L`(!!J"!+!UT!%iSJQ"3+$UT!%KS!J"!+\r!9C!%)J8#J9@3"0+"JS!S!5S%FK$LV3+&!!!!rb"Yrr`U-&`!fS8L"(3Bj+N#J3!\r!!2mJEIrmLV!F!#)%i)N#J3!!!2mJEIrm)M!F!1@*JS8U"!+&!!!!rb"Yrr`U-&`\r!jif+J5J$FK$LV!+%!!!!rb"Yrr`S-%`!f)3L!h3Bj+N#J3!!!2mJEIrmL,!F!#)\r$i)N#J3!!!2mJEIrm)M!F!1@*JS3S!`+%!!!!rb"Yrr`S-%`!jib)JA`!B!!"Q#B\r%FKAMUb)%G![NUB+$*KZcJh!r)J0d'15T`S!JEIriF$mN!be!rq"`%1#Ua+lri1@\r+)Qhrq02#)#N"!)#`(!"b2b3$i)V%JH@+)'hrq0(#J+J#!()r`S2PL5"YrrM4`B#\rS!`#aK5B%FJRMUb)%G"INUB+$*KZcJh!r)J0d%15T`S$PL5"YrrM4`A!r)J0d'15\rT`S$PL5*YrrM6`5!T"!#!U!8!FMmN!q#+a)(PLL"YrrM4`S#S"J"b2m+$jBNJEIr\ridF'!U!F!XB8Q"A)9ikXL"A3,j+Q#JbBEXi0`2b)$G"MNUF+!)'hrq(!r*!-Y32r\rJF"$JUX5Zrq$PLL*YrrM6`L!T!3#!X"`!FMmN!q#+a)(PLL"YrrM4`S#S!J"b2m+\r$jBNJEIridF'!U!-!XB3Q"A)*ikXL"A3Aj+Q#JbBEXi0`2b)$G"$NUF+!jBNJEIr\ridF&`2b)$G"MNUF+!jBNLEIridm%J+33!J+J&!()r*!2JLX5"jBSJEIridF+!U!B\r!FMr#Jq@*)'hrq0("J+J(!,'%8SC`#,b!E3$qC#!&!S$`N!6SL#B%!S2`N!5'J#!\r&!S!2N!3L"!+"$j!%kBQ#J#J"+J4b%1+Y!S8!!!$r)'hrp#S`A!$TM5)%G"MNU3+\r"!!!!rb"Yrr3L-"`!lBQ#K5S%i)d#K3!!!2mJEIrd+M"F!1@0LS%L"!+"!!!!rb"\rYrr5+X"`!+!0b%1+X!S3!!!$r)'hrp#J`6!$TM#)$G"MNU3+"!!!!rb"Yrr3L-"`\r!lBQ#K#J$i)`#K!!!!2mJEIrd+$"-!1@-L)%L!`+"!!!!rb"Yrr5)X"`!4q[rJ#!\r%!S#UN!6LL#B&!S1UN!5'J#!%!S"9N!3L"3+"9C!%dS'#J#J"+J4b%1+Y!S8!!!$\rr)'hrr#S`A!$DK5)%G"MNU3+"!!!!rb"Yrrb+X"`!)J6JL3+"!!!!rb"Yrr`L-"`\r!jBQ#K5S%!S8!!!$r)'hrr#S`A!$RMBU"+!0b%1+X!S3!!!$r)'hrr#J`6!$BK#)\r$G"MNU3+"!!!!rb"Yrrb)X"`!)J2JL3+"!!!!rb"Yrr`L-"`!jBQ#K#J$!S3!!!$\rr)'hrr#J`6!$RM)L"4HS!J(`!B!!"b#B%FJRMUb)%G"INUB+$*L+cJh!r)J2JLF+\r!jBNJEIridF&`2m#$jBJLEIridm!J+3F!J+J'!()r*!-Y32rJF"$JUX5"jBSJEIr\ridF)J+!8!J+lri()r*!-Y3IrFFKMLUX5ZrpcPLL"YrrM4`S#S"!#aK5B%FKAMUb)\r%G![NUB+$*L+cJh!r)J0d'15T`S!JEIriF$mN!q#+a)$PLL*YrrM6`R!r`)2PL#)\r`(!!JEIridF!J+!-!J+N#!(3r,8$ri#!$,8(rh()3iUM!JZ@))'hrq0(!)#J"!)#\rZrq#!V[rFXB8Q"A)*ikXL"A3Aj+Q#JbBLXi0`2b)$i)R#J1@*)'hrq0("F$r!Jq@\r))Qhrq02!)#N(!)#S"J"b2b3$,8$ri(!3i+V%JH@+)'hrq0(#)#J&!)#Zrq"b2b3\r$,8(rh()BiUV%V[rFjBSJEIridF+!U!3!XB3Q"A)9ikXL"A3,j+Q#JbBLXi0`2b)\r$G"MNUF+!)'hrq(!r*!2JLX5!jBSLEIridm*`2m#$jBJL-"`!)'hrq0(!)#J$!)#\rT!J"d2be!rq!J!be"rpab%1+S`),PL#"YrrM4`#!S!3#!V[rJJ+lrh,'%8SC`#,b\r!E3$q0#!&!S$`N!6SL#B%!S2`N!5'J#!&!S!2N!3L"!+"$j!%kBQ#J#J"+J4b%1+\rY!S8!!!$r)'hrp#S`A!$TM5)%G"MNU3+"!!!!rb"Yrr3L-"`!lBQ#K5S%i)d#K3!\r!!2mJEIrd+M"F!1@0LS%L"!+"!!!!rb"Yrr5+X"`!+!0b%1+X!S3!!!$r)'hrp#J\r`6!$TM#)$G"MNU3+"!!!!rb"Yrr3L-"`!lBQ#K#J$i)`#K!!!!2mJEIrd+$"-!1@\r-L)%L!`+"!!!!rb"Yrr5)X"`!)#lrm,'&)#lrl,'%F!L`VJ!3E!!!ZP'Z!"!J"A)\rBiUJ#J!!!!2mJE[rd8Ulrp"#!)!9b%1+S!S!!!!$r)'lrp&+Zrr33J#!&i)J#J!!\r!!2mJE[rd8Ulrp"#!)!8#J!!!!2mJE[rd8Ulrp"#!)!4b'1+S!S!!!!$r)'lrp&+\rZrr33J#!%FK$LU!+!!!!!rb"Zrr45V[rd%)!J"1#)!S!!!!$r)'lrp&+Zrr33J#!\r%!S!!!!$r)'lrp&+Zrr33J#eZrqMrm#eZrq6rl'!!p)JJ,J!3dDlrp#!Z!"!-J!!\r!!!KL!!$!-$X#"Nll!!)!YJ#J!)S!GJ"N!%i!1!!N!")J"!+!!!!!re1Zrr3JE[r\rd%)!J"1#)!S!!!!$r8klrp#"Zrr33J#!%FK$LU!+!!!!!re1Zrr3JE[rd%)!J"()\rBiUJ#J!!!!2p6V[rd)'lrp"#!)!8#J!!!!2p6V[rd)'lrp"#!)!AJL!+!!!!!re1\rZrr3JE[rd%)!J"A)3iUJ#J!!!!2p6V[rd)'lrp"#!)!9b'1+S!S!!!!$r8klrp#"\rZrr33J%cI(2K1ANjd!##3!'4PFemcBf*MAf9ZBh*jF(3!!!!U88j@rpK)jam`*Qi\r!$#4Z!!Kf!"BDF!!3'Z')KS"`!"!DFK$MU)D!F!!3'R)BikL'J(J!'"T`!"!DiBL\r)J(!!%"Tb%11SL)"`!"!DFKMMU)L!,!6SMVH'!SB2N!5pJb!'kBLaK#`$FK,MVVH\r'!SE-c!!!)!1pJ#)'G",NUE'"*J%X"()5ikkjKJ+'c-`!!#!%[B!L"R35j+QaJ5J\r",!6LMVH'!SC9N!5pJb!'d)#aK#`$i)kjKJ+'!2m!rlf%)!EKL,'$,!6LMVH'!SC\r9N!5pJb!'d)#aK#!%!S!!!2m!)J3#J3!!!2pd%1@TJS!J"!+!!2m!!(33j+L!J5)\r$!S(`!!!!k)Q#J#J"!S-2rrrrIJ"J!!(#)'hrI%U`I!"R(L!$FKVMU#)$j)Q#J#B\r")!4b'Z1S)J6NLB+!+!&J(#!$FK[MU#)$iSQ#J#B")!4b'q1S)J6LLB+!+!%#J`r\rrrrm#K!rrrrp`2m#$)'hrH()m*!2ZLX5"FJ-YF!`!rpJJ!qb)`)'!JZ@))'hrH0(\r!)#J"!)#ZrpKb-#3$,8(rh()1iUV%V[rFFJmY3[rJ*!-Y32rNF!hJUX5"K+lri1@\r+)'hrH0(#)#J#!)#Zrq4b"L3$,8(rk()9iUV%V[rSFJ%Y3[rX*!-Y32r`F"6JUX5\r"K+lrl(!i)J-Y3[rdG"ENUF+!JUlrp1@*)'hrH0(")#J$!)#Zrr!N3(`m)J6JLF+\r'I!-N"1k+a)D%JH@+)'hrH0(#I$r-K1@1)QhrH02',#N%!)bS"3"b2b3%,8Erp(`\r2l+V%JH@+)'hrH0(#,#J'!)bZrr4b-#3%,8(rm()@iUV%V[r`FJmY3[rX*!3Y4[r\rSI"AXUX5"K+lrl1@+)'hrH0(#,#J(!)bZrqJJ#J+!!!$rrbS'G"$PVBU!)!APL#)\r&G"lNUG+!*X%J"J+!rrm!!#S+G"$NVBU!)!AYL#)&G"VNUG+!*X&5Kh!3[S"Y!2i\rkF!"-h`ci6Pj1G!!)Lf4PFepcCA4IDf9j!!!U88j@rrJ[$5mYrh![,J!-,bi!##*\rYrf3J@8k3!#TZrr3J,Ip`6Pj1G!!)L@4PFepMFRP`G!!!+P&19[pF51FI2#KZ!!J\rS,J!-*'i!%%IZrqiJ4%S3CJ4`3@!')%33%%R!&)"*`#B!)'hrE(S!'M!i!1@0)%4\r++!!"CJ4`3@!))%33+!!"5F!93!!"5F!Q!#"Yrfam!"``1!$YMRi!B"BB(%S%Cb*\r`!"!%d)""l[rQ%B"i!&+(F!LqJ'ANB!T"l[rQ3M"i!&+(F!LqJ'A`5'lrANKZrqB\rLEIpd)&P1N!!UE[pB,`B["8KZrej)E[rHBIm!!!$Q*LlrhL!$!S!!!!$r&X!J!q#\r)!S!!!!$r&X!J!h)3iUJ#J!!!!2m@`#!$FKMLU!+!!!!!raE!*LlriL!$!S!!!!$\rr&X!J!q#)!S!!!!$r&X!J!h)3iUJ#J!!!!2m@`#!$FKMLU!+!!!!!raE!I!!@2!#\r!3LlrpRi#B%*i!(S!B#EB"(!!%!0"l[rZFJ!5-'J!`S"R"!!%!!(L#dS$CJC5KKB\rm!)"5KA!'ZS"Pe(!!%!3JEIpS&E!!!(J!8SG`$Ek!CEK#+J!0)!T-haci6Pj1G!!\r-LQ4PFepQBh*jF(3!!!!U88j@rma)j`mB)QhrB(S!I!!SEJ!-,@i!%2r8,@i!&2r\r33Ulrc'!!"%#Abf!!"#JJ"R33j+JN"V'#+!,)V[r8a+lrd#i%FK$MVb!')M5m!,1\r!XB5rK#i#FK$MVb!,8S!L"L!d$!#aJE1#[i)J"1#!,8$rp#i%!SF!!!$m!Ui!!!$\rmrr3J!R)FikJL!ZL*dS!N!A!3i+`J-AJ!XB8J5G(Zrr3J+!)!XB8J"1#),8$rm#i\r%!SF!!!$m!Ui!!!$mrr!J5G(()#J%!,'&)%R4l[r`)#J'!,'&)!,JJ#e!rr3Z!J+\r(!!!!r!+Z!!!!r2rdF"$JUL"*dFFJ+!%!XB8J5G(Zrr3J+!-!XB8J!Z#!,8$rm#i\r#!SF!!!$m!Ui!!!$mrr!J5G(()#J&!,'&)%R4l[r`)#J(!,'&)!9d%15S*!@aJLJ\r#b+lre-5Zrp!Z"()3ikmJ#e5!)J8J0!`!XB'cK,q%,J*b%11[)!Y@J#)&)$3-!,'\r"Xi+rJL!%i)!Y32rX,J3#K`!!!2`#VJ!!!2crl#!#FKcMU#)#k)R5J#3"F"$JV#!\raH!#aKL"*dHlrl#!S!J#aKL!%i)JY32rS,J3#K`!!!2`#VJ!!!2crk#"*dFFJ+!3\r!XBBJ5G(ZrqJJ+!B!XBBJ!Z#!,8$rl#i#!SF!!!$m!Ui!!!$mrqa`%1#U)%R4ab!\rS!3#aKL"*dHlrl#!S!`#aKL!#i)!Y32rS,J)#K`!!!2`#VJ!!!2crk#"*dFFJ+!8\r!XBBJ5G(ZrqJJ+!F!XBBJ"R33j+JN"V'#+!,)V[r8a+lrd#i%FK$MVb!,@)!L"L!\rd$!#aJE1%[i3Z!R)3ikmJ#eU!)JBJ0!`!XB'cJVq#)!6JJ#e!rq3Z"!+(!!!!r!+\rZ!!!!r2rN)!*b(11S)J,SLG+!*!&`%1#X)$&i!,'&)%R4l[rN)#J#!,'&)!6JL#e\r!rq!Z"!+(!!!!r!+Z!!!!r2rJ)%R4ab!S"!#aK5"*dHlri#!S"J#aK5!#i)!Y32r\rN,J)#K`!!!2`#VJ!!!2crj(!3i+SJ5G(()#J"!,'&)%R4l[rN)#J$!,'&)!,JJ#e\r!rq!Z!J+(!!!!r!+Z!!!!r2rJ)%R4ab!S"3#aK5"*dHlri#!S"`#aK5!&G"$NU#3\r&XB)S!XLZrp6%V[r3,J4b%11[)!YFJ#)&)$3-!,'"Xi5rK#i#FK$MVb!,AS!L"5!\rd$!#aJE1#[i)J"1#!,8$rh#i%!SF!!!$m!Ui!!!$mrp`J!R)FikJL!ZL*dS!N!A!\r3i+`J-AJ!XBBJ5G(Zrp`J+!)!XBBJ"1#),8$rf#i%!SF!!!$m!Ui!!!$mrpJJ5G(\r()#J%!,'')%R4l[rB)#J'!,'')!,JJ#e!rp`Z!J+(!!!!r!+Z!!!!r2rFF"$JUL"\r*dFFJ+!%!XBBJ5G(Zrp`J+!-!XBBJ!Z#!,8$rf#i#!SF!!!$m!Ui!!!$mrpJJ5G(\r()#J&!,'')%R4l[rB)#J(!,''8)Y`),I!E3$le#3&+JBX!P+Zrma`'E#ZrmaZ!2Z\rk)!9b(H1S)JAQLG+!+J%J"R)GikJL"ZD*dS!X!53&iSUpJJ+#9C!%YBBJ!Y#!XB8\rN"Z#+Zi)#JJ$r!2qeK5!#iBLaKL3&j)UpJJ+#-j!%YBBJ!Z@)XB8N"R)3iUUlJJ+\r#!!$rrl@&)!*b%11SXBBN"HL+[B)#JJq3",@')!,TL,'&)'i!###')'i!##&&!!4\r-haM`6Pj1G!!3LfCMFRP`G&pLEf4j!!!U88j@rrK)ja`m+Li!##4Z!!`S,J!3+'i\r!&#CZ!"JQ,J!F5S0R4Lm$,`3[#Lm&)Qhrm#"C6T!!+Qlrp#!$9m"%!%R!,`![$#m\r+,`SLEIr`)&P1N!!UE[rd,`-[#bm+,`SLEIr`)&P1N!!UE[rdB%3[!bm,,`S["5*\rYrr!J@8k3!#TZrr3J!eI!4!"*`#m!,``[#Lm+)Qhrm#"C6T!!+Qlrp#m$,`3[#Lm\r+)Qhrm#"C6T!!+Qlrp%cI($K1ANjd!"L3!'4PFemcC@0LAf9ZBh*jF(3!N!80)4#\r"!`B!%!!!%"!3!!!3!"!3%!!3%"!%)4!%)4!#)K!3"#%3J3-,%!!3!"#3"3!!!4!\r!!3!3!4!3!3!!%4!!%3!3%4!3%3BK!3)K!3-L!3%")3%$)3%")3%")J%"!L3"N!3\r$)3%#)J%"!5%"!5%"!53"N!3#)J%"!53"N!8N!C!%"#%""#%"!L)"!33K!3%K!3%\rK!3)L!3%")`%"!3JK")%$$3%!!!%!"!!%!!!%"!%%!!%%"!!!)!!!*!%!)!%!*!!\r%)!!%*!%%)#3""#3"!b%"!L-%!3%#)J%"!5)%!3%K"!%K!3%P"!3"!33"*3%""!3\r"!L)J!3)M*!%"!5-J!3%")L3"!5-%)!%"+J3N!3%%)!%""#5"!`m#!!!#!!3$!!!\r$!!3#"!!#"!3$"!!$"!3#!#!#!#3$!#!$!#3#"#!#"#3$"#!P!`3N!3)#)J%#!5-\r%!3-#)J%$!53%!3)%!5F"!J3%!3-%!5B"!`3%!3)")b!"!J%M*!%$!5-J!3-"-53\r"!J3J!3)%*!%$"#!"!`3N"#%#"5%)!5%#!5%)!L%)!L)##!-L#!J")`))#!3L!3)\r#)3%#)`J"!J%L#!%")3J")`%##!%K!3%R#!J"!JJ)!3)K!B%$"`)!!3!!#3)!#3!\r)!3))!3!)#3))#3)M!3%#!5)"!3)M#3%#!5)*!3%R#!%"!JJ"!3%S#!N"!JJ*!4!\r$)4)$)4!")3J")4)")3J")K!)!L)5#!)M%!J)!5-5#!J")4!#)J%5!L)"%!%M#!%\r5!53)!4!)!5-"%JJ"+J%3#!J"%JJ)!4!")3'"!`F5!!%3!!N5!!N3#!%5#!%3#!N\r5#!NK%!%M!3%5!5-"!4!")`N"%J%b#3%3#!%"%JJ"!4!)#3%5#!N""5%%"#%JJJ)\r%"#!3!"3!%#!L&##"!`JJ!!!J"!!J!#!J"#!J%!!J&!!J%#!J&#!$)3L"!`B%!!J\r!)!J%)!J3!!J8!!J3)!JN&#!))!)M##!%!5)))!%S)!JJ"#!))"!")`JJ&!%T##!\r3)!JJ&#!)J3-()!!!*!!!)#!!*#!!-!!!0!!!-#!!)M3JJ3-))#!!)#3!)*!%*#!\rJ-!!J0!!J-#!J0#!")5!")3L"!`BN!!JJ)!JN)!J`!!Jd!!J`)!JP0#!))#!")`J\rJ*!%V##!J)!JJ*#!))$!")`JJ0!%T##!`)!JJ0#!)"b)3#)%$2`!!#!!3!!)!!!)\r3#!)!#!)3!!!#!!!5#!!##!!5!!)#!!)5#!)##!)5"!!!"!!3$!!!$!!3"!)!"!)\r3$!)!$!)3"!!#"!!5$!!#$!!5"!)#"!)5$!)#$!)5!"!!!"!3#"!!#"!3!")!!")\r3#")!#")3!"!#!"!5#"!##"!5!")#!")5#")##")5""!!""!3$"!!$"!3"")!"")\r3$")!$")3""!#""!5$"!#$"!5"")#"")5$")#$")5!!!!!J-K!J)L!J)%)3%")3)\r")3%#)J)"!5-#!J%%)JJ#!L%)!5%#!5-)!J)")3J#)`%)!J%L!3J"*`)"#!)#!3J\r")5!#)J)J!b%L!L)#)J-L)!%")`)J!3)L)J%")`)L!3)K)!%M#!)J!5%)!5%L!5-\r)!L)")3J"*b!"#!)J!3J"*b)"#!)L!3J#)3+"!`F#!!)!!T!&!!!$!J!$!!)$!J)\r$!L-##!)")J))!5F#!JJ#!J))!L-$#!)")J-)!5F#!`J#!J-)!5)J!S%$"`)J!J!\rL!J)L!J!J!`)J!`!L!`)L!`%R)!))!L!##!%R)J))!L)##!%R)!-)!L!$#!%R)J-\r)!L)$#!BK%!3K)!)L%#!")4!$)K!3!L%3!5%J!533%#!)!b%)!5%3!5%)!L)J#!%\rN%#!)%!)M#"!3!5))%!%P)!J3%##"!`F!!!3!%!3!!#3!%#33!!33%!33!#3N%"!\rN#!)L"!J")a!%#!)L*!J"*"!N#"!"*`3)%"!%#"!"*53)%"!NJ3-(!!3!!"3!!!3\rJ!"3J%!3!%"3!%!3J*"!8)!J")33")3J")43")3J")`3J#!%P&#!)%!3")`J3&!%\rS#"!%)!J3&##"!`F!"!3!&!3!"#3!&#33"!33&!33"#3N%"3N#!%M"!3)!5-8"!J\r")`3N#!%b&#3)%!3%#"!8"!J3"#3)%"3N"#%3"#%"!L)3!38L!K!#)3)")3%")`)\r3!3%K!J)K)!%K%!%K)!)L!5!")a!")!-M)!)3!5)J!J%R!5!#%!%J!J%K")%$"`!\r3"!!!"3!3"3!!"!)3"!)!"3)3"5%#!5)%)!%M%!3J!L)&)!%M%!8J!LF%)!)3"#!\r#!5J&)!)3"5!#)!-K-!-L)!%#)M!"!L%J!L)#-!)M!L!"!5-#-!%")J)J!5%J!5%\r`!5%J!5-J!5!")c!")!%K)!%M)!)`!5`J!L!")!)`!5!#)!5"!`F!-!3!)!8!-!8\r!)!3#-!3#)!8#-!8N!L!%)!%M-!3J!5-J"5!")c!&)!%`)!3J!M!%)!)J"5!#-!8\rJ!J3K"!BL!35#!J`"!3!&!!%""3%!%!33!"%%%3%3"4!"%38K%3%K#)%$$`!%#!!\r!#!%%#!%"#!!&#!!"#!%&#!%!#"!%#"!!#"%%#"%"#"!&#"!"#"%&##%4!L%)!5%\r%J3-1#!!!#!%%#!%"#!!&#!!"#!%&#!%!#"!%#"!!#"%%#"%"#"!&#"!"#"%&)JJ\r4!5))#!%M"!J)!LS)#!%%#!J"!3J)!5-&#!J"+!%)#!%&#!J"!5F)#"!%#!J3!6F\r)#"%%#!J4!3J)%!8)#"!"#!J4"3J)%3FK%))#$3!"!"%3!"!3%!%3%3%!!4!"!3%\r4%3!4%"%")K%4J3-[%!!!%!!3%!!"%!!4%"!!%*!&!4!3%4!"!"!"%"!"!4!"%4!\r4!"!4%"!4!4!4%3%!!!%!%!%!!3%!%3%3!!%3%!%3!3%3%3%"!!%"%!'3"4%"%3!\r"%4!"%3%"%4%4!!!4!"!4!!%4!"%4%!!4%"!4%!%4%"%4!3!4!4!4!3%4!4%4%3!\r4%4!4%3%N%4%4%)%$$`!!%!!3%!!"%!!4%"!!%*!&!4!3%4!"!"!"%"!"!4!"%4!\r4!"!4%"!4!4!N%4%3%!)L%"!")a!3%!%M!4!3!534%"!3!5m3N!F"%"!3%4!3!3%\r[%"!"%"!3!3%3%!%4%"!4!5i3%"%3%"!4!4!3%4%3!3)L%!%")a!3!3%M!4!"!53\r4%!%3!5m3!4!3%!%3!4!"%"%3!3%",a!"!4!3!3%"%!%"%4!"%3%Z%!%4%"!"%3%\r3!4%4%"%#)K!4!5-3%"%")`%3%3%N%4!4%!%[%"%3%"!4%!%3%4!4%"%"!5m3%3%\r3%"%"!4!4!4%3%4%",4!4%4!3%4%"%"%4%3'"!`m!!!%!%!%!!3%!%3%3!!%3%!%\r3!3%3%3%"!!%"%!'3"4%"%3!"%4!"%3%"*"%4!4!#)J%3!5-3!4!")`%"%!%N%3%\r3%!%[!4!3%!%3%!%"%"!4!4!"!5m"%!%3!4!"!3%3!4%"%"%",J%3%4!"%"%"!4!\r4%3%"!L)"!3%M%!%"!5-"N!3N%3%"%!%[!3%3%!%"%!%"!4!4!C!%,`%"!4!"N!F\r4!3%4!5i"!4%3!3%4!3%"%4%"%3)L!4%")a!"%3%M!3%4!534!4%3!5m"%4!3!4%\r3!3%4%"%"%3%",`%4!4!"%3%"!4%"%3%4%3%Y!4%4%!%4%3%"%C!%J3-2!!!4!"!\r4!!%4!"%4%!!4%"!4%!%4%"%4!3!4!4!4!3%4!4%4%3!4%4!4%3%4*"%4%4!#)K%\r3!5-3%4!")`%4%!%N%4%3%!%[%4!3%"%3%!%4%"!4%4!"!5m4%!%3%4!"!4%3!4%\r4%"%",K%3%4!4%"%"%4!4%4%"!L)4!3%M%"%"!5-"%3%"*"%4!4!",a%"%"!4!4!\r"%3%3%4%"!3%[%3%"%"%"!3%4!3%4%3%4!5i4!4%3%3%4!4%"%C!%!L)4%3%M%"%\r4!5-"%4%"*"%4%4!",a%4%"!4%4!"%4%3%4%4!3%[%4%"%"%4!3%4%3%4N!3","%\r4%4!4%4%"%C!%"#%#"#%#!L)#!J3K!J%K!J%K!J)L!J)")`)#!J3L!J)#)3)")3)\r")`)#!J%K!J)M!J)#!5)#!J%S!T!(!3-K!`-L!3)#)J-#!L%"!5%#!5%$!5%#!5-\r"!J)")`-#!J%K!3)L!J-#)`)"!J%M!J-#!5)#!3%M!J)$!5S#!J%#!J)$!J)#!5%\r"!L)#!3-K!`)L!J-$)J%#!5-#!3)#)J-#!5-#!`)#)3%")`)#!3%K!J%K!`%M!J)\r$!5%#!5F"!J)#!3)#!5N$!J)#!`)#!3%#)J-"!L)"!`)L!`-#)`%"!J%M!`%#!5-\r"!`)")`-$!J%L!3%")`)$!3%M!J%$!5-#!`-"-3)"!3)#!`%#!J%$!J)$!`)#!L%\r"J3-(!J!"!!)"!J)"!!!$!J!$!!)$!J)$!L-"!J)")J%#!5F#!3)#!J%#!L-$!J)\r")J-#!5J#!`)#!J-#!3%K!B%$"`-!!3%#!3-#!3%!!`-!!`%#!`-#!b%"!5-"!J-\r"+`%#!3)"!J-#!3)"!5-$!J-"+J-#!3)$!J-#!`)")J%"J3-(!J%"!!-"!J-"!!%\r$!J%$!!-$!J-$!5F"!3)#!3%#!5F$!3)#!`%#!5F"!`)#!3-#!5S$!`)#!`-#!3%\r"J3-(!`%"!3-"!`-"!3%$!`%$!313"5!J!3%"!J-"!3)"!`%#!`-"!J%"!`)$!3-\r#!3-$!J-$!`)$)J%#!L%"!5%#!5-"!J)")3%#)`)"!J%L!J%"*`)#!3)#!J%$)J-\r#!L%$!5%#!5-$!J)")3-#)`)$!J%L!J-"+!)#!`)#!J-"!L)"!`)M!3%#!5-"!`)\r")J%"!5-#!3-"+`)"!3)#!3-#!J%"!L)$!`)M!`%#!5-$!`)")J-"!5-#!`-"+J)\r$!3)#!`-#!J-")3%")`%#!3%K!3%K!`%M!3)$!5%"!5F"!J%#!3)"!5F$!J%#!`)\r"!5%"!5-$!J%")3-")3-")`-#!`%K!`%R!3)$!J%#!`%T!`)$!J-#!`%"!5-"!`%\r")`%"!`%M!3-$!6-"!3%#!3-"!J%"!`)"!`-#!C!%)`-$!3%M!`%$!5-$!`-"-3-\r"!3)$!`%#!`%$!J-$!`)$!L-"!3)")J%"!5F#!3%#!J%"!L-$!3)")J-"!5F#!`%\r#!J-"!L-"!`)")J%$!5F#!3-#!J%$!L-$!`)")J-$!5J#!`-#!J-$!3%M!3%$!5X\r"!3%#!3%$!J'3"#-$!3-"+`-"!3)$!3-#!`%"!5-"!`-"+`%$!3)"!`-#!3-"!5-\r$!`-"+J-$!3)$!`-#!`-"*`%"!3)"N!3R!`%"!J-"!3%R!3-"!J%$!3%R!`-"!J-\r$!3%R!3%$!J%"!`%R!`%$!J-"!`%R!3-$!J%$!`%J4`-$!`)$!`-"N!3$!C!%!`%\r"!`-"N!3$!3-"!`%"!`-"!`-$!C!%!`-"!3-"!`%$!`-"!`%"!`-$!3-$!313"`%\rK%!)L!K!")J%#!5)%!3BK"!%K!J%L"!%"*K!%!3)3"!%N!K!%!3%K%!BK!J)K!3-\rL!3)$)J)3!5%"!L-%!3)")33#)a!%!3%K%!%L!3)")33")3)#)`%#%!)M!K!%!L%\r3!5-"!K!%)33$*J3"!K!%!3%L%!3%)J%#"#)3"!%K!J3L%!3#)4!#)3)")`3"!J%\rN"!%#%!%M!3)3!5%"!b%"!5%3!5)"!J-K!J%K"!)K%!)M!K!%!b)%!3%Q%!3"!K!\r%!b-%!3)#*`%#%!3"!K!$)K!%##8"!K!%!38P%!3"!K!%)33")3)#)J%#!5%%!b%\r%!L%3!5%"!5+!JJFKJ!)MJ))#J3-BJ)!#!))#!!!#!)!!!!)!J))!J))#!!)!J!)\r#J)!#J!#3"!)!!J+!!J#!!J!!JJ!!JJ#!J!#!J!#!!J)!J!+!!!+!!!)!J!)&)J)\r#J3-G!))#J!!!!)!!J))#!!!#J)!!J))!J!!!J!!!!!)!J)!#!)!!!))!J!!#!!)\r!!!!#J!)#!))#J))#!)!#J)!!J!)#J!!#!!)#!))#J))!!!)#J!)!J!)!"5+!!J)\rKJJBMJ)!#!L8""!3"!38L"!%")J3%!5%""L3"!33%!5%"!L%"!5)%"!)L"!3#)33\r")3%#*!3"!33")3%")`3%!33M!33%"L3%"!%"!b%"!L)"!3%L"!%#)J3"!5%%!53\r"!33%!5)""!%L!3%#)3%#)33")J%%!b8%"!%""!)K!3%K"!-M"!%"!5%%"#%"!5%\r%!L)""!%K!3)M"!%"!5%%!5%""b%"!L%"!5B%"!%""!3")3%")33#)33#)3%&)J3\r"!5)%"!%L!33")3%#)33$*!3"!33$)33")`%""!%L!3%")33#)`3%!3)K"!%L!33\r#*!%%"!%$)`%""!-M"!3"!5%%!5)"!33MJ!%%!51!!33#)5%#)B!")33&)S!J!b)\r"")%$#`!J")!!"!!"!)!J")!K!)!K"!!!")!J!!!"!!!J"!!J"!8K)!)MJ#%%J3-\rIJ#%%J!%!J#%%!#!!J!!!!#%!!!%%J!%!!#%!!!!%J!!%!#%!J!!!J!%!!#!!!!%\r%!#%!J#!%J!%!J#!!!#%%!!%%J#!%J!!!J!%!!#%%!#%%J!!%J#%!!#%%J!%%"5)\rJ"!)K)33K"!%LJ!%#)S!J!L'!!5%%"L)J"!)L!33")S!J!L5!J%!3!5'!!5-33)!\r")K"!!b&!!59!%%#!3!%M3)"!!L'!!5%3"L*!%!)L3"!"*B"!%%#!!L&!"5&!!50\r!J%!#)B!&)4!#)8!#)i"!%!3K3!%K3!)KJ!%K%!-N%%#!3!%L3)!&)K"!!5&!!5&\r!!L%3!LK!%%#!3""!J!)K3!%K3!%M3)"!!b*!%!%PJ%!33)!#)8!*)N!3!b)33!%\rK3!%M3)"!!5*!J!-MJ%!3!5'!!5-33)!")K"!!bC!J%!33)!#)N#!"5%3!5+!3!)\rKJ!%K%!)P3""!J%!")N#!!5%3!b)33!%K3!)MJ%!3"#&!!5&!"#%3!L4!%%!3!L-\r)%#!%)5!"*K!J)!J3)!8P#"!J)!J")5!#)4!")5!#)b!J#!%K)!)K%!)K#!%K)!%\rL#"!")5!")4!&)L!)"5%J!5))%!%L)!J#)5!#)L!J!5%3!5)J#!-M#"!J!5-)%#!\r")3J&*L!J#"!J)!-L)!J")L!J!5-3)#!")4!$)4!")5!%)`J3)!%K#!%L)#!"*"!\rJ)!J")5!%)b!)%!)K#!%K)!)K%!%K)!%K%!8M)!J3!L8)%#!J#!%L)#!")K!J!bB\rJ)!J3)#!&)K!J!5%)!b%)!L%J!5)3)!-M)#!)!L%J!L%J!5))%!%L)!J%)a!J)!%\rK%!3K)!%L#"!")b!)#!%L##!#)3J#)3)#*3J###!)!b%)!5)))!-L)!J%)3)")b!\r)!J)N#!)))!%L!JJ")`J##!)M!JJJ!L%)"#-J#!)#)3J#)L!)!5%)!b)))!%L!JJ\r#)3)")b!)!J%N)!J##!-L##!))JJ#!5)J#!)L)!J")3J#)`)))!%K!J-M!JJJ!5%\r#!L-)!JJ$)3J%)b!)!J%K)!)K#!)N!JJJ#!%K#!3L)!J#)b!)!J)L#!)")L!)"#%\r#!L%)!5)))!3N#!)))!%K!J%L)!J#)b!)!J)K#!%K#!%K#!%L##!%*!J###!")J)\r)!L)##!-L##!#)JJJ!5%#!5)J#!-M#!))!59!#%!33!%K3!-K3!)M#%!3!5%)"5-\r33!J")K"!!50!%%!#+""!#%!33!K!!5&!!b&!!5&!!L%)"5-33!J")4!")JK!!L%\r)!5)33!%L3"!%)8!&)8!#*3K!%%!)!b%)!5)33!)K%!8L#%!$*8!33!K!!5*!#!3\rL3"!&*3K!%%!)!5%3!5%)!L&!!54!%%!)!L0!#%!$)8!")N!)!L&!!5&!"#833!K\r!%!%M#%!3!b%3!L&!!5&!"59!%%!)3!)K#!)K3!)K%!%K#!%L%%!")d!33!)K%!%\rK#!%K%!%L#%!&)8!")8!$)d!33!-L3!J"*4"!#%!3!5))3!%N!3'3!!J#2JT@CA*\rTCRPTEQFX)("XC@&cC5"bC5ePER4PFL!PF`)i#JF(6@PcE@&dBfJJ,5"dFRNJB@G\rKD@i+!L%+!53"jj!!#!)N!Iq!c!)Q)$"i)(XJ!L)PH!)L,#!#)L"p!L#"!!'3#2k\r3#"q3"!k3"1#3"2'3"!(q!Ii"rJ(qrJ(q!Ii"rJ%Ii"rJ$[%1mH!Ii"ra$[%1!H!\r"i!(a!I(J!H!"m3(a!4rq(ri1rJlqrKrq(ri1rJi"(`%I!3i"$Km"(`%1!3i"i2l\rJr[(qmIlqi2lJr[(qm3XK!B)#"3!"!!%!!3!"!!%&)3'#!J8!!3!"!!%!!3!"!L!\rZdY28eGEAf0RDfpcGhYrJiH,Mj1AQjqMTkZ[XlHl[m2(bmr6ep[IiqIVlr2hqr`%\rJJ48"!J-%"3B(#!N+#`8'"`J*#JX-$3i2%"%5%a39&KFB'4SE("dH(b!K)L-N*5!\rK)L-N*5BR+#NU+b`Y,Lm`-6)c0$8f0cJj1MXm26ir3%&#3d3Z,c!a-M-d06Bh1$P\r"3N0%48C(5%P+5da06Np389*69&9@9eKC@Q&LBf4PCQGSD@TVE'eZEh"aFR0dGAC\rhH(Pk!Iq!T!NL%#!$)5!#)4!")3%$)3%")a!J!3)L)!%")4!#)3J$)`J3)!%K#!%\rK)!%L#"!")J%)!LB"#"!J!3J"*#!"#"!$)5!$)M!J!L)J)!)K-!%K!3%K)!%K!3%\rM-#!"!5-J)!%")6!#)JJJ!L-)-#!")`JJ)!%L#$!")`%))!%V!3J`)!%))#!"#$!\r")3L"!`F!!!J3)!J!)!J3!!N!!!N3)!N!)!NK%!%L#!J#*JJ)%#!)#!%N)!J)%!%\rL#3J#*JN)%#!*#!%N)!N)%!%K#)%$"b!!#$!J##!J#$!!#5!!#6!J#5!J#5%`!5-\r)##!"+`J)-#!)##!J#!J`!5-*##!"+`N)-#!*##!J#3J`"#%#"5%J!5%#!5%J!L%\rJ!L)#)!-L)#!")`)J)!3L"!)#)33#)b!%!J%L)!3")5!")`3#)!%K"!%R)#!%!L!\rJ"!)K")%$"`)!"!!!*!)!*!!J"!)J"!!J*!)J*!)M"!3#!5)%"!)M*!3#!5)N"!%\rR)!3%!L!%"!%S)#3%!L!N""!$)4)$)4!")5!")4)")5!")K!J!L)5)!)M%#!J!5-\r5)#!")4!#)J35!L)%%!%M)!35!53J""!J!5-%%L!"+J33)#!%%L!J""!")35"!`F\r5!!33!#35!#33)!35)!33)#35)#3K%!%M"!35!5-%""!")b3%%J%b*!33)!3%%L!\r%""!J*!35)#3%"b%"!5%%J3-0!!!%!3%!!!%!!3%%!!%%!3!!!J!!!`!%!J!%!`%\r!!J%!!`%%!J%%)3-#)3)$)J)"!5)%!J)N"!)"!3%K!J%K!3%P!J%""!)"*!%%!J%\r#)J)#!L)#!`%M"!)#!53%!J-"!5-#!J%"+`)$!33#!J%%!J-)!b%)!L-"#!5"!`d\r!#!3"#3!!#3!"#33!#33"#!!##!!$#!3##!3$#3!##3!$#33##33L!`J")3)")3J\r"*3)"#!3#!58)"!)"#3%K!J%K#3%P!J%*"!)"*3N%!J%)!5-#!JJ"+`)$#!3#!JJ\r%!J-*!5-#!JN"+J)$#33#!JN%!J-&)4!%)3%#)K!""#%)J3-+%!!)!!%)%!%)!"!\r!%"!!!"%!%"%!!"!)%"!)!"%)*"!4#!3$)J33!L%%!5%"!5-%%!%")33#)`J%%!%\rL#!3"*`%)""!"#!3")4!")`33%!%K"!%K%3%M""!4!5%%!5F3#!33%!J%!5B4#!3\r3%3L"!`m#!!!5!!!#!3!5!3!#!!J5!!J#!3J5!3J#%!!5%!!#%3!5%3!#%!J5%!J\r#%3JP%K%)"!)#)J35!L-%!J%")`35!3%L"!)")`J%%J%X#!3#!3J%%J%)"!)3!5-\r%%K!")`3#%3%M"")4!6!%!K!)"")3#!3#%3J%%K%)"#%3"#%"!L)3!38L""!#)33\r")3'"!aN%%!%%)!!!-!!!)!%!-!%!)!!%-!!%)!%%-!%%!"!!%"!!!"%!%"%!!"!\r%%"!%!"%%%"%%)"!!-"!!)"%!-"%!)"!%-"!%)"%%-"%K"!)K%!%K%!%K%!)L!4!\r")a!"%!-M%!33!5)3"!%S!4!%%!%3"#!")4!")6!")4!")b!"%!%M-!%3!5%J!5-\r3"$!"+K!%)!%3"$!"%!3")K!3!5-3%"!#)K%3!5-3%4!#*a!3""!3%!3"+K%3""!\r4%!3J%"!")c!3%!%M)"%3!5-`%4!"-#!3%!3`%"!%)"%3"$!4%!3%)3J')JJ)!L%\r)!L%%!5%)!5%%!b-%#!J")J3)!5%#!L))!J-K!J%M#!J#!5%)!5)#"!%M#!)%!LF\r#"!J)!J3)!b)"#)%$"J!"!!!*#!!*!!3"#!3"!!3*##)%#3%K!J%M!3J#!5%"!5%\r#!5-*#!)")3N"*`)%!3J#"!%"+!)%#3J#"!N#J3-(!!!+!!!#!!J+!!J#"!!+"!!\r#"!J+*!3)!J)#)JS#!L)#!J%M#!S#!53)!J)%!5-+!J3"+3)#"!J+!J3)!S%$"`!\r"#J!"!J!*#J!*!J3"#J3"!J3*#L3%#3)#!5-"#J)")`%#!J%M#3S#!6%*!J)%!3S\r#"!%#!J3*#J)%#3BK!B%$"J!)!!!)!3%!!!%!!3%)!!%)!3-K%!)L!4!")3J")4!\r"*!J"%!%#)K!"!53"%!%)!583!3J"%!%K)!-L)!'"!`B!+!!!+!%")!!")!%"+!!\r"+!%")5!")4!")b!"%!%K+!%K%!%P+!%3!5!"*a!")!%3!5J"*4!"+!%3!L%#J3-\r(!!!$!!J#!!J$!3!#!3!$!3J#!3J$!L)#%!)L!a!")`J#%!%N#!-3!3%M!K!"!5S\r$%!%)!K!"#!-3!5)J!S%$"`!J!`!S!J!S!`%J!J%J!`%S!J%S!`%M)!)3!5-J!a!\r")bJ#%!%c+!-3!5!#%!%J!a!"+!)3!5J$%!3K"!3K"!)L"!3&)J)%!L%#!5%%!5-\r#"!3")3)#)5!")33")5!#)J3J!5-%"#!$)b!#"!%L)!)"*`3J!J3%)!)$)L!%!L%\rJ!5%%!5-J"!3")5!$)L)%!L%L!5%%!5-L"!3")5)#)b!J"!%L)#!"*`3J)!3%)#!\r#)b!L"!%L)#)"*`3J)J3%)#)#)3J")33")3J#)J3)!5-%"!J$)`J#"!%L#!)"*`3\r)!J3%#!)#)5J")33")5J#)J3S!5-%"#J$)bJ#"!%L+!)"*`3S!J3%+!)#)`JJ"!%\rL##!"*`3))!3%##!#)`JL"!%L##)"*`3))J3%##)#)bJJ"!%L+#!"*`3S)!3%+#!\r#)bJL"!%L+#)"+J3S)J3%+#)##!J#)3J#)3)#*J)##!J#!J3M#!J#!5%)!5)#!J)\rK!J%Q#!J#!JJ)!5)##!3M#!)#!5-)!J)))3J")3)")3J&)J)#!5%)!L))#!%Q!JJ\r)!J))"#-)!J)")3J%)3)#)3J#)JJ)!5)##!%K!J)K#!%K!J%N#!)##!%K!JJP!JJ\r)!J)")3J#)3J"*!)##!J#)3J%)`J#!J%K#!%L!JJ")3)#)3J#)JJ)!5%#!L%#!5-\r)#!)$)J)#!L-#!JJ#*!))#!)")JJ)!5)##!)K!J%M#!)#"5))!J%K#!%K!J8K#!)\rK!J-K!J%P#!)##!J%)`)##!%K!J)K#!)R#!J#3"#!%!8L%)!")N!3!L&!!L%3!L1\r!%%!")B!#)K#!!b'!!5*!%!%K%!-L%%!")B!#)4!"*""!%)!")N!3"5%3!5%3!L&\r!!55!%%!3!5%3!L'!!L33J""!##%3!5)33!%LJ"!"*K#!%%!3J!%K3!)L%%!%)4!\r%*S!33"#!%!%K%!%N%%!3J!%K3!%KJ!)R%)!33"#!%!%K%!%L%%!#)4!%)8!&)S!\r3!5%3!L*!%!%K%!)KJ!%K3!3N%)!33!%PJ""!%)!$)B!&)8!#)4!$*4"!%)!3!5)\r3J!%L3"!#)N!3!5%3!5%3"#1!%%!")B!")8!")S!3!b-33"!$)K#!!5%%!L3""!3\r"!b%"!5%%!5)"!3%K"!%L!33$)33")J%"!5)%!3%K"!%K!3)K"!)L"!3&*3%%"!%\r"!L)"!3-M!33%!5%""5%%!53""!3"!b%"!bB"!33%!3%")33#)33#)`%%"!%L!33\r")3%#*33"!33%!b)%!38K"!3Q"!%""!3"!b%""#%"!5%%"#)"!3%K"!%M!33%!L%\r%!5)"!33M"!3"!L)%!3%L"!3")3%")33")J%%!b3%"!%"!b%"!53%!3%%!L)""!-\rN"!3"!3%K"!)K"!%K!3%K"!%L!3%")J3"!5%%!5%""5)%"!%K!3)M!3%%!L%"!5-\r%!3%#)3%")J3%!b4!%!J3!5%3"#8)%%!3#!3L%%!#)4!")K!)!5&!!53)%%!3!5%\r3!L))%!8M%!J3!L%)!50!%!J")8!#)4!$)K"!!5%)!5*!%!-K%!3K#!%L3"!")4!\r"*"!)%%!%)4!$)K!)"5&!!53)%%!3!5%3!5%3!5)33!%P#""!%!J")8!#)K"!!5%\r)!L)3#!%K3!)K%!)K#!%L3"!")4!")4!%)`J33!)K%!%L%!J')4!#)8!")3J%)K"\r!!53)%%!3!b%3!5%3!b333"!)!50!%!J")8!#*""!%!J$)JJ3!5%3!L0!%!J")8!\r")3J")N!3!5)33!)K%!%L%!J#)a!)%!-K%!)N#""!%!%K#!3K!33K"!%Q#!%%)!J\r"!5)J#!%K"!)P!33J#!%$)3%&)L!)!L%J!5)""!%K#!%N"#!)!3%N)!J""!BL!33\r")3J%)3%")5!#)`3J#!%K"!)M!33J"#%)!L%J!b)J#!%Q"#!)!33J!5%"!5-J#!%\r%)33$*33J#!%%!5-)!33")3J")J3J!5%"!5-J#!%$)3%&)L!)!L)J#!%K"!%K#!3\rL!33"*!J""#!&*!%%)!J&)33#)3%")L!)!5)%)!)K"!8Q#!%%)!J"!53J#!%%!b)\r%)!%K!3-L!33")JJ"!5)J#!%K"!-L"#!$)5!"*3%%)!J"!L%)!L)JJ!)K3!%K)!%\rK3!3MJ#!J!L%J!5&!!L%J!5'!!5)J3!%K)!3Q)%#!)#"!!5)J)!%KJ!-KJ!%K)!%\rKJ!)M3)!J!b-J)%!")5!#)B!"*#"!J#!")8!')5!%*%#!)#!")S!J!5G!J#!J3)!\rJ!L'!"5)J3!-K3!%L)#!#*#!J3)!")5!$)b"!J!-KJ!%K)!)Q)#"!J#!J!L%J!5&\r!"#'!!5%J!5'!"5%J!5+!)!%K3!%K)!-K)!%P3)!J)%!")L!J"#9!J#!J3!%L)#!\r#)5!#)B!")b"!J!)M3)!J!b-J)%!')5!")B!#)N#!!58J3)!J)!%LJ#!%)L"!!b0\r!J#!")8!#)8!$)3)")3'"!ad#!!%!"!&#"!"!"!"#!*!%!3!!!3)%!!)%!8!!!!!\r%!8)!!8!!!!)%!3)%!%!!!%!%!8)%!!!!!3)!!3!%!%)!!8!%!%)%!8)!!!!%!%)\r%!8!%!!)!!33M3J3"J3-+3!!"3!3!!J3!3!!!!J!"!!!"3!3"!J3!3J3!3J!!"#%\r#!5%"J3-5!!3!!!3"!J#3"!%#"!%#!!"#!!!#"!"!!!&#"!%!!!&#!!!!"!"!"!&\r#"!%!"!&#!!&!!!!N3!3JJ)%$(S!JJJ!!!S!!!!!J!J!!J)!JJ!!JJS!!!)!J!!!\r!JJ!!!S!!JS!J!S!J!)!JJ!!!!J!!JS!!J)!J!J!JJS!J!)!!N!5#!#!!!!#!!#!\r#J##!J!#!!!!#!###"#'!!5'!!b%#!L%J!L1!)))")B!")3)")S!J##'#!L)JJ!%\rMJ#!#!51!)!)$)B!")i!JJJ8KJ!%KJ)%$#B!J!J!JJS!!J!!JJ!!J!)!!JJ!!!S!\rJ!S!JJ!3MJ###J3-(!!##J!!!!#!!!##!J!!#!!##J!!!!)&K)LaiJJ)V,)!XL#e\rS)UiXQ"TS'HJV2LbS'UiCU#bi'5JC*"NJ'4`C&#c),0!C"KMX'-`V1Lc`,2JY!#U\rb+VSY%#dB,5!%aJ$'!+B!CJ!Q!!BY-#di,8!-aK$'#-B!)#)r2!%M"UR`!L,rr4)\rL,%##!Mi!-#a!!!)X3&2F,%"0*#a!61iX3%Rd,%!`8La!,rBX3#p@,%!Z-#a!,'S\rX3#[f,%!Ul#a!+D!X3#NQ,%!ShLa!+)3X3#HL,%!R4La!*Z!X3#0Q,%!Be#a!&kB\rX3"DN,%!3R#a!#eBX3!$#,%!!P#a!!%`X3#Z3!&5U!8J!d"NL!J%")3J%)M!"!5%\r)"#4-!3%)"#+8!3%K#!3K`JBP*Z!")!J$*5G'!5!)!b-RSJ%")5!$*5L%!3%)!b)\rShJ)K#!-P+5B"!3J$)LQJ!5,r#!-L+Qi'*5VX!Hm3!bBVp[rrl)B#*LaUrrrXb!)\rQ,M$rrqc1!L8[9J&K#!-P,rB"B3J$)M"5"L0-lJ%")3J$*NdNrrrZD!)L6X!'*92\rF!HF)!b*8UJcrN!3!N!F"!!!YB!!!!!%!!#eB!!!!!`!!!"!!!!!"!!!!c!!!!0`\r!!!0d!!!!"!!!!"S!N!m0!*!,E!#3#`)!!!!0!*!(V`#3#`%!!!!2!*!%!3!!%`)\r!!"X#!!!K!J!!+!)!!$%#!!!i!J!!2`)!!%8#!!"-!J!!83)!!&J#!!"G!J!!C3)\r!!)8#!!#E!J!![!!"!*!&"`#3"+!!+e"+$d)VJ$G'(8)!!!"0594IT8e*9%0-D@)\rZC'9LG@F!AepQD@aPF`"QCf9dF`"`FQPZG'B!BfaPBA*PFR)!CQCXGA0S!(0dFQ0\rSFJ"cFQ&ZC!"cG(*MEA!!FQ&ZC!"YC@eMEA!!G'PYC3"QF(*TER4Q!'ePEA0PG!"\r0594IT8e*9&*eER4TE@9-D@)ZC'9LG@F!AepeER*PCfPcG'9bAfCbB@GYC@jd!&p\rIFQ9RDA0dCA*ICR*KCfePER3!5@jdCA*QB@0P6'PL!&4TBfY$Eh9ZG!"NCA0IC'9\rLG@F!C'9cAh*PB@4IF'&cFhG[FQ3!C'9cAh0PG&pcCA&eC@jMC9pZG@eLCA)!C'9\rcAh0PG&pVCAN!C'9cAfPcAhGPB@YIDf9j!'4PFepcG(*TEQGIG'pIDf9j!'4PFep\rZCAGIFQ&ZC'pYAfYPH3"NCA0IBf*XEf0VAh"bD@jdAfCTE'8!C'9cAfCMFRP`G!"\rNCA0IBfKPBfYIDf9jAh"KFQPdH3"NCA0ICQPiGA"IDf9jAh"KFQPdH3"NCA0IFQ&\rZC'pYAfYPH3"NCA0IBh*jF(3!C'9cAh*PB@4IF(GIFh4bD@jR!'4PFepTEQPdAh*\rKEQ4[E9pZG@eLCA*ICf9ZCA*KG'pb!'4PFemcC@0LAf9ZBh*jF(3!C'9cAc0MBQ0\rIC@jMFRP`G!"NCA0IFf9dAh*KEQ4[E9pRC@jPFQ&dEh*IFf9PC!"NCA0IDf9jAh0\rMD'9N!'4PFepaG@&NAf0VFh9Y!'eKDf9IDf9jAh0MD'9N!'4PFepPBf*IC@jMFRP\r`G!"NCA0IBf*MAf9ZBh*jF(3!C'9cAfGPEQ9bBA4PAh*KEQ4[E9pLE'pMD`"NCA0\rIF'0LBepPEQ0bHA"d!'4PFepMBQ0IBfYcG@d!N!B-!!!!$!!$!!3!"J!%!!F!$!!\r)!!3!#`!%!!`!!!!0!!J!$3!3!!m!#!!6!!!!&3!)!"8!!!!A!!`!&`!*4Fd!%C0\r8!"IZC`!,%NB!$ee'!"&VQ`!5Y*S!&6r)!!U,8!!8R43!&(88!!kAf`!*4A!!%L3\rk!#$#a3!34D!!%&+J!"edaJ!08`S!$S92!!k,#`!2Cm%!$hc"!"N3i3!31U8!$9m\r2!3!!aJ!!+Ui!!3)!!0!!!#cB!!%#!!$L!!!Xq!!"!J!!qJ!!,+J!!3)!!3B!!#b\ri!!%#!!%@!!!Xb!!"!J!"+!!!,4!!!3)!!6X!!#c!!!%#!!&4!!!XQ!!"!J!"A!!\r!,6!!!3)!!A%!!#di!!%#!!''!!!Xi!!"!J!"P3!!,+!!!3)!!Cm!!#c3!!%#!!'\rb!!!Y#!!"!J!"d`!!,*!!!!%#!!(N!!!XX!!"!J!"p3!!,3!!!3)!!K-!!#dB!!%\r#!!)K!!!Xk!!"!J!#-!!!,5!!!3)!!Mm!!#e!!!%#!!*2!!!Y8!!"!J!#A`!!,2!\r!!3)!!RN!!#dS!!%#!!++!!!Y5!!"kh3!!!%!!!!"B!!!!'!!!!!bFf0KE#!f1%X\r!N"G849K8,R"MD!#3(%eA)%-[3bXV)$Bi5`#3&)!!!!"849K8,R"MD#XV!*!D69F\rJ3bp$+bXJ0MK,!*!8J!!!!&4&@&3ZF("e!*!F69FJ8'&cBf&X)$Bi5`#3%e`!N!X\r"!*!6!@df1'X!N"-"!*!42"&0594IT@4PFfaTBLjNC@*eC`!!!3!!!!&J!!!!B!!\r!!$)'Ce5-AJ)!!!!F!$)!!'0QFQF!!!!+!!$rr`#3##0I:\r
\ No newline at end of file
diff --git a/src/mac/libraries/DES/bin/deslib.PPC b/src/mac/libraries/DES/bin/deslib.PPC
deleted file mode 100644 (file)
index 9639332..0000000
+++ /dev/null
@@ -1 +0,0 @@
-(This file must be converted with BinHex 4.0)\r:#Q4PFfaTBLj38%-!FfKXBMq3"!#3")pK!!!"M[Q[5Qpj)A"PCQC`Gh"M!!!!!E*\rETlJ!N!d$!!)!N!6rN!3!N!CIH!!!AhJ!!&pi!!!&S!!%"!$rN!3!N!BYdJ!!,63\r!!#T"!!"P)!)""!$rN!3!N!i&)!!!!)!%"!3!N!ArN!3!N!F"!!!!p!!!!!%!!!$\rX!!!!!`!!!")!!!!"!!!!e!!!!23!!!0d!!!!"!!!!"S!N!m2!*!,$3#3#`)!!!!\r2!*!()!#3#`%!!!!4!*!%!J!!,3)!!$3#!!!l!J!!3J)!!%J#!!"2!J!!9!%!!&X\r#!!"M!J!!DJ)!!'m#!!"f!J!!I!)!!)8#!!#-!J!!P!)!!+S#!!#q!!%!N!83!*!\r%5JCJ#%S)3J*J"d)"3!&#!8!"3KL!%dBD3#UJ!"[`3""0594IT8e*9%0-D@)!68P\r8Ak905945G@jdD@eP6'PL!%PZG'9bCQ&MC8aTBJ"cG(*MEA!!Fh4bBfKb!'CQE(9\rcD!"cFQ&ZC!"YC@eMF(N!FQ&ZC!"YC@eMEA!!AepQD@aPF`"cG(*XC@i!G'PYC3"\r`FQPZG'B!CQGPG(-!BfaPBA*PFR)!E@9YFf9d!'C`FQPZG'B!AepeER*PCfPcG'9\rbAfCbB@GYC@jd!&pIFQ9RDA0dCA*ICR*KCfePER3!9'PMDd0[G@jd!'4PFepbC@&\rNAh"KFh0hEh*NC'9cAh0PG&pcCA&eC@jMC9pZG@eLCA*NCA0IC'9LG@GNCA0IFf9\rdAfYPH@4PFepTFephC@&VAfYPH@4PFepcG(*TEQGIG'pIDf9jC'9cAfjPGepbB@j\rNEfeIDf9jC'9cAf0LE'pMDep`FQPZG&pQD@aPC'9cAfCMFRP`G'4PFepQDAKeF&p\rVCAPIF'&bDA4jC'9cAf0SC@0VAfYPH9p`BA*TG(PNCA0IFQ&ZC'pYAfYPH@4PFep\rMFRP`G'4PFepbC@&NAh"hAh0dFQPZCf4PFepTEQPdAh*KEQ4[E9pZG@eLCA*ICf9\rZCA*KG'pbC'9cAc0PBf*IC@jMFRP`G'4PFemcBf*MAf9ZBh*jF(4NCA0IFf9dAh*\rKEQ4[E9pRC@jPFQ&dEh*IFf9PC'4PFepVCAPIFf0SC@4NCA0IFA9KC&pMDh0eE@e\rKDf9IDf9jAh0MD'9NC'9cAf9MBPpPEQ0bHA"dC'9cAf0LBepPEQ0bHA"dC'9cAfG\rPEQ9bBA4PAh*KEQ4[E9pLE'pMDf4PFep`Bf*MAf9ZBh*jF(4NCA0IBf*MAf0VFh9\rY!*!&$!!!!!`!!`!%!!B!"!!(!!`!#!!%!!X!"!!-!!!!$3!)!!d!%!!2!!J!%`!\r!!"8!#!!9!!!!&`!-!"F!%C08!"IZC`!*4Fd!#a*'!!pG4J!4DjX!%V5D!"8rb!!\r+Le!!&(88!"5G&!!1PpX!#89`!")N1J!J`X8!%%@J!""5S!!GG-B!$9-+!!k&6`!\r1L`X!$fI"!!pm`3!C%1%!%$UP!!eI$`)!!-J!!!&m!!%#!!$C!!!"4!!"!3!!m!!\r!,63!!3)!!2N!!!'N!!%#!!%%!!!"P!!"!J!"%`!!!B3!!3)!!53!!!&F!!%#!!%\rf!!!"M!!"!J!"5`!!!D`!!3)!!98!!!%F!!%#!!&T!!!"&!!"!J!"I3!!!@`!!3)\r!!BX!!!'d!!%#!!'8!!!"G!!"!J!"TJ!!!93!!3)!!FB!!!'m!!%#!!(@!!!"R!!\r"!J!"jJ!!!8`!!3)!!J-!!!%d!!%#!!)3!!!"C!!"!J!#(J!!!5`!!3)!!L`!!!%\r-!!%#!!)l!!!!r!!"!J!#5J!!!6`!!3)!!Q-!!!%N!!%#!!*c!!!""!!"I!J#TT!\r!!3!)P#(r`$JK!%#!!3!)I!J$TNk!!#"m#!+QNq(rr*!!!3!)P#(r`*!!B3"B1q!\r!!)"K!&K)!&`eB!!!!(ar'hKri`Fd,!-!!%'#!!arirYi5!!!#(rMqhL!!3")1#%\r!3(`)!kD$iIrm6S!!)!#3"L""J!%!N!98!"3ZAepTEQPdD@&XDATPAf4PFfaTBJ!\r!I!J#TT!!!3!)P#(r`%J!A#&J!!!!J!%!5$JK!%"m#!1Q6S!!)!#3"L""J!#3"L3\r!%bjIAh4PFQeTEQ&dC9pNCA0XD@)!!!#q)Ir%1Z)2-$[#%c!l!JX`I0XcH#`)!!"\r"JJA8I2BlH)Nf!!!keJ!"95N'2P8m`!k*9J!!1YB!!99+"Mj95S!HIja6H)Pf!!!\rkeJ!"9@X'2P9V3#jrR&YiLCB!!$V@!!&9M!BqIjaMH)Nf!!!keJ!"95N'2P8p`!k\r*9J!!1YB!!99+"Mj95S!HIle6H)Pf!!!keJ!"9@X'2P9V3#jr[9YiLCB!!$V@!!&\r9M!BqIleMH(af'hKmP50i5!!&+#`&!!K"J!$%L6B!!$V@!!&9+3Bq95N'2P8T`!j\rrR%TiL9B!!$V@!!&95JBq98S'2P9+J"jrR&*iLAB!!$V@!!&9D`Bq9@X'2P9V3#j\rrR&TiLCB!!$V@!!&9M!Bq9B`'2RqFBRL*0J!!1YB!!98T"Mj9+3Bq95R!$Rqp5RL\r*9J!!1YB!!99+"Mj95JBq98U!(Rqp8RL*GJ!!1YB!!99V"Mj9D`Bq9@Y!,Rqp@RL\r*PJ!!1YB!!9@-"Mj9M!BqIleLH$LPrrK)!!#`IYBU&#J&!!G"J3#J15)"k&5U%$T\rp+9!ZI5N$TNk!"#!ke[rrLAB!!&9V"Mj9Dd!ZIleDH$V@rrq*PJ!!9B`'2P@-J"j\rr[@*i1YErriNf!!"9+3Bq95R!$Rqp5RJke[rrL9B!!&9+"MjrR&*i1YErriPf!!"\r9D`Bq9@Y!,RqF@RJke[rrLCB!!&@-"Mj9M)!HIjaLH$V@rrq*0J!!95N'2P8T`!j\rrR%Ti1+!!!$e!UUXj5UUUIiT31$eJUUXjDkUUIkYB1&9Vq(jpAeYi2B"996Q-999\rrM'!i9B`)2$dJ998j+999IkP)1(fG5hKAUJBq98S31ReB8#j95KJi9k['2P9V%$T\rpH&JZ9@X31PHX4Mj9M"!kICKJ,PHTKMj9+4!kI6K),P8T#$apM%YiI@YMH(eF@hK\rAkJBq98S31ReB8#j95KJi9q['2P9V%$TpH&JZ9@X31PIX4Mj9M"!kICKJ,PITKMj\r9+4!kI6K),P8T#$apM%YiI@YMH(eG@hJl3!!!5!!"S)&E!!!lH`!%9kZUrPHXU"4\rpDf0iI9pDH&IT"Vj9+4!k15N$!(dq5#jAkXDq98S31MP+!J"pAP!Z9qZ'[P9V%$S\rjD`%!IAjB,PIX4Vj9M"!kICjJ,ReVBhKp5PYiI5P6H(qF5RL"1`!!1hX!"&HU6Ij\rAUdJXI8TEH(dr8RKAl!Dq9B`31MQ-"`"pRQ!Z9qR'[P8T%$Sj+3B!I6j),PIU4Vj\r95K!k18S%!(eH8#jAkiDq9@X31MPV"3"pIPJZI8TEH(dT8hKpM%YiIjaLH)'E!!!\rlH`!%9iQUrPH+U"4p+90iICp+H&IV"Vj9Da!k1@X$!(eq@#jAl-Dq9B`31MQ-!J"\rpRQ!Z9qQ'[P8T%$Sj+3%!I6j),PIU4Vj95K!kI9j3,RdT8hKpM%YiI@YMH(qp@RL\r"H`!!1hX!"&H-6IjAL8JXIBa,H(erBRKAkJDq98S31MP+"`"pAP!Z9q['[P9V%$S\rjD`B!IAjB,PIX4Vj9M"!k1B`%!(fHB#jAkBDq95N31MNT"3"p2NJZIBa,H(eVBhK\rp5PYiIle5H$YD!!%X'J!)3B$qB$e!m2%j5[$`IkT31$eJm2%jDr$`IiYB1&9Vi6j\rpAeYi2B!2$cQ-$`prV'!i9B`J0MdJ$`mj+3m2IiP)1(fG5hKAUJBq98S31ReA8#j\rAUmBq9@X31Reh@#j9Da!k9ka'2P@-%$TpPf!Z9B``-PHTKMj9+4!kI6G),P8T)$C\rpM%YiI@YMH(eF@hKAkJBq98S31ReA8#jAkmBq9@X31Reh@#j9Da!k9qa'2P@-%$T\rpPf!Z9B``-PITKMj9+4!kI6G),P8T)$CpM%YiI@YMH(eG@hJlHrq!9iT'2TP9!!!\rkY3!"9iZ'2TPe!!!kY3!"9ic'2TQ9!!!kY3!"9iN'2TNe!!!kY3!"9kT'2TP9!!!\rkY3!"9kZ'2TPe!!!kY3!"9kc'2TQ9!!!kY3!"9kN'2TNe!!!kY3!",!8!!%'"qYK\r)!!@B,!8!!%'"!!`iB!!!5!!&M(cf1hL*9J!!1YB!!99+"Mj99-!1LAB!!$V@!!&\r9D`Bq9@Z!(Rk8@hL*PJ!!1YB!!9@-"Mj9M%!ZIT4MH)Nf!!!keJ!"95N'2Rk85hL\r*9J!!1YB!!99+"Mj98m!1LAB!!$V@!!&9D`Bq9@Z!(Rjc@hL*PJ!!1YB!!9@-"Mj\r9M%!ZIR0MH)Nf!!!keJ!"95N'2Rjc5hKmGKYiI*8MH)P@!!!keJ!"98S'2P9F`!k\r*GJ!!1YB!!99V"Mj9Di!HIjaEH)Q@!!!keJ!"9B`'2P@-3#jrR'0iL6B!!$V@!!&\r9+3BqIja,H)P@!!!keJ!"98S'2P9G`!k*GJ!!1YB!!99V"Mj9Di!HIleEH)Q@!!!\rkeJ!"9B`'2P@-3#jr[@0iL6B!!$V@!!&9+3BqIle,H(q5ihKrXHYi28#UUcP+UUT\rrLP!i2@#UUcPVUUTrUeJi9@[iIReI@hJpJ&991Ba99Aq-B$K9M!Jm25"996NT999\rrU8JiICe,H&HU"Mj95K!kI9K3,P9+'$KAUmBq9@X31Rei@#j9Da!k9ka'2P@-%$T\rpQ'!Z9kQ'2P8T%$Tp1%JZ95N)2(f-5hKpDf0iI9aEH&IU"Mj95K!kI9K3,P9+'$K\rAkmBq9@X31Rei@#j9Da!k9qa'2P@-%$TpQ'!Z9qQ'2P8T%$Tp1%JZ95N)2(f-5hK\rpDf0iI9eEH$Yl!)!l)!!!5!!"S$Ylrrb"@`!!9kY0rPHX5#apDf0iI9pDH&IT4Vj\r9+4!k15N%!(dq5#jAkSDq98S31MP+"3"pAP!Z9qX'[P9V%$SjD`F!IAjB,PIXaVj\r9M"!k1B`'!(fHB#jpDf0iI8TEH(dT8hKrR%Ti1h[rr)%l!!"AUUVq9kZS&(e+@hK\rp2e*i9qb'[P@-%$SjM!%!ICjJ,PIT"Vj9+4!k15N$!(dq5#jAkXDq98S31MP+!J"\rpAP!ZI5P6H(f-5hKAkdDq9@X31Req@#jpM&YiIjaLH$Ylrrb"Q`!!9iP0rPH+5#a\rp+90iICp+H&IV4Vj9Da!k1@X%!(eq@#jAl)Dq9B`31MQ-"3"pRQ!Z9qN'[P8T%$S\rj+3F!I6j),PIUaVj95K!k18S'!(eH8#jp+90iIBa,H(eVBhKr[9Ti1h[rr)&l!!"\rAM+Vq9iQS&(f-5hKpIf*i9qU'[P9+%$Sj5J%!I9j3,PIV"Vj9Da!k1@X$!(eq@#j\rAl-Dq9B`31MQ-!J"pRQ!ZI@YMH(e+@hKAk8Dq95N31Rdq5#jp5NYiIle5H$Xj!!%\rX'3!)3B$qB$e!m2%j5[$`IkT31$eJm2%jDr$`IiYB1&9Vi6jpAeYi2B!2$cQ-$`p\rrV'!i9B`J0MdJ$`mj+3m2IiP)1(fG5hKAUJBq98S31ReA8#jAUmBq9@X31Reh@#j\r9Da!k9ka'2P@-%$TpPf!Z9B``-PHTKMj9+4!kI6G),P8T)$CpM%YiI@YMH(eF@hK\rAkJBq98S31ReA8#jAkmBq9@X31Reh@#j9Da!k9qa'2P@-%$TpPf!Z9B``-PITKMj\r9+4!kI6G),P8T)$CpM%YiI@YMH(eG@hKrR+*iIlfDH#`&!!K!J3"d1+Arq&H+4Mk\rC93!!1V8!!9H,KMkCG3!!1V8!!9H-aMkCP3!!1V8!!9H*"MkC03!!1V8!!9HU4Mk\rC93!!1V8!!9HVKMkCG3!!1V8!!9HXaMkCP3!!1V8!!9HT"MkC03!!1V8!!Aj8NhK\rq-iYi5rrlR(ke+K3S"3!)3B%!H$P#!F48Ua!kI8TB,Re*!kC1J!3J9k`'2MUerrq\rCP3!!9kR'2MUerrqC03!!9kU'2MUerrqC93!!9kY'2MUerrqCG3!!9i`'2MUerrq\rCP3!!9iR'2MUerrqC03!!9iU'2MUerrqC93!!9iY'2MUerrqCG3!!1'!!!,SKrm4\r1J!!J!*!')%!!$`#3"!Z-!"!ZC'9cAf0LBepPEQ0bHA"d!!#q`IrB1`)2-$[#%c!\rl)JX`I2FlH)NA!!!kp`!"93J'2P8F`!k*0`!!1[F!!98T"Mj9+B!HIja,H)PA!!!\rkp`!"98S'2P9+3#jrR&0iLAF!!$Vh!!&9D`BqIjaEH)QA!!!kp`!"9B`'2P@G`!k\r*&`!!1[F!!98)"Mj9#)!HIle$H)Nh!!!kp`!"95N'2P8T3#jr[8YiL9F!!$Vh!!&\r95JBqIle6H(ah'hKmYLYi5!!%c#`@!!K"J!$%LAF!!$Vh!!&9D`Bq9@X'2P9V`!j\rrR&TiLCF!!$Vh!!&9M!Bq9B`'2P@-J"jrR'*iL4F!!$Vh!!&9#!Bq93J'2P8)3#j\rrR%*iL6F!!$Vh!!&9+3Bq95N'2RqF5RL*9`!!1[F!!99+"Mj95JBq98V!$Rqp8RL\r*G`!!1[F!!99V"Mj9D`Bq9@Z!(Rqp@RL*P`!!1[F!!9@-"Mj9M!Bq9Ba!,RqpBRL\r*&`!!1[F!!98)"Mj9#!BqIle#H$V@rrK)!!#`I[Hb&#J@!!G"J3#J15)##&E+%$T\rp+9!ZI5N$TNk!"#!kprrrLAF!!&9V"Mj9Dd!ZIleDH$Vhrrq*P`!!9B`'2P@-J"j\rr[@*i1[IrriNA!!"9#!Bq93M!$Rqp3RJkprrrL6F!!&8T"MjrR%Ti1[IrriPA!!"\r95JBq98T!,RqF8RJkprrrLAF!!&9V"Mj9Di!HIjaDH$Vhrrq*P`!!9B`'2P@-`!j\rrR'*i1X!!!(cE-hJp!+UV13LUURq)3$Jp)+UV15QUURqT5$K9+IKqI4p,H$e!998\rj5P99IiT31&9+#$`pB&991@Y99AqV@$KpA9Yi9k`'2P@-%$TpQ@!Z9B`B1&HSaMj\r9#"!kI4P!,P8)%$TAU8Bq95N31Rdj5#jAUSBq98S31ReC8#j95JJmI5P6H(d)5hK\rpR%0i9qX'2P9V%$TpH9JZ9@XB1&IXaMj9M"!kICPJ,P@-%$TAk%Bq93J31RdC3#j\rAkBBq95N31Rdj5#j9+3JmI3K,H(f-3hKpI@0i1d!!!%J!!D#"@`!!1hX!"&HVU[j\rAV+J8I@YMH(eI@RKAk!Dq93J31MN)!`"p(N!Z9qR'[P8T%$Sj+3)!I6j),PIUKVj\r95K!k18S"!(eH8#jAkdDq9@X31Req@#jp5PYiI5P6H(d)5hKrR%*iJCX!!$Yl!!4\rAU%hq9kP),(d)5hKpRd*i9qS'[P9+%$Sj5JF!I9j3,PIVaVj9Da!k1@X'!(eq@#j\rAl%Dq9B`31MQ-"!"pRQ!Z9qL'[P8)%$Sj#!8!I4j!,Rf-3hKpDf0iI8TEH(qF8RL\r"1`!!1hX!"&H+U[jALkJ8I8TEH(dr8RKAl!Dq9B`31MQ-!`"pRQ!Z9qM'[P8)%$S\rj#!)!I4j!,PITKVj9+4!k15N"!(dq5#jAkNDq98S31ReH8#jp+90iI3K,H(f-3hK\rr[@*iJAX!!$Yl!!4AM%hq9iK),(f-3hKpIf*i9qN'[P8T%$Sj+3F!I6j),PIUaVj\r95K!k18S'!(eH8#jAkdDq9@X31MPV"!"pIPJZ9qb'[P@-%$SjM!8!ICjJ,ReVBhK\rp5PYiI5P6H(qp5RJl@J!","S!#%'!rQ!p!2$a13M`m(qS3$Jp)2$a15R`m(q*5$K\r9+H%qI4p,H$e!$`mj5Jm2IkT31&9+)$BpB!m21@X2$hq,@$KpA9Yi9k`'2P@-%$T\rpQ'!Z9kM'2P8)%$Tp'%!Z93J31PHT4Mj9+4!kI6K),P8T-$*AUSBq98S31ReB8#j\r95L!fI5P6H(d)5hKpR%0i9qX'2P9V%$TpH&JZ9qc'2P@-%$TpQ'!Z9B`31PIS4Mj\r9#"!kI4K!,P8)-$*AkBBq95N31Rdi5#j9+5!fI3K,H(f-3hKpI@0i1h[rJ#`@!!"\r"JIXdI*FMH&H+4MkC9`!!1[F!!9H,KMkCG`!!1[F!!9H-aMkCP`!!1[F!!9H)"Mk\rC&`!!1[F!!9HT4MkC0`!!1[F!!9HUKMkC9`!!1[F!!9HVaMkCG`!!1[F!!9HX"Mk\rCP`!!1[F!!AqMkhLk`IrB6S!!)!#3"L"!!!S!N!3&m!!1,Q4PFepMBQ0IBfYcG@f\rqSIr81U)2-$[#%c!k`JX`I(JEH)Mi!!!l'!!"91F'2P6m`!k*'!!!1aJ!!98)"Mj\r9#)!HIja$H)Ni!!!l'!!"95N'2P8T3#jrR%YiL9J!!$XB!!&95JBqIja6H)Pi!!!\rl'!!"9@X'2P9p`!k*Q!!!1aJ!!9@-"Mj9M)!HIleMH)Mi!!!l'!!"91F'2P6R3#j\rr[6YiL4J!!$XB!!&9#!BqIle$H$dJUUXj+DUUIiP)1$e!UUXj5UUUIkT31&9+q(j\rp2e0i2@"996PV999rLeJi9@X)2$f!998jM&99IkaJ1(epBhKAT`Bq91F31Rcf1#j\r8jaJi9kM'2P8)%$Tp&N!Z93J31PHT4Mj9+4!kI6C),PHUKMj95K!kI9C3,P9+#$a\rp+90iI3K,H(cm3hKAk`Bq9@X31Ref@#j9DaJi9qc'2P@-%$TpPQ!Z9B`31PIR4Mj\r8ja!kI2Bi,PISKMj9#"!kI4C!,P8)#$amjd0iIB`lH(epBhJX"J!!3B)"Z(bk+hJ\rlB!!!5!!"S)%k!!!l@J!%9kUUrPHVU"4p5PYiI6p5H&IX"Vj9M"!k1B`$!(fHB#j\rAjmDq91F31MMR!J"mrMJZ9qL'[P8)%$Sj#!%!I4j!,PIT4Vj9+4!kI6j),Rd)5hK\rmjd0iIB`lH(qFBRL"@J!!1eS!"&HV6IjAV%JXI@YMH(eI@RKAj`Dq91F31MMR"`"\rmrMJZ9qM'[P8)%$Sj#!B!I4j!,PIT4Vj9+4!k15N%!(dq5#jAkSDq98S31MP+"3"\rpAP!ZI5P6H(d)5hKmjd0iIj`kH)&k!!!l@J!%9ibUrPH(U"4pM$YiIApLH&IS"Vj\r9#"!k13J$!(dH3#jAkFDq95N31MNT!J"p2NJZ9qU'[P9+%$Sj5J%!I9j3,PIV4Vj\r9Da!kIAjB,Re+@hKp+90iI3K,H(qp3RL"QJ!!1eS!"&H(6IjAL%JXI1G$H(fI1RK\rAk3Dq95N31MNT"`"p2NJZ9qV'[P9+%$Sj5JB!I9j3,PIV4Vj9Da!k1@X%!(eq@#j\rAl)Dq9B`31MQ-"3"pRQ!ZI@YMH(e+@hKp+90iIle+H$Yl!!%X'`!)3B$qB%J!!E3\rl*3#!1f!!!%J!!D!l1IrmJ2N!!&HS6IjAU8JXI3K,H(cr3RKAkNDq98S31MP+"!"\rpAP!Z9qZ'[P9V%$SjD`8!IAjB,PIX"Vj9M"!k1B`(!(fHB#jAjmDq91F31MMR"J"\rmrMJZIB`lH(eVBhKp5PYiIja5H$Xjrrb"'3!!9kQUrPHUU"4p+90iI4p+H&IVKVj\r9Da!k1@X"!(eq@#jAl!Dq9B`31MQ-!`"pRQ!Z9qI'[P6R%$Sij`)!I2ii,Rf-1hK\rpDf0i9qK'[P8)%$Tp(N!ZI@Y$H(qF@RJl1IrmJ6N!!&H+6IjALdJXI8TEH(dr8RK\rAl%Dq9B`31MQ-"!"pRQ!Z9qH'[P6R%$Sij`8!I2ii,PIS"Vj9#"!k13J(!(dH3#j\rAkFDq95N31MNT"J"p2NJZI3K,H(cR3hKpM$YiIleLH$Xjrrb"@3!!9iZUrPH-U"4\rpDf0iI9pDH&IRKVj8ja!k11F"!(cq1#jAk!Dq93J31MN)!`"p(N!Z9qR'[P8T%$S\rj+3)!I6j),Rd)5hKmjd0i9qT'[P9+%$TpAP!ZI1G6H(qp1RJlH`!","X!#%'!rQ!\rpB2$a1@[`m(qV@$JpJ2$a1Bc`m(q-B$K9M1%qIApMH$cJ$`mij`m2IkFi1&6R)$B\rp!!m213J2$hq)3$Kmr80i9kN'2P8T%$Tp08JZ9kV'2P9+%$Tp99!Z98S31PHV4Mj\r9Da!kIA9B,P9V-$*AV)Bq9B`31Rf9B#j9M#!fI@YMH(e+@hKp2&0i9qF'2P6R%$T\rmp6JZ9qM'2P8)%$Tp&8!Z93J31PIT4Mj9+4!kI69),P8T-$*AkSBq98S31Re98#j\r95L!fI5P6H(d)5hKmr80iI*FMH&H,4MkCG`!!1[F!!9H-KMkCP`!!1[F!!9H(aMk\rBp`!!1[F!!9H)"MkC&`!!1[F!!9HT4MkC0`!!1[F!!9HUKMkC9`!!1[F!!9HVaMk\rCG`!!1[F!!9HX"MkCP`!!1[F!!6KJ!!#kSIr86S!!)!#3"L"!!!X!N!3')!!3,Q4\rPFepPBf*IC@jMFRP`G!!!Nq(rr$[J!!")!!#BI)2iVP5%"MamJrQZI+2iVP5P"cj\rm`rLZ9-ER2RbP-RK8T3HqI12iVP6R"cjp!rLZ93MR2RcR3RK8jrHqI+8kH&5P"rj\rp)rLZ95N(2Re$q+j95ZFqI5P5H&8T"ljpBrLZ9@X(2Rf$q+j9M1FqI@YLH&9Vplj\rp+9Ti95RrrRbP5RKST3!"I)2iVRb%+hKmJrQZ1rm!!5JI!!K"J2pSJq(rr%k!!#!\r!N!BJ3!!"!*!&X!!9,Q4PFepQDAKeF&pVCAPIF'&bDA4j!*2Krr`li!!!5!!!Y(b\r$q+j8K!IqI+2iVP5P"Ma8T3FqI-2iVP6'"Ma8aZFqI+8bH&5P"ljmirLZ91F'2&6\rR"cjp!rLZ93J'2&8)jcjmjd*i91Ih[RbP1RK8T3IqI52iVP8T"Ma9+3FqI82iVP9\r+"Ma95ZFqI5P5H&8T"ljpBrLZ9@X'2&9V"cjpJrLZ9B`'2&@-jcjpDf*i9@[h[Rd\rT@RK9+IrqI+9+H(`%+!"!JJ!-1'!!!%J!!"3lr`!"+"m!#%'!rd`iB!!"Jq(rr%k\r!!#!!N!BJ3!!"!*!&d!!9,Q4PFepMD'9MDepVCAPIF'&bDA4j!,i"rm!kiJm`1m)\r6-$X##c"mfc0i,!J!!%'#"FampMYiL6B!!$V@!!&9+3Bq96c!$SP@!!!keJ!"98S\r'2P9+J"jrR&0iLAB!!$V@!!&9D`Bq9@Y!,RqF@hL*PJ!!1YB!!9@-"MjrR'0iL6B\r!!$V@!!&9+3Bq96h!$SP@!!!keJ!"98S'2P9+J"jr[90iLAB!!$V@!!&9D`Bq9@Y\r!,Rqp@hL*PJ!!1YB!!9@-"Mjr[@0iI(BEH(b9)hK)!!8J,!8!#%#"!+5*0J!!1YB\r!!98T"Mj90-!1L9B!!$V@!!&95JBq98U!(Rk88hL*GJ!!1YB!!99V"Mj9Dd!ZIT4\rEH)Q@!!!keJ!"9B`'2Rk8BhL*0J!!1YB!!98T"Mj9-m!1L9B!!$V@!!&95JBq98U\r!(Rjc8hL*GJ!!1YB!!99V"Mj9Dd!ZIR0EH)Q@!!!keJ!"9B`'2RjcBhKrR+*iIlf\rDH$LPrrK)!!$!IYBU&#J&!!K"J3#`15)#6&5U%$Tp+9!ZI5N$TNk!"#!ke[rrLAB\r!!&9V"Mjr[9Ti1YErriQ@!!"9M!Bq9Ba!,RqpBRJke[rrL6B!!&8T"Mj9+B!HIle\r+H$V@rrq*9J!!98S'2P9+`!jr[9*i1YErriPf!!"9D`BqIjaDH$V@rrq*PJ!!9B`\r'2P@-3#jrR'*i1YErriNf!!"9+3Bq95Q!(RqF5RJke[rrL9B!!&9+"Mj95X!1Ija\r5H$LJ!!!pB+UV1@ZUURq,@$JpJ+UV1BbUURqXB$K9M2KqIApMH$dJ998j+999IiP\r)1&8T#$`p3&9918T99AqU8$Kp290i9kX'2P9V%$TpH&JZ9@XB1&HXaMj9M"!kICK\rJ,P@-%$TAU8Bq95N31Rdi5#jAUSBq98S31ReB8#j95JJmI5P6H(f-5hKpI'0i9qX\r'2P9V%$TpH&JZ9@XB1&IXaMj9M"!kICKJ,P@-%$TAk8Bq95N31Rdi5#jAkSBq98S\r31ReB8#j95JJmI5P6H(f-5hKpI@0i1d!!!%J!!D#"H`!!1hX!"&HXU[jAUDJ8IBa\r,H(erBRKAkJDq98S31MP+!`"pAP!Z9q['[P9V%$SjD`)!IAjB,PIXKVj9M"!k1B`\r"!(fHB#jAk8Dq95N31Rdq5#jpM%YiI@YMH(e+@hKrR&*iJ9X!!$Yl!!4AUdhq9ka\r),(eVBhKpAeTi9qN'[P8T%$Sj+3F!I6j),PIUaVj95K!k18S'!(eH8#jAkdDq9@X\r31MPV"!"pIPJZ9qb'[P@-%$SjM!8!ICjJ,ReVBhKp5PYiI5P6H(qF5RL"1`!!1hX\r!"&H+U[jALkJ8I8TEH(dr8RKAl!Dq9B`31MQ-!`"pRQ!Z9qR'[P8T%$Sj+3)!I6j\r),PIUKVj95K!k18S"!(eH8#jAkdDq9@X31Req@#jp5PYiI5P6H(f-5hKr[@*iJCX\r!!$Yl!!4AL8hq9iT),(dT8hKpRdTi9qX'[P9V%$SjD`F!IAjB,PIXaVj9M"!k1B`\r'!(fHB#jAk8Dq95N31MNT"!"p2NJZ9qU'[P9+%$Sj5J8!I9j3,RdT8hKpM%YiI@Y\rMH(qp@RJl@J!","S!#%'!rQ!pB2$a1@[`m(qV@$JpJ2$a1Bc`m(q-B$K9M1%qIAp\rMH$dJ$`mj+3m2IkP)1&8T)$Bp3!m218S2$hq+8$Kp290i9kX'2P9V%$TpGeJZ9kc\r'2P@-%$TpPf!Z9B`31PHT4Mj9+4!kI6G),P8T-$*AUSBq98S31ReA8#j95L!fI5P\r6H(f-5hKpI'0i9qX'2P9V%$TpGeJZ9qc'2P@-%$TpPf!Z9B`31PIT4Mj9+4!kI6G\r),P8T-$*AkSBq98S31ReA8#j95L!fI5P6H(f-5hKpI@0i1h[rJ&H,4MkCG3!!1V8\r!!9H-KMkCP3!!1V8!!9H*aMkC03!!1V8!!9H+"MkC93!!1V8!!9HV4MkCG3!!1V8\r!!9HXKMkCP3!!1V8!!9HTaMkC03!!1V8!!9HU"MkC93!!1V8!!AqFSRKr[CTi,!8\r!!%'"qZ")!!@F,!8!!%'"!!`iB!!!5!!&N!"mpMYiLAB!!$V@!!&9D`Bq9A,!$SQ\r@!!!keJ!"9B`'2P@-J"jq8Q0iL6B!!$V@!!&9+3Bq95P!,Rj55hL*9J!!1YB!!99\r+"Mjq8P0iLAB!!$V@!!&9D`Bq9A(!$SQ@!!!keJ!"9B`'2P@-J"jq-@0iL6B!!$V\r@!!&9+3Bq95P!,Ria5hL*9J!!1YB!!99+"Mjq-90iI(BEH(b9)hL*GJ!!1YB!!99\rV"Mj9I-!1LCB!!$V@!!&9M!Bq9Bb!(RqFBhL*0J!!1YB!!98T"Mj9+8!ZIja,H)P\r@!!!keJ!"98S'2RqF8hL*GJ!!1YB!!99V"Mj9IF!1LCB!!$V@!!&9M!Bq9Bb!(Rq\rpBhL*0J!!1YB!!98T"Mj9+8!ZIle,H)P@!!!keJ!"98S'2Rqp8hKrN!$MH*1Krl!\rpB+UV1@ZUURq,@$JpJ+UV1BbUURqXB$K9M2KqIApMH$dJ998j+999IiP)1&8T#$`\rp3&9918T99AqU8$Kp290i9kX'2P9V%$TpH&JZ9@XB1&HXaMj9M"!kICKJ,P@-%$T\rAU8Bq95N31Rdi5#jAUSBq98S31ReB8#j95JJmI5P6H(f-5hKpI'0i9qX'2P9V%$T\rpH&JZ9@XB1&IXaMj9M"!kICKJ,P@-%$TAk8Bq95N31Rdi5#jAkSBq98S31ReB8#j\r95JJmI5P6H(f-5hKpI@0i1hX!J$XJ!!")!!'J1h[rr)&l!!"AV%hq9kP),(f-5hK\rpIf*i9qT'[P9+%$Sj5J3!I9j3,PIVKVj9Da!k1@X&!(eq@#jAl!Dq9B`31MQ-"`"\rpRQ!Z9qR'[P8T%$Sj+3B!I6j),Rf-5hKpDf0iI8TEH(qF8RJlHrrmJ9X!!&HVU[j\rAV+J8I@YMH(eI@RKAkBDq95N31MNT!3"p2NJZ9qS'[P9+%$Sj5J-!I9j3,PIVaVj\r9Da!k1@X#!(eq@#jp5PYiI5P6H&IX4Vj9M"!kICjJ,RdTBhKrR%Ti1h[rr)%l!!"\rALNhq9iY),(e+@hKp2e*i9qa'[P@-%$SjM!3!ICjJ,PITKVj9+4!k15N&!(dq5#j\rAkJDq98S31MP+"`"pAP!Z9q['[P9V%$SjD`B!IAjB,Re+@hKp+90iIBa,H(qpBRJ\rlHrrmJCX!!&H*U[jALUJ8I5P6H(fI5RKAkiDq9@X31MPV!3"pIPJZ9q`'[P@-%$S\rjM!-!ICjJ,PITaVj9+4!k15N#!(dq5#jpM%YiI@YMH&IU4Vj95K!kI9j3,ReV8hK\rr[9Ti1cN!!5`C!!K"J2jJ2@$`m6PVm2"rUeJi2B$`m6Q-m2"rM'!i9BcK2RerBhJ\rp)!m215N2$hqT5$K9+5!f28!2$cP+$`prLP!iI6e6H&HV"Mj9Da!kIAGB,PHXaMj\r9M"!kICGJ,P@-%$TAU8Bq95N31Rdh5#j9+6!b9kU'2P9+%$Tp9e!Z98SJ0RdT8hK\rpM%YiIAaMH&IV"Mj9Da!kIAGB,PIXaMj9M"!kICGJ,P@-%$TAk8Bq95N31Rdh5#j\r9+6!b9qU'2P9+%$Tp9e!Z98SJ0RdT8hKpM%YiIAeMH(qFNRKr[BTi,!8!#%#"!(J\riTIri9iY'2TPe!!!kY3!"9ib'2TQ9!!!kY3!"9iR'2TNe!!!kY3!"9iS'2TP9!!!\rkY3!"9kY'2TPe!!!kY3!"9kb'2TQ9!!!kY3!"9kR'2TNe!!!kY3!"9kS'2TP9!!!\rkY3!"IK,LH)&Krl"pFHTi5rrlQ(ke+K3S"3!)3B%!H$Q#!LK8U4!kIBa),Rf*!kC\r1J!3J9kS'2MUerrqC93!!9k['2MUerrqCG3!!9kb'2MUerrqCP3!!9kP'2MUerrq\rC03!!9iS'2MUerrqC93!!9i['2MUerrqCG3!!9ib'2MUerrqCP3!!9iP'2MUerrq\rC03!!1'!!!,S"rm"1J!!J!*!')%!!%!#3"!Z)!"%ZC'9cAh"MBQ0IC@jMFRP`G!#\rq)Ir%1U)(-$V#!c!k)J-31N)#d$TL!T!!1S)#F(ah'hL)Y`!!1[F!!95P"Mj8[F!\r1L0F!!$Vh!!&8aJBq9-D!(Rqp-hL)p`!!1[F!!96R"Mj8jd!ZIldlH)NA!!!kp`!\r"93J'2Rqp3hKAUGpq95N31Rdd5#j9+4Ji9kUIIP9+%$Tp9&!Z98S31PHV(hj9Da!\rkIA4B,PHXAhj9M"!kIC4J,P@-#$apDf0iI8TEH(dr8hKATImq9+831Rbc+#j8T4J\ri9kDr2P6'%$Tmdc!Z9-B31PHR2cj8ja!kI2-i,PHSIcj9#"!kI40!,P8)#$amjd0\riI-BlH(bq-hL*0`!!1[F!!98T"Mj92F!1L9F!!$Vh!!&95JBq98U!(Rqp8hL*G`!\r!1[F!!99V"Mj9Dd!ZIleEH)QA!!!kp`!"9B`'2RqpBhKATHFq9+831Rbb+#j8T4J\ri9kDR2P6'%$TmdM!Z9-B31PHR*cj8ja!kI2)i,PHSCcj9#"!kI4*!,P8)#$amjd0\riI-BlH(bP-hKrrbYi9kRrIP8T%$Tp-8JZ95NB1&HU[hj95K!kI9&3,P9+%$TAUcp\rq9@X31Rea@#jAV(pq9B`31Rf4B#j9M!JmI@YMH(e+@hKp+90iIpj,H(bD)hJl)(l\rm1`!!%%J!!5aA*3Iq,!8!!%'#!#"AjK%k9qFf[RcI1hKAb"%k9mNf[RdH5hK)!!!\rF9qS*2&IV,[jpAeYi9m`*2&I&,[jpRLYiIcN1F&IQ"hjAjqDiI-BlH&6'%$SiaJ-\r!I0B`,PISjljAkEkkI3K,H&8)%$Sj#!)!I4C!,PIUMcjAkiDfI8TEH&9+%$Sj5J%\r!I9C3,PIX9Vj9M"!kICCJ,Re+BhKp#&0iI0a$H&I&"ljAa[kkI+8cH&5P%$SiT3-\r!I,8S,PI(cVj8ja!k11F#!(ce1#jAb*Fq9mQ1YRd)5hK9#"!k13J"!(d93#jAbPD\rq98S31Re98#jp#&0iI1G$H(bl1hKAL`)Z9f`'$ReVBhL4HJ!!1eS!"&H&"JjACJ)\rZI+8cH*!!ZJ!!1eS!"$XBrrmX'!!!3B(qe$KJ!!#k)Ir%6S!!)!#3"L"!!!m!N!3\r$*!!2,QeKDf9IDf9jAh0MD'9N!!!!I!J#TT2Krrb3!!%!#*3Krm"mIaYiN!#"!&a\rrirYiJ)%!A%[rr*PJ!!!!Iq2lH%[rlqPJ!!!!,!-!!%##!!`iB2rr5!!!*(rMqhK\r)!!Z&B!!!!#`$!!""JJ!-1'$rrNJ!!!JiB!!!J!%!5$JK!%"m#!1QJq(rr%k!!#!\r!N!BJ3B!"!*!&H!!1,Q4PFepVCAPIFf0SC@4m#!+QNq(rr*!!!3!)P#(r`(ar'hK\rrirYi5!!#+@!!!!"rirYi5rrZJ@!!!!"rirYi5!!,"@!!!!!X!`!!3),rf$KJ!!#\r!!3")1#%!3(`)!kD$iIrm6S!!)!#3"L""J!%!N!9B!"-ZC'9cAfjPGepbB@jNEfe\rIDf9j!!!!I!J#TT!!!3!)P#(rX*!!B3"S5!!bIB""!"53!'%!5%J!-R'!33!8N!"\rK!%b!B3"S5!!!T@!!!!!iB3")5!!"+@!!!!!iB3!i5rrr26KK!$K)!!#&B!!!!$K\rK!%")!$*0J%%!&$KK!%4)!$*"J%%!&)"L!#")!!$aB!!!!$KK!$K,rrm&1'%!1%J\r!!%eJ!!!!J!%!@$JK!&"m#!1Q6S!!)!#3"L""J!#3"T`!)5jNCA0ID@jTG&pbB@j\rNEfeIER9YBQ9bAfGPEQ9bBA4[FJ"m#!+QNq(rr*2"rrL3!!%!#*3Krm#3!'%!@$[\r#,EL!B3"B1))Y1%[rrI9J!!!!1q!!!%J!!"!iB!!!I(ljVM[r!!%X(`!)3B$rm)!\r"!%Ji)3"!I!J$TS2Krrb$`Iri6S!!)!#3"L""J!)!N!9J!"iZC'9cAh0PG&pbB@j\rNEfeICf9ZCA*KG'pbAh0PC@4m#!+QN!!"!!L8)Ir!N!"K!&JiBLfiJ)%!@$LJ!!K\r)!$$jJ%%!&)!"!%Ji)3"!I!J$TNk!!#!!N!BJ3B!!N!Bd!"JZC'9cAh0PG&pcCA&\reC@jMC9pZG@eLCA)!!(`)!UD6iIrmNm(rq*!!!3!)P#(r`*!!B3"B1m)YZ(r$mhL\r!J3"B1+)Y1$M!!!&,rqAeB!!!!$[J!!")!!!NI(liVMKM!!&8B`BqI(ljVRbHq+i\rS"!!!3))!%$[r!!%X(`!)3B$rh)!"!%Ji)3"!I!J$TS2Krrb$`Iri6S!!)!#3"L"\r"J!)!N!9m!"SZC'9cAfGPEQ9bBA4PAh*KEQ4[E9pLE'pMDh`)!UDqJIr3N!!"!!L\r8)Iq3!(ae'hKmQ#0iI,BVH(cA-hKmp$YiIS1MH%J!!@&mI"Yi1(3!"%J!!99mHKY\ri+"J!!%##!!Jki!!"1b!!!8J!!,"qhV0iIVZVH%J!!)!X(J!"3)%!)(pMfhK)!!$\rK9'-%2Rrm'K3lH`!#1plrrNJ!!"L)H`!!1hX!!94M"Mjrr"S81m!!!(pGdhKmRrR\r@I,hTeRb%+K3m`)!!1-Errhq%-jCrR$(@Ij`J8$cp"2`ijh-YI2mjeMd!J!!j#2r\rrIdG$PRpD3GCr@MK3,"i!!%##ri!S'!!!3B)!&*1B!!!l'!!%NeJ!!$XB!!3l13!\r","N!"%'"!!am'EJ!3)(r5(q$ihL!!3"i1#%!F(`)!kDkJIr36S!!)!#3"L""J!`\r!N!3"*!!2,Q4PFepaG@&NAf0VFh9Y!!!!L)-!!CL"rr#)S`!!Q+(rmD"Krr"1J!!\rJ!*!')%!!N!FB!"BZG(G[Af*jG'9cAhCKH&pdEepZCA4cL)-!!jL"rr#)S`!#Q+(\rrmBM$!!'B`IrbL1-!!*MKrr1!BIr`6S!!)!#3"L"!!*!(+!!A,QC[GA*IBRPdCA0\rIGQ&iAh4[AfjPG(-!!!"m#!+Q[`(ri*!!!3!)P#(rS(aj'hKr2-YiIcV,H$KK!$K\r)!#j"J%%!&%J!,L'!33!8J)%!1(b%'RL!SJ#SJ-8!!(c(-hJiaJ!"N!$&!!"mjb*\riI2JlH(m$`hK)!#iKJ%%!&%J!,M'!33!8N!"K!$ar3p0i1)%!2$LJ!!4)!#fjJ%%\r!&$YD!!4)!#i0J%%!&*!!B3!mId26H$L"!$`iS!!%5!!YPB""!"3lB!!!5!!!@$[\r!!!#,r!!!1k!!!%J!!"4ArrKq9qJ(rRrH3RJl[3!","d!"N#"rq`X(J!!3))!&)N\rm!!"K+3!"Q6`!!%J!!"#*A!!!98S'2*PF!!!lR!!"1hX!!5`E!!G!JIqS1'!!!)!\r"!'Ji)3"JI!J$TVX"rq"1J!!J!*!')%'!#!#3"!%J!!mZC'9cAh*KEQ4[E9pVCAN\r!!!"m#!+QNq(rr*!!!3!)P#([`*!!B4"BN!#"%&b3!+%3B$KK!$JiJ"!!J+%3A)$\r"%'")!!"eB!!!!(ar'hJX(`!!3))!&$KK!$L!J4"B5!!#9@!!!!!iB3!i1)!!!$L\rJ%!")!#fCJ%%!&(rMqhL!!4")1#%33(`)!kD$iIrm6S!!)!#3"L""J!%!N!9m!")\rZC'9cAh*PB@4IF'&cFhG[FQ4m#!+Q[Z(rh*!!!3!)P#([S(ap'hKmQL0iI,XVH(c\rC-hJkiKY21`)E-)2L!&!lJ!!!,"S3!%#"!5!iB2rr5!!"K(pMfhK)!#b"J%%!&$K\rr!%K)!#b0J%%!&(qMkhKr400iIqAlH%J!,*'!33!8+!-!!%##!"4rirYi5!!XPB"\r"!"4)!!$8Ik2VH$L!!!T)!#bCJ%%!&(aq'hJS(J!!3B)!$$KJ!!#BIJ!!,"N!!%'\r#!+4r!m0iIf6EH%J!,!f!33!81(m!5%J!,"Q!33!81'%!1$L!%!"rjIYi5!!X(B"\r"!"3S!`!!3))!&(rMqhK)!#`KJ%%!&%J!!'!iB3!i1)!!#NJ!,#@!33!8I(iEH#J\rH!!""JJ!-1)!!!*LH!!"rSqYi1)%!1%J!,"Q!33!8,!-!!%'#!#"qilYi5!!VMB"\r"!"3iI`")5!!VQB""!"4)!!!)1i!!!5`F!!""J[lS,"`!!%##!"KrSqYi1)!!!(p\r&dhK)!#[PJ%%!&$KL!0a)!#Y*J%%!&#`C!!""JJ!B1'%!1$L!!!!iS"!!5!!V[B"\r"!"3iS!!!I0VU&*LQrrmii!!!,"`!!%##!!Jii!!"I1-lH)!"%'Ji)4"JI!J$TVV\rKrpa1J!!J!*!')%'!#3#3"!(8!"-ZC'9cAh*PB@4IF(GIFh4bD@jR!!!!I!J#TVl\r"rpL3!!%!#*3KrZ"mH4YiI*FMH(mfbhJlJ!!"1k%!Z(mMbhK)!#Y*J%%!&(ak'hJ\riB3#i1)!!!$LJ!%")!#XCJ%%!&$YJ!!&)!!#%L(N!!$Xj!!&mI`Gd1m!!!%J!!%3\rX(!!!3B)!)&IN"rjrTHYi1ld!!BM&!!"maL*iQ-8!!%J!!"KAj`Iq1lhrriNG!!"\rp#$TiQ4d!!&Irq(ilhJ!","i!"N#"rlaAD3Gq+!N!!%##!"Jj3!!!,"`!!%##!!J\rj3!!"I9a6H$Yl!!&m'p"!3)(rI$ZK!,Kqq,Yi1f!!!%J!!%!li!!!1m!!!%J!!##\r*I3!!1ld!!AeV"h3jRJ!"I@YJ-(rr@hJlhJ!","i!"N#"rq#Eq!!!1aJ!!6Yl!!%\rS'`!(3)(r`(lMZhK,rq64B!!!!(lMZhJiJ3!i5rreK@!!!!"q`l0iIZ5lH(p&dhJ\ri`3!iIZHlH%[rf&&J!!!!1'%!1$L!!!!iS!#!5!!TkB""!"4qilYi5rrNK@!!!!!\riB!!!J!%"+$JK!5"m#!1QZX(rf%k!!#!!N!BJ3B!+!*!%!C`!%LjNCA0IFh4bD@j\rRAh4[AfYPHA`)!UD6iIrmNm(rq*1Krr53!!%!#*3Krl#3!'%!D(bI)hL$S3"S1m!\r!!(rMqhJiJKYS5!!TQB""!"4)!!!iIq2lH$L#!0k)h3!!1ld!!96&"Mj)!#PjJ%%\r!&#`H!!K!J!!8Iq2lH$L#!1&)!#PKJ%%!&#`H!!JlhJ!"3B$ra(rMqhJiJJ$N5!!\rT4B""!"5!!3"B1#%!8(`)!kD$iIrmJm(rq)1Krr41J!!J!*!')%'!!`#3"DJ!&Lj\rNCA0IBf*XEf0VAh"bD@jdAfCTE'9m#!+QNq(rr*2"rrL6SIrdN!!"!!L8)Iq`I(d\rEH$[#'fmli!!!5!!!-(r$mhJlhJ!)Ik6VH$LJ!!K)!#GaJ%%!&#`$!!"!JJ!-1'!\r!!8J!!"3lr`!"+"m!%%'!rp!iB!!!J!%!@$JK!&"m#!1QJq(rr)2"rrL$SIrd6S!\r!)!#3"L""J!-!N!9m!"!ZC'9cAfPcAhGPB@YIDf9j!!#p`Iqi1Z)2-$[#%c!l!JX\r`I0XcH(ck1hKp'80i,!S!!%'#$04p-%YiLA!!!$S3!!&9D`Bq9Ac!$SQ3!!!!1K!\r!!9@-"Mj9M)!HIjaMH)P`!!!k%!!"9@X'2P9V3#jrR&YiLC!!!!!k%!!"9B`'2Rq\rFBhL*F!!!1K!!!99V"Mj9IF!1LC!!!!!k%!!"9B`'2P@-J"jr[@0iLA!!!$S3!!&\r9D`Bq9@Y!,Rqp@hL*N!!!!$S3!!&9M!BqIleMH(a`'hL3!)(rX%J!$#JX"3!)3B!\r!a)P`!!!k%!!"9@X'2P9V"Mj9Dm!1IjaDH)Q3!!!!1K!!!9@-"Mj9M!Bq9Bb!(Rq\rFBRL*F!!!1K!!!99V"Mj9D`Bq9@Y!,RqF@RL*N!!!!$S3!!&9M!Bq9B`'2RqFBRL\r*F!!!1K!!!99V"Mj9D`Bq9@[!$Rqp@RL*N!!!!$S3!!&9M!Bq9B`'2P@-J"jr[@*\riLA!!!$S3!!&9D`Bq9@X'2P9V3#jr[9TiLC!!!!!k%!!"9B`'2P@-"Mjr[@*i1+A\rrq%J!!,"q%#S8+!8!"d'"!+!jBK`89+`31ReVB#jpD31Q6S!%)$S3rrq*F!!!9@X\r'2P9V3#jr[9Ti1K$rriQ3!!!!9B`'2P@-J"jr[@*i1K$rriP`!!"9D`Bq9@[!$Rq\rp@RJk%2rrLC!!!!"9M!BqIjaLH$S3rrq*F!!!9@X'2P9V3#jrR&Ti1K$rriQ3!!!\r!9B`'2P@-J"jrR'*i1K$rriP`!!"9D`Bq9@[!$RqF@RJiS!!!2B#UUcQ-UUTrM'!\ri2@#UUcPVUUTrUeJi9@[iIRfI@hJpJ&991Ba99Aq-B$K9M!Jm2@"996PV999rUeJ\riICeEH&HX"Mj9M"!kICKJ,P@-'$KAUmBq9@X31Rei@#j9Da!k9kp'2PA[%$Tpq(J\rZ9kk'2PA1%$Tpf(!Z9Fi)2(h[FhKpDhYiICaEH&IX"Mj9M"!kICKJ,P@-'$KAlXB\rq9Fi31RhBF#j9cK!k9qp'2PA[%$Tpq(JZ9qZ'2P9V%$TpH&JZ9@X)2(h[@hKpcRY\riICecH$V!!!")!!'JJCX!!$Yl!!4AVUVq9kqS&(h1HhKpRh*i9qX'[P9V%$SjD`-\r!IAjB,PIXaVj9M"!k1B`#!(fHB#jAlSDq9Fi31MR1!3"phR!Z9qp'[PA[%$TprRJ\rZIFjlH(f-FhKpDf0iIjaDH)&l!!!lH`!%9ka0rPHZ5#apM(0iIApLH&I["Vj9la!\rk1Hm(!(hqH#jAkmDq9@X31MPV"J"pIPJZ9qa'[P@-%$SjM!3!ICjJ,PIZKVj9cK!\rk1Fi&!(hHF#jpM(0iI@YMH(h[@hKrR(TiJIX!!$Yl!!4ALkVq9ibS&(eVBhKpreT\ri9qi'[PA1%$SjcJ-!IGj`,PI[aVj9la!k1Hm#!(hqH#jAkiDq9@X31MPV!3"pIPJ\rZ9qa'[P@-%$TpRQ!ZI@YMH(h[@hKpcRYiIlebH)(E!!!lH`!%9ip0rPH,5#apleY\riIGpkH&IX"Vj9M"!k1B`(!(fHB#jAlXDq9Fi31MR1"J"phR!Z9qp'[PA[%$Sjl`3\r!IIji,PIVKVj9Da!k1@X&!(eq@#jpleYiIFjlH(f-FhKr[@*i1YB!!5`@!!K"J2j\rJ2B$`m6Q-m2"rV'!i2F$`m6R1m2"rMR!i9FlK2RfIFhJpi!m21Hm2$hq[H$K9lb!\rf2@!2$cPV$`prLeJiIIeEH&HX"Mj9M"!kICGJ,PHZaMj9cK!kIGG`,PA1%$TAVdB\rq9Hm31RhhH#j9lc!b9kZ'2P9V%$TpGeJZ9@XJ0Rh[@hKpcRYiICacH&IX"Mj9M"!\rkICGJ,PIZaMj9cK!kIGG`,PA1%$TAldBq9Hm31RhhH#j9lc!b9qZ'2P9V%$TpGeJ\rZ9@XJ0Rh[@hKpcRYiICecH$Ylri!pJ+UV1BbUURq-B$Jp`+UV1FkUURqZF$K9c[K\rqICpcH$hJ998jle99Iipi1&A[#$`pB&991@Y99AqV@$Kpr9Yi9k`'2P@-%$TpQ'!\rZ9B`B1&HZaMj9cK!kIGK`,PA1%$TAVdBq9Hm31RhiH#jAUiBq9@X31Rei@#j9D`J\rmIHpEH(h1HhKpR(0i9q`'2P@-%$TpQ'!Z9B`B1&IZaMj9cK!kIGK`,PA1%$TAldB\rq9Hm31RhiH#jAkiBq9@X31Rei@#j9D`JmIHpEH(h1HhKpRA0i1eS!J$UJ!!")!!'\rJ1eVrr)'D!!"AVNhq9kp),(h1HhKpRh*i9qY'[P9V%$SjD`3!IAjB,PIXKVj9M"!\rk1B`&!(fHB#jAlJDq9Fi31MR1"`"phR!Z9qr'[PA[%$Sjl`B!IIji,Rh1HhKpM(0\riI@YMH(qF@RJl@[rmJAS!!&HXU[jAVUJ8IBacH(erBRKAliDq9Hm31MR[!3"prRJ\rZ9qX'[P9V%$SjD`-!IAjB,PIXaVj9M"!k1B`#!(fHB#jpDf0iIHpEH&IZ4Vj9cK!\rkIGj`,Rh[FhKrR(Ti1eVrr)(k!!"ALdhq9ia),(eVBhKpreTi9qj'[PA1%$SjcJ3\r!IGj`,PI[KVj9la!k1Hm&!(hqH#jAk`Dq9@X31MPV"`"pIPJZ9qc'[P@-%$SjM!B\r!ICjJ,ReVBhKpleYiIFjlH(qpFRJl@[rmJGS!!&H2U[jALkJ8IHpEH(hIHRKAl)D\rq9B`31MQ-!3"pRQ!Z9qi'[PA1%$SjcJ-!IGj`,PI[aVj9la!k1Hm#!(hqH#jpcRY\riIBacH&IV4Vj9Da!kIAjB,Rf-@hKr[@*i1V8!!5`9!!K"J2jJ2B$`m6Q-m2"rV'!\ri2F$`m6R1m2"rMR!i9FlK2RfIFhJpi!m21Hm2$hq[H$K9lb!f2@!2$cPV$`prLeJ\riIIeEH&HX"Mj9M"!kICGJ,PHZaMj9cK!kIGG`,PA1%$TAVdBq9Hm31RhhH#j9lc!\rb9kZ'2P9V%$TpGeJZ9@XJ0Rh[@hKpcRYiICacH&IX"Mj9M"!kICGJ,PIZaMj9cK!\rkIGG`,PA1%$TAldBq9Hm31RhhH#j9lc!b9qZ'2P9V%$TpGeJZ9@XJ0Rh[@hKpcRY\riICecH$f!UUXjM+UUIiaJ1$h!UUXjcUUUIkj`1&A1q(jpRh0i2H"996R[999rMhJ\ri9Hm)2$eJ998jDe99IkYB1(hp@hKAV!Bq9B`31RfBB#j9M"Ji9kl'2PA1%$Tpf(!\rZ9Fi31PH[4Mj9la!kIIKi,PHVKMj9Da!kIAKB,P9V#$apleYiIFjlH(fFFhKAl!B\rq9B`31RfBB#j9M"Ji9ql'2PA1%$Tpf(!Z9Fi31PI[4Mj9la!kIIKi,PIVKMj9Da!\rkIAKB,P9V#$apleYiIFjlH(fGFhJkJ!!!5!!"S)'C!!!l13!%9kkUrPH[U"4pcRY\riICpbH&IV"Vj9Da!k1@X$!(eq@#jAl-Dq9B`31MQ-!J"pRQ!Z9qk'[PA1%$SjcJ%\r!IGj`,PI[4Vj9la!kIIji,Rh1HhKpM(0iI@YMH(qF@RL"H3!!1cN!"&HX6IjAVNJ\rXIBacH(erBRKAl`Dq9Hm31MR["`"prRJZ9q['[P9V%$SjD`B!IAjB,PIX4Vj9M"!\rk1B`%!(fHB#jAlSDq9Fi31MR1"3"phR!ZIBacH(eVBhKpleYiIjakH)(j!!!l13!\r%9iZUrPH-U"4pDf0iIIpDH&IZ"Vj9cK!k1Fi$!(hHF#jAlmDq9Hm31MR[!J"prRJ\rZ9qZ'[P9V%$SjD`%!IAjB,PIX4Vj9M"!kICjJ,ReVBhKpleYiIFjlH(qpFRL"f3!\r!1cN!"&H26IjALdJXIHpEH(hIHRKAl!Dq9B`31MQ-"`"pRQ!Z9ql'[PA1%$SjcJB\r!IGj`,PI[4Vj9la!k1Hm%!(hqH#jAkiDq9@X31MPV"3"pIPJZIHpEH(h1HhKpM(0\riIleLH$U8!!%X&!!)3B$qB$f!m2%jM2$`IkaJ1$h!m2%jc[$`Iij`1&A1i6jpRh0\ri2H!2$cR[$`prVhJi9HmJ0MeJ$`mjD`m2IiYB1(hp@hKAV!Bq9B`31RfAB#jAVXB\rq9Fi31RhAF#j9cK!k9kp'2PA[%$TpphJZ9Hm`-PHVKMj9Da!kIAGB,P9V)$CpleY\riIFjlH(fFFhKAl!Bq9B`31RfAB#jAlXBq9Fi31RhAF#j9cK!k9qp'2PA[%$TpphJ\rZ9Hm`-PIVKMj9Da!kIAGB,P9V)$CpleYiIFjlH(fGFhJl1Iq!9ia'2S("rl"pch0\ri1Fi!!C("rl#CM`!!9iZ'2S'"rl"pMQ0i1B`!!C'"rl#CEJ!!9ir'2S&Krl"pE&Y\ri1@X!!C&Krl#Cl!!!9ii'2S(Krl"pkhYi1Hm!!C(Krl#Cb`!!9ka'2S("rl"pch0\ri1Fi!!C("rl#CM`!!9kZ'2S'"rl"pMQ0i1B`!!C'"rl#CEJ!!9kr'2S&Krl"pE&Y\ri1@X!!C&Krl#Cl!!!9ki'2S(Krl"pkhYi1Hm!!C(Krl#Cb`!!,!8!!%'"mpK)!!d\rJ,!8!!%#"$4Kp-%YiLC!!!!!k%!!"9B`'2P@-`!k4JIqXLG!!!$S3!!&9cJBq9Fk\r!(S(Krkaplh0iNH(rV)P`!!!k%!!"9@X'2P9V3#k"JIqXIBaEH*'"rkb*d!!!1K!\r!!9A1"Mk"iIqXIHpcH*(Krkb*F!!!1K!!!99V"Mj9Dm!1N@(rU)Q3!!!!1K!!!9@\r-"Mj9M)!HJF(rU(h1BhL4`IqSLI!!!$S3!!&9l`Bq9Hp!,S&KrkKpDhYiN@(rU)Q\r3!!!!1K!!!9@-"Mk"`IqSIFjMH*("rkKmF"YiN!#"rl#*m!!!1K!!!9A["Mj9r-!\r1LA!!!$S3!!&9D`Bq9@Z!(RqF@hL*N!!!!$S3!!&9M!Bq9Ba!,RqFBhL*d!!!1K!\r!!9A1"MjrR(0iLI!!!$S3!!&9l`Bq9Ih!$SP`!!!k%!!"9@X'2P9VJ"jr[9YiLC!\r!!!!k%!!"9B`'2P@-3#jr[@0iLG!!!$S3!!&9cJBqIlecH*1"rk56SIqJ2H#UUcR\r[UUTrMhJi2@#UUcPVUUTrUeJi9@[iIRhr@hJpJ&991Ba99Aq-B$K9M!Jm2F"996R\r1999rVR!iICecH&H["Mj9la!kIIKi,PA['$KAUmBq9@X31Rei@#j9Da!k9ka'2P@\r-%$TpQ'!Z9kk'2PA1%$Tpf(!Z9Fi)2(f-FhKpDf0iIIaEH&I["Mj9la!kIIKi,PA\r['$KAkmBq9@X31Rei@#j9Da!k9qa'2P@-%$TpQ'!Z9qk'2PA1%$Tpf(!Z9Fi)2(f\r-FhKpDf0iIIeEH$Xj!)!kB!!!5!!"S$Xjrrb"q3!!9kY0rPHX5#apDf0iIIpDH&I\rZ4Vj9cK!k1Fi%!(hHF#jAliDq9Hm31MR["3"prRJZ9qX'[P9V%$SjD`F!IAjB,PI\rXaVj9M"!k1B`'!(fHB#jpDf0iIHpEH(h1HhKrR(*i1cRrr)(C!!"AVkVq9kZS&(h\r[@hKphhTi9qb'[P@-%$SjM!%!ICjJ,PIZ"Vj9cK!k1Fi$!(hHF#jAlmDq9Hm31MR\r[!J"prRJZIFjlH(f-FhKAkdDq9@X31Req@#jpM&YiIjaLH$Xjrrb"Q3!!9ij0rPH\r25#apcRYiICpbH&IV4Vj9Da!k1@X%!(eq@#jAl)Dq9B`31MQ-"3"pRQ!Z9qi'[PA\r1%$SjcJF!IGj`,PI[aVj9la!k1Hm'!(hqH#jpcRYiIBacH(eVBhKr[9Ti1cRrr)&\rj!!"AM+Vq9ikS&(f-FhKpIf*i9qq'[PA[%$Sjl`%!IIji,PIV"Vj9Da!k1@X$!(e\rq@#jAl-Dq9B`31MQ-!J"pRQ!ZI@YMH(h[@hKAlNDq9Fi31RhHF#jplh0iIlekH$T\rc!!%X%`!)3B$qB$hJm2%jlr$`Ikpi1$eJm2%jDr$`IiYB1&9Vi6jpreYi2B!2$cQ\r-$`prV'!i9B`J0Mh!$`mjcJm2Iij`1(fGFhKAV`Bq9Hm31RhhH#jAUmBq9@X31Re\rh@#j9Da!k9ka'2P@-%$TpPf!Z9B``-PHZKMj9cK!kIGG`,PA1)$CpM(0iI@YMH(h\rm@hKAl`Bq9Hm31RhhH#jAkmBq9@X31Reh@#j9Da!k9qa'2P@-%$TpPf!Z9B``-PI\rZKMj9cK!kIGG`,PA1)$CpM(0iI@YMH(hp@hJpi+UV1HqUURq2H$JpB+UV1@ZUURq\rV@$K9DrKqIIpEH$f!998jM&99IiaJ1&@-#$`p`&991Fj99AqZF$KpRA0i9km'2PA\r[%$Tpq(JZ9HmB1&HVaMj9Da!kIAKB,P9V%$TAV%Bq9B`31RfBB#jAVSBq9Fi31Rh\rBF#j9cJJmIBacH(eVBhKpr&Yi9qm'2PA[%$Tpq(JZ9HmB1&IVaMj9Da!kIAKB,P9\rV%$TAl%Bq9B`31RfBB#jAlSBq9Fi31RhBF#j9cJJmIBacH(eVBhKpr9Yi1N!!!%J\r!!D#"qJ!!1eS!"&HVU[jAV+J8I@YMH(hr@RKAlJDq9Fi31MR1!`"phR!Z9qr'[PA\r[%$Sjl`)!IIji,PIVKVj9Da!k1@X"!(eq@#jAl%Dq9B`31RfHB#jpDf0iIHpEH(h\r1HhKrR(*iJGS!!$YD!!4AVdhq9kY),(h[@hKphhTi9q`'[P@-%$SjM!F!ICjJ,PI\rZaVj9cK!k1Fi'!(hHF#jAldDq9Hm31MR["!"prRJZ9qZ'[P9V%$SjD`8!IAjB,Rh\r[@hKpcRYiIBacH(qFBRL"QJ!!1eS!"&H1U[jAMkJ8IFjlH(fIFRKAk`Dq9@X31MP\rV!`"pIPJZ9qc'[P@-%$SjM!)!ICjJ,PIZKVj9cK!k1Fi"!(hHF#jAldDq9Hm31Rh\rqH#jpcRYiIBacH(eVBhKr[9TiJAS!!$YD!!4AM%hq9ij),(f-FhKpIf*i9qm'[PA\r[%$Sjl`F!IIji,PIVaVj9Da!k1@X'!(eq@#jAl%Dq9B`31MQ-"!"pRQ!Z9qk'[PA\r1%$SjcJ8!IGj`,Rf-FhKpDf0iIHpEH(qpHRJk8J!",")!#%'!rQ!pi2$a1Hr`m(q\r[H$JpB2$a1@[`m(q,@$K9Dq%qIIpEH$f!$`mjM!m2IkaJ1&@-)$Bp`!m21Fi2$hq\r1F$KpRA0i9km'2PA[%$TpphJZ9k['2P9V%$TpGeJZ9@X31PHX4Mj9M"!kICGJ,P@\r--$*AVSBq9Fi31RhAF#j9cL!fIBacH(eVBhKpr&Yi9qm'2PA[%$TpphJZ9q['2P9\rV%$TpGeJZ9@X31PIX4Mj9M"!kICGJ,P@--$*AlSBq9Fi31RhAF#j9cL!fIBacH(e\rVBhKpr9Yi1eVrJ$hJUUXjlkUUIipi1$eJUUXjDkUUIkYB1&9Vq(jpreYi2B"996Q\r-999rM'!i9B`)2$h!998jcP99Ikj`1(fGFhKAV`Bq9Hm31RhiH#j9laJi9k['2P9\rV%$TpH&JZ9@X31PHX4Mj9M"!kICKJ,PHZKMj9cK!kIGK`,PA1#$apM(0iI@YMH(h\rm@hKAl`Bq9Hm31RhiH#j9laJi9q['2P9V%$TpH&JZ9@X31PIX4Mj9M"!kICKJ,PI\rZKMj9cK!kIGK`,PA1#$apM(0iI@YMH(hp@hJlH`#!1L!!!%J!!D!lHrrmJIX!!&H\rV6IjAV%JXI@YMH(hr@RKAlNDq9Fi31MR1"!"phR!Z9qq'[PA[%$Sjl`8!IIji,PI\rV"Vj9Da!k1@X(!(eq@#jAl-Dq9B`31MQ-"J"pRQ!ZI@YMH(h[@hKpcRYiIjabH$Y\rlrrb"f`!!9kqUrPHVU"4pleYiIGpkH&IXKVj9M"!k1B`"!(fHB#jAlJDq9Fi31MR\r1!`"phR!Z9qr'[PA[%$Sjl`)!IIji,Rh1HhKpM(0i9qY'[P9V%$TpIPJZIBaEH(q\rFBRJlHrrmJCX!!&H16IjAMdJXIFjlH(fIFRKAkdDq9@X31MPV"!"pIPJZ9qb'[P@\r-%$SjM!8!ICjJ,PIZ"Vj9cK!k1Fi(!(hHF#jAlmDq9Hm31MR["J"prRJZIFjlH(f\r-FhKpDf0iIleDH$Ylrrb"H`!!9ibUrPH1U"4pM(0iIApLH&I[KVj9la!k1Hm"!(h\rqH#jAk`Dq9@X31MPV!`"pIPJZ9qc'[P@-%$SjM!)!ICjJ,ReVBhKpleYi9qj'[PA\r1%$TphR!ZIHpcH(qpHRJk-3!","%!#%'!rQ!pi2$a1Hr`m(q[H$JpB2$a1@[`m(q\r,@$K9Dq%qIIpEH$f!$`mjM!m2IkaJ1&@-)$Bp`!m21Fi2$hq1F$KpRA0i9km'2PA\r[%$TpphJZ9k['2P9V%$TpGeJZ9@X31PHX4Mj9M"!kICGJ,P@--$*AVSBq9Fi31Rh\rAF#j9cL!fIBacH(eVBhKpr&Yi9qm'2PA[%$TpphJZ9q['2P9V%$TpGeJZ9@X31PI\rX4Mj9M"!kICGJ,P@--$*AlSBq9Fi31RhAF#j9cL!fIBacH(eVBhKpr9YiJH(rV(q\rFHRL"BIqSIleDH#`&!!K!J3$F1+Arq&H-4Mk"`Iq`IFpcH$R1!!'4`Iq`QBm!!&H\r,KMk"JIq`IBjMH$Q-!!'4JIq`Q@i!!&H2aMk"BIq`I@aEH$PV!!'4BIq`QH`!!&H\r1"Mk"iIq`IHYlH$R[!!'4iIq`QFX!!&HX4Mk"`Iq`IFpcH$R1!!'4`Iq`QBm!!&H\rVKMk"JIq`IBjMH$Q-!!'4JIq`Q@i!!&H[aMk"BIq`I@aEH$PV!!'4BIq`QH`!!&H\rZ"Mk"iIq`IHYlH$R[!!'4iIq`QFX!!)'"rk54JIqXJF(rS*("rkK,rr5-JH(rX(h\r[+K54iIq`+!8!#%'"!,JjBK[`9+`31ReVB#jpD31Q6S!%)&HZ"Mk"iIq`1Hrrrj(\rKrl#Cc`!!9k['2S'"rl!jM2rrNB(rX*PX!!"AVSBqJH(rX$R[rrq4iIq`QFm!!&H\rV4Mk"JIq`1Bcrrj'"rl#CE!!!9ii'2S(Krl!jlrrrNH(rX*R2!!"ALmBqJB(rX$Q\r-rrq4JIq`Q@`!!&H1KMk"iIq`1Hrrrj(Krl#Cc`!!9iY'2S'"rl!jM2rrNB(rX*P\rX!!#j`Iqi6S!!)!#3"L"!!")!N!3D'!!4,Q4PFemcBf*MAf9ZBh*jF(3![X(rf$V\rL(63k`K`dI*NMH(ai'hL)Z!!!1aJ!!95r"Mk)f!!!1aJ!!96'"Mj8aN!ZIrmcH)M\ri!!!l'!!"91F'2P6RJ"jrrcYiL4J!!$XB!!&9#!Bq93M!$Rrr3hL*1!!!1aJ!!98\rq"Mk*@!!!1aJ!!99+"Mj95N!ZIpj6H)Pi!!!l'!!"9@X'2P9VJ"jrhPYiLCJ!!$X\rB!!&9M!Bq9Bc!$RrHBhKAaH%qI+AkH$c!$`miaJm2I,``1(rriRKAKb!fIpikH&I\rSN!!DI3MkH(8Fc-aALA5qIqVLH(dr8RKAbj!!'ReVmRKeI-c-9iad[Rr&iRKpRLT\ri9mEiIRc'qRJmi&9911G99AcF1$Krrq*i9iJ)2(rH3RKAkF)qI5RbH$e!!2mj5J$\rrI6a31(rHiRKALd!ZIrpDH&I-q(jpM2Ti2+"996LP999pR#JiIrrLH&H'#$arhM*\ri9qF!"P6Ri6jAb!)H93L%2PI*"Mj9+B!H9mS%,RdT8hKp#%YiI2j$H&Ir!6ilB!!\r!5!!"@&GV%$TpGPJZ,!X!!%'#!#"Al2#q9qA3#RfI+hKAa[#q9mI3#RcH1hK)!!!\rF9qMiIPITf!Kp(dYi9mViIPI,f!KpAPYi9rm"2PIH!6jAl&Di9q9RrPIQAhamT60\riIB`VH&@-%$SjM!-!ICGJ,PIRRcjAk*DfI1G$H&6R%$Sij`)!I2Fi,PITeljAkXk\rkI5P6H&8T%$Sj+3%!I6G),PIV"Vj9Da!kIAGB,RdT@hKmjdYiICSlH&I-AcjAa9D\rfIB`VH&@-%$SjM!F!ICGJ,PI'MVj8aK!k1-B'!(cA-#jAa`Dq91F31MMR"!"mpcJ\rZ9mM2[PI*aVTp#%Yi93J31MN)"3"p&d!ZI1G$H(c'1hKpR$0i9iU!(PG,"$jpA9Y\ri9k`A[PHP%$TpM#S8NCN!!$Xj!!4A4S3q9iF!(RcG1hKAU$Dq9kN`-Rd)5K54'3!\r!1cN!"$Yl!!%X'`!33B$qU$KJ!!#k`IrB6S!!)!#3"L"!!!S!N!3#m!!-,Q4PFep\rcCA4IDf9j!!"m#!+QN!!"!!L8)Ir!N!"K!&L3!)%!A)"K!&L!J3"F1+)Y`%J!!$P\rJ!!!!1')Y`)!"!%Ji)3"!I!J$TNk!!#!!N!BJ3B!!N!Bm!!SZC'9cAf0bHA"dI!J\r#TVj"rmL3!!%!#*3Kr["mGKYiI*3MH(bk+hJkiKcd1`%!1)Kd!!"mB`Gd,!-!!%#\r#!!`iJ!""5!!!$)L8!!"mK!GdQ*S!!(b9"h3iSKadI+@SVP5c%$U)e!!"I-B(G#`\r'!!"!JJ!-11!!38J!!!b)p!!"I1F(G*Mk!!&mp3Gd13)FG(d)U+j9%M!b1f!!!%J\r!!#b,eJ!!1YB!!9I*"MiS#3!!3B)!0&I+"Mj95JJm1@%!a(e,fDilH`!"+"X!#%'\r!rp4)!!!81B!!!$KK!-4pJpQZ1hX!!5JE!!K"J2rX1'%!a$L"!%4,rrZaB!!!!$K\rK!-`iJ3"%IQ@EH(j'NhK)!!%aB!!!!)-K!-aA*!BqQ*J!!$XB!!&A*FBqQ,J!!$X\rB!!&A*SBqQ0J!!$XB!!&A*dBqQ2J!!$XB!!'$)3$39bJ'2TNB!!!l'!!"9bR'2TN\ri!!!l'!!"9bU'2TPB!!!l'!!"9bY'2TPi!!!l'!!"1i!!!$[J!)!jJ!!!QB%!3$Y\rJ!!*)!!"N1m!!!$ZJ!!")!!"!9pi)2$KK!$KmBq#Z9q3'2RaM)$JX!`!!3B)!#'2\rH!!&Arrjq9q8'2LJ&!!"!JJ!-1j`!!6[J!)!l[3!"+"d!"N'!rm"AaJBqI0F`VRc\rDfDilH`!"+"X!$8'!rj`ii!!!Q2S!$Ap$dhL!!3%B1#%"%(`)!kDk3Ir)6S!!)!#\r3"L""J!i!N!3#%!!,,Q4PFepQBh*jF(3!!!#q!Ir!1k)P0$Z!!!!lB!!!I*8MH*!\r!SIq`N!$"rk`ii!!!N!$Krl4)!!4-1X!!!%J!"#4AD)3qIhp#H)%Krl"rrNJiJ8(\rrV(rr8$KAfS!H9XX31Ree@#jrDeTiIpjDH(rHdRKAqS!H1CB!!9@-%$TpP@!ZIfa\rLH(rrBRKrrp*iIp4'F&ID"MT@P!Bk9qIK2PISi!Crjd)89pk%2Rdpd#jrR%Ti193\r#!(eG8#jrR&*i9p2#2PID"MT@F`Bk1AS%!(ep@#jrR&Ti1C-'!(fGB#jrR'*iIr4\r'F&Ik"MT@P!Bk9rq%2MMk!3"mr6JZIj`kH$N8!`"p(8!ZIja#H(rc4R"AqJBk9R-\r'1MNk"3"p28JZIja+H$P6"`"pA9!ZIja5H&H,K$jrReTiJB(rX(rqB$L!iIqXIrm\ri1&ICJ"ij&J!#93J31Rd93#jrL%*iIpj#H(rHbRKAqB!H16B!!e8T%$Tp08JZIiP\r+H(rr5RKrrmTiIp*'F&IC"MT@8JBk9qVK2PIVi!CrkPS89pk%2RfGb#jrHf*i12)\r#!(cp1#jrHcTi9p(#2PIC"MT@-3Bk14N%!(dG3#jrHd*i16%'!(dp5#jrHdTiIr*\r'F&Ij"MT@8JBk9rq%2MPC!3"pA9!ZIhY5H$Pb!`"pI9JZIhYDH(ra4R"Aq3Bk9M%\r'1MQC"3"pR@!ZIhYLH$Ma"`"mr6JZIhXkH&GSK$jrId*iJ5(rX(rq5$L"3IqXIrp\r31&IBJ"ijGJ!%9@X31Ree@#jrDeTiIpjDH(rH`RKAq)!H1CB!"9@-%$TpP@!ZIfa\rLH(rrBRKrrm*iIp"'F&IB"MT@%!Bk9qIK2PISi!Crjd)89pk%2Rdp`#jrR%Ti19!\r#!(eG8#jrR&*i9m[#2T&KrkKAf!BkJB(rU&@-"MU4JIqS12J%!(cp1#jrR$TiJ3(\rrU$N)"J"p(8!ZIja#H(r`4R"Aq!Bk9K!'1PIrK$ij1!%!I6e),RqF5RJj8!-!I9e\r3,RqF8RKrkdC`N@(rU&Ii"MU"JIqS9B`'1T'"rkJiq!8!I2di,RqF1RL"!IqS13J\r(!(dG3#jrR%*i9iQ%2RqI5RL"3Iq`Irj31)&KrkarreJi9pH!(MQ@!!C9M"!kIC9\rJ,Rq-BRKrhQ*iIpkkH&IhJ"iipJ!(91F31Rce1#jrKcTiIrmkH(rrZRKrb%C`N3(\rrT&IA"MU")IqN95N'1T%Krk4AkZ%q9q[J"RrU@K4AhS3qICfi,RplBRL!iIqN11F\r#!(cp1#jrHcTi9mM#2T%"rk"Ae`BkJ5(rS&8T"MU4)IqJ19F%!(eG8#jrHe*iJ@(\rrS$PV"J"pI9JZIhYDH(rX4R#4JIqN9rF'1S$Krk48j`BkN!$Krk4Ari3q14F"!(d\rG3#jrHd*iJ5(rT$NT!`"p28JZIhY+H(rU4R#43IqJ9rF'1S&Krk"9D`BkN@(rS$Q\rA"3"pR@!ZIhYLH)$Krk!ij`F!I2di,Rpl1RJkeJ!),"B!)%'!qparRq0iIhcEH(r\rlqhL"!Iqd13J!!C%"rl5")Iqd,!N!'8'!ql"ALZMq9i[S"(q+@K4AE1Mq9fIS"(p\rX1K4AL2KqI3MDH$dJ998j+999I4p)1(plqRKAkJJmIja5H&GV`MjpDq*i2B!!rcQ\r-!2ppIf!iIjckH&IR3#jrHcTi9iM`[Rd)fRJp)$-c15Nc-hdI5$KrHrTi9qS31Rq\rF8RKADi3qI@[LH&9r"$jrR2Ti9qb!(RplBRKAKq%qI1IDH$d!$`mj#!m2I2p!1(p\rlqRKAk5!fIja+H*0M!!#6J`!%ZJ(r`%k!!#!!N!BJ3!!3!*!%"6`!$#jQBh*jF(4\rIBQpNH3!!I!J#TVp"rqL3!!%!#*3Krl"mHKYiI*mMH(bl+hKmh$0iI2dlH(dH3hJ\rX(J!!3B)!B(p$dhKrj2YiIfAEH(r'mhK,rlFGB!!!!(rMqhKrj2YiIiAMH$MJ!!!\rX(J!!3))!#$MJ!!&mjMYi5rqfp@!!!!"rirYiIq6lH(qPkhKra[0i5rqfh@!!!!"\r)!!"FId26H(rNqhKrTHYiImEcH%[rYX&J!!!!Iq2lH(rNqhKrKH0i13!!!#`H!!"\r!JJ!)13!!!Ad'3hK,rlDCB!!!!(rMqhKrj2YiIfAEH(r'mhK,rlD"B!!!!)!"!&J\ri)3"3I!J$TVY"rqK1J!!J!*!')%'!"J#3"IJ!%5jNCA0I-f9MBPpPEQ0bHA"d!(a\r$%hK1J!!JI!J#TT!!!3!)P#(r`%[rrqemD4YiJ')!F)##!'`iSJ!!1-)YcS$L!'#\r"!J"F5!!!@B""!"5!JJ$8N!"N!!",rk0CB!!!!$KJ!!#!!3")1#%!3(`)!kC1J!!\rJI!J#TT!!!3!)P#(r`)"L!05!B`!!5!!!-B""!"5!!3")1#%!3(`)!kC1J!!JJB)\r!2*!!33!8J!`!!)"-!!4m#31Q6S!%))'#!$L3!%%!&)!-!!#!6!!%I!N$TNk!"##\r"JJ!BN!""!"5!$!!!J%`!"(`*!kC1J!3JJB)!%*!!33!8J!`!!)"-!!4m#31Q6S!\r%))'#!%#3!%%!&)!-!!#!6!!%I!N$TNk!"##"JJ!JN!""!"5!$!!!J%`!"(`*!kC\r1J!3JJB)!$*!!33!8J!`!!)"-!!4m#31Q6S!%))'#!"53!%%!&)!-!!#!6!!%I!N\r$TNk!"##"JJ!NN!""!"5!$!!!J%`!"(`*!kC1J!3JJB)!#*!!33!8J!`!!)"-!!4\rm#31Q6S!%))'#!#L3!%%!&)!-!!#!6!!%I!N$TNk!"##"JJ!XN!""!"5!$!!!J%`\r!"(`*!kC1J!3JJB)!"*!!33!8J!`!!)"-!!4m#31Q6S!%))'#!!#3!%%!&)!-!!#\r!6!!%I!N$TNk!"##"JJ!`N!""!"5!$!!!J%`!"(`*!kC1J!3JJB)!(*!!33!8J!`\r!!)"-!!4m#31Q6S!%))'#!$53!%%!&)!-!!#!6!!%I!N$TNk!"#!!!!!FJ!!!I!J\r!N!DBJ!!!6!#3"LQXJ!!!Q!J!N!8U4)!!!)!)!*!&+X5!!!$3!*!'+j5!!!#3!"!\r!N!8X*)!!!'!!N!BXK)!!!+J3!*!&,5b!!!&)B!#3"5m)J!!"4%!!N!8`6)!!!+!\r)!*!&-1b!!!(m5!#3"6,SJ!!"`&!!N!8dU)!!!0!B!*!&0AL!!!#J'!#3"90NJ!!\r!@!#3"P1mJ!!#-(!!N!9E5)!!!4``!*!&A'b!!!"B!*!'A-5!!!!X!*!04L)2-!)\rL%c!#)JX`"L)G0))#"#8dAhKHL#h1"#*IH!BL!F5#!KJ"k!))!LJ#6!F`!c!$%!,\r3!T!!!R!YZ#di!0JE6aX`'fJEEa[`("3F0"cd((3Y`!$S!L%+!5)PH!%L,#!")L"\rp#5'BKJ)D!"`!j!b8%U3C`"MS'VJQC#QX,)3X*#Z8+X3U4#dX,`J`l$"--ZJdU$9\ri0KK39&1m8f4E5#)-C))#+JaB$%`-3!`d$#J-(!`3$!3$%!,m!ZJ#e!,%!V!#R!+\r)$V31S!k-$RJ1D!j8$N!1,#Bd*LJQ(#B3*J3Pq#AX*H!Pe"c8(-!FV"bB()JFG"a\rJ(%`F2!8K%)%$"J!3!!!3%"!!!"!!%"!3!"!3%!3K%!3K%!)L%"!%)4#"!`X3!"!\r!%*!&!!!"%!!"!"!"%"!"!!!4%!!4!"!4%"!4"L%"!L%"!b)"!3%K!3-K!3%K!3%\rL!3%#*!'3"!-K!3)L!3%")3%")3%"*!'3"!)L!3%"*!'3"53"N!3%)3%%)3%#)J%\r""#%"!5%"!5%"!L)"!3%M!3%"##%%J3-0!3!!!3!%!!3!!!3%!33!!33%!!!J!!!\rN!3!J!3!N!!3J!!3N!33J*!%%*!%$)3%#)`3"!3)L!3%")J3"!5%%!5%"!58%"!%\r""!%P!3%%"!%#)L!"!L-N!3%")b!"!3%L*!%")`3J!3%U"#3"!33J!3%%*)%$$`)\r!!!)!"!-!!!-!"!)%!!)%"!-%!!-%"!)!)!)!*!-!)!-!*!)%)!)%*!-%)#8$"#3\r"!J)L!3)")`3"!`)L!3-"*!3"!J3"*`%#"!3"!`3"*J%$"!3"!J%M)!%#!5-N!3-\r")b!"!`%a*!%#"#!"!J3N!3-%)!%$"#3%)3)&)3J")3)")3J#)3J#)J))!b))#!%\rM!JJ)"#)"!J)K!3)M#!%#!5))!3%K#!%M!3))!5%"!5F)#!%##!J"!L%"J3-(!J!\r"!!!*!J!*!!J"!JJ"!!J*!JJ*!L-"!3)")J%"!L-*!3)")JN"!5F)!3%##!%"!5J\r)#3%##!N"%!-K%J-K%!%K#!%K%J%K#!%L%!J#)K))!L-3#!J")a))#!%K%!)L!4)\r#)J%3!5-)!4)"*!J"%!J")`%5#!%U!4!)#!%5#!J"%!%K!B%$"a)!!4!!#4)!#4!\r)!4))!4!)#4))#5%3!5-"!4)")`%"%!%M#3%5!6)*!4!)!3%5#!%"%!J*!4))#3%\r&)33%)5##!J3%)"!!&!!3)#)8))%$##!!!#!%!#!!)#!%)#!3!#!8!#!3)#!8)!-\rK#)%$"J3!#!!J#!3J#"!!#"3!#"!J##38)!JJ!L-))!3")JJJ!5JJ##!%)!JJ%!%\rM##!8!5N))"!J##!8)!L"!`FJ!!!N!!!J)!!N)!!`!!!d!!!`)!!L0##"!`JJ)!!\rJ*!!JN!3N)#!`!#!d!#!`)#!d)!%K)!%K#)%$"L3!##!J##3J#$!!#$3!#$!J##8\rd)!JJ)!%M##!N!5X))#!J##!N)!JJ-!%M##!d!5N))$!J##!d)!J()K!)J3-r!!!\r)!"!!!J!!!K!)!J!)!K!!!!)!!"))!!))!")!!J)!!K))!J))!K)%!!!%!"!-!!!\r-!"!%!J!%!K!-!J!-!K!%!!)%!")-!!)-!")%!J)%!K)-!J)-!K)!%!!!%"!)%!!\r)%"!!%J!!%K!)%J!)%K!!%!)!%"))%!))%")!%J)!%K))%J))%K)%%!!%%"!-%!!\r-%"!%%J!%%K!-%J!-%K!%%!)%%")-%!)-%")%%J)%%K)-%J)-%K)!!!!#!b%#!L)\r#!J3K!3%K!J%K!3)L!J%")`)#!33L#!)#)3J")3)")`J#!J%K#!)M!3J#!5)"#!%\rR!J%)!J)"#!%K)!)L!L!$)5)#)J)L!b)J!3%M!L!"!L)L!3%M!L)"!L%J!5-)!L!\r")3J")5)")`J#)J%K#!%R)!%)!L!"#!%R)J%)!L)"#!)K!S%$"`)!!J!#N!8!!!-\r#!!-!!J-#!J-#)`))!J%L!JJ"*`)##!)#!JJ#)`-)!J%L!`J"*`)$#!)#!`J")L!\r#J3-(!L!#!#)#!L)#!#!$!L!$!#)$!L)$!5FJ!JJ#)!))!5FL!JJ#)J))!5FJ!`J\r#)!-)!5FL!`J#)J-)"L%3"#%J!L)3)!%K%!-L%"!#)4!")5!"*"!3)!J$)3J")4!\r")3J#)L!)!533)!J3!L-)%"!")JJ3!58J#"!3))%$"`!!"!!3"!!!*!!3*"!!""!\r3""!!*#33%#3)!L)%#!%M%!3)!L)N#!%N%#3)%!%R"!J3%!3)%!%P*!J3%#5"!`F\r!"!!!&!!!"#!!&#!3"!!3&!!3"#!N%"3J#!%K"!%K#!%K&!%K#!%M"#!)!588)!J\r3"!%M#"!8!5J)%!3J#"!8))%$"`!%"!!8"!!%*!!8*"!%""!8""!%*#33&#3)!5-\r%"!J")a3%#!%M"#3)!6)8*!J3"!3)%"3%#"!%*!J3&#3%)4!%)3%#)K!""5)#%!)\rK!J%K!3%M!K!"!5%#!L%J!5%3!5%J!L)")!%M%!%J!b-J!K!")L!#!5F")!)3!5!\r#!5%%J3-(!"!%!!!&!"!&!!!%!K!%!J!&!K!&)3)")J3J!5-3"#!#)J8J!5-3"5!\r#*`3J!K!%)!)"+!8J!K!&)!)J!b%`!b)J!3)L-!%#)5!#)J)`!L-#)!%")`)`!3%\rL!L!")5!")6!")5!")b!")!%M-!%J!5%J!5-J!M!",#!#)!%J!M!")!)J")%$"`!\r`"!!J"3!`"3!J"!)`"!)J"3)`"53#)!3J!5-`"#!")b!&)!%M-!8J!6!J"#!#-!3\rJ!L!&)!)`"5!#"#%%"L)""))#$!%"!!8!!3%&!3!3""!!%334!4!&%!%4"5%4!5%\r)J3-2!!3)!!!)!33)!3%)!!8)!!%)!38)!3!)%!3)%!!)%33)%3%)%!8)%!%)%38\r))4%#)3J")35"!`i)!!!)!33)!3%)!!8)!!%)!38)!3!)%!3)%!!)%33)%3%)%!8\r)%!%)%38L#"%")JJ)!5-%#!J#+JJ)!33)#!%"#!J")`8)#!%S!3J)!38)#!%"*`J\r)%!3)#"!"0`J)%33)#"%"#!J3"3J)%!%)#"%&#!J4"b%3JJ)0!!%!%4!!%"!3!4!\r4!3!"%!%"!4%4!"%3%3%L%4'"!bm3!!!3!"!3!!%3!"%3%!!3N!8"%"!4%!%!%!%\r3%!%"%!%4%"%!%"%3%"%"%"%4!3!!!3!3!3!"!3!4!4!!!4!3!4!"!4!4!3%!!3%\r3!C!&%3%4!!%4%!%4!3%4%4%!!"%!%"%!!4%!%4%3!"%3%"%3!4%3%4%"!"%"%"%\r"!4%"%4%4!"%4%"%4!534%4%3J3-2!!!3!"!3!!%3!"%3%!!3N!8"%"!4%!%!%!%\r3%!%"%!%4%"%!%"%3%"%"%#34%4!3!L)3%!%M%"!3!5-"%"!"*"%3%"!",a#3"`%\r3%"!4%"!"!5m3%!%3%"!"!4!3!4%3%"%",K!3%4!3%"%"%"!4%4!"!L)3!3%M%"!\r"!5-"%!%"*"%3!4!",a!"%"!3!4!"%!%3%4!"!3%[%!%"%"!"!3%3!3%4%!%4!5i\r3!4%3%!%4!4!"%4%3%3)L%"%")a!3%3%M!4!4!534%"%3!5m3%4!3%"%3!4!4%"%\r3%3%",a!4!4!3%3%"%"%"%4!4%3%Y%"%4%"!4%3%3%4%4!B%$$`!!!3!3!3!"!3!\r4!4!!!4!3!4!"!4!4!3%!!3%3!C!&%3%4!!%4%!%4!3%N%4%"%!)L!4!")a!"%!%\rM!3%3!534!4!3!5m"%"!3!4!3!3%3%"%"%!%",`%3!4!"%!%"!4!"%3%3%3%Z!4!\r4%!%3%3%"%"%4!3%#)J%"!5-3!3%")`'3"#34!3%3!5m"!4!3!3%3!3%"%"%"N!3\r[!3%"%!'3"a%"!4%",J%"%4!"!4%"!3%4%3%4!L)"%3%M%!%4!5-"!4%"*"%"%4!\r",`%4%"!"%4!"!4%3%3%4!3%[!4%"%!%4!3%"%3%4!4%4!5d"%4%3!4%4!3%4N!5\r"!`m!!"%!%"%!!4%!%4%3!"%3%"%3!4%3%4%"!"%"%"%"!4%"%4%4!"%4%"%4!4%\rN%4%4%!)L%4!")a!4%!%M!4%3!534%4!3!5m4%"!3%4!3!4%3%"%4%!%",a%3!4!\r4%!%"%4!"%4%3%3%Z%4!4%"%3%3%4%"%4%3%#)K%"!5-3%3%")`%4!3%N%4%"%!%\r[%3%3%"%"%!%4!4!4%3%"!5m4!3%3%3%"!4%"!4%4!4%",K%"%4!4!4%"%3%4N!3\r#)K%4!5-3%4%")`%4%3%N%4%4%!%[%4%3%"%4%!%4%4!4%4%"!5m4%3%3%4%"!4%\r4!4'3"!%X%4%4%"%4%3%4N!3%)3)%)3)#)J)#"#%#!5%#!5%#!L)#!J%M!J)#"#)\r#!J)K!J%K!J%M!J)#!5%#!L-#!J)")J)#!5J#N!F"!b%$!b)"!J)L!`)#)3%")3)\r")3-")3)")`%#!J%M!`)#!5%"!L)#!`)M!J%#!5-#!`)")J)"!5-#!J-"+J)#!3)\r#!J-#!J)")3%#)J)"!b%$!L)#!`-L!3)")`)"!J)L!`)")`)$!J)K!3%M!J)"!5%\r#!5%$!5-#!J-")3)"*`%#!J)"!J)"+3-#!J)$!J)"!3)L!`%#)J%$!L)$!`)M!3%\r#!5-$!3)")`%$!J%M!`-#!5)"!3%M!J-"!5-#!3-")`)$!`%a!J%"!J)$!3)#!3-\r#!J-$!J)#)3'"!`F#!!%!!J%#!J%!!!-#!!-!!J-#!J-#)`%#!J%L!3)"*`)"!J)\r#!3)#)`-#!J%L!`)"+!)$!J)#!`)"!5%"J3-(!`!"!3)"!`)"!3!$!`!$!3)$!`)\r$)3%")`%#!`%V!3)"!J%#!`)"!J%")`-#!`%U!`)"!J-#!`)$!J%L!3'"!`F#!3%\r!!`%#!`%!!3-#!3-!!`-#!`-"*`%"!J)"!3)"*`-"!J)$!3)"*`%$!J)"!`)"+J-\r$!J)$!`)"!3'"!`F$!3%"!`%$!`%"!3-$!3-"!j!&)#!"!3%#!`%"!J%$!3)$!`%\r#!3%$!J-"!`)"!`-#!`-$!J-L!3)#)3%")3)")`%#!J%K!3)M!J%#!5)#!3%R!J)\r"!J)#!3-L!`)#)3-")3)")`-#!J%K!`)M!J-#!5)#!`%S!J)$!J)#!`%#)J%$!L-\r"!3)")`%$!J%L!3%")`)"!`%V!J%"!J)"!`)#!3%#)J-$!L-$!3)")`-$!J%L!`%\r")`)$!`%U!J-"!J)$!`)#!`%K!3%M!3)"!5%"!5%$!5-"!J-")3%"*`%#!3)"!J%\r"*`-#!3)$!J%")3%")`-#!3%K!`%K!`%M!`)$!5%$!5F"!J-#!3)$!5N$!J-#!`)\r$!3%")`%$!3%M!3%$!5-"!`-"-`%"!3)"!`%#!3%$!J%$!`)"N!3M!`-"!5-$!3-\r")`-$!`%a!`%"!J-$!3)$!3-#!`-$!J-#)`%"!J%L!3%"*`)"!3)#!3%#)`-"!J%\rL!`%"*`)$!3)#!`%#)`%$!J%L!3-"*`)"!`)#!3-#)`-$!J%L!`-"+!)$!`)#!`-\r"!5-"!3-"+`%"!3)"!3-#!C!%)`-"!`%V!`%"!J-"!`)$!3%")`%$!`%V!3-"!J%\r$!`)"!`%")`-$!`%U!`-"!J-$!`)$!`%R!3%"!J'3"#F$!3%#!`%"!5F"!`%#!3-\r"!5F$!`%#!`-"!5F"!3-#!3%$!5F$!3-#!`%$!5F"!`-#!3-$!5"(!`-$!J-$!`'\r3"!-"N!3$!3%$!`'3"!-"!`%$!3%$!`%$!`-"N!3$!`%"!`%$!3-$!`%$!3%$!`-\r"!`-"!j!(!5%3!L)#%!%L!3)")J3""L%%!5%#!5)%!3%Q%!3"!K!%!53#%!3"!5%\r3"L%#!L%"!b)"!J-L!K!")3%#)`3"!J%K"!)M%!3"!5%3!5)"!J%K"!%K!J)M!3)\r3!L-#%!3#)4!")`%#%!3K"!-Q"!%#%!3"!5)3"!3L!3)%)K!%!5%#"#)3"!)K%!)\rK!J%M"!%#!53%!3)3!5-"!K!")3%$)3%")4!")J%#!b%#!5%%!L%3!L-#%!3$)J3\r"!5B3"!%#%!3$)`3"!J)R!3)3"!%#%!-L%!3)*3%#%!3""583"!%#%!3K"!%K!J)\rL!3)")33$)33#)4!")3%")S##"b'!!L1!JJ+"!aL!J!)!JJ)!!!)!J!!!!J#!JJ#\r!JJ)!!J#!!J+!J!+!!*!%!J!#!S!#!)!#!!##!!##!)#!!)#!!)!#!J#!!S!!!S!\r!!J#!!J8L!J+"!ad!JJ+!!!!!J!#!JJ)!!!+!J!#!JJ#!!!#!!!!!!J#!J!)!J!!\r!JJ#!!!)!!J!!!!+!!J)!JJ+!JJ)!J!+!J!#!!J+!!!)!!J)!JJ+!JJ!!!J+!!J#\r!!J!&)S!#!L'#"L1!J!)#*3%%"!%""5)%!3%L"!3")3%'*!%""!3")3%#)3%")J3\r%!L)%"!)K"!%K!3)N"!%""!%K!3%M"!3""#-""!3'*!3%!3%$)3%#)J%"!5)%!3)\rL"!%")33"*!%""!3")J%%!5)"!3)K!3)K"!%L!33$*33%!3%%!L%"!5%%!b-%!3%\r")33%)3%")33#)J%%!5%"!L-%!3%")33")3%()3%#)3%"*J3%!3%%"!%K!3%K"!)\rK"!)K!38L"!%")J3%!5)""!%K!3)K"!-N"!%""!-K"!%M!3%%!5)"!3%K"!)M"!3\r"!L%%!5)""!)N!33%!3-M!3%%!b-%"!%")33")J%""#1!!33")i!""!)K)3)KJ!%\rK"!8LJ#!$)J%%J3-,!#!%J!!%!!%!J#!%J#%!J#%%!!!%J#!!!!%!!#!%!#!%"5%\rJ!L1!)35"!aq!)35!!3#!)33!)!#!!!!!)3!!!35!!3!!)3!!!!5!!!3!)3#!!!#\r!!3!!)!!!!33!)3#!)!5!!3#!)!!!)33!!35!)!5!!!#!!3!!)33!)35!!!5!)3!\r!)35!!33&)L!%!L%K"#%%!5+!!3)LJ#!#)B!")33')L!%!L)""!%LJ#!#*)#!3"!\r")B!")a"!J!%L%%!$)8!"*8!33)"!!50!J%!#)B!")4!')N!3!L*!%!%PJ%!33)!\r#)8!&)8!")d#!3!)KJ!8K%!)K3!)MJ%!3"#&!!5&!!L'!!5%3!b333)"!!5*!J!8\rL%%!")8!")8!#)4!#+%!33)"!%%#!!L&!!5&!!50!J%!$)N!3!5@!3""!J!)K3!N\rL3"!$)K"!!5&!!50!J%!")N#!!b1!3"!")B!")a"!J!%L%%!$*N#!3""!J!)L3)!\r&)4!")S"!!L'!!5%3!L9!%%#!3!%L3)!")4!$)K"!!5&!!L1!3"!%)8!")8!%)4!\r#*%!33"!#)`J3)!3K)!%Q%#!J#"!J"58)%#!J#!%K)!)K%!%K)!)M)#!)!5%J!L%\r3!L%)!5%J!5))%!%K)!%K%!8L)!J&)5!")JJ3!5)J#!)K)!)L)#!")4!")L!)!b-\r)%#!")`J3)!%K#!8Q)#!)%#!J!b)J#!%L)#!")a!J)!%K%!-K%!%K)!3M#"!J!5%\r)!5)J)!%N%#!J#!%K)!3M)!J3!L%)!5%J!L%3!5%J!5%3"5-J#"!#*3J3)#!)!5)\rJ)!%L%#!$*L!J#"!J)!8L%#!")3J$)3J#)5!")K!J!b-J)!J#)5!#)5!")JJ3!5)\rJ#!3M%#!J!5%3"#%J!5))%!%M)!J)!5)))!)K#!)K!J)P#!)))!J$)3J")JJJ!b)\rJ#!3K!J%M)!J#!L3)!JJJ!5)##!%M#!))!L-###!#)3J%)b!)!J)K#!)L)!J")3J\r$)JJJ!5)##!)K!J%M)!J#!53J#!))!b)))!JL#!)")L!)!L)J#!%K#!)M!JJJ!5%\r#!b-###!")3)#)`J##!-K#!3M)!J#!5%J!L%)!L3###!)!5%)"#)J#!)M)!J#!L)\r)!J%L)!J%)3)#)3J")JJJ"#3)!JJJ!5%#!5)J#!)M)!J#!L%)!5%)!5%)!5)))!3\rN#!)))!%L!JJ#)J))!b)))!)L##!")3)")L!)!b-)!JJ"*8!)3""!!5&!!b&!!L-\r)3"!")3J&)a"!#!%L%%!")d!33!)S%%!)3""!#%!")8!$)8!")8!#)3J&)a"!#!%\rK%!%L#%!#)3J")K"!!5*!%!3K3!8K3!)P#%!33!J$)3J")K"!!L%3"5))3!-P3""\r!#%!")N!)"#*!%!8P#%!33!J")4!")3J#)8!"*%!33!J#)d!)3!-K3!%L3!J#)8!\r")8!%*4"!#%!3!5-)3"!$)4!#)8!")8!&*8!33!K!!L%)!L&!!L%3!5%)!5)33!%\rM3""!!L%3!5%)!5%3!5))3!8K3!%K3!-M3""!!b*!#!%P%%!)3"!")JK!!6i+9Q9\rbD@CjD@jR,#"`E'9KFf8JFQ8YC@jdCA)J*A-"1!S("deTFfeKG'0S)#dJG(*j)'&\rRB@PZ#J%Q)$"i)(XJ!5#"!!'3#2k3#"q3"!k3"1#3"2'3"!(q!Ii"rJ(qrJ(q!Ii\r"rJ%Ii"rJ$[%1mH!Ii"ra$[%1!H!"i!(a!I(J!H!"m3(a!4rq(ri1rJlqrKrq(ri\r1rJi"(`%I!3i"$Km"(`%1!3i"i2lJr[(qmIlqi2lJr[(qm3-L8#L#!K"3&&!!6qa\r2f%r%6l"2R%q)1%`i1$JN1"!i!$IX0pJha!NK!B)#"3!"!!%!!3!"!!%&)3'#!J8\r!!3!"!!%!!3!"!L!ZdY28eGEAf0RDfpcGhYrJiH,Mj1AQjqMTkZ[XlHl[m2(bmr6\rep[IiqIVlr2hqr`%JJ4%"!J-%"3B(#!N+#`8'"`J*#JX-$3i2%"%5%a39&KFB'4S\rE("dH(b!K)L-N*5!K)L-N*5BR+#NU+b`Y,Lm`-6)c0$8f0cJj1MXm26ir3%&#3d3\rZ,c!a-M-d06Bh1$P"3N0%48C(5%P+5da06Np389*69&9@9eKC@Q&LBf4PCQGSD@T\rVE'eZEh"aFR0dGAChH(Pk"b)3)!-K)!)K%!%K!3-K!3%M%#!"!L)J!3%K%!)K#!-\rM#"!J!5%)!5%J!5))%!%L!3J#*J%)%#!"#!%N)!%)%!-K)!-L-#!#)L!J!L%`!5%\r"!5%J!5%"!5-`)!%")b!J!3%K-!)L##!#)`J`)!%M##!J!5))-!%M!3JJ!5X"#$!\rJ!3JJ)!%)-!%K#)%$"`!!#"!J#!!J#"!!#3!!#4!J#3!J#5%3!5))#!)Q#!J3)!J\r)!53J#!J3!5)*#!)Q#3J3)!N)!53J#3J3!5%)J3-()!!)-#!))#!)-!!*)!!*-#!\r*)#!*)6!")`J))!%V#!J`)!J))#!)#$!")`N))!%V#3J`)!N))#!*#$!%)3)&)5!\r")3)")5!#)5!#)J)J!b)J)!%M!L!J"#)%!J)K"!)M)!3#!5)J"!%K)!%M"!)J!5%\r%!5FJ)!3#)#!%!L%%J3-(!J!%!!!N!J!N!#!%!L!%!#!N!L!N!L-%"!)")J3%!L-\rN"!)")L3%!5FJ"!3#)!3%!5JJ*!3#)#3%%!-K%J-K%!%K)!%K%J%K)!%L%#!#)K)\rJ!L-3)#!")a)J)!%K%!)L"")#)J33!5-J"")"*#!%%#!")`35)!%U""!J)!35)#!\r%%!%K")%$"a)!""!!*")!*"!J"")J""!J*")J*#%3!5-%"")")`3%%!%M*!35!6)\rN""!J"!35)!3%%#!N"")J*!3()3%")35"!`d!!!3"!3!!!3!"!33!!33"!!!#!!!\r$!!3#!!3$!3!#!3!$!33#!33K!`)K!J-L!J%")J3#!L3%!J%"!5%#!5%"!58#!3%\r%!J%N!33#!3)L!J)#)J)$!5-%!J)"*!3#!`%")`)#!3%V!J-""!)#!33#!`J$)3J\r#)`%)")%$$3!)"!%*!!!*!!%*"!!*"!%)!!))!!-)"!))"!-*!!)*!!-*"!)*"#)\r$#!%K!J%K#!%P!J%)"!)"*3J%!J%*!5%#!5%*!58#!3N%!J%P#33#!3J")`)##!%\rV!J-)"!)##!3#!`N")`)##3%U!J-*"!)##33#!`8K%!3K!3)L%!%%)3L"!`S3!!J\r!!3J3!3J!%!!3%!!!%3!3%3!!%!J3%!J!%3JN%"%)"!-L""!#)33")3%")`33!3%\rK"!)M#!33!5))"!%R!3J%%!%)"!%K%!%M""!3!5%%!5%4!5-%%"%")33"*a!)""!\r3#!3"*K%)""!4#)%$$`)!!")!!!)"!")"!!)!#")!#!)"#")"#!)3!")3!!)4!")\r4!!)3#")3#!)4##85%3J%!J)L"")#)`3#!3%M"")"!5)%!J%M#!35!5`)"!)"#!3\r5!3J%!K!")`35%!%M"!)4!5-%%K%"-!3#%!J%%K!)"!)4#!35%3J%)4!%)3%#)K!\r""5)%%!)K"!%K!B%$'333!33J!!!`!!!J!3!`!3!J!!3`!!3J!33`!33!%!!3%!!\r!%3!3%3!!%!33%!3!%333%33J%!!`%!!J%3!`%3!J%!3`%!3J%33`%5%%!L%3!5%\r3!5%3!L)"%!%M%!%3!b-3""!")K!%!5J"%!33!4!%)!%K%!%K-!%K%!%M)!%3!5-\r`!4!")5!")a!%-!%U%!3J!4!%-!%3"!%L%"!")a!3%!)L%4!")a!4%!)R%"!%%"!\r3"!%U%4!%%"%3"#!3%!%M-"!3!5-J%4!")c!4%!%`)"!3"$!3%!3J%4!%-"%3"!3\rK#!BL#!J#)3J#)33")3J")33$)`3)#!%L"!J")3)#)JJ#!b%#!5-)#!)")3J")J)\r%!5-)!J3#*`)%#!J#"!J$)J%)J3-'!!%!!!N)!!N!"!%)"!%!"!N))J3*!5%#!5-\r"#!)")3%")3)")`N)!J%K#3%R!J3"#!)%!3%S!J3*#!)%#3+"!`F!!!S!!!)!#!S\r!#!)%!!S%!!)%#!SN"!J#!J)L#J)#)J)#!5-)#J)"*!J#!J3")`S#"!%T!J)%#!S\r#"!J#J3-(!!%+!!%#!!N+!!N#"!%+"!%#"!N+*!3*!J)")`%+!J%M!3)#!5-*#J)\r"-3N#!J3"#J)%!3)#"!N+!J3*"L%"J3-'!!J!!!J"!3!!!3!"!3J!!3J"!b%3!L)\r"%!%K#!%K%!%N#!%3!3)L%!%"*!%3!3J"*4!"#!%3!5%J!b)J!B%$"J!S!!!S!3%\rJ!!%J!3%S!!%S!3%K)!%K%!%M)!%3!5%S!5%3!58S!4!")!%R%!%J!4!"+!%P%!%\rS!4!#)3+"!`F!!!-!#!)!#!-"!!)"!!-"#!)"#!-#)J)3!L)$%!%M#!)3!53)!a!\r"!5-#%!%"+J-3!3J#%!%)!a!")L!#J3-(!#!$!#J#!#J$!5!#!5!$!5J#!5J$!5-\rJ!K!")b!$%!%M+!)3!6-S!a!")!)3!5!$%!%S!K!"+!-3"#%%"#%%!L)%"!8L!J3\r#)3)")33")`)%"!%K!J)K)!%K"!%K)!)L"#!")`3%)!-M)!)%!5)J!J%R"#!#"!3\rJ!J-L)!3#)5!")33")b!%"!%K)!-L)J3#)5)")33")b)%"!%K)J)M)#!%!5)J)!%\rR"#!J"!3J)!)M)#)%!5)J)J%R"#!L"!3J)J)K#!%K"!%K#!)L"!J")`3%#!-M#!)\r%!5))!J%R"!J#"!3)!J)K+!%K"!%K+!)L"#J")`3%+!-M+!)%!5)S!J%R"#J#"!3\rS!J)M##!%!5)))!%R"!JJ"!3))!)M##)%!5)))J%R"!JL"!3))J)M+#!%!5)S)!%\rR"#JJ"!3S)!)M+#)%!5)S)J%U"#JL"!3S)J))#!)K#!)K!J)Q!J))#!)#"#-)#!)\r")3J")J)#!L%#!5B)#!)##!J")J))"#-)!J)")`J#!JJK#!%K!J%K#!8L!J)")3J\r#)JJ)!5B##!J#!JJ%)`J#!J%K#!3K!J)K#!)L#!J")J))!5%#!L%)!5%#!53)!J)\r)!5%###8##!J#!J%K#!)K#!%N!J))#!)K#!3M#!)#!5%)!5)##!%K!J)K#!)L#!J\r")3)#)3)")`J)!J-L!J)#)`)##!)N!JJ)!J%L#!J")J))!L%#!5-)!J)&)JJ#!5%\r)!5%#"5%)!L%#!b%#!58)!J))#!3M!J))!5%#!L%)!LF)#!*!%)!3"5)3J!%L3"!\r#)8!#)4!#)i!33!%KJ!)L%)!$)B!")N!3!5%3!b)33!%KJ!)K%!%N%%!3J!%L3"!\r&)4!")4!#)8!"*)!33"!")4!#)B!#*"#!%%!))4!")K"!!5+!%!%Q%)!33"#!!5&\r!!L)33!3K%!3QJ""!%)!3!5%3!5333"#!!5&!!5'!!LF3J""!%)!3!5%3!5)33!)\rK%!3K3!8LJ"!")4!#)N!3!5%3!L'!!5&!"#33J""!!5@!%%!3J!-KJ!8K3!)K%!-\rP%%!3J"!")K#!!5*!%!)L3"!")4!")4!%)i!33!%KJ!%K3!%LJ"!$)a"!%!-L%)!\r")33#*!%%"!%$)3%")33")J%"!5%%!5)""!-K"!%L!3%")J3"!5%%!5%"!L%%!L)\r%"!8P!33%!3%#)J%"!b-""!3")3%&)33"*!%%"!%$)3%$*J%""!3"!3%K"!)K"!)\rM!33%!5)""!%K!3)P"!%""!3$)J3""5%%"#B%!3%%"!%$)3%%)3%")33%)J%"!5%\r%!5-""!3#)33")J%""#-%"!%#)J3"!5)%"!%K!3%K"!%L!33$*!3%!3%$)3%"*!3\r"!33#)J%%!b3%"!%"!5%%!L%%!5%"!5%%!5)"!3%L"!%")33")3%&)J3%!5%"!L-\r"!33#)3%")`3"!3)K!3%L"!3$*%!3#"!")4!%*3J33"!)"#)33!)K%!%L%!J")8!\r"*!J33"!")4!#)JJ3"5-3#"!#)3J")d!3#!%K3!)K%!-L%%!")3J")N!3!b%3"#%\r)!5*!%!%K%!%N%!J33!3K%!-L%!J&)8!"*!J33"!")4!")4!")K"!!58)%%!3#!%\rK3!)L%%!")3J#)K!)!5&!!L%3!L%)!5*!%!%K%!%K%!3M#""!!L%3!5)3#!BK%!)\rK3!%K#!3L%%!"*!J33"!$)4!")4!$*""!%!J")d!3#!%K3!)N%%!3#!-L#"!")4!\r#)d!3#!%K3!%K#!%L3"!")K"!!L%3!5)3#!)M%!J3!b%3!L3)%%!3!5%)"#%""#%\r%!5B)!33J#!%")L!)!5%%!L8""#!)!3-K!38L)!J#)5!")J%%!5%)!53%)!J"!53\rJ#!%%"L)""!%K#!3K!3%K)!)M"#!)!5%%!L-""#!%)3J#)5!$)L!)!5B%)!J""#!\r")3%")b!)!33K"!-P"#!)!33")`J""!%K#!%L"#!")3%")b!)!3-K!38L)!J#)L!\r)!5%%!5%)"#)""!%N#!%%)!8N!33J#!8K"!)K!3%L)!J")J3J!L%%"5B)!33J#!%\r"*#!)!33$)J3J!5%"!b)""!%L#!%")L!)!5%%!b)%)!-K)!%P!33J#!%#)3J#)L#\r!!L&!!5%J!5&!"#1!)#!#)5!")8!#)5!")B!")L"!!5%J"#BJ3)!J)%!")L!J!5'\r!!b'!!5%J!5'!!L0!J#!$)b!J3!%K)!)KJ!%N)%#!)!%K3!BK)!3N3)!J)!%LJ#!\r"*d#!)#"!J#!#)B!&)L"!!b&!!5)J)!)N)#"!J!%K)!-M)%#!!b'!!5%J!LBJ)%#\r!)#!#)5!")8!%)B!")5!")B!&)5!")S!J!5&!!5%J!b%J!59!J#!J3!%L)#!%*8#\r!)#"!!5)J)!)K)!)KJ!%M)%#!!L0!J#!$)b!J3!BK)!%KJ!)L3)!"*5"!J#!J!5+\r!)!3L)%!$)d#!)!%K3!)K3!-K!J%K!B%$(3)!!3!%!8)%!%!%!%)!N!3"!!!"!J3\r!!J3"3!!!!!3"3J!"3!!!!J3"!J3!3!!!3!3"3J3!!!!"!J!"!!3!3J!"3!3!3J3\r"3J!!!!3!3J3"3!3!!J!""#0#"!'"!`T!!!&!"!!#"!"!!!!#!!%!!!&!"!%#"!"\r#"!"#!!!%)3)")3'"!a)!"!!!"!%#!*!%!3)%!3)!!%)!!!)%!%!!!8)%!3!!!8)\r!!!!%!%!%!8)%!3!%!8)!!8!!!#4!"##!J3-HJ###!!!#J!!!!#!#!!#!J##!!##\r#J!!!J#!!!!##!!!#J!##J#!#J#!!J##!!!!#!!##J!#!J#!#!###J#!!J!#3"))\r!)!!!!)!!)!+!))#!!)!!!!)!)))%)B!")B!$)3)#)5!#)i!JJJ%KJ!%K!J%LJ#!\r))B)#)L#!!51!)!)")i!J!J-KJ!%MJ###"5'!!5'!J3-*J#!#!###J!#!!##!!#!\r!J!##!!!#J#!#J##!"#1!))+"!`B!!)+!!!!!)!!!))#!!!)!!))KJ2rf!!!"!!!\r!!9`!!!"F!!!!-R3JG'KP)'CTEQ&X)(0PC@3JGA0TEQFJG'KP$5!J)#SJBh9bFQ9\rZG#"bB@jNEfdJER9YBQ9b)(0dFQ9KE6S0)#!J+Lm0)#"NCA0IEQ9hAh*KEQ4[E9p\rVCANSEQ9hAfYPH5Nl$5!JC'9cAh0PG&pbB@jNEfeICf9ZCA*KG'pbAh0PC@3SEQ9\rhAfYPH5Nl$Ad0$3d[+JdJ+L"8D'Pc)'e[C(9XC5"TEA"XC@ePER4c)'%JFQ&ZC'p\rY)'jeE@*PFL"RC@jPFQ&dEh)JCQ&MG@adH5"cG@0S)(4SBA3JG'KP)'jPH(30)#S\rJER9YBQ9b)'PZ)!!!!&J!N!X"!*!6!A"hF'-!N"-"!*!41!Y0594IT@4PFfaTBJ#\r3"!%!!!!"A!!!!&`!!!!b"QG8M&fN!!!!(!!b!!"MCR*R!!!!#J!!rrm!N!3'Ce2\rJ@38:\r
\ No newline at end of file
diff --git a/src/mac/libraries/DES/bin/deslib.PPC.debug b/src/mac/libraries/DES/bin/deslib.PPC.debug
deleted file mode 100644 (file)
index ded6d18..0000000
+++ /dev/null
@@ -1 +0,0 @@
-(This file must be converted with BinHex 4.0)\r:%'4PFfaTBLj38%-ZC'9LG@F!FfKXBMq3"!#3")pa!!!"NVNR5Qpj)A"PCQC`Gh"\rM!!!!!E*ETmN!N!d$!!)!N!6rN!3!N!CIH!!!AhJ!!&pi!!!&X!!%"!$rN!3!N!B\rYdJ!!,63!!#T"!!"P-!)""!$rN!3!N!i&,!!!!)!%"!3!N!ArN!3!N!F"!!!!p!!\r!!!%!!!$X!!!!!`!!!")!!!!"!!!!e!!!!23!!!1!!!!!"!!!!"S!N!m2!*!,%`#\r3#`)!!!!2!*!(,!#3#`%!!!!4!*!%!J!!13)!!%!#!!"(!J!!6J)!!&3#!!"E!J!\r!B!%!!'F#!!"[!J!!GJ)!!(X#!!##!J!!L!)!!*%#!!#B!J!!S!)!!,B#!!$+!!%\r!N!83!*!%5JCJ#%S)3J*J"d)"3!&#!8!"3KL!%dBD3#UJ!"[`3""0594IT8e*9%0\r-D@)ZC'9LG@F!68P8Ak905945G@jdD@eP6'PL,Q4PBR9R!%PZG'9bCQ&MC8aTBJ"\rcG(*MEA!!Fh4bBfKb!'CQE(9cD!"cFQ&ZC!"YC@eMF(N!FQ&ZC!"YC@eMEA!!Aep\rQD@aPF`"cG(*XC@i!G'PYC3"`FQPZG'B!CQGPG(-!BfaPBA*PFR)!E@9YFf9d!'C\r`FQPZG'B!AepeER*PCfPcG'9bAfCbB@GYC@jd!&pIFQ9RDA0dCA*ICR*KCfePER3\r!9'PMDd0[G@jd!'4PFepbC@&NAh"KFh0hEh*NC'9cAh0PG&pcCA&eC@jMC9pZG@e\rLCA*NCA0IC'9LG@GNCA0IFf9dAfYPH@4PFepTFephC@&VAfYPH@4PFepcG(*TEQG\rIG'pIDf9jC'9cAfjPGepbB@jNEfeIDf9jC'9cAf0LE'pMDep`FQPZG&pQD@aPC'9\rcAfCMFRP`G'4PFepQDAKeF&pVCAPIF'&bDA4jC'9cAf0SC@0VAfYPH9p`BA*TG(P\rNCA0IFQ&ZC'pYAfYPH@4PFepMFRP`G'4PFepbC@&NAh"hAh0dFQPZCf4PFepTEQP\rdAh*KEQ4[E9pZG@eLCA*ICf9ZCA*KG'pbC'9cAc0PBf*IC@jMFRP`G'4PFemcBf*\rMAf9ZBh*jF(4NCA0IFf9dAh*KEQ4[E9pRC@jPFQ&dEh*IFf9PC'4PFepVCAPIFf0\rSC@4NCA0IFA9KC&pMDh0eE@eKDf9IDf9jAh0MD'9NC'9cAf9MBPpPEQ0bHA"dC'9\rcAf0LBepPEQ0bHA"dC'9cAfGPEQ9bBA4PAh*KEQ4[E9pLE'pMDf4PFep`Bf*MAf9\rZBh*jF(4NCA0IBf*MAf0VFh9Y!*!&$!!!!!`!!`!%!!B!"!!(!!`!#!!%!!X!"!!\r-!!!!$3!)!!d!%!!2!!J!%`!!!"8!#!!9!!!!&`!-!"F!%C08!"IZC`!*4Fd!#a*\r'!!pG4J!4DjX!%V5D!"8rb!!+Le!!&(88!"5G&!!1PpX!#89`!")N1J!J`X8!%%@\rJ!""5S!!GG-B!$9-+!!k&6`!1L`X!$fI"!!pm`3!C%1%!%$UP!!eI$`)!!03!!!&\rm!!%#!!$P!!!"4!!"!3!!r!!!,63!!3)!!38!!!'N!!%#!!%3!!!"P!!"!J!"(`!\r!!B3!!3)!!6!!!!&F!!%#!!&#!!!"M!!"!J!"9`!!!D`!!3)!!@%!!!%F!!%#!!&\re!!!"&!!"!J!"L3!!!@`!!3)!!CF!!!'d!!%#!!'J!!!"G!!"!J!"XJ!!!93!!3)\r!!G)!!!'m!!%#!!(L!!!"R!!"!J!"mJ!!!8`!!3)!!Jm!!!%d!!%#!!)F!!!"C!!\r"!J!#+J!!!5`!!3)!!MJ!!!%-!!%#!!*(!!!!r!!"!J!#9J!!!6`!!3)!!Qm!!!%\rN!!%#!!*r!!!""!!"!*!%I!J#TT!!!3!)P#(r`$JK!%#!!3!)I!J$TNk!!#"m#!+\rQNq(rr*!!!3!)P#(r`*!!B3"B1q!!!)"K!&K)!&`eB!!!!(ar'hKri`Fd,!-!!%'\r#!!arirYi5!!!#(rMqhL!!3")1#%!3(`)!kD$iIrm6S!!)!#3"L""J!%!N!98!"3\rZAepTEQPdD@&XDATPAf4PFfaTBJ!!I!J#TT!!!3!)P#(r`%J!A#&J!!!!J!%!5$J\rK!%"m#!1Q6S!!)!#3"L""J!#3"L3!%bjIAh4PFQeTEQ&dC9pNCA0XD@)!!!#q)Ir\r%1Z)2-$[#%c!l!JX`I0XcH#`)!!""JJA8I2BlH)Nf!!!keJ!"95N'2P8m`!k*9J!\r!1YB!!99+"Mj95S!HIja6H)Pf!!!keJ!"9@X'2P9V3#jrR&YiLCB!!$V@!!&9M!B\rqIjaMH)Nf!!!keJ!"95N'2P8p`!k*9J!!1YB!!99+"Mj95S!HIle6H)Pf!!!keJ!\r"9@X'2P9V3#jr[9YiLCB!!$V@!!&9M!BqIleMH(af'hKmP50i5!!&+#`&!!K"J!$\r%L6B!!$V@!!&9+3Bq95N'2P8T`!jrR%TiL9B!!$V@!!&95JBq98S'2P9+J"jrR&*\riLAB!!$V@!!&9D`Bq9@X'2P9V3#jrR&TiLCB!!$V@!!&9M!Bq9B`'2RqFBRL*0J!\r!1YB!!98T"Mj9+3Bq95R!$Rqp5RL*9J!!1YB!!99+"Mj95JBq98U!(Rqp8RL*GJ!\r!1YB!!99V"Mj9D`Bq9@Y!,Rqp@RL*PJ!!1YB!!9@-"Mj9M!BqIleLH$LPrrK)!!#\r`IYBU&#J&!!G"J3#J15)"k&5U%$Tp+9!ZI5N$TNk!"#!ke[rrLAB!!&9V"Mj9Dd!\rZIleDH$V@rrq*PJ!!9B`'2P@-J"jr[@*i1YErriNf!!"9+3Bq95R!$Rqp5RJke[r\rrL9B!!&9+"MjrR&*i1YErriPf!!"9D`Bq9@Y!,RqF@RJke[rrLCB!!&@-"Mj9M)!\rHIjaLH$V@rrq*0J!!95N'2P8T`!jrR%Ti1+!!!$e!UUXj5UUUIiT31$eJUUXjDkU\rUIkYB1&9Vq(jpAeYi2B"996Q-999rM'!i9B`)2$dJ998j+999IkP)1(fG5hKAUJB\rq98S31ReB8#j95KJi9k['2P9V%$TpH&JZ9@X31PHX4Mj9M"!kICKJ,PHTKMj9+4!\rkI6K),P8T#$apM%YiI@YMH(eF@hKAkJBq98S31ReB8#j95KJi9q['2P9V%$TpH&J\rZ9@X31PIX4Mj9M"!kICKJ,PITKMj9+4!kI6K),P8T#$apM%YiI@YMH(eG@hJl3!!\r!5!!"S)&E!!!lH`!%9kZUrPHXU"4pDf0iI9pDH&IT"Vj9+4!k15N$!(dq5#jAkXD\rq98S31MP+!J"pAP!Z9qZ'[P9V%$SjD`%!IAjB,PIX4Vj9M"!kICjJ,ReVBhKp5PY\riI5P6H(qF5RL"1`!!1hX!"&HU6IjAUdJXI8TEH(dr8RKAl!Dq9B`31MQ-"`"pRQ!\rZ9qR'[P8T%$Sj+3B!I6j),PIU4Vj95K!k18S%!(eH8#jAkiDq9@X31MPV"3"pIPJ\rZI8TEH(dT8hKpM%YiIjaLH)'E!!!lH`!%9iQUrPH+U"4p+90iICp+H&IV"Vj9Da!\rk1@X$!(eq@#jAl-Dq9B`31MQ-!J"pRQ!Z9qQ'[P8T%$Sj+3%!I6j),PIU4Vj95K!\rkI9j3,RdT8hKpM%YiI@YMH(qp@RL"H`!!1hX!"&H-6IjAL8JXIBa,H(erBRKAkJD\rq98S31MP+"`"pAP!Z9q['[P9V%$SjD`B!IAjB,PIX4Vj9M"!k1B`%!(fHB#jAkBD\rq95N31MNT"3"p2NJZIBa,H(eVBhKp5PYiIle5H$YD!!%X'J!)3B$qB$e!m2%j5[$\r`IkT31$eJm2%jDr$`IiYB1&9Vi6jpAeYi2B!2$cQ-$`prV'!i9B`J0MdJ$`mj+3m\r2IiP)1(fG5hKAUJBq98S31ReA8#jAUmBq9@X31Reh@#j9Da!k9ka'2P@-%$TpPf!\rZ9B``-PHTKMj9+4!kI6G),P8T)$CpM%YiI@YMH(eF@hKAkJBq98S31ReA8#jAkmB\rq9@X31Reh@#j9Da!k9qa'2P@-%$TpPf!Z9B``-PITKMj9+4!kI6G),P8T)$CpM%Y\riI@YMH(eG@hJlHrq!9iT'2TP9!!!kY3!"9iZ'2TPe!!!kY3!"9ic'2TQ9!!!kY3!\r"9iN'2TNe!!!kY3!"9kT'2TP9!!!kY3!"9kZ'2TPe!!!kY3!"9kc'2TQ9!!!kY3!\r"9kN'2TNe!!!kY3!",!8!!%'"qYK)!!@B,!8!!%'"!!`iB!!!5!!&M(cf1hL*9J!\r!1YB!!99+"Mj99-!1LAB!!$V@!!&9D`Bq9@Z!(Rk8@hL*PJ!!1YB!!9@-"Mj9M%!\rZIT4MH)Nf!!!keJ!"95N'2Rk85hL*9J!!1YB!!99+"Mj98m!1LAB!!$V@!!&9D`B\rq9@Z!(Rjc@hL*PJ!!1YB!!9@-"Mj9M%!ZIR0MH)Nf!!!keJ!"95N'2Rjc5hKmGKY\riI*8MH)P@!!!keJ!"98S'2P9F`!k*GJ!!1YB!!99V"Mj9Di!HIjaEH)Q@!!!keJ!\r"9B`'2P@-3#jrR'0iL6B!!$V@!!&9+3BqIja,H)P@!!!keJ!"98S'2P9G`!k*GJ!\r!1YB!!99V"Mj9Di!HIleEH)Q@!!!keJ!"9B`'2P@-3#jr[@0iL6B!!$V@!!&9+3B\rqIle,H(q5ihKrXHYi28#UUcP+UUTrLP!i2@#UUcPVUUTrUeJi9@[iIReI@hJpJ&9\r91Ba99Aq-B$K9M!Jm25"996NT999rU8JiICe,H&HU"Mj95K!kI9K3,P9+'$KAUmB\rq9@X31Rei@#j9Da!k9ka'2P@-%$TpQ'!Z9kQ'2P8T%$Tp1%JZ95N)2(f-5hKpDf0\riI9aEH&IU"Mj95K!kI9K3,P9+'$KAkmBq9@X31Rei@#j9Da!k9qa'2P@-%$TpQ'!\rZ9qQ'2P8T%$Tp1%JZ95N)2(f-5hKpDf0iI9eEH$Yl!)!l)!!!5!!"S$Ylrrb"@`!\r!9kY0rPHX5#apDf0iI9pDH&IT4Vj9+4!k15N%!(dq5#jAkSDq98S31MP+"3"pAP!\rZ9qX'[P9V%$SjD`F!IAjB,PIXaVj9M"!k1B`'!(fHB#jpDf0iI8TEH(dT8hKrR%T\ri1h[rr)%l!!"AUUVq9kZS&(e+@hKp2e*i9qb'[P@-%$SjM!%!ICjJ,PIT"Vj9+4!\rk15N$!(dq5#jAkXDq98S31MP+!J"pAP!ZI5P6H(f-5hKAkdDq9@X31Req@#jpM&Y\riIjaLH$Ylrrb"Q`!!9iP0rPH+5#ap+90iICp+H&IV4Vj9Da!k1@X%!(eq@#jAl)D\rq9B`31MQ-"3"pRQ!Z9qN'[P8T%$Sj+3F!I6j),PIUaVj95K!k18S'!(eH8#jp+90\riIBa,H(eVBhKr[9Ti1h[rr)&l!!"AM+Vq9iQS&(f-5hKpIf*i9qU'[P9+%$Sj5J%\r!I9j3,PIV"Vj9Da!k1@X$!(eq@#jAl-Dq9B`31MQ-!J"pRQ!ZI@YMH(e+@hKAk8D\rq95N31Rdq5#jp5NYiIle5H$Xj!!%X'3!)3B$qB$e!m2%j5[$`IkT31$eJm2%jDr$\r`IiYB1&9Vi6jpAeYi2B!2$cQ-$`prV'!i9B`J0MdJ$`mj+3m2IiP)1(fG5hKAUJB\rq98S31ReA8#jAUmBq9@X31Reh@#j9Da!k9ka'2P@-%$TpPf!Z9B``-PHTKMj9+4!\rkI6G),P8T)$CpM%YiI@YMH(eF@hKAkJBq98S31ReA8#jAkmBq9@X31Reh@#j9Da!\rk9qa'2P@-%$TpPf!Z9B``-PITKMj9+4!kI6G),P8T)$CpM%YiI@YMH(eG@hKrR+*\riIlfDH#`&!!K!J3"d1+Arq&H+4MkC93!!1V8!!9H,KMkCG3!!1V8!!9H-aMkCP3!\r!1V8!!9H*"MkC03!!1V8!!9HU4MkC93!!1V8!!9HVKMkCG3!!1V8!!9HXaMkCP3!\r!1V8!!9HT"MkC03!!1V8!!Aj8NhKq-iYi5rrlR(ke+K3S"3!)3B%!H$P#!F48Ua!\rkI8TB,Re*!kC1J!3J9k`'2MUerrqCP3!!9kR'2MUerrqC03!!9kU'2MUerrqC93!\r!9kY'2MUerrqCG3!!9i`'2MUerrqCP3!!9iR'2MUerrqC03!!9iU'2MUerrqC93!\r!9iY'2MUerrqCG3!!1'!!!,SKrm41J!!J!*!')%!!$`#3"!Z-!"!ZC'9cAf0LBep\rPEQ0bHA"d!!#q`IrB1`)2-$[#%c!l)JX`I2FlH)NA!!!kp`!"93J'2P8F`!k*0`!\r!1[F!!98T"Mj9+B!HIja,H)PA!!!kp`!"98S'2P9+3#jrR&0iLAF!!$Vh!!&9D`B\rqIjaEH)QA!!!kp`!"9B`'2P@G`!k*&`!!1[F!!98)"Mj9#)!HIle$H)Nh!!!kp`!\r"95N'2P8T3#jr[8YiL9F!!$Vh!!&95JBqIle6H(ah'hKmYLYi5!!%c#`@!!K"J!$\r%LAF!!$Vh!!&9D`Bq9@X'2P9V`!jrR&TiLCF!!$Vh!!&9M!Bq9B`'2P@-J"jrR'*\riL4F!!$Vh!!&9#!Bq93J'2P8)3#jrR%*iL6F!!$Vh!!&9+3Bq95N'2RqF5RL*9`!\r!1[F!!99+"Mj95JBq98V!$Rqp8RL*G`!!1[F!!99V"Mj9D`Bq9@Z!(Rqp@RL*P`!\r!1[F!!9@-"Mj9M!Bq9Ba!,RqpBRL*&`!!1[F!!98)"Mj9#!BqIle#H$V@rrK)!!#\r`I[Hb&#J@!!G"J3#J15)##&E+%$Tp+9!ZI5N$TNk!"#!kprrrLAF!!&9V"Mj9Dd!\rZIleDH$Vhrrq*P`!!9B`'2P@-J"jr[@*i1[IrriNA!!"9#!Bq93M!$Rqp3RJkprr\rrL6F!!&8T"MjrR%Ti1[IrriPA!!"95JBq98T!,RqF8RJkprrrLAF!!&9V"Mj9Di!\rHIjaDH$Vhrrq*P`!!9B`'2P@-`!jrR'*i1X!!!(cE-hJp!+UV13LUURq)3$Jp)+U\rV15QUURqT5$K9+IKqI4p,H$e!998j5P99IiT31&9+#$`pB&991@Y99AqV@$KpA9Y\ri9k`'2P@-%$TpQ@!Z9B`B1&HSaMj9#"!kI4P!,P8)%$TAU8Bq95N31Rdj5#jAUSB\rq98S31ReC8#j95JJmI5P6H(d)5hKpR%0i9qX'2P9V%$TpH9JZ9@XB1&IXaMj9M"!\rkICPJ,P@-%$TAk%Bq93J31RdC3#jAkBBq95N31Rdj5#j9+3JmI3K,H(f-3hKpI@0\ri1d!!!%J!!D#"@`!!1hX!"&HVU[jAV+J8I@YMH(eI@RKAk!Dq93J31MN)!`"p(N!\rZ9qR'[P8T%$Sj+3)!I6j),PIUKVj95K!k18S"!(eH8#jAkdDq9@X31Req@#jp5PY\riI5P6H(d)5hKrR%*iJCX!!$Yl!!4AU%hq9kP),(d)5hKpRd*i9qS'[P9+%$Sj5JF\r!I9j3,PIVaVj9Da!k1@X'!(eq@#jAl%Dq9B`31MQ-"!"pRQ!Z9qL'[P8)%$Sj#!8\r!I4j!,Rf-3hKpDf0iI8TEH(qF8RL"1`!!1hX!"&H+U[jALkJ8I8TEH(dr8RKAl!D\rq9B`31MQ-!`"pRQ!Z9qM'[P8)%$Sj#!)!I4j!,PITKVj9+4!k15N"!(dq5#jAkND\rq98S31ReH8#jp+90iI3K,H(f-3hKr[@*iJAX!!$Yl!!4AM%hq9iK),(f-3hKpIf*\ri9qN'[P8T%$Sj+3F!I6j),PIUaVj95K!k18S'!(eH8#jAkdDq9@X31MPV"!"pIPJ\rZ9qb'[P@-%$SjM!8!ICjJ,ReVBhKp5PYiI5P6H(qp5RJl@J!","S!#%'!rQ!p!2$\ra13M`m(qS3$Jp)2$a15R`m(q*5$K9+H%qI4p,H$e!$`mj5Jm2IkT31&9+)$BpB!m\r21@X2$hq,@$KpA9Yi9k`'2P@-%$TpQ'!Z9kM'2P8)%$Tp'%!Z93J31PHT4Mj9+4!\rkI6K),P8T-$*AUSBq98S31ReB8#j95L!fI5P6H(d)5hKpR%0i9qX'2P9V%$TpH&J\rZ9qc'2P@-%$TpQ'!Z9B`31PIS4Mj9#"!kI4K!,P8)-$*AkBBq95N31Rdi5#j9+5!\rfI3K,H(f-3hKpI@0i1h[rJ#`@!!""JIXdI*FMH&H+4MkC9`!!1[F!!9H,KMkCG`!\r!1[F!!9H-aMkCP`!!1[F!!9H)"MkC&`!!1[F!!9HT4MkC0`!!1[F!!9HUKMkC9`!\r!1[F!!9HVaMkCG`!!1[F!!9HX"MkCP`!!1[F!!AqMkhLk`IrB6S!!)!#3"L"!!!S\r!N!3&m!!1,Q4PFepMBQ0IBfYcG@fqSIr81U)2-$[#%c!k`JX`I(JEH)Mi!!!l'!!\r"91F'2P6m`!k*'!!!1aJ!!98)"Mj9#)!HIja$H)Ni!!!l'!!"95N'2P8T3#jrR%Y\riL9J!!$XB!!&95JBqIja6H)Pi!!!l'!!"9@X'2P9p`!k*Q!!!1aJ!!9@-"Mj9M)!\rHIleMH)Mi!!!l'!!"91F'2P6R3#jr[6YiL4J!!$XB!!&9#!BqIle$H$dJUUXj+DU\rUIiP)1$e!UUXj5UUUIkT31&9+q(jp2e0i2@"996PV999rLeJi9@X)2$f!998jM&9\r9IkaJ1(epBhKAT`Bq91F31Rcf1#j8jaJi9kM'2P8)%$Tp&N!Z93J31PHT4Mj9+4!\rkI6C),PHUKMj95K!kI9C3,P9+#$ap+90iI3K,H(cm3hKAk`Bq9@X31Ref@#j9DaJ\ri9qc'2P@-%$TpPQ!Z9B`31PIR4Mj8ja!kI2Bi,PISKMj9#"!kI4C!,P8)#$amjd0\riIB`lH(epBhJX"J!!3B)"Z(bk+hJlB!!!5!!"S)%k!!!l@J!%9kUUrPHVU"4p5PY\riI6p5H&IX"Vj9M"!k1B`$!(fHB#jAjmDq91F31MMR!J"mrMJZ9qL'[P8)%$Sj#!%\r!I4j!,PIT4Vj9+4!kI6j),Rd)5hKmjd0iIB`lH(qFBRL"@J!!1eS!"&HV6IjAV%J\rXI@YMH(eI@RKAj`Dq91F31MMR"`"mrMJZ9qM'[P8)%$Sj#!B!I4j!,PIT4Vj9+4!\rk15N%!(dq5#jAkSDq98S31MP+"3"pAP!ZI5P6H(d)5hKmjd0iIj`kH)&k!!!l@J!\r%9ibUrPH(U"4pM$YiIApLH&IS"Vj9#"!k13J$!(dH3#jAkFDq95N31MNT!J"p2NJ\rZ9qU'[P9+%$Sj5J%!I9j3,PIV4Vj9Da!kIAjB,Re+@hKp+90iI3K,H(qp3RL"QJ!\r!1eS!"&H(6IjAL%JXI1G$H(fI1RKAk3Dq95N31MNT"`"p2NJZ9qV'[P9+%$Sj5JB\r!I9j3,PIV4Vj9Da!k1@X%!(eq@#jAl)Dq9B`31MQ-"3"pRQ!ZI@YMH(e+@hKp+90\riIle+H$Yl!!%X'`!)3B$qB%J!!E3l*3#!1f!!!%J!!D!l1IrmJ2N!!&HS6IjAU8J\rXI3K,H(cr3RKAkNDq98S31MP+"!"pAP!Z9qZ'[P9V%$SjD`8!IAjB,PIX"Vj9M"!\rk1B`(!(fHB#jAjmDq91F31MMR"J"mrMJZIB`lH(eVBhKp5PYiIja5H$Xjrrb"'3!\r!9kQUrPHUU"4p+90iI4p+H&IVKVj9Da!k1@X"!(eq@#jAl!Dq9B`31MQ-!`"pRQ!\rZ9qI'[P6R%$Sij`)!I2ii,Rf-1hKpDf0i9qK'[P8)%$Tp(N!ZI@Y$H(qF@RJl1Ir\rmJ6N!!&H+6IjALdJXI8TEH(dr8RKAl%Dq9B`31MQ-"!"pRQ!Z9qH'[P6R%$Sij`8\r!I2ii,PIS"Vj9#"!k13J(!(dH3#jAkFDq95N31MNT"J"p2NJZI3K,H(cR3hKpM$Y\riIleLH$Xjrrb"@3!!9iZUrPH-U"4pDf0iI9pDH&IRKVj8ja!k11F"!(cq1#jAk!D\rq93J31MN)!`"p(N!Z9qR'[P8T%$Sj+3)!I6j),Rd)5hKmjd0i9qT'[P9+%$TpAP!\rZI1G6H(qp1RJlH`!","X!#%'!rQ!pB2$a1@[`m(qV@$JpJ2$a1Bc`m(q-B$K9M1%\rqIApMH$cJ$`mij`m2IkFi1&6R)$Bp!!m213J2$hq)3$Kmr80i9kN'2P8T%$Tp08J\rZ9kV'2P9+%$Tp99!Z98S31PHV4Mj9Da!kIA9B,P9V-$*AV)Bq9B`31Rf9B#j9M#!\rfI@YMH(e+@hKp2&0i9qF'2P6R%$Tmp6JZ9qM'2P8)%$Tp&8!Z93J31PIT4Mj9+4!\rkI69),P8T-$*AkSBq98S31Re98#j95L!fI5P6H(d)5hKmr80iI*FMH&H,4MkCG`!\r!1[F!!9H-KMkCP`!!1[F!!9H(aMkBp`!!1[F!!9H)"MkC&`!!1[F!!9HT4MkC0`!\r!1[F!!9HUKMkC9`!!1[F!!9HVaMkCG`!!1[F!!9HX"MkCP`!!1[F!!6KJ!!#kSIr\r86S!!)!#3"L"!!!X!N!3')!!3,Q4PFepPBf*IC@jMFRP`G!!!Nq(rr$[J!!")!!#\rBI)2iVP5%"MamJrQZI+2iVP5P"cjm`rLZ9-ER2RbP-RK8T3HqI12iVP6R"cjp!rL\rZ93MR2RcR3RK8jrHqI+8kH&5P"rjp)rLZ95N(2Re$q+j95ZFqI5P5H&8T"ljpBrL\rZ9@X(2Rf$q+j9M1FqI@YLH&9Vpljp+9Ti95RrrRbP5RKST3!"I)2iVRb%+hKmJrQ\rZ1rm!!5JI!!K"J2pSJq(rr%k!!#!!N!BJ3!!"!*!&X!!9,Q4PFepQDAKeF&pVCAP\rIF'&bDA4j!*2Krr`li!!!5!!!Y(b$q+j8K!IqI+2iVP5P"Ma8T3FqI-2iVP6'"Ma\r8aZFqI+8bH&5P"ljmirLZ91F'2&6R"cjp!rLZ93J'2&8)jcjmjd*i91Ih[RbP1RK\r8T3IqI52iVP8T"Ma9+3FqI82iVP9+"Ma95ZFqI5P5H&8T"ljpBrLZ9@X'2&9V"cj\rpJrLZ9B`'2&@-jcjpDf*i9@[h[RdT@RK9+IrqI+9+H(`%+!"!JJ!-1'!!!%J!!"3\rlr`!"+"m!#%'!rd`iB!!"Jq(rr%k!!#!!N!BJ3!!"!*!&d!!9,Q4PFepMD'9MDep\rVCAPIF'&bDA4j!,i"rm!kiJm`1m)6-$X##c"mfc0i,!J!!%'#"FampMYiL6B!!$V\r@!!&9+3Bq96c!$SP@!!!keJ!"98S'2P9+J"jrR&0iLAB!!$V@!!&9D`Bq9@Y!,Rq\rF@hL*PJ!!1YB!!9@-"MjrR'0iL6B!!$V@!!&9+3Bq96h!$SP@!!!keJ!"98S'2P9\r+J"jr[90iLAB!!$V@!!&9D`Bq9@Y!,Rqp@hL*PJ!!1YB!!9@-"Mjr[@0iI(BEH(b\r9)hK)!!8J,!8!#%#"!+5*0J!!1YB!!98T"Mj90-!1L9B!!$V@!!&95JBq98U!(Rk\r88hL*GJ!!1YB!!99V"Mj9Dd!ZIT4EH)Q@!!!keJ!"9B`'2Rk8BhL*0J!!1YB!!98\rT"Mj9-m!1L9B!!$V@!!&95JBq98U!(Rjc8hL*GJ!!1YB!!99V"Mj9Dd!ZIR0EH)Q\r@!!!keJ!"9B`'2RjcBhKrR+*iIlfDH$LPrrK)!!$!IYBU&#J&!!K"J3#`15)#6&5\rU%$Tp+9!ZI5N$TNk!"#!ke[rrLAB!!&9V"Mjr[9Ti1YErriQ@!!"9M!Bq9Ba!,Rq\rpBRJke[rrL6B!!&8T"Mj9+B!HIle+H$V@rrq*9J!!98S'2P9+`!jr[9*i1YErriP\rf!!"9D`BqIjaDH$V@rrq*PJ!!9B`'2P@-3#jrR'*i1YErriNf!!"9+3Bq95Q!(Rq\rF5RJke[rrL9B!!&9+"Mj95X!1Ija5H$LJ!!!pB+UV1@ZUURq,@$JpJ+UV1BbUURq\rXB$K9M2KqIApMH$dJ998j+999IiP)1&8T#$`p3&9918T99AqU8$Kp290i9kX'2P9\rV%$TpH&JZ9@XB1&HXaMj9M"!kICKJ,P@-%$TAU8Bq95N31Rdi5#jAUSBq98S31Re\rB8#j95JJmI5P6H(f-5hKpI'0i9qX'2P9V%$TpH&JZ9@XB1&IXaMj9M"!kICKJ,P@\r-%$TAk8Bq95N31Rdi5#jAkSBq98S31ReB8#j95JJmI5P6H(f-5hKpI@0i1d!!!%J\r!!D#"H`!!1hX!"&HXU[jAUDJ8IBa,H(erBRKAkJDq98S31MP+!`"pAP!Z9q['[P9\rV%$SjD`)!IAjB,PIXKVj9M"!k1B`"!(fHB#jAk8Dq95N31Rdq5#jpM%YiI@YMH(e\r+@hKrR&*iJ9X!!$Yl!!4AUdhq9ka),(eVBhKpAeTi9qN'[P8T%$Sj+3F!I6j),PI\rUaVj95K!k18S'!(eH8#jAkdDq9@X31MPV"!"pIPJZ9qb'[P@-%$SjM!8!ICjJ,Re\rVBhKp5PYiI5P6H(qF5RL"1`!!1hX!"&H+U[jALkJ8I8TEH(dr8RKAl!Dq9B`31MQ\r-!`"pRQ!Z9qR'[P8T%$Sj+3)!I6j),PIUKVj95K!k18S"!(eH8#jAkdDq9@X31Re\rq@#jp5PYiI5P6H(f-5hKr[@*iJCX!!$Yl!!4AL8hq9iT),(dT8hKpRdTi9qX'[P9\rV%$SjD`F!IAjB,PIXaVj9M"!k1B`'!(fHB#jAk8Dq95N31MNT"!"p2NJZ9qU'[P9\r+%$Sj5J8!I9j3,RdT8hKpM%YiI@YMH(qp@RJl@J!","S!#%'!rQ!pB2$a1@[`m(q\rV@$JpJ2$a1Bc`m(q-B$K9M1%qIApMH$dJ$`mj+3m2IkP)1&8T)$Bp3!m218S2$hq\r+8$Kp290i9kX'2P9V%$TpGeJZ9kc'2P@-%$TpPf!Z9B`31PHT4Mj9+4!kI6G),P8\rT-$*AUSBq98S31ReA8#j95L!fI5P6H(f-5hKpI'0i9qX'2P9V%$TpGeJZ9qc'2P@\r-%$TpPf!Z9B`31PIT4Mj9+4!kI6G),P8T-$*AkSBq98S31ReA8#j95L!fI5P6H(f\r-5hKpI@0i1h[rJ&H,4MkCG3!!1V8!!9H-KMkCP3!!1V8!!9H*aMkC03!!1V8!!9H\r+"MkC93!!1V8!!9HV4MkCG3!!1V8!!9HXKMkCP3!!1V8!!9HTaMkC03!!1V8!!9H\rU"MkC93!!1V8!!AqFSRKr[CTi,!8!!%'"qZ")!!@F,!8!!%'"!!`iB!!!5!!&N!"\rmpMYiLAB!!$V@!!&9D`Bq9A,!$SQ@!!!keJ!"9B`'2P@-J"jq8Q0iL6B!!$V@!!&\r9+3Bq95P!,Rj55hL*9J!!1YB!!99+"Mjq8P0iLAB!!$V@!!&9D`Bq9A(!$SQ@!!!\rkeJ!"9B`'2P@-J"jq-@0iL6B!!$V@!!&9+3Bq95P!,Ria5hL*9J!!1YB!!99+"Mj\rq-90iI(BEH(b9)hL*GJ!!1YB!!99V"Mj9I-!1LCB!!$V@!!&9M!Bq9Bb!(RqFBhL\r*0J!!1YB!!98T"Mj9+8!ZIja,H)P@!!!keJ!"98S'2RqF8hL*GJ!!1YB!!99V"Mj\r9IF!1LCB!!$V@!!&9M!Bq9Bb!(RqpBhL*0J!!1YB!!98T"Mj9+8!ZIle,H)P@!!!\rkeJ!"98S'2Rqp8hKrN!$MH*1Krl!pB+UV1@ZUURq,@$JpJ+UV1BbUURqXB$K9M2K\rqIApMH$dJ998j+999IiP)1&8T#$`p3&9918T99AqU8$Kp290i9kX'2P9V%$TpH&J\rZ9@XB1&HXaMj9M"!kICKJ,P@-%$TAU8Bq95N31Rdi5#jAUSBq98S31ReB8#j95JJ\rmI5P6H(f-5hKpI'0i9qX'2P9V%$TpH&JZ9@XB1&IXaMj9M"!kICKJ,P@-%$TAk8B\rq95N31Rdi5#jAkSBq98S31ReB8#j95JJmI5P6H(f-5hKpI@0i1hX!J$XJ!!")!!'\rJ1h[rr)&l!!"AV%hq9kP),(f-5hKpIf*i9qT'[P9+%$Sj5J3!I9j3,PIVKVj9Da!\rk1@X&!(eq@#jAl!Dq9B`31MQ-"`"pRQ!Z9qR'[P8T%$Sj+3B!I6j),Rf-5hKpDf0\riI8TEH(qF8RJlHrrmJ9X!!&HVU[jAV+J8I@YMH(eI@RKAkBDq95N31MNT!3"p2NJ\rZ9qS'[P9+%$Sj5J-!I9j3,PIVaVj9Da!k1@X#!(eq@#jp5PYiI5P6H&IX4Vj9M"!\rkICjJ,RdTBhKrR%Ti1h[rr)%l!!"ALNhq9iY),(e+@hKp2e*i9qa'[P@-%$SjM!3\r!ICjJ,PITKVj9+4!k15N&!(dq5#jAkJDq98S31MP+"`"pAP!Z9q['[P9V%$SjD`B\r!IAjB,Re+@hKp+90iIBa,H(qpBRJlHrrmJCX!!&H*U[jALUJ8I5P6H(fI5RKAkiD\rq9@X31MPV!3"pIPJZ9q`'[P@-%$SjM!-!ICjJ,PITaVj9+4!k15N#!(dq5#jpM%Y\riI@YMH&IU4Vj95K!kI9j3,ReV8hKr[9Ti1cN!!5`C!!K"J2jJ2@$`m6PVm2"rUeJ\ri2B$`m6Q-m2"rM'!i9BcK2RerBhJp)!m215N2$hqT5$K9+5!f28!2$cP+$`prLP!\riI6e6H&HV"Mj9Da!kIAGB,PHXaMj9M"!kICGJ,P@-%$TAU8Bq95N31Rdh5#j9+6!\rb9kU'2P9+%$Tp9e!Z98SJ0RdT8hKpM%YiIAaMH&IV"Mj9Da!kIAGB,PIXaMj9M"!\rkICGJ,P@-%$TAk8Bq95N31Rdh5#j9+6!b9qU'2P9+%$Tp9e!Z98SJ0RdT8hKpM%Y\riIAeMH(qFNRKr[BTi,!8!#%#"!(JiTIri9iY'2TPe!!!kY3!"9ib'2TQ9!!!kY3!\r"9iR'2TNe!!!kY3!"9iS'2TP9!!!kY3!"9kY'2TPe!!!kY3!"9kb'2TQ9!!!kY3!\r"9kR'2TNe!!!kY3!"9kS'2TP9!!!kY3!"IK,LH)&Krl"pFHTi5rrlQ(ke+K3S"3!\r)3B%!H$Q#!LK8U4!kIBa),Rf*!kC1J!3J9kS'2MUerrqC93!!9k['2MUerrqCG3!\r!9kb'2MUerrqCP3!!9kP'2MUerrqC03!!9iS'2MUerrqC93!!9i['2MUerrqCG3!\r!9ib'2MUerrqCP3!!9iP'2MUerrqC03!!1'!!!,S"rm"1J!!J!*!')%!!%!#3"!Z\r)!"%ZC'9cAh"MBQ0IC@jMFRP`G!#q)Ir%1U)(-$V#!c!k)J-31N)#d$TL!T!!1S)\r#F(ah'hL)Y`!!1[F!!95P"Mj8[F!1L0F!!$Vh!!&8aJBq9-D!(Rqp-hL)p`!!1[F\r!!96R"Mj8jd!ZIldlH)NA!!!kp`!"93J'2Rqp3hKAUGpq95N31Rdd5#j9+4Ji9kU\rIIP9+%$Tp9&!Z98S31PHV(hj9Da!kIA4B,PHXAhj9M"!kIC4J,P@-#$apDf0iI8T\rEH(dr8hKATImq9+831Rbc+#j8T4Ji9kDr2P6'%$Tmdc!Z9-B31PHR2cj8ja!kI2-\ri,PHSIcj9#"!kI40!,P8)#$amjd0iI-BlH(bq-hL*0`!!1[F!!98T"Mj92F!1L9F\r!!$Vh!!&95JBq98U!(Rqp8hL*G`!!1[F!!99V"Mj9Dd!ZIleEH)QA!!!kp`!"9B`\r'2RqpBhKATHFq9+831Rbb+#j8T4Ji9kDR2P6'%$TmdM!Z9-B31PHR*cj8ja!kI2)\ri,PHSCcj9#"!kI4*!,P8)#$amjd0iI-BlH(bP-hKrrbYi9kRrIP8T%$Tp-8JZ95N\rB1&HU[hj95K!kI9&3,P9+%$TAUcpq9@X31Rea@#jAV(pq9B`31Rf4B#j9M!JmI@Y\rMH(e+@hKp+90iIpj,H(bD)hJl)(lm1`!!%%J!!5aA*3Iq,!8!!%'#!#"AjK%k9qF\rf[RcI1hKAb"%k9mNf[RdH5hK)!!!F9qS*2&IV,[jpAeYi9m`*2&I&,[jpRLYiIcN\r1F&IQ"hjAjqDiI-BlH&6'%$SiaJ-!I0B`,PISjljAkEkkI3K,H&8)%$Sj#!)!I4C\r!,PIUMcjAkiDfI8TEH&9+%$Sj5J%!I9C3,PIX9Vj9M"!kICCJ,Re+BhKp#&0iI0a\r$H&I&"ljAa[kkI+8cH&5P%$SiT3-!I,8S,PI(cVj8ja!k11F#!(ce1#jAb*Fq9mQ\r1YRd)5hK9#"!k13J"!(d93#jAbPDq98S31Re98#jp#&0iI1G$H(bl1hKAL`)Z9f`\r'$ReVBhL4HJ!!1eS!"&H&"JjACJ)ZI+8cH*!!ZJ!!1eS!"$XBrrmX'!!!3B(qe$K\rJ!!#k)Ir%6S!!)!#3"L"!!!m!N!3$*!!2,QeKDf9IDf9jAh0MD'9N!!!!I!J#TT2\rKrrb3!!%!#*3Krm"mIaYiN!#"!&arirYiJ)%!A%[rr*PJ!!!!Iq2lH%[rlqPJ!!!\r!,!-!!%##!!`iB2rr5!!!*(rMqhK)!!Z&B!!!!#`$!!""JJ!-1'$rrNJ!!!JiB!!\r!J!%!5$JK!%"m#!1QJq(rr%k!!#!!N!BJ3B!"!*!&H!!1,Q4PFepVCAPIFf0SC@4\rm#!+QNq(rr*!!!3!)P#(r`(ar'hKrirYi5!!#+@!!!!"rirYi5rrZJ@!!!!"rirY\ri5!!,"@!!!!!X!`!!3),rf$KJ!!#!!3")1#%!3(`)!kD$iIrm6S!!)!#3"L""J!%\r!N!9B!"-ZC'9cAfjPGepbB@jNEfeIDf9j!!!!I!J#TT!!!3!)P#(rX*!!B3"S5!!\rbIB""!"53!'%!5%J!-R'!33!8N!"K!%b!B3"S5!!!T@!!!!!iB3")5!!"+@!!!!!\riB3!i5rrr26KK!$K)!!#&B!!!!$KK!%")!$*0J%%!&$KK!%4)!$*"J%%!&)"L!#"\r)!!$aB!!!!$KK!$K,rrm&1'%!1%J!!%eJ!!!!J!%!@$JK!&"m#!1Q6S!!)!#3"L"\r"J!#3"T`!)5jNCA0ID@jTG&pbB@jNEfeIER9YBQ9bAfGPEQ9bBA4[FJ"m#!+QNq(\rrr*2"rrL3!!%!#*3Krm#3!'%!@$[#,EL!B3"B1))Y1%[rrI9J!!!!1q!!!%J!!"!\riB!!!I(ljVM[r!!%X(`!)3B$rm)!"!%Ji)3"!I!J$TS2Krrb$`Iri6S!!)!#3"L"\r"J!)!N!9J!"iZC'9cAh0PG&pbB@jNEfeICf9ZCA*KG'pbAh0PC@4m#!+QN!!"!!L\r8)Ir!N!"K!&JiBLfiJ)%!@$LJ!!K)!$$jJ%%!&)!"!%Ji)3"!I!J$TNk!!#!!N!B\rJ3B!!N!Bd!"JZC'9cAh0PG&pcCA&eC@jMC9pZG@eLCA)!!(`)!UD6iIrmNm(rq*!\r!!3!)P#(r`*!!B3"B1m)YZ(r$mhL!J3"B1+)Y1$M!!!&,rqAeB!!!!$[J!!")!!!\rNI(liVMKM!!&8B`BqI(ljVRbHq+iS"!!!3))!%$[r!!%X(`!)3B$rh)!"!%Ji)3"\r!I!J$TS2Krrb$`Iri6S!!)!#3"L""J!)!N!9m!"SZC'9cAfGPEQ9bBA4PAh*KEQ4\r[E9pLE'pMDh`)!UDqJIr3N!!"!!L8)Iq3!(ae'hKmQ#0iI,BVH(cA-hKmp$YiIS1\rMH%J!!@&mI"Yi1(3!"%J!!99mHKYi+"J!!%##!!Jki!!"1b!!!8J!!,"qhV0iIVZ\rVH%J!!)!X(J!"3)%!)(pMfhK)!!$K9'-%2Rrm'K3lH`!#1plrrNJ!!"L)H`!!1hX\r!!94M"Mjrr"S81m!!!(pGdhKmRrR@I,hTeRb%+K3m`)!!1-Errhq%-jCrR$(@Ij`\rJ8$cp"2`ijh-YI2mjeMd!J!!j#2rrIdG$PRpD3GCr@MK3,"i!!%##ri!S'!!!3B)\r!&*1B!!!l'!!%NeJ!!$XB!!3l13!","N!"%'"!!am'EJ!3)(r5(q$ihL!!3"i1#%\r!F(`)!kDkJIr36S!!)!#3"L""J!`!N!3"*!!2,Q4PFepaG@&NAf0VFh9Y!!!!L)-\r!!CL"rr#)S`!!Q+(rmD"Krr"1J!!J!*!')%!!N!FB!"BZG(G[Af*jG'9cAhCKH&p\rdEepZCA4cL)-!!jL"rr#)S`!#Q+(rmBM$!!'B`IrbL1-!!*MKrr1!BIr`6S!!)!#\r3"L"!!*!(+!!A,QC[GA*IBRPdCA0IGQ&iAh4[AfjPG(-!!!"m#!+Q[`(ri*!!!3!\r)P#(rS(aj'hKr2-YiIcV,H$KK!$K)!#j"J%%!&%J!,L'!33!8J)%!1(b%'RL!SJ#\rSJ-8!!(c(-hJiaJ!"N!$&!!"mjb*iI2JlH(m$`hK)!#iKJ%%!&%J!,M'!33!8N!"\rK!$ar3p0i1)%!2$LJ!!4)!#fjJ%%!&$YD!!4)!#i0J%%!&*!!B3!mId26H$L"!$`\riS!!%5!!YPB""!"3lB!!!5!!!@$[!!!#,r!!!1k!!!%J!!"4ArrKq9qJ(rRrH3RJ\rl[3!","d!"N#"rq`X(J!!3))!&)Nm!!"K+3!"Q6`!!%J!!"#*A!!!98S'2*PF!!!\rlR!!"1hX!!5`E!!G!JIqS1'!!!)!"!'Ji)3"JI!J$TVX"rq"1J!!J!*!')%'!#!#\r3"!%J!!mZC'9cAh*KEQ4[E9pVCAN!!!"m#!+QNq(rr*!!!3!)P#([`*!!B4"BN!#\r"%&b3!+%3B$KK!$JiJ"!!J+%3A)$"%'")!!"eB!!!!(ar'hJX(`!!3))!&$KK!$L\r!J4"B5!!#9@!!!!!iB3!i1)!!!$LJ%!")!#fCJ%%!&(rMqhL!!4")1#%33(`)!kD\r$iIrm6S!!)!#3"L""J!%!N!9m!")ZC'9cAh*PB@4IF'&cFhG[FQ4m#!+Q[Z(rh*!\r!!3!)P#([S(ap'hKmQL0iI,XVH(cC-hJkiKY21`)E-)2L!&!lJ!!!,"S3!%#"!5!\riB2rr5!!"K(pMfhK)!#b"J%%!&$Kr!%K)!#b0J%%!&(qMkhKr400iIqAlH%J!,*'\r!33!8+!-!!%##!"4rirYi5!!XPB""!"4)!!$8Ik2VH$L!!!T)!#bCJ%%!&(aq'hJ\rS(J!!3B)!$$KJ!!#BIJ!!,"N!!%'#!+4r!m0iIf6EH%J!,!f!33!81(m!5%J!,"Q\r!33!81'%!1$L!%!"rjIYi5!!X(B""!"3S!`!!3))!&(rMqhK)!#`KJ%%!&%J!!'!\riB3!i1)!!#NJ!,#@!33!8I(iEH#JH!!""JJ!-1)!!!*LH!!"rSqYi1)%!1%J!,"Q\r!33!8,!-!!%'#!#"qilYi5!!VMB""!"3iI`")5!!VQB""!"4)!!!)1i!!!5`F!!"\r"J[lS,"`!!%##!"KrSqYi1)!!!(p&dhK)!#[PJ%%!&$KL!0a)!#Y*J%%!&#`C!!"\r"JJ!B1'%!1$L!!!!iS"!!5!!V[B""!"3iS!!!I0VU&*LQrrmii!!!,"`!!%##!!J\rii!!"I1-lH)!"%'Ji)4"JI!J$TVVKrpa1J!!J!*!')%'!#3#3"!(8!"-ZC'9cAh*\rPB@4IF(GIFh4bD@jR!!!!I!J#TVl"rpL3!!%!#*3KrZ"mH4YiI*FMH(mfbhJlJ!!\r"1k%!Z(mMbhK)!#Y*J%%!&(ak'hJiB3#i1)!!!$LJ!%")!#XCJ%%!&$YJ!!&)!!#\r%L(N!!$Xj!!&mI`Gd1m!!!%J!!%3X(!!!3B)!)&IN"rjrTHYi1ld!!BM&!!"maL*\riQ-8!!%J!!"KAj`Iq1lhrriNG!!"p#$TiQ4d!!&Irq(ilhJ!","i!"N#"rlaAD3G\rq+!N!!%##!"Jj3!!!,"`!!%##!!Jj3!!"I9a6H$Yl!!&m'p"!3)(rI$ZK!,Kqq,Y\ri1f!!!%J!!%!li!!!1m!!!%J!!##*I3!!1ld!!AeV"h3jRJ!"I@YJ-(rr@hJlhJ!\r","i!"N#"rq#Eq!!!1aJ!!6Yl!!%S'`!(3)(r`(lMZhK,rq64B!!!!(lMZhJiJ3!\ri5rreK@!!!!"q`l0iIZ5lH(p&dhJi`3!iIZHlH%[rf&&J!!!!1'%!1$L!!!!iS!#\r!5!!TkB""!"4qilYi5rrNK@!!!!!iB!!!J!%"+$JK!5"m#!1QZX(rf%k!!#!!N!B\rJ3B!+!*!%!C`!%LjNCA0IFh4bD@jRAh4[AfYPHA`)!UD6iIrmNm(rq*1Krr53!!%\r!#*3Krl#3!'%!D(bI)hL$S3"S1m!!!(rMqhJiJKYS5!!TQB""!"4)!!!iIq2lH$L\r#!0k)h3!!1ld!!96&"Mj)!#PjJ%%!&#`H!!K!J!!8Iq2lH$L#!1&)!#PKJ%%!&#`\rH!!JlhJ!"3B$ra(rMqhJiJJ$N5!!T4B""!"5!!3"B1#%!8(`)!kD$iIrmJm(rq)1\rKrr41J!!J!*!')%'!!`#3"DJ!&LjNCA0IBf*XEf0VAh"bD@jdAfCTE'9m#!+QNq(\rrr*2"rrL6SIrdN!!"!!L8)Iq`I(dEH$[#'fmli!!!5!!!-(r$mhJlhJ!)Ik6VH$L\rJ!!K)!#GaJ%%!&#`$!!"!JJ!-1'!!!8J!!"3lr`!"+"m!%%'!rp!iB!!!J!%!@$J\rK!&"m#!1QJq(rr)2"rrL$SIrd6S!!)!#3"L""J!-!N!9m!"!ZC'9cAfPcAhGPB@Y\rIDf9j!!#p`Iqi1Z)2-$[#%c!l!JX`I0XcH(ck1hKp'80i,!S!!%'#$04p-%YiLA!\r!!$S3!!&9D`Bq9Ac!$SQ3!!!!1K!!!9@-"Mj9M)!HIjaMH)P`!!!k%!!"9@X'2P9\rV3#jrR&YiLC!!!!!k%!!"9B`'2RqFBhL*F!!!1K!!!99V"Mj9IF!1LC!!!!!k%!!\r"9B`'2P@-J"jr[@0iLA!!!$S3!!&9D`Bq9@Y!,Rqp@hL*N!!!!$S3!!&9M!BqIle\rMH(a`'hL3!)(rX%J!$#JX"3!)3B!!a)P`!!!k%!!"9@X'2P9V"Mj9Dm!1IjaDH)Q\r3!!!!1K!!!9@-"Mj9M!Bq9Bb!(RqFBRL*F!!!1K!!!99V"Mj9D`Bq9@Y!,RqF@RL\r*N!!!!$S3!!&9M!Bq9B`'2RqFBRL*F!!!1K!!!99V"Mj9D`Bq9@[!$Rqp@RL*N!!\r!!$S3!!&9M!Bq9B`'2P@-J"jr[@*iLA!!!$S3!!&9D`Bq9@X'2P9V3#jr[9TiLC!\r!!!!k%!!"9B`'2P@-"Mjr[@*i1+Arq%J!!,"q%#S8+!8!"d'"!+!jBK`89+`31Re\rVB#jpD31Q6S!%)$S3rrq*F!!!9@X'2P9V3#jr[9Ti1K$rriQ3!!!!9B`'2P@-J"j\rr[@*i1K$rriP`!!"9D`Bq9@[!$Rqp@RJk%2rrLC!!!!"9M!BqIjaLH$S3rrq*F!!\r!9@X'2P9V3#jrR&Ti1K$rriQ3!!!!9B`'2P@-J"jrR'*i1K$rriP`!!"9D`Bq9@[\r!$RqF@RJiS!!!2B#UUcQ-UUTrM'!i2@#UUcPVUUTrUeJi9@[iIRfI@hJpJ&991Ba\r99Aq-B$K9M!Jm2@"996PV999rUeJiICeEH&HX"Mj9M"!kICKJ,P@-'$KAUmBq9@X\r31Rei@#j9Da!k9kp'2PA[%$Tpq(JZ9kk'2PA1%$Tpf(!Z9Fi)2(h[FhKpDhYiICa\rEH&IX"Mj9M"!kICKJ,P@-'$KAlXBq9Fi31RhBF#j9cK!k9qp'2PA[%$Tpq(JZ9qZ\r'2P9V%$TpH&JZ9@X)2(h[@hKpcRYiICecH$V!!!")!!'JJCX!!$Yl!!4AVUVq9kq\rS&(h1HhKpRh*i9qX'[P9V%$SjD`-!IAjB,PIXaVj9M"!k1B`#!(fHB#jAlSDq9Fi\r31MR1!3"phR!Z9qp'[PA[%$TprRJZIFjlH(f-FhKpDf0iIjaDH)&l!!!lH`!%9ka\r0rPHZ5#apM(0iIApLH&I["Vj9la!k1Hm(!(hqH#jAkmDq9@X31MPV"J"pIPJZ9qa\r'[P@-%$SjM!3!ICjJ,PIZKVj9cK!k1Fi&!(hHF#jpM(0iI@YMH(h[@hKrR(TiJIX\r!!$Yl!!4ALkVq9ibS&(eVBhKpreTi9qi'[PA1%$SjcJ-!IGj`,PI[aVj9la!k1Hm\r#!(hqH#jAkiDq9@X31MPV!3"pIPJZ9qa'[P@-%$TpRQ!ZI@YMH(h[@hKpcRYiIle\rbH)(E!!!lH`!%9ip0rPH,5#apleYiIGpkH&IX"Vj9M"!k1B`(!(fHB#jAlXDq9Fi\r31MR1"J"phR!Z9qp'[PA[%$Sjl`3!IIji,PIVKVj9Da!k1@X&!(eq@#jpleYiIFj\rlH(f-FhKr[@*i1YB!!5`@!!K"J2jJ2B$`m6Q-m2"rV'!i2F$`m6R1m2"rMR!i9Fl\rK2RfIFhJpi!m21Hm2$hq[H$K9lb!f2@!2$cPV$`prLeJiIIeEH&HX"Mj9M"!kICG\rJ,PHZaMj9cK!kIGG`,PA1%$TAVdBq9Hm31RhhH#j9lc!b9kZ'2P9V%$TpGeJZ9@X\rJ0Rh[@hKpcRYiICacH&IX"Mj9M"!kICGJ,PIZaMj9cK!kIGG`,PA1%$TAldBq9Hm\r31RhhH#j9lc!b9qZ'2P9V%$TpGeJZ9@XJ0Rh[@hKpcRYiICecH$Ylri!pJ+UV1Bb\rUURq-B$Jp`+UV1FkUURqZF$K9c[KqICpcH$hJ998jle99Iipi1&A[#$`pB&991@Y\r99AqV@$Kpr9Yi9k`'2P@-%$TpQ'!Z9B`B1&HZaMj9cK!kIGK`,PA1%$TAVdBq9Hm\r31RhiH#jAUiBq9@X31Rei@#j9D`JmIHpEH(h1HhKpR(0i9q`'2P@-%$TpQ'!Z9B`\rB1&IZaMj9cK!kIGK`,PA1%$TAldBq9Hm31RhiH#jAkiBq9@X31Rei@#j9D`JmIHp\rEH(h1HhKpRA0i1eS!J$UJ!!")!!'J1eVrr)'D!!"AVNhq9kp),(h1HhKpRh*i9qY\r'[P9V%$SjD`3!IAjB,PIXKVj9M"!k1B`&!(fHB#jAlJDq9Fi31MR1"`"phR!Z9qr\r'[PA[%$Sjl`B!IIji,Rh1HhKpM(0iI@YMH(qF@RJl@[rmJAS!!&HXU[jAVUJ8IBa\rcH(erBRKAliDq9Hm31MR[!3"prRJZ9qX'[P9V%$SjD`-!IAjB,PIXaVj9M"!k1B`\r#!(fHB#jpDf0iIHpEH&IZ4Vj9cK!kIGj`,Rh[FhKrR(Ti1eVrr)(k!!"ALdhq9ia\r),(eVBhKpreTi9qj'[PA1%$SjcJ3!IGj`,PI[KVj9la!k1Hm&!(hqH#jAk`Dq9@X\r31MPV"`"pIPJZ9qc'[P@-%$SjM!B!ICjJ,ReVBhKpleYiIFjlH(qpFRJl@[rmJGS\r!!&H2U[jALkJ8IHpEH(hIHRKAl)Dq9B`31MQ-!3"pRQ!Z9qi'[PA1%$SjcJ-!IGj\r`,PI[aVj9la!k1Hm#!(hqH#jpcRYiIBacH&IV4Vj9Da!kIAjB,Rf-@hKr[@*i1V8\r!!5`9!!K"J2jJ2B$`m6Q-m2"rV'!i2F$`m6R1m2"rMR!i9FlK2RfIFhJpi!m21Hm\r2$hq[H$K9lb!f2@!2$cPV$`prLeJiIIeEH&HX"Mj9M"!kICGJ,PHZaMj9cK!kIGG\r`,PA1%$TAVdBq9Hm31RhhH#j9lc!b9kZ'2P9V%$TpGeJZ9@XJ0Rh[@hKpcRYiICa\rcH&IX"Mj9M"!kICGJ,PIZaMj9cK!kIGG`,PA1%$TAldBq9Hm31RhhH#j9lc!b9qZ\r'2P9V%$TpGeJZ9@XJ0Rh[@hKpcRYiICecH$f!UUXjM+UUIiaJ1$h!UUXjcUUUIkj\r`1&A1q(jpRh0i2H"996R[999rMhJi9Hm)2$eJ998jDe99IkYB1(hp@hKAV!Bq9B`\r31RfBB#j9M"Ji9kl'2PA1%$Tpf(!Z9Fi31PH[4Mj9la!kIIKi,PHVKMj9Da!kIAK\rB,P9V#$apleYiIFjlH(fFFhKAl!Bq9B`31RfBB#j9M"Ji9ql'2PA1%$Tpf(!Z9Fi\r31PI[4Mj9la!kIIKi,PIVKMj9Da!kIAKB,P9V#$apleYiIFjlH(fGFhJkJ!!!5!!\r"S)'C!!!l13!%9kkUrPH[U"4pcRYiICpbH&IV"Vj9Da!k1@X$!(eq@#jAl-Dq9B`\r31MQ-!J"pRQ!Z9qk'[PA1%$SjcJ%!IGj`,PI[4Vj9la!kIIji,Rh1HhKpM(0iI@Y\rMH(qF@RL"H3!!1cN!"&HX6IjAVNJXIBacH(erBRKAl`Dq9Hm31MR["`"prRJZ9q[\r'[P9V%$SjD`B!IAjB,PIX4Vj9M"!k1B`%!(fHB#jAlSDq9Fi31MR1"3"phR!ZIBa\rcH(eVBhKpleYiIjakH)(j!!!l13!%9iZUrPH-U"4pDf0iIIpDH&IZ"Vj9cK!k1Fi\r$!(hHF#jAlmDq9Hm31MR[!J"prRJZ9qZ'[P9V%$SjD`%!IAjB,PIX4Vj9M"!kICj\rJ,ReVBhKpleYiIFjlH(qpFRL"f3!!1cN!"&H26IjALdJXIHpEH(hIHRKAl!Dq9B`\r31MQ-"`"pRQ!Z9ql'[PA1%$SjcJB!IGj`,PI[4Vj9la!k1Hm%!(hqH#jAkiDq9@X\r31MPV"3"pIPJZIHpEH(h1HhKpM(0iIleLH$U8!!%X&!!)3B$qB$f!m2%jM2$`Ika\rJ1$h!m2%jc[$`Iij`1&A1i6jpRh0i2H!2$cR[$`prVhJi9HmJ0MeJ$`mjD`m2IiY\rB1(hp@hKAV!Bq9B`31RfAB#jAVXBq9Fi31RhAF#j9cK!k9kp'2PA[%$TpphJZ9Hm\r`-PHVKMj9Da!kIAGB,P9V)$CpleYiIFjlH(fFFhKAl!Bq9B`31RfAB#jAlXBq9Fi\r31RhAF#j9cK!k9qp'2PA[%$TpphJZ9Hm`-PIVKMj9Da!kIAGB,P9V)$CpleYiIFj\rlH(fGFhJl1Iq!9ia'2S("rl"pch0i1Fi!!C("rl#CM`!!9iZ'2S'"rl"pMQ0i1B`\r!!C'"rl#CEJ!!9ir'2S&Krl"pE&Yi1@X!!C&Krl#Cl!!!9ii'2S(Krl"pkhYi1Hm\r!!C(Krl#Cb`!!9ka'2S("rl"pch0i1Fi!!C("rl#CM`!!9kZ'2S'"rl"pMQ0i1B`\r!!C'"rl#CEJ!!9kr'2S&Krl"pE&Yi1@X!!C&Krl#Cl!!!9ki'2S(Krl"pkhYi1Hm\r!!C(Krl#Cb`!!,!8!!%'"mpK)!!dJ,!8!!%#"$4Kp-%YiLC!!!!!k%!!"9B`'2P@\r-`!k4JIqXLG!!!$S3!!&9cJBq9Fk!(S(Krkaplh0iNH(rV)P`!!!k%!!"9@X'2P9\rV3#k"JIqXIBaEH*'"rkb*d!!!1K!!!9A1"Mk"iIqXIHpcH*(Krkb*F!!!1K!!!99\rV"Mj9Dm!1N@(rU)Q3!!!!1K!!!9@-"Mj9M)!HJF(rU(h1BhL4`IqSLI!!!$S3!!&\r9l`Bq9Hp!,S&KrkKpDhYiN@(rU)Q3!!!!1K!!!9@-"Mk"`IqSIFjMH*("rkKmF"Y\riN!#"rl#*m!!!1K!!!9A["Mj9r-!1LA!!!$S3!!&9D`Bq9@Z!(RqF@hL*N!!!!$S\r3!!&9M!Bq9Ba!,RqFBhL*d!!!1K!!!9A1"MjrR(0iLI!!!$S3!!&9l`Bq9Ih!$SP\r`!!!k%!!"9@X'2P9VJ"jr[9YiLC!!!!!k%!!"9B`'2P@-3#jr[@0iLG!!!$S3!!&\r9cJBqIlecH*1"rk56SIqJ2H#UUcR[UUTrMhJi2@#UUcPVUUTrUeJi9@[iIRhr@hJ\rpJ&991Ba99Aq-B$K9M!Jm2F"996R1999rVR!iICecH&H["Mj9la!kIIKi,PA['$K\rAUmBq9@X31Rei@#j9Da!k9ka'2P@-%$TpQ'!Z9kk'2PA1%$Tpf(!Z9Fi)2(f-FhK\rpDf0iIIaEH&I["Mj9la!kIIKi,PA['$KAkmBq9@X31Rei@#j9Da!k9qa'2P@-%$T\rpQ'!Z9qk'2PA1%$Tpf(!Z9Fi)2(f-FhKpDf0iIIeEH$Xj!)!kB!!!5!!"S$Xjrrb\r"q3!!9kY0rPHX5#apDf0iIIpDH&IZ4Vj9cK!k1Fi%!(hHF#jAliDq9Hm31MR["3"\rprRJZ9qX'[P9V%$SjD`F!IAjB,PIXaVj9M"!k1B`'!(fHB#jpDf0iIHpEH(h1HhK\rrR(*i1cRrr)(C!!"AVkVq9kZS&(h[@hKphhTi9qb'[P@-%$SjM!%!ICjJ,PIZ"Vj\r9cK!k1Fi$!(hHF#jAlmDq9Hm31MR[!J"prRJZIFjlH(f-FhKAkdDq9@X31Req@#j\rpM&YiIjaLH$Xjrrb"Q3!!9ij0rPH25#apcRYiICpbH&IV4Vj9Da!k1@X%!(eq@#j\rAl)Dq9B`31MQ-"3"pRQ!Z9qi'[PA1%$SjcJF!IGj`,PI[aVj9la!k1Hm'!(hqH#j\rpcRYiIBacH(eVBhKr[9Ti1cRrr)&j!!"AM+Vq9ikS&(f-FhKpIf*i9qq'[PA[%$S\rjl`%!IIji,PIV"Vj9Da!k1@X$!(eq@#jAl-Dq9B`31MQ-!J"pRQ!ZI@YMH(h[@hK\rAlNDq9Fi31RhHF#jplh0iIlekH$Tc!!%X%`!)3B$qB$hJm2%jlr$`Ikpi1$eJm2%\rjDr$`IiYB1&9Vi6jpreYi2B!2$cQ-$`prV'!i9B`J0Mh!$`mjcJm2Iij`1(fGFhK\rAV`Bq9Hm31RhhH#jAUmBq9@X31Reh@#j9Da!k9ka'2P@-%$TpPf!Z9B``-PHZKMj\r9cK!kIGG`,PA1)$CpM(0iI@YMH(hm@hKAl`Bq9Hm31RhhH#jAkmBq9@X31Reh@#j\r9Da!k9qa'2P@-%$TpPf!Z9B``-PIZKMj9cK!kIGG`,PA1)$CpM(0iI@YMH(hp@hJ\rpi+UV1HqUURq2H$JpB+UV1@ZUURqV@$K9DrKqIIpEH$f!998jM&99IiaJ1&@-#$`\rp`&991Fj99AqZF$KpRA0i9km'2PA[%$Tpq(JZ9HmB1&HVaMj9Da!kIAKB,P9V%$T\rAV%Bq9B`31RfBB#jAVSBq9Fi31RhBF#j9cJJmIBacH(eVBhKpr&Yi9qm'2PA[%$T\rpq(JZ9HmB1&IVaMj9Da!kIAKB,P9V%$TAl%Bq9B`31RfBB#jAlSBq9Fi31RhBF#j\r9cJJmIBacH(eVBhKpr9Yi1N!!!%J!!D#"qJ!!1eS!"&HVU[jAV+J8I@YMH(hr@RK\rAlJDq9Fi31MR1!`"phR!Z9qr'[PA[%$Sjl`)!IIji,PIVKVj9Da!k1@X"!(eq@#j\rAl%Dq9B`31RfHB#jpDf0iIHpEH(h1HhKrR(*iJGS!!$YD!!4AVdhq9kY),(h[@hK\rphhTi9q`'[P@-%$SjM!F!ICjJ,PIZaVj9cK!k1Fi'!(hHF#jAldDq9Hm31MR["!"\rprRJZ9qZ'[P9V%$SjD`8!IAjB,Rh[@hKpcRYiIBacH(qFBRL"QJ!!1eS!"&H1U[j\rAMkJ8IFjlH(fIFRKAk`Dq9@X31MPV!`"pIPJZ9qc'[P@-%$SjM!)!ICjJ,PIZKVj\r9cK!k1Fi"!(hHF#jAldDq9Hm31RhqH#jpcRYiIBacH(eVBhKr[9TiJAS!!$YD!!4\rAM%hq9ij),(f-FhKpIf*i9qm'[PA[%$Sjl`F!IIji,PIVaVj9Da!k1@X'!(eq@#j\rAl%Dq9B`31MQ-"!"pRQ!Z9qk'[PA1%$SjcJ8!IGj`,Rf-FhKpDf0iIHpEH(qpHRJ\rk8J!",")!#%'!rQ!pi2$a1Hr`m(q[H$JpB2$a1@[`m(q,@$K9Dq%qIIpEH$f!$`m\rjM!m2IkaJ1&@-)$Bp`!m21Fi2$hq1F$KpRA0i9km'2PA[%$TpphJZ9k['2P9V%$T\rpGeJZ9@X31PHX4Mj9M"!kICGJ,P@--$*AVSBq9Fi31RhAF#j9cL!fIBacH(eVBhK\rpr&Yi9qm'2PA[%$TpphJZ9q['2P9V%$TpGeJZ9@X31PIX4Mj9M"!kICGJ,P@--$*\rAlSBq9Fi31RhAF#j9cL!fIBacH(eVBhKpr9Yi1eVrJ$hJUUXjlkUUIipi1$eJUUX\rjDkUUIkYB1&9Vq(jpreYi2B"996Q-999rM'!i9B`)2$h!998jcP99Ikj`1(fGFhK\rAV`Bq9Hm31RhiH#j9laJi9k['2P9V%$TpH&JZ9@X31PHX4Mj9M"!kICKJ,PHZKMj\r9cK!kIGK`,PA1#$apM(0iI@YMH(hm@hKAl`Bq9Hm31RhiH#j9laJi9q['2P9V%$T\rpH&JZ9@X31PIX4Mj9M"!kICKJ,PIZKMj9cK!kIGK`,PA1#$apM(0iI@YMH(hp@hJ\rlH`#!1L!!!%J!!D!lHrrmJIX!!&HV6IjAV%JXI@YMH(hr@RKAlNDq9Fi31MR1"!"\rphR!Z9qq'[PA[%$Sjl`8!IIji,PIV"Vj9Da!k1@X(!(eq@#jAl-Dq9B`31MQ-"J"\rpRQ!ZI@YMH(h[@hKpcRYiIjabH$Ylrrb"f`!!9kqUrPHVU"4pleYiIGpkH&IXKVj\r9M"!k1B`"!(fHB#jAlJDq9Fi31MR1!`"phR!Z9qr'[PA[%$Sjl`)!IIji,Rh1HhK\rpM(0i9qY'[P9V%$TpIPJZIBaEH(qFBRJlHrrmJCX!!&H16IjAMdJXIFjlH(fIFRK\rAkdDq9@X31MPV"!"pIPJZ9qb'[P@-%$SjM!8!ICjJ,PIZ"Vj9cK!k1Fi(!(hHF#j\rAlmDq9Hm31MR["J"prRJZIFjlH(f-FhKpDf0iIleDH$Ylrrb"H`!!9ibUrPH1U"4\rpM(0iIApLH&I[KVj9la!k1Hm"!(hqH#jAk`Dq9@X31MPV!`"pIPJZ9qc'[P@-%$S\rjM!)!ICjJ,ReVBhKpleYi9qj'[PA1%$TphR!ZIHpcH(qpHRJk-3!","%!#%'!rQ!\rpi2$a1Hr`m(q[H$JpB2$a1@[`m(q,@$K9Dq%qIIpEH$f!$`mjM!m2IkaJ1&@-)$B\rp`!m21Fi2$hq1F$KpRA0i9km'2PA[%$TpphJZ9k['2P9V%$TpGeJZ9@X31PHX4Mj\r9M"!kICGJ,P@--$*AVSBq9Fi31RhAF#j9cL!fIBacH(eVBhKpr&Yi9qm'2PA[%$T\rpphJZ9q['2P9V%$TpGeJZ9@X31PIX4Mj9M"!kICGJ,P@--$*AlSBq9Fi31RhAF#j\r9cL!fIBacH(eVBhKpr9YiJH(rV(qFHRL"BIqSIleDH#`&!!K!J3$F1+Arq&H-4Mk\r"`Iq`IFpcH$R1!!'4`Iq`QBm!!&H,KMk"JIq`IBjMH$Q-!!'4JIq`Q@i!!&H2aMk\r"BIq`I@aEH$PV!!'4BIq`QH`!!&H1"Mk"iIq`IHYlH$R[!!'4iIq`QFX!!&HX4Mk\r"`Iq`IFpcH$R1!!'4`Iq`QBm!!&HVKMk"JIq`IBjMH$Q-!!'4JIq`Q@i!!&H[aMk\r"BIq`I@aEH$PV!!'4BIq`QH`!!&HZ"Mk"iIq`IHYlH$R[!!'4iIq`QFX!!)'"rk5\r4JIqXJF(rS*("rkK,rr5-JH(rX(h[+K54iIq`+!8!#%'"!,JjBK[`9+`31ReVB#j\rpD31Q6S!%)&HZ"Mk"iIq`1Hrrrj(Krl#Cc`!!9k['2S'"rl!jM2rrNB(rX*PX!!"\rAVSBqJH(rX$R[rrq4iIq`QFm!!&HV4Mk"JIq`1Bcrrj'"rl#CE!!!9ii'2S(Krl!\rjlrrrNH(rX*R2!!"ALmBqJB(rX$Q-rrq4JIq`Q@`!!&H1KMk"iIq`1Hrrrj(Krl#\rCc`!!9iY'2S'"rl!jM2rrNB(rX*PX!!#j`Iqi6S!!)!#3"L"!!")!N!3D'!!4,Q4\rPFemcBf*MAf9ZBh*jF(3![X(rf$VL(63k`K`dI*NMH(ai'hL)Z!!!1aJ!!95r"Mk\r)f!!!1aJ!!96'"Mj8aN!ZIrmcH)Mi!!!l'!!"91F'2P6RJ"jrrcYiL4J!!$XB!!&\r9#!Bq93M!$Rrr3hL*1!!!1aJ!!98q"Mk*@!!!1aJ!!99+"Mj95N!ZIpj6H)Pi!!!\rl'!!"9@X'2P9VJ"jrhPYiLCJ!!$XB!!&9M!Bq9Bc!$RrHBhKAaH%qI+AkH$c!$`m\riaJm2I,``1(rriRKAKb!fIpikH&ISN!!DI3MkH(8Fc-aALA5qIqVLH(dr8RKAbj!\r!'ReVmRKeI-c-9iad[Rr&iRKpRLTi9mEiIRc'qRJmi&9911G99AcF1$Krrq*i9iJ\r)2(rH3RKAkF)qI5RbH$e!!2mj5J$rI6a31(rHiRKALd!ZIrpDH&I-q(jpM2Ti2+"\r996LP999pR#JiIrrLH&H'#$arhM*i9qF!"P6Ri6jAb!)H93L%2PI*"Mj9+B!H9mS\r%,RdT8hKp#%YiI2j$H&Ir!6ilB!!!5!!"@&GV%$TpGPJZ,!X!!%'#!#"Al2#q9qA\r3#RfI+hKAa[#q9mI3#RcH1hK)!!!F9qMiIPITf!Kp(dYi9mViIPI,f!KpAPYi9rm\r"2PIH!6jAl&Di9q9RrPIQAhamT60iIB`VH&@-%$SjM!-!ICGJ,PIRRcjAk*DfI1G\r$H&6R%$Sij`)!I2Fi,PITeljAkXkkI5P6H&8T%$Sj+3%!I6G),PIV"Vj9Da!kIAG\rB,RdT@hKmjdYiICSlH&I-AcjAa9DfIB`VH&@-%$SjM!F!ICGJ,PI'MVj8aK!k1-B\r'!(cA-#jAa`Dq91F31MMR"!"mpcJZ9mM2[PI*aVTp#%Yi93J31MN)"3"p&d!ZI1G\r$H(c'1hKpR$0i9iU!(PG,"$jpA9Yi9k`A[PHP%$TpM#S8NCN!!$Xj!!4A4S3q9iF\r!(RcG1hKAU$Dq9kN`-Rd)5K54'3!!1cN!"$Yl!!%X'`!33B$qU$KJ!!#k`IrB6S!\r!)!#3"L"!!!S!N!3#m!!-,Q4PFepcCA4IDf9j!!"m#!+QN!!"!!L8)Ir!N!"K!&L\r3!)%!A)"K!&L!J3"F1+)Y`%J!!$PJ!!!!1')Y`)!"!%Ji)3"!I!J$TNk!!#!!N!B\rJ3B!!N!Bm!!SZC'9cAf0bHA"dI!J#TVj"rmL3!!%!#*3Kr["mGKYiI*3MH(bk+hJ\rkiKcd1`%!1)Kd!!"mB`Gd,!-!!%##!!`iJ!""5!!!$)L8!!"mK!GdQ*S!!(b9"h3\riSKadI+@SVP5c%$U)e!!"I-B(G#`'!!"!JJ!-11!!38J!!!b)p!!"I1F(G*Mk!!&\rmp3Gd13)FG(d)U+j9%M!b1f!!!%J!!#b,eJ!!1YB!!9I*"MiS#3!!3B)!0&I+"Mj\r95JJm1@%!a(e,fDilH`!"+"X!#%'!rp4)!!!81B!!!$KK!-4pJpQZ1hX!!5JE!!K\r"J2rX1'%!a$L"!%4,rrZaB!!!!$KK!-`iJ3"%IQ@EH(j'NhK)!!%aB!!!!)-K!-a\rA*!BqQ*J!!$XB!!&A*FBqQ,J!!$XB!!&A*SBqQ0J!!$XB!!&A*dBqQ2J!!$XB!!'\r$)3$39bJ'2TNB!!!l'!!"9bR'2TNi!!!l'!!"9bU'2TPB!!!l'!!"9bY'2TPi!!!\rl'!!"1i!!!$[J!)!jJ!!!QB%!3$YJ!!*)!!"N1m!!!$ZJ!!")!!"!9pi)2$KK!$K\rmBq#Z9q3'2RaM)$JX!`!!3B)!#'2H!!&Arrjq9q8'2LJ&!!"!JJ!-1j`!!6[J!)!\rl[3!"+"d!"N'!rm"AaJBqI0F`VRcDfDilH`!"+"X!$8'!rj`ii!!!Q2S!$Ap$dhL\r!!3%B1#%"%(`)!kDk3Ir)6S!!)!#3"L""J!i!N!3#%!!,,Q4PFepQBh*jF(3!!!#\rq!Ir!1k)P0$Z!!!!lB!!!I*8MH*!!SIq`N!$"rk`ii!!!N!$Krl4)!!4-1X!!!%J\r!"#4AD)3qIhp#H)%Krl"rrNJiJ8(rV(rr8$KAfS!H9XX31Ree@#jrDeTiIpjDH(r\rHdRKAqS!H1CB!!9@-%$TpP@!ZIfaLH(rrBRKrrp*iIp4'F&ID"MT@P!Bk9qIK2PI\rSi!Crjd)89pk%2Rdpd#jrR%Ti193#!(eG8#jrR&*i9p2#2PID"MT@F`Bk1AS%!(e\rp@#jrR&Ti1C-'!(fGB#jrR'*iIr4'F&Ik"MT@P!Bk9rq%2MMk!3"mr6JZIj`kH$N\r8!`"p(8!ZIja#H(rc4R"AqJBk9R-'1MNk"3"p28JZIja+H$P6"`"pA9!ZIja5H&H\r,K$jrReTiJB(rX(rqB$L!iIqXIrmi1&ICJ"ij&J!#93J31Rd93#jrL%*iIpj#H(r\rHbRKAqB!H16B!!e8T%$Tp08JZIiP+H(rr5RKrrmTiIp*'F&IC"MT@8JBk9qVK2PI\rVi!CrkPS89pk%2RfGb#jrHf*i12)#!(cp1#jrHcTi9p(#2PIC"MT@-3Bk14N%!(d\rG3#jrHd*i16%'!(dp5#jrHdTiIr*'F&Ij"MT@8JBk9rq%2MPC!3"pA9!ZIhY5H$P\rb!`"pI9JZIhYDH(ra4R"Aq3Bk9M%'1MQC"3"pR@!ZIhYLH$Ma"`"mr6JZIhXkH&G\rSK$jrId*iJ5(rX(rq5$L"3IqXIrp31&IBJ"ijGJ!%9@X31Ree@#jrDeTiIpjDH(r\rH`RKAq)!H1CB!"9@-%$TpP@!ZIfaLH(rrBRKrrm*iIp"'F&IB"MT@%!Bk9qIK2PI\rSi!Crjd)89pk%2Rdp`#jrR%Ti19!#!(eG8#jrR&*i9m[#2T&KrkKAf!BkJB(rU&@\r-"MU4JIqS12J%!(cp1#jrR$TiJ3(rU$N)"J"p(8!ZIja#H(r`4R"Aq!Bk9K!'1PI\rrK$ij1!%!I6e),RqF5RJj8!-!I9e3,RqF8RKrkdC`N@(rU&Ii"MU"JIqS9B`'1T'\r"rkJiq!8!I2di,RqF1RL"!IqS13J(!(dG3#jrR%*i9iQ%2RqI5RL"3Iq`Irj31)&\rKrkarreJi9pH!(MQ@!!C9M"!kIC9J,Rq-BRKrhQ*iIpkkH&IhJ"iipJ!(91F31Rc\re1#jrKcTiIrmkH(rrZRKrb%C`N3(rT&IA"MU")IqN95N'1T%Krk4AkZ%q9q[J"Rr\rU@K4AhS3qICfi,RplBRL!iIqN11F#!(cp1#jrHcTi9mM#2T%"rk"Ae`BkJ5(rS&8\rT"MU4)IqJ19F%!(eG8#jrHe*iJ@(rS$PV"J"pI9JZIhYDH(rX4R#4JIqN9rF'1S$\rKrk48j`BkN!$Krk4Ari3q14F"!(dG3#jrHd*iJ5(rT$NT!`"p28JZIhY+H(rU4R#\r43IqJ9rF'1S&Krk"9D`BkN@(rS$QA"3"pR@!ZIhYLH)$Krk!ij`F!I2di,Rpl1RJ\rkeJ!),"B!)%'!qparRq0iIhcEH(rlqhL"!Iqd13J!!C%"rl5")Iqd,!N!'8'!ql"\rALZMq9i[S"(q+@K4AE1Mq9fIS"(pX1K4AL2KqI3MDH$dJ998j+999I4p)1(plqRK\rAkJJmIja5H&GV`MjpDq*i2B!!rcQ-!2ppIf!iIjckH&IR3#jrHcTi9iM`[Rd)fRJ\rp)$-c15Nc-hdI5$KrHrTi9qS31RqF8RKADi3qI@[LH&9r"$jrR2Ti9qb!(RplBRK\rAKq%qI1IDH$d!$`mj#!m2I2p!1(plqRKAk5!fIja+H*0M!!#6J`!%ZJ(r`%k!!#!\r!N!BJ3!!3!*!%"6`!$#jQBh*jF(4IBQpNH3!!I!J#TVp"rqL3!!%!#*3Krl"mHKY\riI*mMH(bl+hKmh$0iI2dlH(dH3hJX(J!!3B)!B(p$dhKrj2YiIfAEH(r'mhK,rlF\rGB!!!!(rMqhKrj2YiIiAMH$MJ!!!X(J!!3))!#$MJ!!&mjMYi5rqfp@!!!!"rirY\riIq6lH(qPkhKra[0i5rqfh@!!!!")!!"FId26H(rNqhKrTHYiImEcH%[rYX&J!!!\r!Iq2lH(rNqhKrKH0i13!!!#`H!!"!JJ!)13!!!Ad'3hK,rlDCB!!!!(rMqhKrj2Y\riIfAEH(r'mhK,rlD"B!!!!)!"!&Ji)3"3I!J$TVY"rqK1J!!J!*!')%'!"J#3"IJ\r!%5jNCA0I-f9MBPpPEQ0bHA"d!(a$%hK1J!!JI!J#TT!!!3!)P#(r`%[rrqemD4Y\riJ')!F)##!'`iSJ!!1-)YcS$L!'#"!J"F5!!!@B""!"5!JJ$8N!"N!!",rk0CB!!\r!!$KJ!!#!!3")1#%!3(`)!kC1J!!JI!J#TT!!!3!)P#(r`)"L!05!B`!!5!!!-B"\r"!"5!!3")1#%!3(`)!kC1J!!JJB)!2*!!33!8J!`!!)"-!!4m#31Q6S!%))'#!$L\r3!%%!&)!-!!#!6!!%I!N$TNk!"##"JJ!BN!""!"5!$!!!J%`!"(`*!kC1J!3JJB)\r!%*!!33!8J!`!!)"-!!4m#31Q6S!%))'#!%#3!%%!&)!-!!#!6!!%I!N$TNk!"##\r"JJ!JN!""!"5!$!!!J%`!"(`*!kC1J!3JJB)!$*!!33!8J!`!!)"-!!4m#31Q6S!\r%))'#!"53!%%!&)!-!!#!6!!%I!N$TNk!"##"JJ!NN!""!"5!$!!!J%`!"(`*!kC\r1J!3JJB)!#*!!33!8J!`!!)"-!!4m#31Q6S!%))'#!#L3!%%!&)!-!!#!6!!%I!N\r$TNk!"##"JJ!XN!""!"5!$!!!J%`!"(`*!kC1J!3JJB)!"*!!33!8J!`!!)"-!!4\rm#31Q6S!%))'#!!#3!%%!&)!-!!#!6!!%I!N$TNk!"##"JJ!`N!""!"5!$!!!J%`\r!"(`*!kC1J!3JJB)!(*!!33!8J!`!!)"-!!4m#31Q6S!%))'#!$53!%%!&)!-!!#\r!6!!%I!N$TNk!"#!!!!!FJ!!!I!J!N!DBJ!!!6!#3"LQXJ!!!Q!J!N!8U4)!!!)!\r)!*!&+X5!!!$3!*!'+j5!!!#3!"!!N!8X*)!!!'!!N!BXK)!!!+J3!*!&,5b!!!&\r)B!#3"5m)J!!"4%!!N!8`6)!!!+!)!*!&-1b!!!(m5!#3"6,SJ!!"`&!!N!8dU)!\r!!0!B!*!&0AL!!!#J'!#3"90NJ!!!@!#3"P1mJ!!#-(!!N!9E5)!!!4``!*!&A'b\r!!!"B!*!'A-5!!!!X!*!04L)2-!)L%c!#)JX`"L)G0))#"#8dAhKHL#h1"#*IH!B\rL!F5#!KJ"k!))!LJ#6!F`!c!$%!,3!T!!!R!YZ#di!0JE6aX`'fJEEa[`("3F0"c\rd((3Y`!$S!L%+!5)PH!%L,#!")L"p#5'BKJ)D!"`!j!b8%U3C`"MS'VJQC#QX,)3\rX*#Z8+X3U4#dX,`J`l$"--ZJdU$9i0KK39&1m8f4E5#)-C))#+JaB$%`-3!`d$#J\r-(!`3$!3$%!,m!ZJ#e!,%!V!#R!+)$V31S!k-$RJ1D!j8$N!1,#Bd*LJQ(#B3*J3\rPq#AX*H!Pe"c8(-!FV"bB()JFG"aJ(%`F2!8K%)%$"J!3!!!3%"!!!"!!%"!3!"!\r3%!3K%!3K%!)L%"!%)4#"!`X3!"!!%*!&!!!"%!!"!"!"%"!"!!!4%!!4!"!4%"!\r4"L%"!L%"!b)"!3%K!3-K!3%K!3%L!3%#*!'3"!-K!3)L!3%")3%")3%"*!'3"!)\rL!3%"*!'3"53"N!3%)3%%)3%#)J%""#%"!5%"!5%"!L)"!3%M!3%"##%%J3-0!3!\r!!3!%!!3!!!3%!33!!33%!!!J!!!N!3!J!3!N!!3J!!3N!33J*!%%*!%$)3%#)`3\r"!3)L!3%")J3"!5%%!5%"!58%"!%""!%P!3%%"!%#)L!"!L-N!3%")b!"!3%L*!%\r")`3J!3%U"#3"!33J!3%%*)%$$`)!!!)!"!-!!!-!"!)%!!)%"!-%!!-%"!)!)!)\r!*!-!)!-!*!)%)!)%*!-%)#8$"#3"!J)L!3)")`3"!`)L!3-"*!3"!J3"*`%#"!3\r"!`3"*J%$"!3"!J%M)!%#!5-N!3-")b!"!`%a*!%#"#!"!J3N!3-%)!%$"#3%)3)\r&)3J")3)")3J#)3J#)J))!b))#!%M!JJ)"#)"!J)K!3)M#!%#!5))!3%K#!%M!3)\r)!5%"!5F)#!%##!J"!L%"J3-(!J!"!!!*!J!*!!J"!JJ"!!J*!JJ*!L-"!3)")J%\r"!L-*!3)")JN"!5F)!3%##!%"!5J)#3%##!N"%!-K%J-K%!%K#!%K%J%K#!%L%!J\r#)K))!L-3#!J")a))#!%K%!)L!4)#)J%3!5-)!4)"*!J"%!J")`%5#!%U!4!)#!%\r5#!J"%!%K!B%$"a)!!4!!#4)!#4!)!4))!4!)#4))#5%3!5-"!4)")`%"%!%M#3%\r5!6)*!4!)!3%5#!%"%!J*!4))#3%&)33%)5##!J3%)"!!&!!3)#)8))%$##!!!#!\r%!#!!)#!%)#!3!#!8!#!3)#!8)!-K#)%$"J3!#!!J#!3J#"!!#"3!#"!J##38)!J\rJ!L-))!3")JJJ!5JJ##!%)!JJ%!%M##!8!5N))"!J##!8)!L"!`FJ!!!N!!!J)!!\rN)!!`!!!d!!!`)!!L0##"!`JJ)!!J*!!JN!3N)#!`!#!d!#!`)#!d)!%K)!%K#)%\r$"L3!##!J##3J#$!!#$3!#$!J##8d)!JJ)!%M##!N!5X))#!J##!N)!JJ-!%M##!\rd!5N))$!J##!d)!J()K!)J3-r!!!)!"!!!J!!!K!)!J!)!K!!!!)!!"))!!))!")\r!!J)!!K))!J))!K)%!!!%!"!-!!!-!"!%!J!%!K!-!J!-!K!%!!)%!")-!!)-!")\r%!J)%!K)-!J)-!K)!%!!!%"!)%!!)%"!!%J!!%K!)%J!)%K!!%!)!%"))%!))%")\r!%J)!%K))%J))%K)%%!!%%"!-%!!-%"!%%J!%%K!-%J!-%K!%%!)%%")-%!)-%")\r%%J)%%K)-%J)-%K)!!!!#!b%#!L)#!J3K!3%K!J%K!3)L!J%")`)#!33L#!)#)3J\r")3)")`J#!J%K#!)M!3J#!5)"#!%R!J%)!J)"#!%K)!)L!L!$)5)#)J)L!b)J!3%\rM!L!"!L)L!3%M!L)"!L%J!5-)!L!")3J")5)")`J#)J%K#!%R)!%)!L!"#!%R)J%\r)!L)"#!)K!S%$"`)!!J!#N!8!!!-#!!-!!J-#!J-#)`))!J%L!JJ"*`)##!)#!JJ\r#)`-)!J%L!`J"*`)$#!)#!`J")L!#J3-(!L!#!#)#!L)#!#!$!L!$!#)$!L)$!5F\rJ!JJ#)!))!5FL!JJ#)J))!5FJ!`J#)!-)!5FL!`J#)J-)"L%3"#%J!L)3)!%K%!-\rL%"!#)4!")5!"*"!3)!J$)3J")4!")3J#)L!)!533)!J3!L-)%"!")JJ3!58J#"!\r3))%$"`!!"!!3"!!!*!!3*"!!""!3""!!*#33%#3)!L)%#!%M%!3)!L)N#!%N%#3\r)%!%R"!J3%!3)%!%P*!J3%#5"!`F!"!!!&!!!"#!!&#!3"!!3&!!3"#!N%"3J#!%\rK"!%K#!%K&!%K#!%M"#!)!588)!J3"!%M#"!8!5J)%!3J#"!8))%$"`!%"!!8"!!\r%*!!8*"!%""!8""!%*#33&#3)!5-%"!J")a3%#!%M"#3)!6)8*!J3"!3)%"3%#"!\r%*!J3&#3%)4!%)3%#)K!""5)#%!)K!J%K!3%M!K!"!5%#!L%J!5%3!5%J!L)")!%\rM%!%J!b-J!K!")L!#!5F")!)3!5!#!5%%J3-(!"!%!!!&!"!&!!!%!K!%!J!&!K!\r&)3)")J3J!5-3"#!#)J8J!5-3"5!#*`3J!K!%)!)"+!8J!K!&)!)J!b%`!b)J!3)\rL-!%#)5!#)J)`!L-#)!%")`)`!3%L!L!")5!")6!")5!")b!")!%M-!%J!5%J!5-\rJ!M!",#!#)!%J!M!")!)J")%$"`!`"!!J"3!`"3!J"!)`"!)J"3)`"53#)!3J!5-\r`"#!")b!&)!%M-!8J!6!J"#!#-!3J!L!&)!)`"5!#"#%%"L)""))#$!%"!!8!!3%\r&!3!3""!!%334!4!&%!%4"5%4!5%)J3-2!!3)!!!)!33)!3%)!!8)!!%)!38)!3!\r)%!3)%!!)%33)%3%)%!8)%!%)%38))4%#)3J")35"!`i)!!!)!33)!3%)!!8)!!%\r)!38)!3!)%!3)%!!)%33)%3%)%!8)%!%)%38L#"%")JJ)!5-%#!J#+JJ)!33)#!%\r"#!J")`8)#!%S!3J)!38)#!%"*`J)%!3)#"!"0`J)%33)#"%"#!J3"3J)%!%)#"%\r&#!J4"b%3JJ)0!!%!%4!!%"!3!4!4!3!"%!%"!4%4!"%3%3%L%4'"!bm3!!!3!"!\r3!!%3!"%3%!!3N!8"%"!4%!%!%!%3%!%"%!%4%"%!%"%3%"%"%"%4!3!!!3!3!3!\r"!3!4!4!!!4!3!4!"!4!4!3%!!3%3!C!&%3%4!!%4%!%4!3%4%4%!!"%!%"%!!4%\r!%4%3!"%3%"%3!4%3%4%"!"%"%"%"!4%"%4%4!"%4%"%4!534%4%3J3-2!!!3!"!\r3!!%3!"%3%!!3N!8"%"!4%!%!%!%3%!%"%!%4%"%!%"%3%"%"%#34%4!3!L)3%!%\rM%"!3!5-"%"!"*"%3%"!",a#3"`%3%"!4%"!"!5m3%!%3%"!"!4!3!4%3%"%",K!\r3%4!3%"%"%"!4%4!"!L)3!3%M%"!"!5-"%!%"*"%3!4!",a!"%"!3!4!"%!%3%4!\r"!3%[%!%"%"!"!3%3!3%4%!%4!5i3!4%3%!%4!4!"%4%3%3)L%"%")a!3%3%M!4!\r4!534%"%3!5m3%4!3%"%3!4!4%"%3%3%",a!4!4!3%3%"%"%"%4!4%3%Y%"%4%"!\r4%3%3%4%4!B%$$`!!!3!3!3!"!3!4!4!!!4!3!4!"!4!4!3%!!3%3!C!&%3%4!!%\r4%!%4!3%N%4%"%!)L!4!")a!"%!%M!3%3!534!4!3!5m"%"!3!4!3!3%3%"%"%!%\r",`%3!4!"%!%"!4!"%3%3%3%Z!4!4%!%3%3%"%"%4!3%#)J%"!5-3!3%")`'3"#3\r4!3%3!5m"!4!3!3%3!3%"%"%"N!3[!3%"%!'3"a%"!4%",J%"%4!"!4%"!3%4%3%\r4!L)"%3%M%!%4!5-"!4%"*"%"%4!",`%4%"!"%4!"!4%3%3%4!3%[!4%"%!%4!3%\r"%3%4!4%4!5d"%4%3!4%4!3%4N!5"!`m!!"%!%"%!!4%!%4%3!"%3%"%3!4%3%4%\r"!"%"%"%"!4%"%4%4!"%4%"%4!4%N%4%4%!)L%4!")a!4%!%M!4%3!534%4!3!5m\r4%"!3%4!3!4%3%"%4%!%",a%3!4!4%!%"%4!"%4%3%3%Z%4!4%"%3%3%4%"%4%3%\r#)K%"!5-3%3%")`%4!3%N%4%"%!%[%3%3%"%"%!%4!4!4%3%"!5m4!3%3%3%"!4%\r"!4%4!4%",K%"%4!4!4%"%3%4N!3#)K%4!5-3%4%")`%4%3%N%4%4%!%[%4%3%"%\r4%!%4%4!4%4%"!5m4%3%3%4%"!4%4!4'3"!%X%4%4%"%4%3%4N!3%)3)%)3)#)J)\r#"#%#!5%#!5%#!L)#!J%M!J)#"#)#!J)K!J%K!J%M!J)#!5%#!L-#!J)")J)#!5J\r#N!F"!b%$!b)"!J)L!`)#)3%")3)")3-")3)")`%#!J%M!`)#!5%"!L)#!`)M!J%\r#!5-#!`)")J)"!5-#!J-"+J)#!3)#!J-#!J)")3%#)J)"!b%$!L)#!`-L!3)")`)\r"!J)L!`)")`)$!J)K!3%M!J)"!5%#!5%$!5-#!J-")3)"*`%#!J)"!J)"+3-#!J)\r$!J)"!3)L!`%#)J%$!L)$!`)M!3%#!5-$!3)")`%$!J%M!`-#!5)"!3%M!J-"!5-\r#!3-")`)$!`%a!J%"!J)$!3)#!3-#!J-$!J)#)3'"!`F#!!%!!J%#!J%!!!-#!!-\r!!J-#!J-#)`%#!J%L!3)"*`)"!J)#!3)#)`-#!J%L!`)"+!)$!J)#!`)"!5%"J3-\r(!`!"!3)"!`)"!3!$!`!$!3)$!`)$)3%")`%#!`%V!3)"!J%#!`)"!J%")`-#!`%\rU!`)"!J-#!`)$!J%L!3'"!`F#!3%!!`%#!`%!!3-#!3-!!`-#!`-"*`%"!J)"!3)\r"*`-"!J)$!3)"*`%$!J)"!`)"+J-$!J)$!`)"!3'"!`F$!3%"!`%$!`%"!3-$!3-\r"!j!&)#!"!3%#!`%"!J%$!3)$!`%#!3%$!J-"!`)"!`-#!`-$!J-L!3)#)3%")3)\r")`%#!J%K!3)M!J%#!5)#!3%R!J)"!J)#!3-L!`)#)3-")3)")`-#!J%K!`)M!J-\r#!5)#!`%S!J)$!J)#!`%#)J%$!L-"!3)")`%$!J%L!3%")`)"!`%V!J%"!J)"!`)\r#!3%#)J-$!L-$!3)")`-$!J%L!`%")`)$!`%U!J-"!J)$!`)#!`%K!3%M!3)"!5%\r"!5%$!5-"!J-")3%"*`%#!3)"!J%"*`-#!3)$!J%")3%")`-#!3%K!`%K!`%M!`)\r$!5%$!5F"!J-#!3)$!5N$!J-#!`)$!3%")`%$!3%M!3%$!5-"!`-"-`%"!3)"!`%\r#!3%$!J%$!`)"N!3M!`-"!5-$!3-")`-$!`%a!`%"!J-$!3)$!3-#!`-$!J-#)`%\r"!J%L!3%"*`)"!3)#!3%#)`-"!J%L!`%"*`)$!3)#!`%#)`%$!J%L!3-"*`)"!`)\r#!3-#)`-$!J%L!`-"+!)$!`)#!`-"!5-"!3-"+`%"!3)"!3-#!C!%)`-"!`%V!`%\r"!J-"!`)$!3%")`%$!`%V!3-"!J%$!`)"!`%")`-$!`%U!`-"!J-$!`)$!`%R!3%\r"!J'3"#F$!3%#!`%"!5F"!`%#!3-"!5F$!`%#!`-"!5F"!3-#!3%$!5F$!3-#!`%\r$!5F"!`-#!3-$!5"(!`-$!J-$!`'3"!-"N!3$!3%$!`'3"!-"!`%$!3%$!`%$!`-\r"N!3$!`%"!`%$!3-$!`%$!3%$!`-"!`-"!j!(!5%3!L)#%!%L!3)")J3""L%%!5%\r#!5)%!3%Q%!3"!K!%!53#%!3"!5%3"L%#!L%"!b)"!J-L!K!")3%#)`3"!J%K"!)\rM%!3"!5%3!5)"!J%K"!%K!J)M!3)3!L-#%!3#)4!")`%#%!3K"!-Q"!%#%!3"!5)\r3"!3L!3)%)K!%!5%#"#)3"!)K%!)K!J%M"!%#!53%!3)3!5-"!K!")3%$)3%")4!\r")J%#!b%#!5%%!L%3!L-#%!3$)J3"!5B3"!%#%!3$)`3"!J)R!3)3"!%#%!-L%!3\r)*3%#%!3""583"!%#%!3K"!%K!J)L!3)")33$)33#)4!")3%")S##"b'!!L1!JJ+\r"!aL!J!)!JJ)!!!)!J!!!!J#!JJ#!JJ)!!J#!!J+!J!+!!*!%!J!#!S!#!)!#!!#\r#!!##!)#!!)#!!)!#!J#!!S!!!S!!!J#!!J8L!J+"!ad!JJ+!!!!!J!#!JJ)!!!+\r!J!#!JJ#!!!#!!!!!!J#!J!)!J!!!JJ#!!!)!!J!!!!+!!J)!JJ+!JJ)!J!+!J!#\r!!J+!!!)!!J)!JJ+!JJ!!!J+!!J#!!J!&)S!#!L'#"L1!J!)#*3%%"!%""5)%!3%\rL"!3")3%'*!%""!3")3%#)3%")J3%!L)%"!)K"!%K!3)N"!%""!%K!3%M"!3""#-\r""!3'*!3%!3%$)3%#)J%"!5)%!3)L"!%")33"*!%""!3")J%%!5)"!3)K!3)K"!%\rL!33$*33%!3%%!L%"!5%%!b-%!3%")33%)3%")33#)J%%!5%"!L-%!3%")33")3%\r()3%#)3%"*J3%!3%%"!%K!3%K"!)K"!)K!38L"!%")J3%!5)""!%K!3)K"!-N"!%\r""!-K"!%M!3%%!5)"!3%K"!)M"!3"!L%%!5)""!)N!33%!3-M!3%%!b-%"!%")33\r")J%""#1!!33")i!""!)K)3)KJ!%K"!8LJ#!$)J%%J3-,!#!%J!!%!!%!J#!%J#%\r!J#%%!!!%J#!!!!%!!#!%!#!%"5%J!L1!)35"!aq!)35!!3#!)33!)!#!!!!!)3!\r!!35!!3!!)3!!!!5!!!3!)3#!!!#!!3!!)!!!!33!)3#!)!5!!3#!)!!!)33!!35\r!)!5!!!#!!3!!)33!)35!!!5!)3!!)35!!33&)L!%!L%K"#%%!5+!!3)LJ#!#)B!\r")33')L!%!L)""!%LJ#!#*)#!3"!")B!")a"!J!%L%%!$)8!"*8!33)"!!50!J%!\r#)B!")4!')N!3!L*!%!%PJ%!33)!#)8!&)8!")d#!3!)KJ!8K%!)K3!)MJ%!3"#&\r!!5&!!L'!!5%3!b333)"!!5*!J!8L%%!")8!")8!#)4!#+%!33)"!%%#!!L&!!5&\r!!50!J%!$)N!3!5@!3""!J!)K3!NL3"!$)K"!!5&!!50!J%!")N#!!b1!3"!")B!\r")a"!J!%L%%!$*N#!3""!J!)L3)!&)4!")S"!!L'!!5%3!L9!%%#!3!%L3)!")4!\r$)K"!!5&!!L1!3"!%)8!")8!%)4!#*%!33"!#)`J3)!3K)!%Q%#!J#"!J"58)%#!\rJ#!%K)!)K%!%K)!)M)#!)!5%J!L%3!L%)!5%J!5))%!%K)!%K%!8L)!J&)5!")JJ\r3!5)J#!)K)!)L)#!")4!")L!)!b-)%#!")`J3)!%K#!8Q)#!)%#!J!b)J#!%L)#!\r")a!J)!%K%!-K%!%K)!3M#"!J!5%)!5)J)!%N%#!J#!%K)!3M)!J3!L%)!5%J!L%\r3!5%J!5%3"5-J#"!#*3J3)#!)!5)J)!%L%#!$*L!J#"!J)!8L%#!")3J$)3J#)5!\r")K!J!b-J)!J#)5!#)5!")JJ3!5)J#!3M%#!J!5%3"#%J!5))%!%M)!J)!5)))!)\rK#!)K!J)P#!)))!J$)3J")JJJ!b)J#!3K!J%M)!J#!L3)!JJJ!5)##!%M#!))!L-\r###!#)3J%)b!)!J)K#!)L)!J")3J$)JJJ!5)##!)K!J%M)!J#!53J#!))!b)))!J\rL#!)")L!)!L)J#!%K#!)M!JJJ!5%#!b-###!")3)#)`J##!-K#!3M)!J#!5%J!L%\r)!L3###!)!5%)"#)J#!)M)!J#!L))!J%L)!J%)3)#)3J")JJJ"#3)!JJJ!5%#!5)\rJ#!)M)!J#!L%)!5%)!5%)!5)))!3N#!)))!%L!JJ#)J))!b)))!)L##!")3)")L!\r)!b-)!JJ"*8!)3""!!5&!!b&!!L-)3"!")3J&)a"!#!%L%%!")d!33!)S%%!)3""\r!#%!")8!$)8!")8!#)3J&)a"!#!%K%!%L#%!#)3J")K"!!5*!%!3K3!8K3!)P#%!\r33!J$)3J")K"!!L%3"5))3!-P3""!#%!")N!)"#*!%!8P#%!33!J")4!")3J#)8!\r"*%!33!J#)d!)3!-K3!%L3!J#)8!")8!%*4"!#%!3!5-)3"!$)4!#)8!")8!&*8!\r33!K!!L%)!L&!!L%3!5%)!5)33!%M3""!!L%3!5%)!5%3!5))3!8K3!%K3!-M3""\r!!b*!#!%P%%!)3"!")JK!!6i+9Q9bD@CjD@jR,#"`E'9KFf8JFQ8YC@jdCA)J*A-\r"1!S("deTFfeKG'0S)#dJG(*j)'&RB@PZ#J%Q)$"i)(XJ!5#"!!'3#2k3#"q3"!k\r3"1#3"2'3"!(q!Ii"rJ(qrJ(q!Ii"rJ%Ii"rJ$[%1mH!Ii"ra$[%1!H!"i!(a!I(\rJ!H!"m3(a!4rq(ri1rJlqrKrq(ri1rJi"(`%I!3i"$Km"(`%1!3i"i2lJr[(qmIl\rqi2lJr[(qm3-L8#L#!K"3&&!!6qa2f%r%6l"2R%q)1%`i1$JN1"!i!$IX0pJha!N\rK!B)#"3!"!!%!!3!"!!%&)3'#!J8!!3!"!!%!!3!"!L!ZdY28eGEAf0RDfpcGhYr\rJiH,Mj1AQjqMTkZ[XlHl[m2(bmr6ep[IiqIVlr2hqr`%JJ4%"!J-%"3B(#!N+#`8\r'"`J*#JX-$3i2%"%5%a39&KFB'4SE("dH(b!K)L-N*5!K)L-N*5BR+#NU+b`Y,Lm\r`-6)c0$8f0cJj1MXm26ir3%&#3d3Z,c!a-M-d06Bh1$P"3N0%48C(5%P+5da06Np\r389*69&9@9eKC@Q&LBf4PCQGSD@TVE'eZEh"aFR0dGAChH(Pk"b)3)!-K)!)K%!%\rK!3-K!3%M%#!"!L)J!3%K%!)K#!-M#"!J!5%)!5%J!5))%!%L!3J#*J%)%#!"#!%\rN)!%)%!-K)!-L-#!#)L!J!L%`!5%"!5%J!5%"!5-`)!%")b!J!3%K-!)L##!#)`J\r`)!%M##!J!5))-!%M!3JJ!5X"#$!J!3JJ)!%)-!%K#)%$"`!!#"!J#!!J#"!!#3!\r!#4!J#3!J#5%3!5))#!)Q#!J3)!J)!53J#!J3!5)*#!)Q#3J3)!N)!53J#3J3!5%\r)J3-()!!)-#!))#!)-!!*)!!*-#!*)#!*)6!")`J))!%V#!J`)!J))#!)#$!")`N\r))!%V#3J`)!N))#!*#$!%)3)&)5!")3)")5!#)5!#)J)J!b)J)!%M!L!J"#)%!J)\rK"!)M)!3#!5)J"!%K)!%M"!)J!5%%!5FJ)!3#)#!%!L%%J3-(!J!%!!!N!J!N!#!\r%!L!%!#!N!L!N!L-%"!)")J3%!L-N"!)")L3%!5FJ"!3#)!3%!5JJ*!3#)#3%%!-\rK%J-K%!%K)!%K%J%K)!%L%#!#)K)J!L-3)#!")a)J)!%K%!)L"")#)J33!5-J"")\r"*#!%%#!")`35)!%U""!J)!35)#!%%!%K")%$"a)!""!!*")!*"!J"")J""!J*")\rJ*#%3!5-%"")")`3%%!%M*!35!6)N""!J"!35)!3%%#!N"")J*!3()3%")35"!`d\r!!!3"!3!!!3!"!33!!33"!!!#!!!$!!3#!!3$!3!#!3!$!33#!33K!`)K!J-L!J%\r")J3#!L3%!J%"!5%#!5%"!58#!3%%!J%N!33#!3)L!J)#)J)$!5-%!J)"*!3#!`%\r")`)#!3%V!J-""!)#!33#!`J$)3J#)`%)")%$$3!)"!%*!!!*!!%*"!!*"!%)!!)\r)!!-)"!))"!-*!!)*!!-*"!)*"#)$#!%K!J%K#!%P!J%)"!)"*3J%!J%*!5%#!5%\r*!58#!3N%!J%P#33#!3J")`)##!%V!J-)"!)##!3#!`N")`)##3%U!J-*"!)##33\r#!`8K%!3K!3)L%!%%)3L"!`S3!!J!!3J3!3J!%!!3%!!!%3!3%3!!%!J3%!J!%3J\rN%"%)"!-L""!#)33")3%")`33!3%K"!)M#!33!5))"!%R!3J%%!%)"!%K%!%M""!\r3!5%%!5%4!5-%%"%")33"*a!)""!3#!3"*K%)""!4#)%$$`)!!")!!!)"!")"!!)\r!#")!#!)"#")"#!)3!")3!!)4!")4!!)3#")3#!)4##85%3J%!J)L"")#)`3#!3%\rM"")"!5)%!J%M#!35!5`)"!)"#!35!3J%!K!")`35%!%M"!)4!5-%%K%"-!3#%!J\r%%K!)"!)4#!35%3J%)4!%)3%#)K!""5)%%!)K"!%K!B%$'333!33J!!!`!!!J!3!\r`!3!J!!3`!!3J!33`!33!%!!3%!!!%3!3%3!!%!33%!3!%333%33J%!!`%!!J%3!\r`%3!J%!3`%!3J%33`%5%%!L%3!5%3!5%3!L)"%!%M%!%3!b-3""!")K!%!5J"%!3\r3!4!%)!%K%!%K-!%K%!%M)!%3!5-`!4!")5!")a!%-!%U%!3J!4!%-!%3"!%L%"!\r")a!3%!)L%4!")a!4%!)R%"!%%"!3"!%U%4!%%"%3"#!3%!%M-"!3!5-J%4!")c!\r4%!%`)"!3"$!3%!3J%4!%-"%3"!3K#!BL#!J#)3J#)33")3J")33$)`3)#!%L"!J\r")3)#)JJ#!b%#!5-)#!)")3J")J)%!5-)!J3#*`)%#!J#"!J$)J%)J3-'!!%!!!N\r)!!N!"!%)"!%!"!N))J3*!5%#!5-"#!)")3%")3)")`N)!J%K#3%R!J3"#!)%!3%\rS!J3*#!)%#3+"!`F!!!S!!!)!#!S!#!)%!!S%!!)%#!SN"!J#!J)L#J)#)J)#!5-\r)#J)"*!J#!J3")`S#"!%T!J)%#!S#"!J#J3-(!!%+!!%#!!N+!!N#"!%+"!%#"!N\r+*!3*!J)")`%+!J%M!3)#!5-*#J)"-3N#!J3"#J)%!3)#"!N+!J3*"L%"J3-'!!J\r!!!J"!3!!!3!"!3J!!3J"!b%3!L)"%!%K#!%K%!%N#!%3!3)L%!%"*!%3!3J"*4!\r"#!%3!5%J!b)J!B%$"J!S!!!S!3%J!!%J!3%S!!%S!3%K)!%K%!%M)!%3!5%S!5%\r3!58S!4!")!%R%!%J!4!"+!%P%!%S!4!#)3+"!`F!!!-!#!)!#!-"!!)"!!-"#!)\r"#!-#)J)3!L)$%!%M#!)3!53)!a!"!5-#%!%"+J-3!3J#%!%)!a!")L!#J3-(!#!\r$!#J#!#J$!5!#!5!$!5J#!5J$!5-J!K!")b!$%!%M+!)3!6-S!a!")!)3!5!$%!%\rS!K!"+!-3"#%%"#%%!L)%"!8L!J3#)3)")33")`)%"!%K!J)K)!%K"!%K)!)L"#!\r")`3%)!-M)!)%!5)J!J%R"#!#"!3J!J-L)!3#)5!")33")b!%"!%K)!-L)J3#)5)\r")33")b)%"!%K)J)M)#!%!5)J)!%R"#!J"!3J)!)M)#)%!5)J)J%R"#!L"!3J)J)\rK#!%K"!%K#!)L"!J")`3%#!-M#!)%!5))!J%R"!J#"!3)!J)K+!%K"!%K+!)L"#J\r")`3%+!-M+!)%!5)S!J%R"#J#"!3S!J)M##!%!5)))!%R"!JJ"!3))!)M##)%!5)\r))J%R"!JL"!3))J)M+#!%!5)S)!%R"#JJ"!3S)!)M+#)%!5)S)J%U"#JL"!3S)J)\r)#!)K#!)K!J)Q!J))#!)#"#-)#!)")3J")J)#!L%#!5B)#!)##!J")J))"#-)!J)\r")`J#!JJK#!%K!J%K#!8L!J)")3J#)JJ)!5B##!J#!JJ%)`J#!J%K#!3K!J)K#!)\rL#!J")J))!5%#!L%)!5%#!53)!J))!5%###8##!J#!J%K#!)K#!%N!J))#!)K#!3\rM#!)#!5%)!5)##!%K!J)K#!)L#!J")3)#)3)")`J)!J-L!J)#)`)##!)N!JJ)!J%\rL#!J")J))!L%#!5-)!J)&)JJ#!5%)!5%#"5%)!L%#!b%#!58)!J))#!3M!J))!5%\r#!L%)!LF)#!*!%)!3"5)3J!%L3"!#)8!#)4!#)i!33!%KJ!)L%)!$)B!")N!3!5%\r3!b)33!%KJ!)K%!%N%%!3J!%L3"!&)4!")4!#)8!"*)!33"!")4!#)B!#*"#!%%!\r))4!")K"!!5+!%!%Q%)!33"#!!5&!!L)33!3K%!3QJ""!%)!3!5%3!5333"#!!5&\r!!5'!!LF3J""!%)!3!5%3!5)33!)K%!3K3!8LJ"!")4!#)N!3!5%3!L'!!5&!"#3\r3J""!!5@!%%!3J!-KJ!8K3!)K%!-P%%!3J"!")K#!!5*!%!)L3"!")4!")4!%)i!\r33!%KJ!%K3!%LJ"!$)a"!%!-L%)!")33#*!%%"!%$)3%")33")J%"!5%%!5)""!-\rK"!%L!3%")J3"!5%%!5%"!L%%!L)%"!8P!33%!3%#)J%"!b-""!3")3%&)33"*!%\r%"!%$)3%$*J%""!3"!3%K"!)K"!)M!33%!5)""!%K!3)P"!%""!3$)J3""5%%"#B\r%!3%%"!%$)3%%)3%")33%)J%"!5%%!5-""!3#)33")J%""#-%"!%#)J3"!5)%"!%\rK!3%K"!%L!33$*!3%!3%$)3%"*!3"!33#)J%%!b3%"!%"!5%%!L%%!5%"!5%%!5)\r"!3%L"!%")33")3%&)J3%!5%"!L-"!33#)3%")`3"!3)K!3%L"!3$*%!3#"!")4!\r%*3J33"!)"#)33!)K%!%L%!J")8!"*!J33"!")4!#)JJ3"5-3#"!#)3J")d!3#!%\rK3!)K%!-L%%!")3J")N!3!b%3"#%)!5*!%!%K%!%N%!J33!3K%!-L%!J&)8!"*!J\r33"!")4!")4!")K"!!58)%%!3#!%K3!)L%%!")3J#)K!)!5&!!L%3!L%)!5*!%!%\rK%!%K%!3M#""!!L%3!5)3#!BK%!)K3!%K#!3L%%!"*!J33"!$)4!")4!$*""!%!J\r")d!3#!%K3!)N%%!3#!-L#"!")4!#)d!3#!%K3!%K#!%L3"!")K"!!L%3!5)3#!)\rM%!J3!b%3!L3)%%!3!5%)"#%""#%%!5B)!33J#!%")L!)!5%%!L8""#!)!3-K!38\rL)!J#)5!")J%%!5%)!53%)!J"!53J#!%%"L)""!%K#!3K!3%K)!)M"#!)!5%%!L-\r""#!%)3J#)5!$)L!)!5B%)!J""#!")3%")b!)!33K"!-P"#!)!33")`J""!%K#!%\rL"#!")3%")b!)!3-K!38L)!J#)L!)!5%%!5%)"#)""!%N#!%%)!8N!33J#!8K"!)\rK!3%L)!J")J3J!L%%"5B)!33J#!%"*#!)!33$)J3J!5%"!b)""!%L#!%")L!)!5%\r%!b)%)!-K)!%P!33J#!%#)3J#)L#!!L&!!5%J!5&!"#1!)#!#)5!")8!#)5!")B!\r")L"!!5%J"#BJ3)!J)%!")L!J!5'!!b'!!5%J!5'!!L0!J#!$)b!J3!%K)!)KJ!%\rN)%#!)!%K3!BK)!3N3)!J)!%LJ#!"*d#!)#"!J#!#)B!&)L"!!b&!!5)J)!)N)#"\r!J!%K)!-M)%#!!b'!!5%J!LBJ)%#!)#!#)5!")8!%)B!")5!")B!&)5!")S!J!5&\r!!5%J!b%J!59!J#!J3!%L)#!%*8#!)#"!!5)J)!)K)!)KJ!%M)%#!!L0!J#!$)b!\rJ3!BK)!%KJ!)L3)!"*5"!J#!J!5+!)!3L)%!$)d#!)!%K3!)K3!-K!J%K!B%$(3)\r!!3!%!8)%!%!%!%)!N!3"!!!"!J3!!J3"3!!!!!3"3J!"3!!!!J3"!J3!3!!!3!3\r"3J3!!!!"!J!"!!3!3J!"3!3!3J3"3J!!!!3!3J3"3!3!!J!""#0#"!'"!`T!!!&\r!"!!#"!"!!!!#!!%!!!&!"!%#"!"#"!"#!!!%)3)")3'"!a)!"!!!"!%#!*!%!3)\r%!3)!!%)!!!)%!%!!!8)%!3!!!8)!!!!%!%!%!8)%!3!%!8)!!8!!!#4!"##!J3-\rHJ###!!!#J!!!!#!#!!#!J##!!###J!!!J#!!!!##!!!#J!##J#!#J#!!J##!!!!\r#!!##J!#!J#!#!###J#!!J!#3"))!)!!!!)!!)!+!))#!!)!!!!)!)))%)B!")B!\r$)3)#)5!#)i!JJJ%KJ!%K!J%LJ#!))B)#)L#!!51!)!)")i!J!J-KJ!%MJ###"5'\r!!5'!J3-*J#!#!###J!#!!##!!#!!J!##!!!#J#!#J##!"#1!))+"!`B!!)+!!!!\r!)!!!))#!!!)!!))KJ16@!!!"!!!!!@!!!!"J!!!!-J#3&&4&@&3ZC'9Q!*"!9%9\rB9#jNEf-!N$`3!!!!9%9B9#jS!*"#9%9B9!!!!&`!N!X"!*!6!A"hF'-!N"-"!*!\r42"&0594IT@4PFfaTBLjNC@*eC`!!!3!!!!&J!!!!B!!!!$)'Ce5-Aa`!!!!F!$)\r!!'0QFQF!!!!+!!$rr`#3"!CRA"$$eJ:\r
\ No newline at end of file
diff --git a/src/mac/libraries/DES/doc/ChangeLog b/src/mac/libraries/DES/doc/ChangeLog
deleted file mode 100644 (file)
index e9afaec..0000000
+++ /dev/null
@@ -1,369 +0,0 @@
-Wed Jul 26 19:25:10 1995  Ken Raeburn  <raeburn@cygnus.com>
-
-       * quad_cksum.c: Include string.h for memcpy declaration.
-       * random_key.c: Ditto.
-
-Wed Feb 1 12:00:00 1995  John Rivlin  <jrivlin@cygnus.com>
-
-       * Makefile.in: Create install-windows target
-
-Tue Nov 22 10:53:16 1994  Ian Lance Taylor  <ian@sanguine.cygnus.com>
-
-       * random_key.c (des_random_key): Don't assume that the argument is
-       aligned on an integer boundary.
-
-Mon Oct 31 19:40:21 1994  Ian Lance Taylor  <ian@sanguine.cygnus.com>
-
-       * Makefile.in (CODE): Remove Imakefile.
-
-Fri Oct 28 15:21:01 1994  Ian Lance Taylor  <ian@sanguine.cygnus.com>
-
-       * read_password.c (old_sigfunc): Use sigtype in declaration,
-       rather than guessing based on POSIX define.
-
-Mon Oct 10 19:18:48 1994  Julia Menapace  (jcm at toad.com)
-
-       * mac_time.c:  Include des.h and AddressXlation.h.  Put
-       gettimeofdaynet wrapper on gettimeofday_no_offset so it can be
-       returned as a DES pointer with the expected calling sequence.
-
-       * new_rnd_key.c: Make forward declarations and function
-       definitions match the function prototypes that were added as
-       new external declarations to des.h: des_set_sequence_number, 
-       des_generate_random_block, des_new_random_key,
-       des_init_random_number_generator. des_set_random_generator_seed
-
-       (des_init_random_number_generator): Changes to port routine
-       to the Mac.  Initialize the seed using RANDOM_KRB_INT32_1
-       and RANDOM_KRB_INT32_2 instead of gethostid and getpid.  Use a
-       KRB_INT32 instead of a timeval and set it using TIME_GMT_UNIXSEC
-       instead of gettimeofday.
-
-Tue Aug 9 12:00:00 John Rivlin (jrivlin@fusion.com)
-
-       * win_time.c: Removed copy of time structure as stack
-       is now set up properly.
-
-       * Makefile.In: Broke up clean target to not do useless
-       deletes on unix.
-
-Mon Aug 29 10:12:42 1994  Mark Eichin  (eichin@perdiem)
-
-       * key_sched.c (des_key_sched): even if we return an error, build
-       the key schedule anyway. This helps with testing, and avoids
-       garbage encryptions in cases where the error isn't checked.
-
-Fri Jul 29 17:18:55 1994  Mark Eichin  (eichin@cygnus.com)
-
-       * random_key.c (des_random_key): use KRB_INT32 for half-key
-       manipulation, so the upper half really gets set.
-
-Tue Jul 19 20:06:14 1994  Ken Raeburn  (raeburn@cujo.cygnus.com)
-
-       * random_key.c (des_random_key): Don't initialize static local
-       variable n.  Fiddled with whitespace in srandom call.
-
-Fri Jul 15 17:35:30 1994  John Rivlin (jrivlin@fusion.com)
-
-       * ren.msg: updated to handle all files (changelogs, makefiles etc)
-
-       * Makefile.in: added "-" on clean: to avoid stupid messages
-
-Fri Jul 8 02:40:54 1994  John Rivlin  (jrivlin@fusion.com)
-
-       * makefile.in: Updated file with portable directory syntax for PC.
-       Changed .o and .a references to portable syntax
-       Removed all response files which needed to be generated under unix
-       to simplify configure process so that it may be run on the PC.
-       Placed objects in .lib file so that DLL construction can take place
-       without a response file.  This solves a problem with running out of
-       memory on the PC during builds.
-       Updated clean: target to place rm commands on seperate lines for
-       compatibility with PC DEL command.
-
-Tue Jul  5 11:31:59 1994  Ken Raeburn  (raeburn@cujo.cygnus.com)
-
-       * string_to_key.c (des_string_to_key): Deleted static and (some)
-       register decls.
-       * quad_cksum.c (four_bytes_vax_to_nets): Ditto.
-       * util.c (des_cblock_print_file): Ditto.
-
-       * weak_key.c (weak): Now const.
-       (des_is_weak_key): Compensate.
-
-Fri Jul  1 03:12:31 1994  John Gilmore  (gnu@cygnus.com)
-
-       Make Kerberos build using Think C on Macintosh.
-
-       * mac_time.c:  Use GetDateTime, not time.
-       * quad_cksum.c:  Avoid using printf().
-       * %DesLib-project:  New Think C project file for building
-       the DES library as an ordinary library.  (Unfortunately this
-       is a binary file -- there are no textual makefiles in Think C).
-       This makes it semi-possible to debug the code.
-       * %DesLib-project-A4:  Ditto, for building as a library to go
-       into a device driver.
-
-Thu Jun 30 23:11:11 1994  John Gilmore  (gnu@tweedledumb.cygnus.com)
-
-       * *.c:  Remove remaining RCS ID strings.  Strings used as `char *'
-       initializers upset Think C when building device drivers, since it
-       doesn't have a good way to relocate the pointers when the driver
-       is loaded.
-
-       * f_parity.c:  Clarify public domain ownership.
-
-       * *.c:  Use #include "..." rather than #include <...> for
-       our own local include files, because Think C can't find them
-       when enclosed in <...>.
-
-Wed Jun 22 18:29:48 1994  Ken Raeburn  (raeburn@cujo.cygnus.com)
-
-       * new_rnd_key.c, string_to_key.c: Include <string.h>.
-
-Tue Jun 21 00:15:31 1994  John Gilmore  (gnu@cygnus.com)
-
-       * new_rnd_key.c:  Lint.
-
-Sat Jun 18 09:05:30 1994  John Gilmore  (gnu@cygnus.com)
-
-       Make DES library independent of krb library again.
-
-       * Makefile.in (SRCS, OBJS):  Use DES_TIME_SRCS and DES_TIME_OBJS.
-       * unix_time.c, mac_time.c, win_time.c:  New files implement
-       TIME_GMT_UNIXSEC for the various hosts.  Code moved from *_glue.c
-       in lib/krb.
-
-Fri Jun 17 05:01:03 1994  John Gilmore  (gnu@cygnus.com)
-
-       * Makefile.in (DESSRCS):  Move read_password.c to SERVER_DES_SRCS,
-       since we don't use it on micro clients.  Clarify comments.
-       (Links of test routines):  Add $(LDFLAGS) to the line so that
-       mac-mf.sed can find these and modify them to run "Link".
-
-Thu Jun 16 17:08:58 1994  John Gilmore  (gnu@cygnus.com)
-
-       * Makefile.in (unixmac):  New target.
-
-Fri Jun 10 23:03:08 1994  John Gilmore  (gnu@cygnus.com)
-
-       * f_tables.h:  Add comments on the DEB macro.
-       * new_rnd_key.c:  Remove RCS crud, update export notice.
-       * random_key.c:  Clean out obsolete config crud.  
-       Use TIME_GMT_UNIXSEC_US rather than gettimeofday.  Use
-       RANDOM_KRB_INT32_1 and RANDOM_KRB_INT32_2 rather than
-       getpid() and gethostid().  Remove RCS crud, update export notice.
-       * string_to_key.c (des_string_to_key):  Int functions return results.
-       * testit.c:  Print usage message if no args.
-       * verify.c, testit.c: Declare des_debug extern, not common.
-
-Wed Jun  8 13:09:14 1994  John Gilmore  (gnu@cygnus.com)
-
-       * Makefile.in (DBG):  Move to where it will actually work.
-       * testit.c, verify.c:  Include <krb.h>.  Remove raw extern
-       declarations.  Pull RCS crud.
-       * verify.c:  In Windows, set screen buffer to keep all output.
-
-       * string_to_key.c (des_string_to_key):  Fix argument type to match
-       correct prototype.  Pull RCS crud.
-
-Fri May 27 16:55:33 1994  John Gilmore  (gnu@cygnus.com)
-
-       * Makefile.in (DBG):  Override with library-building flags.
-
-       * des_internal.h:  Include krb.h when compiling the DES
-       routines, since it describes some of the DES routines when
-       documenting the external interface of Kerberos.
-       * f_cbc.c, f_ecb.c, f_parity.c, f_pcbc.c, key_sched.c,
-       quad_cksum.c, string_to_key.c, weak_key.c:  Add INTERFACE to
-       definitions of functions visible in the programmer interface.
-       * string_to_key.c:  Remove some error printf's for environments
-       that don't have printf; put them under #ifdef DEBUG.
-
-Tue May 24 06:10:57 1994  John Gilmore  (gnu@cygnus.com)
-
-       * enc.c: Pull RCS crud.
-       * f_pcbc.c (des_pcbc_encryption):  Lint ivec.
-       * key_test.c:  Toss the ridiculous doubled IBMPC/BSDUNIX printf's,
-       use a simple portable printf.  Typo in msg.  Pull RCS crud.
-       * new_rnd_key.c, quad_cksum.c, string_to_key.c:  Lint.
-       * quad_cksum.c:  Pull RCS crud.
-
-Sat May 21 03:37:01 1994  John Gilmore  (gnu@cygnus.com)
-
-       Microsoft Windows port.
-
-       * Makefile.in (c-libdes.${LIBEXT)):  Typo; and fix .o to .obj.
-       * des_internal.h:  Remove pre-Fergusen stuff, leaving one #define.
-       * f_tables.h (FF_UINT32):  Add this, which makes a KRB_UINT32 out
-       of a constant that might otherwise only be int or less.
-       * f_cbc.c, f_cksum.c, f_pcbc.c:  Use it.  Line up code neatly.
-       * key_sched.c:  Lint, pull RCS crud.
-       * ren.msg:  Insert column of entries for MIT PC release.
-
-Thu May 19 22:18:24 1994  John Gilmore  (gnu@cygnus.com)
-
-       More MS-Windows and Mac support.
-
-       * cbc_noop.c, epc_encrypt.c:  Delete two more unused remnants.
-       * ren.msg, Makefile.in:  Remove references to remnants.
-
-       * Makefile.in (OTHERSRCS, OTHEROBJS):  Rename to FERG_* for clarity.
-       (SERVER_DES_{SRCS,OBJS}):  Split out routines used only on servers.
-       (####):  Move host-configuration insertion point so that the
-       per-host Makefile fragments can override the above.
-       (LIBEXT):  Use it everywhere rather than ".a".
-       (libdes.$(LIBEXT)):  Avoid making a .bak file.  Add and 
-       use $(ARCHIVEARGS) to allow making the incredible MSC LIB
-       command work.
-       (c-libdes.$(LIBEXT)):  Add rule to build control file for MSC LIB.
-       This rule must run on Unix (FIXME) since it uses sed and tr.  I
-       didn't know the equivalent DOS commands...
-       
-       * f_tables.h (DES_IP_RIGHT_BITS, DES_FP_RIGHT_BITS): Insert a cast
-       to unsigned, to circumvent a bug in the Macintosh MPW 3.2 C
-       compiler which loses the unsignedness and then does an arithmetic
-       shift rather than a logical shift.
-       (DEB):  Add debug macro for very nested macro defns.
-       (DES_DO_ENCRYPT):  Insert DEB calls to make it possible to
-       debug when DES fails.
-
-Fri May 13 01:59:09 1994  John Gilmore  (gnu@cygnus.com)
-
-       * Makefile.in:  Change {} to () for Microsoft NMAKE.
-       * Makefile:  Remove remnant of old config scheme.
-       * ren.msg:  Specify short and long names for DOS file systems.
-       * key_test.c, quad_cksum.c, testit.c, verify.c:  Pull unused
-       errmsg, errno.
-
-Sun May  8 17:21:50 1994  John Gilmore  (gnu@cygnus.com)
-
-       * read_password.c:  Remove `sigtype', use typedef from osconf.h.
-
-Sat May  7 17:32:43 1994  John Gilmore  (gnu@tweedledumb.cygnus.com)
-
-       * Makefile.in:  Don't build verify, key_test, and testit every
-       time we build the library.
-
-       * Makefile.in:  Update CODE for the removal.
-
-       * cbc_encrypt.c, cksum.c, dbg_prt.c, des.c, desglue.c, destest.c,
-       key_parity.c, make_e.c, make_fp.c, make_ip.c, make_key_perm.c,
-       make_key_sched.c, make_odd.c, make_p.c, make_p_table.c, make_s.c,
-       make_s_table.c, misc.c, noop.c, pcbc_encrypt.c, s_table.h.ibm,
-       tables.h:  Remove remnants of non-Fergusen DES code.  These are all
-       unused, have long, non-DOSlike names, and confuse people (me
-       anyway) into thining that they're live code.
-
-Fri May  6 02:04:48 1994  John Gilmore  (gnu@cygnus.com)
-
-       * desglue.c (quad_cksum):  Put argument declarations in order.
-       * pcbc_encrypt.c (des_pcbc_encrypt):  Ditto.
-       * quad_cksum.c (des_quad_cksum):  Ditto.
-
-Tue Oct 26 12:21:05 1993  Ken Raeburn  (raeburn@rover.cygnus.com)
-
-       * f_tables.h: Define const if not already defined and not
-       __STDC__.
-
-Sun Oct 17 13:47:28 1993  Ken Raeburn  (raeburn@cambridge.cygnus.com)
-
-       * f_*.c, f_tables.h, quad_cksum.c, testit.c, verify.c: Use
-       KRB_INT32 instead of long for 4-byte type.
-
-       * f_tables.c: Include des.h.
-
-       * string_to_key.c (des_string_to_key): Mask values to 32 bits
-       before printing.
-
-       * testit.c (nflag): Set to 1; running 1000 identical iterations
-       was silly.
-
-       * verify.c (print8): New routine.
-       (main): Clean up output formatting.
-
-Thu Feb 11 13:05:12 1993  Ken Raeburn  (raeburn@cambridge.cygnus.com)
-
-       * testit.c (main): Fix usage message.
-
-       * Imakefile: Delete references to assembly code.
-       * key_sched.c: Ditto.  Get rid of useless BIT macro.
-
-Wed Feb 10 14:17:31 1993  Ken Raeburn  (raeburn@cambridge.cygnus.com)
-
-       * des.c (des_ecb_encrypt): Fix pointer type lossage, and NULL/0
-       confusion.  Discard VAX-specific stuff.  Add a couple of minor
-       optimizations, including some based on DES_SHIFT_SHIFT
-       conditional.
-
-       * key_sched.c (make_key_sched): Fix inconsistent fwd declaration.
-
-Fri Jun 19 13:37:35 1992  Mark Eichin  (eichin at tweedledumber.cygnus.com)
-
-       * Imakefile (library_ro_object): punt the read-only object linker
-       mangling as it interferes with debugging.
-
-Tue Nov  8 12:12:32 1988  William Sommerfeld  (wesommer at binkley)
-
-       * (util) Remove \ before { and } characters (causes RT 
-       compiler warning)
-
-       * (read_password) Print a newline after saying "try again".
-
-       * (read_password) Merge in changes by Jim Bloom to do a clearerr
-       after a read fails, and protect against an RTM attack by
-       changing gets to fgets.
-
-Fri Sep 16 16:26:55 1988  Bill Sommerfeld  (wesommer at ra)
-
-       * (read_password) fix dependancies for BSDUNIX.
-
-Mon Sep 12 14:55:23 1988  Bill Sommerfeld  (wesommer at ra)
-
-       * (*) debug->des_debug
-
-       * (*) debug_print() -> des_debug_print()
-
-       * (Makefile) add dbg_prt.o to list of files included in build.
-
-       * (des.c) remove debug_print; it's in dbg_prt.c
-
-        * (des_internal.h) contains definitions of AUTH_DES_ITER, 
-       s-box structures, which aren't part of the encryption interface.
-
-       * (*) #include "conf.h" -> #include "des_internal.h"
-
-       * (*) C_Block -> des_cblock
-
-       * (*) Key_schedule -> des_key_schedule
-
-       * (noop.c) remove #includes for unused include files.
-
-       * (des.c, random_key.c, string_to_key.c) add #include of "des_conf.h"
-
-Fri Sep  9 15:46:13 1988  Bill Sommerfeld  (wesommer at ra)
-
-       * (*) string_to_key() -> des_string_to_key()
-
-       * (*) read_pw_string() -> des_read_pw_string()
-
-       * (*) random_key() -> des_random_key()
-
-       * (*) pcbc_encrypt() -> des_pcbc_encrypt()
-
-       * (*) key_sched() -> des_key_sched()
-
-       * (*) cbc_encrypt() -> des_cbc_encrypt()
-
-       * (*) cbc_cksum() -> des_cbc_cksum()
-
-       * (quad_cksum.c) make {four,two}_bytes_vax_to_nets be static to
-       avoid namespace pollution.
-
-       * (*.c) Rename C_Block_print() to des_cblock_print(). 
-
-       * (make_key_perm.c) Make "key_perm" be static to avoid namespace
-       pollution. 
-
-       * (quad_cksum.c) Make "short_conv" and "long_conv" local
-       variables, to avoid namespace pollution.
diff --git a/src/mac/libraries/DES/doc/READ_ME b/src/mac/libraries/DES/doc/READ_ME
deleted file mode 100644 (file)
index 0228da4..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
-This directory contains the sources for the DES encryption library and
-test programs.  
-
-Two precautions-- 
-
-1)  under US law, DES software and hardware may not be
-       exported without license from the US Dept of Commerce.
-
-2)     The only way to get a significant speedup of the algorithm is to
-       use considerably more space, traded against time. Dont play
-       with the code -- there is a high probability you will either
-       make it slower, or wrong, or both.  This implementation was
-       optimized for the UVAX 2.  Other architectures could benefit from
-       some "asm" tweaking.
-
-3)     If you do play with the code, make sure that the test program
-       "verify" still yields the expected answers.  Otherwise, your
-       ciphertext will not decrypt under a standard implementation, such
-       as on the VLSI chips that have been certified.
-
-       Project Athena          Steve Miller                            3/86 
diff --git a/src/mac/libraries/DES/doc/f_README b/src/mac/libraries/DES/doc/f_README
deleted file mode 100644 (file)
index 0d381e3..0000000
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- * Copyright (c) 1990 Dennis Ferguson.  All rights reserved.
- *
- * Commercial use is permitted only if products which are derived from
- * or include this software are made available for purchase and/or use
- * in Canada.  Otherwise, redistribution and use in source and binary
- * forms are permitted.
- */
-
-Sorry about the poor quality of installation instructions.  Included
-here are replacements for the DES portions of Eric Young's kerberos
-DES library replacement.  To use this you will need his distribution.
-Untar the latter and:
-
-(1) Copy all .c and .h files into the distribution directory.  This will
-    overwrite some files and add others.
-
-(2) Apply the patch included here to set_key.c in the distribution directory.
-
-(3) Edit the Imakefile (or the Makefile) to include the following files
-    on the SRCS= line:
-
-       des_tables.c ecb_buffer.c make_sched.c
-
-    Add the following files to the OBJS= line:
-
-       des_tables.o ecb_buffer.o make_sched.o
-
-    Add the following file to the CODE= line:
-
-       des_tables.h
-
-Recompile and you're done.
-
-The salient differences between this DES and Eric Young's are as follows:
-
-(1) There are no dependencies on byte ordering, the ability to do
-    unaligned loads and stores, or any other machine dependencies
-    that I know of.  There are no #ifdef's.  The code could probably
-    be made faster by adding such things, but not enough to be worth
-    it.
-
-(2) Combined S and P tables are used for the inner loop of the cipher
-    routine and the E expansion is computed on the fly, like Eric
-    Young's code, but the computation is reordered from the standard
-    to save instructions.
-
-(3) The initial and final permutations are table driven, and take
-    about the same amount of work as a single round of the inner
-    loop (i.e. only about 12% of the work done for an ecb encryption
-    is spent in the IP and FP code).
-
-(4) Since NTP (for which this DES was originally implemented) uses
-    lots of keys to encrypt small things, the key permutation code
-    has been well worked over and is quite speedy (the amount of
-    work required to permute a key is on the order of that required
-    to do a single ECB encryption, more or less).
-
-(5) Since the code required to do an ECB encryption using the tables
-    is actually fairly compact, even with lots of inlining, it was
-    implemented as a macro and is expanded in situ where needed.
-
-On the one machine I ran a comparison on this code ran 80% faster than
-Eric's, compiled into a slightly smaller space, and did pass destest.
-I suspect this stuff is also faster, and not a lot larger, than the
-library MIT doesn't export with kerberos.  You mileage may vary.
-
-The silly copyright was a (probably ineffective) afterthought.  If it
-really inconveniences you give me a call.
diff --git a/src/mac/libraries/DES/doc/ren.msg b/src/mac/libraries/DES/doc/ren.msg
deleted file mode 100644 (file)
index 3ee5d0a..0000000
+++ /dev/null
@@ -1,32 +0,0 @@
-  MIT K4 patch10       MIT K4 PC       PROPOSED NAME   (trunc to 8.3)  old Cyg
-$1     $2              $3              $4              $5              $6
-
-@ -                    -               ChangeLog       changelo
-@ -                    debug.c         debug_decl.c    debug_de.c
-@ -                    des_intn.h      des_internal.h  des_inte.h
-@ -                    -               doc             doc
-@ -                    enc.c           enc.c           enc.c
-@ -                    -               f_README        f_readme
-@ -                    -               f_cbc.c         f_cbc.c
-@ -                    -               f_cksum.c       f_cksum.c
-@ -                    -               f_ecb.c         f_ecb.c
-@ -                    -               f_parity.c      f_parity.c
-@ -                    -               f_pcbc.c        f_pcbc.c
-@ -                    -               f_sched.c       f_sched.c
-@ -                    -               f_tables.c      f_tables.c
-@ -                    -               f_tables.h      f_tables.h
-@ -                    keysched.c      key_sched.c     key_sche.c
-@ -                    key_test.c      key_test.c      key_test.c
-@ -                    -               Makefile.in     makefile.in
-@ -                    newrndky.c      new_rnd_key.c   new_rnd_.c
-@ -                    qd_cksum.c      quad_cksum.c    quad_cks.c
-@ -                    rand_key.c      random_key.c    random_k.c
-@ -                    rdpasswd.c      read_password.c read_pas.c
-@ -                    -               READ_ME         read_me
-@ -                    -               ren.msg         ren.msg
-@ -                    strtokey.c      string_to_key.c string_t.c
-@ -                    testit.c        testit.c        testit.c
-@ -                    -               unix_time.c     unix_tim.c
-@ -                    util.c          util.c          util.c
-@ -                    verify.c        verify.c        verify.c
-@ -                    weak_key.c      weak_key.c      weak_key.c
diff --git a/src/mac/libraries/DES/include/des.h b/src/mac/libraries/DES/include/des.h
deleted file mode 100644 (file)
index 8fa12eb..0000000
+++ /dev/null
@@ -1,158 +0,0 @@
-/*
- * des.h
- *
- * Copyright 1987, 1988 by the Massachusetts Institute of Technology.
- *
- * For copying and distribution information, please see the file
- * <mit-copyright.h> (Except for those files which contain other copyright information).
- *
- * Include file for the Data Encryption Standard library.
- */
-
-/* only do the whole thing once         */
-#ifndef DES_DEFS
-#define DES_DEFS
-
-#include "mit-copyright.h"
-#include <stdio.h>
-
-#ifndef DES_INT32
-#define DES_INT32 SInt32
-#endif
-#ifndef DES_UINT32
-#define DES_UINT32 UInt32
-#endif
-
-/* There are some declarations in the system-specific header files which
-   can't be done until DES_INT32 is defined.  So they are in a macro,
-   which we expand here if defined.  */
-
-#ifdef DECL_THAT_NEEDS_DES_INT32
-DECL_THAT_NEEDS_DES_INT32
-#endif
-
-typedef unsigned char des_cblock[8];   /* crypto-block size */
-/* Key schedule */
-typedef struct des_ks_struct { union { DES_INT32 pad; des_cblock _;} __; } des_key_schedule[16];
-
-#define DES_KEY_SZ     (sizeof(des_cblock))
-#define DES_ENCRYPT    1
-#define DES_DECRYPT    0
-
-#ifndef NCOMPAT
-#define C_Block des_cblock
-#define Key_schedule des_key_schedule
-#define ENCRYPT DES_ENCRYPT
-#define DECRYPT DES_DECRYPT
-#define KEY_SZ DES_KEY_SZ
-#define string_to_key des_string_to_key
-#define read_pw_string des_read_pw_string
-#define random_key des_random_key
-#define pcbc_encrypt des_pcbc_encrypt
-#define key_sched des_key_sched
-#define cbc_encrypt des_cbc_encrypt
-#define cbc_cksum des_cbc_cksum
-#define C_Block_print des_cblock_print
-#define quad_cksum des_quad_cksum
-typedef struct des_ks_struct bit_64;
-#endif
-
-#define des_cblock_print(x) des_cblock_print_file(x, stdout)
-
-/* Function declarations */
-
-/*     This is CFM magic that has to be done in order for the library to work under CFM-68K */
-#if defined(__CFM68K__) && !defined(__USING_STATIC_LIBS__)
-#      pragma import on
-#endif
-
-#if !GENERATINGCFM
-#   pragma d0_pointers on
-#endif
-
-int des_cbc_encrypt(des_cblock *in, 
-                    des_cblock *out, 
-                    long length, 
-                    des_key_schedule schedule, 
-                    des_cblock ivec, 
-                    int encrypt);
-
-void des_3cbc_encrypt(des_cblock *in,
-                      des_cblock *out,
-                      long length,
-                      des_key_schedule ks1, 
-                      des_key_schedule ks2, 
-                      des_key_schedule ks3, 
-                      des_cblock ivec, 
-                      int encrypt);
-                    
-unsigned long des_cbc_cksum(des_cblock *in, 
-                            des_cblock *out, 
-                            long length, 
-                            des_key_schedule schedule, 
-                            des_cblock *ivec);
-
-int des_ecb_encrypt(des_cblock *in, 
-                    des_cblock *out, 
-                    des_key_schedule schedule, 
-                    int encrypt);
-
-void des_3ecb_encrypt(des_cblock *in, 
-                      des_cblock *out, 
-                      des_key_schedule ks1, 
-                      des_key_schedule ks2, 
-                      des_key_schedule ks3, 
-                      int encrypt);
-                      
-void des_fixup_key_parity(register des_cblock key);
-int des_check_key_parity(register des_cblock key);
-
-int des_pcbc_encrypt(des_cblock *in, 
-                     des_cblock *out, 
-                     long length, 
-                     des_key_schedule schedule, 
-                     des_cblock ivec, 
-                     int encrypt);
-
-int make_key_sched(des_cblock *key, des_key_schedule schedule);
-
-int des_key_sched(des_cblock k, des_key_schedule schedule);
-
-int des_new_random_key(des_cblock key);
-void des_init_random_number_generator(des_cblock key);
-void des_set_random_generator_seed(des_cblock key);
-void des_set_sequence_number(des_cblock new_sequence_number);
-void des_generate_random_block(des_cblock block);
-
-unsigned long des_quad_cksum(unsigned char *in,
-                             unsigned long *out,
-                             long length,
-                             int out_count,
-                             des_cblock *c_seed);
-
-int des_random_key(des_cblock *key);
-
-int des_read_password(des_cblock *k, char *prompt, int verify);
-int des_read_pw_string(char *s, int max, char *prompt, int verify);
-
-int des_string_to_key(char *str, des_cblock key);
-
-void des_cblock_print_file(des_cblock *x, FILE *fp);
-
-int des_is_weak_key(des_cblock key);
-
-char *des_crypt(const char *buf, const char *salt);
-char *des_fcrypt(const char *buf, const char *salt, char *ret);
-
-int des_set_key(des_cblock *key, des_key_schedule schedule);
-
-#if !GENERATINGCFM
-#   pragma d0_pointers reset
-#endif
-
-/*     CFM magic again */      
-#if defined(__CFM68K__) && !defined(__USING_STATIC_LIBS__)
-#      pragma import reset
-#endif
-
-#endif /* DES_DEFS */
diff --git a/src/mac/libraries/DES/include/deslib.CFMGlue.c b/src/mac/libraries/DES/include/deslib.CFMGlue.c
deleted file mode 100644 (file)
index cfc4905..0000000
+++ /dev/null
@@ -1,842 +0,0 @@
-#include <CodeFragments.h>
-#include <Gestalt.h>
-#include <Errors.h>
-
-#include "des.h"
-#include "deslib.CFMGlue.h"
-
-/* These functions must obey CFM calling conventions. Functions which return
-   pointers must return them in D0, not A0 like ThinkC static 68k does.  This way
-   we can call CFM functions by pointer from here (if they are called by pointer
-   then the compiler can't tell ahead of time to do D0->A0 translation because it
-   doesn't know what calling convention the functions use). 
-   
-   Note that if it is necessary (if you don't use MPWC calling conventions) 
-   the D0->A0 translation will be done by the compiler in the places where 
-   the application calls these glue routines. */
-#pragma d0_pointers on
-
-/* Hardcode library fragment name here */
-#define kLibraryName "\pMIT_Â¥deslib"
-
-/* Private function prototypes */
-
-static OSErr Find_Symbol(
-       Ptr* pSymAddr,
-       Str255 pSymName,
-       ProcInfoType pProcInfo);
-
-static pascal Boolean HaveCFM(void);
-
-static pascal OSErr GetSystemArchitecture(OSType *archType);
-
-
-/* This code is directly from Technote 1077 */
-/* changed Library name to be hardcoded at the top of the file
-   instead in the middle of the code */
-
-/* Private functions */
-
-static pascal OSErr GetSystemArchitecture(OSType *archType)
-{
-       static long sSysArchitecture = 0; // static so we only Gestalt once.
-       OSErr tOSErr = noErr;
-
-       *archType = kAnyCFragArch;   // assume wild architecture
-
-       // If we don't know the system architecture yet...
-       if (sSysArchitecture == 0)
-       // ...Ask Gestalt what kind of machine we are running on.
-       tOSErr = Gestalt(gestaltSysArchitecture, &sSysArchitecture);
-
-       if (tOSErr == noErr) // if no errors
-       {
-               if (sSysArchitecture == gestalt68k)   // 68k?
-                       *archType = kMotorola68KCFragArch;   
-               else if (sSysArchitecture == gestaltPowerPC) // PPC?
-                       *archType = kPowerPCCFragArch;       
-               else
-                       tOSErr = gestaltUnknownErr;  // who knows what might be next?
-       }
-       return tOSErr;
-}
-
-static pascal Boolean HaveCFM(void)
-{
-       long response;
-       return ( (Gestalt (gestaltCFMAttr, &response) == noErr) &&
-                               (((response >> gestaltCFMPresent) & 1) != 0));
-}
-
-static OSErr Find_Symbol(
-       Ptr* pSymAddr,
-       Str255 pSymName,
-       ProcInfoType pProcInfo)
-{
-       static CFragConnectionID sCID = 0;
-       static OSType sArchType = kAnyCFragArch;
-       static OSErr sOSErr = noErr;
-
-       Str255 errMessage;
-       Ptr mainAddr;
-       CFragSymbolClass symClass;
-       ISAType tISAType;
-
-       if (sArchType == kAnyCFragArch)  // if architecture is undefined...
-       {
-               sCID = 0;     // ...force (re)connect to library
-               sOSErr = GetSystemArchitecture(&sArchType); // determine architecture
-               if (sOSErr != noErr)
-               return sOSErr; // OOPS!
-       }
-       
-       if (!HaveCFM()) {
-               // If we don't have CFM68K, return a reasonable-looking error.
-               sOSErr = cfragLibConnErr;
-               return sOSErr;
-       }
-
-       if (sArchType == kMotorola68KCFragArch) // ...for CFM68K
-               tISAType = kM68kISA | kCFM68kRTA;
-       else if (sArchType == kPowerPCCFragArch)  // ...for PPC CFM
-               tISAType = kPowerPCISA | kPowerPCRTA;
-       else
-               sOSErr = gestaltUnknownErr; // who knows what might be next?
-
-       if (sCID == 0) // If we haven't connected to the library yet...
-       {
-               // NOTE: The library name is hard coded here.
-               // I try to isolate the glue code, one file per library.
-               // I have had developers pass in the Library name to allow
-               // plug-in type support. Additional code has to be added to
-               // each entry points glue routine to support multiple or
-               // switching connection IDs.
-               sOSErr = GetSharedLibrary(kLibraryName, sArchType, kLoadCFrag,
-               &sCID, &mainAddr, errMessage);
-               if (sOSErr != noErr)
-               return sOSErr; // OOPS!
-       }
-
-       // If we haven't looked up this symbol yet...
-       if ((Ptr) *pSymAddr == (Ptr) kUnresolvedCFragSymbolAddress)    
-       {
-               // ...look it up now
-               sOSErr = FindSymbol(sCID,pSymName,pSymAddr,&symClass);
-               if (sOSErr != noErr) // in case of error...
-               // ...clear the procedure pointer
-               *(Ptr*) &pSymAddr = (Ptr) kUnresolvedCFragSymbolAddress;
-#      if !GENERATINGCFM // if this is classic 68k code...
-                       *pSymAddr = (Ptr)NewRoutineDescriptorTrap((ProcPtr) *pSymAddr,
-                       pProcInfo, tISAType);  // ...create a routine descriptor...
-#      endif
-       }
-       return sOSErr;
-}
-
-
-/* CFM Glue Code for exported functions! */
-
-/**** des_random_key ****/
-/* int des_random_key(des_cblock *key); */
-
-enum {
-  des_random_key_ProcInfo = kThinkCStackBased
-  | RESULT_SIZE(SIZE_CODE(sizeof(int)))
-  | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(des_cblock *)))
-};
-
-typedef int (*des_random_key_ProcPtrType)(des_cblock *);
-int des_random_key (
-    des_cblock * key)
-{
-  static des_random_key_ProcPtrType des_random_key_ProcPtr = kUnresolvedCFragSymbolAddress;
-
-  // if this symbol has not been setup yet...
-  if((Ptr) des_random_key_ProcPtr == (Ptr) kUnresolvedCFragSymbolAddress)
-    Find_Symbol((Ptr *) &des_random_key_ProcPtr, "\pdes_random_key", des_random_key_ProcInfo);
-  if((Ptr) des_random_key_ProcPtr != (Ptr) kUnresolvedCFragSymbolAddress)
-    return des_random_key_ProcPtr(key);
-}
-
-
-/**** des_cbc_cksum ****/
-/* unsigned long des_cbc_cksum(des_cblock *in, des_cblock *out, long length, des_key_schedule schedule, des_cblock *ivec); */
-
-enum {
-  des_cbc_cksum_ProcInfo = kThinkCStackBased
-  | RESULT_SIZE(SIZE_CODE(sizeof(unsigned long)))
-  | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(des_cblock *)))
-  | STACK_ROUTINE_PARAMETER(2, SIZE_CODE(sizeof(des_cblock *)))
-  | STACK_ROUTINE_PARAMETER(3, SIZE_CODE(sizeof(long)))
-  | STACK_ROUTINE_PARAMETER(4, SIZE_CODE(sizeof(struct des_ks_struct *)))
-  | STACK_ROUTINE_PARAMETER(5, SIZE_CODE(sizeof(des_cblock *)))
-};
-
-typedef unsigned long (*des_cbc_cksum_ProcPtrType)(des_cblock *, des_cblock *, long, des_key_schedule, des_cblock *);
-unsigned long des_cbc_cksum (
-              des_cblock * in,
-              des_cblock * out,
-              long length,
-              des_key_schedule schedule,
-              des_cblock * ivec)
-{
-  static des_cbc_cksum_ProcPtrType des_cbc_cksum_ProcPtr = kUnresolvedCFragSymbolAddress;
-
-  // if this symbol has not been setup yet...
-  if((Ptr) des_cbc_cksum_ProcPtr == (Ptr) kUnresolvedCFragSymbolAddress)
-    Find_Symbol((Ptr *) &des_cbc_cksum_ProcPtr, "\pdes_cbc_cksum", des_cbc_cksum_ProcInfo);
-  if((Ptr) des_cbc_cksum_ProcPtr != (Ptr) kUnresolvedCFragSymbolAddress)
-    return des_cbc_cksum_ProcPtr(in, out, length, schedule, ivec);
-}
-
-
-/**** des_is_weak_key ****/
-/* int des_is_weak_key(des_cblock key); */
-
-enum {
-  des_is_weak_key_ProcInfo = kThinkCStackBased
-  | RESULT_SIZE(SIZE_CODE(sizeof(int)))
-  | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(unsigned char *)))
-};
-
-typedef int (*des_is_weak_key_ProcPtrType)(des_cblock);
-int des_is_weak_key (
-    des_cblock key)
-{
-  static des_is_weak_key_ProcPtrType des_is_weak_key_ProcPtr = kUnresolvedCFragSymbolAddress;
-
-  // if this symbol has not been setup yet...
-  if((Ptr) des_is_weak_key_ProcPtr == (Ptr) kUnresolvedCFragSymbolAddress)
-    Find_Symbol((Ptr *) &des_is_weak_key_ProcPtr, "\pdes_is_weak_key", des_is_weak_key_ProcInfo);
-  if((Ptr) des_is_weak_key_ProcPtr != (Ptr) kUnresolvedCFragSymbolAddress)
-    return des_is_weak_key_ProcPtr(key);
-}
-
-
-/**** des_set_sequence_number ****/
-/* void des_set_sequence_number(des_cblock new_sequence_number); */
-
-enum {
-  des_set_sequence_number_ProcInfo = kThinkCStackBased
-  | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(unsigned char *)))
-};
-
-typedef void (*des_set_sequence_number_ProcPtrType)(des_cblock);
-void des_set_sequence_number (
-     des_cblock new_sequence_number)
-{
-  static des_set_sequence_number_ProcPtrType des_set_sequence_number_ProcPtr = kUnresolvedCFragSymbolAddress;
-
-  // if this symbol has not been setup yet...
-  if((Ptr) des_set_sequence_number_ProcPtr == (Ptr) kUnresolvedCFragSymbolAddress)
-    Find_Symbol((Ptr *) &des_set_sequence_number_ProcPtr, "\pdes_set_sequence_number", des_set_sequence_number_ProcInfo);
-  if((Ptr) des_set_sequence_number_ProcPtr != (Ptr) kUnresolvedCFragSymbolAddress)
-    des_set_sequence_number_ProcPtr(new_sequence_number);
-}
-
-
-/**** des_fixup_key_parity ****/
-/* void des_fixup_key_parity(register des_cblock key); */
-
-enum {
-  des_fixup_key_parity_ProcInfo = kThinkCStackBased
-  | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(unsigned char *)))
-};
-
-typedef void (*des_fixup_key_parity_ProcPtrType)(register des_cblock);
-void des_fixup_key_parity (
-     register des_cblock key)
-{
-  static des_fixup_key_parity_ProcPtrType des_fixup_key_parity_ProcPtr = kUnresolvedCFragSymbolAddress;
-
-  // if this symbol has not been setup yet...
-  if((Ptr) des_fixup_key_parity_ProcPtr == (Ptr) kUnresolvedCFragSymbolAddress)
-    Find_Symbol((Ptr *) &des_fixup_key_parity_ProcPtr, "\pdes_fixup_key_parity", des_fixup_key_parity_ProcInfo);
-  if((Ptr) des_fixup_key_parity_ProcPtr != (Ptr) kUnresolvedCFragSymbolAddress)
-    des_fixup_key_parity_ProcPtr(key);
-}
-
-
-/**** des_cbc_encrypt ****/
-/* int des_cbc_encrypt(des_cblock *in, des_cblock *out, long length, des_key_schedule schedule, des_cblock ivec, int encrypt); */
-
-enum {
-  des_cbc_encrypt_ProcInfo = kThinkCStackBased
-  | RESULT_SIZE(SIZE_CODE(sizeof(int)))
-  | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(des_cblock *)))
-  | STACK_ROUTINE_PARAMETER(2, SIZE_CODE(sizeof(des_cblock *)))
-  | STACK_ROUTINE_PARAMETER(3, SIZE_CODE(sizeof(long)))
-  | STACK_ROUTINE_PARAMETER(4, SIZE_CODE(sizeof(struct des_ks_struct *)))
-  | STACK_ROUTINE_PARAMETER(5, SIZE_CODE(sizeof(unsigned char *)))
-  | STACK_ROUTINE_PARAMETER(6, SIZE_CODE(sizeof(int)))
-};
-
-typedef int (*des_cbc_encrypt_ProcPtrType)(des_cblock *, des_cblock *, long, des_key_schedule, des_cblock, int);
-int des_cbc_encrypt (
-    des_cblock * in,
-    des_cblock * out,
-    long length,
-    des_key_schedule schedule,
-    des_cblock ivec,
-    int encrypt)
-{
-  static des_cbc_encrypt_ProcPtrType des_cbc_encrypt_ProcPtr = kUnresolvedCFragSymbolAddress;
-
-  // if this symbol has not been setup yet...
-  if((Ptr) des_cbc_encrypt_ProcPtr == (Ptr) kUnresolvedCFragSymbolAddress)
-    Find_Symbol((Ptr *) &des_cbc_encrypt_ProcPtr, "\pdes_cbc_encrypt", des_cbc_encrypt_ProcInfo);
-  if((Ptr) des_cbc_encrypt_ProcPtr != (Ptr) kUnresolvedCFragSymbolAddress)
-    return des_cbc_encrypt_ProcPtr(in, out, length, schedule, ivec, encrypt);
-}
-
-
-/**** des_quad_cksum ****/
-/* unsigned long des_quad_cksum(unsigned char *in, unsigned long *out, long length, int out_count, des_cblock *c_seed); */
-
-enum {
-  des_quad_cksum_ProcInfo = kThinkCStackBased
-  | RESULT_SIZE(SIZE_CODE(sizeof(unsigned long)))
-  | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(unsigned char *)))
-  | STACK_ROUTINE_PARAMETER(2, SIZE_CODE(sizeof(unsigned long *)))
-  | STACK_ROUTINE_PARAMETER(3, SIZE_CODE(sizeof(long)))
-  | STACK_ROUTINE_PARAMETER(4, SIZE_CODE(sizeof(int)))
-  | STACK_ROUTINE_PARAMETER(5, SIZE_CODE(sizeof(des_cblock *)))
-};
-
-typedef unsigned long (*des_quad_cksum_ProcPtrType)(unsigned char *, unsigned long *, long, int, des_cblock *);
-unsigned long des_quad_cksum (
-              unsigned char * in,
-              unsigned long * out,
-              long length,
-              int out_count,
-              des_cblock * c_seed)
-{
-  static des_quad_cksum_ProcPtrType des_quad_cksum_ProcPtr = kUnresolvedCFragSymbolAddress;
-
-  // if this symbol has not been setup yet...
-  if((Ptr) des_quad_cksum_ProcPtr == (Ptr) kUnresolvedCFragSymbolAddress)
-    Find_Symbol((Ptr *) &des_quad_cksum_ProcPtr, "\pdes_quad_cksum", des_quad_cksum_ProcInfo);
-  if((Ptr) des_quad_cksum_ProcPtr != (Ptr) kUnresolvedCFragSymbolAddress)
-    return des_quad_cksum_ProcPtr(in, out, length, out_count, c_seed);
-}
-
-
-/**** des_read_password ****/
-/* int des_read_password(des_cblock *k, char *prompt, int verify); */
-
-enum {
-  des_read_password_ProcInfo = kThinkCStackBased
-  | RESULT_SIZE(SIZE_CODE(sizeof(int)))
-  | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(des_cblock *)))
-  | STACK_ROUTINE_PARAMETER(2, SIZE_CODE(sizeof(char *)))
-  | STACK_ROUTINE_PARAMETER(3, SIZE_CODE(sizeof(int)))
-};
-
-typedef int (*des_read_password_ProcPtrType)(des_cblock *, char *, int);
-int des_read_password (
-    des_cblock * k,
-    char * prompt,
-    int verify)
-{
-  static des_read_password_ProcPtrType des_read_password_ProcPtr = kUnresolvedCFragSymbolAddress;
-
-  // if this symbol has not been setup yet...
-  if((Ptr) des_read_password_ProcPtr == (Ptr) kUnresolvedCFragSymbolAddress)
-    Find_Symbol((Ptr *) &des_read_password_ProcPtr, "\pdes_read_password", des_read_password_ProcInfo);
-  if((Ptr) des_read_password_ProcPtr != (Ptr) kUnresolvedCFragSymbolAddress)
-    return des_read_password_ProcPtr(k, prompt, verify);
-}
-
-
-/**** des_ecb_encrypt ****/
-/* int des_ecb_encrypt(des_cblock *in, des_cblock *out, des_key_schedule schedule, int encrypt); */
-
-enum {
-  des_ecb_encrypt_ProcInfo = kThinkCStackBased
-  | RESULT_SIZE(SIZE_CODE(sizeof(int)))
-  | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(des_cblock *)))
-  | STACK_ROUTINE_PARAMETER(2, SIZE_CODE(sizeof(des_cblock *)))
-  | STACK_ROUTINE_PARAMETER(3, SIZE_CODE(sizeof(struct des_ks_struct *)))
-  | STACK_ROUTINE_PARAMETER(4, SIZE_CODE(sizeof(int)))
-};
-
-typedef int (*des_ecb_encrypt_ProcPtrType)(des_cblock *, des_cblock *, des_key_schedule, int);
-int des_ecb_encrypt (
-    des_cblock * in,
-    des_cblock * out,
-    des_key_schedule schedule,
-    int encrypt)
-{
-  static des_ecb_encrypt_ProcPtrType des_ecb_encrypt_ProcPtr = kUnresolvedCFragSymbolAddress;
-
-  // if this symbol has not been setup yet...
-  if((Ptr) des_ecb_encrypt_ProcPtr == (Ptr) kUnresolvedCFragSymbolAddress)
-    Find_Symbol((Ptr *) &des_ecb_encrypt_ProcPtr, "\pdes_ecb_encrypt", des_ecb_encrypt_ProcInfo);
-  if((Ptr) des_ecb_encrypt_ProcPtr != (Ptr) kUnresolvedCFragSymbolAddress)
-    return des_ecb_encrypt_ProcPtr(in, out, schedule, encrypt);
-}
-
-
-/**** des_3ecb_encrypt ****/
-/* void des_3ecb_encrypt(des_cblock *in, des_cblock *out, des_key_schedule ks1, des_key_schedule ks2, des_key_schedule ks3, int encrypt); */
-
-enum {
-  des_3ecb_encrypt_ProcInfo = kThinkCStackBased
-  | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(des_cblock *)))
-  | STACK_ROUTINE_PARAMETER(2, SIZE_CODE(sizeof(des_cblock *)))
-  | STACK_ROUTINE_PARAMETER(3, SIZE_CODE(sizeof(des_key_schedule)))
-  | STACK_ROUTINE_PARAMETER(4, SIZE_CODE(sizeof(des_key_schedule)))
-  | STACK_ROUTINE_PARAMETER(5, SIZE_CODE(sizeof(des_key_schedule)))
-  | STACK_ROUTINE_PARAMETER(6, SIZE_CODE(sizeof(int)))
-};
-
-typedef void (*des_3ecb_encrypt_ProcPtrType)(des_cblock *, des_cblock *, des_key_schedule, des_key_schedule, des_key_schedule, int);
-void des_3ecb_encrypt (
-     des_cblock * in,
-     des_cblock * out,
-     des_key_schedule ks1,
-     des_key_schedule ks2,
-     des_key_schedule ks3,
-     int encrypt)
-{
-  static des_3ecb_encrypt_ProcPtrType des_3ecb_encrypt_ProcPtr = kUnresolvedCFragSymbolAddress;
-
-  // if this symbol has not been setup yet...
-  if((Ptr) des_3ecb_encrypt_ProcPtr == (Ptr) kUnresolvedCFragSymbolAddress)
-    Find_Symbol((Ptr *) &des_3ecb_encrypt_ProcPtr, "\pdes_3ecb_encrypt", des_3ecb_encrypt_ProcInfo);
-  if((Ptr) des_3ecb_encrypt_ProcPtr != (Ptr) kUnresolvedCFragSymbolAddress)
-    des_3ecb_encrypt_ProcPtr(in, out, ks1, ks2, ks3, encrypt);
-}
-
-
-/**** des_key_sched ****/
-/* int des_key_sched(des_cblock k, des_key_schedule schedule); */
-
-enum {
-  des_key_sched_ProcInfo = kThinkCStackBased
-  | RESULT_SIZE(SIZE_CODE(sizeof(int)))
-  | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(unsigned char *)))
-  | STACK_ROUTINE_PARAMETER(2, SIZE_CODE(sizeof(struct des_ks_struct *)))
-};
-
-typedef int (*des_key_sched_ProcPtrType)(des_cblock, des_key_schedule);
-int des_key_sched (
-    des_cblock k,
-    des_key_schedule schedule)
-{
-  static des_key_sched_ProcPtrType des_key_sched_ProcPtr = kUnresolvedCFragSymbolAddress;
-
-  // if this symbol has not been setup yet...
-  if((Ptr) des_key_sched_ProcPtr == (Ptr) kUnresolvedCFragSymbolAddress)
-    Find_Symbol((Ptr *) &des_key_sched_ProcPtr, "\pdes_key_sched", des_key_sched_ProcInfo);
-  if((Ptr) des_key_sched_ProcPtr != (Ptr) kUnresolvedCFragSymbolAddress)
-    return des_key_sched_ProcPtr(k, schedule);
-}
-
-
-/**** des_3pcbc_encrypt ****/
-/* void des_3pcbc_encrypt(des_cblock *input, des_cblock *output, long length, des_key_schedule schedule1, des_cblock ivec1, des_key_schedule schedule2, des_cblock ivec2, des_key_schedule schedule3, des_cblock ivec3, int encrypt); */
-/*
-enum {
-  des_3pcbc_encrypt_ProcInfo = kThinkCStackBased
-  | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(des_cblock *)))
-  | STACK_ROUTINE_PARAMETER(2, SIZE_CODE(sizeof(des_cblock *)))
-  | STACK_ROUTINE_PARAMETER(3, SIZE_CODE(sizeof(long)))
-  | STACK_ROUTINE_PARAMETER(4, SIZE_CODE(sizeof(struct des_ks_struct *)))
-  | STACK_ROUTINE_PARAMETER(5, SIZE_CODE(sizeof(unsigned char *)))
-  | STACK_ROUTINE_PARAMETER(6, SIZE_CODE(sizeof(struct des_ks_struct *)))
-  | STACK_ROUTINE_PARAMETER(7, SIZE_CODE(sizeof(unsigned char *)))
-  | STACK_ROUTINE_PARAMETER(8, SIZE_CODE(sizeof(struct des_ks_struct *)))
-  | STACK_ROUTINE_PARAMETER(9, SIZE_CODE(sizeof(unsigned char *)))
-  | STACK_ROUTINE_PARAMETER(10, SIZE_CODE(sizeof(int)))
-};
-
-typedef void (*des_3pcbc_encrypt_ProcPtrType)(des_cblock *, des_cblock *, long, des_key_schedule, des_cblock, des_key_schedule, des_cblock, des_key_schedule, des_cblock, int);
-void des_3pcbc_encrypt (
-     des_cblock * input,
-     des_cblock * output,
-     long length,
-     des_key_schedule schedule1,
-     des_cblock ivec1,
-     des_key_schedule schedule2,
-     des_cblock ivec2,
-     des_key_schedule schedule3,
-     des_cblock ivec3,
-     int encrypt)
-{
-  static des_3pcbc_encrypt_ProcPtrType des_3pcbc_encrypt_ProcPtr = kUnresolvedCFragSymbolAddress;
-
-  // if this symbol has not been setup yet...
-  if((Ptr) des_3pcbc_encrypt_ProcPtr == (Ptr) kUnresolvedCFragSymbolAddress)
-    Find_Symbol((Ptr *) &des_3pcbc_encrypt_ProcPtr, "\pdes_3pcbc_encrypt", des_3pcbc_encrypt_ProcInfo);
-  if((Ptr) des_3pcbc_encrypt_ProcPtr != (Ptr) kUnresolvedCFragSymbolAddress)
-    des_3pcbc_encrypt_ProcPtr(input, output, length, schedule1, ivec1, schedule2, ivec2, schedule3, ivec3, encrypt);
-}
-*/
-
-/**** make_key_sched ****/
-/* int make_key_sched(des_cblock *key, des_key_schedule schedule); */
-
-enum {
-  make_key_sched_ProcInfo = kThinkCStackBased
-  | RESULT_SIZE(SIZE_CODE(sizeof(int)))
-  | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(des_cblock *)))
-  | STACK_ROUTINE_PARAMETER(2, SIZE_CODE(sizeof(struct des_ks_struct *)))
-};
-
-typedef int (*make_key_sched_ProcPtrType)(des_cblock *, des_key_schedule);
-int make_key_sched (
-    des_cblock * key,
-    des_key_schedule schedule)
-{
-  static make_key_sched_ProcPtrType make_key_sched_ProcPtr = kUnresolvedCFragSymbolAddress;
-
-  // if this symbol has not been setup yet...
-  if((Ptr) make_key_sched_ProcPtr == (Ptr) kUnresolvedCFragSymbolAddress)
-    Find_Symbol((Ptr *) &make_key_sched_ProcPtr, "\pmake_key_sched", make_key_sched_ProcInfo);
-  if((Ptr) make_key_sched_ProcPtr != (Ptr) kUnresolvedCFragSymbolAddress)
-    return make_key_sched_ProcPtr(key, schedule);
-}
-
-
-/**** des_crypt ****/
-/* char *des_crypt(const char *buf, const char *salt); */
-
-enum {
-  des_crypt_ProcInfo = kThinkCStackBased
-  | RESULT_SIZE(SIZE_CODE(sizeof(char *)))
-  | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(const char *)))
-  | STACK_ROUTINE_PARAMETER(2, SIZE_CODE(sizeof(const char *)))
-};
-
-typedef char * (*des_crypt_ProcPtrType)(const char *, const char *);
-char * des_crypt (
-       const char * buf,
-       const char * salt)
-{
-  static des_crypt_ProcPtrType des_crypt_ProcPtr = kUnresolvedCFragSymbolAddress;
-  
-  // if this symbol has not been setup yet...
-  if((Ptr) des_crypt_ProcPtr == (Ptr) kUnresolvedCFragSymbolAddress)
-    Find_Symbol((Ptr *) &des_crypt_ProcPtr, "\pdes_crypt", des_crypt_ProcInfo);
-  if((Ptr) des_crypt_ProcPtr != (Ptr) kUnresolvedCFragSymbolAddress)
-    return(des_crypt_ProcPtr(buf, salt));
-}
-
-
-/**** des_set_random_generator_seed ****/
-/* void des_set_random_generator_seed(des_cblock key); */
-
-enum {
-  des_set_random_generator_seed_ProcInfo = kThinkCStackBased
-  | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(unsigned char *)))
-};
-
-typedef void (*des_set_random_generator_seed_ProcPtrType)(des_cblock);
-void des_set_random_generator_seed (
-     des_cblock key)
-{
-  static des_set_random_generator_seed_ProcPtrType des_set_random_generator_seed_ProcPtr = kUnresolvedCFragSymbolAddress;
-
-  // if this symbol has not been setup yet...
-  if((Ptr) des_set_random_generator_seed_ProcPtr == (Ptr) kUnresolvedCFragSymbolAddress)
-    Find_Symbol((Ptr *) &des_set_random_generator_seed_ProcPtr, "\pdes_set_random_generator_seed", des_set_random_generator_seed_ProcInfo);
-  if((Ptr) des_set_random_generator_seed_ProcPtr != (Ptr) kUnresolvedCFragSymbolAddress)
-    des_set_random_generator_seed_ProcPtr(key);
-}
-
-
-/**** des_new_random_key ****/
-/* int des_new_random_key(des_cblock key); */
-
-enum {
-  des_new_random_key_ProcInfo = kThinkCStackBased
-  | RESULT_SIZE(SIZE_CODE(sizeof(int)))
-  | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(unsigned char *)))
-};
-
-typedef int (*des_new_random_key_ProcPtrType)(des_cblock);
-int des_new_random_key (
-    des_cblock key)
-{
-  static des_new_random_key_ProcPtrType des_new_random_key_ProcPtr = kUnresolvedCFragSymbolAddress;
-
-  // if this symbol has not been setup yet...
-  if((Ptr) des_new_random_key_ProcPtr == (Ptr) kUnresolvedCFragSymbolAddress)
-    Find_Symbol((Ptr *) &des_new_random_key_ProcPtr, "\pdes_new_random_key", des_new_random_key_ProcInfo);
-  if((Ptr) des_new_random_key_ProcPtr != (Ptr) kUnresolvedCFragSymbolAddress)
-    return des_new_random_key_ProcPtr(key);
-}
-
-
-/**** des_set_key ****/
-/* int des_set_key(des_cblock *key, des_key_schedule schedule); */
-
-enum {
-  des_set_key_ProcInfo = kThinkCStackBased
-  | RESULT_SIZE(SIZE_CODE(sizeof(int)))
-  | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(des_cblock *)))
-  | STACK_ROUTINE_PARAMETER(2, SIZE_CODE(sizeof(struct des_ks_struct *)))
-};
-
-typedef int (*des_set_key_ProcPtrType)(des_cblock *, des_key_schedule);
-int des_set_key (
-    des_cblock * key,
-    des_key_schedule schedule)
-{
-  static des_set_key_ProcPtrType des_set_key_ProcPtr = kUnresolvedCFragSymbolAddress;
-
-  // if this symbol has not been setup yet...
-  if((Ptr) des_set_key_ProcPtr == (Ptr) kUnresolvedCFragSymbolAddress)
-    Find_Symbol((Ptr *) &des_set_key_ProcPtr, "\pdes_set_key", des_set_key_ProcInfo);
-  if((Ptr) des_set_key_ProcPtr != (Ptr) kUnresolvedCFragSymbolAddress)
-    return des_set_key_ProcPtr(key, schedule);
-}
-
-
-/**** des_generate_random_block ****/
-/* void des_generate_random_block(des_cblock block); */
-
-enum {
-  des_generate_random_block_ProcInfo = kThinkCStackBased
-  | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(unsigned char *)))
-};
-
-typedef void (*des_generate_random_block_ProcPtrType)(des_cblock);
-void des_generate_random_block (
-     des_cblock block)
-{
-  static des_generate_random_block_ProcPtrType des_generate_random_block_ProcPtr = kUnresolvedCFragSymbolAddress;
-
-  // if this symbol has not been setup yet...
-  if((Ptr) des_generate_random_block_ProcPtr == (Ptr) kUnresolvedCFragSymbolAddress)
-    Find_Symbol((Ptr *) &des_generate_random_block_ProcPtr, "\pdes_generate_random_block", des_generate_random_block_ProcInfo);
-  if((Ptr) des_generate_random_block_ProcPtr != (Ptr) kUnresolvedCFragSymbolAddress)
-    des_generate_random_block_ProcPtr(block);
-}
-
-
-/**** des_fcrypt ****/
-/* char *des_fcrypt(const char *buf, const char *salt, char *ret); */
-
-enum {
-  des_fcrypt_ProcInfo = kThinkCStackBased
-  | RESULT_SIZE(SIZE_CODE(sizeof(char *)))
-  | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(const char *)))
-  | STACK_ROUTINE_PARAMETER(2, SIZE_CODE(sizeof(const char *)))
-  | STACK_ROUTINE_PARAMETER(3, SIZE_CODE(sizeof(char *)))
-};
-
-typedef char * (*des_fcrypt_ProcPtrType)(const char *, const char *, char *);
-char * des_fcrypt (
-       const char * buf,
-       const char * salt,
-       char * ret)
-{
-  static des_fcrypt_ProcPtrType des_fcrypt_ProcPtr = kUnresolvedCFragSymbolAddress;
-
-  // if this symbol has not been setup yet...
-  if((Ptr) des_fcrypt_ProcPtr == (Ptr) kUnresolvedCFragSymbolAddress)
-    Find_Symbol((Ptr *) &des_fcrypt_ProcPtr, "\pdes_fcrypt", des_fcrypt_ProcInfo);
-  if((Ptr) des_fcrypt_ProcPtr != (Ptr) kUnresolvedCFragSymbolAddress)
-    return des_fcrypt_ProcPtr(buf, salt, ret);
-}
-
-
-/**** des_read_pw_string ****/
-/* int des_read_pw_string(char *s, int max, char *prompt, int verify); */
-
-enum {
-  des_read_pw_string_ProcInfo = kThinkCStackBased
-  | RESULT_SIZE(SIZE_CODE(sizeof(int)))
-  | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(char *)))
-  | STACK_ROUTINE_PARAMETER(2, SIZE_CODE(sizeof(int)))
-  | STACK_ROUTINE_PARAMETER(3, SIZE_CODE(sizeof(char *)))
-  | STACK_ROUTINE_PARAMETER(4, SIZE_CODE(sizeof(int)))
-};
-
-typedef int (*des_read_pw_string_ProcPtrType)(char *, int, char *, int);
-int des_read_pw_string (
-    char * s,
-    int max,
-    char * prompt,
-    int verify)
-{
-  static des_read_pw_string_ProcPtrType des_read_pw_string_ProcPtr = kUnresolvedCFragSymbolAddress;
-
-  // if this symbol has not been setup yet...
-  if((Ptr) des_read_pw_string_ProcPtr == (Ptr) kUnresolvedCFragSymbolAddress)
-    Find_Symbol((Ptr *) &des_read_pw_string_ProcPtr, "\pdes_read_pw_string", des_read_pw_string_ProcInfo);
-  if((Ptr) des_read_pw_string_ProcPtr != (Ptr) kUnresolvedCFragSymbolAddress)
-    return des_read_pw_string_ProcPtr(s, max, prompt, verify);
-}
-
-
-/**** des_cblock_print_file ****/
-/* void des_cblock_print_file(des_cblock *x, FILE *fp); */
-
-enum {
-  des_cblock_print_file_ProcInfo = kThinkCStackBased
-  | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(des_cblock *)))
-  | STACK_ROUTINE_PARAMETER(2, SIZE_CODE(sizeof(FILE *)))
-};
-
-typedef void (*des_cblock_print_file_ProcPtrType)(des_cblock *, FILE *);
-void des_cblock_print_file (
-     des_cblock * x,
-     FILE * fp)
-{
-  static des_cblock_print_file_ProcPtrType des_cblock_print_file_ProcPtr = kUnresolvedCFragSymbolAddress;
-
-  // if this symbol has not been setup yet...
-  if((Ptr) des_cblock_print_file_ProcPtr == (Ptr) kUnresolvedCFragSymbolAddress)
-    Find_Symbol((Ptr *) &des_cblock_print_file_ProcPtr, "\pdes_cblock_print_file", des_cblock_print_file_ProcInfo);
-  if((Ptr) des_cblock_print_file_ProcPtr != (Ptr) kUnresolvedCFragSymbolAddress)
-    des_cblock_print_file_ProcPtr(x, fp);
-}
-
-
-/**** des_pcbc_encrypt ****/
-/* int des_pcbc_encrypt(des_cblock *in, des_cblock *out, long length, des_key_schedule schedule, des_cblock ivec, int encrypt); */
-
-enum {
-  des_pcbc_encrypt_ProcInfo = kThinkCStackBased
-  | RESULT_SIZE(SIZE_CODE(sizeof(int)))
-  | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(des_cblock *)))
-  | STACK_ROUTINE_PARAMETER(2, SIZE_CODE(sizeof(des_cblock *)))
-  | STACK_ROUTINE_PARAMETER(3, SIZE_CODE(sizeof(long)))
-  | STACK_ROUTINE_PARAMETER(4, SIZE_CODE(sizeof(struct des_ks_struct *)))
-  | STACK_ROUTINE_PARAMETER(5, SIZE_CODE(sizeof(unsigned char *)))
-  | STACK_ROUTINE_PARAMETER(6, SIZE_CODE(sizeof(int)))
-};
-
-typedef int (*des_pcbc_encrypt_ProcPtrType)(des_cblock *, des_cblock *, long, des_key_schedule, des_cblock, int);
-int des_pcbc_encrypt (
-    des_cblock * in,
-    des_cblock * out,
-    long length,
-    des_key_schedule schedule,
-    des_cblock ivec,
-    int encrypt)
-{
-  static des_pcbc_encrypt_ProcPtrType des_pcbc_encrypt_ProcPtr = kUnresolvedCFragSymbolAddress;
-
-  // if this symbol has not been setup yet...
-  if((Ptr) des_pcbc_encrypt_ProcPtr == (Ptr) kUnresolvedCFragSymbolAddress)
-    Find_Symbol((Ptr *) &des_pcbc_encrypt_ProcPtr, "\pdes_pcbc_encrypt", des_pcbc_encrypt_ProcInfo);
-  if((Ptr) des_pcbc_encrypt_ProcPtr != (Ptr) kUnresolvedCFragSymbolAddress)
-    return des_pcbc_encrypt_ProcPtr(in, out, length, schedule, ivec, encrypt);
-}
-
-
-/**** des_check_key_parity ****/
-/* int des_check_key_parity(register des_cblock key); */
-
-enum {
-  des_check_key_parity_ProcInfo = kThinkCStackBased
-  | RESULT_SIZE(SIZE_CODE(sizeof(int)))
-  | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(unsigned char *)))
-};
-
-typedef int (*des_check_key_parity_ProcPtrType)(register des_cblock);
-int des_check_key_parity (
-    register des_cblock key)
-{
-  static des_check_key_parity_ProcPtrType des_check_key_parity_ProcPtr = kUnresolvedCFragSymbolAddress;
-
-  // if this symbol has not been setup yet...
-  if((Ptr) des_check_key_parity_ProcPtr == (Ptr) kUnresolvedCFragSymbolAddress)
-    Find_Symbol((Ptr *) &des_check_key_parity_ProcPtr, "\pdes_check_key_parity", des_check_key_parity_ProcInfo);
-  if((Ptr) des_check_key_parity_ProcPtr != (Ptr) kUnresolvedCFragSymbolAddress)
-    return des_check_key_parity_ProcPtr(key);
-}
-
-
-/**** des_3cbc_encrypt ****/
-/* void des_3cbc_encrypt(des_cblock *in, des_cblock *out, long length, des_key_schedule ks1, des_key_schedule ks2, des_key_schedule ks3, des_cblock ivec, int encrypt); */
-
-enum {
-  des_3cbc_encrypt_ProcInfo = kThinkCStackBased
-  | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(des_cblock *)))
-  | STACK_ROUTINE_PARAMETER(2, SIZE_CODE(sizeof(des_cblock *)))
-  | STACK_ROUTINE_PARAMETER(3, SIZE_CODE(sizeof(long)))
-  | STACK_ROUTINE_PARAMETER(4, SIZE_CODE(sizeof(des_key_schedule)))
-  | STACK_ROUTINE_PARAMETER(5, SIZE_CODE(sizeof(des_key_schedule)))
-  | STACK_ROUTINE_PARAMETER(6, SIZE_CODE(sizeof(des_key_schedule)))
-  | STACK_ROUTINE_PARAMETER(7, SIZE_CODE(sizeof(des_cblock)))
-  | STACK_ROUTINE_PARAMETER(8, SIZE_CODE(sizeof(int)))
-};
-
-typedef void (*des_3cbc_encrypt_ProcPtrType)(des_cblock *, des_cblock *, long, des_key_schedule, des_key_schedule, des_key_schedule, des_cblock, int);
-void des_3cbc_encrypt (
-     des_cblock * in,
-     des_cblock * out,
-     long length,
-     des_key_schedule ks1,
-     des_key_schedule ks2,
-     des_key_schedule ks3,
-     des_cblock ivec,
-     int encrypt)
-{
-  static des_3cbc_encrypt_ProcPtrType des_3cbc_encrypt_ProcPtr = kUnresolvedCFragSymbolAddress;
-
-  // if this symbol has not been setup yet...
-  if((Ptr) des_3cbc_encrypt_ProcPtr == (Ptr) kUnresolvedCFragSymbolAddress)
-    Find_Symbol((Ptr *) &des_3cbc_encrypt_ProcPtr, "\pdes_3cbc_encrypt", des_3cbc_encrypt_ProcInfo);
-  if((Ptr) des_3cbc_encrypt_ProcPtr != (Ptr) kUnresolvedCFragSymbolAddress)
-    des_3cbc_encrypt_ProcPtr(in, out, length, ks1, ks2, ks3, ivec, encrypt);
-}
-
-
-/**** des_string_to_key ****/
-/* int des_string_to_key(char *str, des_cblock key); */
-
-enum {
-  des_string_to_key_ProcInfo = kThinkCStackBased
-  | RESULT_SIZE(SIZE_CODE(sizeof(int)))
-  | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(char *)))
-  | STACK_ROUTINE_PARAMETER(2, SIZE_CODE(sizeof(unsigned char *)))
-};
-
-typedef int (*des_string_to_key_ProcPtrType)(char *, des_cblock);
-int des_string_to_key (
-    char * str,
-    des_cblock key)
-{
-  static des_string_to_key_ProcPtrType des_string_to_key_ProcPtr = kUnresolvedCFragSymbolAddress;
-
-  // if this symbol has not been setup yet...
-  if((Ptr) des_string_to_key_ProcPtr == (Ptr) kUnresolvedCFragSymbolAddress)
-    Find_Symbol((Ptr *) &des_string_to_key_ProcPtr, "\pdes_string_to_key", des_string_to_key_ProcInfo);
-  if((Ptr) des_string_to_key_ProcPtr != (Ptr) kUnresolvedCFragSymbolAddress)
-    return des_string_to_key_ProcPtr(str, key);
-}
-
-
-/**** des_init_random_number_generator ****/
-/* void des_init_random_number_generator(des_cblock key); */
-
-enum {
-  des_init_random_number_generator_ProcInfo = kThinkCStackBased
-  | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(unsigned char *)))
-};
-
-typedef void (*des_init_random_number_generator_ProcPtrType)(des_cblock);
-void des_init_random_number_generator (
-     des_cblock key)
-{
-  static des_init_random_number_generator_ProcPtrType des_init_random_number_generator_ProcPtr = kUnresolvedCFragSymbolAddress;
-
-  // if this symbol has not been setup yet...
-  if((Ptr) des_init_random_number_generator_ProcPtr == (Ptr) kUnresolvedCFragSymbolAddress)
-    Find_Symbol((Ptr *) &des_init_random_number_generator_ProcPtr, "\pdes_init_random_number_generator", des_init_random_number_generator_ProcInfo);
-  if((Ptr) des_init_random_number_generator_ProcPtr != (Ptr) kUnresolvedCFragSymbolAddress)
-    des_init_random_number_generator_ProcPtr(key);
-}
-
-
-Boolean DESLibraryIsPresent(void)
-{
-       Ptr     symAddr;
-       return (Find_Symbol (&symAddr, "\pdes_cbc_encrypt", des_cbc_encrypt_ProcInfo)) == noErr;
-}
diff --git a/src/mac/libraries/DES/include/deslib.CFMGlue.h b/src/mac/libraries/DES/include/deslib.CFMGlue.h
deleted file mode 100644 (file)
index 7f4277f..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-#ifndef __DESLIB_CFMGLUE__
-#define __DESLIB_CFMGLUE__
-
-/* Prototype for checking if the library is there */
-
-Boolean DESLibraryIsPresent(void);
-
-#endif /* __DESLIB_CFMGLUE__ */
\ No newline at end of file
diff --git a/src/mac/libraries/DES/include/mit-copyright.h b/src/mac/libraries/DES/include/mit-copyright.h
deleted file mode 100644 (file)
index cd30580..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-/* 
-  Copyright (C) 1989 by the Massachusetts Institute of Technology
-
-   Export of this software from the United States of America is assumed
-   to require a specific license from the United States Government.
-   It is the responsibility of any person or organization contemplating
-   export to obtain such a license before exporting.
-
-WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
-distribute this software and its documentation for any purpose and
-without fee is hereby granted, provided that the above copyright
-notice appear in all copies and that both that copyright notice and
-this permission notice appear in supporting documentation, and that
-the name of M.I.T. not be used in advertising or publicity pertaining
-to distribution of the software without specific, written prior
-permission.  M.I.T. makes no representations about the suitability of
-this software for any purpose.  It is provided "as is" without express
-or implied warranty.
-
-  */
diff --git a/src/mac/libraries/Metrowerks/CW Pro 2/MIT C.CFM68K DLL.doc b/src/mac/libraries/Metrowerks/CW Pro 2/MIT C.CFM68K DLL.doc
deleted file mode 100644 (file)
index 95040d6..0000000
+++ /dev/null
@@ -1,31 +0,0 @@
-Changes between CodeWarrior Pro 2 and MITAthena MSL project:
-
- - Ã’MSL C.CFM68K DLL.mcpÓ renamed to Ã’MIT C.CFM68K DLL.prjÓ
- - This document added to the project
- - Ã’MSL MWRuntimeLibCFM68KÓ removed from the project
- - Changed settings in Ã’MSL C.CFM68K DLLÓ target
- - Added Ã’MIT C.CFM68K DLL.debugÓ target
-Changes to Ã’MSL C.CFM68K DLLÓ target:
-
- - Added Ã’MIT RuntimeLib.68KÓ
- - Name set to Ã’MIT C.CFM68K DLLÓ
- - Output directory changed to Ã’{Project Ã„}::bin:Ó
- - Added Ã’{Compiler Ã„}:Metrowerks Standard Library:MSL C:Ó to user paths
-       Â¥Â¥Â¥ Important: this path must come after Ã’{Project Ã„}::Ó so that we can override
-       Â¥Â¥Â¥ original MSL with our own sources
- - Turned on Ã’Activate BrowserÓ
- - Changed output file name to Ã’MIT CLib.68KÓ
- - Changed output file creator to '????'
- - Changed CFM68K fragment name to Ã’MIT_Â¥MITCLibÓ
-Configuration of the Ã’MIT C.CFM68K DLL.debugÓ target:
-
- - Added Ã’MIT RuntimeLib.68K.debugÓ
- - Started by cloning Ã’MIT C.CFM68K DLLÓ target after making the above modifications
- - Changed output file name to Ã’MIT CLib.68K.debugÓ
- - Peephole optimizer turned off
- - CSE optimizer turned off
- - Optimize for size turned off
- - Generating SYM files turned on
- - Changed CFM68K fragment name to Ã’MIT_Â¥MIT CLib.debugÓ
diff --git a/src/mac/libraries/Metrowerks/CW Pro 2/MIT C.CFM68K DLL.prj b/src/mac/libraries/Metrowerks/CW Pro 2/MIT C.CFM68K DLL.prj
deleted file mode 100644 (file)
index 5f53c8a..0000000
Binary files a/src/mac/libraries/Metrowerks/CW Pro 2/MIT C.CFM68K DLL.prj and /dev/null differ
diff --git a/src/mac/libraries/Metrowerks/CW Pro 2/MIT C.PPC DLL.doc b/src/mac/libraries/Metrowerks/CW Pro 2/MIT C.PPC DLL.doc
deleted file mode 100644 (file)
index 35eb3fb..0000000
+++ /dev/null
@@ -1,31 +0,0 @@
-Changes between CodeWarrior Pro 2 and MITAthena MSL project:
-
- - Ã’MSL C.PPC DLL.mcpÓ renamed to Ã’MIT C.PPC DLL.prjÓ
- - This document added to the project
- - Ã’MSL Runtime PPC.DLLÓ removed from the project
- - Changed settings in Ã’MSL C.PPC DLLÓ target
- - Added Ã’MIT C.PPC DLL.debugÓ target
-Changes to Ã’MSL C.PPC DLLÓ target:
-
- - Added Ã’MIT RuntimeLib.PPCÓ
- - Name set to Ã’MIT C.PPC DLLÓ
- - Output directory changed to Ã’{Project Ã„}::bin:Ó
- - Added Ã’{Compiler Ã„}:Metrowerks Standard Library:MSL C:Ó to user paths
-       Â¥Â¥Â¥ Important: this path must come after Ã’{Project Ã„}::Ó so that we can override
-       Â¥Â¥Â¥ original MSL with our own sources
- - Turned on Ã’Activate BrowserÓ
- - Changed output file name to Ã’MIT CLib.PPCÓ
- - Changed output file creator to '????'
- - Changed PPC PEF fragment name to Ã’MIT_Â¥MITCLibÓ
-Configuration of the Ã’MIT C.PPC DLL.debugÓ target:
-
- - Added Ã’MIT RuntimeLib.PPC.debugÓ
- - Started by cloning Ã’MIT C.PPC DLLÓ target after making the above modifications
- - Changed output file name to Ã’MIT CLib.PPC.debugÓ
- - Instruction scheduling turned off
- - Global optimization turned off
- - Peephole optimization turned off
- - Generating SYM files turned on
- - Changed PPC PEF fragment name to Ã’MIT_Â¥MITCLib.debugÓ
diff --git a/src/mac/libraries/Metrowerks/CW Pro 2/MIT C.PPC DLL.prj b/src/mac/libraries/Metrowerks/CW Pro 2/MIT C.PPC DLL.prj
deleted file mode 100644 (file)
index f11064f..0000000
Binary files a/src/mac/libraries/Metrowerks/CW Pro 2/MIT C.PPC DLL.prj and /dev/null differ
diff --git a/src/mac/libraries/Metrowerks/CW Pro 2/MIT RuntimeCFM68K DLL.doc b/src/mac/libraries/Metrowerks/CW Pro 2/MIT RuntimeCFM68K DLL.doc
deleted file mode 100644 (file)
index 8d9795c..0000000
+++ /dev/null
@@ -1,31 +0,0 @@
-Changes between CodeWarrior Pro 2 and MITAthena MSL project:
-
- - Ã’MSL MWRuntimeLibCFM68K.mcpÓ renamed to Ã’MIT RuntimeCFM68K DLL.prjÓ
- - This document added to the project
- - Changed settings in Ã’MSL MWRuntimeLibCFM68KÓ target
- - Added Ã’MIT RuntimeCFM68K DLL.debugÓ target
-Changes to Ã’MSL MWRuntimeLibCFM68KÓ target:
-
- - Target name set to Ã’MIT RuntimeCFM68K DLLÓ
- - Output directory changed to Ã’{Project Ã„}::bin:Ó
- - Set user paths to:
-               Ã’{Project Ã„}::Ó
-               Ã’{Compiler Ã„}:MacOS Support:Libraries:Runtime:Runtime CFM68K:(Sources):Ó
-               Ã’{Compiler Ã„}:MacOS Support:Libraries:Runtime:Common Sources:Ó
-       Â¥Â¥Â¥ Important: the compiler-relative paths must come after Ã’{Project Ã„}::Ó so that
-       Â¥Â¥Â¥ we can override original sources with our own
- - Turned on Ã’Activate BrowserÓ
- - Changed output file name to Ã’MIT RuntimeLib.68KÓ
- - Changed output file creator to '????'
- - Changed PPC PEF fragment name to Ã’MIT_Â¥MITRuntimeLibÓ
-Configuration of the Ã’MIT RuntimeCFM68K DLL.debugÓ target:
-
- - Started by cloning Ã’MIT RuntimeCFM68K DLLÓ target after making the above modifications
- - Changed output file name to Ã’MIT RuntimeLib.68K.debugÓ
- - Peephole optimizer turned off
- - CSE optimizer turned off
- - Optimize for size turned off
- - Generating SYM files turned on
- - Changed PPC PEF fragment name to Ã’MIT_Â¥MITRuntimeLib.debugÓ
diff --git a/src/mac/libraries/Metrowerks/CW Pro 2/MIT RuntimeCFM68K DLL.prj b/src/mac/libraries/Metrowerks/CW Pro 2/MIT RuntimeCFM68K DLL.prj
deleted file mode 100644 (file)
index 197a283..0000000
Binary files a/src/mac/libraries/Metrowerks/CW Pro 2/MIT RuntimeCFM68K DLL.prj and /dev/null differ
diff --git a/src/mac/libraries/Metrowerks/CW Pro 2/MIT RuntimePPC DLL.doc b/src/mac/libraries/Metrowerks/CW Pro 2/MIT RuntimePPC DLL.doc
deleted file mode 100644 (file)
index 3a11d7a..0000000
+++ /dev/null
@@ -1,31 +0,0 @@
-Changes between CodeWarrior Pro 2 and MITAthena MSL project:
-
- - Ã’MSL RuntimePPC.mcpÓ renamed to Ã’MIT RuntimePPC DLL.prjÓ
- - This document added to the project
- - Changed settings in Ã’MSL RuntimePPC DLLÓ target
- - Added Ã’MIT RuntimePPC.debugÓ target
-Changes to Ã’MSL RuntimePPCÓ target:
-
- - Name set to Ã’MIT RuntimePPC DLLÓ
- - Output directory changed to Ã’{Project Ã„}::bin:Ó
- - Set user paths to:
-               Ã’{Project Ã„}::Ó
-               Ã’{Compiler Ã„}:MacOS Support:Libraries:Runtime:Runtime PPC:(Sources):Ó
-               Ã’{Compiler Ã„}:MacOS Support:Libraries:Runtime:Common Sources:Ó
-       Â¥Â¥Â¥ Important: the compiler-relative paths must come after Ã’{Project Ã„}::Ó so that
-       Â¥Â¥Â¥ we can override original sources with our own
- - Turned on Ã’Activate BrowserÓ
- - Changed output file name to Ã’MIT RuntimeLib.PPCÓ
- - Changed output file creator to '????'
- - Changed PPC PEF fragment name to Ã’MIT_Â¥MITRuntimeLibÓ
-Configuration of the Ã’MIT RuntimePPC DLL.debugÓ target:
-
- - Started by cloning Ã’MIT RuntimePPC DLLÓ target after making the above modifications
- - Changed output file name to Ã’MIT RuntimeLib.PPC.debugÓ
- - Instruction scheduling turned off
- - Global optimization turned off
- - Peephole optimization turned off
- - Generating SYM files turned on
- - Changed PPC PEF fragment name to Ã’MIT_Â¥MITRuntimeLib.debugÓ
diff --git a/src/mac/libraries/Metrowerks/CW Pro 2/MIT RuntimePPC DLL.prj b/src/mac/libraries/Metrowerks/CW Pro 2/MIT RuntimePPC DLL.prj
deleted file mode 100644 (file)
index 59338a9..0000000
Binary files a/src/mac/libraries/Metrowerks/CW Pro 2/MIT RuntimePPC DLL.prj and /dev/null differ
diff --git a/src/mac/libraries/Metrowerks/CW Pro 4/MIT C.CFM68K DLL.doc b/src/mac/libraries/Metrowerks/CW Pro 4/MIT C.CFM68K DLL.doc
deleted file mode 100644 (file)
index 8f5a2f4..0000000
+++ /dev/null
@@ -1,30 +0,0 @@
-Changes between CodeWarrior Pro 4 and MITAthena MSL project:
-
- - Ã’MSL C.CFM68K DLL.mcpÓ renamed to Ã’MIT C.CFM68K DLL.prjÓ
- - This document added to the project
- - Ã’MSL MWRuntimeLibCFM68KÓ removed from the project
- - Changed settings in Ã’MSL C.CFM68K DLLÓ target
- - Added Ã’MIT C.CFM68K DLL.debugÓ target
-Changes to Ã’MSL C.CFM68K DLLÓ target:
-
- - Added Ã’MIT RuntimeLib.68KÓ
- - Name set to Ã’MIT C.CFM68K DLLÓ
- - Output directory changed to Ã’{Project Ã„}::bin:Ó
- - Added Ã’{Compiler Ã„}:Metrowerks Standard Library:MSL C:Ó to user paths
-       Â¥Â¥Â¥ Important: this path must come after Ã’{Project Ã„}::Ó so that we can override
-       Â¥Â¥Â¥ original MSL with our own sources
- - Turned on Ã’Activate BrowserÓ
- - Changed output file name to Ã’MIT CLib.68KÓ
- - Changed output file creator to '????'
- - Global optimizations turned off
- - Changed CFM68K fragment name to Ã’MIT_Â¥MITCLibÓ
-Configuration of the Ã’MIT C.CFM68K DLL.debugÓ target:
-
- - Added Ã’MIT RuntimeLib.68K.debugÓ
- - Started by cloning Ã’MIT C.CFM68K DLLÓ target after making the above modifications
- - Changed output file name to Ã’MIT CLib.68K.debugÓ
- - Global optimizations turned off
- - Generating SYM files turned on
- - Changed CFM68K fragment name to Ã’MIT_Â¥MIT CLib.debugÓ
diff --git a/src/mac/libraries/Metrowerks/CW Pro 4/MIT C.CFM68K DLL.prj b/src/mac/libraries/Metrowerks/CW Pro 4/MIT C.CFM68K DLL.prj
deleted file mode 100644 (file)
index 3a54b89..0000000
Binary files a/src/mac/libraries/Metrowerks/CW Pro 4/MIT C.CFM68K DLL.prj and /dev/null differ
diff --git a/src/mac/libraries/Metrowerks/CW Pro 4/MIT C.PPC DLL.doc b/src/mac/libraries/Metrowerks/CW Pro 4/MIT C.PPC DLL.doc
deleted file mode 100644 (file)
index fd91e29..0000000
+++ /dev/null
@@ -1,33 +0,0 @@
-Changes between CodeWarrior Pro 4 and MITAthena MSL project:
-
- - Ã’MSL C.PPC DLL.mcpÓ renamed to Ã’MIT C.PPC DLL.prjÓ
- - This document added to the project
- - Ã’MSL Runtime PPC.DLLÓ removed from the project
- - Changed settings in Ã’MSL C.PPC DLLÓ target
- - Added Ã’MIT C.PPC DLL.debugÓ target
-Changes to Ã’MSL C.PPC DLLÓ target:
-
- - Added Ã’MIT RuntimeLib.PPCÓ
- - Name set to Ã’MIT C.PPC DLLÓ
- - Output directory changed to Ã’{Project Ã„}::bin:Ó
- - Added Ã’{Compiler Ã„}:Metrowerks Standard Library:MSL C:Ó to user paths
-       Â¥Â¥Â¥ Important: this path must come after Ã’{Project Ã„}::Ó so that we can override
-       Â¥Â¥Â¥ original MSL with our own sources
- - Turned on Ã’Activate BrowserÓ
- - Changed output file name to Ã’MIT CLib.PPCÓ
- - Changed output file creator to '????'
- - Global optimizations turned off (because of reports of optimizer bugs)
- - Changed PPC PEF fragment name to Ã’MIT_Â¥MITCLibÓ
-Configuration of the Ã’MIT C.PPC DLL.debugÓ target:
-
- - Added Ã’MIT RuntimeLib.PPC.debugÓ
- - Started by cloning Ã’MIT C.PPC DLLÓ target after making the above modifications
- - Changed output file name to Ã’MIT CLib.PPC.debugÓ
- - Instruction scheduling turned off
- - Global optimization turned off
- - Peephole optimization turned off
- - Global optimizations turned off (because of reports of optimizer bugs)
- - Generating SYM files turned on
- - Changed PPC PEF fragment name to Ã’MIT_Â¥MITCLib.debugÓ
diff --git a/src/mac/libraries/Metrowerks/CW Pro 4/MIT C.PPC DLL.prj b/src/mac/libraries/Metrowerks/CW Pro 4/MIT C.PPC DLL.prj
deleted file mode 100644 (file)
index 8e7abb1..0000000
Binary files a/src/mac/libraries/Metrowerks/CW Pro 4/MIT C.PPC DLL.prj and /dev/null differ
diff --git a/src/mac/libraries/Metrowerks/CW Pro 4/MIT RuntimeCFM68K DLL.doc b/src/mac/libraries/Metrowerks/CW Pro 4/MIT RuntimeCFM68K DLL.doc
deleted file mode 100644 (file)
index 9cfd527..0000000
+++ /dev/null
@@ -1,30 +0,0 @@
-Changes between CodeWarrior Pro 4 and MITAthena MSL project:
-
- - Ã’MSL MWRuntimeLibCFM68K.mcpÓ renamed to Ã’MIT RuntimeCFM68K DLL.prjÓ
- - This document added to the project
- - Changed settings in Ã’MSL MWRuntimeLibCFM68KÓ target
- - Added Ã’MIT RuntimeCFM68K DLL.debugÓ target
-Changes to Ã’MSL MWRuntimeLibCFM68KÓ target:
-
- - Target name set to Ã’MIT RuntimeCFM68K DLLÓ
- - Output directory changed to Ã’{Project Ã„}::bin:Ó
- - Set user paths to:
-               Ã’{Project Ã„}::Ó
-               Ã’{Compiler Ã„}:MacOS Support:Libraries:Runtime:Runtime CFM68K:(Sources):Ó
-               Ã’{Compiler Ã„}:MacOS Support:Libraries:Runtime:Common Sources:Ó
-       Â¥Â¥Â¥ Important: the compiler-relative paths must come after Ã’{Project Ã„}::Ó so that
-       Â¥Â¥Â¥ we can override original sources with our own
- - Turned on Ã’Activate BrowserÓ
- - Changed output file name to Ã’MIT RuntimeLib.68KÓ
- - Changed output file creator to '????'
- - Global optimizations turned off
- - Changed PPC PEF fragment name to Ã’MIT_Â¥MITRuntimeLibÓ
-Configuration of the Ã’MIT RuntimeCFM68K DLL.debugÓ target:
-
- - Started by cloning Ã’MIT RuntimeCFM68K DLLÓ target after making the above modifications
- - Changed output file name to Ã’MIT RuntimeLib.68K.debugÓ
- - Global optimizations turned off
- - Generating SYM files turned on
- - Changed PPC PEF fragment name to Ã’MIT_Â¥MITRuntimeLib.debugÓ
diff --git a/src/mac/libraries/Metrowerks/CW Pro 4/MIT RuntimeCFM68K DLL.prj b/src/mac/libraries/Metrowerks/CW Pro 4/MIT RuntimeCFM68K DLL.prj
deleted file mode 100644 (file)
index 3a60365..0000000
Binary files a/src/mac/libraries/Metrowerks/CW Pro 4/MIT RuntimeCFM68K DLL.prj and /dev/null differ
diff --git a/src/mac/libraries/Metrowerks/CW Pro 4/MIT RuntimePPC DLL.doc b/src/mac/libraries/Metrowerks/CW Pro 4/MIT RuntimePPC DLL.doc
deleted file mode 100644 (file)
index 2536928..0000000
+++ /dev/null
@@ -1,32 +0,0 @@
-Changes between CodeWarrior Pro 4 and MITAthena MSL project:
-
- - Ã’MSL RuntimePPC.mcpÓ renamed to Ã’MIT RuntimePPC DLL.prjÓ
- - This document added to the project
- - Changed settings in Ã’MSL RuntimePPC DLLÓ target
- - Added Ã’MIT RuntimePPC.debugÓ target
-Changes to Ã’MSL RuntimePPCÓ target:
-
- - Name set to Ã’MIT RuntimePPC DLLÓ
- - Output directory changed to Ã’{Project Ã„}::bin:Ó
- - Set user paths to:
-               Ã’{Project Ã„}::Ó
-               Ã’{Compiler Ã„}:MacOS Support:Libraries:Runtime:Runtime PPC:(Sources):Ó
-               Ã’{Compiler Ã„}:MacOS Support:Libraries:Runtime:Common Sources:Ó
-       Â¥Â¥Â¥ Important: the compiler-relative paths must come after Ã’{Project Ã„}::Ó so that
-       Â¥Â¥Â¥ we can override original sources with our own
- - Turned on Ã’Activate BrowserÓ
- - Changed output file name to Ã’MIT RuntimeLib.PPCÓ
- - Changed output file creator to '????'
- - GLobal optimizations turned off (because of reports of optimizer bugs)
- - Changed PPC PEF fragment name to Ã’MIT_Â¥MITRuntimeLibÓ
-Configuration of the Ã’MIT RuntimePPC DLL.debugÓ target:
-
- - Started by cloning Ã’MIT RuntimePPC DLLÓ target after making the above modifications
- - Changed output file name to Ã’MIT RuntimeLib.PPC.debugÓ
- - Schedule instructions turned off
- - Peephole optimization turned off
- - Generating SYM files turned on
- - Global optimizations turned off
- - Changed PPC PEF fragment name to Ã’MIT_Â¥MITRuntimeLib.debugÓ
diff --git a/src/mac/libraries/Metrowerks/CW Pro 4/MIT RuntimePPC DLL.prj b/src/mac/libraries/Metrowerks/CW Pro 4/MIT RuntimePPC DLL.prj
deleted file mode 100644 (file)
index 4cd7f78..0000000
Binary files a/src/mac/libraries/Metrowerks/CW Pro 4/MIT RuntimePPC DLL.prj and /dev/null differ
index 9f285d41c97cc594e89ca28e78ca33782a8fcf6f..79107f86c7ca526057fee61b4a1bcce0aa8c57f0 100644 (file)
@@ -1,3 +1,8 @@
+1998-10-27  Marc Horowitz  <marc@mit.edu>
+
+       * kpropd.c (authorized_principal): make the acl file contain
+       etypes, and use that in the authorization process.
+
 Wed Feb 18 16:27:28 1998  Tom Yu  <tlyu@mit.edu>
 
        * Makefile.in (thisconfigdir): Remove trailing slash.
index 3db4d0bb7e69c5a15eb6b144763d82d59b6f530a..70f07b369079a24c35364bf33876ce18c81f3b8f 100644 (file)
@@ -1,3 +1,29 @@
+/*
+ * Copyright (C) 1998 by the FundsXpress, INC.
+ * 
+ * All rights reserved.
+ * 
+ * Export of this software from the United States of America may require
+ * a specific license from the United States Government.  It is the
+ * responsibility of any person or organization contemplating export to
+ * obtain such a license before exporting.
+ * 
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of FundsXpress. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  FundsXpress makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
 /*
  * slave/kpropd.c
  *
@@ -91,10 +117,12 @@ void       kerberos_authenticate
        PROTOTYPE((krb5_context,
                   int,
                   krb5_principal *,
+                  krb5_enctype *,
                   struct sockaddr_in));
 krb5_boolean authorized_principal
        PROTOTYPE((krb5_context,
-                  krb5_principal));
+                  krb5_principal,
+                  krb5_enctype));
 void   recv_database
        PROTOTYPE((krb5_context,
                   int,
@@ -237,6 +265,7 @@ void doit(fd)
        krb5_data confmsg;
        int lock_fd;
        int omask;
+       krb5_enctype etype;
 
        fromlen = sizeof (from);
        if (getpeername(fd, (struct sockaddr *) &from, &fromlen) < 0) {
@@ -266,8 +295,9 @@ void doit(fd)
        /*
         * Now do the authentication
         */
-       kerberos_authenticate(kpropd_context, fd, &client, from);
-       if (!authorized_principal(kpropd_context, client)) {
+       kerberos_authenticate(kpropd_context, fd, &client, &etype, from);
+
+       if (!authorized_principal(kpropd_context, client, etype)) {
                char    *name;
 
                if (retval = krb5_unparse_name(kpropd_context, client, &name)) {
@@ -495,10 +525,11 @@ void PRS(argv)
  * Figure out who's calling on the other end of the connection....
  */
 void
-kerberos_authenticate(context, fd, clientp, sin)
+kerberos_authenticate(context, fd, clientp, etype, sin)
     krb5_context         context;
     int                          fd;
     krb5_principal     * clientp;
+    krb5_enctype       * etype;
     struct sockaddr_in   sin;
 {
     krb5_error_code      retval;
@@ -577,29 +608,42 @@ kerberos_authenticate(context, fd, clientp, sin)
        exit(1);
     }
 
+    *etype = ticket->enc_part.enctype;
+
     if (debug) {
        char * name;
+       char etypebuf[100];
 
        if (retval = krb5_unparse_name(context, *clientp, &name)) {
            com_err(progname, retval, "While unparsing client name");
            exit(1);
        }
-       printf("authenticated client: %s\n", name);
+
+       if (retval = krb5_enctype_to_string(*etype, etypebuf,
+                                           sizeof(etypebuf))) {
+           com_err(progname, retval, "While unparsing ticket etype");
+           exit(1);
+       }
+
+       printf("authenticated client: %s (etype == %s)\n", name, etypebuf);
        free(name);
     }
+
     krb5_free_ticket(context, ticket);
 }
 
 krb5_boolean
-authorized_principal(context, p)
+authorized_principal(context, p, auth_etype)
     krb5_context context;
     krb5_principal p;
+    krb5_enctype auth_etype;
 {
-    char               *name;
+    char               *name, *ptr;
     char               buf[1024];
     krb5_error_code    retval;
     FILE               *acl_file;
     int                        end;
+    krb5_enctype       acl_etype;
     
     retval = krb5_unparse_name(context, p, &name);
     if (retval)
@@ -615,7 +659,27 @@ authorized_principal(context, p)
        end = strlen(buf) - 1;
        if (buf[end] == '\n')
            buf[end] = '\0';
-       if (!strcmp(name, buf)) {
+       if (!strncmp(name, buf, strlen(name))) {
+           ptr = buf+strlen(name);
+
+           /* if the next character is not whitespace or nul, then
+              the match is only partial.  continue on to new lines. */
+           if (*ptr && !isspace(*ptr))
+               continue;
+
+           /* otherwise, skip trailing whitespace */
+           for (; *ptr && isspace(*ptr); ptr++) ;
+
+           /* now, look for an etype string. if there isn't one,
+              return true.  if there is an invalid string, continue.
+              If there is a valid string, return true only if it
+              matches the etype passed in, otherwise continue */
+
+           if ((*ptr) &&
+               ((retval = krb5_string_to_enctype(ptr, &acl_etype)) ||
+                (acl_etype != auth_etype)))
+               continue;
+
            free(name);
            fclose(acl_file);
            return TRUE;
index 64e0b2801cf91ff135ae237be2542dc17258a75e..ecb782e71b13c61482fd3f346470391c3a56d8e7 100644 (file)
@@ -1,3 +1,7 @@
+1998-10-27  Marc Horowitz  <marc@mit.edu>
+
+       * kdb5_mkdums.c: update to new crypto api
+
 1998-05-06  Theodore Ts'o  <tytso@rsts-11.mit.edu>
 
        * kdb5_mkdums.c (argv): POSIX states that getopt returns -1
index 18ee9e8ac67dadfc7f332cb23d94d54b02d60bc5..4f93766706d250c7937f9c01939b639fb69b24a7 100644 (file)
@@ -65,7 +65,6 @@ int status;
 krb5_keyblock master_keyblock;
 krb5_principal master_princ;
 krb5_db_entry master_entry;
-krb5_encrypt_block master_encblock;
 krb5_pointer master_random;
 krb5_context test_context;
 
@@ -175,8 +174,6 @@ char *argv[];
        exit(1);
     }
 
-    krb5_use_enctype(test_context, &master_encblock, master_keyblock.enctype);
-
     if (!dbname)
        dbname = DEFAULT_KDB_FILE;      /* XXX? */
 
@@ -207,9 +204,6 @@ char *argv[];
       }
     }
 
-    krb5_finish_random_key(test_context, &master_encblock, &master_random);
-    krb5_finish_key(test_context, &master_encblock);
-
     retval = krb5_db_fini(test_context);
     memset((char *)master_keyblock.contents, 0, master_keyblock.length);
     if (retval && retval != KRB5_KDB_DBNOTINITED) {
@@ -280,8 +274,8 @@ add_princ(context, str_newprinc)
 
        pwd.length = strlen(princ_name);
        pwd.data = princ_name;  /* must be able to regenerate */
-       if ((retval = krb5_string_to_key(context, &master_encblock
-                                       &key, &pwd, &salt))) {
+       if ((retval = krb5_c_string_to_key(context, master_keyblock.enctype
+                                          &pwd, &salt, &key))) {
            com_err(progname,retval,"while converting password to key for '%s'",
                    princ_name);
            krb5_free_data_contents(context, &salt);
@@ -296,7 +290,7 @@ add_princ(context, str_newprinc)
            goto error;
         }
 
-        if ((retval = krb5_dbekd_encrypt_key_data(context,&master_encblock, 
+        if ((retval = krb5_dbekd_encrypt_key_data(context,&master_keyblock, 
                                                  &key, NULL, 1, 
                                                  newentry.key_data))) {
            com_err(progname, retval, "while encrypting key for '%s'", 
@@ -357,8 +351,10 @@ char *dbname;
            com_err(pname, retval, "while calculated master key salt");
            return(1);
        }
-       if ((retval = krb5_string_to_key(test_context, &master_encblock, 
-                                   &master_keyblock, &pwd, &scratch))) {
+       if ((retval = krb5_c_string_to_key(test_context,
+                                          master_keyblock.enctype,
+                                          &pwd, &scratch,
+                                          &master_keyblock))) {
            com_err(pname, retval,
                    "while transforming master key from password");
            return(1);
@@ -366,7 +362,7 @@ char *dbname;
        free(scratch.data);
     } else {
        if ((retval = krb5_db_fetch_mkey(test_context, master_princ, 
-                                       &master_encblock, manual_mkey, 
+                                       master_keyblock.enctype, manual_mkey, 
                                        FALSE, 0, NULL, &master_keyblock))) {
            com_err(pname, retval, "while reading master key");
            return(1);
@@ -377,7 +373,7 @@ char *dbname;
        return(1);
     }
     if ((retval = krb5_db_verify_master_key(test_context, master_princ, 
-                                          &master_keyblock, &master_encblock))){
+                                          &master_keyblock))){
        com_err(pname, retval, "while verifying master key");
        (void) krb5_db_fini(test_context);
        return(1);
@@ -399,20 +395,6 @@ char *dbname;
        return(1);
     }
 
-    if ((retval = krb5_process_key(test_context,
-                                 &master_encblock, &master_keyblock))) {
-       com_err(pname, retval, "while processing master key");
-       (void) krb5_db_fini(test_context);
-       return(1);
-    }
-    if ((retval = krb5_init_random_key(test_context,
-                                     &master_encblock, &master_keyblock,
-                                     &master_random))) {
-       com_err(pname, retval, "while initializing random key generator");
-       krb5_finish_key(test_context, &master_encblock);
-       (void) krb5_db_fini(test_context);
-       return(1);
-    }
     mblock.max_life = master_entry.max_life;
     mblock.max_rlife = master_entry.max_renewable_life;
     mblock.expiration = master_entry.expiration;
diff --git a/src/tests/misc/test_nfold.c b/src/tests/misc/test_nfold.c
new file mode 100644 (file)
index 0000000..78b5866
--- /dev/null
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) 1998 by the FundsXpress, INC.
+ * 
+ * All rights reserved.
+ * 
+ * Export of this software from the United States of America may require
+ * a specific license from the United States Government.  It is the
+ * responsibility of any person or organization contemplating export to
+ * obtain such a license before exporting.
+ * 
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of FundsXpress. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  FundsXpress makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+int main(int argc, char *argv[])
+{
+    int inlen, outlen, i;
+    unsigned char *instr, *outstr;
+
+    if (argc != 3) {
+       fprintf(stderr, "%s: instr outlen\n", argv[0]);
+       exit(1);
+    }
+
+    instr = (unsigned char *) argv[1];
+    inlen = strlen(instr)*8;
+    outlen = atoi(argv[2]);
+    if (outlen%8) {
+       fprintf(stderr, "outlen must be a multiple of 8\n");
+       exit(1);
+    }
+
+    if ((outstr = (unsigned char *) malloc(outlen/8)) == NULL) {
+       fprintf(stderr, "ENOMEM\n");
+       exit(1);
+    }
+
+    krb5_nfold(inlen,instr,outlen,outstr);
+
+    printf("%d-fold(",outlen);
+    for (i=0; i<(inlen/8); i++)
+       printf("%02x",instr[i]);
+    printf(") = ");
+    for (i=0; i<(outlen/8); i++)
+       printf("%02x",outstr[i]);
+    printf("\n");
+
+    exit(0);
+}
index 12fb1f93b53fe38418ae865f83dd5394b6c75789..7f4aaf5a53d57b4ccb3190c607ca8e76f47ddd09 100644 (file)
@@ -1,3 +1,7 @@
+1998-10-27  Marc Horowitz  <marc@mit.edu>
+
+       * kdb5_verify.c: update to new crypto api
+
 1998-05-06  Theodore Ts'o  <tytso@rsts-11.mit.edu>
 
        * kdb5_verify.c (argv): POSIX states that getopt returns -1
index 8a95d7125e7ccbe39328ef514ad3224a29ec6437..558ef25335526f68218f168ec0791ce71e277e32 100644 (file)
@@ -272,7 +272,7 @@ check_princ(context, str_princ)
       goto errout;
     }
 
-    if ((retval = krb5_dbekd_decrypt_key_data(context, &master_encblock, 
+    if ((retval = krb5_dbekd_decrypt_key_data(context, &master_keyblock, 
                                             kdbe.key_data, &db_key, NULL))) {
        com_err(progname, retval, "while decrypting key for '%s'", princ_name);
        goto errout;
@@ -386,7 +386,8 @@ set_dbname_help(context, pname, dbname)
        }
        free(scratch.data);
     } else {
-       if ((retval = krb5_db_fetch_mkey(context, master_princ, &master_encblock,
+       if ((retval = krb5_db_fetch_mkey(context, master_princ,
+                                        master_keyblock.enctype,
                                        manual_mkey, FALSE, (char *) NULL, 0,
                                        &master_keyblock))) {
            com_err(pname, retval, "while reading master key");
@@ -398,8 +399,7 @@ set_dbname_help(context, pname, dbname)
        return(1);
     }
     if ((retval = krb5_db_verify_master_key(context, master_princ, 
-                                           &master_keyblock,
-                                           &master_encblock))) {
+                                           &master_keyblock))) {
        com_err(pname, retval, "while verifying master key");
        (void) krb5_db_fini(context);
        return(1);
index 8addd10cd9d87b2e25b90b4cf0b1652275775cf2..e9734a6f950e609d9baff5cb0e041af7ede546b5 100644 (file)
@@ -6,6 +6,10 @@
                problem where an insertion into the middle of the linked
                list didn't update a previous link.  [krb5-libs/615]
 
+1998-07-12  Sam Hartman  <hartmans@fundsxpress.com>
+
+       * Makefile.in: Add dependency on -lcom_err
+
 Mon Mar  2 16:19:58 1998  Ezra Peisach  <epeisach@mit.edu>
 
        * Makefile.in: Integrate in the krb5 build tree rules.
index 6dd0377c80a5cf84f447067a9ffa286068df0a1f..7f566d8c209ae8bf134c5d497ffb797dd7430968 100644 (file)
@@ -36,6 +36,11 @@ MLIBS = -lcom_err $(GEN_LIB)
 LIB=profile
 LIBMAJOR=1
 LIBMINOR=0
+SHLIB_EXPDEPS = $(TOPLIBD)/libcom_err$(SHLIBEXT)
+SHLIB_EXPLIBS = -lcom_err
+SHLIB_DIRS = -L$(TOPLIBD)
+SHLIB_RDIRS=$(KRB5_LIBDIR)
+
 STOBJLISTS=OBJS.ST
 
 all-unix:: includes test_parse test_profile
index 7441f615c6e0ef3b8ac467fdada4061014ab9df1..0594dbaa917b9d7d987c2d0667ae91f6f0be39bd 100644 (file)
@@ -9,5 +9,6 @@ AC_HAVE_FUNCS(stat)
 AC_PROG_AWK
 KRB5_BUILD_LIBOBJS
 KRB5_BUILD_PROGRAM
-KRB5_BUILD_LIBRARY
+KRB5_BUILD_LIBRARY_WITH_DEPS
 V5_AC_OUTPUT_MAKEFILE
+
index 46919b61f8e623781fceab6442a08d29a5b7c3a3..d5c5ba6bc3b8773c4922b06a4c1d5122e99b53db 100644 (file)
@@ -1,3 +1,7 @@
+1998-08-16    <hartmans@fundsxpress.com>
+
+       * Makefile.in (SHLIB_EXPDEPS): Depend on lib_comerr
+
 1998-07-05    <hartmans@fundsxpress.com>
 
        * update_utmp.c (pty_update_utmp): If the ut_exit differs test
index 339a11e9308bf628a34cba5021a27cc512d6fa35..1bf272b587ec39fe0ebfcf49cc49260bfcddc059 100644 (file)
@@ -31,6 +31,11 @@ CFILES=$(srcdir)/cleanup.c $(srcdir)/getpty.c $(srcdir)/init_slave.c \
 
 
 SRCS=pty_err.c $(CFILES)
+SHLIB_EXPDEPS = \
+       $(TOPLIBD)/libcom_err$(SHLIBEXT)
+SHLIB_EXPLIBS= -lcom_err 
+SHLIB_DIRS=-L$(TOPLIBD)
+SHLIB_RDIRS=$(KRB5_LIBDIR)
 
 DEPLIBS=
 
index 71adc940d5fe61d8557e7976638fcae04af3ea93..4c58d6ee3681262f6fee12d61f0fa773ae0fae6c 100644 (file)
@@ -150,6 +150,6 @@ fi
 dnl
 ADD_DEF(-DKERBEROS)
 AC_CONST
-KRB5_BUILD_LIBRARY
+KRB5_BUILD_LIBRARY_WITH_DEPS
 KRB5_BUILD_LIBOBJS
 V5_AC_OUTPUT_MAKEFILE
index 5fb0cad9688f0958b1ed87efc5df0d90b6ec0722..3f684052ca9c6ef0388a8971eb713680e03954fe 100644 (file)
@@ -189,7 +189,7 @@ int ss_execute_line (sci_idx, line_ptr)
     char *line_ptr;
 {
     char **argv;
-    int argc;
+    int argc, ret;
 
     /* flush leading whitespace */
     while (line_ptr[0] == ' ' || line_ptr[0] == '\t')
@@ -212,5 +212,9 @@ int ss_execute_line (sci_idx, line_ptr)
         return 0;
 
     /* look it up in the request tables, execute if found */
-    return really_execute_command (sci_idx, argc, &argv);
+    ret = really_execute_command (sci_idx, argc, &argv);
+
+    free(argv);
+
+    return(ret);
 }
diff --git a/src/windows/lib/ChangeLog b/src/windows/lib/ChangeLog
deleted file mode 100644 (file)
index e371d88..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-Tue Mar 18 12:08:50 1997  Michael Graff  <explorer@flame.org>
-
-       * registry.h, registry.c: add.
-
-Thu Mar 13 20:17:12 1997  Michael Graff  <explorer@flame.org>
-
-       * gic.c, gic.h, vardlg.c, vardlg.h: Finish up the variable dialog box
-       code.
-
-Thu Mar  6 21:45:05 1997  Michael Graff  <explorer@flame.org>
-
-       * gic.c, gic.h:  Added to start using get_init_creds.
-
-       * vardlg.c, vardlg.h: on-the-fly variable dialog building functions.
-
-
diff --git a/src/windows/lib/Makefile.in b/src/windows/lib/Makefile.in
deleted file mode 100644 (file)
index 95eb691..0000000
+++ /dev/null
@@ -1,19 +0,0 @@
-CFLAGS = $(CCOPTS2) $(DEFS)
-
-##DOSBUILDTOP = ..\..
-
-lib-windows: libwin.lib
-
-SRCS=  vardlg.c gic.c registry.c
-
-OBJS=  vardlg.obj gic.obj registry.obj
-
-libwin.lib: $(OBJS)
-       lib /nologo /out:$*.lib $(OBJS)
-
-all-windows:: lib-windows
-
-clean-windows::
-       $(RM) *.dll *.exp *.map *.lib *.obj
-
-install-windows::
diff --git a/src/windows/lib/gic.c b/src/windows/lib/gic.c
deleted file mode 100644 (file)
index 35ac8a8..0000000
+++ /dev/null
@@ -1,156 +0,0 @@
-/*
- * Copyright (C) 1997 Cygnus Solutions.
- *
- * Author:  Michael Graff
- */
-
-#include <windows.h>
-#include <windowsx.h>
-
-#include <stdlib.h>
-#include <string.h>
-#include <ctype.h>
-
-#include "krb5.h"
-
-#include "vardlg.h"
-#include "gic.h"
-
-/*
- * Steps performed:
- *
- *   1)  Create the dialog with all the windows we will need
- *      later.  This is done by calling vardlg_build() from
- *      gic_prompter().
- *
- *   2)  Run the dialog from within gic_prompter().  If the return
- *      value of the dialog is -1 or IDCANCEL, return an error.
- *      Otherwise, return success.
- *
- *   3)  From within the dialog initialization code, call
- *      vardlg_config(), which will:
- *
- *     a)  Set all the label strings in all the entry labels and
- *         the banner.
- *
- *     b)  Set the maximum input lengths on the entry fields.
- *
- *     c)  Calculate the size of the text used within the banner.
- *
- *     d)  Calculate the longest string of text used as a label.
- *
- *     e)  Resize each label and each entry within the dialog
- *         to "look nice."
- *
- *     f)  Place the OK and perhaps the Cancel buttons at the bottom
- *         of the dialog.
- *
- *   4)  When the OK button is clicked, copy all the values from the
- *      input fields and store them in the pointers we are given.
- *      Also, set the actual lengths to what we collected from the
- *      entries.  Finally, call EndDialog(IDOK) to end the dialog.
- */
-
-/*
- * Yes, a global.  It is a PITA to not use them in windows.
- */
-gic_data *gd;
-
-
-/*
- * initialize the dialog
- */
-static BOOL
-gic_dialog_init(HWND hwnd, HWND hwndFocus, LPARAM lParam)
-{
-       vardlg_config(hwnd, gd->width, gd->banner, gd->num_prompts,
-               gd->prompts, (WORD)(gd->id));
-
-       return FALSE;
-}
-
-/*
- * process dialog "commands"
- */
-static void
-gic_dialog_command(HWND hwnd, int cid, HWND hwndCtl, UINT codeNotify)
-{
-
-       int n;
-       WORD id;
-
-       /*
-        * We are only interested in button clicks, and then only of
-        * type IDOK or IDCANCEL.
-        */
-       if (codeNotify != BN_CLICKED)
-               return;
-       if (cid != IDOK && cid != IDCANCEL)
-               return;
-
-       /*
-        * If we are canceled, wipe all the fields and return IDCANCEL.
-        */
-       if (cid == IDCANCEL) {
-               EndDialog(hwnd, IDCANCEL);
-               return;
-       }
-
-       /*
-        * must be IDOK...
-        */
-       id = (gd->id + 2);
-       for (n = 0 ; n < gd->num_prompts ; n++) {
-               Edit_GetText(GetDlgItem(hwnd, id), gd->prompts[n].reply->data,
-                       gd->prompts[n].reply->length);
-               gd->prompts[n].reply->length = strlen(gd->prompts[n].reply->data);
-               id += 2;
-       }
-
-       EndDialog(hwnd, IDOK);
-}
-
-/*
- * The dialog callback.
- */
-static BOOL CALLBACK
-gic_dialog(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
-{
-       switch (message) {
-               HANDLE_MSG(hwnd, WM_INITDIALOG, gic_dialog_init);
-
-               HANDLE_MSG(hwnd, WM_COMMAND, gic_dialog_command);
-       }
-
-       return FALSE;
-}
-
-
-/*
- * All the disgusting code to use the get_init_creds() functions in a
- * broken environment
- */
-krb5_error_code KRB5_CALLCONV
-gic_prompter(krb5_context ctx, void *data, const char *banner,
-            int num_prompts, krb5_prompt prompts[])
-{
-       int       rc;
-       void     *dlg;
-
-       gd = data;
-
-       gd->banner = banner;
-       gd->num_prompts = num_prompts;
-       gd->prompts = prompts;
-       if (gd->width == 0)
-               gd->width = 450;
-
-       dlg = vardlg_build((WORD)(gd->width), gd->banner, (WORD)num_prompts, prompts, (WORD)(gd->id));
-
-       rc = DialogBoxIndirect(gd->hinstance, (LPDLGTEMPLATE)dlg, gd->hwnd, gic_dialog);
-
-       if (rc != IDOK)
-               return 1;
-
-       return 0;
-}
diff --git a/src/windows/lib/gic.h b/src/windows/lib/gic.h
deleted file mode 100644 (file)
index ddea368..0000000
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * Copyright (C) 1997 Cygnus Solutions
- *
- * Author:  Michael Graff
- */
-
-#ifndef _WINDOWS_LIB_GIC_H
-#define _WINDOWS_LIB_GIC_H
-
-#include <windows.h>
-#include <windowsx.h>
-
-#include "krb5.h"
-
-typedef struct {
-       HINSTANCE    hinstance;     /* application instance */
-       HWND         hwnd;          /* parent window */
-       WORD         id;            /* starting ID */
-       WORD         width;         /* max width of the dialog box */
-       const char  *banner;        /* the banner */
-       WORD         num_prompts;   /* the number of prompts we were passed */
-       krb5_prompt *prompts;       /* the prompts themselves */
-} gic_data;
-
-krb5_error_code KRB5_CALLCONV gic_prompter(krb5_context, void *, const char *,
-                                          int, krb5_prompt []);
-
-#endif /* _WINDOWS_LIB_GIC_H */
diff --git a/src/windows/lib/registry.c b/src/windows/lib/registry.c
deleted file mode 100644 (file)
index 7dfbb5b..0000000
+++ /dev/null
@@ -1,231 +0,0 @@
-/*
- * Copyright (c) 1997 Cygnus Solutions
- *
- * Author:  Michael Graff
- */
-
-#include <windows.h>
-#include <windowsx.h>
-
-#include "registry.h"
-
-HKEY
-registry_open(HKEY hkey, char *base, REGSAM sam)
-{
-       HKEY    k = INVALID_HANDLE_VALUE;
-       DWORD   err;
-
-       /*
-        * if the base path is null, return the already open key in hkey
-        */
-       if (base == NULL)
-               return hkey;
-
-       err = RegOpenKeyEx(hkey, base, 0, sam, &hkey);
-       if (err != ERROR_SUCCESS)
-               return INVALID_HANDLE_VALUE;
-
-       return hkey;
-}
-
-void
-registry_close(HKEY hkey)
-{
-       CloseHandle(hkey);
-}
-
-HKEY
-registry_key_create(HKEY hkey, char *sub, REGSAM sam)
-{
-       HKEY    key;
-       DWORD   err;
-       DWORD   disp;
-
-       err = RegCreateKeyEx(hkey, sub, 0, 0, REG_OPTION_NON_VOLATILE, sam,
-                            NULL, &key, &disp);
-       if (err != ERROR_SUCCESS)
-               return INVALID_HANDLE_VALUE;
-
-       return key;
-}
-
-int
-registry_key_delete(HKEY hkey, char *sub)
-{
-       DWORD err;
-
-       err = RegDeleteKey(hkey, sub);
-       if (err != ERROR_SUCCESS)
-               return -1;
-
-       return 0;
-}
-
-int
-registry_string_get(HKEY hkey, char *sub, char **val)
-{
-       DWORD   err;
-       DWORD   type;
-       DWORD   datasize;
-
-       err = RegQueryValueEx(hkey, sub, 0, &type, 0, &datasize);
-       if (err != ERROR_SUCCESS || type != REG_SZ) {
-               *val = NULL;
-               return -1;
-       }
-
-       *val = malloc(datasize);
-       if (*val == NULL)
-               return -1;
-
-       err = RegQueryValueEx(hkey, sub, 0, &type, *val, &datasize);
-       if (err != ERROR_SUCCESS) {
-               free(*val);
-               *val = NULL;
-               return -1;
-       }
-       
-       return 0;
-}
-
-int
-registry_dword_get(HKEY hkey, char *sub, DWORD *val)
-{
-       DWORD   err;
-       DWORD   type;
-       DWORD   datasize;
-
-       err = RegQueryValueEx(hkey, sub, 0, &type, 0, &datasize);
-       if (err != ERROR_SUCCESS || type != REG_DWORD) {
-               *val = 0;
-               return -1;
-       }
-
-       err = RegQueryValueEx(hkey, sub, 0, &type, (BYTE *)val, &datasize);
-       if (err != ERROR_SUCCESS) {
-               *val = 0;
-               return -1;
-       }
-       
-       return 0;
-}
-
-int
-registry_string_set(HKEY hkey, char *sub, char *x)
-{
-       DWORD   err;
-
-       err = RegSetValueEx(hkey, sub, 0, REG_SZ, (BYTE *)x, strlen(x) + 1);
-       if (err != ERROR_SUCCESS)
-               return -1;
-
-       return 0;
-}
-
-int
-registry_dword_set(HKEY hkey, char *sub, DWORD x)
-{
-       DWORD   err;
-
-       err = RegSetValueEx(hkey, sub, 0, REG_DWORD, (CONST BYTE *)&x, sizeof(DWORD));
-       if (err != ERROR_SUCCESS)
-               return -1;
-
-       return 0;
-}
-
-int
-registry_keyval_dword_set(HKEY hkey, char *base, char *sub, DWORD val)
-{
-       HKEY   k;
-       int    err;
-
-       k = registry_open(hkey, base, KEY_WRITE);
-       if (k == INVALID_HANDLE_VALUE)
-               return -1;
-
-       err = registry_dword_set(k, sub, val);
-
-       registry_close(k);
-
-       return err;
-}
-
-int
-registry_keyval_dword_get(HKEY hkey, char *base, char *sub, DWORD *val)
-{
-       HKEY   k;
-       int    err;
-
-       k = registry_open(hkey, base, KEY_READ);
-       if (k == INVALID_HANDLE_VALUE)
-               return -1;
-
-       err = registry_dword_get(k, sub, val);
-
-       registry_close(k);
-
-       return err;
-}
-
-int
-registry_keyval_string_get(HKEY hkey, char *base, char *sub, char **val)
-{
-       HKEY   k;
-       int    err;
-
-       k = registry_open(hkey, base, KEY_READ);
-       if (k == INVALID_HANDLE_VALUE) {
-               *val = NULL;
-               return -1;
-       }
-
-       err = registry_string_get(k, sub, val);
-
-       registry_close(k);
-
-       return err;
-}
-
-int
-registry_keyval_string_set(HKEY hkey, char *base, char *sub, char *val)
-{
-       HKEY   k;
-       int    err;
-
-       k = registry_open(hkey, base, KEY_WRITE);
-       if (k == INVALID_HANDLE_VALUE)
-               return -1;
-
-       err = registry_string_set(k, sub, val);
-
-       registry_close(k);
-
-       return err;
-}
-
-int
-registry_value_delete(HKEY hkey, char *sub)
-{
-       if (RegDeleteValue(hkey, sub))
-               return -1;
-
-       return 0;
-}
-
-int
-registry_keyval_delete(HKEY hkey, char *base, char *sub)
-{
-       HKEY   k;
-       int    err;
-
-       k = registry_open(hkey, base, KEY_WRITE);
-       if (k == INVALID_HANDLE_VALUE)
-               return -1;
-
-       err = registry_value_delete(k, sub);
-
-       registry_close(k);
-
-       return err;
-}
diff --git a/src/windows/lib/registry.h b/src/windows/lib/registry.h
deleted file mode 100644 (file)
index d628d2b..0000000
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * Copyright (c) 1997 Cygnus Solutions
- *
- * Author:  Michael Graff
- */
-
-#ifndef LIB_WINDOWS_REGISTRY_H
-#define LIB_WINDOWS_REGISTRY_H
-
-#include <windows.h>
-#include <windowsx.h>
-
-HKEY registry_open(HKEY, char *, REGSAM);
-void registry_close(HKEY);
-HKEY registry_key_create(HKEY, char *, REGSAM);
-int registry_key_delete(HKEY, char *);
-int registry_string_get(HKEY, char *, char **);
-int registry_dword_get(HKEY, char *, DWORD *);
-int registry_string_set(HKEY, char *, char *);
-int registry_dword_set(HKEY, char *, DWORD);
-int registry_keyval_dword_set(HKEY, char *, char *, DWORD);
-int registry_keyval_dword_get(HKEY, char *, char *, DWORD *);
-int registry_keyval_string_get(HKEY, char *, char *, char **);
-int registry_keyval_string_set(HKEY, char *, char *, char *);
-int registry_value_delete(HKEY, char *);
-int registry_keyval_delete(HKEY, char *, char *);
-
-#define CYGNUS_SOLUTIONS     "SOFTWARE\\Cygnus Solutions"
-
-#define KERBNET_SANS_VERSION CYGNUS_SOLUTIONS "\\Kerbnet"
-#define KERBNET_BASE         KERBNET_SANS_VERSION "\\1"
-
-#define KERBNET_TELNET_BASE  KERBNET_BASE "\\telnet"
-#define KERBNET_TELNET_HOST  KERBNET_TELNET_BASE "\\hosts"
-
-#define KERBNET_CNS_BASE     KERBNET_BASE "\\cns"
-
-#define KERBNET_HOME         "KERBNET_HOME"
-
-#endif /* LIB_WINDOWS_REGISTRY_H */
diff --git a/src/windows/lib/vardlg.c b/src/windows/lib/vardlg.c
deleted file mode 100644 (file)
index 41d897b..0000000
+++ /dev/null
@@ -1,450 +0,0 @@
-/*
- * Dialog box building for various numbers of (label, entry) fields.
- *
- * This code is somewhat hardcoded to build boxes for the krb5_get_init_creds()
- * function.
- *
- * Copyright (C) 1997 Cygnus Solutions.
- *
- * Author:  Michael Graff
- */
-
-#include <windows.h>
-#include <windowsx.h>
-
-#include <stdlib.h>
-#include <string.h>
-#include <ctype.h>
-
-#include "krb5.h"
-#include "vardlg.h"
-
-/*
- * a hack, I know...  No error checking below, either.
- */
-static unsigned char dlg[DLG_BUF];
-
-/*
- * Add a WORD (16-bit int) to the buffer.  Return the number of characters
- * added.
- */
-static int
-ADD_WORD(unsigned char *p, WORD w)
-{
-       *((WORD *)p) = w;
-
-       return 2;
-}
-
-static int
-ADD_DWORD(unsigned char *p, DWORD dw)
-{
-       *((DWORD *)p) = dw;
-
-       return 4;
-}
-
-static int
-ADD_UNICODE_STRING(unsigned char *p, const char *s)
-{
-       WORD *w;
-       int i;
-       int len;
-
-       w = (WORD *)p;
-
-       len = strlen(s) + 1; /* copy the null, too */
-       
-       for (i = 0 ; i < len ; i++)
-               *w++ = *s++;
-
-       return (len * 2);
-}
-
-#define DWORD_ALIGN(p) { while ((DWORD)p % 4) *p++ = 0x00; }
-
-static int
-ADD_DLGTEMPLATE(unsigned char *dlg, short x, short y, short cx, short cy,
-               const char *caption, const char *fontname, WORD fontsize,
-               WORD n)
-{
-       unsigned char    *p;
-       DLGTEMPLATE       dlt;
-
-       p = dlg;
-
-       dlt.style = (DS_MODALFRAME | WS_POPUP);
-       if (caption != NULL)
-               dlt.style |= WS_CAPTION;
-       if (fontname != NULL)
-               dlt.style |= DS_SETFONT;
-       dlt.dwExtendedStyle = 0;
-       dlt.cdit = n;
-       dlt.x = x;
-       dlt.y = y;
-       dlt.cx = cx;
-       dlt.cy = cy;
-       memcpy(p, &dlt, sizeof(dlt));
-       p += sizeof(dlt);
-
-       p += ADD_WORD(p, 0x0000);  /* menu == none */
-
-       p += ADD_WORD(p, 0x0000);  /* class == default? */
-
-       if (caption != NULL)
-               p += ADD_UNICODE_STRING(p, caption);
-       else
-               p += ADD_WORD(p, 0x0000);
-
-       if (fontname != NULL) {
-               p += ADD_WORD(p, fontsize);
-               p += ADD_UNICODE_STRING(p, fontname);
-       }
-
-       DWORD_ALIGN(p);
-
-       return (p - dlg);
-}
-
-static int
-ADD_DLGITEM(unsigned char *dlg, short x, short y, short cx, short cy,
-           const char *label, WORD id, WORD type, DWORD style)
-{
-       unsigned char    *p;
-       DLGITEMTEMPLATE   dit;
-       
-       p = dlg;
-
-       dit.style = style;
-       dit.dwExtendedStyle = 0;
-       dit.x = x;
-       dit.y = y;
-       dit.cx = cx;
-       dit.cy = cy;
-       dit.id = id;
-       memcpy(p, &dit, sizeof(dit));
-       p += sizeof(dit);
-
-       p += ADD_WORD(p, 0xffff);
-       p += ADD_WORD(p, type);
-
-       p += ADD_UNICODE_STRING(p, label);
-
-       /*
-        * creation data? For now, just make this empty, like the resource
-        * compiler does.
-        */
-       p += ADD_WORD(p, 0x0000);
-
-       DWORD_ALIGN(p);
-
-       return (p - dlg);
-}
-
-#define ADD_DLGITEM_defpushbutton(a, b, c, d, e, f, g) \
-       ADD_DLGITEM((a), (b), (c), (d), (e), (f), (g), 0x0080, 0x50010001);
-
-#define ADD_DLGITEM_pushbutton(a, b, c, d, e, f, g) \
-       ADD_DLGITEM((a), (b), (c), (d), (e), (f), (g), 0x0080, 0x50010000);
-
-#define ADD_DLGITEM_left_static(a, b, c, d, e, f, g) \
-       ADD_DLGITEM((a), (b), (c), (d), (e), (f), (g), 0x0082, 0x50020000);
-
-#define ADD_DLGITEM_centered_static(a, b, c, d, e, f, g) \
-       ADD_DLGITEM((a), (b), (c), (d), (e), (f), (g), 0x0082, 0x50020001);
-
-#define ADD_DLGITEM_right_static(a, b, c, d, e, f, g) \
-       ADD_DLGITEM((a), (b), (c), (d), (e), (f), (g), 0x0082, 0x50020002);
-
-#define ADD_DLGITEM_entry(a, b, c, d, e, f, g) \
-       ADD_DLGITEM((a), (b), (c), (d), (e), (f), (g), 0x0081, 0x50810080);
-
-#define ADD_DLGITEM_hidden_entry(a, b, c, d, e, f, g) \
-       ADD_DLGITEM((a), (b), (c), (d), (e), (f), (g), 0x0081, 0x508100a0);
-
-
-/*
- * "build" the dialog box.  In this bit of code, we create the dialog box,
- * create the OK button, and a static label for the banner text.
- *
- * If there are items, we also create a Cancel button and one (label, entry)
- * fields for each item.
- */
-void *
-vardlg_build(WORD cx, const char *banner, WORD n, krb5_prompt prompts[],
-            WORD id)
-{
-       unsigned char *p;
-       WORD i;
-
-       p = dlg;  /* global */
-
-       if (cx < MIN_WIDTH)
-               cx = MIN_WIDTH;
-       if (cx > MAX_WIDTH)
-               cx = MAX_WIDTH;
-
-       /*
-        * Store the dialog template
-        */
-       p += ADD_DLGTEMPLATE(p, 0, 0, cx, 0, "KerbNet", "MS Sans Serif", 8,
-                            (WORD)(n * 2 + 3));
-
-       /*
-        * Create a label for the banner.  This will be ID (id).
-        */
-       p += ADD_DLGITEM_left_static(p, 0, 0, 0, 0, "", id++);
-
-       /*
-        * Each label field is ID (id + 1) + (item * 2), and each entry field
-        * is (id + 2) + (item * 2)
-        */
-       for (i = 0 ; i < n ; i++) {
-               p += ADD_DLGITEM_right_static(p, 0, 0, 0, 0, "", id++);
-               if (prompts[i].hidden) {
-                       p += ADD_DLGITEM_hidden_entry(p, 0, 0, 0, 0, "", id++);
-               } else {
-                       p += ADD_DLGITEM_entry(p, 0, 0, 0, 0, "", id++);
-               }
-       }
-
-       /*
-        * Create the OK and Cancel buttons.
-        */
-       p += ADD_DLGITEM_defpushbutton(p, 0, 0, 0, 0,
-                                      "OK", IDOK);
-       if (n != 0)
-               p += ADD_DLGITEM_pushbutton(p, 0, 0, 0, 0,
-                                           "Cancel", IDCANCEL);
-
-       return dlg;
-}
-
-#define SPACE_Y     4  /* logical units */
-#define SPACE_X     4  /* logical units */
-#define ENTRY_PX  120  /* pixels */
-#define BUTTON_PX  70  /* pixels */
-#define BUTTON_PY  30  /* pixels */
-
-void
-vardlg_config(HWND hwnd, WORD width, const char *banner, WORD num_prompts,
-             krb5_prompt *prompts, WORD id)
-{
-       int         n;
-       WORD        cid;
-       HDC         hdc;
-       SIZE        csize;
-       SIZE        maxsize;
-       LONG        cx, cy;
-       LONG        ccx, ccy;
-       LONG        space_x, space_y;
-       LONG        max_x, max_y;
-       LONG        banner_y;
-       RECT        rect;
-       int         done;
-       const char *p;
-
-       /*
-        * First, set the banner's text.
-        */
-       Static_SetText(GetDlgItem(hwnd, id), banner);
-
-       /*
-        * Next, run through the items and set their static text.
-        * Also, set the corresponding edit string and set the
-        * maximum input length.
-        */
-       cid = (id + 1);
-
-       for (n = 0 ; n < num_prompts ; n++) {
-               Static_SetText(GetDlgItem(hwnd, cid), prompts[n].prompt);
-               cid++;
-               Edit_SetText(GetDlgItem(hwnd, cid), "");
-               Edit_LimitText(GetDlgItem(hwnd, cid), prompts[n].reply->length);
-               cid++;
-       }
-
-       /*
-        * Now run through the entry fields and find the longest string.
-        */
-       maxsize.cx = maxsize.cy = 0;
-       cid = (id + 1);
-       hdc = GetDC(GetDlgItem(hwnd, cid)); /* assume one label is the same as all the others */
-
-       for (n = 0 ; n < num_prompts ; n++) {
-               GetTextExtentPoint32(hdc, prompts[n].prompt, strlen(prompts[n].prompt), &csize);
-               if (csize.cx > maxsize.cx)
-                       maxsize.cx = csize.cx;
-               if (csize.cy > maxsize.cy)
-                       maxsize.cy = csize.cy;
-       }
-
-#if 0
-       /*
-        * convert the maximum values into pixels.  Ugh.
-        */
-       rect.left = 0;
-       rect.top = 0;
-       rect.right = maxsize.cx;
-       rect.bottom = maxsize.cy;
-       MapDialogRect(hwnd, &rect);
-
-       max_x = rect.right;
-       max_y = rect.bottom;
-#else
-       max_x = maxsize.cx;
-       max_y = (long)(((double)maxsize.cy) * 1.5);
-#endif
-
-       /*
-        * convert the spacing values, too.  Ugh.  Ugh.
-        */
-       rect.left = 0;
-       rect.top = 0;
-       rect.right = SPACE_X;
-       rect.bottom = SPACE_Y;
-       MapDialogRect(hwnd, &rect);
-
-       space_x = rect.right;
-       space_y = rect.bottom;
-
-       /*
-        * Now we know the maximum length of the string for the entry labels.  Guestimate
-        * that the entry fields should be ENTRY_PX pixels long and resize the dialog
-        * window to fit the longest string plus the entry fields (plus a little for the
-        * spacing between the edges of the windows and the static and edit fields, and
-        * between the static and edit fields themselves.)
-        */
-       cx = max_x + ENTRY_PX + (space_x * 3);
-       cy = (max_y + space_y) * num_prompts;
-
-       /*
-        * resize the dialog box itself (take 1)
-        */
-       SetWindowPos(hwnd, HWND_TOPMOST,
-               0, 0,
-               cx + 10, cy + 30,
-               SWP_NOMOVE);
-
-       /*
-        * position the dialog items.  First, the banner. (take 1)
-        */
-       SetWindowPos(GetDlgItem(hwnd, id), HWND_BOTTOM,
-               space_x, space_y,
-               (cx - space_x * 2), max_y,
-               0);
-
-       /*
-        * Now that the window for the banner is in place, convert the width into logical units
-        * and find out how many lines we need to reserve room for.
-        */
-       done = 0;
-       p = banner;
-       banner_y = 0;
-
-       do {
-               int nFit;
-               int pDx[128];
-
-               hdc = GetDC(GetDlgItem(hwnd, id));
-
-               GetTextExtentExPoint(hdc, p, strlen(p), cx, &nFit,
-                       pDx, &csize);
-
-               banner_y += csize.cy;
-
-               p += nFit;
-
-       } while (*p != 0);
-
-       banner_y += space_y;
-
-       /*
-        * position the banner (take 2)
-        */
-       SetWindowPos(GetDlgItem(hwnd, id), HWND_BOTTOM,
-               space_x, space_y,
-               (cx - space_x * 2), banner_y,
-               0);
-
-       /*
-        * Don't forget to include the banner estimate and the buttons, too.  Once again,
-        * assume the buttons are BUTTON_PY pixels high.  The extra three space_y's are
-        * for between the top of the dialog and the banner, between the banner and the
-        * first label, and between the buttons and the bottom of the screen.
-        */
-       cy += banner_y + BUTTON_PY + (space_y * 3);
-
-       /*
-        * resize the dialog box itself (Again...  ugh!)
-        */
-       SetWindowPos(hwnd, HWND_TOPMOST,
-               0, 0,
-               cx + 10, cy + 30,
-               SWP_NOMOVE);
-
-       cid = (id + 1);
-       ccy = banner_y + (space_y * 2);
-       ccx = max_x + (space_x * 2);  /* where the edit fields start */
-
-       for (n = 0 ; n < num_prompts ; n++) {
-               SetWindowPos(GetDlgItem(hwnd, cid), HWND_BOTTOM,
-                       space_x, ccy,
-                       max_x, max_y, 0);
-               cid++;
-               SetWindowPos(GetDlgItem(hwnd, cid), HWND_BOTTOM,
-                       ccx, ccy,
-                       ENTRY_PX, max_y - 3, 0);
-               cid++;
-               ccy += (max_y + space_y);
-       }
-
-       /*
-        * Now the buttons.  If there are any entries we will have both an OK and a
-        * Cancel button.  If we don't have any entries, we will have only an OK.
-        */
-       if (num_prompts == 0) {
-               SetWindowPos(GetDlgItem(hwnd, IDOK), HWND_BOTTOM,
-                       (cx / 2), cy - space_y - BUTTON_PY,
-                       BUTTON_PX, BUTTON_PY, 0);
-       } else {
-               SetWindowPos(GetDlgItem(hwnd, IDOK), HWND_BOTTOM,
-                       space_x, cy - space_y - BUTTON_PY,
-                       BUTTON_PX, BUTTON_PY, 0);
-               SetWindowPos(GetDlgItem(hwnd, IDCANCEL), HWND_BOTTOM,
-                       cx - space_x - BUTTON_PX, cy - space_y - BUTTON_PY,
-                       BUTTON_PX, BUTTON_PY, 0);
-       }
-
-       return;
-}
-
-/*
- * To use these functions, first create the dialog box and entries.
- * You will always get an OK button.  If there are at least one item,
- * you will also get a cancel button.  The OK button is IDOK, and the cancel
- * button is IDCANCEL, as usual.
- *
- * After calling bld_dlg, the banner will have ID "id", and the labels
- * will be "1 + id + i * 2" (i is the entry number, starting with zero) and 
- * the entries will be "2 + id + i * 2".
- *
- *     unsigned char *dlg = vardlg_build(minwidth, banner, num_prompts,
- *                                       krb5_prompt[], id);
- *
- * Then, "run" the dialog using:
- *
- *     rc = DialogBoxIndirect(hinstance, (LPDLGTEMPLATE)dlg,
- *                            HWND_DESKTOP, myDialogProc);
- *
- * Note that the vardlg_build function uses a static data area and so cannot
- * be used more than once before the DialogBoxIndirect() procedure is called.
- * I assume windows won't need that area after that call is complete.
- *
- * In the dialog's _initialization_ procedure, call
- *
- *     vardlg_config(hwnd, banner, num_prompts, krb5_prompt[], id);
- *
- * This function will resize the various elements of the dialog and fill in the
- * labels.
- */
diff --git a/src/windows/lib/vardlg.h b/src/windows/lib/vardlg.h
deleted file mode 100644 (file)
index e832e51..0000000
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * Copyright (C) 1997 Cygnus Solutions
- *
- * Author:  Michael Graff
- */
-
-#ifndef _WINDOWS_LIB_VARDLG_H
-#define _WINDOWS_LIB_VARDLG_H
-
-#include <windows.h>
-#include <windowsx.h>
-
-#define DLG_BUF 4096
-
-/*
- * The minimum and maximum dialog box widths we will allow.
- */
-#define MIN_WIDTH 350
-#define MAX_WIDTH 600
-
-/*
- * "build" the dialog box.  In this bit of code, we create the dialog box,
- * create the OK button, and a static label for the banner text.
- *
- * If there are items, we also create a Cancel button and one (label, entry)
- * fields for each item.
- */
-void *vardlg_build(WORD, const char *, WORD, krb5_prompt *, WORD);
-
-void  vardlg_config(HWND, WORD, const char *, WORD, krb5_prompt *, WORD);
-
-#endif /* _WINDOWS_LIB_VARDLG_H */