summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/ChangeLog17
-rw-r--r--src/aclocal.m417
-rw-r--r--src/appl/bsd/ChangeLog23
-rw-r--r--src/appl/bsd/kcmd.c125
-rw-r--r--src/appl/bsd/krlogin.c175
-rw-r--r--src/appl/bsd/krlogind.c175
-rw-r--r--src/appl/bsd/login.c2306
-rw-r--r--src/appl/gss-sample/ChangeLog12
-rw-r--r--src/appl/gss-sample/gss-client.c35
-rw-r--r--src/appl/gss-sample/gss-server.c22
-rw-r--r--src/appl/gssftp/ftp/ChangeLog7
-rw-r--r--src/appl/gssftp/ftp/ftp.c91
-rw-r--r--src/appl/telnet/libtelnet/ChangeLog7
-rw-r--r--src/appl/telnet/libtelnet/enc_des.c109
-rw-r--r--src/appl/telnet/libtelnet/kerberos.c200
-rw-r--r--src/appl/telnet/telnet/ChangeLog7
-rw-r--r--src/appl/telnet/telnet/commands.c8
-rw-r--r--src/clients/ChangeLog8
-rw-r--r--src/clients/Makefile.in2
-rw-r--r--src/clients/configure.in1
-rw-r--r--src/clients/kinit/ChangeLog4
-rw-r--r--src/clients/kinit/kinit.c536
-rw-r--r--src/clients/klist/ChangeLog6
-rw-r--r--src/clients/klist/klist.c89
-rw-r--r--src/include/ChangeLog18
-rw-r--r--src/include/k5-int.h173
-rw-r--r--src/include/kerberosIV/ChangeLog6
-rw-r--r--src/include/kerberosIV/krb_db.h2
-rw-r--r--src/include/krb5.hin203
-rw-r--r--src/include/krb5/ChangeLog5
-rw-r--r--src/include/krb5/kdb.h46
-rw-r--r--src/include/krb5/kdb_dbc.h28
-rw-r--r--src/kadmin/cli/ChangeLog5
-rw-r--r--src/kadmin/cli/keytab.c53
-rw-r--r--src/kadmin/dbutil/ChangeLog17
-rw-r--r--src/kadmin/dbutil/dumpv4.c47
-rw-r--r--src/kadmin/dbutil/kadm5_create.c27
-rw-r--r--src/kadmin/dbutil/kdb5_create.c97
-rw-r--r--src/kadmin/dbutil/kdb5_stash.c34
-rw-r--r--src/kadmin/dbutil/kdb5_util.c216
-rw-r--r--src/kadmin/dbutil/loadv4.c82
-rw-r--r--src/kadmin/server/ChangeLog7
-rw-r--r--src/kadmin/server/ovsec_kadmd.c42
-rw-r--r--src/kadmin/v4server/ChangeLog15
-rw-r--r--src/kadmin/v4server/acl_files.c2
-rw-r--r--src/kadmin/v4server/admin_server.c5
-rw-r--r--src/kadmin/v4server/kadm_funcs.c2
-rw-r--r--src/kadmin/v4server/kadm_ser_wrap.c24
-rw-r--r--src/kadmin/v4server/kadm_server.h1
-rw-r--r--src/kdc/ChangeLog53
-rw-r--r--src/kdc/do_as_req.c27
-rw-r--r--src/kdc/do_tgs_req.c59
-rw-r--r--src/kdc/extern.h2
-rw-r--r--src/kdc/kdc_preauth.c256
-rw-r--r--src/kdc/kdc_util.c115
-rw-r--r--src/kdc/kerberos_v4.c240
-rw-r--r--src/kdc/main.c84
-rw-r--r--src/krb524/ChangeLog23
-rw-r--r--src/krb524/cnv_tkt_skey.c46
-rw-r--r--src/krb524/krb524d.c46
-rw-r--r--src/lib/crypto/ChangeLog31
-rw-r--r--src/lib/crypto/Makefile.in213
-rw-r--r--src/lib/crypto/block_size.c49
-rw-r--r--src/lib/crypto/checksum_length.c53
-rw-r--r--src/lib/crypto/cksumtype_to_string.c49
-rw-r--r--src/lib/crypto/cksumtypes.c74
-rw-r--r--src/lib/crypto/cksumtypes.h31
-rw-r--r--src/lib/crypto/coll_proof_cksum.c44
-rw-r--r--src/lib/crypto/configure.in130
-rw-r--r--src/lib/crypto/crc32/ChangeLog4
-rw-r--r--src/lib/crypto/crc32/Makefile.in26
-rw-r--r--src/lib/crypto/crc32/crc-32.h32
-rw-r--r--src/lib/crypto/crc32/crc32.c166
-rw-r--r--src/lib/crypto/cryptoconf.c168
-rw-r--r--src/lib/crypto/decrypt.c56
-rw-r--r--src/lib/crypto/decrypt_data.c66
-rw-r--r--src/lib/crypto/des/.rconf8
-rw-r--r--src/lib/crypto/des/ChangeLog4
-rw-r--r--src/lib/crypto/des/FUNCTIONS26
-rw-r--r--src/lib/crypto/des/Makefile.in114
-rw-r--r--src/lib/crypto/des/afsstring2key.c32
-rw-r--r--src/lib/crypto/des/cbc_cksum.c164
-rw-r--r--src/lib/crypto/des/d3_ecb.c47
-rw-r--r--src/lib/crypto/des/d3_procky.c60
-rw-r--r--src/lib/crypto/des/d3_str2ky.c137
-rw-r--r--src/lib/crypto/des/des.h59
-rw-r--r--src/lib/crypto/des/des_int.h29
-rw-r--r--src/lib/crypto/des/destest.c68
-rw-r--r--src/lib/crypto/des/f_README69
-rw-r--r--src/lib/crypto/des/f_ecb.c95
-rw-r--r--src/lib/crypto/des/f_pcbc.c207
-rw-r--r--src/lib/crypto/des/fin_rndkey.c51
-rw-r--r--src/lib/crypto/des/finish_key.c48
-rw-r--r--src/lib/crypto/des/init_rkey.c167
-rw-r--r--src/lib/crypto/des/process_ky.c70
-rw-r--r--src/lib/crypto/des/random_key.c95
-rw-r--r--src/lib/crypto/des/string2key.c40
-rw-r--r--src/lib/crypto/des/t_random.c117
-rw-r--r--src/lib/crypto/des/t_verify.c146
-rw-r--r--src/lib/crypto/des/u_nfold.c99
-rw-r--r--src/lib/crypto/des/u_rn_key.c139
-rw-r--r--src/lib/crypto/des3_raw.c104
-rw-r--r--src/lib/crypto/des3_sha.c178
-rw-r--r--src/lib/crypto/des_crc.c170
-rw-r--r--src/lib/crypto/des_md5.c171
-rw-r--r--src/lib/crypto/encrypt.c56
-rw-r--r--src/lib/crypto/encrypt_data.c70
-rw-r--r--src/lib/crypto/encrypt_length.c52
-rw-r--r--src/lib/crypto/enctype_compare.c58
-rw-r--r--src/lib/crypto/enctype_to_string.c49
-rw-r--r--src/lib/crypto/etypes.c82
-rw-r--r--src/lib/crypto/etypes.h30
-rw-r--r--src/lib/crypto/hmac.c131
-rw-r--r--src/lib/crypto/keyed_checksum_types.c95
-rw-r--r--src/lib/crypto/keyed_cksum.c49
-rw-r--r--src/lib/crypto/krb5_glue.c233
-rw-r--r--src/lib/crypto/make_checksum.c111
-rw-r--r--src/lib/crypto/make_random_key.c84
-rw-r--r--src/lib/crypto/md4/.rconf2
-rw-r--r--src/lib/crypto/md4/ChangeLog4
-rw-r--r--src/lib/crypto/md4/Makefile.in30
-rw-r--r--src/lib/crypto/md4/md4crypto.c385
-rw-r--r--src/lib/crypto/md4/md4driver.c202
-rw-r--r--src/lib/crypto/md4/md4glue.c115
-rw-r--r--src/lib/crypto/md5/ChangeLog4
-rw-r--r--src/lib/crypto/md5/Makefile.in22
-rw-r--r--src/lib/crypto/md5/md5crypto.c353
-rw-r--r--src/lib/crypto/md5/md5glue.c89
-rw-r--r--src/lib/crypto/md5/t_cksum.c203
-rw-r--r--src/lib/crypto/nfold.c132
-rw-r--r--src/lib/crypto/old_api_glue.c360
-rw-r--r--src/lib/crypto/os/.Sanitize39
-rw-r--r--src/lib/crypto/os/ChangeLog204
-rw-r--r--src/lib/crypto/os/Makefile.in28
-rw-r--r--src/lib/crypto/os/c_localaddr.c348
-rw-r--r--src/lib/crypto/os/rnd_confoun.c98
-rw-r--r--src/lib/crypto/prng.c155
-rw-r--r--src/lib/crypto/raw_des.c100
-rw-r--r--src/lib/crypto/sha/.Sanitize42
-rw-r--r--src/lib/crypto/sha/ChangeLog89
-rw-r--r--src/lib/crypto/sha/Makefile.in43
-rw-r--r--src/lib/crypto/sha/hmac_sha.c101
-rw-r--r--src/lib/crypto/sha/sha_crypto.c76
-rw-r--r--src/lib/crypto/sha/sha_glue.c97
-rw-r--r--src/lib/crypto/sha/shs.c392
-rw-r--r--src/lib/crypto/sha/shs.h59
-rw-r--r--src/lib/crypto/sha/t_shs.c132
-rw-r--r--src/lib/crypto/string_to_cksumtype.c45
-rw-r--r--src/lib/crypto/string_to_enctype.c45
-rw-r--r--src/lib/crypto/string_to_key.c68
-rw-r--r--src/lib/crypto/t_nfold.c76
-rw-r--r--src/lib/crypto/valid_cksumtype.c41
-rw-r--r--src/lib/crypto/valid_enctype.c41
-rw-r--r--src/lib/crypto/verify_checksum.c84
-rw-r--r--src/lib/des425/ChangeLog8
-rw-r--r--src/lib/des425/Makefile.in5
-rw-r--r--src/lib/des425/new_rnd_key.c124
-rw-r--r--src/lib/des425/random_key.c49
-rw-r--r--src/lib/gssapi/Makefile.in2
-rw-r--r--src/lib/gssapi/generic/ChangeLog5
-rw-r--r--src/lib/gssapi/generic/gssapi.hin8
-rw-r--r--src/lib/gssapi/generic/gssapi_err_generic.et3
-rw-r--r--src/lib/gssapi/generic/util_token.c7
-rw-r--r--src/lib/gssapi/krb5/ChangeLog39
-rw-r--r--src/lib/gssapi/krb5/Makefile.in6
-rw-r--r--src/lib/gssapi/krb5/accept_sec_context.c980
-rw-r--r--src/lib/gssapi/krb5/acquire_cred.c115
-rw-r--r--src/lib/gssapi/krb5/add_cred.c309
-rw-r--r--src/lib/gssapi/krb5/canon_name.c17
-rw-r--r--src/lib/gssapi/krb5/delete_sec_context.c15
-rw-r--r--src/lib/gssapi/krb5/disp_status.c10
-rw-r--r--src/lib/gssapi/krb5/gssapiP_krb5.h77
-rw-r--r--src/lib/gssapi/krb5/gssapi_err_krb5.et1
-rw-r--r--src/lib/gssapi/krb5/gssapi_krb5.c39
-rw-r--r--src/lib/gssapi/krb5/gssapi_krb5.h3
-rw-r--r--src/lib/gssapi/krb5/init_sec_context.c604
-rw-r--r--src/lib/gssapi/krb5/inq_cred.c57
-rw-r--r--src/lib/gssapi/krb5/inq_names.c3
-rw-r--r--src/lib/gssapi/krb5/k5seal.c356
-rw-r--r--src/lib/gssapi/krb5/k5unseal.c585
-rw-r--r--src/lib/gssapi/krb5/rel_oid.c3
-rw-r--r--src/lib/gssapi/krb5/ser_sctx.c305
-rw-r--r--src/lib/gssapi/krb5/util_cksum.c27
-rw-r--r--src/lib/gssapi/krb5/util_crypt.c161
-rw-r--r--src/lib/gssapi/krb5/util_ctxsetup.c208
-rw-r--r--src/lib/gssapi/krb5/util_seed.c16
-rw-r--r--src/lib/gssapi/krb5/util_seqnum.c12
-rw-r--r--src/lib/gssapi/krb5/wrap_size_limit.c108
-rw-r--r--src/lib/kadm5/ChangeLog11
-rw-r--r--src/lib/kadm5/alt_prof.c11
-rw-r--r--src/lib/kadm5/clnt/ChangeLog9
-rw-r--r--src/lib/kadm5/clnt/Makefile.in2
-rw-r--r--src/lib/kadm5/clnt/client_init.c42
-rw-r--r--src/lib/kadm5/srv/ChangeLog8
-rw-r--r--src/lib/kadm5/srv/Makefile.in2
-rw-r--r--src/lib/kadm5/srv/server_kdb.c27
-rw-r--r--src/lib/kadm5/srv/svr_principal.c72
-rw-r--r--src/lib/kdb/ChangeLog30
-rw-r--r--src/lib/kdb/Makefile.in4
-rw-r--r--src/lib/kdb/decrypt_key.c88
-rw-r--r--src/lib/kdb/encrypt_key.c80
-rw-r--r--src/lib/kdb/fetch_mkey.c40
-rw-r--r--src/lib/kdb/kdb_cpw.c209
-rw-r--r--src/lib/kdb/kdb_db2.c38
-rw-r--r--src/lib/kdb/kdb_db2.h2
-rw-r--r--src/lib/kdb/kdb_dbm.c12
-rw-r--r--src/lib/kdb/kdb_xdr.c39
-rw-r--r--src/lib/kdb/keytab.c2
-rw-r--r--src/lib/kdb/verify_mky.c21
-rw-r--r--src/lib/krb4/ChangeLog31
-rw-r--r--src/lib/krb4/Makefile.in2
-rw-r--r--src/lib/krb4/cr_tkt.c92
-rw-r--r--src/lib/krb4/decomp_tkt.c85
-rw-r--r--src/lib/krb4/rd_req.c47
-rw-r--r--src/lib/krb4/tf_util.c2
-rw-r--r--src/lib/krb5/ChangeLog8
-rw-r--r--src/lib/krb5/Makefile.in4
-rw-r--r--src/lib/krb5/asn.1/ChangeLog7
-rw-r--r--src/lib/krb5/asn.1/asn1buf.c2
-rw-r--r--src/lib/krb5/ccache/ChangeLog4
-rw-r--r--src/lib/krb5/ccache/ccapi/Makefile.in21
-rw-r--r--src/lib/krb5/ccache/ccapi/stdcc.c394
-rw-r--r--src/lib/krb5/ccache/ccapi/stdcc.h73
-rw-r--r--src/lib/krb5/ccache/ccapi/stdcc_util.c368
-rw-r--r--src/lib/krb5/ccache/ccapi/stdcc_util.h25
-rw-r--r--src/lib/krb5/ccache/ccbase.c6
-rw-r--r--src/lib/krb5/configure.in1
-rw-r--r--src/lib/krb5/error_tables/krb5_err.et2
-rw-r--r--src/lib/krb5/keytab/file/ChangeLog5
-rw-r--r--src/lib/krb5/keytab/file/ktf_g_ent.c87
-rw-r--r--src/lib/krb5/krb/ChangeLog36
-rw-r--r--src/lib/krb5/krb/Makefile.in3
-rw-r--r--src/lib/krb5/krb/auth_con.c70
-rw-r--r--src/lib/krb5/krb/auth_con.h1
-rw-r--r--src/lib/krb5/krb/decode_kdc.c18
-rw-r--r--src/lib/krb5/krb/decrypt_tk.c24
-rw-r--r--src/lib/krb5/krb/enc_helper.c53
-rw-r--r--src/lib/krb5/krb/encode_kdc.c66
-rw-r--r--src/lib/krb5/krb/encrypt_tk.c61
-rw-r--r--src/lib/krb5/krb/gen_seqnum.c70
-rw-r--r--src/lib/krb5/krb/gen_subkey.c27
-rw-r--r--src/lib/krb5/krb/get_creds.c107
-rw-r--r--src/lib/krb5/krb/gic_pwd.c8
-rw-r--r--src/lib/krb5/krb/in_tkt_pwd.c9
-rw-r--r--src/lib/krb5/krb/init_ctx.c183
-rw-r--r--src/lib/krb5/krb/kdc_rep_dc.c29
-rw-r--r--src/lib/krb5/krb/kfree.c11
-rw-r--r--src/lib/krb5/krb/mk_cred.c47
-rw-r--r--src/lib/krb5/krb/mk_priv.c59
-rw-r--r--src/lib/krb5/krb/mk_rep.c44
-rw-r--r--src/lib/krb5/krb/mk_req_ext.c65
-rw-r--r--src/lib/krb5/krb/mk_safe.c15
-rw-r--r--src/lib/krb5/krb/preauth.c16
-rw-r--r--src/lib/krb5/krb/preauth2.c23
-rw-r--r--src/lib/krb5/krb/rd_cred.c26
-rw-r--r--src/lib/krb5/krb/rd_priv.c41
-rw-r--r--src/lib/krb5/krb/rd_rep.c27
-rw-r--r--src/lib/krb5/krb/rd_req_dec.c93
-rw-r--r--src/lib/krb5/krb/rd_safe.c11
-rw-r--r--src/lib/krb5/krb/send_tgs.c100
-rw-r--r--src/lib/krb5/krb/ser_actx.c39
-rw-r--r--src/lib/krb5/krb/ser_eblk.c4
-rw-r--r--src/lib/krb5/krb/str_conv.c148
-rw-r--r--src/lib/krb5/krb/vfy_increds.c104
-rw-r--r--src/lib/krb5/os/ChangeLog13
-rw-r--r--src/lib/krb5/os/Makefile.in3
-rw-r--r--src/lib/krb5/os/c_ustime.c (renamed from src/lib/crypto/os/c_ustime.c)2
-rw-r--r--src/lib/krb5/os/ktdefname.c22
-rw-r--r--src/lib/krb5/os/localaddr.c317
-rw-r--r--src/lib/krb5/os/locate_kdc.c31
-rw-r--r--src/lib/rpc/ChangeLog9
-rw-r--r--src/lib/rpc/Makefile.in2
-rw-r--r--src/lib/rpc/auth_gssapi.h6
-rw-r--r--src/lib/rpc/svc_auth_gssapi.c43
-rw-r--r--src/mac/TestTrack/ChangeLog24
-rw-r--r--src/mac/TestTrack/MITAthenaLib1
-rw-r--r--src/mac/TestTrack/ShlibTestTrack.c115
-rw-r--r--src/mac/TestTrack/ShlibTestTrack.h19
-rw-r--r--src/mac/TestTrack/TestTrackLib.h59
-rw-r--r--src/mac/TestTrack/testtrack.h30
-rw-r--r--src/mac/libraries/CCache API/bin/CCacheGlobalsLib.68K1
-rw-r--r--src/mac/libraries/CCache API/bin/CCacheGlobalsLib.PPC1
-rw-r--r--src/mac/libraries/CCache API/bin/CCacheLib.68K1
-rw-r--r--src/mac/libraries/CCache API/bin/CCacheLib.68K.debug1
-rw-r--r--src/mac/libraries/CCache API/bin/CCacheLib.PPC1
-rw-r--r--src/mac/libraries/CCache API/bin/CCacheLib.PPC.debug1
-rw-r--r--src/mac/libraries/CCache API/include/CCache.h350
-rw-r--r--src/mac/libraries/CCache API/include/CCacheUtil.h28
-rw-r--r--src/mac/libraries/CodeWarrior Dependencies/Pro2.prjbin17459 -> 0 bytes
-rw-r--r--src/mac/libraries/CodeWarrior Dependencies/Pro4.prjbin18655 -> 0 bytes
-rw-r--r--src/mac/libraries/DES/bin/deslib.68K1
-rw-r--r--src/mac/libraries/DES/bin/deslib.68K.debug1
-rw-r--r--src/mac/libraries/DES/bin/deslib.PPC1
-rw-r--r--src/mac/libraries/DES/bin/deslib.PPC.debug1
-rw-r--r--src/mac/libraries/DES/doc/ChangeLog369
-rw-r--r--src/mac/libraries/DES/doc/READ_ME21
-rw-r--r--src/mac/libraries/DES/doc/f_README69
-rw-r--r--src/mac/libraries/DES/doc/ren.msg32
-rw-r--r--src/mac/libraries/DES/include/des.h158
-rw-r--r--src/mac/libraries/DES/include/deslib.CFMGlue.c842
-rw-r--r--src/mac/libraries/DES/include/deslib.CFMGlue.h8
-rw-r--r--src/mac/libraries/DES/include/mit-copyright.h20
-rw-r--r--src/mac/libraries/Metrowerks/CW Pro 2/MIT C.CFM68K DLL.doc31
-rw-r--r--src/mac/libraries/Metrowerks/CW Pro 2/MIT C.CFM68K DLL.prjbin86057 -> 0 bytes
-rw-r--r--src/mac/libraries/Metrowerks/CW Pro 2/MIT C.PPC DLL.doc31
-rw-r--r--src/mac/libraries/Metrowerks/CW Pro 2/MIT C.PPC DLL.prjbin97000 -> 0 bytes
-rw-r--r--src/mac/libraries/Metrowerks/CW Pro 2/MIT RuntimeCFM68K DLL.doc31
-rw-r--r--src/mac/libraries/Metrowerks/CW Pro 2/MIT RuntimeCFM68K DLL.prjbin83326 -> 0 bytes
-rw-r--r--src/mac/libraries/Metrowerks/CW Pro 2/MIT RuntimePPC DLL.doc31
-rw-r--r--src/mac/libraries/Metrowerks/CW Pro 2/MIT RuntimePPC DLL.prjbin80572 -> 0 bytes
-rw-r--r--src/mac/libraries/Metrowerks/CW Pro 4/MIT C.CFM68K DLL.doc30
-rw-r--r--src/mac/libraries/Metrowerks/CW Pro 4/MIT C.CFM68K DLL.prjbin89611 -> 0 bytes
-rw-r--r--src/mac/libraries/Metrowerks/CW Pro 4/MIT C.PPC DLL.doc33
-rw-r--r--src/mac/libraries/Metrowerks/CW Pro 4/MIT C.PPC DLL.prjbin95479 -> 0 bytes
-rw-r--r--src/mac/libraries/Metrowerks/CW Pro 4/MIT RuntimeCFM68K DLL.doc30
-rw-r--r--src/mac/libraries/Metrowerks/CW Pro 4/MIT RuntimeCFM68K DLL.prjbin80278 -> 0 bytes
-rw-r--r--src/mac/libraries/Metrowerks/CW Pro 4/MIT RuntimePPC DLL.doc32
-rw-r--r--src/mac/libraries/Metrowerks/CW Pro 4/MIT RuntimePPC DLL.prjbin91916 -> 0 bytes
-rw-r--r--src/slave/ChangeLog5
-rw-r--r--src/slave/kpropd.c80
-rw-r--r--src/tests/create/ChangeLog4
-rw-r--r--src/tests/create/kdb5_mkdums.c36
-rw-r--r--src/tests/misc/test_nfold.c65
-rw-r--r--src/tests/verify/ChangeLog4
-rw-r--r--src/tests/verify/kdb5_verify.c8
-rw-r--r--src/util/profile/ChangeLog4
-rw-r--r--src/util/profile/Makefile.in5
-rw-r--r--src/util/profile/configure.in3
-rw-r--r--src/util/pty/ChangeLog4
-rw-r--r--src/util/pty/Makefile.in5
-rw-r--r--src/util/pty/configure.in2
-rw-r--r--src/util/ss/execute_cmd.c8
-rw-r--r--src/windows/lib/ChangeLog16
-rw-r--r--src/windows/lib/Makefile.in19
-rw-r--r--src/windows/lib/gic.c156
-rw-r--r--src/windows/lib/gic.h28
-rw-r--r--src/windows/lib/registry.c231
-rw-r--r--src/windows/lib/registry.h40
-rw-r--r--src/windows/lib/vardlg.c450
-rw-r--r--src/windows/lib/vardlg.h32
340 files changed, 11806 insertions, 15571 deletions
diff --git a/src/ChangeLog b/src/ChangeLog
index 2189342e5c..409a200cbf 100644
--- a/src/ChangeLog
+++ b/src/ChangeLog
@@ -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
diff --git a/src/aclocal.m4 b/src/aclocal.m4
index af2d8a9238..1bfd92606f 100644
--- a/src/aclocal.m4
+++ b/src/aclocal.m4
@@ -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 '
diff --git a/src/appl/bsd/ChangeLog b/src/appl/bsd/ChangeLog
index 6eaa52942e..8f7e9a8fc8 100644
--- a/src/appl/bsd/ChangeLog
+++ b/src/appl/bsd/ChangeLog
@@ -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
diff --git a/src/appl/bsd/kcmd.c b/src/appl/bsd/kcmd.c
index c6f21e02f2..f775719174 100644
--- a/src/appl/bsd/kcmd.c
+++ b/src/appl/bsd/kcmd.c
@@ -19,6 +19,32 @@
* 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);
}
diff --git a/src/appl/bsd/krlogin.c b/src/appl/bsd/krlogin.c
index 54d048b65a..0bfb3ef571 100644
--- a/src/appl/bsd/krlogin.c
+++ b/src/appl/bsd/krlogin.c
@@ -19,6 +19,32 @@
* 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:
diff --git a/src/appl/bsd/krlogind.c b/src/appl/bsd/krlogind.c
index bd376ff098..f433897190 100644
--- a/src/appl/bsd/krlogind.c
+++ b/src/appl/bsd/krlogind.c
@@ -19,6 +19,32 @@
* 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)))
diff --git a/src/appl/bsd/login.c b/src/appl/bsd/login.c
index cb18f4c2c5..c8017cc77b 100644
--- a/src/appl/bsd/login.c
+++ b/src/appl/bsd/login.c
@@ -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 */
-
/* UNIX password support */
struct passwd *pwd;
@@ -475,16 +480,19 @@ int unix_passwd_okay (pass)
#endif
return !strcmp (namep, pwd->pw_passwd);
}
-
+
/* 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 */
-
/* 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
}
-
+
/* 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
diff --git a/src/appl/gss-sample/ChangeLog b/src/appl/gss-sample/ChangeLog
index 476fb5bce1..bdf6e8d71a 100644
--- a/src/appl/gss-sample/ChangeLog
+++ b/src/appl/gss-sample/ChangeLog
@@ -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
diff --git a/src/appl/gss-sample/gss-client.c b/src/appl/gss-sample/gss-client.c
index e0bca99c46..33a7e963a3 100644
--- a/src/appl/gss-sample/gss-client.c
+++ b/src/appl/gss-sample/gss-client.c
@@ -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,
diff --git a/src/appl/gss-sample/gss-server.c b/src/appl/gss-sample/gss-server.c
index ef9d495820..3e9ff09592 100644
--- a/src/appl/gss-sample/gss-server.c
+++ b/src/appl/gss-sample/gss-server.c
@@ -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);
diff --git a/src/appl/gssftp/ftp/ChangeLog b/src/appl/gssftp/ftp/ChangeLog
index ed4aecb1a9..b021129b04 100644
--- a/src/appl/gssftp/ftp/ChangeLog
+++ b/src/appl/gssftp/ftp/ChangeLog
@@ -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.
diff --git a/src/appl/gssftp/ftp/ftp.c b/src/appl/gssftp/ftp/ftp.c
index f6fb156773..d19d62c206 100644
--- a/src/appl/gssftp/ftp/ftp.c
+++ b/src/appl/gssftp/ftp/ftp.c
@@ -31,6 +31,32 @@
* 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);
diff --git a/src/appl/telnet/libtelnet/ChangeLog b/src/appl/telnet/libtelnet/ChangeLog
index 494050438d..55168c36b3 100644
--- a/src/appl/telnet/libtelnet/ChangeLog
+++ b/src/appl/telnet/libtelnet/ChangeLog
@@ -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
diff --git a/src/appl/telnet/libtelnet/enc_des.c b/src/appl/telnet/libtelnet/enc_des.c
index f44700a731..3912b35e93 100644
--- a/src/appl/telnet/libtelnet/enc_des.c
+++ b/src/appl/telnet/libtelnet/enc_des.c
@@ -31,11 +31,38 @@
* 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 */
diff --git a/src/appl/telnet/libtelnet/kerberos.c b/src/appl/telnet/libtelnet/kerberos.c
index 63738b53bf..ed32392c9c 100644
--- a/src/appl/telnet/libtelnet/kerberos.c
+++ b/src/appl/telnet/libtelnet/kerberos.c
@@ -53,7 +53,38 @@
* 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>
@@ -73,6 +104,7 @@
#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;
diff --git a/src/appl/telnet/telnet/ChangeLog b/src/appl/telnet/telnet/ChangeLog
index 6d13e63f2c..7d94d0acf7 100644
--- a/src/appl/telnet/telnet/ChangeLog
+++ b/src/appl/telnet/telnet/ChangeLog
@@ -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
diff --git a/src/appl/telnet/telnet/commands.c b/src/appl/telnet/telnet/commands.c
index 5c8ae3cb72..c23e199cce 100644
--- a/src/appl/telnet/telnet/commands.c
+++ b/src/appl/telnet/telnet/commands.c
@@ -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;
diff --git a/src/clients/ChangeLog b/src/clients/ChangeLog
index 75b04852d1..e8390d6b21 100644
--- a/src/clients/ChangeLog
+++ b/src/clients/ChangeLog
@@ -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.
diff --git a/src/clients/Makefile.in b/src/clients/Makefile.in
index b793c04303..e772cf6b86 100644
--- a/src/clients/Makefile.in
+++ b/src/clients/Makefile.in
@@ -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
diff --git a/src/clients/configure.in b/src/clients/configure.in
index 4959bdebfa..db30b09c31 100644
--- a/src/clients/configure.in
+++ b/src/clients/configure.in
@@ -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)
diff --git a/src/clients/kinit/ChangeLog b/src/clients/kinit/ChangeLog
index 65bcc031eb..5bdf452576 100644
--- a/src/clients/kinit/ChangeLog
+++ b/src/clients/kinit/ChangeLog
@@ -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
diff --git a/src/clients/kinit/kinit.c b/src/clients/kinit/kinit.c
index 6f7b840c98..f02db2e186 100644
--- a/src/clients/kinit/kinit.c
+++ b/src/clients/kinit/kinit.c
@@ -24,43 +24,64 @@
* 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;
-}
diff --git a/src/clients/klist/ChangeLog b/src/clients/klist/ChangeLog
index 3150210e4c..20feffb355 100644
--- a/src/clients/klist/ChangeLog
+++ b/src/clients/klist/ChangeLog
@@ -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
diff --git a/src/clients/klist/klist.c b/src/clients/klist/klist.c
index 6d05f822d6..deb5f44bc2 100644
--- a/src/clients/klist/klist.c
+++ b/src/clients/klist/klist.c
@@ -30,11 +30,13 @@
#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;
diff --git a/src/include/ChangeLog b/src/include/ChangeLog
index b3c8848e00..d66def009e 100644
--- a/src/include/ChangeLog
+++ b/src/include/ChangeLog
@@ -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
diff --git a/src/include/k5-int.h b/src/include/k5-int.h
index db82e0266e..fa8824c49e 100644
--- a/src/include/k5-int.h
+++ b/src/include/k5-int.h
@@ -34,6 +34,33 @@
* 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 ** ));
diff --git a/src/include/kerberosIV/ChangeLog b/src/include/kerberosIV/ChangeLog
index 85f624b066..0ecf2b09e7 100644
--- a/src/include/kerberosIV/ChangeLog
+++ b/src/include/kerberosIV/ChangeLog
@@ -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
diff --git a/src/include/kerberosIV/krb_db.h b/src/include/kerberosIV/krb_db.h
index 4925137c43..dc2265d960 100644
--- a/src/include/kerberosIV/krb_db.h
+++ b/src/include/kerberosIV/krb_db.h
@@ -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 */
diff --git a/src/include/krb5.hin b/src/include/krb5.hin
index 9949524045..8b1d42f0d0 100644
--- a/src/include/krb5.hin
+++ b/src/include/krb5.hin
@@ -24,6 +24,32 @@
* 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
diff --git a/src/include/krb5/ChangeLog b/src/include/krb5/ChangeLog
index 202608002e..af894dad15 100644
--- a/src/include/krb5/ChangeLog
+++ b/src/include/krb5/ChangeLog
@@ -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()
diff --git a/src/include/krb5/kdb.h b/src/include/krb5/kdb.h
index 6a75372d11..65731279f7 100644
--- a/src/include/krb5/kdb.h
+++ b/src/include/krb5/kdb.h
@@ -24,6 +24,31 @@
* 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 *));
diff --git a/src/include/krb5/kdb_dbc.h b/src/include/krb5/kdb_dbc.h
index 3dfd0d8416..e0bbd1b476 100644
--- a/src/include/krb5/kdb_dbc.h
+++ b/src/include/krb5/kdb_dbc.h
@@ -24,6 +24,32 @@
* 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;
diff --git a/src/kadmin/cli/ChangeLog b/src/kadmin/cli/ChangeLog
index 9bf1d76f00..455733b5f1 100644
--- a/src/kadmin/cli/ChangeLog
+++ b/src/kadmin/cli/ChangeLog
@@ -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
diff --git a/src/kadmin/cli/keytab.c b/src/kadmin/cli/keytab.c
index df4f6ce257..8a474b92c3 100644
--- a/src/kadmin/cli/keytab.c
+++ b/src/kadmin/cli/keytab.c
@@ -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;
}
diff --git a/src/kadmin/dbutil/ChangeLog b/src/kadmin/dbutil/ChangeLog
index e6ab156f96..2f0c84e73e 100644
--- a/src/kadmin/dbutil/ChangeLog
+++ b/src/kadmin/dbutil/ChangeLog
@@ -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):
diff --git a/src/kadmin/dbutil/dumpv4.c b/src/kadmin/dbutil/dumpv4.c
index fd5d0b2f45..9eb203c3a4 100644
--- a/src/kadmin/dbutil/dumpv4.c
+++ b/src/kadmin/dbutil/dumpv4.c
@@ -24,6 +24,32 @@
* 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"
@@ -45,14 +71,13 @@
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;
diff --git a/src/kadmin/dbutil/kadm5_create.c b/src/kadmin/dbutil/kadm5_create.c
index b60ec9759e..9cedf30c4b 100644
--- a/src/kadmin/dbutil/kadm5_create.c
+++ b/src/kadmin/dbutil/kadm5_create.c
@@ -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;
diff --git a/src/kadmin/dbutil/kdb5_create.c b/src/kadmin/dbutil/kdb5_create.c
index 2e2c5f9126..5aa7ae11ed 100644
--- a/src/kadmin/dbutil/kdb5_create.c
+++ b/src/kadmin/dbutil/kdb5_create.c
@@ -24,6 +24,32 @@
* 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;
diff --git a/src/kadmin/dbutil/kdb5_stash.c b/src/kadmin/dbutil/kdb5_stash.c
index 40084e2bb4..c682f3a566 100644
--- a/src/kadmin/dbutil/kdb5_stash.c
+++ b/src/kadmin/dbutil/kdb5_stash.c
@@ -24,6 +24,32 @@
* 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;
diff --git a/src/kadmin/dbutil/kdb5_util.c b/src/kadmin/dbutil/kdb5_util.c
index ead82aa634..0a053c8c8e 100644
--- a/src/kadmin/dbutil/kdb5_util.c
+++ b/src/kadmin/dbutil/kdb5_util.c
@@ -24,6 +24,32 @@
* 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;
+}
diff --git a/src/kadmin/dbutil/loadv4.c b/src/kadmin/dbutil/loadv4.c
index 01a4bf2a6b..b7df142bd8 100644
--- a/src/kadmin/dbutil/loadv4.c
+++ b/src/kadmin/dbutil/loadv4.c
@@ -25,6 +25,32 @@
* 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;
diff --git a/src/kadmin/server/ChangeLog b/src/kadmin/server/ChangeLog
index 22f8214bd0..8131a8695c 100644
--- a/src/kadmin/server/ChangeLog
+++ b/src/kadmin/server/ChangeLog
@@ -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
diff --git a/src/kadmin/server/ovsec_kadmd.c b/src/kadmin/server/ovsec_kadmd.c
index 6ac8709c76..b8a5088d8e 100644
--- a/src/kadmin/server/ovsec_kadmd.c
+++ b/src/kadmin/server/ovsec_kadmd.c
@@ -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);
diff --git a/src/kadmin/v4server/ChangeLog b/src/kadmin/v4server/ChangeLog
index e64ee0e386..b00913cde9 100644
--- a/src/kadmin/v4server/ChangeLog
+++ b/src/kadmin/v4server/ChangeLog
@@ -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.
diff --git a/src/kadmin/v4server/acl_files.c b/src/kadmin/v4server/acl_files.c
index 35dd6608f1..22a0007de6 100644
--- a/src/kadmin/v4server/acl_files.c
+++ b/src/kadmin/v4server/acl_files.c
@@ -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++;
diff --git a/src/kadmin/v4server/admin_server.c b/src/kadmin/v4server/admin_server.c
index 9cd2f8fb51..90bf087c95 100644
--- a/src/kadmin/v4server/admin_server.c
+++ b/src/kadmin/v4server/admin_server.c
@@ -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);
diff --git a/src/kadmin/v4server/kadm_funcs.c b/src/kadmin/v4server/kadm_funcs.c
index 1d32073007..658d4b721c 100644
--- a/src/kadmin/v4server/kadm_funcs.c
+++ b/src/kadmin/v4server/kadm_funcs.c
@@ -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,
diff --git a/src/kadmin/v4server/kadm_ser_wrap.c b/src/kadmin/v4server/kadm_ser_wrap.c
index 2c5c8076c2..bca814d076 100644
--- a/src/kadmin/v4server/kadm_ser_wrap.c
+++ b/src/kadmin/v4server/kadm_ser_wrap.c
@@ -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,
diff --git a/src/kadmin/v4server/kadm_server.h b/src/kadmin/v4server/kadm_server.h
index e7a7fed272..f293273265 100644
--- a/src/kadmin/v4server/kadm_server.h
+++ b/src/kadmin/v4server/kadm_server.h
@@ -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;
diff --git a/src/kdc/ChangeLog b/src/kdc/ChangeLog
index 30cf89bdd6..757ac7dc58 100644
--- a/src/kdc/ChangeLog
+++ b/src/kdc/ChangeLog
@@ -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):
diff --git a/src/kdc/do_as_req.c b/src/kdc/do_as_req.c
index 22d5b1b563..b6fa39d3df 100644
--- a/src/kdc/do_as_req.c
+++ b/src/kdc/do_as_req.c
@@ -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);
diff --git a/src/kdc/do_tgs_req.c b/src/kdc/do_tgs_req.c
index ff6f214d3d..7faf748da3 100644
--- a/src/kdc/do_tgs_req.c
+++ b/src/kdc/do_tgs_req.c
@@ -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);
diff --git a/src/kdc/extern.h b/src/kdc/extern.h
index e8de8a7e32..c31e5c70e5 100644
--- a/src/kdc/extern.h
+++ b/src/kdc/extern.h
@@ -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
diff --git a/src/kdc/kdc_preauth.c b/src/kdc/kdc_preauth.c
index b88c772831..0324694a2e 100644
--- a/src/kdc/kdc_preauth.c
+++ b/src/kdc/kdc_preauth.c
@@ -23,6 +23,32 @@
* 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);
diff --git a/src/kdc/kdc_util.c b/src/kdc/kdc_util.c
index 863ffd19c9..51d4d7807e 100644
--- a/src/kdc/kdc_util.c
+++ b/src/kdc/kdc_util.c
@@ -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 */
diff --git a/src/kdc/kerberos_v4.c b/src/kdc/kerberos_v4.c
index f5a3a77895..a1efd8b375 100644
--- a/src/kdc/kerberos_v4.c
+++ b/src/kdc/kerberos_v4.c
@@ -65,10 +65,12 @@
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);
}
diff --git a/src/kdc/main.c b/src/kdc/main.c
index 4524c00f4e..a8f4233beb 100644
--- a/src/kdc/main.c
+++ b/src/kdc/main.c
@@ -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:
diff --git a/src/krb524/ChangeLog b/src/krb524/ChangeLog
index e68edba1fa..40ef10cd17 100644
--- a/src/krb524/ChangeLog
+++ b/src/krb524/ChangeLog
@@ -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
diff --git a/src/krb524/cnv_tkt_skey.c b/src/krb524/cnv_tkt_skey.c
index df270776ab..4c51b6777f 100644
--- a/src/krb524/cnv_tkt_skey.c
+++ b/src/krb524/cnv_tkt_skey.c
@@ -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;
diff --git a/src/krb524/krb524d.c b/src/krb524/krb524d.c
index f72726fff3..1afeec2dce 100644
--- a/src/krb524/krb524d.c
+++ b/src/krb524/krb524d.c
@@ -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);
}
diff --git a/src/lib/crypto/ChangeLog b/src/lib/crypto/ChangeLog
index dd0e7b5611..566afc88f3 100644
--- a/src/lib/crypto/ChangeLog
+++ b/src/lib/crypto/ChangeLog
@@ -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.
diff --git a/src/lib/crypto/Makefile.in b/src/lib/crypto/Makefile.in
index 468818cb80..48d035a78b 100644
--- a/src/lib/crypto/Makefile.in
+++ b/src/lib/crypto/Makefile.in
@@ -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
index 0000000000..de5c3ac89c
--- /dev/null
+++ b/src/lib/crypto/block_size.c
@@ -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
index 0000000000..38773cae01
--- /dev/null
+++ b/src/lib/crypto/checksum_length.c
@@ -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
index 0000000000..21cc5905f6
--- /dev/null
+++ b/src/lib/crypto/cksumtype_to_string.c
@@ -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
index 0000000000..8107d3b8f7
--- /dev/null
+++ b/src/lib/crypto/cksumtypes.c
@@ -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
index 0000000000..900a7c8914
--- /dev/null
+++ b/src/lib/crypto/cksumtypes.h
@@ -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
index 0000000000..07925c641a
--- /dev/null
+++ b/src/lib/crypto/coll_proof_cksum.c
@@ -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);
+}
diff --git a/src/lib/crypto/configure.in b/src/lib/crypto/configure.in
index 19688e35e6..2fb1faffbf 100644
--- a/src/lib/crypto/configure.in
+++ b/src/lib/crypto/configure.in
@@ -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
diff --git a/src/lib/crypto/crc32/ChangeLog b/src/lib/crypto/crc32/ChangeLog
index 1ee004262c..5f6e617cb9 100644
--- a/src/lib/crypto/crc32/ChangeLog
+++ b/src/lib/crypto/crc32/ChangeLog
@@ -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
diff --git a/src/lib/crypto/crc32/Makefile.in b/src/lib/crypto/crc32/Makefile.in
index b1ad86bdd8..97ab64cf04 100644
--- a/src/lib/crypto/crc32/Makefile.in
+++ b/src/lib/crypto/crc32/Makefile.in
@@ -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
diff --git a/src/lib/crypto/crc32/crc-32.h b/src/lib/crypto/crc32/crc-32.h
index 28d0dc4519..1b05b9ac6a 100644
--- a/src/lib/crypto/crc32/crc-32.h
+++ b/src/lib/crypto/crc32/crc-32.h
@@ -24,11 +24,41 @@
* 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
index 0000000000..654981fc9f
--- /dev/null
+++ b/src/lib/crypto/crc32/crc32.c
@@ -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
index 62be745812..0000000000
--- a/src/lib/crypto/cryptoconf.c
+++ /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
index 0000000000..0d66ec0c0e
--- /dev/null
+++ b/src/lib/crypto/decrypt.c
@@ -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
index ae886d0c9d..0000000000
--- a/src/lib/crypto/decrypt_data.c
+++ /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
index b886964867..0000000000
--- a/src/lib/crypto/des/.rconf
+++ /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
diff --git a/src/lib/crypto/des/ChangeLog b/src/lib/crypto/des/ChangeLog
index e236a9cb96..70c431aa5c 100644
--- a/src/lib/crypto/des/ChangeLog
+++ b/src/lib/crypto/des/ChangeLog
@@ -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
index 7ed082e32d..0000000000
--- a/src/lib/crypto/des/FUNCTIONS
+++ /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
diff --git a/src/lib/crypto/des/Makefile.in b/src/lib/crypto/des/Makefile.in
index 3f9311b96e..fdef9e869a 100644
--- a/src/lib/crypto/des/Makefile.in
+++ b/src/lib/crypto/des/Makefile.in
@@ -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
diff --git a/src/lib/crypto/des/afsstring2key.c b/src/lib/crypto/des/afsstring2key.c
index 36c42c4823..7eac0807c2 100644
--- a/src/lib/crypto/des/afsstring2key.c
+++ b/src/lib/crypto/des/afsstring2key.c
@@ -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
index 29a38a0a59..0000000000
--- a/src/lib/crypto/des/cbc_cksum.c
+++ /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
index 306f97dd60..0000000000
--- a/src/lib/crypto/des/d3_ecb.c
+++ /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
index 9c969a823b..0000000000
--- a/src/lib/crypto/des/d3_procky.c
+++ /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
index ed9f5183d2..0000000000
--- a/src/lib/crypto/des/d3_str2ky.c
+++ /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
index bd0a30b370..0000000000
--- a/src/lib/crypto/des/des.h
+++ /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 */
diff --git a/src/lib/crypto/des/des_int.h b/src/lib/crypto/des/des_int.h
index df8e9ca1ed..0f81908615 100644
--- a/src/lib/crypto/des/des_int.h
+++ b/src/lib/crypto/des/des_int.h
@@ -24,6 +24,32 @@
* 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));
diff --git a/src/lib/crypto/des/destest.c b/src/lib/crypto/des/destest.c
index 1e077a4239..bf442e8698 100644
--- a/src/lib/crypto/des/destest.c
+++ b/src/lib/crypto/des/destest.c
@@ -25,20 +25,43 @@
*/
-#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
index 0d381e3739..0000000000
--- a/src/lib/crypto/des/f_README
+++ /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
index a1d1dcb0c7..0000000000
--- a/src/lib/crypto/des/f_ecb.c
+++ /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
index cb445446b9..0000000000
--- a/src/lib/crypto/des/f_pcbc.c
+++ /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
index 7b8a2c385c..0000000000
--- a/src/lib/crypto/des/fin_rndkey.c
+++ /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
index e7e9e13ae3..0000000000
--- a/src/lib/crypto/des/finish_key.c
+++ /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
index 5096647ec6..0000000000
--- a/src/lib/crypto/des/init_rkey.c
+++ /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
index 64cef57ad6..0000000000
--- a/src/lib/crypto/des/process_ky.c
+++ /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
index 1dc4600b4f..0000000000
--- a/src/lib/crypto/des/random_key.c
+++ /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;
- }
-}
diff --git a/src/lib/crypto/des/string2key.c b/src/lib/crypto/des/string2key.c
index 8a2b1415b7..79b7c9cbd8 100644
--- a/src/lib/crypto/des/string2key.c
+++ b/src/lib/crypto/des/string2key.c
@@ -21,6 +21,32 @@
* 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
index bc013bdab7..0000000000
--- a/src/lib/crypto/des/t_random.c
+++ /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);
-}
-
diff --git a/src/lib/crypto/des/t_verify.c b/src/lib/crypto/des/t_verify.c
index 82a73e21fb..e8a7dc0eed 100644
--- a/src/lib/crypto/des/t_verify.c
+++ b/src/lib/crypto/des/t_verify.c
@@ -28,13 +28,37 @@
* -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
index 6da58cbef3..0000000000
--- a/src/lib/crypto/des/u_nfold.c
+++ /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
index 44d3c73839..0000000000
--- a/src/lib/crypto/des/u_rn_key.c
+++ /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
index 62e3d724dc..0000000000
--- a/src/lib/crypto/des3_raw.c
+++ /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
index 9b060e5899..0000000000
--- a/src/lib/crypto/des3_sha.c
+++ /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
index 6317f61d7a..0000000000
--- a/src/lib/crypto/des_crc.c
+++ /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
index 6794f568f6..0000000000
--- a/src/lib/crypto/des_md5.c
+++ /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
index 0000000000..76b8c84031
--- /dev/null
+++ b/src/lib/crypto/encrypt.c
@@ -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
index b2f039f339..0000000000
--- a/src/lib/crypto/encrypt_data.c
+++ /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
index 0000000000..005b2211da
--- /dev/null
+++ b/src/lib/crypto/encrypt_length.c
@@ -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
index 0000000000..8972589685
--- /dev/null
+++ b/src/lib/crypto/enctype_compare.c
@@ -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
index 0000000000..2c25a52510
--- /dev/null
+++ b/src/lib/crypto/enctype_to_string.c
@@ -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
index 0000000000..cebb5bda5a
--- /dev/null
+++ b/src/lib/crypto/etypes.c
@@ -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
index 0000000000..53d8b655af
--- /dev/null
+++ b/src/lib/crypto/etypes.h
@@ -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
index 0000000000..7cf11a6c70
--- /dev/null
+++ b/src/lib/crypto/hmac.c
@@ -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
index 0000000000..cf0b736f2f
--- /dev/null
+++ b/src/lib/crypto/keyed_checksum_types.c
@@ -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
index 0000000000..0ff6d3e38c
--- /dev/null
+++ b/src/lib/crypto/keyed_cksum.c
@@ -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
index 3b26aed18c..0000000000
--- a/src/lib/crypto/krb5_glue.c
+++ /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
index 0000000000..b2faef191f
--- /dev/null
+++ b/src/lib/crypto/make_checksum.c
@@ -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
index 0000000000..391f56dfc2
--- /dev/null
+++ b/src/lib/crypto/make_random_key.c
@@ -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
index de30fd8c9c..0000000000
--- a/src/lib/crypto/md4/.rconf
+++ /dev/null
@@ -1,2 +0,0 @@
-ignore RFC1186.TXT
-ignore RFC1186B.TXT
diff --git a/src/lib/crypto/md4/ChangeLog b/src/lib/crypto/md4/ChangeLog
index 3ca8c08728..7714d4a43f 100644
--- a/src/lib/crypto/md4/ChangeLog
+++ b/src/lib/crypto/md4/ChangeLog
@@ -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
diff --git a/src/lib/crypto/md4/Makefile.in b/src/lib/crypto/md4/Makefile.in
index 739b34b84c..be6baebb01 100644
--- a/src/lib/crypto/md4/Makefile.in
+++ b/src/lib/crypto/md4/Makefile.in
@@ -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
index eac9647f2d..0000000000
--- a/src/lib/crypto/md4/md4crypto.c
+++ /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
index 425ef2954a..0000000000
--- a/src/lib/crypto/md4/md4driver.c
+++ /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
index f7e566e9b2..0000000000
--- a/src/lib/crypto/md4/md4glue.c
+++ /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 */
-};
diff --git a/src/lib/crypto/md5/ChangeLog b/src/lib/crypto/md5/ChangeLog
index 1c0026add4..79fb94a7dd 100644
--- a/src/lib/crypto/md5/ChangeLog
+++ b/src/lib/crypto/md5/ChangeLog
@@ -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
diff --git a/src/lib/crypto/md5/Makefile.in b/src/lib/crypto/md5/Makefile.in
index 3707f897b8..219fa3081a 100644
--- a/src/lib/crypto/md5/Makefile.in
+++ b/src/lib/crypto/md5/Makefile.in
@@ -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
index b83e50e77b..0000000000
--- a/src/lib/crypto/md5/md5crypto.c
+++ /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
index 66d5aa7917..0000000000
--- a/src/lib/crypto/md5/md5glue.c
+++ /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
index 5bc63709d2..0000000000
--- a/src/lib/crypto/md5/t_cksum.c
+++ /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
index 0000000000..07c539ebea
--- /dev/null
+++ b/src/lib/crypto/nfold.c
@@ -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
index 0000000000..64be9b8891
--- /dev/null
+++ b/src/lib/crypto/old_api_glue.c
@@ -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
index 2e24ee69f4..0000000000
--- a/src/lib/crypto/os/.Sanitize
+++ /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
index ebcb593a1b..0000000000
--- a/src/lib/crypto/os/ChangeLog
+++ /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
index d4c5f41416..0000000000
--- a/src/lib/crypto/os/Makefile.in
+++ /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
index 3b3bcb474f..0000000000
--- a/src/lib/crypto/os/c_localaddr.c
+++ /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
index e904cb5c7a..0000000000
--- a/src/lib/crypto/os/rnd_confoun.c
+++ /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
index 0000000000..2d4f6647d4
--- /dev/null
+++ b/src/lib/crypto/prng.c
@@ -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
index 65e0ebdbbd..0000000000
--- a/src/lib/crypto/raw_des.c
+++ /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
index 886bb2b0a3..0000000000
--- a/src/lib/crypto/sha/.Sanitize
+++ /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
index 19abbbf6ed..0000000000
--- a/src/lib/crypto/sha/ChangeLog
+++ /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
index 058ac0db00..0000000000
--- a/src/lib/crypto/sha/Makefile.in
+++ /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
index d57092e69a..0000000000
--- a/src/lib/crypto/sha/hmac_sha.c
+++ /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
index b539b1199f..0000000000
--- a/src/lib/crypto/sha/sha_crypto.c
+++ /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
index 58a93b7230..0000000000
--- a/src/lib/crypto/sha/sha_glue.c
+++ /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
index e18f3af9e2..0000000000
--- a/src/lib/crypto/sha/shs.c
+++ /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
index 01acddb825..0000000000
--- a/src/lib/crypto/sha/shs.h
+++ /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
index da55992ec9..0000000000
--- a/src/lib/crypto/sha/t_shs.c
+++ /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
index 0000000000..fe46e8a9be
--- /dev/null
+++ b/src/lib/crypto/string_to_cksumtype.c
@@ -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
index 0000000000..8d3e6a37e2
--- /dev/null
+++ b/src/lib/crypto/string_to_enctype.c
@@ -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
index 0000000000..a569e4954c
--- /dev/null
+++ b/src/lib/crypto/string_to_key.c
@@ -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
index 0000000000..2693318e14
--- /dev/null
+++ b/src/lib/crypto/t_nfold.c
@@ -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
index 0000000000..24108a3eca
--- /dev/null
+++ b/src/lib/crypto/valid_cksumtype.c
@@ -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
index 0000000000..03944c068c
--- /dev/null
+++ b/src/lib/crypto/valid_enctype.c
@@ -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
index 0000000000..f2749c8dea
--- /dev/null
+++ b/src/lib/crypto/verify_checksum.c
@@ -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);
+}
diff --git a/src/lib/des425/ChangeLog b/src/lib/des425/ChangeLog
index ce04691e95..4eeef10287 100644
--- a/src/lib/des425/ChangeLog
+++ b/src/lib/des425/ChangeLog
@@ -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>
diff --git a/src/lib/des425/Makefile.in b/src/lib/des425/Makefile.in
index 541a516e61..e96e03f999 100644
--- a/src/lib/des425/Makefile.in
+++ b/src/lib/des425/Makefile.in
@@ -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 \
diff --git a/src/lib/des425/new_rnd_key.c b/src/lib/des425/new_rnd_key.c
index 943b9e03b5..4dd2e4be76 100644
--- a/src/lib/des425/new_rnd_key.c
+++ b/src/lib/des425/new_rnd_key.c
@@ -23,35 +23,34 @@
*
*/
-
-#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);
-}
diff --git a/src/lib/des425/random_key.c b/src/lib/des425/random_key.c
index 04399c1f05..fde324dece 100644
--- a/src/lib/des425/random_key.c
+++ b/src/lib/des425/random_key.c
@@ -23,39 +23,48 @@
*
*/
+/*
+ * 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);
}
diff --git a/src/lib/gssapi/Makefile.in b/src/lib/gssapi/Makefile.in
index 6835596f79..8432071335 100644
--- a/src/lib/gssapi/Makefile.in
+++ b/src/lib/gssapi/Makefile.in
@@ -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=\
diff --git a/src/lib/gssapi/generic/ChangeLog b/src/lib/gssapi/generic/ChangeLog
index 74f13a4a3e..601ca76f6b 100644
--- a/src/lib/gssapi/generic/ChangeLog
+++ b/src/lib/gssapi/generic/ChangeLog
@@ -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"
diff --git a/src/lib/gssapi/generic/gssapi.hin b/src/lib/gssapi/generic/gssapi.hin
index d00e19ab94..a30b794311 100644
--- a/src/lib/gssapi/generic/gssapi.hin
+++ b/src/lib/gssapi/generic/gssapi.hin
@@ -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))
diff --git a/src/lib/gssapi/generic/gssapi_err_generic.et b/src/lib/gssapi/generic/gssapi_err_generic.et
index ddeed4227e..99ba45fe38 100644
--- a/src/lib/gssapi/generic/gssapi_err_generic.et
+++ b/src/lib/gssapi/generic/gssapi_err_generic.et
@@ -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
diff --git a/src/lib/gssapi/generic/util_token.c b/src/lib/gssapi/generic/util_token.c
index 627b5011bc..9e186a1538 100644
--- a/src/lib/gssapi/generic/util_token.c
+++ b/src/lib/gssapi/generic/util_token.c
@@ -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;
diff --git a/src/lib/gssapi/krb5/ChangeLog b/src/lib/gssapi/krb5/ChangeLog
index a94aeb72d4..e12dfdb2b3 100644
--- a/src/lib/gssapi/krb5/ChangeLog
+++ b/src/lib/gssapi/krb5/ChangeLog
@@ -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
diff --git a/src/lib/gssapi/krb5/Makefile.in b/src/lib/gssapi/krb5/Makefile.in
index 5b74b81d99..00b575c34f 100644
--- a/src/lib/gssapi/krb5/Makefile.in
+++ b/src/lib/gssapi/krb5/Makefile.in
@@ -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 \
diff --git a/src/lib/gssapi/krb5/accept_sec_context.c b/src/lib/gssapi/krb5/accept_sec_context.c
index ee204d3e0a..90e988ae05 100644
--- a/src/lib/gssapi/krb5/accept_sec_context.c
+++ b/src/lib/gssapi/krb5/accept_sec_context.c
@@ -20,6 +20,32 @@
* 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);
diff --git a/src/lib/gssapi/krb5/acquire_cred.c b/src/lib/gssapi/krb5/acquire_cred.c
index 1ca1bf31a7..f968b7d4f6 100644
--- a/src/lib/gssapi/krb5/acquire_cred.c
+++ b/src/lib/gssapi/krb5/acquire_cred.c
@@ -20,6 +20,32 @@
* 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
index 0000000000..2a6fdb47b5
--- /dev/null
+++ b/src/lib/gssapi/krb5/add_cred.c
@@ -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);
+}
diff --git a/src/lib/gssapi/krb5/canon_name.c b/src/lib/gssapi/krb5/canon_name.c
index 652745c7b8..688366e1f9 100644
--- a/src/lib/gssapi/krb5/canon_name.c
+++ b/src/lib/gssapi/krb5/canon_name.c
@@ -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));
}
diff --git a/src/lib/gssapi/krb5/delete_sec_context.c b/src/lib/gssapi/krb5/delete_sec_context.c
index 16964995a7..28c2358906 100644
--- a/src/lib/gssapi/krb5/delete_sec_context.c
+++ b/src/lib/gssapi/krb5/delete_sec_context.c
@@ -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);
diff --git a/src/lib/gssapi/krb5/disp_status.c b/src/lib/gssapi/krb5/disp_status.c
index 4dc13843ce..3a6ba7b1ae 100644
--- a/src/lib/gssapi/krb5/disp_status.c
+++ b/src/lib/gssapi/krb5/disp_status.c
@@ -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,
diff --git a/src/lib/gssapi/krb5/gssapiP_krb5.h b/src/lib/gssapi/krb5/gssapiP_krb5.h
index 11b7c50f44..bcbde38943 100644
--- a/src/lib/gssapi/krb5/gssapiP_krb5.h
+++ b/src/lib/gssapi/krb5/gssapiP_krb5.h
@@ -68,8 +68,17 @@
((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
diff --git a/src/lib/gssapi/krb5/gssapi_err_krb5.et b/src/lib/gssapi/krb5/gssapi_err_krb5.et
index 54a126518b..3c9be6351f 100644
--- a/src/lib/gssapi/krb5/gssapi_err_krb5.et
+++ b/src/lib/gssapi/krb5/gssapi_err_krb5.et
@@ -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
diff --git a/src/lib/gssapi/krb5/gssapi_krb5.c b/src/lib/gssapi/krb5/gssapi_krb5.c
index c0942c39a6..aaa47ea065 100644
--- a/src/lib/gssapi/krb5/gssapi_krb5.c
+++ b/src/lib/gssapi/krb5/gssapi_krb5.c
@@ -21,6 +21,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.
+ */
+
+/*
* $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;
diff --git a/src/lib/gssapi/krb5/gssapi_krb5.h b/src/lib/gssapi/krb5/gssapi_krb5.h
index 63ac530f31..e4eccbb429 100644
--- a/src/lib/gssapi/krb5/gssapi_krb5.h
+++ b/src/lib/gssapi/krb5/gssapi_krb5.h
@@ -32,9 +32,12 @@
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;
diff --git a/src/lib/gssapi/krb5/init_sec_context.c b/src/lib/gssapi/krb5/init_sec_context.c
index 50855b58cf..4ff2085b4f 100644
--- a/src/lib/gssapi/krb5/init_sec_context.c
+++ b/src/lib/gssapi/krb5/init_sec_context.c
@@ -20,6 +20,32 @@
* 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>
@@ -33,8 +59,257 @@
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);
}
diff --git a/src/lib/gssapi/krb5/inq_cred.c b/src/lib/gssapi/krb5/inq_cred.c
index ee5d436c19..c800012c84 100644
--- a/src/lib/gssapi/krb5/inq_cred.c
+++ b/src/lib/gssapi/krb5/inq_cred.c
@@ -20,6 +20,32 @@
* 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);
}
diff --git a/src/lib/gssapi/krb5/inq_names.c b/src/lib/gssapi/krb5/inq_names.c
index 9c5f474509..01a1994301 100644
--- a/src/lib/gssapi/krb5/inq_names.c
+++ b/src/lib/gssapi/krb5/inq_names.c
@@ -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 */
diff --git a/src/lib/gssapi/krb5/k5seal.c b/src/lib/gssapi/krb5/k5seal.c
index c174bb7cbf..e1877b71f9 100644
--- a/src/lib/gssapi/krb5/k5seal.c
+++ b/src/lib/gssapi/krb5/k5seal.c
@@ -20,15 +20,269 @@
* 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;
diff --git a/src/lib/gssapi/krb5/k5unseal.c b/src/lib/gssapi/krb5/k5unseal.c
index 041cae06a3..c32e3255d5 100644
--- a/src/lib/gssapi/krb5/k5unseal.c
+++ b/src/lib/gssapi/krb5/k5unseal.c
@@ -20,6 +20,32 @@
* 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>
@@ -27,34 +53,417 @@
* $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);
+}
diff --git a/src/lib/gssapi/krb5/rel_oid.c b/src/lib/gssapi/krb5/rel_oid.c
index f35727e3f1..afb2171b86 100644
--- a/src/lib/gssapi/krb5/rel_oid.c
+++ b/src/lib/gssapi/krb5/rel_oid.c
@@ -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)) {
diff --git a/src/lib/gssapi/krb5/ser_sctx.c b/src/lib/gssapi/krb5/ser_sctx.c
index 36e70d742c..36a16d426e 100644
--- a/src/lib/gssapi/krb5/ser_sctx.c
+++ b/src/lib/gssapi/krb5/ser_sctx.c
@@ -40,192 +40,6 @@
* 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)
diff --git a/src/lib/gssapi/krb5/util_cksum.c b/src/lib/gssapi/krb5/util_cksum.c
index 68561f10b3..10e6b657fd 100644
--- a/src/lib/gssapi/krb5/util_cksum.c
+++ b/src/lib/gssapi/krb5/util_cksum.c
@@ -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);
}
diff --git a/src/lib/gssapi/krb5/util_crypt.c b/src/lib/gssapi/krb5/util_crypt.c
index 1684377ad6..93d46946c1 100644
--- a/src/lib/gssapi/krb5/util_crypt.c
+++ b/src/lib/gssapi/krb5/util_crypt.c
@@ -20,6 +20,32 @@
* 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>
@@ -31,103 +57,126 @@
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
index 0000000000..0add6bf73f
--- /dev/null
+++ b/src/lib/gssapi/krb5/util_ctxsetup.c
@@ -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;
+}
+
diff --git a/src/lib/gssapi/krb5/util_seed.c b/src/lib/gssapi/krb5/util_seed.c
index 14f3652452..206ee68a7b 100644
--- a/src/lib/gssapi/krb5/util_seed.c
+++ b/src/lib/gssapi/krb5/util_seed.c
@@ -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);
}
diff --git a/src/lib/gssapi/krb5/util_seqnum.c b/src/lib/gssapi/krb5/util_seqnum.c
index ed9293f778..e14b2f3fec 100644
--- a/src/lib/gssapi/krb5/util_seqnum.c
+++ b/src/lib/gssapi/krb5/util_seqnum.c
@@ -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]) ||
diff --git a/src/lib/gssapi/krb5/wrap_size_limit.c b/src/lib/gssapi/krb5/wrap_size_limit.c
index f2366d16e2..7459492609 100644
--- a/src/lib/gssapi/krb5/wrap_size_limit.c
+++ b/src/lib/gssapi/krb5/wrap_size_limit.c
@@ -20,6 +20,32 @@
* 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);
}
diff --git a/src/lib/kadm5/ChangeLog b/src/lib/kadm5/ChangeLog
index ae8bb7e1b1..64dc648d6c 100644
--- a/src/lib/kadm5/ChangeLog
+++ b/src/lib/kadm5/ChangeLog
@@ -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
diff --git a/src/lib/kadm5/alt_prof.c b/src/lib/kadm5/alt_prof.c
index b2260d67a8..934785322b 100644
--- a/src/lib/kadm5/alt_prof.c
+++ b/src/lib/kadm5/alt_prof.c
@@ -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 */
diff --git a/src/lib/kadm5/clnt/ChangeLog b/src/lib/kadm5/clnt/ChangeLog
index e1e761ce53..5f46d21854 100644
--- a/src/lib/kadm5/clnt/ChangeLog
+++ b/src/lib/kadm5/clnt/ChangeLog
@@ -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):
diff --git a/src/lib/kadm5/clnt/Makefile.in b/src/lib/kadm5/clnt/Makefile.in
index 662bc76019..b125ea7a1a 100644
--- a/src/lib/kadm5/clnt/Makefile.in
+++ b/src/lib/kadm5/clnt/Makefile.in
@@ -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=\
diff --git a/src/lib/kadm5/clnt/client_init.c b/src/lib/kadm5/clnt/client_init.c
index 11cd77c748..96c5907af7 100644
--- a/src/lib/kadm5/clnt/client_init.c
+++ b/src/lib/kadm5/clnt/client_init.c
@@ -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 */
diff --git a/src/lib/kadm5/srv/ChangeLog b/src/lib/kadm5/srv/ChangeLog
index 04011541b1..67dbe38429 100644
--- a/src/lib/kadm5/srv/ChangeLog
+++ b/src/lib/kadm5/srv/ChangeLog
@@ -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):
diff --git a/src/lib/kadm5/srv/Makefile.in b/src/lib/kadm5/srv/Makefile.in
index ff6552bd72..53e4698635 100644
--- a/src/lib/kadm5/srv/Makefile.in
+++ b/src/lib/kadm5/srv/Makefile.in
@@ -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=\
diff --git a/src/lib/kadm5/srv/server_kdb.c b/src/lib/kadm5/srv/server_kdb.c
index 1a900a380f..2487f88e02 100644
--- a/src/lib/kadm5/srv/server_kdb.c
+++ b/src/lib/kadm5/srv/server_kdb.c
@@ -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:
diff --git a/src/lib/kadm5/srv/svr_principal.c b/src/lib/kadm5/srv/svr_principal.c
index ee45723a47..9504556ffb 100644
--- a/src/lib/kadm5/srv/svr_principal.c
+++ b/src/lib/kadm5/srv/svr_principal.c
@@ -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;
diff --git a/src/lib/kdb/ChangeLog b/src/lib/kdb/ChangeLog
index ec0b38457c..e12270d5c8 100644
--- a/src/lib/kdb/ChangeLog
+++ b/src/lib/kdb/ChangeLog
@@ -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
diff --git a/src/lib/kdb/Makefile.in b/src/lib/kdb/Makefile.in
index 9ec4b23d48..c44b58631d 100644
--- a/src/lib/kdb/Makefile.in
+++ b/src/lib/kdb/Makefile.in
@@ -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)
diff --git a/src/lib/kdb/decrypt_key.c b/src/lib/kdb/decrypt_key.c
index 2aa199ac7e..0cfdbda8e0 100644
--- a/src/lib/kdb/decrypt_key.c
+++ b/src/lib/kdb/decrypt_key.c
@@ -24,6 +24,32 @@
* 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"
/*
@@ -33,40 +59,53 @@
*/
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;
}
diff --git a/src/lib/kdb/encrypt_key.c b/src/lib/kdb/encrypt_key.c
index ea7d17ca78..7bcfe11eb1 100644
--- a/src/lib/kdb/encrypt_key.c
+++ b/src/lib/kdb/encrypt_key.c
@@ -24,6 +24,32 @@
* 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"
/*
@@ -33,10 +59,10 @@
*/
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;
}
diff --git a/src/lib/kdb/fetch_mkey.c b/src/lib/kdb/fetch_mkey.c
index 5eda4eae6b..829e0283cd 100644
--- a/src/lib/kdb/fetch_mkey.c
+++ b/src/lib/kdb/fetch_mkey.c
@@ -25,6 +25,32 @@
* 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);
diff --git a/src/lib/kdb/kdb_cpw.c b/src/lib/kdb/kdb_cpw.c
index ec7419e1c6..d68d784c19 100644
--- a/src/lib/kdb/kdb_cpw.c
+++ b/src/lib/kdb/kdb_cpw.c
@@ -22,6 +22,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 "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;
diff --git a/src/lib/kdb/kdb_db2.c b/src/lib/kdb/kdb_db2.c
index 80c9213dd3..ab4d07e231 100644
--- a/src/lib/kdb/kdb_db2.c
+++ b/src/lib/kdb/kdb_db2.c
@@ -22,6 +22,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.
+ */
+
#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;
}
diff --git a/src/lib/kdb/kdb_db2.h b/src/lib/kdb/kdb_db2.h
index d17fde4769..f2f01311e7 100644
--- a/src/lib/kdb/kdb_db2.h
+++ b/src/lib/kdb/kdb_db2.h
@@ -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
diff --git a/src/lib/kdb/kdb_dbm.c b/src/lib/kdb/kdb_dbm.c
index 1ae241dfa0..7af32d720b 100644
--- a/src/lib/kdb/kdb_dbm.c
+++ b/src/lib/kdb/kdb_dbm.c
@@ -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;
}
diff --git a/src/lib/kdb/kdb_xdr.c b/src/lib/kdb/kdb_xdr.c
index 209e4f3ca9..a26b7f79da 100644
--- a/src/lib/kdb/kdb_xdr.c
+++ b/src/lib/kdb/kdb_xdr.c
@@ -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) {
diff --git a/src/lib/kdb/keytab.c b/src/lib/kdb/keytab.c
index 9c184b5148..63a7bf7c88 100644
--- a/src/lib/kdb/keytab.c
+++ b/src/lib/kdb/keytab.c
@@ -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;
diff --git a/src/lib/kdb/verify_mky.c b/src/lib/kdb/verify_mky.c
index 121c721488..4bab17024e 100644
--- a/src/lib/kdb/verify_mky.c
+++ b/src/lib/kdb/verify_mky.c
@@ -29,16 +29,13 @@
/*
* 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);
diff --git a/src/lib/krb4/ChangeLog b/src/lib/krb4/ChangeLog
index 54e185d2ec..0162fc450f 100644
--- a/src/lib/krb4/ChangeLog
+++ b/src/lib/krb4/ChangeLog
@@ -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
diff --git a/src/lib/krb4/Makefile.in b/src/lib/krb4/Makefile.in
index f75a6327bf..af2dca43c5 100644
--- a/src/lib/krb4/Makefile.in
+++ b/src/lib/krb4/Makefile.in
@@ -8,7 +8,7 @@ DEFINES=-I$(srcdir)/../../include/kerberosIV
##DOS##OBJFILE=krb4.lst
LIB=krb4
-LIBMAJOR=1
+LIBMAJOR=2
LIBMINOR=0
RELDIR=krb4
diff --git a/src/lib/krb4/cr_tkt.c b/src/lib/krb4/cr_tkt.c
index 39ed53859c..a8224f879a 100644
--- a/src/lib/krb4/cr_tkt.c
+++ b/src/lib/krb4/cr_tkt.c
@@ -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
@@ -69,9 +69,53 @@
* <=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;
}
diff --git a/src/lib/krb4/decomp_tkt.c b/src/lib/krb4/decomp_tkt.c
index 3c59523687..d4dfd4edcb 100644
--- a/src/lib/krb4/decomp_tkt.c
+++ b/src/lib/krb4/decomp_tkt.c
@@ -13,6 +13,7 @@
#include "krb.h"
#include "prot.h"
#include <string.h>
+#include <krb5.h>
#ifdef KRB_CRYPT_DEBUG
extern int krb_debug;
@@ -65,6 +66,57 @@ decomp_ticket(tkt, flags, pname, pinstance, prealm, paddress, session,
* (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;
char *ptr = (char *)tkt->dat;
@@ -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) {
diff --git a/src/lib/krb4/rd_req.c b/src/lib/krb4/rd_req.c
index 79564e4f37..a78aadc881 100644
--- a/src/lib/krb4/rd_req.c
+++ b/src/lib/krb4/rd_req.c
@@ -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.");
diff --git a/src/lib/krb4/tf_util.c b/src/lib/krb4/tf_util.c
index b3eb0b43a9..1c7aadd9fa 100644
--- a/src/lib/krb4/tf_util.c
+++ b/src/lib/krb4/tf_util.c
@@ -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];
diff --git a/src/lib/krb5/ChangeLog b/src/lib/krb5/ChangeLog
index f7922150e9..f1e1e81f93 100644
--- a/src/lib/krb5/ChangeLog
+++ b/src/lib/krb5/ChangeLog
@@ -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):
diff --git a/src/lib/krb5/Makefile.in b/src/lib/krb5/Makefile.in
index 4864a2f94f..12ce18512b 100644
--- a/src/lib/krb5/Makefile.in
+++ b/src/lib/krb5/Makefile.in
@@ -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 \
diff --git a/src/lib/krb5/asn.1/ChangeLog b/src/lib/krb5/asn.1/ChangeLog
index a42ad235c3..ca3f679f50 100644
--- a/src/lib/krb5/asn.1/ChangeLog
+++ b/src/lib/krb5/asn.1/ChangeLog
@@ -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
diff --git a/src/lib/krb5/asn.1/asn1buf.c b/src/lib/krb5/asn.1/asn1buf.c
index 30dad8b491..52ac387d50 100644
--- a/src/lib/krb5/asn.1/asn1buf.c
+++ b/src/lib/krb5/asn.1/asn1buf.c
@@ -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)
diff --git a/src/lib/krb5/ccache/ChangeLog b/src/lib/krb5/ccache/ChangeLog
index 2a4d39551d..71aa06dc82 100644
--- a/src/lib/krb5/ccache/ChangeLog
+++ b/src/lib/krb5/ccache/ChangeLog
@@ -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
index e47ded4432..0000000000
--- a/src/lib/krb5/ccache/ccapi/Makefile.in
+++ /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
index 2b9007bf81..0000000000
--- a/src/lib/krb5/ccache/ccapi/stdcc.c
+++ /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
index c157770c49..0000000000
--- a/src/lib/krb5/ccache/ccapi/stdcc.h
+++ /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
index 4f4fcfc50a..0000000000
--- a/src/lib/krb5/ccache/ccapi/stdcc_util.c
+++ /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
index 7d0af3dcb4..0000000000
--- a/src/lib/krb5/ccache/ccapi/stdcc_util.h
+++ /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
-
diff --git a/src/lib/krb5/ccache/ccbase.c b/src/lib/krb5/ccache/ccbase.c
index 4570f8053c..ae89334a0f 100644
--- a/src/lib/krb5/ccache/ccbase.c
+++ b/src/lib/krb5/ccache/ccbase.c
@@ -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
diff --git a/src/lib/krb5/configure.in b/src/lib/krb5/configure.in
index 1f924319a5..b42fbf0cee 100644
--- a/src/lib/krb5/configure.in
+++ b/src/lib/krb5/configure.in
@@ -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
diff --git a/src/lib/krb5/error_tables/krb5_err.et b/src/lib/krb5/error_tables/krb5_err.et
index d8f8533c8b..b483116e1d 100644
--- a/src/lib/krb5/error_tables/krb5_err.et
+++ b/src/lib/krb5/error_tables/krb5_err.et
@@ -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
diff --git a/src/lib/krb5/keytab/file/ChangeLog b/src/lib/krb5/keytab/file/ChangeLog
index 2120127db1..4e575b6519 100644
--- a/src/lib/krb5/keytab/file/ChangeLog
+++ b/src/lib/krb5/keytab/file/ChangeLog
@@ -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
diff --git a/src/lib/krb5/keytab/file/ktf_g_ent.c b/src/lib/krb5/keytab/file/ktf_g_ent.c
index 7122cb41d5..57d6edabd6 100644
--- a/src/lib/krb5/keytab/file/ktf_g_ent.c
+++ b/src/lib/krb5/keytab/file/ktf_g_ent.c
@@ -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;
diff --git a/src/lib/krb5/krb/ChangeLog b/src/lib/krb5/krb/ChangeLog
index 49d6ef3bb5..9d1cfb02a0 100644
--- a/src/lib/krb5/krb/ChangeLog
+++ b/src/lib/krb5/krb/ChangeLog
@@ -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
diff --git a/src/lib/krb5/krb/Makefile.in b/src/lib/krb5/krb/Makefile.in
index ec6384e072..3c734210c0 100644
--- a/src/lib/krb5/krb/Makefile.in
+++ b/src/lib/krb5/krb/Makefile.in
@@ -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 \
diff --git a/src/lib/krb5/krb/auth_con.c b/src/lib/krb5/krb/auth_con.c
index 3795086235..335f7ae7dd 100644
--- a/src/lib/krb5/krb/auth_con.c
+++ b/src/lib/krb5/krb/auth_con.c
@@ -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);
+}
diff --git a/src/lib/krb5/krb/auth_con.h b/src/lib/krb5/krb/auth_con.h
index 9d9df0e867..e6704169ed 100644
--- a/src/lib/krb5/krb/auth_con.h
+++ b/src/lib/krb5/krb/auth_con.h
@@ -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 */
};
diff --git a/src/lib/krb5/krb/decode_kdc.c b/src/lib/krb5/krb/decode_kdc.c
index 71e01a8111..60c983878f 100644
--- a/src/lib/krb5/krb/decode_kdc.c
+++ b/src/lib/krb5/krb/decode_kdc.c
@@ -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;
diff --git a/src/lib/krb5/krb/decrypt_tk.c b/src/lib/krb5/krb/decrypt_tk.c
index 354a3f2a06..47f675591a 100644
--- a/src/lib/krb5/krb/decrypt_tk.c
+++ b/src/lib/krb5/krb/decrypt_tk.c
@@ -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
index 0000000000..ff42149370
--- /dev/null
+++ b/src/lib/krb5/krb/enc_helper.c
@@ -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);
+}
+
diff --git a/src/lib/krb5/krb/encode_kdc.c b/src/lib/krb5/krb/encode_kdc.c
index bb9311f6af..e20c1f5364 100644
--- a/src/lib/krb5/krb/encode_kdc.c
+++ b/src/lib/krb5/krb/encode_kdc.c
@@ -41,10 +41,12 @@
/* 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;
}
-
-
diff --git a/src/lib/krb5/krb/encrypt_tk.c b/src/lib/krb5/krb/encrypt_tk.c
index cb1fb28b9d..e1a1b1850e 100644
--- a/src/lib/krb5/krb/encrypt_tk.c
+++ b/src/lib/krb5/krb/encrypt_tk.c
@@ -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);
}
diff --git a/src/lib/krb5/krb/gen_seqnum.c b/src/lib/krb5/krb/gen_seqnum.c
index 3694d2cd07..4b3cd6fe6a 100644
--- a/src/lib/krb5/krb/gen_seqnum.c
+++ b/src/lib/krb5/krb/gen_seqnum.c
@@ -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));
}
-
diff --git a/src/lib/krb5/krb/gen_subkey.c b/src/lib/krb5/krb/gen_subkey.c
index 89e21a1b79..861d61e722 100644
--- a/src/lib/krb5/krb/gen_subkey.c
+++ b/src/lib/krb5/krb/gen_subkey.c
@@ -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);
+}
diff --git a/src/lib/krb5/krb/get_creds.c b/src/lib/krb5/krb/get_creds.c
index 3a1ec526b7..37f2bb5a93 100644
--- a/src/lib/krb5/krb/get_creds.c
+++ b/src/lib/krb5/krb/get_creds.c
@@ -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));
+}
diff --git a/src/lib/krb5/krb/gic_pwd.c b/src/lib/krb5/krb/gic_pwd.c
index 45a076246f..c517062f86 100644
--- a/src/lib/krb5/krb/gic_pwd.c
+++ b/src/lib/krb5/krb/gic_pwd.c
@@ -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);
diff --git a/src/lib/krb5/krb/in_tkt_pwd.c b/src/lib/krb5/krb/in_tkt_pwd.c
index 7373f62f19..e03883e9d7 100644
--- a/src/lib/krb5/krb/in_tkt_pwd.c
+++ b/src/lib/krb5/krb/in_tkt_pwd.c
@@ -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);
}
diff --git a/src/lib/krb5/krb/init_ctx.c b/src/lib/krb5/krb/init_ctx.c
index daa9fd95f8..2285b0f421 100644
--- a/src/lib/krb5/krb/init_ctx.c
+++ b/src/lib/krb5/krb/init_ctx.c
@@ -23,6 +23,32 @@
* 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;
@@ -280,6 +317,16 @@ krb5_get_default_in_tkt_ktypes(context, ktypes)
}
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;
const krb5_enctype *ktypes;
@@ -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);
}
diff --git a/src/lib/krb5/krb/kdc_rep_dc.c b/src/lib/krb5/krb/kdc_rep_dc.c
index e9431aef94..a9cbcf39bb 100644
--- a/src/lib/krb5/krb/kdc_rep_dc.c
+++ b/src/lib/krb5/krb/kdc_rep_dc.c
@@ -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);
diff --git a/src/lib/krb5/krb/kfree.c b/src/lib/krb5/krb/kfree.c
index 17c4f8c7f7..87eeca9619 100644
--- a/src/lib/krb5/krb/kfree.c
+++ b/src/lib/krb5/krb/kfree.c
@@ -149,6 +149,16 @@ krb5_free_checksum(context, val)
}
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;
register krb5_cred FAR *val;
@@ -572,3 +582,4 @@ krb5_free_unparsed_name(context, val)
krb5_xfree(val);
return;
}
+
diff --git a/src/lib/krb5/krb/mk_cred.c b/src/lib/krb5/krb/mk_cred.c
index 23545fb612..cdda80d062 100644
--- a/src/lib/krb5/krb/mk_cred.c
+++ b/src/lib/krb5/krb/mk_cred.c
@@ -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);
diff --git a/src/lib/krb5/krb/mk_priv.c b/src/lib/krb5/krb/mk_priv.c
index 7986e18562..2e7f2ce255 100644
--- a/src/lib/krb5/krb/mk_priv.c
+++ b/src/lib/krb5/krb/mk_priv.c
@@ -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;
diff --git a/src/lib/krb5/krb/mk_rep.c b/src/lib/krb5/krb/mk_rep.c
index 45784284c3..f0398475f5 100644
--- a/src/lib/krb5/krb/mk_rep.c
+++ b/src/lib/krb5/krb/mk_rep.c
@@ -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;
diff --git a/src/lib/krb5/krb/mk_req_ext.c b/src/lib/krb5/krb/mk_req_ext.c
index 726bb434b0..1530f79616 100644
--- a/src/lib/krb5/krb/mk_req_ext.c
+++ b/src/lib/krb5/krb/mk_req_ext.c
@@ -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
diff --git a/src/lib/krb5/krb/mk_safe.c b/src/lib/krb5/krb/mk_safe.c
index 1a44a75e59..0d5a490804 100644
--- a/src/lib/krb5/krb/mk_safe.c
+++ b/src/lib/krb5/krb/mk_safe.c
@@ -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;
diff --git a/src/lib/krb5/krb/preauth.c b/src/lib/krb5/krb/preauth.c
index c106dd15a3..ab1432fdb0 100644
--- a/src/lib/krb5/krb/preauth.c
+++ b/src/lib/krb5/krb/preauth.c
@@ -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);
diff --git a/src/lib/krb5/krb/preauth2.c b/src/lib/krb5/krb/preauth2.c
index 0a154f6e14..86d325d7b9 100644
--- a/src/lib/krb5/krb/preauth2.c
+++ b/src/lib/krb5/krb/preauth2.c
@@ -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);
diff --git a/src/lib/krb5/krb/rd_cred.c b/src/lib/krb5/krb/rd_cred.c
index 7537ac990a..86c5ccf727 100644
--- a/src/lib/krb5/krb/rd_cred.c
+++ b/src/lib/krb5/krb/rd_cred.c
@@ -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);
diff --git a/src/lib/krb5/krb/rd_priv.c b/src/lib/krb5/krb/rd_priv.c
index c4e1ed0b6f..f08975f221 100644
--- a/src/lib/krb5/krb/rd_priv.c
+++ b/src/lib/krb5/krb/rd_priv.c
@@ -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)))
diff --git a/src/lib/krb5/krb/rd_rep.c b/src/lib/krb5/krb/rd_rep.c
index d4d559d14a..411a61ddbb 100644
--- a/src/lib/krb5/krb/rd_rep.c
+++ b/src/lib/krb5/krb/rd_rep.c
@@ -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 */
diff --git a/src/lib/krb5/krb/rd_req_dec.c b/src/lib/krb5/krb/rd_req_dec.c
index 0c62c19df1..cdbdc81dff 100644
--- a/src/lib/krb5/krb/rd_req_dec.c
+++ b/src/lib/krb5/krb/rd_req_dec.c
@@ -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;
diff --git a/src/lib/krb5/krb/rd_safe.c b/src/lib/krb5/krb/rd_safe.c
index 5f0fcd6ca6..1c5aca21ca 100644
--- a/src/lib/krb5/krb/rd_safe.c
+++ b/src/lib/krb5/krb/rd_safe.c
@@ -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;
}
diff --git a/src/lib/krb5/krb/send_tgs.c b/src/lib/krb5/krb/send_tgs.c
index b06ef2bfc7..19de14e1aa 100644
--- a/src/lib/krb5/krb/send_tgs.c
+++ b/src/lib/krb5/krb/send_tgs.c
@@ -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 */
diff --git a/src/lib/krb5/krb/ser_actx.c b/src/lib/krb5/krb/ser_actx.c
index 5705b711fc..42b9bfeb64 100644
--- a/src/lib/krb5/krb/ser_actx.c
+++ b/src/lib/krb5/krb/ser_actx.c
@@ -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) {
@@ -556,8 +565,6 @@ krb5_ser_auth_context_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)
kret = krb5_ser_principal_init(kcontext);
diff --git a/src/lib/krb5/krb/ser_eblk.c b/src/lib/krb5/krb/ser_eblk.c
index 20b3da6726..04e21faab5 100644
--- a/src/lib/krb5/krb/ser_eblk.c
+++ b/src/lib/krb5/krb/ser_eblk.c
@@ -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
diff --git a/src/lib/krb5/krb/str_conv.c b/src/lib/krb5/krb/str_conv.c
index 6346aef234..b30638d4fb 100644
--- a/src/lib/krb5/krb/str_conv.c
+++ b/src/lib/krb5/krb/str_conv.c
@@ -31,17 +31,13 @@
*
* 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.
@@ -52,24 +48,12 @@
/*
* 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 */
-/*
- * 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;
@@ -447,25 +345,6 @@ krb5_string_to_salttype(string, salttypep)
}
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;
krb5_timestamp FAR * timestampp;
@@ -545,33 +424,6 @@ krb5_string_to_deltat(string, deltatp)
* 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;
char FAR * buffer;
diff --git a/src/lib/krb5/krb/vfy_increds.c b/src/lib/krb5/krb/vfy_increds.c
index bb8ea349b0..85a8465030 100644
--- a/src/lib/krb5/krb/vfy_increds.c
+++ b/src/lib/krb5/krb/vfy_increds.c
@@ -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);
}
-
-
-
diff --git a/src/lib/krb5/os/ChangeLog b/src/lib/krb5/os/ChangeLog
index 0ee4a7192f..84f0dec670 100644
--- a/src/lib/krb5/os/ChangeLog
+++ b/src/lib/krb5/os/ChangeLog
@@ -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
diff --git a/src/lib/krb5/os/Makefile.in b/src/lib/krb5/os/Makefile.in
index 9e132dbc86..56edfac36b 100644
--- a/src/lib/krb5/os/Makefile.in
+++ b/src/lib/krb5/os/Makefile.in
@@ -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 \
diff --git a/src/lib/crypto/os/c_ustime.c b/src/lib/krb5/os/c_ustime.c
index e790acc956..350c1aa5c7 100644
--- a/src/lib/crypto/os/c_ustime.c
+++ b/src/lib/krb5/os/c_ustime.c
@@ -27,7 +27,7 @@
#define NEED_SOCKETS
#include "k5-int.h"
-#ifdef macintosh
+#ifdef _MACINTOSH
/* We're a Macintosh -- do Mac time things. */
diff --git a/src/lib/krb5/os/ktdefname.c b/src/lib/krb5/os/ktdefname.c
index c645635ab0..0493244f61 100644
--- a/src/lib/krb5/os/ktdefname.c
+++ b/src/lib/krb5/os/ktdefname.c
@@ -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;
diff --git a/src/lib/krb5/os/localaddr.c b/src/lib/krb5/os/localaddr.c
index cb204b597e..9f33e5d98b 100644
--- a/src/lib/krb5/os/localaddr.c
+++ b/src/lib/krb5/os/localaddr.c
@@ -20,16 +20,329 @@
* 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
diff --git a/src/lib/krb5/os/locate_kdc.c b/src/lib/krb5/os/locate_kdc.c
index c0ccf7e38c..d8187ac3a6 100644
--- a/src/lib/krb5/os/locate_kdc.c
+++ b/src/lib/krb5/os/locate_kdc.c
@@ -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);
diff --git a/src/lib/rpc/ChangeLog b/src/lib/rpc/ChangeLog
index 7db8539231..50ec692cba 100644
--- a/src/lib/rpc/ChangeLog
+++ b/src/lib/rpc/ChangeLog
@@ -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):
diff --git a/src/lib/rpc/Makefile.in b/src/lib/rpc/Makefile.in
index 1340d3ffd4..a03ef026f0 100644
--- a/src/lib/rpc/Makefile.in
+++ b/src/lib/rpc/Makefile.in
@@ -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= \
diff --git a/src/lib/rpc/auth_gssapi.h b/src/lib/rpc/auth_gssapi.h
index 218b5cb9d3..2cdd20f2fe 100644
--- a/src/lib/rpc/auth_gssapi.h
+++ b/src/lib/rpc/auth_gssapi.h
@@ -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,
diff --git a/src/lib/rpc/svc_auth_gssapi.c b/src/lib/rpc/svc_auth_gssapi.c
index 2a3233ee93..df59859f0d 100644
--- a/src/lib/rpc/svc_auth_gssapi.c
+++ b/src/lib/rpc/svc_auth_gssapi.c
@@ -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.
@@ -917,6 +917,13 @@ bool_t _svcauth_gssapi_set_names(names, num)
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
index ac6e964266..0000000000
--- a/src/mac/TestTrack/ChangeLog
+++ /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
index d7ae71ad30..0000000000
--- a/src/mac/TestTrack/MITAthenaLib
+++ /dev/null
@@ -1 +0,0 @@
-(This file must be converted with BinHex 4.0) :$%e*9%&dD'9ZB8aTBJ"cD'aL2j!%!*!%b$d!!!*A#-K+EhNKF'9QCQdf1'X!!!! "XG%Hb!#3$3-!!J#3$NXd!!",0!!!5c3!!!#8!!%#!*!%"3#3"LFJ!!!R)!!!"GJ !!%[)!J%#!*!%$J#3$J9)!!"4S!3"!J"0B@PZ!#9"09G[FQaN!%a[B@4PFJ#3"#T 46PErp#m0F!%[!$!mUQi[!#*YrC3J@8k3!#TZrr!Y32rdF!%[!$!mU'i[!#*YrC3 J@8k3!#TZrr#`V[rdCJB`2!)!B!3`2!3!6Pj1GBp1G@e8EfpXBQpi9(*KF(-!!#T 46PErq$!Z!!S#J!!!#!"Q"(!!B!*`!8jH6R3!")Y(CA48FQ&`9(P`C3!!+P&19[r d51FB"$BZ!!S[!f(rN!6%'!!-"!!"CK*Krj!%@!*$"rqf3'd%0MbSRbm%,`-LEIf 8)&P1N!!UE[r`,8$rp(!",`!`2+LI,`!LEIf8)&P1N!!UE[r`X+lrp&E!4!"*`%c I!"K1ANjd!!5+9(*KF%9iDA0dF`!!!#T46PErj#m05'lrk(!",`!LEIcB)&P1N!! UE[rJ5'lrj#mZ!!`[,J!)-#lrpLm!)Qhmc#"C6T!!+Qlri%M!C``JEJ!)3P!JEJ! -3T!!6Pj1G!!)MdGPG&0jFh4PE8C[E'4PFJ!!+P&19[rd51F30#CZ!!JNEJ!-GJ! `2+'Y,`"Krj!%#%S!Caa)E[rd,caQEfaN)QhpN!!J@8k3!#TZrr")`'B#GJ&+!fB -,`S[#f(rN!4@B#J[#Lm,F!![!#mmBh4bE$!mJ!![!#*YrB`J@8k3!#TZrr")`'F %3P0#NNcI$!K1ANjd!!L24f9d3e"KEQ9X4QpXC'9b!!!U88j@rRa)jam%,Li!##` Z!!`k,J!5+#i!&%+ZriT"l[jq,8MrN!!p4Iq8,86rVMem!!(rQQ"F[UlrRQC1[+l rSQC)F!%[!%KZrRi["#m&)QhpV#"C6T!!+QlqH$B!F!%[!#mmC'jbF#*YrA`J@8k 3!#TZrRK+J'B3,`-LEIeB)&P1N!!UE[jiB!3`!f!H8QlrQLe%rkj)E[pq)Qhmr#" C6T!!+QlqH%M!Cj!!F2p-h`$i6Pj1G!!3Ne0PBA*MD%C[E'4PFNC[FN418P!!!#T 46PErm#m$5'lrmNKZrrCKrrrrrT3[,[rb-#lrpLm!,cakG'0`,caMC'9fBIq3"!` f!!a$rrpR"$!$B'j)E[rb5'lrpQ(rrrrpr#mZrr)`,[rf,`![2'edBh![2'0NCAC KrrrrrYBf!!a$rrpR"$!$B$K)E[rb5'lrpQ(rrrrq+#mZrr)`,[rf,`![2'edBh! [2'0NCACKrrrrrU!f!!a$rrpR"$!$B!*`rbBI6Pj1GBP2F'9Z6h9b8NB!!#T46PE rq%MR%!4+VISSC`C`!'!!!04Krj!%,$B!F!%[!#mmC'jbF#*YrA`J@8k3!#TZrr3 V32SN5Uhk*'B3)QhpL#"C6T!!+Qlrp'!!!*`[,ISN)Qhp##"C6T!!+Qlrp!a$rrp R$Lm$)Qhp@#"C6T!!+Qlrp#mYqL3LEIc8)&P1N!!UE[rd,bhk*#*YrE`J@8k3!#T Zrr3JEISN+e$k+#mZ!!K)H!!"5(J$i5mYqLJLEIcX)&P1N!!UE[rd0J!`!dM!6qm !%'FN,bhk*#*Yr0`J@8k3!#TZrr3[,ISN)QhpZ#"C6T!!+Qlrp%+YqLJ`!bBI6Pj 1G!!%M%p`C@j5CA0[E(CPFJ!!!#T46PErq#m05Uhk+'B%F14J+LmZ!"3[,J!3,bi !$#mZ!!K)H!!$,c`!!2rK,bhk+#*Yr1`J@8k3!#TZrr41ANjd!"#*8h4b9'p"C'4 b!!!U88j@rrK)EIT)5'hk6#mZ!!KKr`!!!SK+J'F%F!"J-N(YqNJV52T!3Uhk4%( YqN`V52SX3Uhk-(!#+d$k0(!%+d$k1%(YqN!V52Sm3Hhk,#!)6Pj1G!!%M@GPG'K [Fh4LH@jKE@8!!#T46PErp#m05'hl6%KYr[`LEIcS)&P1N!!UE[r`5-!Y32rd)#l rp%jH6R@,Eh"PEPpNFQPfCA)!!#T46PErq#m05Uhl8'F1)Qhl8#"C6T!!+Qlrp'! #F!"1ANjeMh9cCA*IB@*[FR4IC'PcF!!!+P&19[ri51F3*#4Z!!Kf!!a5!!&R"M! 55-"J('(rN!5`*J"R"#!$B!iLEIe`)&P1N!!UE[rdB0K-h`3)6Pj1G!!%L(GKDA4 ICQpb!!!!+P&19[ri51F3"%TYqdaQ%Q(rN!3f*J"+JfF')!0J!!#`5(J!CN+R5'h la#*YrM3J@8k3!#TZrr3lEIY-qp`lI!!QqpiVEJ!)qq!EI!!Hqq4#,I[P'hcr`2[ Q5'hla#*Yr@`J@8k3!#TZrr4)EI[8BIq3"%3Q!%Ki!'C#TdKYqm3LEIid)&P1N!! UE[rd1fhl62[F1h`!+[[H+fi!#2[J5'hla#*YrC`J@8k3!#TZrr4+EI[8CK![,I[ N)QhqQ#"C6T!!+Qlrp%U$CJBf,I[85--J!bBI6Pj1G!!%N!"dBh"IBfa[Ff9IFh4 bC@&Y!!!!+P&19[ri51F3"%TYqdaQ%'(rrrrq5LB!5S0R"(!!B&C)H!"Q3UG)EIY H)Qhq0#"C6T!!+Qlrp$YYqdclGMYm!#MlH#YZ!!MlHNKYqeiLEIeX)&P1N!!UE[r d5'hlEQ(rrrrqDLB!5S0R"(!!B!T+EIZD9X"%!%R!*Kp1ANjd!!5,G'0`Af0KER* PB@3!!#T46PErq%MR%$3QEJ!-5Uhl9'BN5'hr!L*Yr[JJ@8k3!#TZrr4)`#B!5S0 R"L!$B!!!RR!"+d$l9(!3,`")H!2!,bhqk#*Yr8JJ@8k3!#TZrr3N3$Ym!!(lA%K Yqe`[#LmYrZ`[,J!))Qhqp#"C6T!!+Qlrp#"YrZ`-N!$rrkAqCK")EIYFBIrrrrf i)'hql##!,`SLEIdS)&P1N!!UE[rd)'hql%U3!'F))'hql#!3B#)JEIlX)Qi!%#+ S!33J#fF3)%XLEIlX3qN!"#!)%0PQr(!!60m-#%jH6R3!$)pZFepbCA0[E(CPAfj KE@8!!#T46PErq#"Z!!JLEJ!--UJ!!NjH6R3!#)abCA0[E(CPAh"bEf-!!!!U88j @rrK)j`!N$'i!!3!1CKJNEJ!3,bS!##mZ!"!LDJ!%)&P1N!!UE[rd*&p1ANjd!"# +G@4`Afj[G'PQH3!!!#T46PEr[%MR%$3QEJ!)GJ"+EIY-CK*Krrrrr'BQ!%U$C`B J!f!!!-4)H!!k3UG)E[qq)Qhq0#"C6T!!+QlrZ%Ki!!`LEIkF)&P1N!!UE[qi*%! J#QB'F!aJ!!#52A`!&2rB2@hl62r@,@i!%2rH,@i!&2rL5Uhl@'BFF"![!%Ki2X! [,IlN)Qhp5#"C6T!!+QlrZ#Y!qeJYEIYBrqBp8rrU,8Vrl%KZrliLEIeX)&P1N!! UE[qi5QlrcQF@,`SLEIkB)&P1N!!UE[qi-#lrcNM!B"`NV[rD*@i!(!!%*@i!$!! ))'i!'##+0UlrkL!$60m-#%jH6R3!')aeC("IFQ9RDA0dCA)!!!!U88j@rkJ[$8K i!$T#TdKZrliLEIid)&P1N!!UE[qN2@i!'[qb,@i!&2qd3QlrZ#eZ!!MrUMem!"I rf$eYqdcreL"ZrkSY82rD,@i!$2rJ2@i!%[rN(A`!!IrU3HlrXLe)rqC)E[qq)Qh pE#"C6T!!+QlrT%KZrmjKrrrrqfiY32qZ)#lrVNjH6R3!&)jeC("IFf9ZC&pNCh* KE3!!!#T46PEr[%MR'#3S,J!B5(J!1N+R5'lr[L*YrM3J@8k3!#TZrlJNEJ!)2A` !&IrB2@hl62r@,9,rfR!!%#hl6Me!rpj)E[qq)QhpE#"C6T!!+QlrZ%KZrmjKrrr rq[)Q!%U$C`3J!f"dF!!`,[rUZ)"X"#!%B!C`!$!ZrqSLEJ!8)'lrjR)JX)&P"+) ZB!j+J'F+)JN5f&1!C[SL3A!!-#lrkL"Z!"`JJ#"Z!!`JV[rJ)'i!%$#Zrq3pI!! @rpK)E[qq)QhpE#"C6T!!+QlrZ%KZrmjKrrrrqRJQ!#!$60m%'%jH6R3!')eeC(" ICf9dAf4RFQ&Y!!!U88j@rlK)j`!N5(J!1N+R5'lr[L*YrM3J@8k3!#TZrl3NEJ! )2A`!'2rB2@hl62r@,9,rfNKZrliLEIeX)&P1N!!UE[qd5'lrcQ(rrrrk$#e!rlS [#L*YrTJJ@8k3!#TZrl3NAdjH6R3!")YeC("IFQ9XC@&cC3!!+P&19[r851F3"(B !5Qhl6'B-BIrrrrPJ*J"+JfC!5(J!*%+R5'lre#*YrM3J@8k3!#TZrp!pI!!2rqi pEIY-rqa)E[r8)QhpE#"C6T!!+Qlrd%TZrq4Q##"Z!!JJV[r`*Kp1ANjd!!51Cf9 dAfejAfP`Af&NC()!!!!U88j@rrK1ANjeL'jPG&pTC'aP!!!!+P&19[ri51F3"%U Yr#TR"(!!B'4)H!N!)QhqR#"C6T!!+Qlrp#Y!r#T+VI`UCK"`$#Y!m%JlI!!-r,j `rf!k5(J*!%+R,bhm+L*YrM3J@8k3!#TZrr4f!'!B)!-'J!!!!)"b5%`$'!!JEI` U)B!B"&+$F##fJ'hLF!!Q(djH6R@+BfKPBfYID@jTG!!!!#T46PErq#m$BIq3"'a +J'F%F!"J-(B!B#4`5%`$#!!JEI`U#$!!"`J!CK"`5%`$#!!JEI`UdF!J#'!+8S0 `),D!EGC`!#BI6Pj1GC&RCA4IG@jeFf9NAh0[BfYPG!!!+P&19[ri*#i!#()!B#* `5%`"#!!JEI`UY,!)"'B3F%K-!3J!)'hm+Y(!)!KJ#P+"F##bJ'hBF!"1ANjd!!5 ,CQPZC&pcEf0VCA3!!#T46PErq%MR!#3NEJ!)5(J!"%+R,`SLEIid)&P1N!!UE[r d3US!1%UU!$4R%#mU!$3LEIkB)&P1N!!UE[rd3US!0%+U!$!NAdjH6R3!")jbC@a PBA0PAh0[BfYPG!!!!#T46PErq%MR(#3Q,J!)+Li!$#JZ!""`!VD!CJT+K'FBF!+ iJ'F5F"BV32")1h`!&[bqF2pJ!!#bF!+kJ'FBF!'kJ'F5F"BV32")1h`!&[bqF2p J!!#8BIrrrrkJ*%!J#QB3F!`V32")1h`!$2bqF2pJGM9$!!Je3`!B08-!+$9%!#S P43!X5US!0'Bb5(J)!#*YrT`J@8k3!#TZrr3P3!!d*A`!!!J!!$"+UJ!dCK"`$#Y !m%JlI!!-r,j`rf!U5(J!"%+R,`SLEIid)&P1N!!UE[rd!")!J!*5J(m#+J$[!!& #UJ!i)#S!"%cI"$K1ANjd!!b'FfpMDf9d!!!!+P&19[ri51F!*#4Z!!`)%J!(CK" )EIm))Qhp4#"C6T!!+Qlrp1R5!%K531r5!%JNAdjH6R3!#*4cEf0VCA4ICACPER4 ID'&ZC'aPFJ!!!#T46PErq%MR'$JS,J!3+'i!'#mZ!!KKrrrrrIBN3#!+CK*`&LY !m%JlI!!@r,j`rf!!!-*`!V#U!#aQ#!aU!!)!#'F5F"BV32")1h`!&[bqF2pJ!!# J5US!1'C),bhqi%KU!$J[+J!`,bS!0#m+5'S!#Q(rrrrj&LB!5S0R&Lm+BIrrrrh BF"NV32")1d2m[R$rB'")DJ!-BIrrrr[k!#S!%!!"F"#`VJ!FCJB-9!!#Ca"`&LY !m%JlI!!@r,j`rf!b*N`["#mZ!!``+`!#,`![+`!%,bS!1'(rrrrjY#B!5S0R$R! C+d$`5$Y$r,j`rf!#)!4-ha`B6Pj1G!!BKR0PEQ4dE`!!!#T46PErp%MR%$!QEJ! F,bi!#'(rrrrmmL4!)!TQ%R!@+d$`5$Ym!"Em[R$rB!!!LR!#X+S!,'B)$'S!!J! )Ca"`&LY!m%JlI!!@r,j`rf"SF"#`Nf-3F"BV32")1h`!&[bqF2pJ8R!3*S!QEJ! B0V`!!NKZrr3[,J!3,bi!$%KV!!*)D`!%,bS!1'(rrrrjPLB!kG)!5'F+kG)!5&0 !lp)!5%U$CJBJ,[rdB!a`'5Y!m%Jl3rbqF2p-h``)6Pj1G!!BL(*PBhCQFQpY!!! !+P&19[ri51FI2#SZ!!JSEJ!-*Qi!%#iZ!"3NEJ!B)!TQ"(cqB#3LEId3)&P1N!! UE[rdFMa-%K!!dS!J+J!%6(`!N!4"'Y#",!")H!!J3UG)EIb1)Qhq0#"C6T!!+Ql rp%Ki!#"#TdKYr'iLEIid)&P1N!!UE[rd5(J!)%+R5'hm6L*YrM3J@8k3!#TZrr4 )H!!J3UG)EI`Z)Qhq0#"C6T!!+Qlrp(J!)!aQ"%RYr#iJ#fB%4qhm,NU(CJC"lI` Z,JKf!'!!!+)J!qU))J0d(m+#G!(MUX5c$!"R(L!$FKr!JA)"iDNJ!qU)3HhmEN( `$!!J%)#"))"5K#!$kSJL!h3I`S*d!H1Ua,3-!'GBF)$3Jh)JX)&Z6Lm$BIrrrrX J*%!J#QG!#")!"fFkkG)!5'B@F!'`UJ!XCL`[+J!mBIrrrr5D5S"R(L!$FKr!JA) "iDNJ!qU)3HhmMN(`$!!J%)#"))"5K&+$YS9Y!2pF5S4Q*#*YrA!J@8k3!#TZrr4 KrrrrqESLEId3)&P1N!!UE[rdX)CP!2mZ)!9HJ#B!j)2JLq#,i)[ULpD!jS0`),D !B`*f)#*-3HhmML!$FL#`J@8%SLjJ$NU!C`SL#4,B8i"QqL*")NY"lIaZ)!0b),# "C35L,Q!15S"R#L)*%YK6J'Ek)N%L4d(Yr%iJ!h)JX)&P"+)ZB!j+J'F+)JN5f&1 !C[SL35!%60mFq%jH6R3!&)CcC@aPBh3!!!!U88j@rrK)ja!N*Li!#!b$!!!!J'` 5,`-LEIh3)&P1N!!UE[rdB!!!RLm$BIrrrrRS*%!J#QB'F!"J!!#+)!TR$JJ5!!G R#!aU!!)!+'F3F"BV32")1h`!&[bqF2pJCL!U!#a6J'F'8i"R,Q!q5US!2'G),bS !2'(rrrrb6LB!5S0R1(!C+d$`5$Y$r,i[#Q(rrrrjd($rB#a+UJ!iCa`[+J!iBIr rrrH!B""`&LY!m%JlI!!@r,j`rf!+,`TKrrrrqD*`!%cI"!K1ANjd!!5-FfpMDf9 dAf0XEh0P!!!!+P&19[ri,`e+VIbZCK4)H!,))QhqR#"C6T!!+Qlrp#Y!r+j+VIb bCK4)H!!8)QhqR#"C6T!!+Qlrp#Y!r,*1ANjeLh4dAf&XE'pMBA4P!!!U88j@rrJ [$8UYr+jR%#mYr+iLEIkB)&P1N!!UE[rd3UhmVNUYr,*R%#mYr,)LEIkB)&P1N!! UE[rd3UhmXNjH6R@(G(4ICR*PC3!!+P&19[[S,`e"l[[i)Qi!%#!)%0PQr%KZqrJ LEIeN)&P1N!!UE[[N5'llkNKZqr4)E[[b-#i!$Lm!,bi!##*Yr43J@8k3!#TZqq4 )E[[i,bllp#*Yr63J@8k3!#TZqq41ANjd!!b3!(4dAh0PG&pTG'9YAh4PH(3!!!! U88j@qqJ[$8KZqqT)E[[d5'llmM!Z!!i[!#mZ!!JLEId8)&P1N!!UE[[N5'llq#m Zqr3LEIdN)&P1N!!UE[[N5'llq#*Yr33J@8k3!#TZqq3JEJ!33qllq#!)%0PQr%j H6R3!$*!!G(4ICf9dAfPdC@eIG'9iG!!!!#T46PErj%MR%$`SEJ!)*'i!$#CZ!"" `!$!59i"R$R!!-"*EJ'F'F!"J!!$Z*LS!!J+$!!!!r`b$!!!!!fF8$)-!!!!0C`` -J`!!!"YRCQ!!!-Bf[!!"5'lrkNKZrr4)E[rbF!%[!#m-)Qhp&#"C6T!!+Qlri(! +,`![,[rd)Qhp'#"C6T!!+Qlri%KZrqC)H!!))Qhp$#"C6T!!+Qlri(!!,`![,[r d)Qhp'#"C6T!!+Qlri(!"B'3f[!!#5'lrkNKZrr4)E[rbF!)[!#m-)Qhp&#"C6T! !+Qlri(!+,`![,[rd)Qhp'#"C6T!!+Qlri%KZrqC)H!!))Qhp$#"C6T!!+Qlri(! !,`![,[rd)Qhp'#"C6T!!+Qlri(!"B!*`!%cI(!K1ANjd!!b0G(4ICA9TAfCTE(4 PFJ!!+P&19[p),`e#V[p@3UlrA%KZrdSLEIeJ)&P1N!!UE[p%5N"R"($rB#j#V[q +3QlrQMeZrf$rP%+Zrj!!5'lrIL*Yr2!J@8k3!#TZrd4+3'F%F2pJ"#!Zrja1ANj eQ(4dAfGPG&pfEfaIBh*PBA4TEfjIC'&dC3!!!#T46PErj%MR!$`SEJ!)3QlrpNK irrp#Tc!m"%`[!#*Yr5`J@8k3!#TZrq!Q3#!,CJC`rf!!!9SJ9%)3)&4#+!"N,a4 `"#m!,`YKrrrrr53J9%KS!'4`"Lm!,`YKrrrrr4*`%#m!5(J2d#mYrYJLEIe))&P 1N!!UE[rJ*%")E[rU)Qhp9#"C6T!!+Qlri#m,)Qhp6#"C6T!!+Qlri%KZrqj)E[r N5'lrk(!",`![#b*Yr43J@8k3!#TZrq"`!bm!F!-[!#*YrE!J@8k3!#TZrq"`r#m !F2`[!%KZrqiLEIh!)&P1N!!UE[rJF"![!(!3,`")E[rZ)Qhmb#"C6T!!+Qlri%K ZrrB[#L*Yr13J@8k3!#TZrq!-EJ!"rrCR#!aZ!!,rpQEH,`SLEIdS)&P1N!!UE[r J$'i!!IrfCL`[&(!%,`![#f(rrrrmU#"85'J!C(!',`![#f(rrrrmPQ(rrrrq1#" 8)8!!b#m,)QhpH#"C6T!!+Qlri#m-)QhpD#"C6T!!+Qlri#m-)QhpY#"C6T!!+Ql ri$!ZrrC)`%cI(!"1ANjd!!54G(4IC@4TG&peFf9bAfPZCQm!!#T46PErq%MR!#3 `2!4-,`![2(4dG@NLEIdm)&P1N!!UE[rd*%"+J'C85(J!c#*Yr3!J@8k3!#TZrr3 N3%KYre)`2!4-,`![2(4dG@N[#L*Yr6!J@8k3!#TZrr4)H!$-3UF[%L*YrM3J@8k 3!#TZrr3[#Q(rrrrpjP1!CbT`rf"D$#i!!3!2C`jKrrrrr9SJ8V#S!-KR%#m+BIr rrrh!8i"R"($rB$3LEJ!))&)J2!!!!-ab),#"C35L,Q!15S"R#L)*%YK6J'Ek)N% [#L*YrB!J@8k3!#TZrr4`!#4I6Pj1G!!)N!"dG&pRCA4IGA0PFPpTEQC[!!!!+P& 19[rN,`e)E[rSF!%[!#*Yr0JJ@8k3!#TZrq!p32rQCb)`,[rQ5-![!%KYrfB[,J! ))Qhpp#"C6T!!+Qlri%r[!!aJ8$!Zrr4)`#m!F!!3,[ra,`"`!"!Zrr![!$!Zrqj )`#m!-#lrl%M!,`!`,[rU5-![!$!ZrqK)`#m!5'hrK#mZ!!JLEIhd)&P1N!!UE[r J6qm!*%jH6R3!"*0dG&pRCA4IFhPcAf9ZGQPbEfjc!!!U88j@rr4)j`!N-$`%6#m !,ca$8e45)Qhp2#"C6T!!+Qlrm#4!5S"R4Lm+)Qhp[#"C6T!!+Qlrm#m5BIrrrqS 5,8$rp'F1)'lrp#"S!"!J8#Y3r,B[#L*Yr0`J@8k3!#TZrr![#L*YrB!J@8k3!#T Zrr!NAdjH6R@8G(4ICf9dAh0PFRCPFPpTF'&NC()!!!!U88j@q"K)jam%&Li!&bJ Z!"Kk!(i!)QhpU#"C6T!!+Qli&$e!rYi`,Ibm,`!LEIcd)&P1N!!UE[J8F!'iJ'm D)Qhp%#"C6T!!+Qli&%a%!!&+J@F'F!"J!!*L5UhmYQB5BIq3""C+VIbfCJC`!'! !!NT)E[VHBIrrrrj3GJ"+!fFX%#i!%bm!5'lqp'(rrrrp5%U!Cb3`,[lH,`!LEIc d)&P1N!!UE[J8F2pJ!!)13Llqp%)ZreK#V[qmBIrrrrK#5(J#b%+R,bhmVL*YrM3 J@8k3!#TZq"3JEIbZ-,`!!5"Yr+iaI!!"!!)JEIbZ-A`!!3!%5J0R"(!"B!*`!#" Yr+ia3!!')Qhp%#"C6T!!+Qli&#"Yr+iK3!!)5'lkhNKZreK)E[ld5'hrd%KZq#) LEIhd)&P1N!!UE[J8)'hmXL#Z!!JJEIbb)@i!$!!%3HhrfL*Yr,)M5!!)3Hhr8#* Yr,)M5!!-3Hli)L*Yr,)M5!!3,bhmXLmYr+jKr`!!!PiX!%+R5(J!!NKi!!*Krrr rm9)Q!$em!!,r`$em)66r`LeYr,Era%Ki!"")E[r!3UF["LmYr+i[!f(rrrrbF(S !6qm!&%Ki!#"#TdKZrp!LEIid)&P1N!!UE[J8)!0b(m#"FJ(KU5!$kSK"l[r33I! -!#!3J)%JJ(!&,8$rm%+Zrr4)E[r`3UG#TdKZrp")H!%!BIrrrr2Z+!"+K'BB5(J !%%KZrm"#Tbm',bhmVLm$BIrrrr(k5S4Q#&+&F!1kJ'f%F!'iJ'C@F"!Y32JH5'l i(NKZrm"#TdKi!XJ[,IbZ,`0KrrrrmY!S!#"Yr+i-D!!%!!CQ+%KZrZ![,IbZBIm !!!#L)'lql"!35F!%J!!!!&*R!Q!#I[mYE[l`q"S[!f(rrrreK'(rrrrfUM!ZrYi [!#*Yr23J@8k3!#TZq"3J"dcI!2K1ANjd!"5+G'9cG&pdFQ&MD`!!!#T46PErq#m -)'i!##*Z!!`SEJ!3)Li!&'!++-Lab@3%5KKQq#!"8i&+J'EZ+&p1ANjd!"#3!(C IF'&bFf9IF'YdAf4KG'%!!!!U88j@rrK)H!!&,bi!$#"Z!!K)D!,()'i!#%KS!!a Krj!%QNjH6R3!#)YfAh"KFR0PAh"VG!!!+P&19[ri51FB2#4Z!!JSEJ!-*Qi!%#B Z!"3S#Q!f5T0Q"%)DB"BJ6*(+,`J[%bm+)Qhpm#"C6T!!+Qlrp%+R,`SLEIhS)&P 1N!!UE[rd)%"5L#4)@)XJ!e1$5S"Q`L"+NF3J#%cI("K1ANjd!"#6GPpKFh0PE@* XC9p`Dh4IC'&dB3!!+P&19[ri,`0f"5m$,bi!$#"Z!!K"k!,)NF0)8#"Z!!K)D!! -BIq3"&Tb$0#"*Kp1ANjd!!L1GPpKFh0PE@*XC9p`Dh3!!!!U88j@rrK)jaJN*'i !#(B!BIm!!!&`)QhpU#"C6T!!+Qlrp$J!F2mV32bkF!'`UJ!-CM"`!5m!,bS!%#* YrD3J@8k3!#TZrr4)`#Y!r,T`rl#Yr,TQ$L*YrBJJ@8k3!#TZrr3f!#m%)Qhmp#" C6T!!+Qlrp$!$60m%'%jH6R3!"*&IAfPZDA4TB@aTHQ9I9&466!!!+P&19[ri,`e `rl#Yr,TQ%M!Yr,`[!#*Yr9JJ@8k3!#TZrr4Kr`!!!2a1ANjeN!"IAh4PFQeTEQ& dC9p89&0-!!!!+P&19[ri-#hm[NjH6R@3!%GPG%*64%eKBdp64A*bEh)!!!!U88j @rrK`!%jH6R3!")j*ER0dB@aX3fpZFfpXC3!!!#T46PErq%jH6R@08Q9YEhCP3fp ZFfpXC3!!+P&19[riF!"1ANjd!!L69h*TG'9$D'&bFe4[3fpZFfpXC3!!+P&19[r iF!"1ANjd!!L88Q9KC%0SBA*c4R*[E80[ER0[E'8!!!!U88j@rrK1ANje+P&19[r i,`dJ$5m!,bhqa#*YrV3J@8k3!#TZrr3V32c!BIq3"0C`!%jH6R3!"#T46PErq#m 0)Qhq[#"C6T!!+Qlrp#mYr-!LEIk`)&P1N!!UE[rd6Pj1G5T46PErq%MR!#4J'L" YrX!JNR$r,`![+J!))QS!"#"C6T!!+Qlrp#"YrX!N8#!+CY`NAdjH6R8U85m-+'m !##*[!!a`!#"YrVKJ%%U3!'B)))`K53!%B!j5J&#)$)!!!!#!EHK`rbKI6R3!##T 4)Lm!"%U"E4J-J3!!!)"X%#!"jiJJEIkidF"#N!"#U!!%6R3!"#"[!!4`!*!!V`! -)8!!"(!!)Lm!#*'"))"1G!!-)'m!"#![!!b3!+m!&#&!!!3J,`!))Lm!%*'"))" 1G!!86PErk%MR(cJU,J!)*'i!$#KZ!"!QEJ!85T*Q#%UU!!4R!!$@GJ"i!#"&,"! YD!!%rr3Y8[rX,@S!"2rSIJ"k!%+Zrr"J!!#8eS-J"!+!J!!!!'F%F!''J0L%)!B #J)!!!!"R"(!"L)$FKL!Zrr3#J)!!!!"R"(!"M)!J,[rdd)!Y32rdhSFJ"3+!J!! !!'F%F!'1J0U&YUlrl')-YUlrl'BdZ+lrk'8ZF!'+J#e$rrJY42rm,bS!"#mU!!! [,[rm,blrq%KZrrKKrj!%&LBZrrJS,[rm8Ulrm("!X+lrm'i!rfBJ$'F'+)FT43! %)!YR"LD$*d3!"%cI(2K1ANjd!""19J!!,`SNEJ!)3UF[#NKZ!"4)EJ!-BIrrrrl Q)!SNAdjH6R3!&%j@!!![#L4Z!!J[#N+R5'i!&%KZ!!aKrrrrrX!J#L4I6Pj1G!! 8)#m!",#[!!aR#'85F!&1G!!3)#m!#,#[!""R#'6ZF2p1G!!3F!"1G!!3*#m!##! [!!3L,`!-P+m!%*'"C`TY"R!"6R3!%($r6R3!%#"[!!3J,`!))8!!"!J!!"pR#($ r))"1G!!)F!!JJ%jd!!JU88j@rrK)j`!N5(J!!5*YrR!J@8k3!#TZrr3JEIkN5T! !CKJ[,IkJ)Qhq)#"C6T!!+Qlrp#"YrU4`!5#!,bi!##mYrU!LEIiF)&P1N!!UE[r d*%")H!!")QhqE#"C6T!!+Qlrp#!+*&p1ANjd!!3U88j@rrJ[$5"YrU4+N!"R0%K i!!%LEIj`)&P1N!!UE[rd,bi!##mYrU!LEIiB)&P1N!!UE[rd5(J!!5*YrQ`J@8k 3!#TZrr41ANjd!!3U88j@rrK)ja!d*'i!##CZ!"!Q,J!83T)PEJ!-!!3#+J!I!!J #+J$[!!K#+J!-3LS!$8+U!"*+JfFB,`0)H!!#,`X[#L*YrR`J@8k3!#TZrr4J&%+ R3UG#Tbm+)QhqI#"C6T!!+Qlrp#9U!"B!(N+U!#,TkJ(#!!46J'F'9B"R('!`*@h q8!!b*@hq@!!f*@hq9!!k*@hq6!!qB"C#UJ!b*@hph!!f*@hpf!!k*@hpe!!q3US !3NcI$!K1ANjd!"!U88j@rrK)ja!N5(J!!L*YrR!J@8k3!#TZrr4f!#4YrYaJ)ZR U!F)!"'F8,`SLEIjN)&P1N!!UE[rd!QVqI`!%8S0`4YA!F#1fJ'hB5(J!!L*YrQ` J@8k3!#TZrr4-h`3)6Pj1G5T46PErq%MR'#4i!(B!*'hqh'!LkHS"`J!%Ca3[#L* YrQ!J@8k3!#TZrr4+J'F#H2p5Jh"'eF"`)lD!EGJJ"%cI""K1ANje+P%[$#K[!!J LE`!-)%`L%@!B$"!!$@B'%,`!#Q!+$"!!#QB%%,`!$9+))!&6J8U!CZ!SAdjd!!J U85"[!!3KD!!@!"iKD!!D!#)J+!!5`+J!*T'S!#)KD!!5!#j1G!!%+P&19[ri51F 30#4Z!!JQEJ!-)'S!(T(U!"BQ#%U$Ce3P3`!L##S!"J!&CK4)DJ!L,bS!&L*YrSJ J@8k3!#TZrr3[+J"#5'S!)LmU!"B[%L*U!$SJ@8k3!#TZrr3Q!#!,C`3QUJ!L5S0 R"#!$B"JJ+J!LdDS!%Lm+)QhqK#"C6T!!+Qlrp(!!60m-#%jH6R3!##T46PErq%M R($3NEJ!)*Qi!$#BZ!"!S,J!8kHT4`J!%kHS!!`!)CJ4+K@B'F2pJ!!$+5S0R%R! "YS"R$(!#YS"R"R$rB!!!Y%UU!"CR'!JU!!3!#'F3,bS!&L*YrTJJ@8k3!#TZrr6 [kM&#!!3#+J$[!!JJ5P#)A)JP5!!@)%T3L&b)*8J!(R!"*8!!'N+U!#*#UJ!Q5S0 R"R!"Z)"N#L"U!"j#%(!!B&)J#fBH,`3LEIkF)&P1N!!UE[rd*N"+J'B%F2pJ0J! U!"!!##9,!"BPDJ!@!"iP4!!D3US!*ZRU!F)!"&1!CK)J"!+!!!!"rfB)*A`!!!( r!#C`!%cI$$K1ANjd!"!U88j@rrK)jaJN+#i!##4Z!!cTkM(#!!4#UJ!L5LS!$@B %5S0Q"R$rB!!"%(!#YS"Q$#*YrL3J@8k3!#TZrr6TkJ!$!!KQ81RU!)-!"()#`)& R41RU!)-!"()%`)&R(NKi!!*#Tbm+)Qhq1#"C6T!!+Qlrp%U!C`C`!'!!!-!#+J! I!!J!+J!J!!J[#L*YrS3J@8k3!#TZrr6TkJ!$!!K6!'F3&A`!!3!03US!)R$rB!! !M1RU!8)!"&8!C`iJDJ!HNHS!&V(U!"TQ)N+R,`SLEIk!)&P1N!!UE[rd5S"R$K9 m!!%!$8+U!#*`rf"38kS!)L"U!"j5UJ!H%)6TkJ&#!!49!'FdkHS"3J!%C`C`#VL !CL*#Tbm+)QhqJ#"C6T!!+Qlrp%U!C`i9I!!"!!e#UJ!LF2pJ#%+U!#*`!"!%60m %'%jH6R3!##T46PErq%MR%!4f!#"YrR4`!E#3!'B%F!&JCNKi!!-LEIj`)&P1N!! UE[rd)'hqG%U3!'Bm)Qhq*#"C6T!!+Qlrp(!!,`!LEIl8)&P1N!!UE[rd5N"R#L" YrR4`!L#!B")JEIkS)+hqd#"YrR4`!5#!GJ&)H!!$)QhqE#"C6T!!+Qlrp#!$*Kp 1ANje+P&19[ri51F!*#4Z!""Krj!%E%U!CJ4`!@!d)'hqh%KS!%BLEIjJ)&P1N!! UE[rd,a)[,J!-)Qhqb#"C6T!!+Qlrp#5!F2q`NQB%F!&J!R!!*&p1ANjd!"!U88j @rrK)j`!N*'i!%'(rN!385S"Q"(!"B#![%LmZ!!`LEIl-)&P1N!!UE[rd*)"`rl# 5CJ4`!@!#F!!NAdjH6R3!%#T4F!"1G!!%+P&1G!!%+P&1G!!%+P&19[rd51FI2#K Z!!JX,J!-+#i!%#4Z!"3Q"N`%-!"+JfF15LS!$@B)kHS"`J!%CJC`!'!!!LETkJ( #!!49J'B-)Qhq*#"C6T!!+Qlrm!JU!!B!"@FLkHS"`J!%9i"R'1RU!8)!"&8!C`l TkJ&#!!46!'F%F!"J!R!"+J$TkJ!$!!KQ81RU!)-!"()#`)&R41RU!)-!"()%`)& R(NKi!!*#Tbm+)Qhq1#"C6T!!+Qlrm%U!C`C`!'!!!D3#+J!I!!J!+J!J!!J[#L* YrS3J@8k3!#TZrr$TkJ!$!!K6!'F3&A`!!3!03US!)R!!B!!"F#C-H!"+JfF!!2! JDJ!HXHS!&QB'5S9R!!$J)'S!(T(U!"BJ+J!DN!#)*8!!)TR-,@S!)[rdYUlrp'3 %,82rp1RU!8)!"&-!CLa+V[rdCbB[,[rd5(J!#Lm,)Qhq,#"C6T!!+Qlrm#K!5S" R#L"-8SL4bbe)rr4+V[rdCciLDJ!H)%XJ,[rdFL#`J@8%SLjJ$NU!C`SL#4,B8i" QqL*"eqlrp0LZrr5@V[rd)#lrp0'U!"iJ,[rdNDS!)NUU!#*R$#!-CJMTkJ&#!!4 Q*%+R,`SLEIk!)&P1N!!UE[r`,J"+KfF1&A`!!3!03US!)RB!B!T+JfF'5S9Q!2m f5S0R@NU&CPBSDJ!@+LS!'L9,!"BP3`!D)%[4`b9)!"j)E[rd,`SLEIk!)&P1N!! UE[r`5S"R#K9m!!%!$8+U!#,BV[rd*8`!&L9&!"S[#L*YrS3J@8k3!#TZrr"#UJ! LkHS"3J!%93"R"%+U!#)J"0#'8i"-4J!!60mFq%jH6R3!%#T46PErq%MR'#3NEJ! ))!TQ"($rB&VTkJ(#!!4Q"(!!B%i[#L*YrQ!J@8k3!#TZrr3Q!#m5)QS!2L"C6T! !+Qlrp#J!!QVqI`!%3T))+J!%!!KR%#mU!"BLEIkB)&P1N!!UE[rd5S0Q"%U%C`4 `rf!#F!"-h`3B6Pj1G!!%+P&19[ri51F3*#4Z!!JJ#QB3)QhqM#"C6T!!+Qlrp'! !!+"++J!0CJMTkJ(#!!4Q"R$rB!!!M1RU!!-!#!`!!!0P$!)U!"m!#!!U!%!!#1R U!!-!#&8!CJ4#UJ!LkHS!!`!)8`"R#J)U!"m!#(!!B&$TkJ(#!!46J'B5,`SLEIj !)&P1N!!UE[rd*J"J!RB!3UF[#L*YrS!J@8k3!#TZrr4+J'F1&A`!!3!03US!)R$ rB"!#+J!I!!JP3`!53US!)R!!60m%#%jH6R3!"#T40#m!"R)!)'hqA'!1Y&"Q"#! )B!j5JA")dF"`)l+!EHa`!%jd!!3U88j@rm4)ja!m*Li!##KZ!!`NEJ!3*Qi!&%+ Zrp)p3rrH,8crjLe5rqT#E[rb)!YR*%KZrmBLEIc3)&P1N!!UE[r!B!SL5b"C6T! !+Qlr`%TZrpCZm'!35'lraL*Yr1!J@8k3!#TZrm!NV[rZ$'lrfIr@CJa+NQF%F!" J%(!#B!a+E[r@CJ4`!'!#F!&-ha`)6Pj1G!!3+P&19[r%51F32#BZ!!JSEJ!-*'i !%#CZ!"4#V[r5282rhLe-rqBY8[rU3QlrmL!,Cb4)E[r')QhpA#"C6T!!+Qlr`'! +)NXJ@8k3!#TZrm"+E[r@E["J%%KZrmBLEIfJ)&P1N!!UE[r!*+lrlNTZrpCQ"(! !B!*`!8cI(!K1ANjd!"!U88j@rm4)ja`d+Li!##CZ!!`S,J!3*'i!&%+Zrp)p4Ir H)!4R$P@!C`*J%$em!!,rmQ!12A`!!IrbB!C`!@!!!4!Y8rrd)!TR*%KZrmBLEIf %)&P1N!!UE[r!B!SL5L"C6T!!+Qlr`%TZrpCZm'!35'lraL*YrCJJ@8k3!#TZrm! J%j!!V[rd*J"+J'm!!,BJ,[rdd)-Y32rL)!TR*%KZrmBLEIe!)&P1N!!UE[r!B!S L5L"C6T!!+Qlr`%TZrpCZm'!35'lraL*Yr2JJ@8k3!#TZrm"+E[r@CJ4`!'!#F!& +J'CL3UlrdMe&rpiJ"'F19B"R!Q!32A`!![rbB!`pI!!"rr*J"(!"B%`Y8rrd)!T R*%KZrmBLEIf%)&P1N!!UE[r!B!SL5L"C6T!!+Qlr`%TZrpCZm'!35'lraL*YrCJ J@8k3!#TZrm!QV[rd5QlreQB%F!"J!R!"60m-1%jH6R3!%#T46PErI%MR%#3Q,J! ),`0Krrrrr9SN3$e$rjC)E[pq)Qhp8#"C6T!!+QlrH$B!CLSJ#QFQ)%T3L#e)rj! !2@S!![q8,@S!"2qZ5'lrIL*YrA3J@8k3!#TZrhJf!#!+C`*#8NT$CJ4`!'!#F!& -h`3)6Pj1G!!%+P%LE`!%kHN4`J!%$!%!!@F'$!%!!QB'5LN!$@F-)'hq5(!M))" `rf!dkHN!!`!)CJBJ+3!5B#BJD3!HNHN!&L)T!#l5L1RT!!-!#!`!!!0P#ZRT!!- !#&@!NS!J!8jd!!3U88j@rrJ[$5mZ!!JLEIj%)&P1N!!UE[rd6Pj1G!!%+P&19[r i51FB0#4Z!!JQ,J!3kHT"`J!%$!3!!@B'5LS!$@F1)'hq5(!M))"`rf!!!4ETkJ! $!!K6!'BX3UF[#L*YrS!J@8k3!#TZrr4+J'FB&A`!!3!03US!)L"YrNK`)b#!F2p J!!$JF!'fJ'B@GJ![#L*YrN3J@8k3!#TZrr3S!0QZ!!a`!VD!CfETkJ#$!!4A!'G FkHS!!`!)93"R#ZRU!!-!#&F!CNJJ,J!-X+S!%Q3+)#i!$,#U!#jN#!)U!"m!#'! b)#i!$*!!UJ!Z)'S!&Y(!*8J!(L!U!"+3!+i!$#9!!#)#+J!I!!J!+J"!!!KJ"J) U!"m!#1RU!!-!#'C'*QS!-L!,Cc![+J"#,`0)EJ!-,a)L5b"C6T!!+Qlrp%U!CaB 9I!!"!!e#UJ!L)'hq5(!M))"`rf!33LS!$#9Z!!`!%N+U!#*`!%cI$"K1ANjd!!` U88j@rrK)ja`N*'i!##SZ!!`S,J!3*J8["#m$,`SLEIim)&P1N!!UE[rd60m%1%j H6R3!$#T46PErq%MR'#3NEJ!)+#i!$#BZ!"![!bm%,`SLEIiS)&P1N!!UE[rd)!T -h`3B6Pj1G!!-+P%[#bC[!!JN,`!-)#m!%")#)NY5J'!-XKPQ##"*8iJJ#'!'8i" Qm(!!*Pp1G!!-+P%LE`!%*#m!##![!!`5!L"*dF"5J'!)XL"Q"#!)B!C6J'EdF!" 1G!!-+P&)ja`!)'m!%#J[!"3U,`!BGJ!@"(!JZS"PAR!$+!K%K-L!5S4R#*U%%-0 6K'Ek5S0R&L!$FK$MU#)$G"MPUB+!)!2KL)#"KS!S"HU-5S4R&#$$)--J`b$$)-- J`b$$)-06K'EXH"r)KH5-5S4R"L$$8i4QqR!$bS"+K@F'%-06K@Ek60m!1%jd!!` U85"YrU`JVIk3!%je+P%[#b*[!!JQ58+V!!3J5eL)*dJ!$#G)!!JQL#0YrK3!%#0 YrK!!&#0m!!#!!!!B3UN!(%+T!#"#U3!N*Pp1G!!%+P&19[ri51FF2#4Z!!JQ,J! -+%T+JfF'F2LfJ'-'F!"J!!$D@)0`r#)$9S(#J#B"YUS!''9!5US!%'Fk5US!('B dH"$BJbm+,`3LDJ!3)&P1N!!UE[rd+J![#Lm%,`9Kr`!!!9JQ3#!,CJC`!'!!!)j fr-D6B(*`%,D!C!*f%#m$,`aKr`!!!I)Q3#!,C``[#bm-BIm!!!'bB%"+UJ!3Cc+ fUJ!BBJKi%0LU!"KJ"(J3f)-[#Lm%)QS!%#"C6T!!+Qlrp#S!,`S["#m&BIm!!!$ X*N!J#fB%F!"J)Lm$,`X[$'(r!!!"`LB!F!%L%i+!*S&`!S'c1!!J5eL))!K-ha` i6Pj1G!!)+P&19[ri51FB2#KZ!!JQEJ!-+!`J#fF!!)iN5eQ+F2iL%X+!*)&fr-D 5*NVA`h$p)K2#J#D"*d2rr#m+,`4Kr`!!!ISN3(EmaT)Q5YI$5U`!&'G)F!,!NQC #5UVrr'`m5T0X1#C+8BYCLdU6C`SJ8b&V!!3!"'!'+@X!"!!J5UX!"'F')'X!"## 6,``[#b*X!"3J@8k3!#TZrr4J#Lm+,`4Kr`!!!(*-ha`B6Pj1G!!)+P&)j`!B*#m !$#)[!"!SE`!85S*Q"(!!B%!L3R!3NS!Q58UX!#"R"L"X!#!JLd+6*f`!)!!%+8X !)&#*F2`LJ&L*)S%J!9Q!dm!LJ9L*F2`LJ#"#8)KBL#!)60mB!%jd!!`U85m,)Qm !##C[!!`J59L)*dJ!"#GT!!`!##"T!!`K5`!%)dX!$#CI6R3!##T4,`XQE`!))Qm !$,26CJBJ8bDS!!JJD3!))@N!"!!%)'N!"#&T!!J!##CI6R3!##T4,``LE`!))Lm !$#"4+%K`r-#3!,#"C3BLL#!)B!SJD!!)XFaQkR!!+&p1G!!)+P&)jami*Qm!+#B [!#a`r#)$9S(#J#B"+K0qr-k&+!HBJb4,eFFX%NU'E4a`!F#'CKB[#Lm[!#KKrj! %DRlmcSEBKpA(B!T`%,L!C!3J"f"#F!2!KB#$*S!S5pR$F!(!K@B%+82rr(!"`)9 +J'F%F!*J!R!!J)3SJ#9%rra`r5)5`S!NJ5m-,bm!+'(rrrrqkL!$60mFq%jd!!` U88MR($JSE`!F*'m!)(Mmb*)Q5YI%+K0fr-D&5S9Y'R!"`)9Q&#m,,`aKrrrrrYc BJh!$`*+!K#5!*LVrr(!#`**Q"%U$E!BPK%MmB"iQ5TI$,`X[$'(rrrrqX0D%F!2 !Ni#$*S!RJcMm*%XJ#NcI($K1G!!)+P&19[ri,`d[,J!))Qhpa#"C6T!!+Qlrp%j H6R3!##T46PErq#m0,bi!##*Yr4`J@8k3!#TZrr41ANjd!!JU88MR'$K2lrr`*Lm !+#K[!#`QE`!`*%-II!!"!!*#,`!$3Lm!"%)[!!9#,`!'3Um!#%+[!!a5LK!55F! Q!()PX)&Q("p$!!G"l`!#3p-Lf#,B)YJbf#"+8SJJ#'!!!U*i!5!$")!!!!!JCb" AJ'FX8B"R%&@!C`CAJ'FSB$4#,`!#B$!II!!"!!0J+!`[!!%!!fFJ(h`!!J!$B"J II!!"!!9J%%S[!!*R#Kpm!!)!!Q!#H!"+K'F)8SS@%NR$B+"`+VD!CMjBP#"8,fM rr!!)5UMrr'`13Lm!!L![!!K%J#p!!!K5LKB55F0J+R!+6#m)!!!)FY$5Jp+!,d% !#&++&K**`h!!%!-JEIl`%$!)!()3`)&QeJb[!!!"r3!)EaiII!$r!!G"l`!#3p- Lf#,B)YJbf#"+8SJJ#'!!!F4`,VD!CPSII!!"!!45LK!55F!Q!()UX)&Q0&L8)&3 [D2rm!!a+U2rmE!4#,`!%8SS@%NR$B#T`#N`[#!!!$(,3dS25J#p"!!a5LKB55F0 `!"!$)'hqm"!`#!"b%-#"CYCi!3b$!!!!D'F5$)-!!!"XCa)-J`!!!%aR%Q!B(h` !!3!'B")II!!#!!CJ#Kpm!!3!"Q!#H!"+K'F'8SS@%NR$(d-!"b!$")!!!!"&C`! !L&@!ChB%J!!!!"&R2&'!9i"R!!#d8i"R-&1!CfT6J'GQ8i"R9P@!Cb"EJ'F!!,a 6J'F@8i"RGPH!C`!!S&@!C`KAJ'F%B!!!XJ`[!!3!"QB'(h`!!`!'5Lm!"'B+F!% [3!!-B!!!QJ`[!!)!!QB!!*!!(h`!!3!#B!!!KNU[!!aQ"R!",d!!$!`[!!%!"QF )$#m!!J!'CJJII!$r!!GJB%S[!!4Q@R!',d!!$'"5(h`!!J!'(h`!!3!&(h`!H!! (F!J[3!!-B$K+,`!%CJC+,`!'Cb`II!$r!!GJ*%S[!!CR(Kpm!2m!"f!@$#m!"!! 'CJiII!!$!!CJ"Kpm!2m!"d([!!*$db,B)YJLf$,B)%T5L#!)6qm!%%cI("K1G!! -+P&)jam`+#m!)#C[!#4q!#S%*%Y#)R`!5S4Q'NU[!$*Q&%S[!#YR#!`[!'m!,@F ')!TJ!!%JF!!3,`!Y")!!!!"BCc44J&Q!Ca*EJ'F1AB"R&Pf!CaTAJ'FHB#*f#NU %E"a%KAi"B"Cf#%)[!#PJ$RB+3Lm!+@!'GK"#,`!T)!9-3`!"+!&-3e!&F!UiJ'` 'F$$BJ'!@F!UBJ!`[!(J!,@B'F'(BJ'!%F%(BJ"8%8SC+K@E+F!LfJ'B55Lm!+fF -$")!-'F'&6`!-&+'$#m!!J!SCL3[E`!Z!$*+KfB'5Lm!+@F%8km!-R!3YS"Q#NS [!#YR"&@[!$)J5j(+)#m!-Y#)$)!!!!(pE`T`!'"'&6`!-&+'[+m!-QhdF"#fJ'B 15Lm!+fF)&5m!,48m!$"+KfF'&6`!,@!D$#m!!3!TCJB92!!VB!`-,`!#!#PQ""8 m!#!J#NcI$2K1G!!B+P&)ja``6qrrk#C[!$Kk!#p[!$!!##p[!$3!$#4,3L*i!%+ R3UF[,`!m,bm!2'(rrrrQC%T!CKT+V`"'CK4+,`!rC`J-,`"[!%&R"L!+B!!"hR! !%#m!335!!!!!@'Gd8B"CJ'F5@i"R$Pf!Cd*GJ'G39i"RAQ"X3Um!%#pm!!!!#J! 83UG#Tbm[!$`[,`!mBIrrrqBX5N"X5Lm[!!`[,`!-5'm!%'(rrrrNBRS"B$4#V`! 3,h`!!!!)!"4#,`!pB#*#V`!3,h`!!!!+!"4#,`!pB""#V`!3,h`!!!!3!"4#,`! p,bm!&#m[!"3[,`!8,bm!&%K[!""KrrrrjA3Q+!!%,bm!&#m[!"3[,`!8,bm!&%K [!"KKrrrrj6"`#VD!E!C`-0D!B"C`#TD!$#m!H!""CJC`BGD!B!4`3GD!&305K%+ R3UF[,`!8,bm!&'(rrrrP4%T!CSa)H!!)3UF[,`!F,bm!('(rrrrP,%T!CK*+,`! rC``-%J!`C`B92!!`8S3-,`!#!$aQ0Lp[!%)!4NU&CJC+,`!pC`46V`"'5(J!%%+ R,bm!(#m[!"aKrrrrj1C+3'B+5Lm!2fF%9Dm!4L",NFSJ,`"'d)J-J!!!!Ie[#R! !B&J92!!`8S5iV`"'EI4)H!!33UF[,`!F,bm!('(rrrrNSNT!CJj+,`!rC`J9,`" "&6`!-%U&C`B92!!YB"S-,`!"!$eQ"K8m!#YJ$!`[!!)!2@B%&6`!)#!+6qm!'%c I$$K1G!!F+P&)ja`i*'m!(#B[!#"+Jf`@3K*#DJ!#&A`!!3!%&A`!-!!&B!!!VR! !%#S!",D!E!!!SLC+@S[A`e+,'#0*a(,3f)%-"!!&CLa`!"!U!!3S5PU-f-"6M,R ,B`B-&!!`Cr5jbfB+%#[rrh)"`)&J!R!"+J"J1J`%!!9H`%3!5F!U!'!X'#0*a(, 3f)(BK3`%!!PH`%3!5F!U!'B%5J4Q"&1$B!`3"%R!FM$3J4D!B!4+JfE35S9R%P* U!!)9I!!"!!39I!!a!!9J#NU$C`$r4"9$!!4-ha`i6R3!##T46PEra%MR($3QEJ! 8$+i!!!(p!#*["R!!B!!$`%)ZrmipI!!Jrp")E[r5,bi!%#mZ!!`[,J!)5'lrcL* YrF`J@8k3!#TZrm"`!"!ZrpC&l[r5@SV8`'!)8blreP*Zrp3-,J!"rpCM"J`L!$" RkR!!%#lre`5!!!!!-'F1")!!!!!CCa"EJ'G3B'4#,[r53Qlre'"D3Ulra%+ZrmK #E[r-5'lra%KZ!!Jr2!!)UHYX%L4,@iSJ5L*YrJ`J#"$CC[aJ%#4,@BSJ5L*YrJJ J#"$CC[`J#Q!!!`BN5eQ+)%SLEIi%)!J3f@Em)!TJ!!,`F!!3,[r@8i$4E[r8*%Y #)R!!%#i!(35!!!!!4@F!!,49J'FB")!!!!!HC`!!TP1!C`!"RP1!C`4J!!+bF!! 3,[r@X+i!)Qm1,bi!)NKZrp*KrrrrrHB-E[rmrp4Y$$!Zrp4)`,#Z!#*Y-%SZ!"Y R"P1Z!#*J$(!!%#lreP1!,8!!)J`Z!'F!(@B)(A`!C3!GB%!GI!"&!"eJ1%SZ!"Y R%$!Zrp4)`&+!NDi!)Q!!!5)`,[r85-"5J()!%LlreT+!,8%!)NU"E!!"#%+Z!#* J!!%!)#i!)P+!FJ!5,[r@XS"[%L!Z!#*5J#m!5'lrdQ(rrrrp5$JZrp4)a(SV5S4 X"%5%HLef!'!D)!4-I!J"!!!!#R!`dS!9!8am5!3!!!!+8S0+K'ELF!+fJ'hF&38 9,J!G)%Z4bL!Z!#,3L!b!!!!"r@m'F!"J!!'Q)#i!)P+!FJ!5,[r@XS"X'(!!%#l reLJZ!#*8K*L!B!392!!`8i4Qq(J!'#lreR!!%!4(l[r5@S[@`'!#&506K'Ek5Ui !)QB'5Li!'fF%&6`!,K8ZrpG+,[r5C`J92!!YB!!"3!`Z!!%!'@B)&6`!+f!!!6! -,J!#!"PQ!!%Q&6`!)'!!!4j`!"!ZrpBb,[r85-&%JG+!8i%S!8U"E!*i!,LZ!#* [0#!%N!#Z!#*b!")ZrpD5J#m"5'lrdQ(rrrrm-R!!%#lreM)Zrp4)`85"dS"6J5J "5S&X!RJ!-#lre%M!8S!U!%U!E!*k!#!&d)3-J!!!!Ie["R!!B!!!UR!!%#lreNI Zrp*DLpE!GJ"J"K8m!$"5Jb!Z!#+3!)5fJ'h`GJ"J""8M8S1fK'`5F!!3,[r@YS" YlQ!'&6`!-&+$YS4YpNUZ!#*Q"NSZ!"YR""8m!#j+K@FNGJ"J"K8m!$"5Jh!!%#l reL)&NS#fJ@hXB!39)e+$YS9Yq'!%&6`!-%SZrp*R"K8m!#eJ'J`Z!!%!'@B'&6` !+f!-$#i!!J!CCJ392!!J)!T-h``i6Pj1G!!J+P&19[h-51FI2#CZ!!JNEJ!-IL! S5RJ!B!!&%%Ki!#8[$#*YrH`J@8k3!#TZrFJX!'Bf)%a`re+!5KKQqLB!f)0+JfF !"1`[#dKi!!%[!bm-)QhqD#"C6T!!+Qlpb%U!CJ!%d($rB!!%c#"'NF`Q#0L$5S0 R)#m,5(J!!5m$,``LEIjS)&P1N!!UE[h)5S"Q"R$rB!!%S#K'5'lrkNKZ!"![$'( rrrrcr#K!F!!3,[r[")!!!!!PC`!$&J5!!!!!)'F!!ET9J'F!!E3%J!!!!"&R!!$ m8B"AJ'F!!Z"6J'G#8i"R!!'B8i"R!!'58i"R!!'-9B"R,&Z!C`!#I&1!C`!!cPQ !C`!"rP@!C`!!`PH!C`!![!5!!!!!KfF!!VjJ!!+k$#i!![rZCJjBVJ!3)'i!%#S SrraJ+J`Z!!2rlQB@8+i!%#"Z!"!YD2rirH)YD2rmrHCJ$&LZ!"!JEJ!3+LMrr!` Z!!(rlQB%-%8U#!`Z!!2rlQBS3HlrqLmJ,b![)#mJ5'lrkLmZrHB[,[hLBIrrrrG i*%"+J'BNB!!#2N(ZrrS[)#mJ,b![)%KZrqS["@(rrrreqL4!5S"R!!)H3HlpkN( S!Iq4bLB)B!!#4J`Z!!,rlQB1@+i!%#"Z!"!U+2rmB#S-,J!$rqjQ&P#Z!"!JEJ! 3,@Mrq2hL,@Mrr2hQB!aBVJ!3)'i!%#SSrr`-,J!"rqjQ"R!!-!8U!!`Z!!2rlQB S3HlrqLmJ,b![)#mJ5'lrkLmZrHB[,[hLBIrrrrE+*%"+J'BNB!!"N!""l[rk,b! [)#mJ,b")E[rU,`9Krrrrp8`N3%U!C`!"F%(ZrHT"k!(rNFSQ#'!!!CJ-,J!%rqj Q(R!+dDi!%#"Z!"!YD2rfrGJYD2rkrG`pD2rqrH"J+&#Z!"!JEJ!35'Mrq%KZrFi r2!J1UHXYE[h1rGJYE[h5rG`pE[h@rH""l[rk,b![)#mJ,b")E[rU,blpi#mZrG` [,[hBBIrrrrNf*%"+J'F!!1K"l[hU3HJ"rj(+*JKJ!!%3@+i!%#"Z!"!ND2rm)!T Q"#4YrJ"+,[rYCaaf!"BD5Llrl'F!!1UfV[rdE`!!iLBZrr4J!!$D5Llrl'FQ*Ll rp#m$3UF[#L*YrM!J@8k3!#TZrFJX!'F!!,JJ4T(+*JKJ!!#Z)%T`re+!5KKQqLB !B!!!RPLZ!"!JEJ!3*'Mrr(!!%#lrlQF38i"R%P1!Ca46J'F@B!!"P#5%B!!"MM5 %B!!"L#5%B!!"JLm%,`TKrrrrh$4J!!&d4HlpkPLZ!"!JEJ!3&+MrrhB"B%4&l[h U&,`!*AB"B$JJ4R$r8S"+''Ek*J$BJdU$Cb![#dKi!!%[!bm')QhqD#"C6T!!+Ql pb%U!CJC`rf!!!5SJ"'!!!53X!dSZrqTR!!#Q$#i!![rUCJ4`-'!#F#!H!!`5!#Y R#!`5!#eQ!!##$!F!-'Ck)#X!)P1V!#*+J'F3)'X!(P+V!"i3NR!!%"*J&#m,%"* *`#m!)QhqH#"C6T!!+Qlpb&+!CJC`rf!!!,a5LP1$B$SJ+`!L8kX!)NU!Ca!JD`! H8UX!(K#(F!!3"f!8,`X3"dR!,`!LEIji)&P1N!!UE[h)8S"Q"($rB(a5KVbZrr" Y`%U$Cai[#dKi!!%[!bm+)QhqD#"C6T!!+Qlpb%U!CJ4`rf"55LlrkQC#B$SJ+`! L8kX!)NU!Ca)JD`!H8UX!(K#m!#"`!(!JB")[#dKi!#!LEIji)&P1N!!UE[h)8S" Q"($rB"*5KVbZrr"Y`0L'5K4Q!2VZ)!4-haci6Pj1G!!-+P&19[q`51F32#4Z!!J SEJ!-*Qi!%%Ki!!&)H2rr,`T)E[qb)Qhpi#"C6T!!+QlrV#m,,`a)E[qb)Qhpr#" C6T!!+QlrV#B!5S0Y"%)b1!!J!dcI(!K1ANjd!!`U88j@rrJ[$8KZ!"![,J!-,bi !##*YrIJJ@8k3!#TZrr41ANje+P%[$#K[!!JJE`!-)#m!%#*))%a5J'!1%0PQ#Q! #3KK6J'EkB!46J'EZ)!`SAdjd!!`U88MR'$!QE`!8+#m!'#4,&J4J$,J$CJJJ5P1 ))!KJ%KJDC["+!fF%NFKJ"#"+8iJJ#%cI$"K1G!!)+P&)jaJ`*Qm!&#J[!"JN5jI ,&J4J#,J$CJ3Q5P1,'"TQp#!,C`3J#f!15J0R"*()B!3J5P1))!K-h``B6R3!##T 46PErq%MR'$3NEJ!)*Qi!$#JZ!"!Q,J!8,`3[#b"YrH3[%#m+)QhqP#"C6T!!+Ql rp1rU-!-!##m+)QhqK#"C6T!!+Qlrp(!!60m-'%jH6R3!%#T4F!*1G!!3+P&`!%j d!"!U8A!!6R3!"#T46PEr3%MR'!3S,J!)5S4Y#R!#Z)"Z"(!!B(T#E[pF286r@%+ Zre*)E[p!)Qhp1#"C6T!!+Qlr2$B!-!0)`'Bm2@lr9[q8286rPNKZrhiLEIe3)&P 1N!!UE[mm0J!`!dM!CKT#V[q3!$eZreErP%KZrhiLEIdJ)&P1N!!UE[mm-!0)`'F +-!0)`#"YrNJJJ%T$CJ4`!'!#F2p-h`!B6Pj1G!!%+P&2lrrd,fm!&!!#,fm!'!! '2fm!(!!+,bm!)%K[!!B[,`!B,aF[,`!),bm!%$mm!!ZTke"2@%p2l`!-6R3!&!J N!4q"K!)K!3%LK"J#)3%")S3B!L%"!5+!Z!)N!4q(k)B#!3X!$#)5&!)K!3-L%K3 @)L3i!L)N-!)L*#J))4-6)K%8!L%"!b)4&"BL*$J#)L3`!L)N+!JK%4-L%"3#)3% $)K!8&L)N1!)L*$!#)L3S!*&%))&r!C!*!T!&!C!5"!L3$c#3#JL3"k#3"S#3&!L 3"Q#3"N#3&!L3"!'!N!G!N"N)N!G!#*!'J)!)N!j!3!L3#i#3"%!)N!K!J!L3"%" !#*!&J*!,#)#3"!L3#J%N,8PZCJ)M5@jQ!501B8i$)Kh!!+Y3)L-)JJ*,)a!M'#- J)bJM-#-i#XJM3#0))e!M@#0J)fJ+aJV##Vi+Z#0`)hJMJ#1))j!!)jJMS#1S)l! MZ#2!)mJMd#2B%aJMi#2S)r!Mq"-F*!!N##33*"JN)"-8*%!N5#43*&JNB#4S*(! NH#5!*)J2l!rS$q32i#53!#5B#q!NS"q8*4JNU#5`*,JN`#6S!#BNm#6i*3!+c!Q i*3JR*4!%,NP38!%J-39SEh0dFbGcEf0VCA4ICACPER4ID'&ZC'aPFMSJFfpMDf9 d)'j[G#"TEL"eFf@UrJF,)YIe!5%3!5%%!L)Ni!JK2`%J-408CA0d9(*KBfXJ9A0 PFL"*EQC[4A*bEh)J*@3J4f9dG'PZCb"6HA-J4@jfDA*[ER-")%T&ERC@CA)J*@3 JE@&MD&4jF'8J*@3JFhPc9Q9b)#9N)("bEf-J*@3J4P"9)#9N)%0[E'pb883J*@3 JDf*N)#9N)'&d9Q9bFb!PC!)S*A-k*A-k*A-#*8eKBdp6!51UrJF-)58")4!")33 #)L6)!#SL2c`")`DTm!)Lrrd5)L,3JJ+""NVd)Y"+9#,35N`Ld%T%)Y"+2#,35HS Ld%QU)Y"*F#,356iLd%ND)Y")`#,33i3Ld$J#)Y!hj#,306BLd$3`)Y!clL,3-q) Ld$0@)Y!c,#,3-[`Ld$,))Y!bP#,3-83Ld$%Q)Y!`a#,3-&!Ld#lf)Y!ZGL,3,H) Ld#c`)Y!XGL,3+K!Ld#S+)Y!U"#,3+I`Ld#Qi)Y!TB#,3*jBLd#D5)Y!Q"#,3*G` Ld#@N)Y!PAL,3*2`Ld#3q)Y!Mp#,3)iSLd#&X)Y!K1#,3)3)Ld#"m)Y!J@#,3)$i Ld#!H)Y!Ir#,3(l`Ld"mX)Y!E%L,3&C!!)Y!1jL,3#(`Ld!K8)Y!%JL,3!i)Ld## B5c3#D!(J%L%"!5%-"#&H"b5+!3--!b-""J%")4`$*3&S!@%-!bB"r2rrh6J#)J, %!5)"%!-P!i)"!3J$)`5#!B%$"`J!!!63!!J!!!8i!3`!!!9`!3J!!#8&T!%K#!- P"I)"!3J$*3EH!3%)!b8(DJ&K#!-L#&3'*3Km!5!)!b8)[!&K4!-M#F!"!5&B!b8 +A!%M4!-P#e!")%J$*3['!3%X!b)-2JBP$&3"!3J$)JcJ!5)"#!-L$8!'*3f-!5! )!b80kJ%R#!-P$ZB")!J$)Jmd!5,M#!-L%$`")Q%-!b84#J(r#!-P%bi")3J$)a3 -!3%K#!-M&&S"!5%)!bB8T2rrh6i#*K8DrrrG4!)P&C!!!H%F!bB@`[rrh8S#*4F i!H!F!b8Bj!%J#!-M'GB"!5%F!b8DKJ%J$!-Q'a,rrpe3!L)GiJBL(LS#)3J$*4j L!H-)!b)Hj!%L!3J$*4mX!5-)!b-I[!%")3J$)Krm"L-JV!%")3J$)b$D!3%K#!- P)3)")!J$)L%i"L)KcS%$"[mB!!!Ld#!!!!!LpL!!!!!M(![rN!3!N!F"!!!Nf!! !!!%!!#63!!!!!3!!!%!!!!!"!!!"A!!!!C3!!!8)!!!!!3!!!!3!N!p!!*!)!J! !$3)!!"`#!!!Q!J!!-J)!!$S#!!"'!J!!6J)!!&N#!!"P!J!!F!)!!))#!!#5!J! !R3)!!+S#!!#k!J!!a!)!!-X#!!$D!J!!i!)!!1S#!!$i!J!""J)!!4%#!!%J!J! "-J)!!8X#!!&B!J!"C!)!!AB#!!'(!J!"N`)!!D%#!!'U!J!"[`)!!FF#!!(6!J! "f`)!!HJ#!!(e!J!#!`)!!JS#!!)D!J!#+3)!!M3#!!*#!J!#8!)!!Pm#!!*[!J! #IJ)!!SF#!!+5!J!#QJ)!!US#!!+i!J!#aJ)!!Y)#!!,K!J!#l!)!![N#!!-"!J! $$`)!!ad#!!-M!J!$,3!"!*!&(!#3"!4"S!!!2%)!!F1!)8)!S!!!JN)!!F1!)8) !S!!!b%)!!F1J!"qB5Mp#6!q"S!!L&%)!J1p'38)!5@jdCA*QB@0P6'PL!%CbB@e P8QpeEQ45C@0d!%GPG&G%5@jQE`"33P*PB@4"FhPZB`"0EhCP5%KT!&0jFd9ZGQP bEfjc!%K9EQa[BfX!8%*5C@&N8hPZB`"0Ef4KE%4TB@a[C`"2F'9Z4(*TGQ9b!%0 KE'a9EQPfCA*cB@a3FQpM!&"#5%GPG&C*EQC[8hPZB`"9Ff95CA0'D@aP!&"#8f9 d48p'8hPZB`"33NK(CA4'5@jQEe0jEQ-!6Q9h5'&ZC'aP!(!bBh0dFJ"%CA4KBfK 5CA0[GA*MC3"%C@aKH3"8D@0V3fpeER3!4f9d4'PKE'pR5A4PE3")D@aTG'9$Efj dFQpX!%4TFh"[Ff93G()!8%*'E(9cD&C[E&0jEQ-!4f9d4'PKE'pR5A4PE94PH(3 !4'PcF'pcC9*[GA4TEQ9%CA0MFQP`G'pb!%GPG%jPGd4TB@a[C`""C'45CA0[GA* MC3"6CA4%D@&XEfG*G'9Y9'9iG!"33NGPG%C$3NPZCQp6H@jM!%GPG&*PFfpeFQ0 P!&"#8f9d48p'3A0jEQ-!4'9LG@G6G()!6Q9h8QpeG'PZC84PFf0bDA"dEh)!8f9 d8'pbG!"33N0XEh0P8hPZB`"(CA43Eh*d!%0XEh0P8Q9c4QPXC3"33PGbDA4P3A0 jEQ-!8%*)4f9d9QpX8hPZB`"M-R"cG()!3fKKEQGPC&*PFfpeFQ0P!&"#3fpZG(* [E%&cH@jM!&0jFh4PE94KFfX!8%*)4'9XCA4P8hPZB`"%DA0`Eh0P4'PKE'pR!%G PG%PZC&*PFfpeFQ0P!&*PE'9KFf95CA0[GA*MC3"33P0PG%C3Eh0"FhPZB`"5CA0 &FR*[FJ"'D@jN4QpXC'9b!%GPFh4KE(3!6NGPG&4bBA""C'4bCA0c!&"#8f9d4P" [Fe0jEQ-!8%*$EfjdFQpX8hPZB`"33PGbDA4P8hPZB`"'8h"2F'9Z8Q9c4QPXC3" $GA*5CA0'D@aP!%K2F'9Z8Q9c4QPXC3"3C@j6DATP!&GbDA4P8Q9cEh9bBf8!4'P cF'pcC8KKEQ4XC3")6'pMD`"*ER0PG&*PBh3!6Q9h8(4b!%GPG%*64%eKBdp64A* bEh*(E(9P!%GPG%*64%eKBdp64A*bEh)!G'9cG&pdFQ&MDdGXG@8!G'9cG&pdFQ& MD`!!#!!!!!J!!J!8a+F!%$dd!!jkQJ!+TjN"!!-d!!!LX!!"!J!$53!!*-J!!3% !!eS!!#)!!!%#!!0T!!!Ni!!"!*!)5Qpj)A"PCQC`Gh"M!!!!!E(413S!N!d$!!) !N!6rN!3!N!CR+!!!CbJ!!'FS!!!'!!!%"!$rN!3!N!BP&!!!%2%!!!3G!!"Y-!) ""!$rN!3!N!i&H!!!!)!%"!3!N!ArN!3!N!F"!!!#H!!!!!%!!!*`!!!!!J!!!%) !!!!"!!!"I!!!!DJ!!!8i!!!!!3!!!!3!N!p"!*!,$3#3#`%!!!""!*!%!J!!&3) !!#3#!!!Z!J!!1J)!!%)#!!"1!J!!9J)!!'%#!!"Y!J!!H!)!!)S#!!#D!J!!T3) !!,)#!!$#!J!!c!)!!0-#!!$L!J!!k!)!!2)#!!%!!J!"$J)!!4N#!!%S!J!"1J) !!9-#!!&J!J!"E!)!!Ai#!!'2!J!"Q`)!!DN#!!'b!J!"a`)!!Fm#!!(E!J!"i`) !!I!#!!(q!J!##`)!!KN#!!)J!J!#-!)!!Mm#!!*+!J!#@!)!!QB#!!*e!J!#K3) !!T3#!!+G!J!#U!)!!V!#!!,!!J!#cJ)!!Y`#!!,S!J!#p`)!!`3#!!-2!J!$&`) !!b8#!!-V!J!$13)!!d-#!!0+!!%!N!89!*!%5N&#&%!"3J&!!8)IJ&0'&35"#S% #!3""!8-"`3""!8-"`3""!81+!d#'!!"*ER4PFQCKBf9-D@)!6@&dD%aTBJ"'FQ& YC9*[G@jN8Q9MG!"(CA4A4%PZCQm!8%*5C@&N3A0jEQ-!6@pfC8K)D3"6HA0&ERC TFQpZF`")9@jXEf0V!&"#8Q9KC&0jEQ-!6@pNB@a%D@&XEfF!6h"PEN4bDACPFJ" $B@aX9@jTGQ9bFf&X8(*[B`"33NK(CA4@5@jQEe0jEQ-!9A0P8Q9c4QPXC3"33P0 PG%924P0jEQ-!8%*)4f9d4NPZCQp6H@jM!%jPGdKKEQ4XC3"`-Q0cG()!4'9dB@0 S8Q9cEh9bBf8!4'9XBAN!9'PMDd0[G@jd!%GPG%4TB@a[CdPdC@d!5'PXDA4P3fp ZG(*[E!"%DA0`Eh0P8(4b!&"#4QaeFfK@Efa6H@jM!%GPG%4TB@a[CdPdC@e8CAK d!%4TFh"[Ff95Eh9dD@jP4'9cBh*TF(4[FJ"(CA41CAG%D@&XEfF!3@4N8Q9cEh9 bBf8!8f9d4'PKE'pR5A4PE94PH(3!8%*(CA4'3d**EQC[8hPZB`"(CA45CA0[GA* MC3"33P0PG%924N&cH@jM!%4PBR9R8h4b!%jPGe*[GA4TEQ9%CA0MFQP`G'pb!&0 PG&"[FR3!8%*$E'pcC90jEQ-!4f9d8'pbG!"$E'pcC9*PFdCTE'8!3Qa[BfY0EhC P4'&dB3"33PGbDA4P3A0jEQ-!8%*)4f9d9QpX8hPZB`"M-R"cG()!3fKKEQGPC&* PFfpeFQ0P!&"#3fpZG(*[E%&cH@jM!&0jFh4PE94KFfX!8%*)4'9XCA4P8hPZB`" %DA0`Eh0P4'PKE'pR!%GPG%PZC&*PFfpeFQ0P!&*PE'9KFf95CA0[GA*MC3"33P0 PG%C3Eh0"FhPZB`"5CA0&FR*[FJ"'D@jN4QpXC'9b!%GPFh4KE(3!6NGPG&4bBA" "C'4bCA0c!&"#8f9d4P"[Fe0jEQ-!8%*$EfjdFQpX8hPZB`"33PGbDA4P8hPZB`" '8h"2F'9Z8Q9c4QPXC3")6h"PEP*PFdCTE'8!3h9b8Q9c4QPXC3"3C@j6DATP!&G bDA4P8Q9cEh9bBf8!5%a[BfX!4'PcF'pcC8KKEQ4XC3"*ER0PG&*PBh3!6Q9h8(4 b!'jeE6*NC@-!4f9d3P0%6@&M6e0&FR*[FNGPG%*64%eKBdp64A*bEh*(E(9PG'9 cG&pdFQ&MDh4PFh4IG(*KBfY(E(9P!!!!#!!!!!J!!J!3263!&-5R!!URQ3!1HTS #!!05!!!#J!!"!3!$BJ!!!pJ!!3)!!hB!!!*S!!%"!!1!!!!$,!!"!*!)I!J#TT! !!3!)P#(r`$JK!%#!!3!)I!J$TNk!!#"m#!+QNq(rr*!!!3!)P#(r`$aJ!!%iBkT Z1)!!!8J!Ab'!33!8I(mEH$aJ!!%iBkKZ1)!!!8J!A`Q!33!8I!2i3%##!!`iB!) !5!!!#$KJ"!#!!3")1#%!3(`)!kD$iIrm6S!!)&4N"5P!JJ!-1'!!!%k!!#!iB!! "6S!!)(`)!UD6iIrmNm(rq*1Krr53!!%!#*3Krl"mIaYiIq2lH%[rrmPmIKYiIm- (G#`$!!&!JJ!J5rrr8AaM"c4Ar`9qIq3(0(`%'!""J!!)1q#SRhrMqhKra20i5!" HDB""!"4mI4Yi2'!!!6KMU*miJ!!"5!"H8B""!"4m!qK!I+!!*P5P(rjSS`!"J!% !@$JK!&"m#!1QJq(rr)2"rrL$SIrd6S!!)(`)!UD6iIrmNm(rq*!!!3!)P#(rS(a q'hKmRb0i1'!!!6L"!$a)!&iTJ%%!&+KK!%Tra20iIqAlH$M"!$K)!&iTJ%%!&(a M"c9"JJ!81'!!!,"q!!!iJ!!!N!#I!!#!!3"S1#%!B(`)!kD$iIrmJm(rq%k!!#" m#!+QNq(rr*2"rrL6SIrdN!!"!!L8)Iq`I(dEH(bH)hJli!!!1'#KV8[rrX&8B`B r3B)!*$aJCQmiBfaN1)%!1%J!AB'!33!8I'-(08##!!Jli!!"9q-'2d##!"4rSqY iIm6cH%[rrbP)!!!m1'#!!$b!Bh3iK(*X1+!!!(qQkhKrar0i5!"GKB""!"4mB`F e3B)!&$L!!!#`R3!!1+!!!*!![J!!J!%!@$JK!&"m#!1QJq(rr)2"rrL$SIrd6S! !)(`)!UDrBIrXN!!"!!L8)Ii`I(XEH(bF)hKm[5YiI0icH$KJ!!#3!'%"4$L"!$L 3!)%"5V1K!8k6`3&S1+!!!E#K!94)!!"mJ-%"@(`'f%"!JJ"JJ1%"A(`(i%"!JJ" 8Ik2VH(r%mhJiS3!i1-!!!8J!A2@!33!8I(mEH$aJC'iiBh*`1)!!!8J!A2@!33! 8+!-!!%##!"4rirYi5!"EmB""!"4)!!!-Iq2lH%J!!#bT!3&813J!!E%"!956`3& S1'%"1%J!A0'!33!8I'-(08'#rhJiB2rrJ!%"f$JK!G"m#!1QZf(rl%k!!#"m#!+ QNq(rr*!!!3!)P#(rX$KK!$`iJ3!i5rrq36aJBf3iBf9f2)"kG$L%Bh#SS3!mJ-% !1%[rrZ9mIaYiIq-(0#`$rrp"JJ!-Iq2lH%J!!)JiB3!m1)%!1%[rrBdmB'0N1'0 PGMb!EA3iK'0`U+%!2)$"!$K,rrkPI(mEH(rN"c3X"2rr3B)!$(rMqhK)!!")1'% !2$L"!$K,rrh"2'"MC$KMCABmJ'ed1)4MF+LK!$b!`3!i5rrqCAar'hKrj3Fd,!A rrd'#!!arirYi5!!!#$KJrrq!!3"B1#%!8(`)!kD$iIrm6S!!)(`)!UD6iIrmNm( rq*!!!3!)P#(r`*!!B3"BJ')"p#J$!!""JJ!-1'!!!%J!!-a,rrlYI(mEH$aJC'i iBh*`1)!!!8J!@fQ!33!8N!"L!IL!JJ(i+!3!!%##!"")!&SaJ%%!&%J!!*5!BJ( i5!"EFB""!"4rj3Fd,!Arrd'#!""rirYi5!"D1B""!"5!BJ(i5!"ECB""!"5!BJ( i5!"DDB""!"5!`J(iJ-B!!*!!`J(dJ')"p$L!!q%iS!!"J-%!@%J!@df!33!8I(i EH(r("c9"JJ!NJ')"q%J!@df!33!8J')"q%J!@eQ!33!813!!!*%#!I4r`r0iJ!% !5$JK!%"m#!1QJq(rr)2"rrK1J!!JI!J#TT!!!3!)P#(r`*!!B3"BN!#"!&b3!+% !B*!!`3"NJ')"p#J$!!"!JJ!-1'$rj%J!!#b!BJ(d2)!!!6L%rq%iS!!$J-%!@)$ K!&b"!3"JJ5%!C%J!@Uf!33!8J!%!5$JK!%"m#!1Q6S!!)(`)!UD6iIrmNm(rq*! !!3!)P#(r`*!!B3"B1q)4r$[#%I5!B3"B1))3mB#L!Aa)!!-CB!!!!#`$!!""JJ! -1'!!!%J!!$b!BJ&mN!"q!!!iJ!!!N!#H!!3iSK$aN!#r!!!i`!!!N!$I!!3ii!! #N!$r!!Jj!!!%N4m!$*2I!""rirYiJ!%!5$JK!%"m#!1QJq(rr)2"rrK1J!!JI!J #TT2Krrb3!!%!#*3Krm!iBJ,i1))#$NJ!AI'!33!8I(m(0(rMqhL!!3")1#%!3(` )!kD$iIrm6S!!)(`)!UD3!!%!#*3Krm#!BJ))+!-!!%'#!"5"JJ))5!"H+B""!"4 )!!!)1'!!!)!"!%Ji)3"!I!J$TNk!!#"m#!+QNq(rr*2"rrL3!!%!#*3Krm"mIKY iU(i!!#`$!!&"JJ!-U(i!!%J!!#4,rrqCI(mEH8'#!!arirYi5!!!%%J!@DQ!33! 85rrrd)!"!%Ji)3"!I!J$TS2Krrb$`Iri6S!!)(`)!UD6iIrmNm(rq*1Krr53!!% !#*3Krl"mI4Yi1q)5%+KL!JiX!`!!3))!(%[rr[PmIKYi,"i!!%'#!!ar`r0i5!! !Z(rMqhJiJ!!!1+!!CNJ!-lPJ!!!!U))#$V#I!"JiS!!QX,m!'T1r!"`i`!!HQ0m !)$MJ!!#Br`!K13$r`*NI!#*rirYi5!"F[B""!"3iI`!35rrr#Aaq'hKrirYi1)! !!$LJ!'C)!$0KB!!!!+NL!Jka2`!B18!!+V&I!"U6[`!FIq2lH%J!A-@!33!8UAm !%#`,!!"!JJ!3J(m!)%J!(M9J!!!!,"i!!%##!!LVh`!3Im2cH)!"!&Ji)3"3I!J $TS2Krrb$`IriJk(rp%k!!#"m#!+QNq(rr*2"rrL3!!%!#*3Krm#3!'%!@$[L%RL SBJ)1,!-!!%##!"a,rrhTI(iEH#`H!!""JJ!-1'!!!%J!!'arirYi1)!!!$LJ!'C )!$+TB!!!!+L#!Jk`R`!B1+!!+,#r!"U!`3"BN!$I!"arirYi5!"E`B""!"3iI`! 35rrq$Aaq'hJX(J!!3B)!$$KJ!!")!!!BS2m!2#J(!!"p!!!Q93JIrQN$!!'!!3" )1#%!3(`)!kD$iIrmJm(rq%k!!#"m#!+Q[f(rl*!!!3!)P#(rX*!!B3"SI*XMH*! !S3"`1q)5i)2#!Bb!BJ)%,!-!!%##!#`iBJ,p5rrl&@!!!!"mI3Fd,"d!!%'#!!a rSqYi5!!!T$L!!!'3!))#")"L!C!!1)!$`$LJ!!&)!&FeJ%%!&(am'hJiS!!"X,i !!)"K!'Krj2YiIiAMH(r'mhK,rr[0B!!!!)$I!!!X"UAq3))!%(r$mhK,rrdTN!" r!!"rJq0i5!"A(B""!"5!r`!!,!F!!%'#!!b!I`!!5!!!,)%I!35")3"`N3N!!#J E!!""JJ!8If2EH$LI!!4)!%mYB!!!!$KJ!!#!!3"B1#%!8(`)!kDlBIrX6S!!))# M!!#`T!!!6S!!)(`)!UD6iIrmNm(rq*!!!3!)P#(r`,#"!&jm[LYiS'%!ALJ$!!& !JJ!FIprcH(r$mhL!R`!)JCm!"%J!@SQ!33!8J!%!5$JK!%"m#!1QJq(rr)2"rrK 1J!!JI!J#TT2Krrb6`IriNk(rp*1"rr#3!!%!#*3Krh"mI"YiN!#"!+b3!+%!X*! !`3#dN!$K!,L4!3#m1k)6p$[!!!#SBJ)1,!-!!%##!"a,rrZKI(iEH#`H!!""JJ! -Im2cH%J!!1JiB3!i1)!!!$LJ!$T)!$"KB!!!!$KJ!!a)!"VGB!!!!(ar'hJS(`! !3))!$$KJ!!a)!!#d1)!!&,#"!&+SSJ)1X+%!8)$"!,#3!-%!@)$K!,53!1%!A)% G!!!S#!!!3))!()"L!B3iJ$l!1+!!!8J!9@@!33!8N!"p!!#"23!!N5%!B+&F!!# a33"NNq%!CMKK!$K)!&NCJ%%!&+PK!%JX#`!!3B)!'(rMqhK)!"V4B!!!!+KK!%K )!!!`JB%!9*'I!!#!B3#mN!"r!!5!J3#XN!#I!!L!S3#iNq8!!+$"!'5`h!!!Im2 cH)!"!*Ji)3#3!(`)!kD$iIrmJm(rq)1Krr5$JIr`6S!!)(`)!UD6iIrmNm(rq*! !!3!)P#(rF*!!B3#SN!#"!+b`S3#bN!$"!,53!1%!Z$KK!%3iJ!!!1+!!1NJ!,c9 J!!!!J'%!Z,"K!$L!J3#dN!#"!$SiS!!!X+%!2S2K!+Ji`!!AX-%!AUML!Jk`i3" FJ4m!!*%"!'#")3#XN5%!CU&"!,+a33"U1@!!!CPK!(!jJ3!iNB%!E$KK!%4)!&J 4J%%!&$KK!&4,rrTGI(iEH(r$mhL!!3#B1#%!N!"m#!1QJq(rr)2"rrK1J!!JI!J #TT2Krrb6`IriNk(rp*!!!3!)P#(rF*!!B3#SN!#"!+b3!+%!X*!!`3#dI2dlH*% "!,`iB3!i1)!!!$LJ!$T)!#jTB!!!!)2"!+JiB!!9X'%!8UL#!Jk`J3"3J,i!!*! !S3"8L-)#$,$"!&JiB3!i5!"AGB""!"3iB3")5rrj`Aar'hJX(`!!3B)!$(rMqhK )!!"dJ'%!Y)#"!'#Ji3"NI"di!%#!!!arTHYi5!!!#+#K!'4)!#fjB!!!!+%"!'5 ")3#mN3N!!)&"!&U"B3#XN8X!!+'"!&k!B3#`XB-!!$L!!"D`J3"51'%!1%J!9[Q !33!81'%!5%[rq89mIaYiIq2lH)!"!*Ji)3#3!(`)!kD$iIrmJm(rq)1Krr41J!! JI!J#TT2Krrb3!!%!#*3Kri#3!'%!Q$KK!$`iJ!!!1+!!1NJ!,@PJ!!!!Jq%!Q$K J!"L`B3"@U))#$V#"!&5![`!!N!#K!&JiB3!m5!"@IB""!"3iB3"-5rribC!!B3! iIq2lH%J!'$9J!!!!J!%!L$JK!)"m#!1QJq(rr%k!!#"m#!+QNq(rr*!!!3!)P#( rN!#3!'%!L+KL!JiX!`!!3))!&%[rq!PmIaYi,"m!!%##!%`iB3!i1)!!!$LJ!#4 )!#c4B!!!!$L!!!q`J3"5U+)#$V#K!&!iB3!i5!"9mB""!"5S`3"),!B!!%##!"# !i3"8J3%!L*!!k!!!J!%!H$JK!("m#!1QJq(rr%k!!#"1J!!JI!J#TT2Krrb3!!% !#*3Krm#!BJ)3+!-!!%'#!!`iB!!!5!!!J$KJ#3")!"EGB!!!!*!!BJ)3J))#%#J %!!"!JJ!N1+!!$$M#&l#3!+B!!$MJ!!`j!K4iX1J!!$KJrrp)!!"%J')#%$L!!!! iS!N!5!!X%@!!!!!li!!!5!!!($Nr!)#"3J)3(Am!5$P+!!4p+PNZ1rm!!5`I!#" "J2rN1'!!!)!"!%Ji)3"!I!J$TS2Krra1J!!JI!J#TT2Krrb3!!%!#*3Krm",rrm p,!-!!%'#!!`iB!!!5!!!3$[J!!")!!!XJ')#%"bI!%KmBb#Z9'22rd##!"5!SJ) 3(0m!5(aP-K4)!!!81rm!!5`I!#""J2r81'!!!)!"!%Ji)3"!I!J$TS2Krra1J!! JNq(rr$[J!!")!!!`J))#%"br!%JiK!!%I)3S,R`$)!"!JJ!8J-)#%"cr!%KmCMS 85!!!&$[r!!%X(`!J3B$rd$KJ!!#$iIrm6S!!)(`)!UD6iIrmN!!"!!L8)Ir!I(m EH(rMqhJiJ!!!1+!!"%J!+ZPJ!!!!1'!!!*!!I`!iJ*m!0#J%!!""JJ!3J(m!0%J !&G9J!!!!1+!!!*!![`!d1-!!!*!!h`!`J!%!5$JK!%"m#!1QJq(rr%k!!#"m#!+ Q[d(rk*!!!3!)P#(rX(am'hKmQL0iI,XVH$ZL&(Jl`KH`,"`!!N##!"3X'`!!3B) !*#`E!!*"JJ!F1'!!&T!!IJ!!1)!!&V#G!!!iB2rr5!!"!#`D!!*"JJ!N,"S!!8' #!"`iS!!@N!#q!!!i`!!@X0d!!$KJrrp)!!$B5rrq@Aar'hJS(`!!3))!($MJ!!b 3!2i!!$N!!!ba(3!!1'$rrdJ!!,#cR`!)Xjm!',1I!#LcI`!UNem!,)%r!$3S#3! !3))!3$KJ#!")!"4GB!!!!*!!I`!d18!)!*&I!$#"I`!d+!X!!%##!"`jJ!!-NCi !!$KJ!!b`I3!!1'$rrdJ!!&4rirYi1)!!!$LJ!!4)!#Q4B!!!!$L!!!')[`!!8)8 q-*Lr!!!i`!!!S2m!!&$(2(#`r`!!13!!!)Nr!!&4#5EfQ6m!!6P!!!#4A`!iJ(m !")!"!&Ji)3"3I!J$TVY"rqK1J!!JI!J#TT2Krrb3!!%!#*3Krm#3!)%!A)2K!&b )I`!!9'22rd##!"!iBJ-$5!"5(B""!"5JR`!!9)A12MLP!!&3T$a`X*m!!)!"!%J i)3"!I!J$TS2Krra1J!!JI!J#TVm"rq#3!!%!#*3Krk#3!'%!H*!!J3"mI,JVH(c j1hL4!3#-1k)8H$[#&l#!B3"i5rrpAAar'hJS(`!!3))!($KJ!"D3!(i!!$L!!"D `R3!!1'$rrdJ!!4L![`!X,!8!!N##!"#Jh`!)+!B!!N'#!"`ii!!@N!$q!!!j!!! @X4d!!$KJrrp)!!$SJ6m!1#J*!!"!JJ"S1(m!#RrNqhL![`!dJ0m!-$Mr!$L"!J' i5rrhD@!!!!"mHKYi,"S!!%'#!#"rirYi5rrp&6P!!"Q4AJ!!Xed!!$KJrrp)!!# 81(m!$%[rq[9J!!!!1@!!!BQI!!&4E#EfQCm!!B"K!)`S!`!33))!%+#C!!!S"!! #3B)!($LJ!"D3!,i!!$M!!"D`h3!!1'$rrdJ!!%Kr2-YiJ(m!1)#F!!5J[!!#J-% !I(m(`hK,rrJjB!!!!(al'hJX'`!!3B)!'$MJ!"Q3!2i!!,0p!!!iB2rr5!!!#(m $`hL!!3"S1#%!B(`)!kDl!IrJ6S!!)(`)!UDr3IrSN!!"!!L8)IqJN!"K!(L3!)% !I*!!S3#!N!$K!)Kp'N0i1k)8H$[#&l#!B3"i5rrlhAar'hJS(`!!3))!($KJ!"D 3!(i!!$L!!"D`R3!!1'$rrdJ!!0#![`!X,!8!!N##!"#Jh`!)+!B!!N'#!"`ii!! @N!$q!!!j!!!@X4d!!$KJrrp)!!#JJ6S!!#J*!""!J!!F18!!&T&H!!!jB!!@XAd !!$KJrrp)!!"m1B!!%*'D!!#$J3#)1'!!!V"m!!#!I`!i1*`!"$Lm!!+!`3"mJ1% !J$N"!$K,rrIPB!!!!(al'hLJR`!!9)612d'#!"LJ[`!!9+E12MM'rrp3a6a`X,m !!#`E!!"!JJ!-J'%!1%J!!"3ii!!CN!$q!!#cI3!!1'$rri!"!'Ji)3"JI!J$TVY "rqK1J!!JI!J#TVjKrmb3!!%!#*3Krj!!I(JEH(bE)hKm[#YiI0-cH(cd1hJkSK4 B1b)8'$Y#%rJS&!!!3))!$$VJrrj)!!!S5!"*cB""!"5!P!!!()3!2)#d!!3i`%% DI+8cPRaM+K4qj"S8Id26H$L!!!!iS!!J5!!PZ@!!!!"r)mYi1)!!!$LJ!#")!#@ PB!!!!$KL&$JiJ!!!1+!!)%J!*C&J!!!!IU1VH$L!!!!iS!!J5!!PI@!!!!!lS!! !+"X!!%##!!KqZkYi+"`!!%##!!Kq[+Yi+"-!!%##!!KqXkYi1q!!!%J!!0Jii!! "9qJ'rRcR3$"AkHMkI6a),RcR5$P"JJ!N18!!!9IV"[jp5PJ`9qcSqRajB#jmBe0 iI(PK,MZp!!%iJ!!"9q8'rRb%+$"AjZMkI0X`,Rb%-$P"JJ"m12rrJ#`(!#""J3" `Iq2lH%[rqBPmIKYi+"i!!%'#!&b*(J!!93M2rd'#!&#K2J!!95R12d##!#5"AJ! X,!S!!8##!$L!IJ!m5rraX@!!!!!X!`!!3B)!*$PJ!!&Al!EqI@YJ-&IMk2TmQKJ ZI)4EH(bD'5il[3!"1rm!!A`I`!""J2mS,"d!!%##!#4)!%RGJ%%!&%[rppPJ!!! !5!")0B""!"4m!lK!3B$qq$Li!!GmYKj`IYB"P#J@!#"!J3!)1X!!)(pMfhKr400 iIX@cH%J!)q&J!!!!Ii2MH(mNbhKqaE0i5!!Mc@!!!!"qBjYi1))81(l&XhK)!#1 jB!!!!(qMkhL!!3"i1#%!F(`)!kDkBIr-6S!!)(`)!UDrBIrXN!!"!!L8)Iq`I(X EH$ZL&(Jl`KH`,"X!J%#!!"4rBpYi5!"#m@!!!!")!!$dIf2EH%[rq%PmIaYi+"m !!%##!!`iB!!!5!!!f#JI!!""JJ!FL(m!!&4Mcrp"JJ!3S*m!+#J%!!*"JJ!F1+! !&T!![J!!1-!!&V$G!!!iB2rr5!!!S)$r!#`X"`!#3B)!9%#!!'`X"`!"3)!!#%J !!'#"(`!m+!J!!%'#!'b!I`!m5rr['@!!!!"mI"Yi,"`!!%'#!&3j)!!CN6i!!,1 G!!"rirYi5rrhp6KJrrp)!!"%J9m!1#J+!!""JJ!XJ(m!1%[rp9PJ!!!!5!!!($P J!"D4IJ!!1B!!&V'G!!!iB2rr5!!!%(rMqhK,rrHa1'!!!)!"!&Ji)3"3I!J$TVY Krqa1J!!JI!J#TT!!!3!)P#(r`)"L!L!S!`!!3))!&$KJ!XK)!!d*B!!!!*!!BJ) JJ))#(#J%!!"!JJ!81'!!&%J!$1eJ!!!!N!"L!Kb!!3")1#%!3(`)!kC1J!!JI!J #TT!!!3!)P#(r`)"L!L!S!`!!3B)!%)"L!L")!!djB!!!!$L!!!#3!))#))#L!K` S"3!!3B)!%)"L!Ka)!!dCB!!!!$M!!!#3!-)#()!"!%Ji)3"!I!J$TNk!!#"m#!+ QN!!"!!L8)IZ`N!"K"'L`J34ZN!#K"(!iB3!iJ)%%F%J!2kPJ!!!!1'%!1%J!54f !33!8J'%%D+L""'iiS34!1-%%4$MK"$K)!%NCJ%%!&)"K"%3iJ3!i5!"*)B""!"5 !!34B1#%%8(`)!kC1J!!JI!J#TT!!!3!)P#(lX*!!B34SX)%%ET!!S34`J'%%D+L ""'iiS34!1-%%4$MK"$K)!%M&J%%!&)"K"%3iJ3!i5!"*TB""!"3iB3!i5!"*XB" "!"5!B34`1)%!1%J!2`&J!!!!J!%%@$JK"&"m#!1Q6S!!)(`)!UD6iIrmNm(rq*1 Krr56JIr`N!!"!!L8)IqJI(`EH(bH)hKm[5YiS(i!!#`$!!0"JJ!BS*i!!#`%!!9 "JJ!-1'!!!%J!!1b![J!#9,m'2L`I!!e"JJ!J3)!!%#`I!!0"JJ!85!!!b#`I!"Y "JJ"N5!!![$M!!!'`h3!!Ii2MH$L!!!%iS3")1-%!2$MK!%")!%IaJ%%!&)"K!$` iJ!!+5!")%B""!"3iB!!)1)%!1%J!5"Q!33!8J'%!2$L!!!")!%IaJ%%!&$KJ!!& )!!"N11!!!V$p!!"rJq0i1)!!!MLK!%Ji`3!m11%!3%J!4j@!33!8J'%!2$L!!!T )!%HeJ%%!&$KJ!!JiJ3!i5!"([B""!"5!B3!m1)!!!%J!4j@!33!81'!!!8J!!!J iB!!!J!%!D$JK!'"m#!1QJq(rr)2"rrL$SIrdJi(rm%k!!#"m#!+QN!!"!!L8)Im 31'!!!*!!B3"%1)!!!*!!J3"+1'%!1%J!5$'!33!8I'-(08'#!!`iB2rr5!!!4$L J!!#3!+%!H$M!!!#``3#)U1%!6V$K!))j!!!!N3%!IMKK!'a)!%J0J%%!&(aM"c9 "JJ!-1'$rrdJ!!!L!B3#+J!%!q$JK!2"m#!1Q6S!!)(`)!UD6iIrmNm(rq*1Krr5 3!!%!#*3Krk"mI4Yi1'!!!,"K!%`iB!4-1)!!!$LJrrp)!%C*J%%!&(aq'hJS(J! !3))!$$KJrrp)!!&F1)!!!)#p!!#BK3!!1-!!!)$p!!#Ba`"NIm2cH$L!!!5![3! !5rrmfAr$mhJiJ!!'J4d!!$LS!'4,rrc&J')"d$L!$p!iS!!"5!"%"B""!"4mIaY i1'%!5%J!4Q@!33!8Im2cH%J!4R'!33!8Im2cH$L!!!%iS3"%1-%!1$MK!$a)!%A GJ%%!&$KJ!!-iJ!!$5!"'AB""!"3iB3!m1)$rr$LJrra)!%CKJ%%!&$KK!$`iJ!! 31+!!%%J!4Q@!33!8Iq2lH$L"!%a)!%CYJ%%!&+NK!%`X#3!"3B)!%+P"!%`X#J! #3),rh(rMqhK)!%14J%%!&+PK!%`X#`!"3))!0(r$mhJiJ!!%J,d!!%[rr'&r`r0 i1)!!"S'G!!!iV!"N5rrm68[rrJQ!R3!!N!"N!-Kr`r0i5!"'HB""!"4rSqYi5!" 'KB""!"4rSqYi5!"'NB""!"5SB3"-J!%!D$JK!'"m#!1QJq(rr)2"rrL$SIrd6S! !)(`)!UD6iIrmN!!"!!L8)Ir!N!"K!&LBJ3"I2'"dG$KMG@NiJ!4-5!""6B""!"4 mIaYi+"m!!%##!&`iB!$-5!"%6B""!"4mIaYiIq2lH$b!G(3iK(9T1+!%6$M#!da )!%4&J%%!&)"r!!!iJ!!!1+!!c%J!(39J!!!!Iq2lH%[rrF8X!`!"3B)!4$KJrrp )!!"JL'%!AbJ$!!&"JJ!B5rrp(B#I!!#!K!$)I!3B!%'#!"arirYi5rrpM5`$!!& "JJ!-1'$rrdJ!!#L!B3"BJ*m!!$LJ!-a)!"aPB!!!!(rMqhK)!%*"J%%!&$KJ!!# !!3")1#%!3(`)!kD$iIrm6S!!)(`)!UD6iIrmNm(rq*!!!3!)P#(rS(aq'hJiB!! "1)%!3%J!3,'!33!8I(mEH(rM"c9"JJ!FIm2cH$L#!f"rj3Fd5!!jV@!!!!")!!! dU)%!6*!!J3!iIm2cH$L#!hkSS3"!U-%!3UMK!%5T!3"'L5%!5)P"!%P)!$PjB!! !!)!"!'Ji)3"JI!J$TS2Krrb$`Iri6S!!)(`)!UD6iIrmNm(rq*!!!3!)P#(r`$a J3e-iBe451)!%6%J!2lf!33!8I(mEH#JI!!""JJ"3Iq2lH%J!2lf!33!8J(m!!%[ rjL9J!!!!I(iEH#JH!!""JJ!8J(i!%)"M!!#!B`!!N!"L!KKrirYi5!"!UB""!"4 rirYi5!""&B""!"5!!3")1#%!3(`)!kD$iIrmJm(rq%k!!#"m#!+Q[`(ri*!!!3! )P#(h`*!!B3KBN!#"#&bBS3KMI2JlH$YJ!!")!$k4J%%!&(ak'hJiJK4mJ'3!!%J !2X@!33!8,"J!!8#"!#4)!$lPJ%%!&(bM`jCmTF(@I+8B88'#!!`iB!!!5!!#i)$ #!KJX"J!!3))!(%[rr[@!iJ)B,!F!!%##!!`iB!!!5!!#[$KK!`K,rrj&1b!!!&F S"Mp"JJ!X1'%(6)L"#'0,rrdY,!-!!%'#!$"r3p0i5!!q4B""!"3iB2rr5!!#J$N J!!#C)3G-18!!!*P""l!jB!!!N@%)&%[rpmf!BJ)J1)!!!$LJ!XK)!"TCB!!!!$Q !!!'!BJ)JXB-!!$L!!!'!SJ)JX)8!!MM!!!'!iJ)JX-F!"&FS"Mp"JJ!-15!!!8J !!!Jj)!!!95N'2S&#!L#a+J!'5!!pmB""!"5"BJ)JN!"V!!JiB3"-1))$b6LK"d` i`3H`11%$#%J!0f&J!!!!JB%)@)"L!Kb4J`!!J)%)A)#L!Kb3!)8!"$M#!p+!iJ) FN!$(!!Jj!J)8J5)#(*%*!!`j33"-J@)#(*&,!"#!BJ)JJ))#(%J!!V9J!!!!I(` EH$KJ!!)iJ!!#1+!!!%[rlZPJ!!!!I(mEH$Q!!!+aJ3!m1'!K0,"K!$k!JJ)BN!# "!%"rirYiJ))#)(q&ihJi`!!!11%!2$N!!"",rr"TB!!!!$ZJ!!!iB3F)1)!!!$L J!#")!"NaB!!!!$LJ!!&AjJEqI+8`-&IRk2Sj!3F)I5Ji,RdT+hKp+$NZ18!!"C& ""b`jB!!!N@%(-$KJ!3!iJ3F)1+!!!$M!!!!ii3FX5rrb[@!!!!"mIKYi,"i!!%# #!#4rirYiJ))#)(q&ihJi`!!!11%!2$N!!"",rqrCB!!!!#`H!!"!JJ!31ld!!5` G!!0"J2pN,"i!!8##!(3jJ!!3NB%!1(rMqhL!JJ)J1+!#b$M!!!!ii3!m13%!1%[ rm49J!!!!N!"K"bJX!`!!J))#)+#%!!BX"!!%3))!0)"L!L!iJ3Fi5!!!N@!!!!# !S3G%L+8!!#`&!&*"JJ!)5!!!#$YJrrq!`3G)N!$""c4rirYi5rrd6@!!!!",rrA 4Id26H%J!1m@!33!8If2EH)!"#%Ji)3K!I!J$TVX"rq"1J!!J5!!!**!!C3!!1+8 !"(`$)%"!J!!8L1-!!$KM!!&mj`Ge3),rl#`'!!!ia[rr3),rf%k!!#"m#!+QNq( rr*!!!3!)P#(r`(ar'hL3!)%!A$Kr!!`iR`,(J+%!A$M!!!9,rrqPJ!%!5$JK!%" m#!1QJq(rr%k!!#"m#!+Q[f(rl*!!!3!)P#(rX(ar'hKmR#0iI,iVH(cG-hKrqrY i5!!!6)"q!!!S!`!!3))!&$L!!!#BR`!!1rm!!8J!!"KrirYiJ*i!!(bri&")!$8 PB!!!!(rMqhJiJ!!!5!!eM@!!!!!li`!"1pi!"#`G!!!l[Irr3),rX(alq&#!!3" B1#%!8(`)!kDlBIrX6S!!)(`)!UD6iIrmNm(rq*!!!3!)P#(r`(aq'hL3!)%!A$[ J!!8iIJ!-1,i#b(bI+&#!S3"FIqElH%[rrcNiB`!-J!%!5$JK!%"m#!1QJq(rr)2 "rrK1J!!JI!J#TT2Krrb6`IriNk(rp*1"rr#3!!%!#*3Krl"mI"Yi1q)8I$[!!!" )!$GpB!!!!%J!1G'!33!8I(dEH$KJrrq3!(m!!)#F!!`X"!!"3))!0)"m!"!iJ!! "5!!j`B""!"4mB`FdN!"r!!#![`!!,!Arrd##!"")!$QpJ%%!&(aq'hKrSqYi5!! jaB""!"4r`r0iJ!%!@$JK!&"m#!1QJq(rr)2"rrL$SIrdJi(rm%k!!#"m#!+QN!! "!!L8)Ir!1')8I)"M!!!X!rrr3))!&$L#&(b!C!!!5!!jMB""!"4)!$FKB!!!!)! "!%Ji)3"!I!J$TNk!!#!iBK4iU'-!!%k!!#!iB!!!6S!!)%k!!#!iB!!!6S!!)$K J!!"1J!!JI!J#TT2Krrb6`IriN!!"!!L8)Ir!I(iEH$[L&)JiB!!"5!!)l@!!!!# !!J)N,!!!!%##!"KrirYi5!!@P@!!!!!i!!!"N!!#!L4rirYiIm6cH%J!&X&J!!! !I(mEH$KJ!!&)!!LaB!!!!(rMqhL!!3")1#%!3(`)!kD$iIrmJm(rq%k!!#"m#!+ QNq(rr*!!!3!)P#(r`(ar'hL!!J)N,!!!!%'#!#`iB!!"5!!)C@!!!!!iBK5)Iq6 lH%J!&q&J!!!!1'!!!8J!#%eJ!!!!J!%!5$JK!%"m#!1QJq(rr%k!!#"m#!+QNq( rr*!!!3!)P#(r`(ar'hL3!)%!A$MJ!!#3!2m!!)!"!&`S"J!!N!!I!!5)(`!)81! Z0*JI!!L)(`!)81!QpTJI!!LBr`!-Q2m!$C!!r`!83B)!((bN+hKrirYi1+!!!NJ !!ZeJ!!!!5!!!((rMqhKmj$YiI18lH(cQ1hK)!!,4B!!!!)!I!"JiB!!!N!!I!## 3!(m!*+!I!!48!-qq,!!!!N'#!'"!J!!3,!!!!8#!!"4)!!"3,!!!"%#!!%K)!!! SJ')"0)!#!6#3!(m!0)"L!5b3!"m!1)!#!5L3!(m!2*!!(`"!5!!!))!#!553!(m !0)"L!5#3!"m!1)!#!4b3!(m!2*!!(`"!1!!!!*!!(`"%J!%!5$JK!%"m#!1QJq( rr%k!!#"m#!+QNq(rr*2"rrL6SIrdN!!"!!L8)Iq`1'!!!NJ!"[9J!!!!1k)$q$[ !!!!li!!%S"d!"&3!clp"JJ!FIk2VH%J!#HeJ!!!!S"d!"&2J2I#`(3!%1pi!!6Z p!%JX(J!M3B$rd$KJ!!*)!!DYB!!!!)!"!&Ji)3"3I!J$TS2Krrb$`IriJk(rp%k !!#"m#!+QNq(rr*2"rrL6SIrdN!!"!!L8)Iq`1m!!!$ZL!rKrhr0iS"d!"&3!clp "JJ!FIk2VH%J!#M9J!!!!,!-!!%'#!!Jl`2rr1rm!!6Zp!%JX(`!M3B$rd(r$mhL !!3"B1#%!8(`)!kD$iIrmJm(rq)1Krr41J!!JJ-3!!$L!!!Si!!!05!!!+)LM!!! S"3!03))!$*L$!!")!!!3+!8!#N##!!LB!`!!1'-!!5J'!!!ia[rr3),re%k!!## !!`!BN!!$!##!!`!FN!!$!#5!S`!8J)-!+)!$!#4mT#!iI!3!8*!!!`!NJ!-!&*! !!`!`6S!!)(`)!UD6iIrmNm(rq*!!!3!)P#(r`(aq'hKmRb0iJ(i!')!H!#"m!`" 43B)!D*!!(J!NL"i!"93!erp!JJ!3J(i!'$LH!#4,rrp&J(i!!)#H!"L!hJ"%JCi !2$Lq!#4)!$Y"J%%!&#JI!!""JJ!-J"i!**!!(`!!,!-!!%'#!!K)!!!JJ(i!*)! H!"4m!"S8N!!H!"4r`r0i5rrr16KJ!!#!!3")1#%!3(`)!kD$iIrmJm(rq%k!!#" m#!+Q[f(rl*!!!3!)P#(rX(aq'hKmQb0iI,`VH(cI-hL)(J!)S(i!"&3!hhp8Bmq q3))!$#`$!!"!JJ!-1'$rrdJ!!4!X(!!!3B)!(#`F!!&"JJ!8,"`!!N'#!!`iB2r r5!!!m)"q!"JS!`!!3B)!')JH!!K8!1Ir3B)!$%[rqpeJ!!!!L"i!"$L!!!"6J!p mQ"i!")Kq!!Ji(J!38)-QpTKq!!L3!"i!'*!!(J!J1k!!!C1q!"b3!*i!*#`F!!# 3!*i!+%'#!!`S(`!"3)!!')#H!#!i!!!!I!-$H*J%!!")!!"d+"X!!%##!$"rirY i5rrkk@!!!!"mHaYi+"X!!%##!!`iB2rr5!!!6)JH!!K6S#EfQ"i!#*0q!"L!IJ! B1!!!!*!!IJ!JNri!(*!!(J!SS"i!"&3!cliX!!!"3))!&&IJ"Ip!JJ!-1!!"rj! !(J!S1'!!!)!"!&Ji)3"3I!J$TVYKrqa1J!!JI!J#TT2Krrb6`IriN!!"!!L8)Ir !I(iEH(bI)hLJI`!%1!!!!*!!(`!NL"m!$94McliS!!!!3))!$#`$!!"!JJ!-1'$ rrdJ!!A3X!`!#3))!$%J!%0eJ!!!!L"m!#&3!hhp!JJ"FL"m!"&3$lhj8B!Hp3B) !6&4J"hY"JJ!SIq2lH$L!!!!iS!!#5!!2"@!!!!!X!`!!3B)!$$KJ!!")!!%FL"m !#$KJ!!&3B#idIq2lH*JI!!K,rrd"B!!!!)JI!!K8!0pq+!!!!8'#!"`i!!!"Q"m !$6J!!!#3!"m!*$KJrrp)!!$BL"m!"&3!rliS!!!#3B)!()"r!"L!(`!JJ*m!((` $!&"m"!"!3))!0(rMqhJiJ!!!5rrme@!!!!!X!`!!3B)!($J!!!'B(`!01!!!!*! !(`!N1'$rrdJ!!)#!I`!N1!2rrj!!(`!NJ(m!)$J$!!'3!"m!)*[$!!#)(`!%9!2 r[P4J"MiS!!!#3B)!6&4J"Mp"JJ!-,"i!#N##!$4rirYi1)!!!%[rr'9J!!!!,!- !!%'#!"`i!!!"Q"m!$6J!!!#3!"m!*$KJrrp)!!!31!!!!*!!(`!N9m-'2S!"!%J i)3"!I!J$TS2Krrb$`Iri6S!!)(`)!UD6iIrmN!!"!!L8)Ir!J!)#+$[J!!!X!!! "3))!$$KJ!!&)!!"X1'!!!dJ!!B&J!!!!J!)#+#`!!!"!JJ"%5!!2(@!!!!"rirY i5rri1@!!!!"mB!Fe3B)!%$J!!!+3!!)#+%J!!"b!JJ%m1')8J$J!!!'3!)-!!(` I!hL3!!)#+$KJ!!0)!!%YB!!!!(rMqhL!!3")1#%!3(`)!kD$iIrm6S!!)(`)!UD 6iIrmNm(rq*!!!3!)P#(r`(bH)hKm[bYi5rrr35`$!!"!JJ!-1'!!!8J!!%3iBJ2 i1'-!5%J!",9J!!!!Im2cH)#I!!",rrHYB!!!!*!!I`!!J(m!!$J!rrpm!`"!3)) !$$KJ!!&)!!!)1'!!!)!"!%Ji)3"!I!J$TS2Krrb$`Iri6S!!)(`)!UD6iIrmNm( rq*!!!3!)P#(r`(bH)hKm[bYi5rrqZ5`$!!"!JJ!-1'!!!8J!!$4r`r0iJ*m!!%[ rpbeJ!!!!N!"r!!#!I`!!1!$rrh`$!%"!JJ!-1'!!!8J!!!JiB!!!J!%!5$JK!%" m#!1QJq(rr)2"rrK1J!!J1'!!!%k!!#"1J!!J6S!!)(`)!UDr)IrNN!!"!!L8)Iq JI(XEH(bC)hKmfM0iIlNTed'#!"b)'J!0+!!!!%##!"#JHJ!%9'$2[d##!!`iB!! !5!!#`&4JcliX!!!#3))!$%J!$9PJ!!!!L"S!"6[J!!"8!0Ir3B)!,+!D!!48!-q q,!!!!d'#!"b)'J!%9!$r[LJ!!!*"JJ!-+!!!!8##!!Jli!!"L"S!#&3!hhp!JJ" FL"S!"&3$lhj8B!Hp3B)!6&4J"hY"JJ!SId26H$L!!!!iS!!#5!!,4@!!!!!X!`! !3B)!$$KJ!!")!!)SL"S!#$KJ!!&3B#idId26H*JD!!K,rrP"B!!!!)JD!!K8!0p q+!!!!8'#!"`iB!!"1!!!!*Kk!!em!`0iN!!D!#4)!!(N+"d!!(pqfhJlJ!!!3B) "2)"k!##!'J!BI!-!3%##!!`X(`!!3B)"*)#D!"L!HJ!JJ"S!((aN'&"m!`"3N!! D!#5!'J!N1f!!!*!!!3!iJ!%!1(`!k%"!J3!)Nk%!1)JD!!48!2qq+!!!!8##!$L !S3!i+!8!!%'#!#ar`r0i1)!!#NJ!#bPJ!!!!I(XEH#JE!!""JJ!31"X!!A`H!&# 3!!%!1)#K!$JS"3!!3B)!3)"k!#"ra20i5!!+9@!!!!#!J3!iJ"S!)(rH)K4m!#) 8N!!D!##!B3!iJ"S!*(qF)K4m!`"3N!!D!#4rT1K3J"S!*#J!!!""JJ!B+"X!!%# #!"#)'J!%9!$r[d##!$4r3p0i1)!!!%[rq$9J!!!!,!-!!%'#!"`iB!!"1!!!!*K k!!em(30iN!!D!#4)!!!8+"d!!%'#!!`X(`!!3),qr#JG!!""JJ"`,"m!!%##!'L $HJ!BJrS!((`HkK56fJ!BNlS!((p$dhL3!"S!)$L"!$K,rrI0B!!!!#`$!!""JJ! 81!!!!CJD!!di!!!!N!!D!#5!!3!iId26H*0k!"L6qJ!FIj`#&%[rpf9J!!!!1!! !!*!!'J!NL"S!"&3!rliS!!!#3B)!$$J!!!#3!"S!*$JCrrpm(!)8I'$,PS!"!'J i)3"JI!J$TVXKrq41J!!JI!J#TT2Krrb6`IriNk(rp*!!!3!)P#(rX(ap'hJS(3! !3))!$$KJrrp)!!#%S"d!"&3!clp!JJ!-1'!!!%J!!("rSqYi5!!!K@!!!!"mIaY iJ(d!!)'G!%")!$+9J%%!&+!G!!3iJ!!!8)!pm,!G!!53!*d!!)JG!!KmIKYi9!$ Rrd'#!"#!I3!B5rrce@!!!!!X(`!!3))!$#`H!!""JJ!-1'$rrdJ!!!JiB!!!J!% !@$JK!&"m#!1QJq(rr)2"rrL$SIrd6S!!)(`)!UD6iIrmNm(rq*!!!3!)P#(r`(a r'hJS(`!!3))!%%[rpAPJ!!!!5!!!q)JI!!dS!!!!3))!%+!I!!48!-qr3))!$$K Jrrp)!!$BL(m!#&4JhhiS!!!$3B!!&(aJ'hJiB!!#8'!Z0*JI!!L)(`!)9!$IILJ !!!*!JJ!-1!!!!*!!(`!NL*m!#&5!hhiS!!!"3B)!'$KJ!!"mJ#0i8'!Z0*JI!!K )!!"mS"m!"&3!cliX!!!"3))!((rMqhK)!!9KB!!!!(aq'hJS(J!!5!!!#$[!!!" rirYi1)!!!%[rpDeJ!!!!,!-!!%'#!"`i!!!"Q"m!$6J!!!#3!"m!*$KJrrp)!!! JL"m!#$L!!!"3J#idQ"m!#*2I!"4mJb0iN!#I!#5!!3")1#%!3(`)!kD$iIrmJm( rq%k!!#!iSKHd1!!!)h`*!kDSK3!!I'!(0(`%!!"!JJ!-I+-VH%k!!#!iT3")3J$ rj$KJ!!"1J!!JI!J#TT2Krrb6`IriN!!"!!L8)Iq!I,iVH(cI-hJiS!!!N!#K!%5 `B3"3N!#"!&L!(J!!+"m!!*!!!3"FX+%!C%'#!$!iB3!i5!!Y,B""!"4)!!!3Iqc lH%J!-'@!33!8U!%!5#`!!!""JIrX5!!!%$KK!$K)!#dCJ%%!&)!"!'#3!"i!!+J "!%JX!2rC3))!))!H!!!S!!!!3B)!$$KJ!!")!!!J1'!!!NJ!!"JX!!!!3))!$$K J!!")!!!)1'!!!B!"!)Ji)3#!I!J$TS2Krrb$`Iri6S!!)(`)!UD6iIrmNm(rq*! !!3!)P#(rJ(bq+hKmhc0i1+!!!*!!S3"%X'%!8*!!J3"BJ"i!!#JI!!#3!!%!A,# K!'4"JJ!`1'%!1%J!,)Q!33!85!!!%(rXqhK)!#q4J%%!&+J"!%JX!!!!3B(rl%J !!"!iB3!i5!!XGB""!"5!!3"JN!!H!!#S!3"),!!!!%##!!`iB!!!5!!!#$KJ!!' !!3#)1#%!J(`)!kD$iIrmJm(rq%k!!#"m#!+QNq(rr*2"rrL6SIrdNi(rm*!!!3! )P#(rJ(am'hKmRL0iI,dVH(cI-hJi!!!!N!!"!%3X(3!"Xi%!8%'#!$4!J!!3,"d !!%#!!"a)!!!N,"d!!d#!!"`i!!!#X!%!C%J!!"Ji!!!"X!%!C%J!!!`iB!!"5!! "H)!H!!!S(`!!N!!"!'C"JJ!`1'%!1%J!+`'!33!85!!!%(rXqhK)!#kCJ%%!&+J "!%JX!!!!3B(rl%J!!"!iB3!i5!!UlB""!"5!B3"QJ"i!!(`$!&&!J3%!+"m!!(` $!K53!!%!9%'#!$!iB3!i5!!UfB""!"4)!!!3IqclH%J!,N'!33!8U!%!5#`!!!" "JIrX5!!!%$KK!$K)!#V&J%%!&+J"!%JX!!!!3))!$$J!!!")!!!)1!!!!5`!!!" !JJ#B1!!!!*!!!3"%,"d!!E1"!&""JJ!d3)!!%#`G!!"!J!!F5!!!*#`G!!0!J!! F1!!!!V!"!'4)!!!B1!!!!E!"!'4)!!!-1'!!!8J!!'b!(J!!+"m!!*!!!3"Q3B) !-$KK!$K)!#ReJ%%!&%J!!""rl2Yi5!!YMB""!"5S!3"),!!!!%'"rqa)!!!31'% !1%J!+H'!33!8J!%!CT!!(J!!U!%!5#`!!!"!JJ!-1'!!!%J!!!JiB!!"J!%!L$J K!)"m#!1QJq(rr)2"rrL$SIrdJi(rm%k!!#"m#!+QNq(rr*2"rrL3!!%!#*3Krd" mIKYiIm2cH%[rr#&mIaYiXm%!8$KK!$K)!#S9J%%!&(aJ"c9!JJ!`+"m!!%'#!#J i(`!)N!!"!%US(`!#1'%!1,!"!%k!(`!%N!!"!'K)!#RjJ%%!&#JI!!""JJ!-1!! !!,!I!!"mB!Fe3))!$$KJ!!")!!!)1'!!!B!"!-Ji)3$!I!J$TS2Krrb$`Iri6S! !)+!$!!48!-qq+!!!!8'#!!`S!!!#3))!%)J$!!dS!!!!3B)!'$KL&l!i!!!MN!! $!!!iB2rr6S!!))J$!!K8"Ypq9-!'2d##!!b!B`!86S!!)&6!"Mk!S`!BJ)-!)#J !!!1!B`!`I!8J8(aM!K40J!!J1!ErrRaJ'&"1J!!JI!J#TT!!!3!)P#(r`%[rrhQ !!3")1#%!3(`)!kC1J!!JI!J#TT2Krrb6`IriNk(rp*!!!3!)P#(rX(ap'hKm[LY iN!#"!'bJ(3!%1q)AX&3!cliS!!!"3))!%)JG!!dS!!!!3B)!&$J!!#13!"m!!$K Jrrp)!!'%L"d!#&3!hhiS!!!"3))!2(qMkhJiJ!!!5rr[i@!!!!!X!`!!3B)!*$J !!!'B(3!01!!!!*!!(3!N1!!!)j!!(`!!1'$rrdJ!!6`X(J!"3))!)$[!!!"rSqY i5rrqZB!"!'`S!`!!I!!D&*!!!3"X,"i!!N'#!*!!L"d!"&3!lhiS!!!$3B)!J)J G!!K8!0pq+!!!!N'#!!`S!!!$3))!D)#"!'b!(3!8I!3!3%#!!"#!(3!`I!3!3%# !!"L)(3!)1'!!!&"J,M5B(3!)5!!!5)"p!"Km!#"3I!-#&*!!(3!JJ)%!E)!G!"3 iB!!#I!3!8*!!(3!NL"d!#&"J,M5B(3!)5!!!&)JG!!JiB!!!8'!Z0*JG!!L)(3! )9!$IId##!'5"R3!d+!`!!%'#!%5!I3!!J0d!4(r&mhJiJ3"X5!!UAB""!"3X!`! !3B)!*$J!!!'B(3!01!!!!*!!(3!N1!!!)j!!(`!!1'$rrdJ!!"`iB!!!Q(d!$)! "!'b3!"d!&*!!I3!N1'!!!)!"!&Ji)3"3I!J$TS2Krrb$`IriJk(rp%k!!#"m#!+ QN!!"!!L8)Ir!5rrq"B!"!%Ji)3"!I!J$TNk!!#"m#!+QNq(rr*!!!3!)P#(r`(a r'hKmJb0iIq6lH%J!*`@!33!8Iq2lH)!"!%Ji)3"!I!J$TS2Krra1J!!JI!J#TT2 Krrb3!!%!#*3Krm"mIaYiIq2lH%J!!(PJ!!!!Iq2lH)!"!%Ji)3"!I!J$TS2Krra 1J!!J1'2rrcLP!!&)!!!8M!-!!A`!)%"!JJ!)6S!!)$5Prrp!J[rX1'!!!%k!!#" mBbS81+8!!8J!!"5-!rrrI!!J3%##!!K1J!!J0+Arrd##rq`iB!!!6S!!)#J&!#" 8KJBq112rrd'!!*!!I!F!d&3!"lp"JJ!8I+!S8*c(!!%d!2rr3),rq#J'!!""JJ! F9-2!$P6!J"j8a%!ZI'!$H(b!!hKmaJ0i9+$CIcMRrre"JJ!XP-F!"*6(!!58a`! %P-F!"*6(!!58a`!%P-F!"*6(!!3d!2rr3),rh&5Jphp"JJ!3P-F!"$3!rrp!J[r i11F!!e5P"liS"3!!6B)!)*c(!!%dTIrr3),rq%k!!##!!J&%1')8K*!!!`!!6S! !)$M!!!#3!--!"$J$!!53!!-!$*!!!`!)2)!!!B#L!9#3!!-!!)!#!8b3!+-!%*! !!`!81)5!!*!!J`!BN!$$!"b3!--!)*!!``!N6S!!)(`)!UD6iIrmNm(rq*1Krr5 6JIr`N!!"!!L8)Iq`I(`EH#J%!!"rRq0i3B)!%$J!rr4m"!"!3)%!$$KJ!!")!!% X1'3!#i!F!"K8I3!iI"d!3%'!!&b"R!!3+!`!!%'#!&#!(!!F,!!!!%##!%3lh3! 3Im2cH(q%ihK)!#H0J%%!&(r%mhKrKH0i5!!##Aaq'hJS(J!!3))!$$KJ!!")!!$ -J"i!!&3G!$T)!!#N+"d!%%#!!!JlS!!3Iq2lH(qNkhK)!!+&I(iEH#JH!!""JJ! 8Iq2lH(r%mhK)!!)p5!!!A)!F!"!S!!!!3B)!3)"m!"Km(4K!3B%!$$[$!"")!!! )1pd!%)'F!""r`r0iIi6MH%J!*[@!33!8Im6cH(q&ihK)!!&aI(iEH#JH!!"!JJ! -1'!!!%J!!$4rirYiIm6cH(qPkhK)!!)pI(dEH)!H!!!iIJ!%B!!!!C!!(J!!I"l S,Q!!!!*m(ZNZJ!%!@$JK!&"m#!1QJq(rr)2"rrL$SIrdJi(rm%k!!#"m#!+QNq( rr*2"rrL3!!%!#*3Krm"mIaYi+!3!!(rqqhK"JJ$31+6rr)!&!!"r`r0i9!!!2*! !"3!!J!8!!(bN+hK8"`!kI-8k&)!'!!"8!!IkN!!'!!#3!1Err%J!!R9mC4YiJ"m !&)"P!!!S!!!!9'F!1Rc&1K4"JJ"`9'!([8##!'L!"Irm,!!!!%#!!&b!"J!!,!! !!%#!!&!iCIrdJ)-!!#J%!!""JJ!3J!-!"*!!"!!%5!!!$)!$!!53!"m!))#$!!3 S"!!!3B)!$)!$!!#3!!3!!)'I!"4rj2Yi5!!PTB""!"4)!!!3Im2cH(bN+hK)!!# "J!%!5$JK!%"m#!1QJq(rr)2"rrK1J!!J+!-!!%##!!`iB!!!6S!!))$&!#"mCaY i+!B!!(cS1hJj*2r`3B)!#*%'!!!i!!!!N!!)!!#!"3!J1)$rr*!!#!!%N38!)*5 (!!L9*`!%1!Rrr(cR!K54*`!!P)F!"$KM!!a1J!!J1!-!"*!!"!!%J!-!$*!!"!! )J+-!$*!!K3!%N!#$!!a1J!!JJ+-!!(`%+%"!JJ!-J!8!#*!!!`!!J!3!")"N!!L 3!!-!")!%!!L!C!!%N!!$!!K1J!!JI'BEH)#Q!!"mSbYiJ!8!!&3!!$Tm!#"!3B! !%(bM+hL3!+B!!%k!!##!T3!)I!8B3%##rp`iB!!!6S!!)(`)!UDr)IrNN!!"!!L 8)IqJI(mEH(bC)hL$f3!!1!8!"eI$!$TrH4S8JlX!!&3D!$JX(3!!IjSB8%'!!#K AS!Ir3))!)(rMqhKrC0Yi5rrr59HJ!$TrR!)8IhX#&%J!!"!S(!!33)!!#%J!!&K A`!HqId-$H&I!"rq3!(N!!(bCdK4!JJ!)Nd6rr&I!"rp"JJ!-1!!!!NJ!!!Ji!!! !Ii!$H*!!"!!!Nj[rr)!E!!"rirYi9!!(qT!!'`!!5rrq[Ap$dhL!!3"S1#%!B(` )!kDl)IrN6S!!)(`)!UDrBIrXN!!"!!L8)Iq`I(XEH(bF)hL!(!!!9"i!1RrmmK5 !(`!!,!!!!&3G!$T"J!!X9!!(rd##!#4rBpYiIq6lH%[rrRf!(!!!IplU&&3!"lj r`!0iN!!F!!#!(!!!Jlcrr&3!"le!JJ!-,"d!!%#!!"!i([rmIp`",NJ!!$4rrH" 3If2EH(rNqhK,rrieJ"m!!(qpmK48!!HqIk!$H*!!(`!!1"hrr(rmqhKr[`%ZIi2 MH)!"!&Ji)3"3I!J$TVYKrqa1J!!JI!J#TT!!!3!)P#(r`%J!(`@!33!8J!%!5$J K!%"m#!1Q6S!!)(`)!UD3!!%!#*3Krm")!"ljJ%%!&)!"!%Ji)3"!I!J$TNk!!#! i!!!"Q!(rm$J!!!#B!IraQ!(rmTJ"rr1B!IrdN!!"rrL3!!(rr$M$!!'*"J!!1') 0d(d)"h3X#!!P3))!-*N"rr@!JIr`J!(rp$KQ!!'3!)8!!*!!"3!%J)(rq)!"rrb 3!)8!#*!!"3!-6S!!)$J)rq!S!!!315!!!8'"!'3iiJqJ9!!31RcR!#jmk31Q6S! %)$J!!!#B!Ir`5!!!5*NKrr&)!!"!L!(rm5J!!!&"JJ!d1!!!!TJ"rr&)!!!SQ5( rmdJ!!##)!Ir`+!!!!%'#!"3i!!!#Q!(rm%J!!!Jj)!!!,!N!!%'#!"#0"J!"I3J (G%[rrh`X#!!U3))!B)$N!!!ij`!%N!$N!!#!"rrm,!!!!*!!!Iri3)!!'$J!!!# B!Ir`J!(rq(`!!0#3!!(rq)d'!!&p#!Gd5!!!0%J!!##!!Iri(!!!#RcS!K3i"rr 3N!!"rrL0"J!"I3J(G&8!"Mjm!`#Z9!!'pd##rpL!!Iri,!!"r8#"!$3i!!$rQ!( rpB#"rr#!!Ird1'B!!C!!K3!!N!!&!!5!JIriJ!(rr*!!K3!)N!!&!!a1J!!J,!J !,N##!(`i!!!"Q!(rmSd'!!&p#!Gd,!J!+N##!&5!C!!!1'-!"*!!C!!!J!2rr#` !!!#3!!(rr%#!!!`i!!!!Q!(rmSd'!!&p#!Gd5!!!0%J!!##!!Irm(!!!#Rb)!K3 i"2r3N!!"rrb0"J!"I3J(G&8!"Mjm!`#Z9!!'pd##rpJX#!"S15!!!8'#!#"!J!! 3,!J!6%'#!#K)!!!`,!J!E%'#!"")!!!NQ5(rp%J!!#!i!!!#Q!(rp%J!!"3i!!! %Q!(rp%J!!!Jj)!!!,!N!!%'#!!b0"J!"I3J(G$J)rlXS!!!cQ3(rp8'"!5!iBJl 39!!31RaM!#jmD31Q6S!%))J"rr3S!!!%3))!$$J!!!1B!IrdL!(rmLJ!!!"!JJ! 31!!!!C!!!Irm5!!!k)J"rr!S!!!#3))!h$J!!!'B!Ir`5!!!d)!"rr`X!!!!3)) !$$J!!!'3!!(rr)J"rr3S!!!"3B)!$#J!!!*!JJ!31!!!rjJ"rr9)!!#FL!(rmLJ !!!"!JJ#3!$J!!!D3!!(rr%J!!)3i!!!#Q!(rp$J!!!'B!Irc1!!!H*J"rr8i!!! )N!!"rra)!!"JL!(rmLJ!!!"!JJ!3L!(rp#J!!!""JJ")1!!!rjJ"rr9)!!!mL!( rp#J!!!""JJ!`1!!!rjJ"rr9)!!!NL!(rp#J!!!4!JJ!B1!!!!jJ"rr4)!!!-1!! !rjJ"rr@!JIr`J!(rp$KQ!!'3!)8!!*!!"3!%J)(rq)!"rrb3!)8!#*!!"3!-6S! !)*!!S3!JN!$"!#53!1%!+*%"!#`X!`!!11!!!$LNrrpmDKYiI1BlH*MP!!"!JJ! `J3%!,#`)!!"!JJ!NL3%!)bJ)!!""JJ!3L3%!*5J)!'p"JJ!-I+-VH%k!!##*!3! P15MrU#J*!#""J3"F13)2j&8T%$Tp#%JZI3N$TNk!"#!X!`!!1!!!#N#!!$ap5J$ 311!!!8J!!$!i!!!!Q!%!)6J!!!K)!!!J1!!!!*J"!#%i!!!+5!!!%$J!!!#B!3! K1!!!%(d+!jCp#!(@I3K38(e+!jBX#!!+3)!!$$N)!$")!!!JL'%!*6N)rrBS!`" i3))!$$N)!'&)!!!)13J!35J+!!#G"Irr1-B!!8##rlJS!!!)3))!+)KK!#-S!`! !3B)!()KP!!!X!`!`3B)!%$KJ!$#FCIrr1-B!!BKK!#!S!`!#3))!6)"K!#JX"`! !N!"K!#a!JJ!3L'%!)5J$!!""JJ!3J'%!,$KMrrq3!'%!,#J!!""!JJ!FL'%!)bJ $!!""JJ!3J'%!,$KMrrk3!'%!,)%"!#amC5"3I'JD&#`$!Ie!J3!-1'!!!%k!!#! iJ!!`5!!!$*b&rrmiaJ!"J'%!,(`''!""J2r`+!!!%%##!##)!3!M+!!!!%'#!"5 )!3!PR!ArrcJ!!$#F"Irr,!F!!%'#!"!i!!!YR!ArrdJ!!#b)!3!K+!!!!8##!"! i!!!VR!ArrdJ!!"3S!!!#3))!$$J!!##F"IrrI+-VH%k!!#"m#!+Q[Z(rh*!!!3! )P#(rS*!!`3#%N!$K!)L4!3#-I,JVH*%K!*!!1b!!!(mJrR"mKFTiI'!#H$Yirrp mS!0jI*iMH(ar'hKr1XYiQcX!!%##!$#!!3#3!#`!!!"!JJ!NL!%!KbJ!!!""JJ! 3L!%!L5J!!'p"JJ!-If2EH%J!!Nb)S3#*1!ArU#J!!#""J3"i1+)3D&3!%$TmT3! ZI+N$TNk!"#!lS!!!E'@!!'qMJ!"m(5!3I'-T%(aP+4"mB`$41i!!#N'#!%!MhJ! !Irm"N!!l)!!"5!!!-$ZJ!!#ES3#&1i!!#%J!!#!lS!!!Qk%!K6Z!!!T)!!!31k! !!*ZK!)8lJ!!3Iq2lH(r%mhKrTHYiIiEMH%J!&(PmPb0iIq2lH(r%mhKrTHYiIiE MH%J!%h8X&`!+I*iMH(ar'hK!J!!-1[F!-%J!!##)!3#*1[IrpLJ!!(K!JJ!-1[F !B8J!!!Jkp`""1)!!!(r$)RKri#*iI'!$HCllrrml@J!"3),rL$J!!!KrJ`*iIk! LH(aJ!hP!JJ!SL!%!KbJ!!!""JJ!FL"X!!#`!!$""JJ!31!!!-*`Errml@J!"L!% !K#J!!!*!JJ"FJ!%!M#`C!!#3!!%!N!"!JJ!3L!%!K5J!!!""JJ!3J'%!N!!i!rr rN!!"!*!!1'!!%$J!!!"rJaTiIk!#H(aJ!hP!JJ!FL!%!KbJ!!!""JJ!3J'%!N!! i!rrqN!!"!*!!J'%!N!"m'm"3I!-#&#`!!Ie!J3!-1'!!!%J!!*3iB!!`5!!!$*a lrrml@J!"J!%!N!"m'J!!3B$rm$KJ!"!i!!!!Ii-DH(qJ!RKmB!0j3))!))J"!)F S!!!!3B)!&)J"!)QF'rrr1!!!-*`ErrmX'3!!3B)!%$J!!#fF'rrr5!!!,)J"!)8 S!!!"3))!%$J!!#ZF'rrr5!!!&#J!!!*!JJ!-1!!!)*`ErrprBpYiJ!%!D$JK!'" m#!1QZZ(rh%k!!#!X"!!!3)!!*$J!!!#B!`!!X!-!!MJ!!!'B!`!%1!!!-*J$!!9 1J!!JL--!"(`%-!"-J!!JI+-L&$MP!!D-Trrr1+Ard(bJ"h3X!!!&3))!3(bM-K3 iT3!&1+Arrh`&1%"!J3!3L!8!!#`!!$""J[rXI!8i3%##!"#)"rrr9!B(rNJ!!&3 i`!!"5!!!6(`!!#C8"KIq5!!!3)`(rrpmS$)81+Ard(bJ"h3X!!!*I!!!*P3'&rp !JJ!-I+!(G8##!!`iK2rr5!!!%$J&!$#B"`!!5!!!$#`%!!"!J[r!,!B!!%'#!#5 SJ`!#1!!!!6L%!!'`J`!#Q!-!"$J!!$'B!`!&6S!!)#`%!!""J[m!Q)-!"%k!!#" m#!+Qfq(rq*2Krqb6`IrSN!!"!!L8)Iq!N!$"!+6ri!L3!*!!i3#SN3%!V(bq+hL 4)3#`J!%!X#`!!Ie!J3!-1'!!!%J!"36m)2L3!$J!!!#B!3!i1!!!),!"!$SiB3! i1-%!2%J!&E'!33!8L!%!3$[K!%&rr`)85!!!()KK!%!i!rrrQ!%!3+KK!$ii!`! "X!%!2SJ"!%!S!!!"3)%!%)`IrrmX!!!`3B,re)J"!%%X!!"*3B)!-%#!!"!X!!! `3B)!&%J!!(`X!!"13B)!@%J!!(!i!!!!Q!%!2,!"!$j)!!"Jb!)#12`I!%"!J!! F1rlrqcL#%1arirYi5!!,q@!!!!")!!!B1rlrr(rMqhJiJJ)X5!!,i@!!!!"rirY i5!!%+$[qrrarirYi1))#-%J!#m9J!!!!Iq2lH%J!"!b)B3"!U!%!2MKMrrpm!"S 8X!%!2M[qrrmi!!!!Q"m!!)J"!+NX!!"P3B)!p%#!!#JX!!"'3B)$d%#!!"!X!!" &3)!!h%J!!m!X!!")3)!$Z%J!!"3X!!"R3B)!$%#!!kK)!!))L!%!3)#"!,"m!#! !3)%!$$KK!$a,rrdjU)%!2L`%rra"J!!3J'%!X(`%'!""J!"3L!%!TbJ!!!""JJ! 8J'%!X$J$rrq3!!%!X%J!!"#)B3"!1!2rrj!!!3#`L!%!U5J!!'G!JJ!31!!!CCJ "!+P)!!"-1!!!4CJ"!+P)!!"!L!%!TbJ!!!""JJ!81!3!!A`!'&#3!!%!X%J!!A# )!3"!1'3!!A`$!&'3!!%!X%#!!9`i!!!!N!!"!,")!!&3J'%!X)J"!%!iJ`!"I!! J!%#"!!`iB3!m5rrmIDLK!$iii!!V,!8!!%#!!!amT3$311!!,6M!!!!iJ!!+5!! !)(aP)pCmBb(@I'-S8(bP)pBi!`!`R"rrrcM'!!%X"3!!3),ri#`'!!*"J2rBR2r rriJ"!+QF(rrrJ)%!X(`Im&"m"!)8,!!"r8#"!!`iB!!!5!!#A)KK!%!i"!!"I!- !!%#!!#!i"!!#I+-!8$J!!$")!!!)R"rrrc5Prrp!J[riL+%!3$L"!%&mK#S85!! !$)`%rrqF(rrr0+Arrd##rr5!!3#`,!!!!%##!"#)!3#R+!!!!%'#!!`i!!!ZR"r rriJ"!%'F(rrrL!%!2(`!"h9"JJ!31!!!,C`Irrp)!!(-L!%!T5J!!!&!JJ!31!! !+j`Irrp)!!'d+!!!!N##!D`i!!!JR"rrrdJ!!D#S!3!qL'%!3(`!!0!iirrrI1! k&8#!!!Jii!!!J'%!X(`('!"!J3!dL!%!3(b$1&!iB3!mI)3!8%[rqa'S!3!qL'% !3(`!!0!iirrrI1!k&8#!!!Jii!!!U!%!2M5J!!&!J!!)1+!!!(`&1K3X!!(p3)% !$$KJ!!")!!%SL!%!3$L"!%&mK!)81-!!!$KJ!$")!!!-R(rrrcM'!!'!!3#`I!F !8(`'!!""J2rX1-!!!%J!!"#-"2rr1-B!!C`Irrpm"MJ!3)!!%)J"!%"m"J!!3B$ rj$J!!$")!!!-R"rrrcM'!!&m"MJ!3B$rp)!"!,!X!!!!3))!%)J"!+FS!!!!3B) !$$J!!#kF(rrr,!8!!%'#!%3i`!!!1'!!-%J!!!bFIrrr1-B!!BJ"!%"m!#K3I!B !!%'!rqa)!!!3M!6rrcM'!!'F(rrrI!BS!%'!rr")!!!-1!!!-*`Irrq)!3!mI!! (G8'#!"!i!!!YR"rrrdJ!!#b)!3#P+!!!!8##!"!i!!!VR"rrrdJ!!"3S!!!#3)) !$$J!!##F(rrrIq2lH)!"!)Ji)3#!bq(rq(`)!kD$iIrXJm(rk%k!!#"m#!+Q[U( re*!!!3!)P#(pJ(ae'hL3!+%#S(bE)hJlS!!!1q%#0dJ!"QarBpYi1)!!*8J!"m& J!!!!I(`EH#JF!!"!JJ"%If2EH%J!"bPJ!!!!I(iEHAqpmK4"JJC%If2EH(r%mhK qTUYi1+!!!8[rh19J!!!!+!-!!%##"L3iB2rr5!!')(rEi&&r[I)83B)!,(pMfhK ra20iIUDVH$LJ!!&,rpbaB!!!!#J$!!"!JJ!-1'$rrdJ!"HarQq0iIf2EH$L"!U! iS3)i5rr[kBJ"!MemHaYi,!!!D8'#!+4!J!"B,!!!@%'#!@4!J!!S,!!!48'#!L4 !J!!3,!!!*8'#!j!!5!!$S#`!!%G"JJ)-5!!$P#`!!'4"JJ"S3)!!%#`!!'0!J!0 -5!!$I#`!!'K!J!0d5!!"j#`!!(9"JJ%33)!!+#`!!'p"JJ%%3)!!%#`!!'j!J!+ i5!!$6#`!!(0"JJ)85!!$3#`!!2p"JJ-i3)!$0#`!!(K"JJ$85!!$+)J"!M`S!!! #3))!')"K!U!iB`!%N!"K!U#$3rrm5!!!0#J!!!0!JJ!FJ'%#S$KM!!L3!'%#S)- $rrb$)rri5!!!&)"K!U!iB`!%N!"K!U#$3rrmL!%#2#J!!!&!JJ!)IeS(0)J"!M` S!!!$3))!0)$"!ML!i3)mJ3%#3)%K!N4r)mYiI`6$H$LK!MK,rr5aI(FEH#JA!!" "JJ+3!%J!!#b!S3)iJ-%#2)$K!N#"!3*%Id26H$L"!MK,rr*CI(FEH#JA!!""JJ* NIpIi8%J!!U5)!3)m+!!!!N##!"L!B3+J1'-!"*!!B3+JJd2rr%J!!$3S!!!$3)) !()"K!U!iB`!)N!"K!U#$!rrmJb2rq%J!!"5!B3+J1'-!"*!!B3+JJd2rr)J"!M` S!!!"3))!#&GD"$k)!3)m+!!!!d##!$5!`3)iJ1%#2)%"!N#")3*%Ib2,H(m%`hJ iS3)i5rrcjAah'hJS&`!!3B)"a%J!!#b!S3)iJ-%#2)$K!N#"!3*%Id26H$L"!MK ,rr'0I(FEH#JA!!""JJ'BIpIi8%J!!GL)!3)m+!!!"%##!"L!B3+J1'-!#*!!B3+ Jb#2rq%J!!"5!B3+J1'-!#*!!B3+Jb#2rq)$"!ML!i3)mJ3%#3)%K!N3iS3)i5rr h5Aah'hJS&`!!3B)"2(rAq&")!!&mJ'%#S$KM!!53!'%#S),Mrr`S&`!!3))!#$V L!M5)!3)l+!!!!%'#!#b)!3)kLpF!!#J!!!!kp`!"3B)"3)!"!N4m(J!!3)%"0(` H!hK)!!%XL!%#1LJ!!!""JJ!XJm%#4(lMZhKraI0i1)!!!%[rjK&J!!!!+!-!!%' #!3"reaK35!!!q(lMZhK)!!0jB!!!!(aq'hK)!!$NJ'%#S)J"!M`iB`!%N!"K!U! X!!!#JZ2rr%'#!$4!J!!8,!!!!%'#!"K!J!!F5!!#A#`!!!4!J!*85!!!(*1h!!" )!!*)XlF!!%J!!N#6Y`!!5!!#1*1h!!4rS2j`N!!A!!")!!)SJ'%#S$VK!$JiB`! %N!"K!U#!!rrm1m!!!CJA!!")!!"J1Z%!1$J!!#@B&`!!1m!!!8J!!%arJq0i5!! #c@!!!!"mIKYjIlhb&%'#!#arJq0iIm6cH(kQUhJiS!!"5rrBL@!!!!!S!`!!3)) !$$KJrrp)!!(%Ik2VH%J!!Eb)!3)iIpccH#J!!!""JJ$i+!!!!N##!!`k`!!`5!! !#$V!!##)&`!!I!!(G#`!!#Y"JJ!-,!!!,8##!-"q`!Gd,!!!-%##!,5!G3!N+!- !!$J$rrq3!"8!*%'#!##!G3!JL*F!!$J$!!'3!"8!)*L$!!"8J`Bq5!!!')Kh!!" qT+YiI'-(G%[re'&J!!!!,!2rrd##!!`iB2rr5!!")$Vh!!%lh[rr5!!!9)"e!#3 S!`!!1!2rrj!!&3!N3B)!()#9!#"@``Bq1!3!!C!!&3!JQX3!!%J!!"4q``GdIU5 VH%[re!PJ!!!!,!2rrd##!!`iB2rr5!!!b$ZF!!'!!3*!I"`!!%'!rkJX(J!!3B) !,(lMZhKra20iIUDVH$LJ!!&,rpG0B!!!!#J$!!"!JJ!-1'$rrdJ!!)L)!3)i+!! !!%##!'Jk`!!J5!!!9)"e!#3S!`!!1!2rrj!!&3!N3B)!()#9!#"@``Bq1!3!!C! !&3!JQX3!!%J!!"3iB!!JIU5VH%[rdfPJ!!!!,!2rrd##!!`iB2rr5!!!+$ZF!!' !!3*!I"`!!%'!rkKr[H)8L"X!!(`!"h9!J[Q3!(qMkhL!!3+)1#%#J(`)!kDkSIr 86S!!)(`)!UD6iIrmNm(rq*1Krr53!!%!#*3Krh"mI4YiI*iMH(br+hKrT1Yi1'% !1$LJrrmi`!!"5!!"L@!!!!"ra20iIqAlH$KK!$K,rrN&,!-!!%'!!!`i!!!!I"d CVS!"!*Ji)3#3!(`)!kD$iIrmJm(rq)1Krr41J!!JI!J#TT!!!3!)P#(r`*!!S3" JN!$"!'53!1%!D*%"!'b4)3"`N8%!G*!!J3"FJ)%!A$LK!'",rrpCJ!%!5$JK!%" m#!1Q6S!!)$L!rrmiBrrrM!-!!6L%!!%S!!!!3),rp(b$)hK1J!!J1+6rrcM$rrq -K3!"9)!'2jb'!!&!J[rd6S!!)$M%rrmiirrr1+8!!8J!!#b-KJ!"9)!'2jb(!!& !JJ!F1!!!!%J!!!LF"`!"0+Arrd##rrK1J!!J0+Arrd##rp41J!!J1'2rre5%"Mj )!!!3I!!J3%##!!K1J!!JM!-!!93!"Mp!J[rX+!3!!%f#!#!iB!!!6S!!)$LMrrp 8K!Bq1'!!!%J!!""m!#"!3))!#(bM+hL-"3!"9!!'2d##rq`S!`!!3B)!#%k!!#! S"!!!3B)!$$KJ!!"1J!!JI+-VH%k!!#"m#!+QNq(rr*2"rrL3!!%!#*3Krm"mIKY iI)FMH(bJ+hKmhc0iJ))#3(r$mhKmj6YiI!B$H%[rc(PJ!!!!L"i!#(r$mhK6i#i dQ"i!#%[rcX9J!!!!1'!!!)!"!%Ji)3"!I!J$TS2Krrb$`Iri6S!!)$KJ!!*1J!! J1'!!!%k!!#!iB!!!6S!!)(`)!UD6iIrmNm(rq*1Krr53!!%!#*3Kr["mI4Yi,"d !!%'!!"3X(3!#3B%!$$KJ!!")!!#3!$[J!!#ci3"8Xk%!8*2K!%SiB3!i5!!*bB" "!"4mIKYiIm!(08##!%#S!3"11'%!H,!"!)kcS3#3!%J!"`@!33!8I(iEH(r!"c9 !JJ!FU!%!6T2K!)U`!3#11'%!H%J!#CQ!33!8Im!(08'#!"!iBKH`Im!(0*!!!`! !Im!(08##!!`iB!!!5!!!#$KJrrq!!3%B1#%"%(`)!kD$iIrmJm(rq)1Krr41J!! J18)KM$PJ!!!i!!!JI!N$TS!+!!JS!!!!3))!+*!!DJ!)N!#+!!b3!+S!%*!!bJ! 8N!$U!!#4#J!%I@0EH*%U!"K1J!!J1@X!!6P+!"a#!2r)1'$rrdk!!#!X!`!!6B! !)#`$!#"-J!!J('-!($L#)B`i!!!!I'3D&*!!!`!)N!!$!!b3!!-!%*!!!`!8N!! $!!#3!!-!"*!!!`!B6S!!)(`)!UD6iIrmN!!"!!L8)Ir!1q)P$%J!!##!"3!!1)$ rrj!!(`!!J'8!#)'&!!4)!!LpJ%%!&)#r!!!S"3!!3),rh)!"!%Ji)3"!I!J$TS2 Krra1J!!JI%-6H%k!!#"m#!+QN!!"!!L8)Ir!5rrrlAaT'hL!BJ&`J))"E$LL!!! i`L83J1)"B)%#!9a,rrlPB!!!!)##!I#3!'3!!%[rSiPJ!!!!1'!!!)!"!%Ji)3" !I!J$TNk!!#"m#!+QN!!"!!L8)Ir!5rrr3@!!!!#!BJ(`J'-!!%[rr[&J!!!!J!% !5$JK!%"m#!1Q6S!!)#`$!!"mB!!dI)N!0%##!!Ji#3!J,!8!!(bT!$4mbJ!d3)) !#$NU!#"m!%J!)8!!3%'"!,!j+3!")5N!3(`!5K4p+9"3I5N$TL`*!#!ikIrJ3B! !%(aS2$!ii!!!5!!!'(b)6$!Jk3!JI'Fi-(d)1hKmCd``,!!!)$%Jrq""J!!3I)0 )-$L!!!")!!!BI'-!-#%J!#"mL8``I'0,H(b%!$!j32rr-1F!!(b%)44mBaN8I3K "&(cR144m"N!3I58j%8'!!""m#!0iI5G,H$!+!!&#!2rBI)3K&(aM'441J!!J1)! !!$KJ!!"1J!!J,!-!!(aJ!$4mL3!d3))!#$J*!#!X"3!!I+N!0(c+!$4!JJ!)15S !)(`!5!!K3!"!3B%!X$NT!!%K+3"!I!"+&(dT8&"p+31Q,!N!)$MTrq""J!!3I'J m-$MJ!!")!!!BI)K--#$T!#"mCcJ`I3JlH(aR6$!X!!!J-5$ri%'!!""mJdJ`1)! !!%J!!"KmB`!`)5!!)(b*6$"mBdYiI)3!-$P!rrm`j`!!I)3K&(aM'44p#%%8I1F j&(`'3""p*6N43B!!%(`)!hKp*dYi-!S!!8)!rpKp"%0iI1-lH%k!!#"1J!!JJB) !k*!!33!8J!`!!)"-!!4m#31Q6S!%))'#!1#3!%%!&)!-!!#!6!!%I!N$TNk!"## "JJ$%N!""!"5!$!!!J%`!"(`*!kC1J!3JJB)!,*!!33!8J!`!!)"-!!4m#31Q6S! %))'#!*!!N!""!"5!$!!!J%`!"(`*!kC1J!3JJB)!5*!!33!8J!`!!)"-!!4m#31 Q6S!%))'#!(53!%%!&)!-!!#!6!!%I!N$TNk!"##"JJ$dN!""!"5!$!!!J%`!"(` *!kC1J!3JJB)!d*!!33!8J!`!!)"-!!4m#31Q6S!%))'#!-b3!%%!&)!-!!#!6!! %I!N$TNk!"##"JJ!3N!""!"5!$!!!J%`!"(`*!kC1J!3JJB)!"*!!33!8J!`!!)" -!!4m#31Q6S!%))'#!-L3!%%!&)!-!!#!6!!%I!N$TNk!"##"JJ$NN!""!"5!$!! !J%`!"(`*!kC1J!3JJB)!Z*!!33!8J!`!!)"-!!4m#31Q6S!%))'#!$53!%%!&)! -!!#!6!!%I!N$TNk!"##"JJ"!N!""!"5!$!!!J%`!"(`*!kC1J!3JJB)!$*!!33! 8J!`!!)"-!!4m#31Q6S!%))'#!#53!%%!&)!-!!#!6!!%I!N$TNk!"##"JJ!8N!" "!"5!$!!!J%`!"(`*!kC1J!3JJB)!q*!!33!8J!`!!)"-!!4m#31Q6S!%))'#!)# 3!%%!&)!-!!#!6!!%I!N$TNk!"##"JJ#XN!""!"5!$!!!J%`!"(`*!kC1J!3JJB) !B*!!33!8J!`!!)"-!!4m#31Q6S!%))'#!,b3!%%!&)!-!!#!6!!%I!N$TNk!"## "JJ%!N!""!"5!$!!!J%`!"(`*!kC1J!3JJB)!9*!!33!8J!`!!)"-!!4m#31Q6S! %))'#!-#3!%%!&)!-!!#!6!!%I!N$TNk!"##"JJ$8N!""!"5!$!!!J%`!"(`*!kC 1J!3JJB)!H*!!33!8J!`!!)"-!!4m#31Q6S!%))'#!$#3!%%!&)!-!!#!6!!%I!N $TNk!"##"JJ!)N!""!"5!$!!!J%`!"(`*!kC1J!3JJB)!'*!!33!8J!`!!)"-!!4 m#31Q6S!%))'#!*L3!%%!&)!-!!#!6!!%I!N$TNk!"##"JJ$FN!""!"5!$!!!J%` !"(`*!kC1J!3JJB)!L*!!33!8J!`!!)"-!!4m#31Q6S!%))'#!,#3!%%!&)!-!!# !6!!%I!N$TNk!"##"JJ#8N!""!"5!$!!!J%`!"(`*!kC1J!3JJB)""*!!33!8J!` !!)"-!!4m#31Q6S!%))'#!$L3!%%!&)!-!!#!6!!%I!N$TNk!"##"JJ"SN!""!"5 !$!!!J%`!"(`*!kC1J!3JJB)!C*!!33!8J!`!!)"-!!4m#31Q6S!%))'#!+#3!%% !&)!-!!#!6!!%I!N$TNk!"##"JJ"-N!""!"5!$!!!J%`!"(`*!kC1J!3JJB)!E*! !33!8J!`!!)"-!!4m#31Q6S!%))'#!&#3!%%!&)!-!!#!6!!%I!N$TNk!"##"JJ" %N!""!"5!$!!!J%`!"(`*!kC1J!3JJB)!M*!!33!8J!`!!)"-!!4m#31Q6S!%))' #!)53!%%!&)!-!!#!6!!%I!N$TNk!"##"JJ$XN!""!"5!$!!!J%`!"(`*!kC1J!3 JJB)!r*!!33!8J!`!!)"-!!4m#31Q6S!%))'#!!#3!%%!&)!-!!#!6!!%I!N$TNk !"##"JJ!FN!""!"5!$!!!J%`!"(`*!kC1J!3JJB)!A*!!33!8J!`!!)"-!!4m#31 Q6S!%))'#!$b3!%%!&)!-!!#!6!!%I!N$TNk!"##"JJ#FN!""!"5!$!!!J%`!"(` *!kC1J!3JJB)!+*!!33!8J!`!!)"-!!4m#31Q6S!%))'#!,53!%%!&)!-!!#!6!! %I!N$TNk!"##"JJ#NN!""!"5!$!!!J%`!"(`*!kC1J!3JJB)!m*!!33!8J!`!!)" -!!4m#31Q6S!%))'#!(b3!%%!&)!-!!#!6!!%I!N$TNk!"##"JJ!JN!""!"5!$!! !J%`!"(`*!kC1J!3JJB)!U*!!33!8J!`!!)"-!!4m#31Q6S!%))'#!(#3!%%!&)! -!!#!6!!%I!N$TNk!"##"JJ"BN!""!"5!$!!!J%`!"(`*!kC1J!3JJB)!f*!!33! 8J!`!!)"-!!4m#31Q6S!%))!-!!#3!%%!&(`*!kD!6!!%6S!%)!!!!"b!!!"N#!# 3"TL!!!#N'!#3"3%mJ!!!G"!!N!8"X)!!!-!B!*!&!R#!!!$S+!#3"30BJ!!!k!J !N!8%3)!!!3`3!*!&"8b!!!"S!*!'"E5!!!#8%!#3"3C)J!!!2!J!N!8'K)!!!$` !N!B'`)!!!'33!*!&"b5!!!%8'!#3"3JiJ!!!`"!!N!8)q)!!!33S!*!&#JL!!!" B%!#3"3TJJ!!"C#!!N!8,a)!!!-33!*!&$)L!!!%F'!#3"3fNJ!!!I!J!N!81))! !!)`)!*!&$V#!!!#d#!#3"3pNJ!!!G!J!N!83*)!!!'`)!*!&%*!!J!!"C$!!N!8 4p)!!!&J)!*!&%Nb!!!'!3!#3"42-J!!"1$!!N!89")!!!P4S!*!&&eL!!!%i+!# 3"4L3!)!!!&3!N!BBj)!!!&`!N!BC3)!!!(!!N!BCX)!!!(!!N!BD))!!!9!J!*! &'h#!!!#)!*!''rL!!!(!'!#3"4fiJ!!"!!J!N!8HZ)!!!*33!*!&(db!!!#B%!# 3"4rNJ!!$@%!!N!8MF)!!!%!)!*!&)l#!!!#8+!#3"54%J!!!9"!!N!8NQ)!!!,! J!*!&*8L!!!"%!*!'@q#!!!"8#!#3"9`mJ!!!@!#3"Pb8J!!!0!#3$B)+)K2dJJ) A&(JAX"4m&)J#i!,S![!#X!,!!XJ#Z!2i!SJ8J!+3!"5%!Y!#f!h3*3aR+'6F*4! %)QFS"L)4r))#(a(d!I`3m3*)%Z!#!!*3![d5H!,i%K!8@"3i&"J6q!-$!PJ$dJ2 *!hi$B!0-!Q!AY"$X%'J2j!l3$k!KM!*%(L%r&b0*EQB")djK6JdL(F!))JS)KJ) 8#I`4p"SJ(q3P5#5B*B`PS#H`,VJZ3#fi0k!eP$6N0""#"%(J@QKDB#*D@!3J-`3 Z59"3"@K[Fh4c*h0[BfYPG&pPGQ9ZG&pSB@jNE'9b1L"cEf0VCA3JEQpd)'PZ)(9 cC3%MU[i(#b,Ap3%K!3%K"!)L!QJ))$%69'9cG&4bB@0V)&9cCA)J5@jQEd9bFQp b)#9N)%GPG(4TEQFJ8hPc)%9ZGQPbEfjc!5"+4@jf9Q9b)#9N)'eKBfK8HA"P)#9 N)(0jFeCPFL!PC#"`FQpM)#9N)%C395!PC#"$Efa[FP&%)#9N)'YLC#!PC#"KG&C PFR-J*@3"+#9c1L9c1L9c!590B@028`%MU[i($#%P!5%"!5%%!L)#J!`K#a8L&,! #)3%$)K5`&L)#U!)L!U!#)J+B##%6&5)9X!)K!3-L&E!@)J+S!L)#S!)L!TJ))4% 9)KD`!L%"!b)@X"BL!UJ#)J+J!L)#Q!#5"##"I`'3#3+3"3'3%J3)N!m`N!S)N!H JN!D!N"3)N!CJN!C!N"3)N!3"J*!(3*!C#*!(3!L3"S#!#*!13%!)N!Z!N!4!#*! )3)!)N!4!3!L3"B#3#`L!N!3)N!S$)N8JJJ+""8A343a&d%A34G"&d%A34G"&d%A 34G"&d%A34G"&d%A34G"&d%6)4G"&d%A34G"&d%A34G"&d%A34G"&I%6)45"&)%8 -4G"%b%A34G"&d%A34EK%b%9B4G"&d%@J4G"%b%A34G"%b%,)3`"$!%,J3`"$!%- !3`"$!%-!3`"#`%-!3V4$!%-!3ZK'Y%E!4X"'`%E!4X"'`%E!4X"'`%E!4X"'I%E !4X"'`%E!4Ra'`%E!4X"'`%E!4T4'`%E!4X"'`%E!4U4'`%E!4V4*)%NX55a*,%N X55a*,%NX55a*,%NX55a)c%NX55a*,%NX5-a*,%NX55a*,%NX53"*,%NX55a*,%N X54"*,%NX*NNJ,8PZCJ'j&J!!!3!!!!(p!!!!r3!!!&S!N2-4GQ9bFfP[ER-ZE@P d,Q9NG3#3"%J!3B!!!!!&-#id,M%l-#id,M%X)%0[F(PbD@GSG#!a16Nh)%eKFh0 KBfKeFf9dG(-J5@jcG'PdGA4P)'pQ)&4PBfKZEfa[ChN!!!#B!*!,!3#3%`*Y0MK V!*!6!3#3"PES!*!*2"&0594IT94PFh48FQ&MDdaTBR"hF'-!N"-"!!"@m!!!F8d !N!Nm%8e*9&qP9'9cG&4bB@0V6'PL!!!"!!!!!Id!!!$p!!!!@JG,jj!!64i!!!! F!&S!!N069&)!!!!DGQ9bF`!!!#CMCR*R!!!!-J4-rrm!N!N"rrm!!!!9!*!'rrm !!!"K"e'ZQ+%S: \ No newline at end of file
diff --git a/src/mac/TestTrack/ShlibTestTrack.c b/src/mac/TestTrack/ShlibTestTrack.c
deleted file mode 100644
index 01c69f69b8..0000000000
--- a/src/mac/TestTrack/ShlibTestTrack.c
+++ /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
index 12e656b1a0..0000000000
--- a/src/mac/TestTrack/ShlibTestTrack.h
+++ /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
index b005b1c090..0000000000
--- a/src/mac/TestTrack/TestTrackLib.h
+++ /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
index 167340b665..0000000000
--- a/src/mac/TestTrack/testtrack.h
+++ /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
index c87625249d..0000000000
--- a/src/mac/libraries/CCache API/bin/CCacheGlobalsLib.68K
+++ /dev/null
@@ -1 +0,0 @@
-(This file must be converted with BinHex 4.0) :&%0$B@0SC8GXEf*KE(0-D@)Z0MK,!(0SE')rN!3!N!3"#J!!!CBl&%T[H5&`C@C QE6BiD`!!!!'b#cB`!*!0!`!#!*!EP!!"!J#3"!8!N!G)!!!!5!!!!!m!!!#8!J% #!*!%$J#3$fB!!!#N"!%#!%eKD@i!*8%e9fpbE'3!6'pKC'9b!*!&+L)r2!%M"UR `!L,rr443rj!%!*!%rj!%!*!%rj!%!*!2!3!!!%3!!!"%!!!!8!!!!!%!!!!"!!% !N!TR3fjdFQa#E'pMD`!!"!#3"3%!#eP3!3#3"J3!!Ble!!!"!!!!!@3!!!"N!!! !-J#31'!!!!""F("X!*"!B!!!!%e06%)!N#"-D@)J5@e`Eh*d)&"33`#3&Ne36%B !N#0J!*!,!3#3%`&Y0MKV!*!6!3#3%8!968P8Ak9$3f&MD'9(E'pLB@ac6'PL!!! "!!!!!@3!!!"N!!!!-J9@1G!cb!!!!"`!-J!!BfCbC`!!!!S!!2rr!*!)q0d: \ 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
index 67940ed6ed..0000000000
--- a/src/mac/libraries/CCache API/bin/CCacheGlobalsLib.PPC
+++ /dev/null
@@ -1 +0,0 @@
-(This file must be converted with BinHex 4.0) :&%0$B@0SC8GXEf*KE(0-D@)Z8&"$!(0SE')rN!3!N!A`!!!"PU")5Qpj)A"PCQC `Gh"M!!!!!E*6cT3!N!d$!!)!N!6rN!3!N"2`!!3%!2q3"!#3"`J!N![`!J3%!2q 3"!#3$fB!!!#!"!3%!*!&rj!%!*!%rj!%!*!%rj!%!*!2!3!!!%3!!!"%!!!!8!! !!!%!!!!"!!%!N!TR3fjdFQa#E'pMD`!!"!#3"3%!#eP3!3#3#!%!N!T+,`!!!3! !!!&N!!!!C!!!!$)!N%`3!!!!,`)!!!!#!!!6!!F"!!%!N"!(!3!"!*!3!3%!N!S (!3!"!3!"!3!!!!%!!!d!!3#3"4&KER0TAh"bC@CTH#jYB@-ZD!#3%!%"!!!!!3! !!!%!N!3"!*!&"3'3"`#3"J%!!!P0CA*R!!!!B!#3#`%!N"-"F(G`B`#3%`%!N"& !&8e*9&qP3d0KBfKP4fa[BQ&XFdaTBJ!!!3!!!!&N!!!!C!!!!$)&9MR30#B!!!! F!$)!!'0QFQF!!!!+!!$rr`#3"!9EF&$%G`: \ 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
index ba927ec34d..0000000000
--- a/src/mac/libraries/CCache API/bin/CCacheLib.68K
+++ /dev/null
@@ -1 +0,0 @@
-(This file must be converted with BinHex 4.0) :$80$B@0SC8aTBLif1%X!FfKXBN0"*%J"!!!!(ei!!!'5RAj+EhNKF'9QCQdf1'X !!!!"XJXf03#3$3-!!J#3$KM+!!!BbJ!!'-S!!!#8!!%#!*!%"3#3"J*i!!!#H!! !!D-!!"PJ!J%#!*!%$J#3$J4D!!!E"!3"!J"0B@PZ!#9"09G[FQaN!%a[B@4PFJ# 3"#T451FB1#4[!"JS,`!F*Lm!)#K[!#3JEIpi*P!J#fBb5(J!%'(r!!!-1#5!*P) J#fB%F!CJ2N+V!!3J8N+3!#"53UJ!##"53UJ!$#"YrhJJNQ!#*)Y`!EL!E`4`#@! @5S0R"L"$F!%JJ#!-C`BJEIrm+*!!F!"-ha`B6R3!%#T451F!-#4[!!`J#QFB*P) J#fF5,`YKr`!!&L![%Q(r!!!+Z'!%F!TJ"%+5F!"-h``!6R3!"#T451FH1#C[!#! Q,`!N,#m!+#K[!#`U,`!`+#m!0#!,CJC`#Q!!!0C+K'B'F!aJ!!$-5(J#*Q(r!!! ,G#4!)!TQ"R!'B!!!YNU$Ca)J3h$r8S"+''Ek$)!!!!$rC3C`!@!!!*SJ5L*$)!J 3f@Em)!aR%L"-F2p5J%SBC[S-J!!!!2pP"(!-B(4"kJ%%)N`J#"$CC[`P43)-3QS #"#9'!3!9I!!#!K"`C#9!!K)[#Q(r!!!,1L9!!JK+UJ))CJ4`"Q!k5UX!#'B33US #)N+U!KiQLLG+!!4J&L"V!!3K5J)H*@X!"!)L3US#(LG+!!45U`!)8UX!$#"%))T `!%cI((K1G!!B+P&19[ri51FH2#SZ!!JSEJ!-+#i!%#CZ!"Kf!%U&CJC`#Q!!!*S J#fB'F!aJ!!#3!#!-CN`JEIq),""`!Eb!CKj`!5m!5(J!UbmYrr3[,Iri)QhrM#" C6T!!+Qlrp'!LF!5mJ'BFF!%[!%Ki!+X[,Ird,bhrq#*Yri`J@8k3!#TZrr3J454 3B#)[#Lm-)QhrJ#"C6T!!+Qlrp%U!CJUiUJ%!CJ4f!@!%*'S#(L!+C`4+!fI@5J0 R"LD+F!"J"%+6F!T-haai6Pj1G!!8+P&19[ri51F32#KZ!!JNEJ!-)!aQ"(!+B(` J#QB%F!aJG%U5CN`JEIq)*K"`!ED!CKj`!5m!5(J!c5mYrr3[,Ir`)QhrM#"C6T! !+Qlrp'!LF!5fJ'BFF!%[!%Ki!-d[,Ird,bhrm#*Yri`J@8k3!#TZrr3Q8J`V!!% #%'F%F!jJ&Lm,,`aKr`!!%&3[#f(r!!!)5%+5F!"-ha`)6Pj1G!!)+P&19[ri51F B2#CZ!!JSEJ!-)!YQ"R!+B!!!hL!-CJC`$'!!!04+P'C-)'hrL#B3F!'fJ'BHF!% [!%Ki!1X[,Ird,bhrm#*Yri`J@8k3!#TZrr4J)R!%YS"Q((!",`")H!$V,bhrp#m Yrr!LEIq-)&P1N!!UE[rd*&4`C,#U!K*R%#m+BIm!!"155J"Q"(!)B'K+UJ)LCK! QUJ)H*LS#(QF')%0#U!)L5US#(QB5*fS#)J!%*LS#)QF')%0#U!)H+#S#)QF@*LS #(QF3)%-K4!)L)'S#)L&U!Ki#(K9m!!%#%#m-,`XLEIrX)&P1N!!UE[rd*J"5U`! -)!0-ha`B6Pj1G!!)+P%LE`!%)'m!##!*CJ4`#Q!1)!KR###T!!a`!'!#F!a1G!! )+P&)ja!`*Qm!%#4[!"3J#fB%F!TJ5#!+CJ4`#Q"!*LS#%R"NYS"R&R"QYS"Q$#m +BIm!!"+q5J"Q"(!)B#![,`!F,bm!(#m+BIm!!!dJ*J"+JfB%8UX!#&+V!!`J!dc I$!K1G!!3+P&)ja!`*Qm!%#4[!"3J#fF%)!TQ"(!+B$BQ+J)5F'5fJ'F@F'DfJ'B -,`TKr`!!%Pa+!'B%F!KJ&Lm[!"`[,`!F,`TKr`!!$E*5U`!-F!"-h``)6R3!%#T 46PErq%MR'$`QEJ!)*'i!$#JZ!"!SEJ!8)!YR"#!+CJC`#Q!!!*JJ$'C-)'hrL#B 3F!'fJ'BHF!%[!%Ki!@X[,Ird,bhrj#*Yri`J@8k3!#TZrr4J)R!%YS"Q((!",`" )H!&V,bhrp#mYrq3LEIq-)&P1N!!UE[rd*LS#%R"NYS"R&R"QYS"Q$#m+BIm!!"' Q5J"Q"(!)B#DiUJ%!C`4`#Q!F5(J!rbm-5'S""#*Yrh`J@8k3!#TZrr45U`!-F!" -ha`B6Pj1G!!3+P&)j`!i*'m!&#C[!"JJ#QB%F!TJ3("QX+S#%QB3,`TKr`!!%8K +!'B%F!KJ+#!,Cb*)H!$rBIm!!!88*S!S8b!-CJ4`"Q!1)%a$kJ%%)!J3f@EmF!" -ha`!6R3!$#T451F!-#4[!"!QE`!8)!TQ"(!+B#C`CV#U!K*Q%#m+BIm!!"$U5J" Q"(!)B!iJ#fB%F!CJ"LDU!3"`!%cI$!"1G!!-+P&)j`!`*'m!%#C[!"3J#QB%F!T J0("QX+S#%QB3,`TKr`!!%+C+!'B%F!KJ(#!,CaC)H!$rBIm!!!4b*S!J8b*+)!J 3f@EmF!"-h``!6R3!$#T451FB1#J[!"JSE`!F*'m!)#!-C`JJ#QF%5S4Q"(!+B%K +NQBD5(J!#'(r!!!%,#5!*K*Q"(!'B$!J4#*$)T!!)&)Q%'B3,a*Kr`!!"%a#NN+ 8F!0J&#m-,`0Kr`!!$GSQ8L"6*UJ#(R!!60mF'%jd!!`U88MR($K46bB[!#3QE`! S+'m!,#4[!$!J#fF))!TR"%U$CJC`#Q!!!6`J$'B'F!CJ!!%bF'D`U`)5CK)[#f( r!!!2a%S!CJC`#'!!!4K+NQBN5(J!#'(r!!!$ML5!*K*Q"R!'B!!!rL"$3UJ!"'! ')%05U!!%1LX#"$!&5-!Q%L"$+#J!",L!E")J"1@))'X###"`#!"`Bl#3!'I8-!9 )`,L!E4)[%Q(r!!!$I%+83T*`!f!!!,!J"1@))'X###S`#!!J45B3F!'fJ'CS5(J !#'(r!!!$&#L!5T4Q"R!'B!!!K%Ki(AjKr`!!![iJ9#&!!!3J9#BS!!4Q"(!'B'B J8L!S!!6PL#"V!JJJF!J!)'J!"#*$)$`!!"eqFL#`J@8%SLjJ$NU!C`SL#4,B8i" QqL*"B#K`!VD!CK`[D!!%!!4`!Lk!,``[,`!),bm!#'(r!!!(KQ!'3T4`%'!))&* 5U!!%F!"36dcI($K1G!!3+P&19[ri51FB2#KZ!!JNEJ!-H!!J$'B'F!TJ!!#F)!T Q"R!'B!!!NL!X!!K5J1@),`!LEIqX)&P1N!!UE[rd*)"+NQB%F!CJF#C8B'K)H!) #)QhrV#"C6T!!+Qlrp#"5)B!i!#K55V3i!'B%F!CJ5L"d1!!L5b!)%0PQr#"5)(! i!%(S!2p$k`%%)!J3f@Em)&)JF$J!)@X"!!(q*QX#(P+%@)-J#fDQ)!6PL#"53V! )!(!!B!4f!'$U60mF'%jH6R3!##T4,`SNE`!-)!TQ"(!'B!S[#Q(r!!!"i(!!*&p 1G!!)+P%[#L4[!!`J#QB%F!CJ#Lm+BIm!!!(!F!!NAdjd!!JU85m+*'m!$#!+CJ4 `#Q!8,a*Kr`!!$MJ[%Q(r!!!"Q%+5F!!NAdjd!!JU88j@rrK)jaJd*'i!$#!+CJ4 `#Q!iH!"J-#mc1!!LEIqF)&P1N!!UE[rd8S4BJbC55V-i!'EN,a)LEIqF)&P1N!! UE[rd3T*`!'!%GJ"Ji%cI$"K1ANjd!!JU88j@rqa)ja!N*'i!$#BZ!"!J#QB'F!a J!!$15'lrm#*YrkJJ@8k3!#TZrqK`C,#U!K*R'%KZrqp)DJ)@5'lrm#*Yrk3J@8k 3!#TZrqJJ!e1!C`a6J'F58i"R0Q!!!)C`C#9!!K*J!!#!*LS#%R"NYS"Q&("P*8! #%L9Zrr!#&L9Zrr3#'Q"JF'DfJ'CDF!KJ@#BU!K*`C,D!CK4`CL9!!K)PE[r`!KB PE[rd!KTJ1("QYS"Q#NSZrqpQ"(!)B#T`CED!CL*+,[r[Ca4`CL9!!K)PE[r`!KB PE[rd!KTJ#(!)B!C`$'!#F!"-h`3)6Pj1G!!-+P&19[ri51F3*#BZ!!J[!b*Yrk` J@8k3!#TZrr3N3#!+Ca![!bm+)QhrQ#"C6T!!+Qlrp#!+60m%#%jH6R3!"#T46PE rq%MR'#3NEJ!),`SLEIqJ)&P1N!!UE[rd*J!J#QC-)'hrL#J3F!'iJ'BHF!%[!%K i!#F[,IrB,bhrh#*Yri`J@8k3!#TZrr4J)R!%Z)"Q((!",`")H!!R,bhrf#mYrp` LEIq-)&P1N!!UE[rd5S0Z6#"YriJS%(!"Z)"Q(R!",`")H!!S,bhrf#mYrp3LEIq -)&P1N!!UE[rdB#*`",L!CKa`!5m!5(J!+#mYrpJ[,Ir8)QhrM#"C6T!!+Qlrp#m $3UF[#L*Yri3J@8k3!#TZrr3[!d+R,`SLEIq%)&P1N!!UE[rd,`-[#L*Yrj3J@8k 3!#TZrr3[#L*Yrj`J@8k3!#TZrr4-h`3B6Pj1G!!%+P&19[ri51F3*#BZ!!J[!b* Yrj!!)&P1N!!UE[rd*%!J#QF3,`-[#L*YrjJJ@8k3!#TZrr3J#NcI"!K1ANjd!!3 U88j@rrK)ja!N*'i!##!+CN`JEIq)*K"`!ED!CKj`!5m!5(J!8#mYrpJ[,Ir3)Qh rM#"C6T!!+Qlrp'!LF!5fJ'BFF!%[!%Ki!&![,IrB,bhrd#*Yri`J@8k3!#TZrr4 #DJ)%0A`!#J)'5(J!+'(rN!4@*8!###!U!JK-h`3)6Pj1G!!%+P&19[ri51F30#4 Z!!JJ#QC-)'hrL#B3F!'fJ'BHF!%[!%Ki!&i[,IrB,bhrc#*Yri`J@8k3!#TZrr4 J)R!%YS"Q((!",`")H!"H,bhrf#mYrm`LEIq-)&P1N!!UE[rd*+i!$#9Z!"!!"%U Z!"4Q#%+U!!K`!'!q,bi!%'(rrrrqa#9!!!JQDJ!))!YQ"(!'B#3L5b"Z!"3J,J! 3FL#`J@8%SLjJ$NU!C`SL#4,B8i"QqL*"F!"-h``)6Pj1G!!3+P&19[ri51FH2#K Z!!JNEJ!-H!!J#QC-)'hrL#S3F!'kJ'BHF!%[!%Ki!(3[,IrB,bhrb#*Yri`J@8k 3!#TZrr4J)R!%ZS"Q((!",`")H!"d,bhrf#mYrmJLEIq-)&P1N!!UE[rd*N`J$'B )3T*J!!'`8S4+QfEk)!45J1@),`"KrrrrrJ)NJ#S!5S9Q6#"YriJX%(!"[)"Q(R! ",`")H!"m,bhrf#mYrm3LEIq-)&P1N!!UE[rdB#*`",b!CKa`!5m!5(J!I#mYrpJ [,Ir%)QhrM#"C6T!!+Qlrp%U&C`!"3LC-B!!"+NKi!!aKrrrrrCJJ8L#!)&*+N!" Q6#"YriJX%(!"[)"Q(R!",`")H!#$,bhrf#mYrm!LEIq-)&P1N!!UE[rdB#*`",b !CKa`!5m!5(J!JbmYrpJ[,Ir!)QhrM#"C6T!!+Qlrp#"5,""R!!$8)NBJ9(!-FL# `J@8%SLjJ$NU!C`SL#4,B8i"QqL*")&)J8#mS!!4Krrrrr3iJ8L"3)8!!##"5)&" +U!!)CN`JEIq),""`!Eb!CKj`!5m!5(J!LbmYrpJ[,Iqm)QhrM#"C6T!!+Qlrp'! LF!5mJ'BFF!%[!%Ki!)X[,IrB,bhr[#*Yri`J@8k3!#TZrr3J8L"3,#J!#'Fq*K3 J3b!S!!3L4L"$)'J!#()JX)&P"+)ZB!j+J'F+)JN5f&1!C[SL39L+@)Y+NfB!rY3 J"1@))%9#X!J!*)9-haai6Pj1G!!)+P&19[ri51F!2#KZ!"!QEJ!-)!aQ"R!'B!! "%%Ki!!KKrrrrr$JSJ%U8CJC`"Q!!!2T)H!"-BIrrrr`L*%!J#QB'F!CJ!!$N5(J %iQ(rrrrm$#5!5T*Q"R!'B!!!cNKi"1*KrrrrqrBP3!!%5US!"'B'F!CJ!!#d5(J %hbm6,a)LEIpm)&P1N!!UE[rd5(J%hbmV!!3[+J!%)QhrI#"C6T!!+Qlrp#mV!"! [+`!-,bX!#%KU!!KKrrrrr'BPD`!8!"3PD`!B!"JPD`!F!"`PD`!J!#!PD`!N!#3 PD`!S!#K)DJ!X,bX!,'(rrrrmmLmV!$J[+`!d,bX!-%KU!$"Krrrrr"i[+`"%,bX !3#mV!$a)DJ!mBIrrrr`)3US!5#"8F!)JJ#"8)8S!"(!!60mF!%jH6R3!$#T451F !-#4[!"3J#QB%F!CJ@NKi!!KKrrrrq`iNJ#C5)!YQ"(!'B%4`!5D!5(JGIQ(rrrr kp#C!)!YQ"(!'B#`L5b"[!"!J2!!!(Ajb),#"C35L,Q!15S"R#L)*%YK6J'Ek)N% J8L&,!!4`!%cI$!"1G!!-+P&)j`!`@8mNE`!33TFJ#QB'F!TJ!!$8F!'`V`!8C`j `!V#[!"4R"R!3B!!![P*U!J3`+J)%X'S#"QCL-#S#"Y"!08!#"M!U!JC)`1@),`" KrrrrqQ!Q3#!,CJC`"Q!!!)S`+J)'5-"-I!J!N!3#jBJL5b"U!JKb),#"C35L,Q! 15S"R#L)*%YK6J'Ek)N%[+J))BIrrrrN5*8X##(!"X+m!&'B55&F[,`!F,bm!('( rrrrqh'!HF!+`V`!8CK*)9bm[!"`[,`!FBIrrrrf1B!4`%'!8-#S#"%M!8i$PL#" U!JJKP`J!F!"B6dcI$!"1G!!-+P&)ja`i*'m!(#!+CJC`#Q!!!*af!'!!!*)[,`! N,bm!*#"U!JJJF%J!,bJ!"#mS!!"Kr`!!!6a+!'G8)!2PL#"U!JJSF!J!,`aKr`! !"3![$'(rrrriB#J$B%JQDJ)))!45J1@)*l-)!&J!8S4BK6!U!J4)`&1!*J#iJ'h H)!2PL#"U!JK#X!J!8fS#"'!38S0BK$!U!J4)`,D!E3$rI(!!B!SU!q@0B-Ci!'$ Q60mF1%jd!!`U88j@rr4)jaJd*Qi!##4Z!!a#V[rd)!TQ6#"YriJQ%(!"YS"Q(R! ",`")H!&),bhrf#mYrlJLEIq-)&P1N!!UE[r`B#*`",D!CKa`!5m!5(J"5#mYrpJ [,Iqi)QhrM#"C6T!!+Qlrm#!+CJ4`$'"!H!"J1#"U!JJYF$J!rr4)E[rd,`XLEIr J)&P1N!!UE[r`8S4BJc!U!J4)`,L!EGB[+J))BIrrrrGFF!"J"(B!B14-h``B6Pj 1G!!)+P&19[ri51F!0#4Z!!`J#QF)*Qi!&#!,CJC`!'!!!,`J,J!)X+i!%'F'F!" J!!#XF!'`VJ!)CPT)D`!"5'S!!5*Yri!J@8k3!#TZrr4+J'Bq5'X%idKU"1-LEIq !)&P1N!!UE[rd5S"Q*NKV%iP)DK1*)QhrJ#"C6T!!+Qlrp%U!CJiJ+KKmX+XBI'B %F!&J6(!!B%K`!V#Z!!KQ2Lm6,a)LEIq!)&P1N!!UE[rd5S"Q*LmV!!3[+J!%)Qh rJ#"C6T!!+Qlrp%U!CJiJ+J!BX+X!''B%F!&J"R!!B!*`!%cI$!"1ANjd!"!U88M R($JQE`!F+'m!)#!-CJC`"Q!!!@j)H!)QBIrrrrB'+)!N9#!+CJC`"Q!!!9BJ5L* ,)!J3f@Em*@X"!!%!3HS""%2V!33J#"$CC[`eD`)%!J3eD`)'!JB9I!!"!K!`+J) '5-$PL#m!BIrrrr@i*8!##%UU!JKQ"R!'B!!""RJ!B!!!r#"V!JJSF$J!+K4`!EU !CJ!!K%Ki!!KKrrrrpBBJDJ)))B!i!#"U!JJSF$J!)!aQ"R!'B!!!bR!"+)")H"e qBIrrrr9H)'S###"`1!!K3!!%)'S###"`1!!SD!!%)!aQ"R!'B!!!QL*-)'X###" `1!!JD!!%)$`!!"eqFL#`J@8%SLjJ$NU!C`SL#4,B8i"QqL*"B%T`!VU!CKJJDJ) )5(!i!#mX!!3[,!!!BIrrrrRLB#a`BlU!CLC)H!!)BIrrrr6J)'S###'!1!!JDJ) )+(!i!#!-CJ4`"Q!NF'-SJ&+%@)-`+J)%5-#iJ'd!ra4#UJ)L3US#(R!!B!4f!'$ N60mF1%jd!!JU88MR!$JSE`!3*%`J$'B1B"S[+`!)BIrrrr5q@)SQ8L!,CZi[$'( rrrrdVNcI(!"1G!!%+P&19[ri51F3*#4Z!!JJ#QCH)'hrL#B3F!'fJ'BHF!%[!%K i!F)[,IrB,bhrY#*Yri`J@8k3!#TZrr4J0(!%YS"Q,R!",`")H!(#,bhrf#mYrl3 LEIq-)&P1N!!UE[rdB"![#Lm+)Qhrk#"C6T!!+Qlrp%U5CZa`!%cI"!K1ANjd!!3 U88j@rqa)ja!N*'i!##!+CN`JEIq)*K"`!ED!CKj`!5m!5(J"dLmYrpJ[,Ir3)Qh rM#"C6T!!+Qlrk'!LF!5fJ'BFF!%[!%Ki!G)[,IrB,bhrd#*Yri`J@8k3!#TZrqK )E[rZ)QhrU#"C6T!!+Qlrk$B!-!0)`'F%F!"J0("NX+S#%QFN5'lrpdKU!KC)E[r Z)QhrT#"C6T!!+Qlrk$B!-!0)`'F)F!"J#%)ZrrF3,[rh60m%#%jH6R3!"#T46PE rq%MR%$`QEJ!))!YQ6#"YriJQ%(!"YS"Q(R!",`")H!(R,bhrf#mYrl!LEIq-)&P 1N!!UE[rdB#*`",D!CKa`!5m!5(J"jbmYrpJ[,Iq`)QhrM#"C6T!!+Qlrp(!#X*0 QCL4V!!3[%Q(rrrrbrLmU!!4Krrrrm[4+UJ!3C`S[+J!3BIrrrr,N5US!1'F+,bS !1'(rrrrbe%UU!%4R#LmU!%4KrrrrmX3SDJ"))!aR##m-BIrrrrhJ+'S!,#!-C`J [$'(rrrrpd#mV!!4KrrrrmTT`!%cI(!K1ANjd!!4PF`3Z68P8)%N[8b"0B@0%CAB &,J3-)5KZB@eP)#%p)$!T!5N)3d0KBfKP,Q-")$d2)5JUD'&ZC'aP)#%p)$!T%5% SF(*TEQ0TF'&X)#%p)$!T$5%SFf&QC9!J)6dJ-#N-3d0KBfKP9A4TE#jM!5d-)5K cDATP)$iJ-%`T!5X+)5KZBb!K25!`+3%j#b%SEf*U)#%p)$!T$#%SC'9cG#!K25! `+3%r$h*PG'4PFh3J26dJ6P9-6!iU+Q4PFh3J26dJ6P9-6!%h&LJU+Q4PFh3T,6j NBA4K)$dp)%j96%`"+`TZBb!p25"198a-!6-5)5KMER4bE%*XEf0V)#%p)$!T!5i 0)5KMFQ9NFb!K25!`+3!l)IU#!K-!jJ$D!-)!XJ#L!*3!L!"m!'i!B!"5!GJ!3!* !!NJ!-!!Q!"J!&!!J)Mmm!5-'UI!#)[rp$L)+)S)#*`'3!!R+!C!!#D!"N!!*J!' 3!!PJ!C!!#*i"N!!(-!'3!!Dq!C!!"Q`"N!!'+!'3!!A+!C!!"3)"N!!%UJ'3!!4 %!C!!"#!"N!!$(J'3!!*q!C!!!EB"N!!!XJ'3!!"m!C!!"#)"N!!)C2q3"!#3"2q 3"!#3"2q3"!#3"`3!!!!1!!!!!3!!!0`!!!$S!!!#p!!!!!3!!!!9!*!2!3#3#b) !N!X$!!!!!3#3"d8!!!!"!!!!!3!!!!)!!!!%!*!(FJ#3#`J!!!!'!*!%!3!!&J) !!#m#!!!h!J!!2J%!!&F#!!"N!J!!I`)!!)N#!!#@!J!!S3)!!+`#!!#h!J!!``) !!08!!3#3"3B!N!3"3B$[5Je#%i!h4K40594IT80$B@0SC8GXEf*KE(0-D@)!Cd0 ZG(*X3Qa[BfX!68P8Ak90594$6'PL!(0dFQjMF(N!Fh4bBfe`!'ePEA0PG!"0594 IT84PBR9RCfPZCdaTBJ"R4'9LG@G6D@GZB@`!3@aPFR46D@GZB@a"G!"*ER4PFQC KBf9-D@)!6Q9h8(4b8hPc!&9ZD'pXC%ePE@pbH3")EfaN6@9YEh*j!%4TFh"[Ff9 3G()!4f9d8(4b8fPkC3"6B@eP8(*[Bf9cF`"(CA4$GA*bC@jd8(*[Bf9cF`"1CAG 3G()!Bf0ICf9dAf0bC@4IGQ9bFfP[EJ"MBepQFQ9PAdj$AfPZCQm!Bf0ICf9dAf0 SB@jRC9pdD@eP!'0MAf4PFh4bEhN!Bf0IBfa[Ff8!Bf0IBh*PBA4P!'0MAfCbC@9 IBh*PC(-!Bf0ICf9dAfjKE@8!Bf0ICR*PC9p`FQPZBfP`B@`!Bf0IFQ9YEhCPAf0 bC@3!Bf0IEh"PEJ"MBepRCA4I6N0ID@jQE`"MBepcCA&ICQ9dBfKI6N0c!'0MAh0 PG&p`FQPZBfP`B@`!Bf0IFfKeG'4[Gfi!Bf0IFf9aAfCPG'0SAf0bC@4c!'0MAfG PG&p`FQPZBfP`B@`!Bf0ID@jTG'PKE'PkC3"MBepcG'pbC3"MBepXEf0VAh*PFA9 PFh3!Bf0ICR*PC9pZB@eP!*!*"!!!!!`!!3!)!!3!!!!'!!J!"J!)!!J!!!!+!!3 !#J!!!!X!%!!,!!`!$`!!!")!"!!5!!!!%`!)!"-!%qq*!!mc9`!569F!#TVI!!J Qc`!*6#%!$Fk[!!XfqJ!4q!B!$ZC6!!F66!!1ZFB!%)+a!"#-#J!,2Ad!%JKH!"$ -#`!0b18!##F0!!mB(J!-CeS#!!$F!!!#%!!"!J!!m!!!!G!!!3)!!3!!!!)i!!% #!!%6!!!#3!!"!J!"(J!!!NJ!!3)!!5F!!!*B!!%#!!%a!!!"f!!"!J!"2`!!!JJ !!3)!!8X!!!(S!!%#!!&G!!!#+!!"!J!"E!!!!P!!!3)!!A3!!!(`!!%#!!'$!!! #!!!"!J!"P!!!!L!!!3)!!D8!!!*J!!%#!!'a!!!"q!!"!J!"a!!!!KJ!!3)!!G8 !!!*S!!%#!!(M!!!#-!!"!J!"l!!!!FJ!!3)!!I`!!!(J!!'qG3!!!3!!!!&J!!! !B!!!!$)[Fh*M,feKBbpdC@aZCA30Eh9d)'CPC5"TFb"SCA*PBRNJCh*KER4PC#` JF(*[GQPNC@3JG'KKG#"dD'8JB@*[GQ8JBfp`HA*TCfKd$5!U)'j[G'PMC5"KF(" PBA)JD@iJB@aX)'0[F'PPFb"KEQ3JG'KKG#"LEh4S)(4SBA3JBfp`HA*TCfKd)'j [G'PMC5"KEQ30)#SJG'KTFb"`CA*YDA0cD@pZ)'j[G'PMC5"KF("PBA)JD@iJFh9 `F'pbG'PZCb"NEf0eE@9ZG'&dD@pZ,#"KEQ3JG'KKG!dJ+L"dD'8JEQ&YC5"[CL" 0,NNZ9#i!!!"F!*!,!3#3%`&Y0MKV!*!6!3#3%6`168P8Ak9$3f&MD'9-D@)!N!8 "!!!!!@!!!!"J!!!!-J9@1G!cb!!!!"`!-J!!BfCbC`!!!!S!!2rr!*!)H,J: \ 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
index 36bdabc3c7..0000000000
--- a/src/mac/libraries/CCache API/bin/CCacheLib.68K.debug
+++ /dev/null
@@ -1 +0,0 @@
-(This file must be converted with BinHex 4.0) :%d0$B@0SC8aTBLif1%XZC'9LG@F!FfKXBN0"*%J"!!!!*fB!!!'@B"K+EhNKF'9 QCQdf1'X!!!!"XJXf-3#3$3-!!J#3$L!B!!!J'!!!)"J!!!#8!!%#!*!%"3#3"J, `!!!#m!!!!G%!!##X!J%#!*!%$J#3$J6Q!!!LJ!3"!J"0B@PZ!#9"09G[FQaN!%a [B@4PFJ#3"#T46PErq%MR!$JNEJ!)+'i!%#CZ!"3JEIpJ5T!!CM*)H!!3BIm!!!p `*)"+NQB%F!CJ4#"53UJ!"#"53T!!)&*#U!!))&*#U!!-)'hrB##5B!BJEIpJ**! !F!'`VJ!-E!4`#@!8)!aR"(!"+)!J#fF')'hrr#D3!(!!60mF!%jH6R3!%)eMBep TEQPdD@&XDATP!!!U88j@rrJ[#L4Z!!JJ#QF@5T*R%Lm5BIm!!"[),a*Kr`!!$9K J"(!+B!4#NR!!*&p1ANjd!!5,Bf0IFfKeG'4[Gfi!!#T46PErq%MR'$JQEJ!)*Li !$#KZ!"3S,J!FPFSJ#fB'F!TJ!!$D5S4Q"R!-B!!!d%Ki!LCKr`!!$SSN3#!+CJC `"Q!!!,T+JfF5)%0`re+!5KKQqJb!!!!!rf8'F!&J!!#H)%SL3b!)%0PQr#!-Ca) J6($r8S"+''Ek$)!!!!$rC34`$'"i3HS""#*-)!J3f@Em*@i!'!)-3QS#"#9Z!"! "!"9m!!)#%("N*8!#%Lm+BIm!!!jD*8!##%UU!JKQ"(!'B$T+U`!)CK"#UJ)L3US #(LD+*dS!"'!@)'X!"#&+!KiPD`!%!L*#UJ)H*dS!"&+V!!K5U`!-)%3JLR!!60m F'%jH6R3!')PMBepMFQ9KG'8!!#T46PErq%MR($`U,J!)*Qi!$#JZ!"!SEJ!BPFT f!%U&CJC`#Q!!!0)J$'B'F!aJ!!$))!YQ!!#%)'hrM(!"X*!!CKj`!#m!5(J!Ubm Yrr3[,Iri)QhrN!!J@8k3!#TZrr4J@L"Yria`!V#3!'B5,bhrq#*YrhJJ@8k3!#T Zrr4J2L"Yria`!l#3!'B1)QhrC#"C6T!!+Qlrp'!Q)'hrM(!%X*!!CKa`!5m!5(J !UbmYrr3[,Iri)QhrN!!J@8k3!#TZrr3J4543B#)[#Lm,)QhrQ#"C6T!!+Qlrp%U !CJUiUJ%!CJ4f!@!%*'S#(L!+C`4+!fI@5J0R"LL+F!"J"%+8F!T-ha`i6Pj1G!! 8Kf0MAfp`C@i!!#T46PErq%MR!$`SEJ!)*'i!$*I,)!aQ"R!+B!!!ZL!+CJC`$'! !!,"+NQB!!)3JEIq-F!'`N!"Q(R!!,`")H!$0,bhrp#mYrr!LEIq3!#"C6T!!+Ql rp'"D)'hrM(!#X*!!CK)[,Ir`)QhrH#"C6T!!+Qlrp'!q)'hrM(!$X*!!CJiLEIp N)&P1N!!UE[rdB#BJEIq-F!5`N!"Q((!",`")H!$0,bhrp#mYrr!LEIq3!#"C6T! !+Qlrp#"5$#J!!3)3C`4`$Q!B*P)[#bm-BIm!!"5i,`YKr`!!#NC#NR!!60mF!%j H6R3!#)KMBepME'pcC3!!!#T46PErq%MR%$`SEJ!)*Qi!$*A+)!aQ"R!+B!!"(L! ,CJC`$'!!!44+NfB!!)3JEIq-F!'`N!"Q(R!!,`")H!$V,bhrp#mYrr!LEIq3!#" C6T!!+Qlrp'"D)'hrM(!#X*!!CK)[,Ir`)QhrH#"C6T!!+Qlrp'!q)'hrM(!$X*! !CJiLEIpN)&P1N!!UE[rdB#BJEIq-F!5`N!"Q((!",`")H!$V,bhrp#mYrr!LEIq 3!#"C6T!!+Qlrp#46F'5`UJ)5Ca![#Q(r!!!BPNS!CJ4`#'"`5US#)QB5++S#(NU U!KjR##"U!Kj#U!)L5US#(QB8+@S#)J!%5US#)QF))'S#)N+S!Kj+UJ)LCaT+UJ) HCa3JDJ)H)@S#)J)L)'S#)L&U!Ki#(K9m!!%#%#m,,``LEIrX)&P1N!!UE[rd*J" 5V!!-)!0-ha`)6Pj1G!!)LQ0MAf4PFh4bEhN!!!!U88j@rrK+VJ!)CJ4`#Q!B5Ui !$'F3)'i!##*Z!!`LU!!-F!"J!R!-6Pj1G!!)NQ0MAfGPG&pMD'&ZCf9IG'PYC3! !!#T46PErq%MR%$!QEJ!)*'i!$(B!)!YQ"(!+B%JJ#QB%F!TJ3("NX+S#%QFBF'D `UJ)5CJ`[#Q(r!!!AKNS!CJ4`#'!J,bi!&#mZ!"![#Q(r!!!3e#B!5S0Q"&+V!!K 5U`!-)!0-h``)6Pj1G!!3L'0MAh0dEh*P!!!!+P&19[rd51F!-#CZ!!JNEJ!-3Ul rp#!,C`3J#QB%F!TJ0R"NX+S#%QFBF'D`UJ)5CJ`[#Q(r!!!A$NS!CJ4`#'!@,bi !&#mZ!"![#Q(r!!!4GP+V!!a`!%cI$!"1ANjd!"#1Bf0IFQ9YEhCPAf0bC@3!!!! U88j@rrK)j`!m+'i!##CZ!!`NEJ!8)!aR"#!,CJC`#Q!!!03J#QB!!)3JEIq-F!' `N!"Q(R!!,`")H!&V,bhrp#mYrq3LEIq3!#"C6T!!+Qlrp'"D)'hrM(!#X*!!CK) [,IrN)QhrH#"C6T!!+Qlrp'!q)'hrM(!$X*!!CJiLEIpN)&P1N!!UE[rdB#BJEIq -F!5`N!"Q((!",`")H!&V,bhrp#mYrq3LEIq3!#"C6T!!+Qlrp("NX+X#%QFBF'D `U`)5CJ`[#f(r!!!@%%S!CJ4`#'!U)#X"!,#Z!""R"(!+B"a)H!$r,`T)D`%%)Qh rP#"C6T!!+Qlrp&+X!!a`!%cI(!"1ANjd!"#3!'0MAh0PG&p`FQPZBfP`B@`!!!! U88j@rrK)j`!`*Qi!$#4Z!"!J#fB%F!TJ2R"QX+X#%QB3,`YKr`!!&CC+!'B%F!K J*L!+Cb")H!$rBIm!!!B+*)"+NQB%F!CJ$L"53qX""#!)%0PQr(!!60m-!%jH6R3 !$*!!Bf0ICf9dAh"bD@jMDA"KE!!!!#T46PErq#m+*'i!$#!+CJ4`#Q!XF'D`UJ) 5CK![#Q(r!!!9*NS!CJ4`#'!85Ui!%'B%F!CJ#L"Z!"!JUJ%!F!!NAdjH6R3!$*0 MBepRCA4IBh*PC&pfCA*cD@pZ!!!U88j@rrK)j`!`*'i!$#CZ!"!J#QB%F!TJ0(" QX+S#%QB3,`TKr`!!&-*+!'B%F!KJ(#!,CaC)H!$rBIm!!!8f*S!J8b*+)!J3f@E mF!"-h``!6Pj1G!!-Lf0MAfGPG&pZB@eP!!!U88j@rrK)j`!i+'i!##CZ!!`NEJ! 3)!YR##!+C`3J$'B%F!TJ5NU5CKK)H!!)BIm!!!6F*)"+NQB%F!CJ-L"5)*3J8NU 3!'B3,a*Kr`!!"3T#NN+6F!0J'#m,)&)[%'(r!!!49L"5)&!L8L+S!Kj`!%cI(!" 1ANjd!!b3!'0MAh0PF9pQCA4MD&p13h-!!!!U88j@rr")ja!i*Qi!$#KZ!"!NEJ! 8)!YR#L!+C`C+VJ!)CJC`#Q!!!9!J$'B'F!CJ!!&'F'D`U`)5CK)[#f(r!!!6Y%S !CJC`#'!!!5a+NQBN5(J!#'(r!!!%*L5!5T*Q"R!'B!!"%L"53UJ!"'!')&*5U!! %-#X#"%M!)&+`U!!%Ea3J8L*V!JJJ+!!%)R%-!("MX*&Rf$!V!J4)`#"5X+J!"'i 5,a*Kr`!!""j#P%+5F!0J!!$#)&)LD`)))#J!"#*a$!!Q%A!"YS"QDNKi!!KKr`! !!kSSJ%U8CJC`"Q!!!*C)H"eqBIm!!!18)&3K3!!%)&4+U!!%CJ4`"Q"i)&)LD`) ))#J!"#*a$!!JD3!%)P3LD3!%)$`!!"eqFL#`J@8%SLjJ$NU!C`SL#4,B8i"QqL* "B$K`!VD!CL`J8L*V!JJJ+!!%)R%-!#eT!!6rp(!#,8$rm#m-,blrp#mZrr"Kr`! !#LCJ"N+8F""J##"58UJ!"(!!60mF#%jH6R3!%**MBepcCA&ICQ9dBfKIBh*PC(- !!!!U88j@rrK)ja!m+'i!##CZ!!af!*A+)!aQ"R!+B!!!NL!,CJC`"Q!!!)JJ,!! )8S$PL#m!)QhrL#"C6T!!+Qlrp#D!5T0Q"(!'B'BN9'"@5(J#!L*YriJJ@8k3!#T Zrr3J8b'!2!!J8dU`2!"Q"(!'B%!J8b"`2!!L5L!)%0PQr#"6)(!m!%(S!2p$kJ% %)!J3f@Em)&-JF$`!)@S"!!(q*'S#(P+$)!TQTL"63V!m!(!!60mF#%jH6R3!#)j MBepRCA4I6N0ID@jQE`!!!#T46PErq%UZ!!aQ"(!'B!`[,J!-BIm!!!*1F!"1ANj d!!L4Bf0ICR*PC9p`FQPZBfP`B@`!!#T46PErq%UZ!!aQ"(!'B!`[,J!-BIm!!!) BF!"1ANjd!!L-Bf0ICR*PC9pZB@eP!!!!+P&19[ri,`SNEJ!-)!TQ"(!+B"3[%Q( r!!!5$Lm5BIm!!!(F3T*`!#4I6Pj1G!!)M@0MAfCbC@9IBh*PC(-!!#T46PErq%M R%#3NEJ!-)!TQ"(!+B$4f!'!8)&)[-$`!)QhrG#"C6T!!+Qlrp&+$)&*+X$`!CZ3 [%L*Yrh3J@8k3!#TZrr4#NTA+F!"-h`3)6Pj1G!!)Mf0MAfCbC@9I6N0ID@jQE`! !+P&19[rX51F!*#4Z!!`J#QB'F!aJ!!$D5'lrm#*Yri3J@8k3!#TZrqJp32rXF'5 `UJ)5Caa)E[r[5'S#&NKZrr!LEIq!)&P1N!!UE[rS28$rl#!Z!""6J'F-8i"R%P1 !CcCJ!!#)F'3P3!)5B!!!JR"NX+S#%QB8F'8P3!)5*@lrm!)@*@lrp!)DB'4`CV# U!K*QA(!)B&T`C,#U!K*Q&("Q*8!#%L9Zrr!#&L9Zrr3#'Q!mF'D`UJ)5CJT+,[r [CJ4`#'!XF'@`UJ)5CL*+,[r[Ca4`CL9!!K)PE[r`!KBPE[rd!KTJ#(!)B!C`$'! #F!!NAdjH6R3!$)pMBepXEf0VAh*PFA9PFh3!!#T46PErq%MR!#3[,J!))QhrL#" C6T!!+Qlrp#4!)!TR%LmZ!!J[#L*Yrh!J@8k3!#TZrr3J#L4I6Pj1G!!%LNjPGe0 KCQ93G()!!!!U88j@rrK)ja!N*'i!##m+)QhrI#"C6T!!+Qlrp#B!)!TQ!!#%)'h rM(!"X*!!CKj`!#m!5(J!*bmYrpJ[,IrF)QhrN!!J@8k3!#TZrr4J@L"Yria`!V# 3!'B5,bhrh#*YrhJJ@8k3!#TZrr4J2L"Yria`!l#3!'B1)QhrC#"C6T!!+Qlrp'! Q)'hrM(!%X*!!CKa`!5m!5(J!*bmYrpJ[,IrF)QhrN!!J@8k3!#TZrr4+Jfi!!)3 JEIq-F!'`N!"Q(R!!,`")H!!S,bhrf#mYrp3LEIq3!#"C6T!!+Qlrp'"D)'hrM(! #X*!!CK)[,Ir8)QhrH#"C6T!!+Qlrp'!q)'hrM(!$X*!!CJiLEIpN)&P1N!!UE[r dB#BJEIq-F!5`N!"Q((!",`")H!!S,bhrf#mYrp3LEIq3!#"C6T!!+Qlrp#m$3UF [#L*Yrj`J@8k3!#TZrr3[!d+R,`SLEIqF)&P1N!!UE[rd,`-[#L*Yrf`J@8k3!#T Zrr3[#L*Yrh3J@8k3!#TZrr4-h`3)6Pj1G!!%MN4TFh"[Ff96B@CP8(4b!!!!+P& 19[ri51F!*#mZ!!JLEIpS)&P1N!!UE[rd*%!J#QF5,bi!##m+)QhrF#"C6T!!+Ql rp#!+*&p1ANjd!!506Q9h8f&QC9"dFP0jF`!!+P&19[ri51F!*#4Z!!JJ#QB!!)3 JEIq-F!'`N!"Q(R!!,`")H!"3,bhrf#mYrp!LEIq3!#"C6T!!+Qlrp'"D)'hrM(! #X*!!CK)[,Ir3)QhrH#"C6T!!+Qlrp'!q)'hrM(!$X*!!CJiLEIpN)&P1N!!UE[r dB#BJEIq-F!5`N!"Q((!",`")H!"3,bhrf#mYrp!LEIq3!#"C6T!!+Qlrp%*U!J3 eI!!+!JC)H!!SBIq3""!P3!)))#S###4I6Pj1G!!%M@jPGd0bC@4#G@CQCA)!!#T 46PErq%MR!#3NEJ!))!TQ!!#%)'hrM(!"X*!!CKj`!#m!5(J!ALmYrpJ[,Ir-)Qh rN!!J@8k3!#TZrr4J@L"Yria`!V#3!'B5,bhrc#*YrhJJ@8k3!#TZrr4J2L"Yria `!l#3!'B1)QhrC#"C6T!!+Qlrp'!Q)'hrM(!%X*!!CKa`!5m!5(J!ALmYrpJ[,Ir -)QhrN!!J@8k3!#TZrr3NVJ!-*@i!%!!%5Ui!&'B)3US!#(!!B$i[,J!3BIrrrri i*8!!#%UU!!KQ"(!'B#BLDJ!))'i!&#!Z!""b),#"C35L,Q!15S"R#L)*%YK6J'E k)N&`!#4I6Pj1G!!3Lf0[F(P%BA4K6f*U!!!U88j@rrK)jaJm+'i!##4Z!!ai!*I ,GJ!J#QB!!)3JEIq-F!'`N!"Q(R!!,`")H!"d,bhrf#mYrmJLEIq3!#"C6T!!+Ql rp'"D)'hrM(!#X*!!CK)[,Ir))QhrH#"C6T!!+Qlrp'!q)'hrM(!$X*!!CJiLEIp N)&P1N!!UE[rdB#BJEIq-F!5`N!"Q((!",`")H!"d,bhrf#mYrmJLEIq3!#"C6T! !+Qlrp#C-)!YQ#%+5B!!#@P+%5TYQqL!%8S$PL#m!BIrrrrdZ*)!Q!%U$CJ!!K#" Yria`!E#3!'BHF!![!%Ki!(`[,IrB,bhra#*Yrj!!)&P1N!!UE[rdB&SJEIq-F!+ `N!"Q%LmYrm3LEIpi)&P1N!!UE[rdB$iJEIq-F!1`N!"Q$L*Yrf3J@8k3!#TZrr4 J*L"Yria`",#3!'BFF!%[!%Ki!(`[,IrB,bhra#*Yrj!!)&P1N!!UE[rd5S0R!!' d*NaJ!!'J5(J!$'(rrrrmM#"5))!J8NU3!'B!!)3JEIq-F!'`N!"Q(R!!,`")H!# $,bhrf#mYrm!LEIq3!#"C6T!!+Qlrp'"D)'hrM(!#X*!!CK)[,Ir!)QhrH#"C6T! !+Qlrp'!q)'hrM(!$X*!!CJiLEIpN)&P1N!!UE[rdB#BJEIq-F!5`N!"Q((!",`" )H!#$,bhrf#mYrm!LEIq3!#"C6T!!+Qlrp#"55T!!C`!"$L*5)P%J9(!-FL#`J@8 %SLjJ$NU!C`SL#4,B8i"QqL*")&)J8#mS!!4KrrrrqmJJ8L"3)8!!##"5)&"+U!! )CJ!!K#"Yria`!E#3!'BHF!![!%Ki!)X[,IrB,bhr[#*Yrj!!)&P1N!!UE[rdB&S JEIq-F!+`N!"Q%LmYrl`LEIpi)&P1N!!UE[rdB$iJEIq-F!1`N!"Q$L*Yrf3J@8k 3!#TZrr4J*L"Yria`",#3!'BFF!%[!%Ki!)X[,IrB,bhr[#*Yrj!!)&P1N!!UE[r d)&)J8%US!!KR2L"8)#J!"#*5)P%LD3!))&3JD!!)FL#`J@8%SLjJ$NU!C`SL#4, B8i"QqL*"@)TBLdU6CJ$qAL"$3V"-!#5$60mF'%jH6R3!#)eMEh"j4'&dB8&bFQ& j!!!U88j@rrK)j`!m+'i!%*A+PmXQEJ!-)!aQ"R!'B!!"%%Ki!!KKrrrrqUBSJ%U 8CJC`"Q!!!2T)H!"-BIrrrrU3!#4!)!TQ"R!'B!!!j%Ki"1*KrrrrqRSNJ%U5CJC `"Q!!!-j)H!6LBIrrrrTN*8!!"%UU!!4Q"R!'B!!!Y%Ki"0m[%bm5)QhrP#"C6T! !+Qlrp%Ki"0m[+`!%,bS!"#*Yrj3J@8k3!#TZrr3[+`!3,bX!$#mV!!K)DJ!)BIr rrrXS*@X!&!!8*@X!'!!B*@X!(!!F*@X!)!!J*@X!*!!N*@X!+!!S5'S!,#mV!#a KrrrrqrJ[+`!i,bX!0#mV!$")DJ!`BIrrrrVJ,bX!4#mV!%![+`!m5'S!2'(rrrr kbN+U!%JJ9(!#))!J9#&+!!4`!%cI(!"1ANjd!!b+Bfp`H9Be3h*PC!!!!#T46PE rq%MR!$!QEJ!3PFSJ#fB%F!CJ@NKi!!KKrrrrq@JQJ%U6CJ4`"Q"')&0`!5#!5(J GIQ(rrrrj6L4!)!TQ"(!'B#`L5L"Z!!`J2!!!(Ajb),#"C35L,Q!15S"R#L)*%YK 6J'Ek)N%J8b&+!!4`!%cI$!"1ANjd!!b+Bfp`H9Bd3h*PC!!!!#T46PErp%MR!$! NEJ!)PmY#V[rd)!TQ"R!+B!!!i(!"X+i!$'F1F!+`VJ!-C`C`%'!!!-T5DJ)%-#S #","U!JCQDM!U!JE33$9!!JB`+J)'5-$PL#m!BIrrrrLN*N!J#fB'F!CJ!!#@-#S #"NM!)J$JLH#*i)RZLG+!iS(PL5!")NXJDJ))FL#`J@8%SLjJ$NU!C`SL#4,B8i" QqL*",bS##'(rrrrfc#9,!JK`!E#Z!!aQ&%KZrr3[,J!3,bi!$'(rrrrqYQ!JF!+ `VJ!-CK4)E[rd,bi!%#mZ!!aKrrrrr94J"(!3B"3`+J)%5-"6J#"U!JJKV[rd$!" `!%cI$!"1ANjd!!b3!'0bC@4#G@CQCA**ER0PFR3!!!!U88j@rrK)jaJ`*'i!#*I ,)!TQ"R!+B!!!L(J!B(B[,J!3,bi!$#"U!JJJF%`!,bJ!"#mS!!"Kr`!!!B4+!'G 5)'S###C`6!![#f(r!!!'0#m,BIrrrrB#*J4J&#!$8S!JDJ)))QS###1`$!!m!&+ $-#S#"%M!8i#fJ'hJ-#S#"%M!8i!JDJ))3V!-!&0U!J4J$&+%-#S#"%M!Z)"YJ(! !60m-'%jH6R3!$*!!Bh*PC%*eCQCPFP*PE@pfC3!!!#T46PErp%MR%$3QEJ!)*'i !$%+Zrr3J#QB!!)3JEIq-F!'`N!"Q(R!!,`")H!&),bhrf#mYrlJLEIq3!#"C6T! !+Qlrm'"D)'hrM(!#X*!!CK)[,Iqi)QhrH#"C6T!!+Qlrm'!q)'hrM(!$X*!!CJi LEIpN)&P1N!!UE[r`B#BJEIq-F!5`N!"Q((!",`")H!&),bhrf#mYrlJLEIq3!#" C6T!!+Qlrm#!+CJ4`$'!iGJ"J(L"U!JJYF$`!rr4)E[rd,`XLEIrJ)&P1N!!UE[r `8S-`+J)%5-#fJ'hB,bS##'(rrrrd`(!!60m-#%jH6R3!#*&NDA0`Eh0P3h*PC%* eCQCPFJ!!+P&19[ri51F!0%UZ!!aR"NUZ!"4Q"R!!B!!!c#!Z!!L`VJ!3C`C`!'! !!,a`!E#Z!!KQBL4Z!!`QEJ!85'X!!8KU!!%LEIqB)&P1N!!UE[rd5S"Q2NKV"10 )DJ6M)QhrQ#"C6T!!+Qlrp%U!CLC)Da1*5'S6L5*YrjJJ@8k3!#TZrr4+J'B1)#S BI,#V'(aQ"(!"B&4`!'"3F!+`VJ!)CNBNEJ!-*Qi!&#m6,a)LEIqB)&P1N!!UE[r d5S"Q*LmV!!3[+J!%)QhrQ#"C6T!!+Qlrp%U!CJiJ+J!BX+X!''B%F!&J"R!!B!* `!%cI$!"1ANjd!"#(Bh*PC'0YF!!!+P&19[ri51F31#CZ!!JSEJ!-PFSJ$'B'F!C J!!'3!%Ki!LCKrrrrmc3SJ%U8CJC`"Q!!!ASN9#"+)NXJ#"$CC[`PD`%!!3""kJ% %3qX""#!)%0PQr$9V!J3#"$9V!JB#"K9m!!%#%$!U!JC)`1@),`"KrrrrmZBP3!) )5US##'B'F!CJ!!%SGJ"J!!%-)'X###"`2!"`!E#3!'B!!**)H!!)BIrrrr+f)'S ###'!2!!JDJ))5V!m!'B'F!CJ!!$`)'S###"`2!"`!5#!5(JGIQ(rrrrbL#"U!JJ JF$`!)8!!"#"U!JJJF$`!5UJ!"'B'F!CJ!!#k)QS###*a2!!LD3!%)'X###"`2!! JD!!%)$`!!"eqFL#`J@8%SLjJ$NU!C`SL#4,B8i"QqL*"B'JJD`)))(!m!(!#X*! !CL!JDJ))5(!m!#"V!JJJF$`!,bJ!"#mS!!"Krrrrq4"J1L"V!JJJF$`!F'1`N!" Q,%Ki!!KKrrrrmHSJDJ)))B!m!#"U!JK+X$`!CJ4`"Q!N)'S###"`2!"`Bb#!8S- `+J)%5-#fJ'd!rZa#UJ)L3US#(R!!60mF#%jH6R3!#)9NGA"13`!!+P&19[ri,`S NEJ!))!TR(Q!1)&)[+!!)BIrrrr(+@)T+NQEZ,bi!#'(rrrraZL4I6Pj1G!!%N!" NDA0`Eh0P4'&dB8&bFQ&j!!!!+P&19[ri51F!*#4Z!!JJ#QB!!*BJEIq-F!'`N!" Q(R!!,`")H!(#,bhrf#mYrl3LEIq3!#"C6T!!+Qlrp'"X)'hrM(!#X*!!CK)[,Iq d)QhrH#"C6T!!+Qlrp'"3)'hrM(!$X*!!CJiLEIpN)&P1N!!UE[rdB$JJEIq-F!5 `N!"Q,R!",`")H!(#,bhrf#mYrl3LEIq3!#"C6T!!+Qlrp'!3,`S[#L*YrqJJ@8k 3!#TZrr4+NQEXF!!NAdjH6R3!")TQFQ9P6N0-DA0d!!!!+P&19[rX51F3*#4Z!!J J#QB!!)3JEIq-F!'`N!"Q(R!!,`")H!(5,bhrf#mYrp!LEIq3!#"C6T!!+Qlrk'" D)'hrM(!#X*!!CK)[,Ir3)QhrH#"C6T!!+Qlrk'!q)'hrM(!$X*!!CJiLEIpN)&P 1N!!UE[rSB#BJEIq-F!5`N!"Q((!",`")H!(5,bhrf#mYrp!LEIq3!#"C6T!!+Ql rk%KZrqiLEIq%)&P1N!!UE[rS0J!`!dM!C`4`!'!dF'5`UJ)5Cb4)E[rh5'S#&NK ZrqiLEIq!)&P1N!!UE[rS0J!`!dM!C`K`!'!)3Llrpa!ZrrG-h`3)6Pj1G!!%LQP c6'pMDdpeFR-!!!!U88j@rrK)j`!d*Qi!##!,CJ!!K#"Yria`!E#3!'BHF!![!%K i!HF[,IrB,bhrX#*Yrj!!)&P1N!!UE[rdB&SJEIq-F!+`N!"Q%LmYrl!LEIpi)&P 1N!!UE[rdB$iJEIq-F!1`N!"Q$L*Yrf3J@8k3!#TZrr4J*L"Yria`",#3!'BFF!% [!%Ki!HF[,IrB,bhrX#*Yrj!!)&P1N!!UE[rdF!+`NfCQ*'X!"#m5BIrrrqmd,bS !"'(rrrr[+NUU!""R#LmU!""KrrrrlaT+UJ!iC`S[+J!iBIrrrqm+5US!4'F+,bS !4'(rrrrZqNUU!%KR#LmU!%KKrrrrr3K+UJ!XC`S[+J!XBIrrrrci,bX!"'(rrrr Zd(!!60m-!%jH6R3!"*CMBepQFQ9PAf0bC@4ID@jdCA*ZB@ac!!!!+P&19[ri,`0 f!#mZ!!KKr`!!!&if!$!$5-"R"$!$B!JJEIpJ3T!!-!-Q(djH6R3!"***EQPdD@& XDATP3f&MD'9-D@)!!!!U88j@rrKKr`!!!%j1ANjeN94PFQeTEQ&dC80KBfKP6'P L!!"1G5T46PErq#m0)!d[!#mYrk`LEIqN)&P1N!!UE[rd+d$rA'(rN!6FF!"1ANj d!!3U88j@rrJ[$5mYre`LEIqJ)&P1N!!UE[rd6Pj1G3JZ68P8)%N[8b"0B@0%CAB &,JJ-)5KZB@eP)#%p)$!T!5N)3d0KBfKP,Q-")$d2)5JUD'&ZC'aP)#%p)$!T%5% SF(*TEQ0TF'&X)#%p)$!T$5%SFf&QC9!J)6dJ-#N-3d0KBfKP9A4TE#jM!5d-)5K cDATP)$iJ-%`T!5X+)5KZBb!K25!`+3%j#b%SEf*U)#%p)$!T$#%SC'9cG#!K25! `+3%r$h*PG'4PFh3J26dJ6P9-6!iU+Q4PFh3J26dJ6P9-6!%h&LJU+Q4PFh3T,6j NBA4K)$dp)%j96%`"+`TZBb!p25"198a-!6-5)5KMER4bE%*XEf0V)#%p)$!T!5i 0)5KMFQ9NFb!K25!`+3"1)J(SJJ)9!UJ!rJ$U!0i!aJ#f!+B!Q!#-!)!!FJ"N!&B #%!"%!RJ#J!!d!#S!(!!B!#!L2c`")`DTm!)Lrrd5)J'`JJ)X(kJ"X"pL!E!-XJ' `$%`"X!`-!E!,fJ'`#k3"X!VB!E!*3!'`#,)"X!K-!E!(lJ'`"hJ"X!CN!E!&m!' `"AB"X!8b!E!$i!'`![3"X!(S!E!!e!'`!*!!!E!%)J'`JJ)%!9JJ'!%B!#!B)ar 1!3%K#!-M(r`"!5%)!b)J'!`!!!$rN!3!N!F"!!!"q!!!!!%!!!(`!!!!"3!!!") !!!!"!!!""!!!!43!!!1!!!!!"!!!!"8!N!m"!*!,)J#3#`S!!!!"!*!(RJ!!!!% !!!!"!!!!!J!!!!X!N!I4!*!,!`!!!!d!N!Ik!*!,!J!!!"!!N!3"!!!@!J!!,`) !!$J#!!"#!J!!6`)!!&S#!!"P!J!!EJ)!!(N#!!#&!J!!P`%!!,B#!!$$!J!!j!) !!1`#!!$c!J!"%`)!!5N!!3#3"3F!N!3"JB$c5K&#&B!h4KG#!!!!68P8Ak9$3f& MD'9(E'pLB@ac6'PL!'G$ER4bE%*XEf0V!%PZG'9bCQ&MC8aTBJ"6HA0#FQ9KD`" 1CAG3G(*6HA-!9@jSEfaN6@9YEh*j!%K[E'40C@e[FRN!4'PcF'pcC9"dFJ"%C@* eCe0dFJ"(CA43G(*6DATP!&0KE@93FQpMCA0c!%GPG%0eFR*PER43FQpMCA0c!%j PGe"dFJ"0594IT84PBR9RCfPZCdaTBLjNC@*eC`"R4'9LG@G6D@GZB@`!3@aPFR4 6D@GZB@a"G!"0594IT8e*9%0-D@)ZC'9LG@F!Fh4bEQ0`H3"cG(*MEA!!E@9YFf9 d!%e*9&qP68P88R9ZG'PYC8aTBLjNC@*eC`"IAh9ZFQ9RDA0dCA*ICR*KCfePER3 !AepbC@GTFh4PFPpQFQ&RE@9ZG!"MBepRCA4IBh*PC&pfCA*cD@pZ!'0MAfCbC@9 I6N0ID@jQE`"MBepRCA4IBfKKEQGPAh4TE@8!Bf0IC'9cG(*[H3"MBepME'pcC3" MBepMFQ9KG'8!Bf0ICR*PC9pMFQ9NF`"MBepRCA4IEQ&YC3"MBepQFQ9PAh"bD@j MDA"KE!"MBepbC@e[GQ9IBh*PC!"MBep[F'9Z!'0MAfGPG&p13epTEQC[!'0MAh0 PF9pQCA4MD&p13h-!Bf0IFf9dAh"bD@jMDA"KE!"MBepcD(9dC'phEJ"MBepcCA& ICQ9dBfKIBh*PC(-!Bf0ICf9dAh"bD@jMDA"KE!"MBepTEQPdD@&XDATP!'0MAh0 dEh*P!'0MAfa[BfYIFQ9aG@9cG!"MBepQFQ9PAfjKE@8!N!J%!!!!$!!"!!J!"!! !!!B!#!!'!!J!#!!!!!S!"!!+!!!!#`!3!!X!$!!2!!!!%J!%!")!!!!6!!J!%`! 6liN!$c0A!"*09`!+QYm!##E2!!P-)3!0cUm!#cEk!"(i"J!1jP-!"a0-!!kjaJ! 3JV%!%)`+!!XpI3!5#&i!%-`,!!h)j3!)*`d!$aJH!!aR@J)!!6d!!!*)!!%#!!& 4!!!##!!"!J!"B3!!!R!!!3)!!A3!!!*i!!%#!!&r!!!#J!!"!J!"L!!!!T!!!!% #!!'5!!!#%!!"!J!"S!!!!N!!!3)!!D`!!!)J!!%#!!'q!!!#B!!"!J!"c3!!!SJ !!3)!!G8!!!)S!!%#!!(N!!!#1!!"!J!"p3!!!PJ!!3)!!JB!!!+B!!%#!!)5!!! #-!!"!J!#*3!!!P!!!3)!!MB!!!+J!!%#!!*%!!!#D!!"!J!#63!!!J!!!3)!!Pd !!!)B!!%Bd`!!!3!!!!&N!!!!C!!!!$)!N20J!*!,!3#3%`&Y0MKV!*!6!3#3%8! 868P8Ak9$3f&MD'9-D@)ZC'9LG@F!!!!"!!!!!@3!!!"N!!!!-J9@1G!cb!!!!"` !-J!!BfCbC`!!!!S!!2rr!*!)5'8: \ 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
index 98e665770c..0000000000
--- a/src/mac/libraries/CCache API/bin/CCacheLib.PPC
+++ /dev/null
@@ -1 +0,0 @@
-(This file must be converted with BinHex 4.0) :$80$B@0SC8aTBLj38%-!FfKXBN0"*%J"!!!!-#J!!!'5'R*+EhNKF'9QCR"hF'- !!!!"XP21U`#3$3-!!J#3"2q3"!#3"LPX!!!TE!!!+@`!!!93!!3%!2q3"!#3"J* K!!!#A3!!!@J!!#l!!J%%!2q3"!#3$J6'!!!!J!3%"!#3"Iq3"!#3"`%!!!&J!!! !!3!!!9J!!!!&!!!!%`!!!!%!!!%)!!!"'!!!!f!!!!!%!!!!&3#3$`J!N!X0!*! ,!3!!!!J!N!FM!*!,"J!!!!N!N!F`!*!,!J!!!!m!N!G$!!!!!3!!!!%!!!!#!!! !%3#3"!)!!&8#!!"I!J!!E!)!!(F#!!##!J!!M3)!!*N#!!#V!3!!XJ)!!,i#!!$ &!J!!c!)!!03#!!$E!J!!iJ)!!1N#!!$r!3!"%`)!!5!!!3#3"3J!N!4+%N!"3J& !!8)33J#!!dB@5@jdCA*QB@0P6'PL!%e*9&qP3d0KBfKP4fa[BQ&XFdaTBJ"0594 IT8e*9%0-D@)!68P8Ak905945G@jdD@eP6'PL!%e*9&qP4'9LG@GRD@jR6'PL!%j PGe"dFP0jF`"9EQK[E'40C@e[FRN!5'pXC%ePE@pbH3"%DA0`Eh0P8(4b!%GPG&" dFP0THQ8!8f&YC9"bEf0PFh-!4f9d3h9bFQ9ZG&"bEf0PFh-!6Q9h8(4b!'G$ER4 bE%*XEf0V!(0dFQ0YF!"YC@eMF(N!Fh4bEQ0`H3"cG(*MF(N!Fh4bE'9Z!'ePEA0 PG!"IAh9ZFQ9RDA0dCA*ICR*KCfePER3!AepbC@GTFh4PFPpQFQ&RE@9ZG!"R4'9 LG@G6D@GZB@`!3@aPFR46D@GZB@a"G!"MBepRCA4IBh*PC&pfCA*cD@pZBf0IC'9 cG(*[H@0MAfGPG&pMD'&ZCf9IG'PYC@0MAfCbC@9I6N0ID@jQEf0MAf0bC@&dC@0 MAf0XEh0PBf0ICf9dAfjKE@9MBepQFQ9PAf0bC@4cBf0IFQ9YEhCPAf0bC@4MBep QFQ9PAh"bD@jMDA"KE'0MAfp`C@jMBepcD(9dC'phEQ0MAh0PG&p`FQPZBfP`B@a MBepcCA&ICQ9dBfKI6N0cBf0ICf9dAdj$AfPZCQpMBepTEQPdD@&XDATPBf0ICf9 dAh"bD@jMDA"KE'0MAh0PF9pQCA4MD&pMFQ9NFf0MAh0dEh*PBf0ICR*PC9pZB@e PBf0IE'pMDepbCA&eCA0d!*!("!!!!!`!!3!)!!3!!!!'!!J!"J!)!!J!!!!+!!3 !#J!!!!X!%!!,!!`!$`!!!")!"!!5!!!!%`!)!"-!%qq*!!UDh`!569F!$c0A!!P -)3!)*Xm!#cEk!!h1V`!1jP-!%IJ'!!F66!!,2Ad!%)`+!"##X3!1ZFB!$FMP!"$ -#`!5#&i!##F0!!aR@J!2'"i#!!%Z!!!!q!!"!J!"33!!!5J!!3)!!8X!!!%J!!% #!!&G!!!!Z!!"!J!"E!!!!8!!!3)!!A8!!!%`!!%#!!&p!!!!m!!"!J!"L!!!!-! !!3)!!C8!!!%3!!%#!!'M!!!!d!!"!J!"Y!!!!6J!!3)!!EX!!!&)!!%#!!('!!! "#!!"!J!"eJ!!!1J!!3)!!HB!!!$B!!%#!!(d!!!"8!!"!J!#!3!!!3!!!3)!!K% !!!$J!!%#!!)M!!!"'!!"!J!#+`!!!-J!!3)!!MF!!!#`!!%!N!Tm#!+QN!!"!!L 8)Ir!1#%!3)!"!!Km#!1Q6S!!)(`)!UDrBIrXN!!"!!L8)Iq`I(XEH(bF)hKm[5Y iI0icH)2L!##!(`!!+!!!!%##!&3iB!!35!!9*@!!!!#3!(X!!)"l!!!S!`!!3)) !$$KJ!!C)!!"S1!!!!*!!!`!%J(X!!*!!!`!!J(X!!*!!!`!)J(X!!*!!!`!-J"X !!*!!(`!!5!!!#*!!'`!!,"`!!8#"!!`iB!!*5!!!+#JG!!""JJ!-1!!!!C!!(3! !+"i!!%'#!!b!!J#SN!!H!!!iB!!!J!%!@$JK!&"m#!1QZf(rl%k!!#!!N!BJ3B! &!*!&c!!1,Q0MAfPZDA4TB@aTHQ9m#!+QNq(rr*!!!3!)P#(r`(ar'hJS(`!!3B) !+)"r!!!S!`!!3B)!(%J!)T9J!!!!J(m!!%J!%ZeJ!!!!5!!!$$KJ!!T)!!!-1'! !!*!!I`!!J!%!5$JK!%"m#!1QJq(rr%k!!#!!N!BJ3B!"!*!&C!!-,Q0MAh0SGA4 NEhGZ!!"m#!+Q[b(rj*!!!3!)P#(rS(aj'hKmQL0iI,XVH(cF-hKmrcYiI4e$H#J C!!"!JJ!-1'!!#NJ!!6JS(3!!3))!$$KJ!!a)!!%S1'!#+%J!%jeJ!!!!I(iEH#J H!!"!JJ!-1'!!"NJ!!3JS'J!!3B)!'(p$dhK)!#FpJ%%!&#J$!2p"J!!-1'!!!8J !!14r`r0iId66H%J!*Sf!33!8+"`!!%'#!"KrJq0i5!!R#B""!"3S!`$r3B!!$$K J!!a)!!#`1(i""(q%ihK)!#CCJ%%!&*2q!J`li!!!Xri#"*0q!3!i!!!#Q"i#%$J !!'53!"i#&(r$mhK)!"0PB!!!!*!!IJ))J"i###J!!!"!JJ!-1'!!"NJ!!&b!'3! ),!!!!%##!"L6rJ)NNri#)*2C!!#6f3!%5!!!()"j!!56``)JJ"N!"*!!(J)NNri #)*2C!!5!H3!)1!-!!C!!'3!)J(N!$$J$!!'3!"N!$*2G!!!iB!!!J!%!D$JK!'" m#!1QZb(rj%k!!#!!N!BJ3B!(!*!%!B!!#LjMBepMFQ9KG'9m#!+Q[d(rk*!!!3! )P#(rX(ak'hKmQb0iI,`VH(cp1hJiJJ'%1')"Gi#L!%3li!!!IrllH#JD!!"!JJ! -1'!!#NJ!!,`S(3!!3))!$$KJ!!a)!!#X+"X!!%##!$b!"3!!,!!!!8##!"JiS!# V1-!!!8J!**f!33!85!!!(#`!!!4!JJ!81+!!UcM!!!&)!#5"J%%!&)2k!!")!!! dIf2EH(rNqhK)!#9CJ%%!&#`$!!"!JJ!BJ"m"!(`F!!"!JJ!-1m!!!8J!!!L$r`) J+"m!!%'#!!ar`!Ge3B,ra(r!"h9"JJ!3Nrd!!$KJ!!")!!!31!!!!*!!(3!!1'! !#S!"!&Ji)3"3I!J$TVY"rqK1J!!J!*!')%'!"J#3"!%3!!JZBf0IEh"PEJ!!I!J #TVqKrr53!!%!#*3Krl"mI4YiI*iMH$KL!BdiJJ'%J+)!4#JG!!"!JJ!-1'!!#NJ !!*JS(J!!3))!$$KJ!!a)!!#)J"i!!#J!!!"!JJ!mJ!8!!#`!!!&!JJ!B1+!!c6M !!!&)!#0pJ%%!&%J!!"`X!!!%3))!&$LJ!-di`!!"5!!MBB""!"5!IJ!!L!-#%#` !!!&"JJ!-1'!!$NJ!!#amIaYiIk2VH(rNqhK)!"S*B!!!!(rMqhK)!!mGB!!!!$K J!!#3!(i!!)!"!&Ji)3"3I!J$TVZKrr41J!!J!*!')%'!!`#3"G`!#5jMBepME'p cC3"m#!+Q[k(rp*!!!3!)P#(rX(aq'hKmRb0i1')"M6L#!B5!SJ"%+"i!!%##!!` iB!!+5!!"(#JI!!"!JJ!-1'!!$%J!!3b!(`!!+!!!!%##!$b!"3!!,!!!!8##!"J iS!$V1-!!!8J!)S@!33!85!!!(#`!!!4!JJ!81+!!kcM!!!&)!#*TJ%%!&)1r!!# !(3)8,!!!C%'#!#"rSqYi5!!HP@!!!!"mB!Ge3))!$$KJ!!K)!!#FJ"d#*#J!!!" !JJ!JJ"d#)*!!(J!!J(d#)#J$!!""JJ!-1!!!!*!!!`)NJ"d#)#J!!!"!JJ!JJ"d #**!!(J!%J(d#*#J$!!""JJ!-1!!!!*!!!`)JJ"d#*#J!!!""JJ!JJ(d#)#J$!!" "JJ!8N!!$!L5!(3)JJ(d#**!!!`)J1!!!!CJG!K"r`r0iIq6lH%[rrFf!RJ!-1!3 !!C!!(J!-J!%!@$JK!&"m#!1QZk(rp%k!!#!!N!BJ3B!$!*!%!@!!#bjMBepNCA0 dFQpj!!!!+!-!!%##!!`iB!!+6S!!)#J%!!""JJ!8J!-!$*!!"!!!1'!!!%k!!#! iB!!-6S!!)!#3"L"!!*!(-!!6,Q0MAfGPG&pMD'&ZCf9IG'PYC3!!!(`)!UDr`Ir iN!!"!!L8)Ir!I(iEH(bI)hL3!+%!B*!!`3"N+"i!!%##!!`iB!!+5!!!H#JI!!" !JJ!-1'!!#NJ!!'L!(`)8,!!!C%'#!#JX!!"Q3))!'(rMqhK)!"d"B!!!!(aJ"h9 !JJ!-1'!!#%J!!$KrirYiJ)%!B)#K!'4)!"6eB!!!!#`$!!"!JJ!3J*i!#$J%!!' 3!"i!#)#H!!`i"!!"N!!H!!b!!3")1#%!3(`)!kDl`Iri6S!!)!#3"L""J!)!N!@ i!!NZBf0IFh4[FQ8!I!J#TVr"rrL3!!%!#*3Krm"mIKYiI*mMH*!!S3"JN!$"!'3 S(J!!3B)!$#JI!!"!JJ!-1'!!#NJ!!&L!(`)8,!!!C%'#!#JX!!"Q3))!'(rMqhK )!"`eB!!!!(aJ"h9!JJ!-1'!!#%J!!#KrirYiJ)%!B)#K!'4)!"9jB!!!!)"q!!` i!`!"N!!H!!`iB!!!J!%!5$JK!%"m#!1QZm(rq%k!!#!!N!BJ3B!#!*!&S!!2,Q0 MAh*PE@pfC9pMFQ9N!!!!I!J#TVq"rr#3!!%!#*3Krl"mI"YiI*dMH(bq+hKmhc0 i1')"R6L#!B5!SJ"%+"`!!%'#!!`S(3!!3))!$$KJ!!T)!!#X+"m!!%##!$b!"3! !,!!!!8##!"JiS!&V1-!!!8J!(aQ!33!85!!!(#`!!!4!JJ!81+!"DcM!!!&)!"l pJ%%!&)!G!K3X!!"N3B)!+#`!!'C!JJ!BIk2VH%J!'b9J!!!!I'!(G8##!!`iB!! )5!!!2)!G!3"m!2!!3B)!$$KJ!!T)!!!S1(d""(rNqhJiS!$r5!!IIB""!"5!I!! -1!-!!C!!(!!-1'!!!)!"!&Ji)3"3I!J$TVZ"rr"1J!!J!*!')%'!"!#3"!%!!"% ZBf0IFf9dAh"bD@jMDA"KE!"m#!+Q[m(rq*!!!3!)P#(r`(bH)hKm[bYi+"i!!%# #!!`iB!!+5!!!D)!H!K3X!!"Q3))!)(r$mhK)!"TPB!!!!(aJ"h9!JJ!-1'!!#%J !!%!S(`!!3B)!0$KJ!2p)!!PpB!!!!*!!I`!!J(m!!#J$!!"!JJ!-1'!!"NJ!!"3 iRJ%%5!!H6B""!"3iB!!!J!%!5$JK!%"m#!1QZm(rq%k!!#!!N!BJ3B!#!*!&S!! 4,Q0MAfGPG&p`FQPZBfP`B@`!I!J#TVr"rrL3!!%!#*3Krm"mRL0iI,mVH#JH!!" !JJ!-1'!!#NJ!!%L!(J)8,!!!CN##!#"r`r0i5!!CS@!!!!"mB!Ge3))!$$KJ!!K )!!!J+"m!!%##!!`iB!!'5!!!%)!H!3#3!"m!!$KJ!!#!!3")1#%!3(`)!kDl`Ir i6S!!)!#3"L""J!)!N!@!!"3ZBf0ICf9dAf0bC@4IGQ9bFfP[EJ!!I!J#TVr"rrL 3!!%!#*3Krm"mRL0iI,mVH#JH!!"!JJ!-1'!!#NJ!!&L!(J)8,!!!CN##!#"r`r0 i5!!Bq@!!!!"mB!Ge3))!$$KJ!!K)!!!`+"m!!%'#!#3iB!$r5!!)%@!!!!#3!(m !!)"r!!"ra20i5!!FmB""!"3iB!!!J!%!5$JK!%"m#!1QZm(rq%k!!#!!N!BJ3B! #!*!&N!!!$#jMBepRCA4IEQ&YC3!!I!J#TVqKrr53!!%!#*3Krl"mI4YiI*iMH(b r+hJS(J!!3B)!&#JI!!""JJ!-+"d!!%##!!`iB!!+5!!!M)!I!!!S!!!!3))!-$K J!!K)!!GaB!!!!*!!I`!!J(m!!#J$!!"!JJ!-1'!!"NJ!!&b!(3!!N!!$!!#!I`! !J!-!!#J!!!"!JJ!J5!!(U@!!!!!i!!!!N!!I!!#3!"i!!$KJ!!0)!!!SI!-$H(r %mhK)!"5eB!!!!)#I!!#!C!!!J!-#)*!!"!!!1'!!!)!"!&Ji)3"3I!J$TVZKrr4 1J!!J!*!')%'!!`#3"GJ!%5jMBepcCA&ICQ9dBfKI6N0c!(`)!UDrSIrdN!!"!!L 8)Iq`I*dMH(bq+hKmhc0i+"d!!%'#!"3S(`!!3B)!$#J$!!"!JJ!-1'!!#NJ!!FJ S(J!!3))!$$KJ!!C)!!'iJ"d#&#`!!'C!JJ!JIk2VH%J!&bPJ!!!!I'!(G8##!!` iB!!)5!!"N!#!(`!!+!!!!%##!%3iB!!)5!!'2@!!!!#3!(m!!)"r!!!S!`!!3)) !$$KJ!!C)!!&J1!!!!*!!!`!%5!!!&)#I!!#!C!!%1!-!!C!!"!!%J(m!!)#$!!5 S(3)%I!3!!%#!!"b!I3))9)!31RaM!#k!!`!!,!!!Bd'#rmL!I`!!J)-!"+JG!J4 m"!!!3B!!)%J!"M&J!!!!1!!!!*!!(J!!N!!I!!!iB!!$5!!!k)"p!JK8J"!kI'- !,S!$!!!X!!!"3))!I$KJ!!K)!!@*B!!!!*!!IJ!!J"i!!#J!!!"!JJ!-1'!!"NJ !!+`iB"f!5!!&C@!!!!#!RJ!!N!"N!!5!IJ!!J'-!"#J$!!"!JJ!-1'!!"NJ!!)# ![3))J*m!!)!%!!48!"!kI)8!,S#%!!3iS"f!5!!D4B""!"4)!!"%,!!!!N##!#b !!`!%N!!"!$`i!!!#N!!"!$L!B3!iJ)%!2(r&mhK)!!YYB!!!!%J!!"3i!!!!N!! H!!!iB!!35!!!')#I!!#!C!!%1!-!!C!!"!!%1'!!!)!"!&Ji)3"3I!J$TVZKrr4 1J!!J!*!')%'!!`#3"!)8!"-ZBf0IFf9aAfCPG'0SAf0bC@4c!!!!I!J#TVpKrqb 3!!%!#*3Krl"mI"YiI*XMH$ZJ!!"r[qYi+"`!!%##!!`iB!!+5!!!d#JE!!"!JJ! -1'!!"NJ!!-#!I!!)1!-!!93$%$T)!"N9J%%!&*!!H`!!J"X!!#J!!!"!JJ!-1'! !"NJ!!*5$R!!!5!!!G$KJ!J4)!"MTJ%%!&)#E!!"rr[YiI'6a,S"l!!"mBr!Z+!- !!%##!!`iB!!'5!!!A(q%ihK)!"M4J%%!&)"l!!"mBr!Z1'-!rcLF!34)!"LjJ%% !&)!F!3#!H`!!I'2`,T!!!`)!Jj`#)$Zp!!%lr`!%+"`!!%##ri`iB!!!J*X!!&H J%$TmC!%ZJ!%!@$JK!&"m#!1QZf(rl%k!!#!!N!BJ3B!&!*!%!4!!$bjMBepRCA4 I6N0ID@jQE`!!!(`)!UD3!!%!#*3Krm!S"!!!3))!$$KJ!!C)!!!8I)-MH%J!!k& J!!!!1'!!!)!"!%Ji)3"!I!J$TNk!!#!!N!BJ3B!!N!Bm!")ZBf0ICR*PC9p`FQP ZBfP`B@am#!+QN!!"!!L8)Ir!+!3!!%##!!`iB!!'5!!!&(b$)hK)!!0"B!!!!$K J!!#!!3")1#%!3(`)!kC1J!!J!*!')%'!!*!'2!!0,Q0MAfCbC@9IEQ&YC3"m#!+ QNq(rr*!!!3!)P#(r`(bI)hJS(`!!3))!$$KJ!!T)!!!NJ(m!!%J!&"eJ!!!!J(m !!%J!!Y&J!!!!1'!!!*!!I`!!J!%!5$JK!%"m#!1QJq(rr%k!!#!!N!BJ3B!"!*! &@!!1,Q0MAfCbC@9IBh*PC(0m#!+Q[m(rq*!!!3!)P#(r`(bH)hJS(J!!3))!$$K J!!T)!!"%1!!!!(`I!hK)!!!BJ(i!!(aMq#j)!"C*J%%!&$[r!!5!IJ!!I!2i,LJ !!!"!J[rJ5!!@,B""!"3iB!!!N!"q!!#!!3")1#%!3(`)!kDl`Iri6S!!)!#3"L" "J!)!N!9i!"!ZBf0ICR*PC9p13epTEQC[!!"m#!+Q[m(rq*!!!3!)P#(rX(bI)hK m[LYi+"m!!%##!!`iB!!-5!!"*$KK!$K)!"@*J%%!&)!I!K3X!!"N3B)!'$KK!$J iR`)B1+%!3%J!&B'!33!8,"i!!N'#!#a!J!!3,"i!!8#!!"4)!!$8,"i!"%#!!-a )!!")1!!!C*!!(`)85!!!a)!I!K3X!!"N3))!)$J!!'@3!"m#&)"K!$L!!3!mN!" r!KL3!"m#(%J!!*`X!!"Q3))!P$KJ!!K)!!#3!)!I!K3X!!"N3))!)$J!!'D3!"m #&)"K!$L!!3!mN!"r!KL3!"m#(%J!!'3X!!"Q3))!')J"!%!S!!!!3))!$$KJ!!K )!!"-J"m#&#`!!'9!JJ!mL!%!3#J!!!""JJ!J1!!!CT!!(`)8J'%!1)!"!$b3!(m #'*!!(`)F5!!!&$KJ!!K)!!!31'!!$%J!!!JiB!!!J!%!@$JK!&"m#!1QZm(rq%k !!#!!N!BJ3B!#!*!%!9`!%#jMBepXEf0VAh*PFA9PFh3!!(`)!UDr`IriN!!"!!L 8)Ir!I(iEH%J!&-Q!33!8I(mEH#JI!!""JJ!8Iq2lH(r%mhK)!"6GJ%%!&(rMqhL !!3")1#%!3(`)!kDl`Iri6S!!)!#3"L""J!)!N!93!!XZ6Q9h8f&QC9"dFJ!!!(` )!UDr3IrSN!!"!!L8)Iq`I(SEH$Z#!FSlSJ'p1m)"Vi2L!%4)!"3"J%%!&(al'hJ S'J!!3))!6)!I!!!X!!!"3))!)(r$mhKrT1Yi1+!!*cM!!!&)!"1jJ%%!&%J!!#3 X!!!%3))!((r$mhKrT1Yi1+!!*cM!!!&)!"19J%%!&#`E!!""J3"-J"m!!#`!!!& !JJ!JIi2MH(qNkhJiS!!S1-!!!8J!%fQ!33!85!!!*#`!!!4!JJ!FIi2MH(qNkhJ iS!!S1-!!!8J!%d@!33!8Id26H$L!!!"rCGYi5!!6BB""!"4r3p0i1)!!!(pPfhK )!"00J%%!&(p$dhKrC0Yi5!!69B""!"4r3p0i5!!5kB""!"5!!3"B1#%!8(`)!kD l3IrS6S!!)!#3"L""J!B!N!3"+!!2,N4TFh"[Ff96B@CP8(4b!!!!I!J#TVr"rrL 3!!%!#*3Krm"mIKYi5!!6EB""!"4mIaYi+"m!!%'#!"4rirYiIm6cH%J!%b'!33! 8Iq2lH)!"!%Ji)3"!I!J$TV["rrK1J!!J!*!')%'!!J#3"9!!$Lj1CAG6B@CP8(4 b8hPcI!J#TT2Krrb3!!%!#*3Krm"mIaYi1')"ecL#!Ef!SJ"%+"m!!%##!$b!"3! !,!!!!8##!"JiS!"31-!!!8J!%K@!33!85!!!(#`!!!4!JJ!81+!!8$M!!!&)!"( jJ%%!&$J!!!#`(`)%1!!!#V!I!JBiB!!S5rrr(C!!I`))J(m##)!"!%Ji)3"!I!J $TS2Krra1J!!J!*!')%'!!3#3"C3!$LjZCAG$FQ9N3R9QCQ9bI!J#TT2Krrb3!!% !#*3Krm"mIaYiN!#"!&b3!+%!B*!!`3"N1')"iML#!Ef!SJ"%+"m!!%##!$b!"3! !,!!!!8##!"JiS!"H1-!!!8J!%9@!33!85!!!(#`!!!4!JJ!81+!!AMM!!!&)!"% jJ%%!&)!"!&b3!"m!!)!"!'#3!"m!")!"!'3S!!!!3))!%$KJ!!#3!(m!#%J!!$L !B3"J5rrq4C!!I`!)J(m!##J$!!"!JJ!-1'!!"NJ!!"L!J3"NJ+%!B%J!%BQ!33! 81'!!!)!"!%Ji)3"!I!J$TS2Krra1J!!J!*!')%'!!3#3"G`!$#jMEh"j4'&dB8p LDJ!!I!J#TVl"rpL3!!%!#*3Krk"mGaYiI*JMH$Z#!KSlSJ),1X)"qcKL!Hil`J' pJq)!4$YJ!!!S'!!!3))!4)!I!!!X!!!"3))!((r%mhJiS!"d1-!!!8J!%%f!33! 85!!!)#`!!!4!JJ!BIm6cH$LJ!(3i`!!"5!!3,B""!"4qqVYi+"S!!%##!"Ji!!! !N!!B!!")!!(F5!!!#$Yl!!'!'J!!1eS!"#J!!!"!J[r`1"X!!93$%$T,rrdYN!" i!!"mH4Yi+"N!!%##!%b!(`!!,!!!!8##!#"q`l0iIm6cH$LJ!(`i`!!"5!!2[B" "!"4)!!!N,!!!"%##!"aq`l0iIm6cH$LJ!(`i`!!"5!!2QB""!"3S'3!!3B)"@(l kZhK)!!%d1'!!$%[rr,f!Q!!!N!"N!!#!H!!!J!-!!#J!!!"!JJ"-J"m!!#`!!!& !JJ!JIk2VH(r%mhJiS!#$1-!!!8J!$d@!33!85!!!*#`!!!4!JJ!FIk2VH(r%mhJ iS!#$1-!!!8J!$b'!33!8J(J!!)"M!!!S!`!!3B)!f)#A!!!iS!!-5!!2UB""!"5 !H!!!J'-!!)"M!!4,rr`YJ*J!!)#%!!#3!'3!#)"i!!#!B`!!J!-!##J!!!"!JJ" -J"m!!#`!!!&!JJ!JIi2MH(r%mhJiS!#,1-!!!8J!$Uf!33!85!!!*#`!!!4!JJ! FIi2MH(r%mhJiS!#,1-!!!8J!$SQ!33!8J(J!!)"M!!#!B`!)+!-!!%'#!$b!Y`! !J)8!#)#P!!4)!!m*J%%!&$XB!!3l@J!%J"S!!#J!!!"!J[l)1'!!!&GJ%$TmH3% ZNcJ!!)!"!'Ji)3"JI!J$TVV"rpK1J!!J!*!')%'!#J#3"!+!!!iZBfp`H84KG'& "FR*KHA`)!UDrSIrdN!!"!!L8)Iq`N!"K!'L3!)%!E(bp+hL$`3"X+"d!!%##!!` iB!!'5!!"2$KJ!!K,rrX0N!"p!!#!(3!!+!!!!%##!!`iB!!'5!!"($KJ!%a,rrV YI(mEH#JI!!"!JJ!-1'!!"NJ!!3!iB!6L5rrkdC!!I`!!J"m!!#J!!!"!JJ!-1'! !"NJ!!1!iB!6L5rrkXC!!I`!%J"m!"#J!!!"!JJ!-1'!!"NJ!!-#!I`!!J*i!!$L J"0p)!!iKJ%%!&)"r!!5!RJ!%1+!%hdJ!$Jf!33!81(m!#)#H!!L![J!-J0i!%%[ rqi'!(J!8N!!I!"5!(J!BN!!I!"L!(J!FN!!I!"b!(J!JN!!I!##!(J!NN!!I!#5 !(J!SN!!I!#L!IJ!X1*m!,%[rr%%iI`!`J*i!-)#q!$5!hJ!i5rrl-6Kr!$b!RJ! mJ,i!3)$H!%4,rrXG1'!!!*!!I`")1!!!!S#G!!#3!!3!!)#G!!#6j!!%J!%!@$J K!&"m#!1QZk(rp%k!!#!!N!BJ3B!$!*!%!A`!#bjMEh"j9M9$FQ9N!!!!I!J#TVr "rrL3!!%!#*3Krm#3!'%!@*!!J3"FI,iVH#JH!!"!JJ!-1'!!"NJ!!'JiB!!)5rr jGC!!IJ!!J(i!!#J$!!"!JJ!-1'!!"NJ!!%Ji!!!"N!!$!!!iB"f!5rrj6Aar'hJ S(`!!3))!$$KJ!!C)!!!NIq2lH)#"!&`iS"f!5!!-NB""!"5!IJ!!Nq-!"$KJ!!# !!3")1#%!3(`)!kDl`Iri6S!!)!#3"L""J!)!N!@N!!XZBfp`H9Bd3h*PC!!!!(` )!UDr`IriN!!"!!L8)Iq`I(iEH*!!J3"XN!#K!(!li!!!Nq%!1#JH!!"!JJ!-1'! !#NJ!!1L!!3"X,!!!!8'#!"3X!!!#3B)!$$KJ!"")!!$-U(i#"$J$!!'`(J)%U(i #"+JH!JCm!`!!3))!@&3!#$b`(J)'U"i#"P3$%$T,rrKPI(mEH#JI!!"!JJ!-1'! !"NJ!!)KrirYiJ*i##+JH!JCm!!j`I!!"P&3&%$T)!!ZGJ%%!&)"q!JK,rrEGNri ##)"K!'`X!`!"3))!&)#"!(!iS3!i5rrqD8J!!#3X!`!#3))!&)#"!(!iS3!i5rr mY8J!!!`iB!!35!!!))#K!$L!RJ))U(i#"$J$rrp8!"!kI+3",MKJ!!#!!3"B1#% !8(`)!kDl`Iri6S!!)!#3"L""J!)!N!3",!!4,Q0bC@4#G@CQCA**ER0PFR3!I!J #TVqKrr53!!%!#*3Krl"mIaYiN!#"!'b3!+%!F$[!!!!S(`!!3))!$$KJ!!T)!!$ !IphcH%J!!+L!I`))I)2`,S"N!!#!K!!%J+%!E)$"!(")!!(4B!!!!(aJ"h9"JJ" iJ(m##(r$m#jr`r0i5!!('@!!!!"r`r0i5rrecAqPkhK8Sa!k5!!!))#I!JJi"3! "9!!31R`%!#jm""NZ1+8!!6KM!!5SR`)%1!6rrh`&!!""J2rB1)!!!)"r!JK8!"! kI)-",UKr!J3i!rrrX"m#"%J!!"Jl[3!"1pi!"+JI!J4m(3!!3B$r9$KJ!!#!!3" B1#%!8(`)!kDlSIrd6S!!)!#3"L""J!-!N!3"!!!4,Q0bC@4#G@CQCA*5C@e[GQ8 !I!J#TVq"rr#3!!%!#*3Krl"mI"YiI*dMH$KL!M%iJJ'pJ+)!4$J!!!#3!!%!1#J G!!"!JJ!mJ!8!!#`!!!&!JJ!B1+!"5$M!!!&)!!MPJ%%!&%J!!"`X!!!%3))!&$L J!8Ji`!!"5!!)bB""!"3S(3!!3))!$$KJ!!a)!!"-1m!!!(rImhK)!!!SJ(d##(` $q#k3!!%!1(q$ihJiJ3!i5rraJ@!!!!!lhJ!"1rm!"+JG!J4m(J!!3B$re)"p!JK ,rr4P1'!!!)!"!&Ji)3"3I!J$TVZ"rr"1J!!J!*!')%'!"!#3"GJ!%LjNDA0`Eh0 P3h*PC%*eCQCPFR`)!UDr`IriN!!"!!L8)Ir!N!"K!&L3!)%!A*!!S3"JN!$"!'5 $`3"F+"i!!%'#!"#$i3"N+"m!!%##!!`iB!!!5!!!k)"K!&L!!3"JI!-!!%'#!!` iB!!!5!!!d#`$!!&!JJ"X1(i!!6LI!!&)!!LjJ%%!&#`$!!"!JJ"-1(i%icLI"10 )!!LKJ%%!&#`$!!"!JJ!d1(i6L6LI%iP)!!L*J%%!&#`$!!"!JJ!FJ(iBI)!I'(a m!`!!3))!$$KJ!!&)!!"S1'!!!%J!!'!X!`!#3))!9)"q!!#!R`!!5!!)5B""!"3 X!`!!3))!0)"q!!5!R`!%5!!)-B""!"3X!`!!3))!()"q!"L!(`!BI!-!!%##!!` iB!!"5!!!%$KJ!!")!!!)1'!!!)!"!%Ji)3"!I!J$TV["rrK1J!!J!*!')%'!!J# 3"!%i!!JZBh*PC'0YF!!!I!J#TVq"rr#3!!%!#*3Krl"mI4YiI*`MH#JF!!"!JJ! -1'!!"NJ!!C`iB!)S5rrb0C!!I!!!J"`!!#J!!!"!JJ!-1'!!"NJ!!Aam(`0iIq2 lH(qNkhK)!!F"J%%!&)!G!3#3!"m"!$Kr!33iR3%%5!!'kB""!"5S(3)%X"m#"+J G!JD`(`)'1!!!!CJI!K#S(`)'9!-31N[rmFf3!(m##)!I!JJS!!!!3))!$$KJ!!C )!!%81m!!!(rFmhK)!!$`J(d##(b$i#k!C!!!,!-!!8##!)!iB!!)5rraMB#I!JK mC1%ZJ(m##(aMi#iS!`!!3))!$$KJ!!C)!!$-1!!!!C!!!`!!1'!GJ%[rm9f!R`) )I)6J,T!!C!!%J(m##(aMi#k!B`!%+!-!!%##!!`iB!!'5!!!P)#G!JKmK1!ZJ)3 !"$LJ(B")!!C&J%%!&%J!!&JX!`!#3))!')#%!!5!(`))I+$L&%[rphe)!!!m,!- !Bd##!$3iB!!)5rr`lB#I!JKmC1%ZJ(m##(aMi#iS!`!!3))!$$KJ!!C)!!!X1!! !Bj!!!`!!1pi!!6ZF!!5S(`)%I"i!!%'!r``iB!!!N!"r!L53!(m#))!"!&Ji)3" 3I!J$TVZ"rr"1J!!J!*!')%'!"!#3"!(8!!BZC(9`6N0m#!+Q[m(rq*!!!3!)P#( r`(aq'hKrhr0i+"m!!%'#!#a)!!!8J(m!!)"M!!K,rr#j1rm!")!I!!!S!!!!3), rk(r$mhK,rr#KJ!%!5$JK!%"m#!1QZm(rq%k!!#!!N!BJ3B!#!*!&A!!4,Q4TFh" [Ff9%BA4K3A*bBAN!I!J#TT2Krrb3!!%!#*3Krm"mIaYi1')#2$L#!Ef!SJ"%+"m !!%##!&#!"3!!,!!!!8##!"JiS!(#1-!!!8J!"$@!33!85!!!-#`!!!4!JJ!S1+! "`MM!!!&)!!3CJ%%!&%J!!"4rirYiIq6lH%[ri4eJ!!!!J"m!!#J!!!"!J[rS1'! !!)!"!%Ji)3"!I!J$TS2Krra1J!!J!*!')%'!!3#3"CJ!#bjQFQ9P6N0-DA0d!!! !I!J#TT2Krrb3!!%!#*3Krl"mIaYi1')"ecL#!Ef!SJ"%+"m!!%##!$b!"3!!,!! !!8##!"JiS!(51-!!!8J!!hf!33!85!!!(#`!!!4!JJ!81+!"dMM!!!&)!!0KJ%% !&$KK!$K)!!-0J%%!&(aJ"c9"JJ!-1'!!!%J!!%#!(`)8,!!!C%'#!#JiB3!i1*m #'$LK!%")!!,eJ%%!&(aJ"c9"JJ!81'!!!%J!!"!i!!!!Q!%!3)KK!%#!!3"B1#% !8(`)!kD$iIrm6S!!)!#3"L""J!%!N!A-!!XZDA0-Ef0V6h9bF`!!!(`)!UDr`Ir iN!!"!!L8)Ir!I(iEH$KL!NmiJJ'pJ+)!4#JH!!"!JJ!mJ!8!!#`!!!&!JJ!B1+! "jcM!!!&)!!+4J%%!&%J!!"`X!!!%3))!&$LJ!HFi`!!"5!!#GB""!"5!(J!!,!! !!N##!'L$rJ!%J(m!!%[rlNf!I`!%5rrZ4B"r!"!S!`!!3B)!#%[rlM@!I`!i+!- !!%'#!!K,rqiPJ(m!4#J$!!""JJ!)5rrZ&B"r!%JS!`!!3B)!#%[rr5'!I`!X+!- !!%'#!!K,rrd4J(i!"%[rlHdiB!!!J!%!5$JK!%"m#!1QZm(rq%k!!#!!N!BJ3B! #!*!&m!!A,Q0MAfCbC@9IBh*PC&pTER4PFQjKE(-!!!"m#!+QN!!"!!L8)Ir!5!! !U@!!!!"mB!Fe3B)!#%J!!"!i!!!!J))!)*!!"!!!J!%!5$JK!%"m#!1Q6S!!)!# 3"L""J!#3"M`!%bj*EQPdD@&XDATP3f&MD'9-D@)!!!"m#!+QN!!"!!L8)Ir!5!! !R@!!!!#!!3")1#%!3(`)!kC1J!!J!*!')%'!!*!'*!!5,P4PFQeTEQ&dC80KBfK P6'PLI%-6H%k!!#"m#!+QN!!"!!L8)Ir!5rrrlAaT'hL!BJ"JJ))!A$LL!!!i`J* GJ1)!8)%#!%a)!!"CJ%%!&)##!+53!'3!!%[rf)eJ!!!!1'!!!)!"!%Ji)3"!I!J $TNk!!#"m#!+QN!!"!!L8)Ir!J')!T)"M!!")!!!aJ%%!&)!"!%Ji)3"!I!J$TNk !!##"JJ"!N!""!"5!$!!!J%`!"(`*!kC1J!3JJB)!2*!!33!8J!`!!)"-!!4m#31 Q6S!%))'#!"L3!%%!&)!-!!#!6!!%I!N$TNk!"##"JJ!8N!""!"5!$!!!J%`!"(` *!kC1J!3JJB)!$*!!33!8J!`!!)"-!!4m#31Q6S!%))'#!%L3!%%!&)!-!!#!6!! %I!N$TNk!"##"JJ!3N!""!"5!$!!!J%`!"(`*!kC1J!3JJB)!1*!!33!8J!`!!)" -!!4m#31Q6S!%))'#!!53!%%!&)!-!!#!6!!%I!N$TNk!"##"JJ!FN!""!"5!$!! !J%`!"(`*!kC1J!3JJB)!-*!!33!8J!`!!)"-!!4m#31Q6S!%))'#!!L3!%%!&)! -!!#!6!!%I!N$TNk!"##"JJ!SN!""!"5!$!!!J%`!"(`*!kC1J!3JJB)!!*!!33! 8J!`!!)"-!!4m#31Q6S!%))'#!#b3!%%!&)!-!!#!6!!%I!N$TNk!"##"JJ!NN!" "!"5!$!!!J%`!"(`*!kC1J!3JJB)!0*!!33!8J!`!!)"-!!4m#31Q6S!%)!!!*cL !!!"B!*!'*j!!J!!!,!#3#8iL+@`#)LP8!L)#ABB#!5PX)J'GJJ)4!Bd"K!&h!Nm #2!)a!KS##`(l!Hi"iJ(A!FS"[3'[!+`"D!3L%ML'!K84R"%N%-J3D!md$2J,r!Y -#U3*i!Lm"rJ(*!E-"8`%9!-S!B`"#!!F*ZJL*S3%,Ne*9#"*,e-J6@&M4'9f!5# "CJ`K+'jKE@8J)6dJ-#N)3d0KBfKP,Q-2)5JUD'&ZC'aP)#%p)$!T%5%SF(*TEQ0 TF'&X)#%p)$!T$5%SFf&QC9!J)6dJ-#N-3d0KBfKP9A4TE#jM$#%SFfPkC5!q)$" -+3SK+'jM)#%p)$!T#b%SEf*U)#%p)$!T$#%SC'9cG#!K25!`+3pbCA4NCA0d)$d p)%j96%`1+LTNCA0d)$dp)%j96%`@+#SUC'9cG#NY2Q4KG'%J26dJ6P9-6!TZBb! p25"198a-%L%SBfjdFQa#E'pMDb!K25!`+3dK+'0bC@4c)#%p)$!TFGB!!!%!!!! "B!!!!'!!!!!b!,V"!*!%2S!!CL!!ZZ%!N!3qK3#X)!$p1`#3"B!!E!!!Z[d!N!@ !!(J!!,X2!*!%2S$rr`!!Zam!N!3qMIrr!!#l3`#3"$k-rrm!!,Yr!*!%2SArr`! !qmF!N!3qJ2rr!!#lZ`#3"$k0rrm!!,[[!*!%2Scrr`!![#-!N!3qKIrr!!$lN`# 3"$k!!))J!,aA!*!%2S!!M3!![&m!N!8"rrm!!2Xr!*!%2SArr`!!r*d!N!Err`! !r@N$VL"F!d0@8`T8BA0V)%jKE@9c$%0A3eC6)&"KEQ9XF`i!!!"F!*!,!3#3%`& `Gh"M!*!6!3#3%6`168P8Ak9$3f&MD'9-D@)!N!8"!!!!!@!!!!"J!!!!-J9@1G! d*J!!!"`!-J!!BfCbC`!!!!S!!2rr!*!%"9Bi[&YF: \ 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
index c72e54adb6..0000000000
--- a/src/mac/libraries/CCache API/bin/CCacheLib.PPC.debug
+++ /dev/null
@@ -1 +0,0 @@
-(This file must be converted with BinHex 4.0) :%d0$B@0SC8aTBLj38%-ZC'9LG@F!FfKXBMq3"!#3"$LS!!!"PV5C5Qpj)A"PCQC `Gh"M!!!!!E*6cTi!N!d$!!)!N!6rN!3!N!Ba`!!!-F!!!$(!!!!&J!!%"!$rN!3 !N!B#D3!!!Q8!!!&S!!!h3!)%"!$rN!3!N!i%mJ!!!)!%"!3!N!ArN!3!N!F"!!! "D!!!!!%!!!&J!!!!"3!!!"8!!!!"!!!"%!!!!5!!!!1-!!!!"!!!!"8!N!m+!*! ,$3#3#`%!!!!+!*!()`!!!!%!!!!"!!!!!J!!!!X!N!Fl!*!,!J!!!!d!N!G8!*! ,"J!!!!m!N!3#!!"R!J!!F!)!!(S#!!#(!J!!NJ)!!*d#!!#Q!J!!X3)!!,d#!!$ 2!3!!eJ%!!1)#!!$[!J!!r3)!!4-#!!%R!J!",J)!!68#!!%p!J!"4!)!!8X!!3# 3"3J!N!4+&%!"3J&!!8)33J#!!dB@5@jdCA*QB@0P6'PL!%e*9&qP3d0KBfKP4fa [BQ&XFdaTBJ"0594IT84PBR9RCfPZCdaTBLjNC@*eC`"0594IT8e*9&*eER4TE@9 -D@)ZC'9LG@F!68P8Ak90594$6'PL,Q4PBR9R!&0jFd*bC@&V!%jPGe"dFP0jF`" 9EQK[E'40C@e[FRN!5'pXC%ePE@pbH3"%DA0`Eh0P8(4b!%4PBR9R8h4b!%GPG&" dFP0THQ8!8f&YC9"bEf0PFh-!4f9d3h9bFQ9ZG&"bEf0PFh-!6Q9h8(4b!'G$ER4 bE%*XEf0V!'G%C@*eCe0TCfjKE!""E'9bG&0TCfjKE%&d!&pIG@jbC@GTFh4PFPp QFQ&RE@9ZG!"IAh*PCfPcG'9bAfCbB@GYC@jd!(0dFQ0YF!"YC@eMF(N!Fh4bEQ0 `H3"cG(*MF(N!Fh4bE'9Z!'ePEA0PG!"MBepRCA4IBh*PC&pfCA*cD@pZBf0IC'9 cG(*[H@0MAfGPG&pMD'&ZCf9IG'PYC@0MAfCbC@9I6N0ID@jQEf0MAf0bC@&dC@0 MAf0XEh0PBf0ICf9dAfjKE@9MBepQFQ9PAf0bC@4cBf0IFQ9YEhCPAf0bC@4MBep QFQ9PAh"bD@jMDA"KE'0MAfp`C@jMBepcD(9dC'phEQ0MAh0PG&p`FQPZBfP`B@a MBepcCA&ICQ9dBfKI6N0cBf0ICf9dAdj$AfPZCQpMBepTEQPdD@&XDATPBf0ICf9 dAh"bD@jMDA"KE'0MAh0PF9pQCA4MD&pMFQ9NFf0MAh0dEh*PBf0ICR*PC9pZB@e PBf0IE'pMDepbCA&eCA0d!*!("!!!!!`!!3!)!!3!!!!'!!J!"J!)!!J!!!!+!!3 !#J!!!!X!%!!,!!`!$`!!!")!"!!5!!!!%`!)!"-!%qq*!!UDh`!569F!$c0A!!P -)3!)*Xm!#cEk!!h1V`!1jP-!%IJ'!!F66!!,2Ad!%)`+!"##X3!1ZFB!$FMP!"$ -#`!5#&i!##F0!!aR@J!2'"i#!!&5!!!"!!!"!J!"C3!!!6!!!3)!!@m!!!%S!!% #!!'"!!!!`!!"!J!"N!!!!!&)!!%#!!'C!!!"1!!"!J!"S3!!!2J!!3)!!D`!!!$ )!!%#!!'j!!!"'!!"!J!"a`!!!0J!!3)!!GJ!!!&!!!%#!!(I!!!"8!!"!J!"kJ! !!4!!!3)!!IS!!!$`!!%#!!)+!!!!i!!"!J!#'!!!!9J!!3)!!L8!!!%)!!%#!!) e!!!!k!!"!J!#4`!!!5!!!3)!!Nm!!!$3!!%#!!*E!!!!Z!!"!*!1I!J#TT!!!3! )P#(r`$JK!%#!!3!)I!J$TNk!!#"m#!+QNq(rr*2"rrL6SIrdNi(rm*!!!3!)P#( rX(ar'hL3!)%!E(bm+hKmh60iJm)!+)"q!!!S!`!!3))!B$KJ!"")!"PeB!!!!*! !I`!!J*m!!#J%!!"!JJ!-1'!!"NJ!!(`iS!!!J0m!!*!!TJ!%J2m!!*!!T`!!13! !!)%r!!#4#3!)18!!!)&r!!#45`!-JCm!!*'H!!")!!!-J(i!!*!!I`!!J)%!E#` %!!&!J3!-1'!!#8J!!#JS(!!!3B)!$$LJ!!'3!,`!!#JG!!""JJ!-J-)!X*!!h3! !1'!!!)!"!&Ji)3"3I!J$TS2Krrb$`IriJk(rp)1"rr"1J!!J!*!')%'!"!#3"IJ !$LjMBepTEQPdD@&XDATPI!J#TT2Krrb3!!%!#*3Krm"mIaYi+"m!!%'#!#b!I`! !+!-!!%'#!##!I`!!5!!U)@!!!!#!I`!!5!!@T@!!!!")!!!-1'!!#NJ!!"!iJ!! !N!#I!!!iB!!!J!%!5$JK!%"m#!1QJq(rr%k!!#!!N!BJ3B!"!*!&E!!-,Q0MAh0 SGA4NEhGZ!!"m#!+Q[f(rl*!!!3!)P#(rX(aq'hKmR#0iN!#K!("mh60iN!$K!(K p'd0i1q!!!#JH!!"!JJ!-1'!!#NJ!!8JS'`!!3))!$$KJ!!a)!!%i1'!#+%J!&m& J!!!!I(mEH#JI!!"!JJ!-1'!!"NJ!!4JS(!!!3B)!'(q$ihK)!#pCJ%%!&#J$!2p "J!!-1'!!!8J!!24rirYiIi6MH%J!,UQ!33!8+"d!!%'#!"KrSqYi5!![*B""!"3 S!`$r3B!!$$KJ!!a)!!$!1(m""(qNkhK)!#jeJ%%!&)"K!(L3!(m#$$L!!!#`R`) %J+%!F*!![`%!1-!!!TMI!K!ii!"NN!$r!K4rirYi5!!AM@!!!!#3!(m##)%I!JJ S#!!!3))!$$KJ!!C)!!"NJ6i!##`*!!"!JJ!F18!!!*&I!L54A`)JNri!!*2q!!4 )!!!JJAi!"*2V!L#"RJ!%NCm#*$KJ!!#3!(m#)*2q!!5!RJ!)1)3!!C!!RJ!)J,i !$$LP!!'3!,i!$*2l!!!iB!!!J!%!@$JK!&"m#!1QZf(rl%k!!#!!N!BJ3B!&!*! %!C3!#LjMBepMFQ9KG'9m#!+Q[Z(rh*!!!3!)P#(rS(ah'hKmQL0iI,NVH(ci1hJ lSJ'-1m)"Ii2L!#`lJ!!!1f!!!#JA!!"!JJ!-1'!!#NJ!!3`S'!!!3))!$$KJ!!a )!!$m+"S!!%##!)5!I`!!,!-!!8##!#"r`r0iIk6VH$LJ!+Xi`!!!5!!XFB""!"4 )!!"FJ*m!!#`%!!*!JJ!8Im2cH%J!,'f!33!85!!!3)#r!!!X"3!$3))!%%J!,'f !33!85!!!+)$I!!!X"J!%3))!((r$mhKrT1Yi1+!!UcM!!!&)!#`9J%%!&)1A!!" )!!!dId26H(q%ihK)!#dGJ%%!&#`$!!"!JJ!BJ2`"!(`C1!"!JJ!-1f!!!8J!!!L $R!)J+"`!!%'#!""rD!Gd,!J!!%'#rm"rD3Gd,!N!!%'#!"#6Q!!!1'!!!%J!!"! j3!!!N9J!!$KJ!!U!!3"S1#%!B(`)!kDkiIrF6S!!)!#3"L""J!N!N!3"B!!),Q0 MAfp`C@i!!(`)!UDr3IrSN!!"!!L8)Iq`I(SEH(bF)hJl`J'91k)"M)2L!#`lB!! !+"S!!%##!!`iB!!+5!!!k#JF!!"!JJ!-1'!!$%J!!0L!I!!!+!-!!%##!)5!R`! !,!3!!8##!#"r`r0iIk6VH$LJ!-di`!!!5!!UrB""!"4)!!"FJ,m!!#`&!!*!JJ! 8Im2cH%J!+[Q!33!85!!!3)$I!!!X"J!$3))!%%J!+[Q!33!85!!!+)$r!!!X"`! %3))!((r$mhKrT1Yi1+!!c6M!!!&)!#UKJ%%!&)%F!!#*#!)3I3J(G#`)!!&"JJ! -1'!!$NJ!!$#$I!!!Id26H(pNfhK)!"r0B!!!!(pMfhK)!")GB!!!!$NJ!!#42!! !1'!!!)!"!&Ji)3"3I!J$TVY"rqK1J!!J!*!')%'!"J#3"!%`!!NZBf0IBfa[Ff8 !I!J#TVmKrq53!!%!#*3Krk"mHKYiI*XMH$[#!C8lSJ'-Jq)!,$Z!!!!S'J!!3)) !$$KJ!!T)!!'!+"X!!%##!!`iB!!-5!!"F)"l!!!S!`!!3))!K)#I!!!X"!!"3)) !)(r$mhKrT1Yi1+!!kcM!!!")!#QaJ%%!&%J!!&b![`!!,!8!!N##!"4r`r0i5!! TVB""!"4)!!"!J0m!!#`'!!0!JJ!35!!TVB""!"4)!!!SJ2m!!#`(!!4!JJ!FIm2 cH(qNkhJiS!$V1-!!!8J!+9@!33!8JjX!!)%F!K3X#!"N3B)!*(q$ihK)!#9jB!! !!(aM"h3X!`!!3))!$$KJ!!K)!!#dJ6`#*#J*!!"!JJ!NJ9`#)*&D!!#"I!)J+!X !!%'#!"!jJ!!!J(`#)*'$!L5!R!)J+!3!!%##!#5![!)NN!#k!!5!h!)N+!B!!%' #!"!ii!!!J4`#**!!k!)JJ6`#*#J*!!""JJ!SJ9`#)#J+!!""JJ!FJA`#*)'F!L# 4E!)NJ(`#))#F!L53!'3#)$LJ!!'B[!)3Id26H(pNfhK,rrdCI(NEH)$D!!`iaJ! "N!$D!!ar)mYiJ!%!D$JK!'"m#!1QZb(rj%k!!#!!N!BJ3B!(!*!%!FJ!#bjMBep NCA0dFQpj!!!!+!-!!%##!!`iB!!+5!!!)#J%!!""JJ!8J+-!$*!!T!!!1'!!!%J !!!JiB!!-6S!!)!#3"L"!!*!(-!!6,Q0MAfGPG&pMD'&ZCf9IG'PYC3!!!(`)!UD 6iIrmNm(rq*1Krr53!!%!#*3Krl"mI4YiI*mMH*!!S3"`N!$"!(3l`!!!+"d!!%# #!!`iB!!+5!!!L#JI!!"!JJ!-1'!!#NJ!!(L!I`)8,!-!C%'#!$#!R`)8,!3!CN# #!"arirYi5!!MZ@!!!!"mB`Gd,!-!!%##!!`iB!!)5!!!3(rMqhL!J3"`J+%!G%J !'HeJ!!!!I(iEH#`H!!"!JJ!3J,d!#$LP!!'3!,d!#)$G!!`iaJ!"N!$G!!ar`r0 iJ!%!@$JK!&"m#!1QJq(rr)2"rrL$SIrd6S!!)!#3"L""J!-!N!AF!!NZBf0IFh4 [FQ8!I!J#TT2Krrb6`IriN!!"!!L8)Iq`I(iEH(bI)hL3!+%!F*!!`3"d1'!!!*! !B3!i+"i!!%'#!!`S(`!!3))!$$KJ!!T)!!"JJ*m#&#`%!'4"JJ!`J,m#&#`&!'C !JJ!FIq2lH%J!)XPJ!!!!I'-(G#`$!!"!JJ!-1'!!#%J!!#KrirYiJ)%!F)#K!(4 )!"TaB!!!!)$H!!`iaJ!"N!$H!!`iB!!!J!%!@$JK!&"m#!1QJq(rr)2"rrK1J!! J!*!')%'!!J#3"EJ!$bjMBepbC@e[GQ9IBh*PC!!!!(`)!UDr3IrSN!!"!!L8)Iq `I(SEH(bE)hL3!+%!F(cF-hJl`J'P1k)"M)2L!#`S'J!!3B)!$#JE!!"!JJ!-1'! !#NJ!!3!S(!!!3))!K)"r!!!X!`!"3))!)(r$mhKrT1Yi1+!"DcM!!!")!#@PJ%% !&%J!!&b!R`!!,!3!!N##!"4r`r0i5!!PSB""!"4)!!"!J,m!!#`&!!0!JJ!35!! PSB""!"4)!!!SJ0m!!#`'!!4!JJ!FIm2cH(qNkhJiS!&V1-!!!8J!*8Q!33!8J2X #&#`(!'4"JJ!`J4X#&#`)!'C!JJ!FIf2EH%J!)@9J!!!!I'-(G#`$!!"!JJ!-1'! !#%J!!%#"1`%!J8%!F(`*8!""JJ!-1'!!#NJ!!#JiH`%%Ii6MH$LJ!2p)!#AYJ%% !&)&k!!`jD`!"NAS!$$KJ!!#!!3"B1#%!8(`)!kDl3IrS6S!!)!#3"L""J!B!N!3 "9!!4,Q0MAh0PG&p`FQPZBfP`B@`!I!J#TT2Krrb6`IriN!!"!!L8)Ir!I*iMH(b r+hJS(J!!3))!$$KJ!!T)!!"`J(i#&#`$!'C!JJ!NIm2cH%J!)*PJ!!!!I'-(G#` $!!"!JJ!-1'!!#%J!!%3S(`!!3B)!1$KJ!2p)!!YYB!!!!*!!I`!!J*m!!#J%!!" !JJ!-1'!!"NJ!!"L!I`!!1*i""%J!*,'!33!81'!!!)!"!%Ji)3"!I!J$TS2Krrb $`Iri6S!!)!#3"L""J!)!N!@`!"%ZBf0ICf9dAh"bD@jMDA"KE!"m#!+QNq(rr*2 "rrL3!!%!#*3Krm"mRb0iI,iVH#JI!!"!JJ!-1'!!#NJ!!%b!I`)8,!-!CN##!#4 rirYi5!!Ia@!!!!"mB`Gd,!-!!%##!!`iB!!)5!!!)#JH!!"!JJ!-1'!!"NJ!!"# !R`%!N!#H!!!iB!!!J!%!5$JK!%"m#!1QJq(rr)2"rrK1J!!J!*!')%'!!J#3"B` !&#jMBepRCA4IBh*PC&pfCA*cD@pZ!!"m#!+QNq(rr*2"rrL3!!%!#*3Krm"mRb0 iI,iVH#JI!!"!JJ!-1'!!#NJ!!&b!I`)8,!-!CN##!#4rirYi5!!I%@!!!!"mB`G d,!-!!%##!!`iB!!)5!!!-#JH!!""JJ!N1'!!rdJ!#H9J!!!!N!"q!!#!IJ!!Iq6 lH%J!)cf!33!81'!!!)!"!%Ji)3"!I!J$TS2Krrb$`Iri6S!!)!#3"L""J!)!N!@ F!!`ZBf0ICf9dAfjKE@8!!(`)!UD6iIrmNm(rq*1Krr53!!%!#*3Krl"mI4YiI*i MH(br+hJS(J!!3B)!&#JI!!""JJ!-+"d!!%##!!`iB!!+5!!!S)"r!!!S!`!!3)) !0$KJ!!K)!!NjB!!!!*!!I`!!J*m!!#J%!!"!JJ!-1'!!"NJ!!(#![3!!J0m!!*! !TJ!!J2m!!)$R!!!S"`!!3))!+)"r!!")!!PeB!!!!$N!!!#4(`!!15!!!*%q!!! iB!!$5!!!-)&I!!#!DJ!!Im6cH%J!'E&J!!!!JAm!!)&V!!#"D`)JJCm!!*&X!!! iB!!!J!%!@$JK!&"m#!1QJq(rr)2"rrL$SIrd6S!!)!#3"L""J!-!N!Am!"%ZBf0 IFf9aAfCPG'0SAdj$F`"m#!+QNq(rr*2"rrL6SIrdNi(rm*!!!3!)P#(rX*!!B3" SI*iMH(bp+hKmhc0i+"i!!%'#!"JS(`!!3B)!%)"K!'JS!`!!3))!$$KJ!!T)!!) %+"d!!%##!!`iB!!'5!!"p)#H!K3X"!"Q3))!*(r$mhK)!"d"B!!!!(aM"h3X!`! !3))!$$KJ!!K)!!()J,m!!#J&!!"!JJ")1'!!#%J!"p&J!!!!N!"r!!#!h`!!+!B !!%##!!`iB!!'5!!"Q$MJ!!#"(`!!N!$S!!4)!!!8J6m!!)&*!!3j5J!"N8N!")& r!!#"D`!%UCi#"(`,B!"!J!!NJ(i##)#I!!#!K!!%9)331RaM)#k!B`!!,!-!Bd' #rm#![`!!J+8!"+MH!J4m"6!!3B!!+)"r!!")!!I"B!!!!$MJ!!#3!2d!!$N!!!# 4(`!!1'!!!dJ!!3b"2J))J9m!!)&+!!495K!kI5P3,S1*!!!X(!!"3))!K$KJ!!K )!!F"B!!!!*!!I3!!JAd!!#J,!!"!JJ!-1'!!"NJ!!-JiB"f!5!!'h@!!!!#"R3! !N!"X!!5!I3!!J'-!"#J$!!"!JJ!-1'!!"NJ!!*b!R3!!J'3!")#q!JL!h`!!J-B !"&6'%$TmT6!ZJ)8!"$LJ(B")!#!YJ%%!&%J!!&JX(!!#3))!3)$q!JL"(`!!J3J !"&8)%$Tmjd!ZJ1F!"*!!i3!m15!!!T%K!$L!B3!iJ)%!2(qPkhK)!!mKB!!!!%J !!"3j3!!!N9d!!$KJ!"")!!!BJAm!!)',!!3jM!!"NBX!"$KJ!!#!!3"B1#%!8(` )!kD$iIrmJm(rq)1Krr5$JIr`6S!!)!#3"L""J!3!N!3#F!!6,Q0MAh0PF9pQCA4 MD&pMFQ9NF`!!!(`)!UD6iIrmNm(rq*1Krr56JIr`N!!"!!L8)Iq`I(`EH(bG)hJ li!!!1m!!!#JF!!"!JJ!-1'!!#NJ!!1JS(3!!3))!$$KJ!!C)!!$BJ*`!#$L%!!& 8Ja!k5!!HdB""!"53!(d!!)#p!!!S"3!!3))!$$KJ!!C)!!#XJp`!!%J!!)JiB!) %5!!HTB""!"5!h3!!9qF31RaQ15k"(3!!9qN31Rd)5#iS#!!!3))!$$KJ!!C)!!" `J9d!!&IV%$TmDPJZIm6cH%J!(Rf!33!8JCd!!&IN%$TpM#!Z1'`!rcLH!34)!"j KJ%%!&)#q!3#!h3!!9qF31Rc'1#k3!+B#!)2H!L!lr`!"+"i!!%##rhJj!!!!J6d !!&IU%$Tp#9%Z1'!!!)!"!&Ji)3"3I!J$TS2Krrb$`IriJk(rp)1"rr"1J!!J!*! ')%'!"!#3"!&!!!mZBf0ICf9dAdj$AfPZCQm!!!"m#!+QNq(rr*!!!3!)P#(r`(b I)hJS(`!!3))!$$KJ!!C)!!!8Iq2lH%J!"-9J!!!!1'!!!)!"!%Ji)3"!I!J$TS2 Krra1J!!J!*!')%'!!3#3"8J!%LjMBepQFQ9PAh"bD@jMDA"KE(`)!UD6iIrmN!! "!!L8)Ir!I*mMH#JI!!"!JJ!-1'!!"NJ!!"4rirYi5!!%@@!!!!!iB!!!J!%!5$J K!%"m#!1QJq(rr%k!!#!!N!BJ3B!"!*!&5!!0,Q0MAfCbC@9IEQ&YC3"m#!+QNq( rr*!!!3!)P#(r`(bI)hJS(`!!3))!$$KJ!!T)!!!SJ(m!!%J!'EeJ!!!!J(m!!%J !!q9J!!!!1'!!!*!!I`!!1'!!!)!"!%Ji)3"!I!J$TS2Krra1J!!J!*!')%'!!3# 3"9`!$LjMBepQFQ9PAf0bC@4cI!J#TT2Krrb6`IriN!!"!!L8)Ir!I*iMH#JH!!" !JJ!-1'!!#NJ!!&3li!!!5!!!()#H!!"Aj4!kI'3S,NJ!'j'!33!81rm!!B$H!!" Aja!kI-Bi,LJ'!!"!J[rBJ(i!!%J!'ff!33!813!!!*%H!!!l`!!!1'!!!)!"!%J i)3"!I!J$TS2Krrb$`Iri6S!!)!#3"L""J!)!N!@3!!!3,Q0MAfCbC@9I6N0ID@j QE`!!I!J#TT2Krrb6`IriN!!"!!L8)Iq`I*mMH*!!S3"`+"m!!%##!!`iB!!-5!! "1$KK!$K)!"UjJ%%!&(aq'hL!I`)8,!-!C%'#!"`iB3!i1*m#'$LK!%")!"UYJ%% !&(aq'hL!J3"`,!3!!N'#!#a!J!!3,!3!!8#!!"4)!!$F,!3!"%#!!04)!!"-1+! !C*!![`)85!!!c)$I!K3X"J"N3))!)$MJ!'@3!2m#&)%"!$L")3!mN4m#'*%r!Ka )!!#NJ9m#&#`+!'C!JJ#B1'!!#%J!!*5"I`)8,!X!C%##!#!jJ!"QNCm#&)"K!$L !J3!mN!"r!KL3!*m#(%J!!'L![`)8,!8!CN##!"L)`3"!+!B!!%##!!`iB!!)5!! !6)$r!K3X"`"P3))!2)N"!%!S#!!!3B)!)$NJ!'D42`)8J8%!1)&K!$b4A`)BNAm #(%J!!"3iB!!)5!!!%$KJ!!a)!!!)1'!!!)!"!&Ji)3"3I!J$TS2Krrb$`Iri6S! !)!#3"L""J!)!N!3"H!!3,Q0MAfa[BfYIFQ9aG@9cG!!!I!J#TT2Krrb3!!%!#*3 Krm#3!'%!@$[J!!#!B3"B5!!BI@!!!!"mIaYiIq-(0#`$!!""JJ!-Iq2lH%J!!"3 iJ!!!J+)!+*!!K3!!Iq2lH)!"!%Ji)3"!I!J$TS2Krra1J!!J!*!')%'!!3#3"@! !%bj*EQPdD@&XDATP3f&MD'9-D@)!!!"m#!+QN!!"!!L8)Ir!5!!BA@!!!!#!!3" )1#%!3(`)!kC1J!!J!*!')%'!!*!'*!!5,P4PFQeTEQ&dC80KBfKP6'PLI!J#TT2 Krrb6`IriN!!"!!L8)Ir!I(iEH(r$mhK)!"NjJ%%!&(ar'hJS(`!!3B)!&(rMqhK ra20i5!!C6B""!"4rirYiJ!%!5$JK!%"m#!1QJq(rr)2"rrK1J!!J!*!')%'!!J# 3"9`!#bj1CAG6B@CP8(4b!!!!I!J#TVp"rqL3!!%!#*3Krl"mHaYi1i)"dM[#!F8 lSJ'hJq)!,(pMfhK)!"KTJ%%!&(ak'hJS'`!!3))!K)"r!!!X!`!"3))!)(qMkhK ra20i1+!!*cM!!!")!"IaJ%%!&%J!!&b!R`!!,!3!!N##!"4rSqYi5!!AlB""!"4 )!!"!J,m!!#`&!!0!JJ!35!!AlB""!"4)!!!SJ0m!!#`'!!4!JJ!FIk2VH(r%mhJ iS!!R1-!!!8J!&j@!33!8,"S!!%'"!)5!r`!!,!F!!8##!#"rJq0iIm6cH$LJ!#J i`!!!5!!ADB""!"4)!!"FJ4m!!#`)!!*!JJ!8Ii2MH%J!&f@!33!85!!!3)%r!!! X#3!$3))!%%J!&f@!33!85!!!+)&I!!!X#J!%3))!((q$ihKra20i1+!!+$M!!!& )!"F0J%%!&(pMfhJiJ!!!IdA6H%J!&eQ!33!8If2EH$L!!!"r4G0i5!!A4B""!"4 rBpYiId66H%J!&df!33!8If2EH%J!&V'!33!8J!%!@$JK!&"m#!1QZd(rk%k!!#! !N!BJ3B!'!*!%!C`!$bj%DA0`Eh0P8f&QC9"dFJ!!!(`)!UD6iIrmNm(rq*!!!3! )P#(r`(aq'hKr`r0i5!!AAB""!"4mIaYi+"m!!%'#!"4rirYiIm6cH%J!&a'!33! 8Iq2lH)!"!%Ji)3"!I!J$TS2Krrb$`Iri6S!!)!#3"L""J!)!N!9F!!iZ6Q9h8f& QC9"dFP0jFh`)!UD6iIrmNm(rq*1Krr56JIr`N!!"!!L8)Iq`I(`EH$[#!GmlSJ( &Jq)!,#JF!!"!JJ#%J(m!!#`$!!&!JJ!JIm2cH(qNkhJiS!"31-!!!%J!&Ef!33! 85!!!A)#I!!!X"!!#3))!&(r$mhK)!"@jJ%%!&%J!!%#![`!!,!8!!d##!"")!"@ jJ%%!&%J!!#L!h`!!,!B!"%##!"ar`r0iIk6VH$LJ!&!i`!!"5!!9BB""!"3ii!! !X2`#"$N!!!Ua(!)'1'!!+%[rrVf3!(`##)"m!JL!!3"B1#%!8(`)!kD$iIrmJm( rq)1Krr5$JIr`6S!!)!#3"L""J!3!N!Ad!!iZEQ9h3h*PC%*eCQCPFR`)!UD6iIr mNm(rq*1Krr56JIr`N!!"!!L8)Iq`I(`EH*!!J3"XN!#K!(#3!-%!G$[#!HSlSJ( &Jq)!,#JF!!"!JJ#%J(m!!#`$!!&!JJ!JIm2cH(qNkhJiS!"H1-!!!%J!&*f!33! 85!!!A)#I!!!X"!!#3))!&(r$mhK)!"5CJ%%!&%J!!%#![`!!,!8!!d##!"")!"5 CJ%%!&%J!!#L!h`!!,!B!"%##!"ar`r0iIk6VH$LJ!&ii`!!"5!!83B""!"5!i3" XN!$m!!#"!3"`N4`!")%K!(3S#3!!3))!&$P!!!#4A!!)1'!!!%J!!$b!B3"`5rr pJC!!I!!)JA`!##J,!!"!JJ!-1'!!"NJ!!"b!I!!)J)%!G)#K!(")!"5jJ%%!&$K J!!#!!3"B1#%!8(`)!kD$iIrmJm(rq)1Krr5$JIr`6S!!)!#3"L""J!3!N!3"4!! -,Q0[F(P%BA4K6f*U!!"m#!+Q[U(re*!!!3!)P#(rN!"mGaYiI*XMH$Z#!L)lSJ) 61b)#!cY#!IBl`J(&Jq)!,$UJ!!!l!!!!1X!!!#JE!!"!JJ#%J(m!!#`$!!&!JJ! JId26H(r%mhJiS!"d1-!!!%J!%c@!33!85!!!A)#I!!!X"!!#3))!&(p$dhK)!"- aJ%%!&%J!!%#![`!!,!8!!d##!"")!"-aJ%%!&%J!!#L!h`!!,!B!"%##!"ar3p0 iIm6cH$LJ!(3i`!!"5!!5fB""!"4qq,Yi+"J!!%##!"3ii!!!N!$l!!")!!+B1V8 !!B%B!!!l'!!%+!J!!%##rr!j03!"95-31N[rr"@3!(X!!(af'hJS&J!!3))!K)& I!!!X#J!"3))!)(mMbhKra20i1+!!I$M!!!")!"*YJ%%!&%J!!&b"I`!!,!X!!N# #!"4r)mYi5!!5DB""!"4)!!"!JCm!!#`-!!0!JJ!35!!5DB""!"4)!!!SJ(m!!#` $!!4!JJ!FIb2,H(r%mhJiS!"m1-!!!8J!%K'!33!8+"B!!%'#!H"qq,Yi5!!"[$K J!!a,rrYYJ*X!!*!!C!!!J,X!!)#P!!!S"3!!3))!K)$I!!!X"J!"3))!)(qMkhK ra20i1+!!JcM!!!")!"'pJ%%!&%J!!&b!r`!!,!F!!N##!"4rSqYi5!!4ZB""!"4 )!!"!J4m!!#`)!!0!JJ!35!!4ZB""!"4)!!!SJ6m!!#`*!!4!JJ!FIk2VH(r%mhJ iS!#$1-!!!8J!%@'!33!8J9X!!)&+!!!S#J!!3B)"+)&l!!#!D`!!J*F!!$LJ!!a )!")4J%%!&)'E!!#"M!!!J'`!"%[rqTf!Q`!!J)3!!*!!C!!)J,X!!)#P!!#!T3! )+!8!!%##!)5!h`!!,!B!!8##!#"rJq0iIm6cH$LJ!)Xi`!!!5!!3jB""!"4)!!" FJ2m!!#`(!!*!JJ!8Ii2MH%J!%1'!33!85!!!3)%I!!!X#!!$3))!%%J!%1'!33! 85!!!+)%r!!!X#3!%3))!((q$ihKra20i1+!!LcM!!!&)!"#*J%%!&)&E!!#"5J! !J8S!##J+!!""JJ"-JAX!!)&V!!#!D`!)JCF!!)#-!!L!e`!!J+B!"%J!%5Q!33! 81hX!"$XB!!5!q!!!+!F!!%##rN!j!!!!9UN31Rd@55k5f`!!J!%!H$JK!("m#!1 QZU(re%k!!#!!N!BJ3B!,!*!%!i3!$LjMEh"j4'&dB8&bFQ&jI!J#TT2Krrb6`Ir iNk(rp*!!!3!)P#(rX*!!B3"SN!#"!'am[5Yi1q!!!$[!!!#$`3"X+"d!!%##!!` iB!!'5!!"3$KJ!!K,rrNPN!"p!!#!I3!!+!-!!%##!!`iB!!'5!!")$KJ!%a,rrN &I(mEH#JI!!"!JJ!-1'!!"NJ!!33iB!6L5rrikC!!I`!!J*m!!#J%!!"!JJ!-1'! !"NJ!!13iB!6L5rribC!!I`!%J,m!"#J&!!"!JJ!-1'!!"NJ!!-5!I`!!J*i!!$L J"0p)!"!aJ%%!&)"r!!5!RJ!%1+!%hdJ!%"f!33!81(m!#)#H!!L![J!-J0i!%%[ rqJ@!hJ!8N!$I!"5!rJ!BN!$r!"L"(J!FN4m!()%q!##42`!JJ9i!**&I!#5"IJ! SNAm!+)"q!#`iR`!X5rrl,6Kr!$#!RJ!`J,i!0)$H!$K,rrQe1(m!2)#H!$b![J" !J0i!4%[rqD%jJ!!!NCm!5$KJ!!+!R3!!N!"N!!#![3!!Nq8!"$KJ!!#!!3"B1#% !8(`)!kD$iIrmJm(rq)1Krr41J!!J!*!')%'!!`#3"!'B!!XZBfp`H9Be3h*PC!! !!(`)!UD6iIrmNm(rq*!!!3!)P#(r`*!!B3"BN!#"!&am[LYi1q!!!#JH!!"!JJ! -1'!!"NJ!!'`iB!!)5rrhHC!!IJ!!J(i!!#J$!!"!JJ!-1'!!"NJ!!%`iJ!!"J,i !!*!!K3!!1'!GJ%[rpdemIaYi+"m!!%##!!`iB!!'5!!!*(rMqhL!J3"F1+!GJ%J !$SQ!33!8J0i!!*2Q!!3iB!!!J!%!5$JK!%"m#!1QJq(rr)2"rrK1J!!J!*!')%' !!J#3"E3!#bjMEh"j9M4$FQ9N!!!!I!J#TT2Krrb6`IriN!!"!!L8)Iq`I(mEH*! !J3"XN!#K!(!l`!!!1'!!!*!!B3!i+"m!!%##!!`iB!!+5!!"!)#"!'`X"!!"3B) !')#K!'`X"3!#3B)!$$KJ!"")!!$JU0m#"$M'!!'`h`)%U2m#"(cR"c5T(`)'I!G !!%##!&bT2`)'95N)2,%r!JDTA`)'98-31N[rpNemIKYi+"i!!%##!!`iB!!'5!! !P(r$mhL!R`))UAm#"ReV$R"pD`'89@831NJ!$Af!33!8J(m##%[rp&'6h`))JB% !E#`-!!&!JJ!BJ'%!E)#"!(!iS3!i5rrq38J!!#b!B3"X,!-!!N##!"L!B3"XJ)% !F$LK!$K,rraT5!!!$$KJ!"")!!!JJ)%!1)#r!JLSh`)%1-Erre6'%$TmK6%Z1'! !!)!"!&Ji)3"3I!J$TS2Krrb$`Iri6S!!)!#3"L""J!)!N!3"8!!4,Q0bC@4#G@C QCA**ER0PFR3!I!J#TT2Krrb6`IriNk(rp*1"rr#3!!%!#*3Krl"mIKYiN!#"!'b 3!+%!F$Z!!!!S(J!!3))!$$KJ!!T)!!$31k!!!%J!!,L!IJ))9k331RaM)#k!J`! %J'-!!)#K!'b!`3"`5!!#,@!!!!"mB`Gd,!-!!%'#!)5![J))9kB31Rq&-#jrJq0 i5!!)m@!!!!"rJq0i5rrc'AqrkhK)!!!NJ2i##$NI!!&9#"!kI1G!,S%q!JKAkK! kI1P4,M[r!!'TIJ)%1@[rrh`I@!""J2r81B!!!)"q!JLSRJ)%1)6rre5%%$TpJb% ZU,i#"$LPrrq`[J)%5!!!&$Zp!!'ShJ)%I"d`!%'!rd3iB!!!J!%!@$JK!&"m#!1 QJq(rr)2"rrL$SIrdJi(rm%k!!#!!N!BJ3B!%!*!%!5J!%5jMFQ9N3R9QCQ9b8Q9 YEhCP!(`)!UDr3IrSN!!"!!L8)IqJI(SEH(bF)hJl`J)j1k)"aB2L!#`iB!!!N!" K!$JS(!!!3))!K)#I!!!X"!!"3))!)(r$mhKrT1Yi1+!"5$M!!!")!!T9J%%!&%J !!&b![`!!,!8!!N##!"4r`r0i5!!+8B""!"4)!!"!J0m!!#`'!!0!JJ!35!!+8B" "!"4)!!!SJ2m!!#`(!!4!JJ!FIm2cH(qNkhJiS!&)1-!!!8J!#IQ!33!8+"`!!%# #!!`iB!!-5!!!5$YJ!!")!!!SJ4`##&GT%$Tp#%JZN3%!1(p$dhJiJ3!i5rrYB@! !!!!lH`!"U9`#"(`E8!""J2r8J(`##%[rm9diB!!!J!%!D$JK!'"m#!1QZd(rk%k !!#!!N!BJ3B!'!*!%!4`!%LjNDA0`Eh0P3h*PC%*eCQCPFR`)!UD6iIrmNm(rq*1 Krr56JIr`N!!"!!L8)Iq`N!"K!'L3!)%!E*!!S3"`N!$"!(5!B3"X+!-!!%'#!"# !J3"d+!3!!%##!!`iB!!!5!!"!)#K!'L!`3"`I!8`!%'#!!`iB!!!5!!!k)$K!'J X"`!"3))!G)2K!'b$`3"d1(m!!6LH!!&)!!S&J%%!&#`$!!"!JJ"-1(m%icLH"10 )!!RYJ%%!&#`$!!"!JJ!d1(m6L6LH%iP)!!R9J%%!&#`$!!"!JJ!FJ4mBI)%q'(a m#%J!3))!$$KJ!!&)!!"d1'!!!%J!!'b"33"S,!S!!N##!&b$S3"XJi%!G)"p!!# !R!!!5!!*LB""!"3X!`!!3))!0)"p!!5!R!!%5!!*FB""!"3X!`!!3))!()&p!"L "R!!BI!YJ!%##!!`iB!!"5!!!%$KJ!!")!!!)1'!!!)!"!&Ji)3"3I!J$TS2Krrb $`IriJk(rp)1"rr"1J!!J!*!')%'!"!#3"!&S!!JZBh*PC'0YF!!!I!J#TT2Krrb 6`IriNk(rp*1"rr#3!!%!#*3Krl"mI4YiI*`MH$[!!!!S(!!!3))!$$KJ!!C)!!) 81'!#+%[rlZ'3!(`!!)"m!!!S!`!!3))!$$KJ!!C)!!(dJp`!!(r$mhKrT1Yi5!! )*B""!"5!R3%!N!#H!3!iIJ%%1*d""%J!#!f!33!8U,d#",#q!J5Sh3)'X0i#"MM J!!'BrJ)3U4i#"P8$%$T,rqjjN!"q!JL"2J))+!N!!%##!!`iB!!'5!!"M$[J!!" )!!&SJ9d##&IV%$Tp5PJZJ8S!!#`+!!&!JJ#`1'!!#%[rlMQ"RJ))9q331RaX)5k ![J))9qB31RbP-#iS"3!!3))!$$KJ!!C)!!%m11!!!B%H!JKAk4!kI3K),T!!k!! !1'!GJ%[rlI@"AJ))9qX31Re+@#k3!'S!")'H!JKAia!kIB`B,S'-!!3S$!!!3)) !$$KJ!!C)!!$`J*i##&IP%$TmK#JZJ'3!")$G!JKAja!kI-Bi,S#'!!3iS"f!5!! (1B""!"4)!!#JJ4d##&IT%$Tp#%JZJ3J!!#`)!!*!JJ!XJ9d##&IV%$Tp5PJZJ'S !!)#+!!5"RJ))9qB31RbX-K4,rrBY5!!!B)$p!JKAk"!kI1G!,S$R!!!X"`"M3)) !5$KJ!!K,rqdeJ6i##&IU%$TmD9%ZJAi##&IX%$TpDf!Z+!X!!%##!!`iB!!'5!! !1$KJ!'1!RJ))9q831Rb%+#k3!'3!!$[r!!'ShJ)%I"m`!%'!rT3ii!!!N!$q!L5 3!2i#)$KJ!!#!!3"B1#%!8(`)!kD$iIrmJm(rq)1Krr5$JIr`6S!!)!#3"L""J!3 !N!3#D!!',Q4eF%j$I!J#TT2Krrb6`IriN!!"!!L8)Ir!I(iEH(rImhJS(`!!3B) !,%J!!"5!R`!!J'3!#%[rl1Nlr`!%J,m!!#J&!!"!J[rSIm2cH%[rl0'!!3")1#% !3(`)!kD$iIrmJm(rq%k!!#!!N!BJ3B!#!*!&C!!4,Q4TFh"[Ff9%BA4K3A*bBAN !I!J#TT2Krrb6`IriNk(rp*1"rr#3!!%!#*3Krl"mI"Yi1m)#4$ZL!F@$iJ!X+"` !!%##!*L!I`!!,!-!!8##!#"r`r0iIk6VH$LJ!F)i`!!!5!!%LB""!"4)!!"`J*m !!#`%!!*!JJ!8Im2cH%J!")@!33!85!!!9)#r!!!X"3!$3))!%%J!")@!33!85!! !2)$I!!!X"J!%3))!-(r$mhKrT1Yi1+!"`MM!!!&)!!3YJ%%!&%J!!"4rJq0iIi6 MH%[rfIPJ!!!!J2`!!#J(!!"!J[rS1'!!!)!"!&Ji)3"3I!J$TS2Krrb$`IriJk( rp)1"rr"1J!!J!*!')%'!"!#3"IJ!#bjQFQ9P6N0-DA0d!!!!I!J#TVpKrqb3!!% !#*3Krk"mI"Yi1m)"hcZL!F@$iJ!X+"`!!%##!)5!I`!!,!-!!8##!#"r`r0iIk6 VH$LJ!G)i`!!!5!!$IB""!"4)!!"FJ*m!!#`%!!*!JJ!8Im2cH%J!!hQ!33!85!! !3)#r!!!X"3!$3))!%%J!!hQ!33!85!!!+)$I!!!X"J!%3))!((r$mhKrT1Yi1+! "dMM!!!&)!!-KJ%%!&$KK!$K)!!,0J%%!&(al'hKrC`Fd,!F!!%'#!!`iB!!!5!! !5)%F!K3X#!"N3B)!-$KK!$JiR!)B1+%!3%J!!Uf!33!8I(XEH(pT"c3X#3!!3B) !&$KJ!!")!!!318!!!*P"!%#)B3"!J!%!D$JK!'"m#!1QZf(rl%k!!#!!N!BJ3B! &!*!%!53!#bjTFda[BfY2GA*c!!!!I!J#TVpKrqb3!!%!#*3Krl"mHaYi1m)#9cZ L!F@$iJ!X+"X!!%##!)5!I`!!,!-!!8##!#"r`r0iIk6VH$LJ!HFi`!!!5!!#1B" "!"4)!!"FJ*m!!#`%!!*!JJ!8Im2cH%J!!M@!33!85!!!3)#r!!!X"3!$3))!%%J !!M@!33!85!!!+)$I!!!X"J!%3))!((r$mhKrT1Yi1+!"jcM!!!&)!!(GJ%%!&)$ l!!!X"`!#3))!I)1E!!5!I!!!5rrTHB"m!!4,rqPaJ4`!%#J)!!""JJ!-J(`!%%[ rk9f"2!!i+!N!!%'#!!b!I!!i5rrT5B&F!%3S#J!!3B)!$)"m!%4,rqNeJA`!5#J ,!!""JJ!-J(`!5%[rr!Q"R!!X+!`!!%'#!!b!I!!X5rrlpB"l!!4,rqN&1'!!!)! "!&Ji)3"3I!J$TVYKrqa1J!!J!*!')%'!"3#3"!&-!"FZBf0ICR*PC9pMFQ9NAfP ZG'9bEQ&XF`!!!(a$%hK1J!!JI!J#TT!!!3!)P#(r`%[rrqemD4YiJ')!D)##!'3 iSJ!!1-)#CB$L!&L"!J"85!!!@B""!"5!JJ#XN!"N!!",rp"TB!!!!$KJ!!#!!3" )1#%!3(`)!kC1J!!JI!J#TT!!!3!)P#(r`)"L!+b!B`!!5!!!-B""!"5!!3")1#% !3(`)!kC1J!!JJB)!1*!!33!8J!`!!)"-!!4m#31Q6S!%))'#!$53!%%!&)!-!!# !6!!%I!N$TNk!"##"JJ!JN!""!"5!$!!!J%`!"(`*!kC1J!3JJB)!(*!!33!8J!` !!)"-!!4m#31Q6S!%))'#!"#3!%%!&)!-!!#!6!!%I!N$TNk!"##"JJ!`N!""!"5 !$!!!J%`!"(`*!kC1J!3JJB)!&*!!33!8J!`!!)"-!!4m#31Q6S!%))'#!!#3!%% !&)!-!!#!6!!%I!N$TNk!"##"JJ!BN!""!"5!$!!!J%`!"(`*!kC1J!3JJB)!8*! !33!8J!`!!)"-!!4m#31Q6S!%))'#!!L3!%%!&)!-!!#!6!!%I!N$TNk!"##"JJ! NN!""!"5!$!!!J%`!"(`*!kC1J!3JJB)!5*!!33!8J!`!!)"-!!4m#31Q6S!%))' #!!b3!%%!&)!-!!#!6!!%I!N$TNk!"##"JJ"!N!""!"5!$!!!J%`!"(`*!kC1J!3 JJB)!"*!!33!8J!`!!)"-!!4m#31Q6S!%))'#!%53!%%!&)!-!!#!6!!%I!N$TNk !"##"JJ!mN!""!"5!$!!!J%`!"(`*!kC1J!3JJB)!6*!!33!8J!`!!)"-!!4m#31 Q6S!%)!!!,eb!!!"B!*!',l5!!!!X!*!&9L)a`!)L-DJ#)J*PKJ)"-F!L!D@#!K% "P3'-!Am#9`*%!MN#)J)6!J-"pJ(U!Gm"dJ(&!EF!Y!&`"#)9+)B#&44d%rJ6N!! 6*"(!$bJ1#!e-$*J,a!T-#A!)H!JJ"MJ%l!0`!F!"0!!F&d`L&X3%,Ne*9#"*,e- J6@&M4'9f!5#"CJ`K+'jKE@8J)6dJ-#N)3d0KBfKP,Q-2)5JUD'&ZC'aP)#%p)$! T%5%SF(*TEQ0TF'&X)#%p)$!T$5%SFf&QC9!J)6dJ-#N-3d0KBfKP9A4TE#jM$#% SFfPkC5!q)$"-+3SK+'jM)#%p)$!T#b%SEf*U)#%p)$!T$#%SC'9cG#!K25!`+3p bCA4NCA0d)$dp)%j96%`1+LTNCA0d)$dp)%j96%`@+#SUC'9cG#NY2Q4KG'%J26d J6P9-6!TZBb!p25"198a-%L%SBfjdFQa#E'pMDb!K25!`+3dK+'0bC@4c)#%p)$! T1k3!!!%!!!!"C!!!!'3!!!!bC@*eCcSf1%XJ3fpNC8GPEJ"0593J8R9ZG'PYC9" 33b"%6%`ZC'9LG@Fk0MK,)%4TFf&cFf9YBQaPFJ"0593J8R9ZG'PYC9"33b"%6%` ZC'9LG@Fk0MK,)%GXEf*KE#"2F(4TE@PkCA)!68P8)&*eER4TE@938%-J4%a-,Q4 PBR9R1MBi5b"-D@jVCA)!68P8)&*eER4TE@938%-J4%a-,Q4PBR9R1MBi5b"3FQp UC@0d!%e*9#"5G@jdD@eP8&"$)%4-6#jNC@*eCcT$,d-V+b"$Efe`D@aPFJ"0593 J8R9ZG'PYC9"33b"%6%`ZC'9L!!!!B!#3#`%!N"-"F(G`B`#3%`%!N"&!&%e*9&q P3d0KBfKP6'PL,Q4PBR9R!!!!!3!!!!&N!!!!C!!!!$)&9MR30#B!!!!F!$)!!'0 QFQF!!!!+!!$rr`#3"!9EF&b1RJ: \ 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
index f758c14f3a..0000000000
--- a/src/mac/libraries/CCache API/include/CCache.h
+++ /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
index 23426fc67e..0000000000
--- a/src/mac/libraries/CCache API/include/CCacheUtil.h
+++ /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
index 82cced375f..0000000000
--- a/src/mac/libraries/CodeWarrior Dependencies/Pro2.prj
+++ /dev/null
Binary files differ
diff --git a/src/mac/libraries/CodeWarrior Dependencies/Pro4.prj b/src/mac/libraries/CodeWarrior Dependencies/Pro4.prj
deleted file mode 100644
index 445248db6d..0000000000
--- a/src/mac/libraries/CodeWarrior Dependencies/Pro4.prj
+++ /dev/null
Binary files differ
diff --git a/src/mac/libraries/DES/bin/deslib.68K b/src/mac/libraries/DES/bin/deslib.68K
deleted file mode 100644
index eb4f909081..0000000000
--- a/src/mac/libraries/DES/bin/deslib.68K
+++ /dev/null
@@ -1 +0,0 @@
-(This file must be converted with BinHex 4.0) :#Q4PFfaTBLif1%X!FfKXBMq3"!#3")8`!!!"MQI+5Qpj)A"PCQCY0MKV!!!!!E* @K3m!N!d$!!)!N!j8UJ!!9+S!!&5U!!!!P!!"!J#3"!8!N!BZB!!!,Q!!!#VF!!" 93!)"!J#3"!i!N!i&&!!!J"`%!3)!6@&TEJ!P369AEh*XC!"-Ef&NCA)!N!41G5T 46PErq#m0)!d[!#mYre`LEIp))&P1N!!UE[rd+d$r$'(rN!6FF!"1ANjd!!3U88j @rrJ[$5mYr``LEIp%)&P1N!!UE[rd6Pj1G5T46PErq%MR%!4f!#mZ!!JLEIpB)&P 1N!!UE[rd0J!`!dM!C`3`!f!#-!-Q(djH6R3!"*0IAfPZDA4TB@aTHQ9IC'9cE'P L!!!U88j@rrJ[$5*Yre3J@8k3!#TZrr41ANjeNPpIG'9bE@PZBA4PAf4PFfaTBJ! !!#T46PEri%MR(c`X,J!)*Li!$#iZ!"!SEJ!B*'i!&%UZ!"aR!!8@*Nak!"SEFKM MVA!!%"Yb%11SLS"`!"!EiBL+J(!!%"Z+J(J!'"Yb'11XF!!3'h)3ikL)J(!!%"[ KL)L!F!!3'iL!*NBS3f!!"-*`#,k!EAT`!"!E!S!!!!$rFKMMU,'&F!!3'`+!!!! !rh)3ikLaKA!!%"X#J!!!!2rKL,'&F!!3'`+!!!!!rl'&F!!3'`+!!!!!rh)BikL aK(!!%"X#J!!!!2pb%11SXB4`!"!E!S!!!!$riBLaK(!!%"X#J!!!!2qaK&'(B!! !NYI()!F-J!!!!!GL!!##-$X#"Nll!!)!H!"S!&J!5J!q!#i!(J!3F!!3)`+!!!! !rq')XB4`!"!M!S!!!!$rFK$MU,'%F!!3)`+!!!!!rh)BikLaK(!!%#-#J!!!!2q aKA!!%#-#J!!!!2rKL,'&F!!3)`+!!!!!rh)3ikLaKA!!%#-#J!!!!2pb'11SXB9 q!#!%!S#UN!6LL#B&!S1UN!5'J#!%!S"9N!3L"3+"9C!%dS'#J#J"+J4b%1+Y!S8 !!!$r)'hrr#S`A!$DK5)%G"MNU3+"!!!!rb"Yrrb+X"`!)J6JL3+"!!!!rb"Yrr` L-"`!jBQ#K5S%!S8!!!$r)'hrr#S`A!$RMBU"+!0b%1+X!S3!!!$r)'hrr#J`6!$ BK#)$G"MNU3+"!!!!rb"Yrrb)X"`!)J2JL3+"!!!!rb"Yrr`L-"`!jBQ#K#J$!S3 !!!$r)'hrr#J`6!$RM)L"I!"J!!'B*J4b&H1V)J4d#q5TJS-Q'V1$F$mL!h3Bj+R #J#"YrrK`2b3$,8$ri(!3i+V%V[rJjBSLEIridm)J+3%!J,!F!()r*!2JLX5"jBS JEIridF+!U!)!FMr#Jq@*)'hrq0("J+J$!,'&*J4b#H1V)J4d&q5TJS-Q'V1$F$m L!h33j+R#J1@*)'hrq0("F$mL!h3Bj+R#J1@*)Qhrq02")#N%!)#S"3"b2b3$i)V %JH@+)'hrq0(#J+J'!()r`S2PL5"YrrM4`B#S"`#aK5B&FKAMUb)&G![NUB+$*KU cJh!r)J0d'15T`S!JEIriF$mN!be!rq"`%1#Ua+lri1@+)Qhrq02#)#N"!)#`(!" b2b3$i)V%JH@+)'hrq0(#J+J#!()r`S2PL5"YrrM4`B#S!`#aK#B&FJRMUb)&G"I NUB+$*KUcJh!r)J0d%15T`S$PL5"YrrM4`A!r)J0d'15T`S$PL5*YrrM6`5!T"!# !U!8!FMmN!q#+a)(PLL"YrrM4`S#S"J"b2m+$jBNJEIridF'!U!F!XB45KR!)[)" Y!2jN)!8#J2#3"1L)*J3#Jr#3")D!)!8#J!q3"#)%!S%2N!6TLB+!+!%U"()3iUd #K3!!!2mJEIrd+M"F!1Q0)J4d'15T!S%!!!$r)'hrp#)`(!$YLB+&+J6JM3+&!!! !rb"Yrr3U-&`!jBf+J5)%!S%!!!$r)'hrp)U`(!!S!h)3iU`#K!!!!2mJEIrd+$" -!1Q-)J0d'15T!S%!!!$r)'hrp#)`(!$YLB+%+!2JM!+%!!!!rb"Yrr3S-%`!jBb )J5)$!S%!!!$r)'hrp)L`(!"&k[q!)!9b'1+S!S!!!!$r'-!J"A)3iUJ#J!!!!2m B`#!&i)J#J!!!!2mB`#!&!S!!!!$r'-!J"()BiUJ#J!!!!2mB`#!%FK$LU!+!!!! !raM!)!6JL!+!!!!!raM!)!3#J!!!!2mB`%U(EJ$l2'!!"6j+Kfi'F!"J!!8f*Na `!"!EFKMMU#e!rr4`!"!EFK$MU)'Zrr4`!"!EiBL"V[rdF!!3'i'Zrr4`!"!EFKM MU#e!rr"`!"!EFK$MU)'Zrr"`!"!EiBL"V[r`F!!3'i'Zrr!Q4LK$HJ!D'h)Bike `!"!EFK$MU)U!F!!3'q')LS"`!"!ELS"i!"JEFKMMV(!!%"Yb%11SL)"`!"!EiBL )J(!!%"Z)J#e&rq`Y42rS)!3#J+U3"1+)*J8#JkU3")D!)!3#J&@3"#)&!S&9N!6 5JB+!+!%U"()3iUd#K3!!!2mJEIrm+M"F!0U&)J4d'15T!S%!!!$r)'hrr)U`(!! L"1#*!S%!!!$r)'hrr#)`(!$PLB+&+J3#K3!!!2mJEIrm+M"F!1H0LS%S!h)3iU` #K!!!!2mJEIrm+$"-!0L%)J0d'15T!S%!!!$r)'hrr)L`(!!L!q#*!S%!!!$r)'h rr#)`(!$PLB+%+!-#K!!!!2mJEIrm+$"-!1H-L)&&kJ#!I!"J!!()*J4b#H1V)J4 d&q5TJS-Q)V1$F$mL!q#*`S$PL5"YrrM4`A!r`)2PL#*YrrM6`#!T"`#!U!B!FMm N!be!rq"`%1#Ua)(PLL"YrrM4`L!S"3#!V[rJFMmN!be"rq4b'1+Ua+lrj1@+)'h rq0(#J+J%!,'&*J4b&H1V)J4d#q5TJS-Q)V1$F$mL!h3Bj+R#J#"YrrK`2b3$i)V %J1@+)Qhrq02#F$r!Jq@))M!F!#"YrrM4`#!S!`#!U3)!G$mY32rN)!-Y3IrJFK$ LU-##jBJJEIridF!J+!%!J+lrj)#Zrq#aK5B&FJRMUb)&G"INUB+$*L+cJh!r)J2 JLF+!jBNJEIridF&`2m#$jBJLEIridm!J+3F!J+J'!()r*!-Y32rNF"$JUX5"jBS JEIridF)J+!8!J+lrj()r*!-Y3IrJFKMLUX5Zrq$PLL"YrrM4`S#S"!#aK#B&FKA MUb)&G![NUB+$*L+cJh!r)J0d'15T`S!JEIriF$mN!q#+a)$PLL*YrrM6`R!r`)2 PL#)`(!!JEIridF!J+!-!J+N#!(3r,8$rj#!$,8(ri()3iUM!JZ@))'hrq0(!)#J "!)#Zrq5!V[rJXB45KR!)[)"Y!2id)!8#J2#3"1L)*J3#Jr#3")D!)!8#J!q3"#) %!S%2N!6TLB+!+!%U"()3iUd#K3!!!2mJEIrd+M"F!1Q0)J4d'15T!S%!!!$r)'h rp#)`(!$YLB+&+J6JM3+&!!!!rb"Yrr3U-&`!jBf+J5)%!S%!!!$r)'hrp)U`(!! S!h)3iU`#K!!!!2mJEIrd+$"-!1Q-)J0d'15T!S%!!!$r)'hrp#)`(!$YLB+%+!2 JM!+%!!!!rb"Yrr3S-%`!jBb)J5)$!S%!!!$r)'hrp)L`(!!J,[rdXB8J,[r`XB4 `#,k!EhC4Kb!&FKMLU!+!!!!!raM!)!9b%1+S!S!!!!$r'-!J"H#)!S!!!!$r'-! J"3+!!!!!raM!)!4b'1+S!S!!!!$r'-!J"()3iUJ#J!!!!2mB`#!%i)J#J!!!!2m B`#!%!S!!!!$r'-!YE[rXrr3YE[rSrr"J!2ZffFFJ"`b!!!!!#')!!)!`1`)'6[X !!J"f!'J!@J"1!%3!0J!S!"`!%L!%!S!!!!$r'3!J"1#)!S!!!!$r'3!J"()3iUJ #J!!!!2mC!#!%FKMLU!+!!!!!raN!)!8#J!!!!2mC!#!&i)J#J!!!!2mC!#!&FK$ LU!+!!!!!raN!)!9b'1+S!S!!!!$r'3"`!%cI(2K1ANjd!"L2C'9cAf0LBepPEQ0 bHA"d!!!U88j@rr4)jamm+'i!&#CZ!"Kk!"SEFKMMVA!!%"Yb%11SLS"`!"!EiBL +J(!!%"Z+J(J!'"Yb'11XF!!3'h)3ikL)J(!!%"[KL)L!F!!3'iL!*Qi!##iZ!"" J!!4JF!LqJ'ekF!!3'`+!!!!!rh)BikLaKA!!%"X#J!!!!2pb%11SXB9`!"!E!S! !!!$riBLaKA!!%"X#J!!!!2qaKA!!%"X#J!!!!2pb'11SXB4`!"!E!S!!!!$rFK$ MU,'%F!!3'`+!!!!!rq')XB4`!"!E!S!!!!$rXB44Kf!!!*,Aab!($)!!!!!(BJ! !JM!l!JC1q`!#!(J!D!"B!%S!2J!Z!"i!%(!!%#-#J!!!!2rKL,'%F!!3)`+!!!! !rh)3ikLaK(!!%#-#J!!!!2pb'11SXB4`!"!M!S!!!!$rXB9`!"!M!S!!!!$riBL aKA!!%#-#J!!!!2pb%11SXB9`!"!M!S!!!!$rFKMMU,'&IJ!N6#!%!S#UN!6LL#B &!S1UN!5'J#!%!S"9N!3L"3+"9C!%dS'#J#J"+J4b%1+Y!S8!!!$r)'hrr#S`A!$ DK5)%G"MNU3+"!!!!rb"Yrrb+X"`!)J6JL3+"!!!!rb"Yrr`L-"`!jBQ#K5S%!S8 !!!$r)'hrr#S`A!$RMBU"+!0b%1+X!S3!!!$r)'hrr#J`6!$BK#)$G"MNU3+"!!! !rb"Yrrb)X"`!)J2JL3+"!!!!rb"Yrr`L-"`!jBQ#K#J$!S3!!!$r)'hrr#J`6!$ RM)L"I!"J!!'B*J4b&H1V)J4d#q5TJS-Q'V1$F$mL!h3Bj+R#J#"YrrK`2b3$,8$ rp(!3i+V%V[rdjBSLEIridm)J+3%!J,!F!()r*!2JLX5"jBSJEIridF+!U!)!FMr #Jq@*)'hrq0("J+J$!,'&*J4b#H1V)J4d&q5TJS-Q'V1$F$mL!h33j+R#J1@*)'h rq0("F$mL!h3Bj+R#J1@*)Qhrq02")#N%!)#S"3"b2b3$i)V%JH@+)'hrq0(#J+J '!()r`S2PL5"YrrM4`B#S"`#aK5B&FKAMUb)&G![NUB+$*KUcJh!r)J0d'15T`S! JEIriF$mN!be!rr4`%1#Ua+lrp1@+)Qhrq02#)#N"!)#`(!"b2b3$i)V%JH@+)'h rq0(#J+J#!()r`S2PL5"YrrM4`B#S!`#aK#B&FJRMUb)&G"INUB+$*KUcJh!r)J0 d%15T`S$PL5"YrrM4`A!r)J0d'15T`S$PL5*YrrM6`5!T"!#!U!8!FMmN!q#+a)( PLL"YrrM4`S#S"J"b2m+$jBNJEIridF'!U!F!XB45KR!)[)"Y!2jN)!8#J2#3"1L )*J3#Jr#3")D!)!8#J!q3"#)%!S%2N!6TLB+!+!%U"()3iUd#K3!!!2mJEIrd+M" F!1Q0)J4d'15T!S%!!!$r)'hrp#)`(!$YLB+&+J6JM3+&!!!!rb"Yrr3U-&`!jBf +J5)%!S%!!!$r)'hrp)U`(!!S!h)3iU`#K!!!!2mJEIrd+$"-!1Q-)J0d'15T!S% !!!$r)'hrp#)`(!$YLB+%+!2JM!+%!!!!rb"Yrr3S-%`!jBb)J5)$!S%!!!$r)'h rp)L`(!"&k[q!5SGZ!2ZH*Qi!$#!&FKMLU!+!!!!!raE!)!9b%1+S!S!!!!$r&X! J"H#)!S!!!!$r&X!J"3+!!!!!raE!)!4b'1+S!S!!!!$r&X!J"()3iUJ#J!!!!2m @`#!%i)J#J!!!!2m@`#!%!S!!!!$r&X!J"%cI(2K1ANjd!"50C'9cAf0LBepMDh0 eE3!!+P&19[r`51FH-#CZ!"!NEJ!)HJ!D'R)Bike`!"!DFK$MU)U!F!!3'Z')LS" `!"!DLS"i!"JDFKMMV(!!%"Tb%11SL)"`!"!DiBL)J(!!%"U)J#!%!S#UN!6LL#B &!S1UN!5'J#!%!S"9N!3L"3+"9C!%dS'#J#J"+J4b%1+Y!S8!!!$r)'hrr#S`A!$ DK5)%G"MNU3+"!!!!rb"Yrrb+X"`!)J6JL3+"!!!!rb"Yrr`L-"`!jBQ#K5S%!S8 !!!$r)'hrr#S`A!$RMBU"+!0b%1+X!S3!!!$r)'hrr#J`6!$BK#)$G"MNU3+"!!! !rb"Yrrb)X"`!)J2JL3+"!!!!rb"Yrr`L-"`!jBQ#K#J$!S3!!!$r)'hrr#J`6!$ RM)L"5Ui!&'F!!D`N5h`!B!!"Q#B%FKAMUb)%G![NUB+$*KUcJh!r)J0d'15T`S! JEIriF$mN!be!rr"`%1#Ua+lrm1@+)Qhrq02#)#N"!)#`(!"b2b3$i)V%JH@+)'h rq0(#J+J#!()r`S2PL5"YrrM4`B#S!`#aK5B%FJRMUb)%G"INUB+$*KUcJh!r)J0 d%15T`S$PL5"YrrM4`A!r)J0d'15T`S$PL5*YrrM6`5!T"!#!U!8!FMmN!q#+a)( PLL"YrrM4`S#S"J"b2m+$jBNJEIridF'!U!F!XB8Q"A)9ikXL"A3,j+Q#JbBDXi0 `2b)$G"MNUF+!)'hrq(!r*!-Y32r`F"$JUX5Zrr$PLL*YrrM6`L!T!3#!X"`!FMm N!q#+a)(PLL"YrrM4`S#S!J"b2m+$jBNJEIridF'!U!-!XB3Q"A)*ikXL"A3Aj+Q #JbBDXi0`2b)$G"$NUF+!jBNJEIridF&`2b)$G"MNUF+!jBNLEIridm%J+33!J+J &!()r*!2JLX5"jBSJEIridF+!U!B!FMr#Jq@*)'hrq0("J+J(!,'%8SC`#,b!E3$ qC'!!!G`N5dAU!)"m!'!!!FJQ"()*ikXL"(3Aj+Q#JbBLXi0`2b)$i)R#J1@*)'h rq0("F$r!Jq@))Qhrq02!)#N(!)#S"J"b2b3$,8$rm(!3i+V%JH@+)'hrq0(#)#J &!)#Zrr"b2b3$,8(rp()BiUV%V[rdjBSJEIridF+!U!3!XB8Q"()9ikXL"(3,j+Q #JbBLXi0`2b)$G"MNUF+!)'hrq(!r*!2JLX5!jBSLEIridm*`2m#$jBJL-"`!)'h rq0(!)#J$!)#T!J"d2be!rr3J!be"rr"b%1+S`),PL#"YrrM4`#!S!3#!V[rdJ+l rm,'&*J9b#H1V)J9d&q5TJS-Q)V1$F$mL!q#*`S$PL5"YrrM4`A!r`)2PL#*YrrM 6`#!T"`#!U!B!FMmN!be!rr4`%1#Ua)(PLL"YrrM4`L!S"3#!V[rdFMmN!be"rr" b'1+Ua+lrm1@+)'hrq0(#J+J%!,'%*J9b&H1V)J9d#q5TJS-Q)V1$F$mL!h3Bj+R #J#"YrrK`2b3$i)V%J1@+)Qhrq02#F$r!Jq@))M!F!#"YrrM4`#!S!`#!U3)!G$m Y32rd)!-Y3Ir`FK$LU-##jBJJEIridF!J+!%!J+lrp)#Zrr#aK&+'F!LmJ'd!rM3 J"3+!m*!%k)JQ"!+$m*!%KS!J"3+!$j!%)J3#J3q3"1Q*JS!S!5S%FK$LV3+&!!! !rb"Yrr3U-&`!kBdL"(3Bj+N#J3!!!2mJEIrd)M!F!1f*JS8U"1#0!S8!!!$r)'h rp#S`A!$PMBU")J3#J3!!!2mJEIrdLV!F!#J$FK$LV!+%!!!!rb"Yrr3S-%`!kB` L!h3Bj+N#J3!!!2mJEIrd)M!F!1f*JS3S!q#-!S3!!!$r)'hrp#J`6!$PM)L")J- #J3!!!2mJEIrdL,!F!#4Z!!`J"A)BiUJ#J!!!!2m8`#!&FK$LU!+!!!!!ra6!)!A JL!+!!!!!ra6!)!8#J!!!!2m8`#!%FKMLU!+!!!!!ra6!)!4b%1+S!S!!!!$r&-! J"1#)!S!!!!$r&-!J"!+!!!!!ra6!F!"-h`ai6Pj1G!!3Mf4PFepPBf*IC@jMFRP `G!!!+P&19[rF,`-JEJ!)GJ"J!!$+!M!!rMJ!F!&b!h32,8$rh(!!%$!i!1L!`)) 8-$J!!S)!!!!2XB,NJX5"F!0b$be"rq"b!")`1!$SJF+Zrq!Y3[rN&$!i!!+#!!! !$l1#a)!J,[rNXB,LJX5Zrpa`!A)$,8$rk(!!%$!i!1L!!S!!!!!2,8(rl")`1!! #J3!!!!qaJH5"`Ulrl(!$,8,rm(3!&$!i!1L#!S)!!!!2,8$rp"!`1!!#J!!!!!q eJ-#Zrr5cJ-#ZrqJL,[r`Xi!+J!!!!!'"-$J!8S0`#,D!C3$r-LBI6Pj1G!!%P'4 PFepQDAKeF&pVCAPIF'&bDA4j!!!!+P&19[rB,`-JEJ!)GJ"J!!$dF!&b!h32,8$ rf"!`1!!#J!!!!2lSJ-##G!mY3IrF%M!i!!+"!!!!rX+#XB(NJF+Zrpa`!h32,8, ri"3`1!!#JJ!!!2lSJX5Zrq!Y32rN%$!i!!+!!!!!rJ+!!!!!$l@!`+lrj,1!iS$ !V[rBFJ&d!be"rqJ5-$J!!S%!!!$qk)%#J3!!!!mY3[rX&$!i!!+#!!!!rJ+#!!! !$l1#j),%V[rXFJ-Y32r`%$!i!!+!!!!!rZL!!S!!!!!2,8(rp")`1!!#J3!!!2i #J3!!!!qaJF+Zrr5eJF+ZrqJJ,[r`XB%3-$J!G!(!JV#"CJ4`!'!-8S0`#,D!C3$ r#(!"*Kp1ANjd!!58C'9cAf0SC@0VAfYPH9p`BA*TG(N!!!!U88j@rq")jamm,#i !##BZ!!`SEJ!B*'i!&%UZ!"aR!!8@*Nak!"SEFKMMVA!!%"Yb%11SLS"`!"!EiBL +J(!!%"Z+J(J!'"Yb'11XF!!3'h)3ikL)J(!!%"[KL)L!F!!3'iL!*NBS3f!!"-" `#,#Z!""X@Ri!(KYb'11[F!!3'h)3ikL1J(!!%"[KL)k!F!!3'ik!F!!3'h)BikJ Y32rdF!!3'h)3ikL"V[rdF!!3'q')JDlrp(!!%"Z"V[rd[i8J,[rdXB44VJ!3B!! !TYIZ!"!J,J!3$)!!!!!)BJ!!N!!`1`)'6[X!!J#'!(B!CJ"B!%`!2!!X!"i!%R! !%#-#J!!!!2qaK(!!%#-#J!!!!2rKL,'%F!!3)`+!!!!!rh)3ikLaK(!!%#-#J!! !!2pb'11SXB4`!"!M!S!!!!$rXB9`!"!M!S!!!!$riBLaKA!!%#-#J!!!!2pb%11 SXB9`!"!M!S!!!!$rFKMMU,'&3Ui!%#!%!S#UN!6LL#B&!S1UN!5'J#!%!S"9N!3 L"3+"9C!%dS'#J#J"+J4b%1+Y!S8!!!$r)'hrr#S`A!$DK5)%G"MNU3+"!!!!rb" Yrrb+X"`!)J6JL3+"!!!!rb"Yrr`L-"`!jBQ#K5S%!S8!!!$r)'hrr#S`A!$RMBU "+!0b%1+X!S3!!!$r)'hrr#J`6!$BK#)$G"MNU3+"!!!!rb"Yrrb)X"`!)J2JL3+ "!!!!rb"Yrr`L-"`!jBQ#K#J$!S3!!!$r)'hrr#J`6!$RM)L"I!"J!!'B*J4b&H1 V)J4d#q5TJS-Q'V1$F$mL!h3Bj+R#J#"YrrK`2b3$,8$ri(!3i+V%V[rJjBSLEIr idm)J+3%!J,!F!()r*!2JLX5"jBSJEIridF+!U!)!FMr#Jq@*)'hrq0("J+J$!,' &*J4b#H1V)J4d&q5TJS-Q'V1$F$mL!h33j+R#J1@*)'hrq0("F$mL!h3Bj+R#J1@ *)Qhrq02")#N%!)#S"3"b2b3$i)V%JH@+)'hrq0(#J+J'!()r`S2PL5"YrrM4`B# S"`#aK5B&FKAMUb)&G![NUB+$*KUcJh!r)J0d'15T`S!JEIriF$mN!be!rq"`%1# Ua+lri1@+)Qhrq02#)#N"!)#`(!"b2b3$i)V%JH@+)'hrq0(#J+J#!()r`S2PL5" YrrM4`B#S!`#aK#B&FJRMUb)&G"INUB+$*KUcJh!r)J0d%15T`S$PL5"YrrM4`A! r)J0d'15T`S$PL5*YrrM6`5!T"!#!U!8!FMmN!q#+a)(PLL"YrrM4`S#S"J"b2m+ $jBNJEIridF'!U!F!XB45KR!)[)"Y!2jN)!8#J2#3"1L)*J3#Jr#3")D!)!8#J!q 3"#)%!S%2N!6TLB+!+!%U"()3iUd#K3!!!2mJEIrd+M"F!1Q0)J4d'15T!S%!!!$ r)'hrp#)`(!$YLB+&+J6JM3+&!!!!rb"Yrr3U-&`!jBf+J5)%!S%!!!$r)'hrp)U `(!!S!h)3iU`#K!!!!2mJEIrd+$"-!1Q-)J0d'15T!S%!!!$r)'hrp#)`(!$YLB+ %+!2JM!+%!!!!rb"Yrr3S-%`!jBb)J5)$!S%!!!$r)'hrp)L`(!"&k[q!)!9b'1+ S!S!!!!$r'-!J"A)3iUJ#J!!!!2mB`#!&i)J#J!!!!2mB`#!&!S!!!!$r'-!J"() BiUJ#J!!!!2mB`#!%FK$LU!+!!!!!raM!)!6JL!+!!!!!raM!)!3#J!!!!2mB`,q &)#lrp,'%5Ui!%'i!qcaJ!!8q5Ui!%'i'F!"J!!8d*Naq!"iEFKMMVh!!%"Yb%11 SMS"`!"!EiBL1J(!!%"Z1J(!!%"Yb'11S,8$rm(!!%"Yb%11SJDlrm(!!%"[KL)' Zrr"`!"!EJDlrm#C'+%0k!"SEFKMMVA!!%"Yb%11SLS"`!"!EiBL+J(!!%"Z+J(J !'"Yb'11XF!!3'h)3ikL)J(!!%"[KL)L!F!!3'iL!,8Arl#e%rqJJ"!+!UT!%iSJ Q"3+$UT!%KS!J"!+!9C!%)J8#J9@3"0+"JS!S!5S%FK$LV3+&!!!!rb"Yrr`U-&` !fS8L"(3Bj+N#J3!!!2mJEIrmLV!F!#)%i)N#J3!!!2mJEIrm)M!F!1@*JS8U"!+ &!!!!rb"Yrr`U-&`!jif+J5J$FK$LV!+%!!!!rb"Yrr`S-%`!f)3L!h3Bj+N#J3! !!2mJEIrmL,!F!#)$i)N#J3!!!2mJEIrm)M!F!1@*JS3S!`+%!!!!rb"Yrr`S-%` !jib)J8AU!)"m!'!!!FJQ"()*ikXL"(3Aj+Q#JbBLXi0`2b)$i)R#J1@*)'hrq0( "F$r!Jq@))Qhrq02!)#N(!)#S"J"b2b3$,8$ri(!3i+V%JH@+)'hrq0(#)#J&!)# Zrq"b2b3$,8(rj()BiUV%V[rNjBSJEIridF+!U!3!XB8Q"()9ikXL"(3,j+Q#JbB LXi0`2b)$G"MNUF+!)'hrq(!r*!2JLX5!jBSLEIridm*`2m#$jBJL-"`!)'hrq0( !)#J$!)#T!J"d2be!rq3J!be"rq"b%1+S`),PL#"YrrM4`#!S!3#!V[rNJ+lri,' &*J9b#H1V)J9d&q5TJS-Q)V1$F$mL!q#*`S$PL5"YrrM4`A!r`)2PL#*YrrM6`#! T"`#!U!B!FMmN!be!rq4`%1#Ua)(PLL"YrrM4`L!S"3#!V[rNFMmN!be"rq"b'1+ Ua+lri1@+)'hrq0(#J+J%!,'%*J9b&H1V)J9d#q5TJS-Q)V1$F$mL!h3Bj+R#J#" YrrK`2b3$i)V%J1@+)Qhrq02#F$r!Jq@))M!F!#"YrrM4`#!S!`#!U3)!G$mY32r N)!-Y3IrJFK$LU-##jBJJEIridF!J+!%!J+lrj)#Zrq#aK&+'F!LmJ'd!rM3J"3+ !m*!%k)JQ"!+$m*!%KS!J"3+!$j!%)J3#J3q3"1Q*JS!S!5S%FK$LV3+&!!!!rb" Yrr3U-&`!kBdL"(3Bj+N#J3!!!2mJEIrd)M!F!1f*JS8U"1#0!S8!!!$r)'hrp#S `A!$PMBU")J3#J3!!!2mJEIrdLV!F!#J$FK$LV!+%!!!!rb"Yrr3S-%`!kB`L!h3 Bj+N#J3!!!2mJEIrd)M!F!1f*JS3S!q#-!S3!!!$r)'hrp#J`6!$PM)L")J-#J3! !!2mJEIrdL,!F!,q&)#lrm,'%F!L`VJ!3E(a4VJ!3)!9b'1+S!S!!!!$r'-!J"A) 3iUJ#J!!!!2mB`#!&i)J#J!!!!2mB`#!&!S!!!!$r'-!J"()BiUJ#J!!!!2mB`#! %FK$LU!+!!!!!raM!)!6JL!+!!!!!raM!)!3#J!!!!2mB`#iZrqblKb!ZrqLjJ#e !rr"J!2ZbfHi!%#!Z!"!-J!!!!!KL!!#!-$X#"Nll!!)!GJ"S!&S!6J"%!$B!+!! F!")J"!+!!!!!raN!)!6JL!+!!!!!raN!)!4b%1+S!S!!!!$r'3!J"()BiUJ#J!! !!2mC!#!&!S!!!!$r'3!J"H#)!S!!!!$r'3!J"A)3iUJ#J!!!!2mC!#!&FKMLU!+ !!!!!raN!F!"-haci6Pj1G!!BN!"NCA0IF'0LBepPEQ0bHA"d!!!!+P&19[rS51F I%#*Z!!Kk!"SCFKMMVA!!%"Pb%11SLS"`!"!CiBL+J(!!%"Q+J(!(*J9d&H5VaS! JEIrN*M!m!0D$F!FN"5e!rqK`(H#Ua+lrk#"Yrq5'X#`!F!FN"5e$rqaf$HDUa)! JEIrN*$!X!1@+K+lrl(!(*JAULmD!)'hrj#B`2!$RLiD#F!mS"A34j+c)J#"Yrq! S-%`!f)4`$b3&,8$rl(!Ci+V%V[rX)'hri)L`,!"`$b3&,86rk(J*k+V%J#"Yrq! N-#`!jBU%V[rSF!mS"H+-b)!JEIrJ+$"-!1H-L)*k!"SCFKMMVA!!%"Pb%11SLS" `!"!CiBL+J(!!%"Q+J(!2)J9d&15T`S!JEIrF)M!F!0+"F!mN"5e!rqa`(1#Ua+l rl#"Yrpb#X#`!F!mN"5e"rqKb$1+Ua)!JEIrF*$!X!1@+K+lrk(!2)JASLF+!)'h rh#)`(!$RLB+#KS&`"b)&G"(NUF+!)'hrf#)`(!$5JA!(*!8Y32rXF"RJUX5Zrq` JEIrBJV!X!(!(*!8Y3IrSFJRLUX5!)'hrf#3`,!$PLS5ZrqK`"b)&iSR#J#"YrpJ L-"`!jiQ#JSL")Qi!$#im!!"qr(!3*N"J!!'#F!(!KfFU)!0b'Z+S)J2PL3+"$rr rr)+!*J%J"()DiUJL"1@*!S%2rrrmJS!S!@!S)!0b'q+S)J25J3+"$rrrrS+!*J% J"()EiUJL"0+"!S%2rrrqJS!S!H+(HMmL!h3@j+R#K5"Yrp4k-#3$,8Arl(S3kUV %V[rXHJmYF"`!rqJL!be#rr"d$q5T`S@#V[r`jBNJEIr8dF%U+!%!LUlrk()m*!- Y4IrdHJRUUX5"HJ-L!qL*`S@#JZ@*)'hre0("+LJ#!)UZrr4b1#3$k)V%JA)(`S1 #JZ@*)'hre0("LUJ$!(`r)J4d&Z5T`SBJEIr3I$!N"#e'rr4m$qbUa+lrp(`2,A! F!2r`)J3Y3[rXG!lNUF+'JUlrl1@*)'hrd0(",#J"!)bZrr"b2b3%lSV%JH@+)'h rd0(#M+J#!()m*!6LLX5"FJ2#K)+#jBNJEIr3dF'-U!-!)!B#J2m!!2mL"3+"!2r r!)+!)X%J"J+!!2rr!#)&!S(r!!$rJS!L`91,Y[`!!'i!rRT`!%cI#2K1ANjd!!L 1E@&VC9pVCAPIFf0SC@3!!!!U88j@rrK)j`!N*'i!##mZ!!`[#L*Yrm`J@8k3!#T Zrr3[#L*YrqJJ@8k3!#TZrr4+J'B%F2pJ'#m+)QhrJ#"C6T!!+Qlrp%U!C`4`rQ! #F!!NAdjH6R3!#)eNCA0IDf9jAh0MD'9N!!!U88j@rrK)j`!N*'i!##m+)QhrX#" C6T!!+Qlrp#m+)Qhrl#"C6T!!+Qlrp#m+)QhrJ#"C6T!!+Qlrp%U!CY*`!#4I6Pj 1G!!%NQ4PFepZCAGIFQ&ZC'pYAfYPH3!!!#T46PEri#m0)Qhr6#"C6T!!+Qlrh#e !rqJLEIp-)&P1N!!UE[rF,8$rl#mZ!!JLEIqi)&P1N!!UE[rF5'lrk#*Yrl3J@8k 3!#TZrpa)E[r`)Qhra#"C6T!!+Qlrh%KZrr!LEIqi)&P1N!!UE[rF5'lri#*YrcJ J@8k3!#TZrpa)E[rN)Qhr1#"C6T!!+Qlrh#mYrcJLEIqd)&P1N!!UE[rF5'lrm#* Yrm3J@8k3!#TZrpa)E[r`)QhrZ#"C6T!!+Qlrh%jH6R3!")!JC'9cAfPZDA4IFQ& ZC'pYAfjeE@*PFPpRC@jPFQ&dEh)!!#T46PErq%MR%!3[,Ir!,bi!##*YrmJJ@8k 3!#TZrr4f!'!+)'hr[%)`1!"5Jh!)YS"Ym#BI6Pj1G!!%R@4PFepcCA4IFQ&ZC'p YAfGPEQ9bBA4[FPpcC@9N!!!U88j@rrJLEIqm)'i!#(!)FL#`J@8%SLjJ$NU!C`S L#4,B8i"QqL*"6Pj1G!!%Pf4PFepcCA4IFf9aG@9ZBf9IER9YBQ9b!!!U88j@rrK )ja!%5(J!!5mYrm![,J!),bhr[#*Yrr!J@8k3!#TZrr4f!'!Q)'hr[(!!%$!i!&+ !!S!!!!$r)'hr["'!1!!JEIqm5M!i!'B)8S0`#,D!EG3Q(djH6R3!"*PNCA0ICf9 ZCA*KG'9IFQ&ZC'pYAf*XEf0V!!!U88j@rrK)jami+'i!$#4Z!"J[#Q(r!!!!p#` !5'S!"'(r!!!!k#i!)!aQ"R!",8!!&(!"*N"JE#JZ!"!NEJ!)B&4`!EL!EaB[#Q( r!!!!K()!-J$5KLB"9)T9K'!)GJ!@'YD'H!!U"b!&6!8!!#)$6!-3!0+!6(`3!(r rrrmX!#!&"S!%r(-Y6!-!!%am!!&rrrrr,J&+K'DS)!aR"#M'+-G5Lh!%Ym"Z"VI Z!"4[L#!'60mFq%jH6R3!&)jNCA0IFA9KC&pMDh0eE3!!!#T46PErp#"Z!!JGD!! "rrBJEJ!)(9$rpc!ZrrC1ANjd!!59G(G[Af*jG'9cAhCKH&pdEepZCA4c!!!U88j @rr3JEJ!)(@J!!rrd(@J!![re(@J!!Irf(9$rpb!Zrr41ANjd!!5@CQpeFPpLHA4 PFepfBAKIG'pIEQ9dF`!!!#T46PErm%MR(M`SEJ!)*%`Q6%KZrr!LEImi)&P1N!! UE[rX)Qhr6#"C6T!!+Qlrl#)Zrr#aJ5"Yrk`J%&+3!,1!,`!LEImS)&P1N!!UE[r X)Qhr-#"C6T!!+Qlrl#e!rr3L5d(Zrr4`"()JX)&P"+)ZB!j+J'F+)JN5f&1!C[S L39L,)Qhr-#"C6T!!+Qlrl#e!rr3L5d(Zrr4`"()JX)&P"+)ZB!j+J'F+)JN5f&1 !C[SL3A`!B$4i!(B!&K*k!'!+iSY`!F#$XB45KA!'ZS"[m%U%CJS3%J!!!!%8J'! )%")#!!$q&)"5LP+'F!HmJ'r'F!"-haai6Pj1G!!%MQ4PFepbB@jNEfeIDf9j!!! !+P&19Zri51F3"#mZ!"![,J!-5(J3!%KZlrJLEIqF)&P1N!!UEZrd*J"+JfB8,bi !#%KZlrJLEIqB)&P1N!!UEZrd5(J3!%+R5'l[q#*Yrd!J@8k3!#TZlr3J!bBI6Pj 1G!!-N@4PFepbC@&NAh"KFh0hEh*N!!!U88j@lrK)ja`m*Qi!##JZ!!`SEJ!3+Li !&(B!$)3!!"!!E`!"+R$rB!!"I#m-)Qhr'#"C6T!!+Ql[p#"Yra")D!"')Qhr)#" C6T!!+Ql[p#mYra!["#m,)Qhr&#"C6T!!+Ql[p%U!@%pQ&#mYra!LEImF)&P1N!! UEZrdB!!!e%Ki!!S[#b*Yrb3J@8k3!#TZlr3N3%U!C`*#%NU&C`!!XLm-,bhrU#* YraJJ@8k3!#TZlr3JEIm35'J!4L*Yrb!J@8k3!#TZlr3[,Im35(J3!%KZlrJLEIm 8)&P1N!!UEZrd5S"36fB5,bhr%#*Yra`J@8k3!#TZlr4JA%Ki!!T)EZri)Qhr*#" C6T!!+Ql[p#4!5S"R!N)55'l[q#m,)Qhr,#"C6T!!+Ql[p%U!CbJ[,IqN)Qhr'#" C6T!!+Ql[p#"Yra")D!"')Qhr)#"C6T!!+Ql[p&K2B!*f!8U$C`$qfNU$CK)["%+ R,`XLEIp!)&P1N!!UEZrd,bhrS#*YraJJ@8k3!#TZlr4+K9K2CaC)H"!!3UG)EZr i)Qhr3#"C6T!!+Ql[p#!%8i"#-`J!)!0A`%3!5F"-ha`i6Pj1G!!3NQ4PFepbC@& NAh"hAh0dFQPZC`!!!#T46PEr0%MR(c`QEJ!)+'i!$#e,rc4k!8AZrlJJ5h$r8S" +''Ek,J")H!"!3UG)E[qi)Qhr3#"C6T!!+Qlr-(`"B$S@'dR$H!"J'NU&C`SJ!h) "`)'a'Q!))!0b!F#"X5,LLe+%F!DiJ'rJF!I!KQB+)!9A`%3!5F!U!&+'[)GM`NA ZrlJQ6(`!B"jf!(J!B!iJ"&+!%KT*`H'TKS&5K(!'Z)"[l"E$8SC`"lb!Bp`[$#* Yrq`J@8k3!#TZrc")E[mi,``LEIr))&P1N!!UE[m`,`a)E[mi,`F[$#mZrc4Krrr rh%T)H!#!3UG)E[mi)Qhr3#"C6T!!+Qlr-#m-)Qhrl#"C6T!!+Qlr-(!!60mFq%j H6R3!#*&NCA0IFh4bD@jRAh4[AfYPH3!!+P&19[ri51F30#4Z!!`QEJ!)GJ![,Iq 8,`SLEImm)&P1N!!UE[rd8%pJ0R!!%"X[!#mYrj!!,`SLEImm)&P1N!!UE[rdF!L fJ%r[!!aX&#mYri`[#L*Yrc`J@8k3!#TZrr436b!$8S0b#,#"EF![,Iq),`SLEIm m)&P1N!!UE[rd8%p-h``)6Pj1G!!)P@4PFepMBQa[BfYIF(*TER4ICQPXC3!!+P& 19[ri51F30#CZ!!JNEIq%GJ"J)NKi!!J[#b"+8)T)8#*Yrc3J@8k3!#TZrr4+J'B %F!&J#P+$F"#fJ'ABF!"-h``)6Pj1G!!%Mf4PFepTFephC@&VAfYPH3!!+P&19[r F51FI2#`Z!!`Q,J!J*'i!&#CZ!"JSEJ!F5Ui!*'F!$)`Z!b"(8SGk!"S3FKMMV5" (8SG`!"!3FK$MU)U!)%G5Kh!!%"$KL)U!)%G5Kh!!%"#+J#"(8SGi!"J3FKMMV#" (8SG`!"!3FK$MU)L!)%G5Kh!!%"$KL)L!)%G5Kh!!%"#)J#iZ!!JY4[rdB!!-%R! )X+i!%'i!!*iJ4e+(F!!3%!+!!!!!rh)BikLaK5"(8SG`!"!3!S!!!!$rFK$MU,' &)%G5Kh!!%"!#J!!!!2rKL,'&)%G5Kh!!%"!#J!!!!2qaK5"(8SG`!"!3!S!!!!$ rFKMMU,'%)%G5Kh!!%"!#J!!!!2pb%11SXB3J4e+(F!!3%!+!!!!!rq')XB3J4e+ (F!!3%!+!!!!!rl'%8Di!%'!!!,6HVJ!3)#i!%!b!!!!!"f)!!*i`1`)'6[X!!J# 8!)!!E!"D!%S!0J!L!""6Kb"(F!!3%!+!!!!!rq')XB46Kb"(F!!3%!+!!!!!rh) 3ikLaK&1()%G`!"!3!S!!!!$rFKMMU,'%8iFJ4h!!%"!#J!!!!2qaK91()%G`!"! 3!S!!!!$riBLaK91()%G`!"!3!S!!!!$rFK$MU,'&8iFJ4h!!%"!#J!!!!2pb'11 SXB9#VJ!3)!3#J+U3"1+)*J8#JkU3")D!)!3#J&@3"#)&!S&9N!65JB+!+!%U"() 3iUd#K3!!!2mJEIrm+M"F!0U&)J4d'15T!S%!!!$r)'hrr)U`(!!L"1#*!S%!!!$ r)'hrr#)`(!$PLB+&+J3#K3!!!2mJEIrm+M"F!1H0LS%S!h)3iU`#K!!!!2mJEIr m+$"-!0L%)J0d'15T!S%!!!$r)'hrr)L`(!!L!q#*!S%!!!$r)'hrr#)`(!$PLB+ %+!-#K!!!!2mJEIrm+$"-!1H-L)&m!'!!!CJQ"()9ikXL"(3,j+Q#JbBDXi0`2b) $G"MNUF+!)'hrq(!r*!-Y32rFF"$JUX5ZrpcPLL*YrrM6`L!T!3#!X"`!FMmN!q# +a)(PLL"YrrM4`S#S!J"b2m+$jBNJEIridF'!U!-!XB8Q"()*ikXL"(3Aj+Q#JbB DXi0`2b)$G"$NUF+!jBNJEIridF&`2b)$G"MNUF+!jBNLEIridm%J+33!J+J&!() r*!2JLX5"jBSJEIridF+!U!B!FMr#Jq@*)'hrq0("J+J(!,'&*J9b&H1V)J9d#q5 TJS-Q'V1$F$mL!h3Bj+R#J#"YrrK`2b3$,8$rh(!3i+V%V[rFjBSLEIridm)J+3% !J,!F!()r*!2JLX5"jBSJEIridF+!U!)!FMr#Jq@*)'hrq0("J+J$!,'%*J9b#H1 V)J9d&q5TJS-Q'V1$F$mL!h33j+R#J1@*)'hrq0("F$mL!h3Bj+R#J1@*)Qhrq02 ")#N%!)#S"3"b2b3$i)V%JH@+)'hrq0(#J+J'!()r`S2PL5"YrrM4`B#S"`#aK&+ 'F!LmJ'd!rQ3J"3+!m*!%k)JQ"!+$m*!%KS!J"3+!$j!%)J3#J3q3"1Q*JS!S!5S %FK$LV3+&!!!!rb"Yrr3U-&`!kBdL"(3Bj+N#J3!!!2mJEIrd)M!F!1f*JS8U"1# 0!S8!!!$r)'hrp#S`A!$PMBU")J3#J3!!!2mJEIrdLV!F!#J$FK$LV!+%!!!!rb" Yrr3S-%`!kB`L!h3Bj+N#J3!!!2mJEIrd)M!F!1f*JS3S!q#-!S3!!!$r)'hrp#J `6!$PM)L")J-#J3!!!2mJEIrdL,!F!%AUri!J"!+!UT!%iSJQ"3+$UT!%KS!J"!+ !9C!%)J8#J9@3"0+"JS!S!5S%FK$LV3+&!!!!rb"Yrr`U-&`!fS8L"(3Bj+N#J3! !!2mJEIrmLV!F!#)%i)N#J3!!!2mJEIrm)M!F!1@*JS8U"!+&!!!!rb"Yrr`U-&` !jif+J5J$FK$LV!+%!!!!rb"Yrr`S-%`!f)3L!h3Bj+N#J3!!!2mJEIrmL,!F!#) $i)N#J3!!!2mJEIrm)M!F!1@*JS3S!`+%!!!!rb"Yrr`S-%`!jib)J8IV!)"m!'! !!FJQ"()*ikXL"(3Aj+Q#JbBMXi0`2b)$i)R#J1@*)'hrq0("F$r!Jq@))Qhrq02 !)#N(!)#S"J"b2b3$,8$rh(!3i+V%JH@+)'hrq0(#)#J&!)#Zrpab2b3$,8(ri() BiUV%V[rJjBSJEIridF+!U!3!XB8Q"()9ikXL"(3,j+Q#JbBMXi0`2b)$G"MNUF+ !)'hrq(!r*!2JLX5!jBSLEIridm*`2m#$jBJL-"`!)'hrq0(!)#J$!)#T!J"d2be !rq!J!be"rpab%1+S`),PL#"YrrM4`#!S!3#!V[rJJ+lrh,'&*J9b#H1V)J9d&q5 TJS-Q)l1$F$mL!q#*`S$PL5"YrrM4`A!r`)2PL#*YrrM6`#!T"`#!U!B!FMmN!be !rq"`%1#Ua)(PLL"YrrM4`L!S"3#!V[rJFMmN!be"rpab'1+Ua+lrh1@+)'hrq0( #J+J%!,'%*J9b&H1V)J9d#q5TJS-Q)l1$F$mL!h3Bj+R#J#"YrrK`2b3$i)V%J1@ +)Qhrq02#F$r!Jq@))M!F!#"YrrM4`#!S!`#!U3)!G$mY32rJ)!-Y3IrFFK$LU-# #jBJJEIridF!J+!%!J+lri)#ZrpbaK&+'F!LmJ'd!rM3J"3+!m*!%k)JQ"!+$m*! %KS!J"3+!$j!%)J3#J3q3"1Q*JS!S!5S%FK$LV3+&!!!!rb"Yrr3U-&`!kBdL"(3 Bj+N#J3!!!2mJEIrd)M!F!1f*JS8U"1#0!S8!!!$r)'hrp#S`A!$PMBU")J3#J3! !!2mJEIrdLV!F!#J$FK$LV!+%!!!!rb"Yrr3S-%`!kB`L!h3Bj+N#J3!!!2mJEIr d)M!F!1f*JS3S!q#-!S3!!!$r)'hrp#J`6!$PM)L")J-#J3!!!2mJEIrdL,!F!#! %!S#UN!6LL#B&!S1UN!5'J#!%!S"9N!3L"3+"9C!%dS'#J#J"+J4b%1+Y!S8!!!$ r)'hrr#S`A!$DK5)%G"MNU3+"!!!!rb"Yrrb+X"`!)J6JL3+"!!!!rb"Yrr`L-"` !jBQ#K5S%!S8!!!$r)'hrr#S`A!$RMBU"+!0b%1+X!S3!!!$r)'hrr#J`6!$BK#) $G"MNU3+"!!!!rb"Yrrb)X"`!)J2JL3+"!!!!rb"Yrr`L-"`!jBQ#K#J$!S3!!!$ r)'hrr#J`6!$RM)L"I!"J!!'B*J4b&H1V)J4d#q5TJS-Q(,1$F$mL!h3Bj+R#J#" YrrK`2b3$,8$ri(!3i+V%V[rJjBSLEIridm)J+3%!J,!F!()r*!2JLX5"jBSJEIr idF+!U!)!FMr#Jq@*)'hrq0("J+J$!,'&*J4b#H1V)J4d&q5TJS-Q(,1$F$mL!h3 3j+R#J1@*)'hrq0("F$mL!h3Bj+R#J1@*)Qhrq02")#N%!)#S"3"b2b3$i)V%JH@ +)'hrq0(#J+J'!()r`S2PL5"YrrM4`B#S"`#aK5B&FKAMUb)&G![NUB+$*KbcJh! r)J0d'15T`S!JEIriF$mN!be!rq"`%1#Ua+lri1@+)Qhrq02#)#N"!)#`(!"b2b3 $i)V%JH@+)'hrq0(#J+J#!()r`S2PL5"YrrM4`B#S!`#aK#B&FJRMUb)&G"INUB+ $*KbcJh!r)J0d%15T`S$PL5"YrrM4`A!r)J0d'15T`S$PL5*YrrM6`5!T"!#!U!8 !FMmN!q#+a)(PLL"YrrM4`S#S"J"b2m+$jBNJEIridF'!U!F!XB45KR!)[)"Y!2j N)!8#J2#3"1L)*J3#Jr#3")D!)!8#J!q3"#)%!S%2N!6TLB+!+!%U"()3iUd#K3! !!2mJEIrd+M"F!1Q0)J4d'15T!S%!!!$r)'hrp#)`(!$YLB+&+J6JM3+&!!!!rb" Yrr3U-&`!jBf+J5)%!S%!!!$r)'hrp)U`(!!S!h)3iU`#K!!!!2mJEIrd+$"-!1Q -)J0d'15T!S%!!!$r)'hrp#)`(!$YLB+%+!2JM!+%!!!!rb"Yrr3S-%`!jBb)J5) $!S%!!!$r)'hrp)L`(!"*l2q!)!9b'1+S!S!!!!$r)'lrp&+Zrr33J#!&FK$LU!+ !!!!!rb"Zrr45V[rd%)!J"H#)!S!!!!$r)'lrp&+Zrr33J#!&!S!!!!$r)'lrp&+ Zrr33J#!%FKMLU!+!!!!!rb"Zrr45V[rd%)!J"()3iUJ#J!!!!2mJE[rd8Ulrp"# !)!6JL!+!!!!!rb"Zrr45V[rd%)!J"!+!!!!!rb"Zrr45V[rd%)"+VJ!3EJ$ckQ! !$0C+VJ!3E`!-cLi$)%G5Kh!!%""b'11S,8$rm#"(8SG`!"!3FK$MU)'Zrr!J4e+ (F!!3%1')JDlrm#"(8SG`!"!3JDlrm#"(8SG`!"!3FKMMU#e!rq`J4e+(F!!3%() 3ikL"V[rX)%G5Kh!!%"$KL)'Zrq`J4e+(F!!3%)'Zrq`Z,J!),8Erp#"(8SGk!"S 3FKMMV5"(8SG`!"!3FK$MU)U!)%G5Kh!!%"$KL)U!)%G5Kh!!%"#+J#"(8SGi!"J 3FKMMV#"(8SG`!"!3FK$MU)L!)%G5Kh!!%"$KL)L!)%G5Kh!!%"#)J#e&rqJY42r N)!3#J+U3"1+)*J8#JkU3")D!)!3#J&@3"#)&!S&9N!65JB+!+!%U"()3iUd#K3! !!2mJEIrm+M"F!0U&)J4d'15T!S%!!!$r)'hrr)U`(!!L"1#*!S%!!!$r)'hrr#) `(!$PLB+&+J3#K3!!!2mJEIrm+M"F!1H0LS%S!h)3iU`#K!!!!2mJEIrm+$"-!0L %)J0d'15T!S%!!!$r)'hrr)L`(!!L!q#*!S%!!!$r)'hrr#)`(!$PLB+%+!-#K!! !!2mJEIrm+$"-!1H-L)&*l!#!I!"J!!()*J4b#H1V)J4d&q5TJS-Q*,1$F$mL!q# *`S$PL5"YrrM4`A!r`)2PL#*YrrM6`#!T"`#!U!B!FMmN!be!rq"`%1#Ua)(PLL" YrrM4`L!S"3#!V[rJFMmN!be"rpab'1+Ua+lrh1@+)'hrq0(#J+J%!,'&*J4b&H1 V)J4d#q5TJS-Q*,1$F$mL!h3Bj+R#J#"YrrK`2b3$i)V%J1@+)Qhrq02#F$r!Jq@ ))M!F!#"YrrM4`#!S!`#!U3)!G$mY32rJ)!-Y3IrFFK$LU-##jBJJEIridF!J+!% !J+lri)#ZrpbaK5B&FJRMUb)&G"INUB+$*L5cJh!r)J2JLF+!jBNJEIridF&`2m# $jBJLEIridm!J+3F!J+J'!()r*!-Y32rJF"$JUX5"jBSJEIridF)J+!8!J+lri() r*!-Y3IrFFKMLUX5ZrpcPLL"YrrM4`S#S"!#aK#B&FKAMUb)&G![NUB+$*L5cJh! r)J0d'15T`S!JEIriF$mN!q#+a)$PLL*YrrM6`R!r`)2PL#)`(!!JEIridF!J+!- !J+N#!(3r,8$ri#!$,8(rh()3iUM!JZ@))'hrq0(!)#J"!)#Zrq#!V[rFXB45KR! )[)"Y!2id)!8#J2#3"1L)*J3#Jr#3")D!)!8#J!q3"#)%!S%2N!6TLB+!+!%U"() 3iUd#K3!!!2mJEIrd+M"F!1Q0)J4d'15T!S%!!!$r)'hrp#)`(!$YLB+&+J6JM3+ &!!!!rb"Yrr3U-&`!jBf+J5)%!S%!!!$r)'hrp)U`(!!S!h)3iU`#K!!!!2mJEIr d+$"-!1Q-)J0d'15T!S%!!!$r)'hrp#)`(!$YLB+%+!2JM!+%!!!!rb"Yrr3S-%` !jBb)J5)$!S%!!!$r)'hrp)L`(!!J"!+!UT!%iSJQ"3+$UT!%KS!J"!+!9C!%)J8 #J9@3"0+"JS!S!5S%FK$LV3+&!!!!rb"Yrr`U-&`!fS8L"(3Bj+N#J3!!!2mJEIr mLV!F!#)%i)N#J3!!!2mJEIrm)M!F!1@*JS8U"!+&!!!!rb"Yrr`U-&`!jif+J5J $FK$LV!+%!!!!rb"Yrr`S-%`!f)3L!h3Bj+N#J3!!!2mJEIrmL,!F!#)$i)N#J3! !!2mJEIrm)M!F!1@*JS3S!`+%!!!!rb"Yrr`S-%`!jib)JA`!B!!"Q#B%FKAMUb) %G![NUB+$*KZcJh!r)J0d'15T`S!JEIriF$mN!be!rq"`%1#Ua+lri1@+)Qhrq02 #)#N"!)#`(!"b2b3$i)V%JH@+)'hrq0(#J+J#!()r`S2PL5"YrrM4`B#S!`#aK5B %FJRMUb)%G"INUB+$*KZcJh!r)J0d%15T`S$PL5"YrrM4`A!r)J0d'15T`S$PL5* YrrM6`5!T"!#!U!8!FMmN!q#+a)(PLL"YrrM4`S#S"J"b2m+$jBNJEIridF'!U!F !XB8Q"A)9ikXL"A3,j+Q#JbBEXi0`2b)$G"MNUF+!)'hrq(!r*!-Y32rJF"$JUX5 Zrq$PLL*YrrM6`L!T!3#!X"`!FMmN!q#+a)(PLL"YrrM4`S#S!J"b2m+$jBNJEIr idF'!U!-!XB3Q"A)*ikXL"A3Aj+Q#JbBEXi0`2b)$G"$NUF+!jBNJEIridF&`2b) $G"MNUF+!jBNLEIridm%J+33!J+J&!()r*!2JLX5"jBSJEIridF+!U!B!FMr#Jq@ *)'hrq0("J+J(!,'%8SC`#,b!E3$qC#!&!S$`N!6SL#B%!S2`N!5'J#!&!S!2N!3 L"!+"$j!%kBQ#J#J"+J4b%1+Y!S8!!!$r)'hrp#S`A!$TM5)%G"MNU3+"!!!!rb" Yrr3L-"`!lBQ#K5S%i)d#K3!!!2mJEIrd+M"F!1@0LS%L"!+"!!!!rb"Yrr5+X"` !+!0b%1+X!S3!!!$r)'hrp#J`6!$TM#)$G"MNU3+"!!!!rb"Yrr3L-"`!lBQ#K#J $i)`#K!!!!2mJEIrd+$"-!1@-L)%L!`+"!!!!rb"Yrr5)X"`!4q[rJ#!%!S#UN!6 LL#B&!S1UN!5'J#!%!S"9N!3L"3+"9C!%dS'#J#J"+J4b%1+Y!S8!!!$r)'hrr#S `A!$DK5)%G"MNU3+"!!!!rb"Yrrb+X"`!)J6JL3+"!!!!rb"Yrr`L-"`!jBQ#K5S %!S8!!!$r)'hrr#S`A!$RMBU"+!0b%1+X!S3!!!$r)'hrr#J`6!$BK#)$G"MNU3+ "!!!!rb"Yrrb)X"`!)J2JL3+"!!!!rb"Yrr`L-"`!jBQ#K#J$!S3!!!$r)'hrr#J `6!$RM)L"4HS!J(`!B!!"b#B%FJRMUb)%G"INUB+$*L+cJh!r)J2JLF+!jBNJEIr idF&`2m#$jBJLEIridm!J+3F!J+J'!()r*!-Y32rJF"$JUX5"jBSJEIridF)J+!8 !J+lri()r*!-Y3IrFFKMLUX5ZrpcPLL"YrrM4`S#S"!#aK5B%FKAMUb)%G![NUB+ $*L+cJh!r)J0d'15T`S!JEIriF$mN!q#+a)$PLL*YrrM6`R!r`)2PL#)`(!!JEIr idF!J+!-!J+N#!(3r,8$ri#!$,8(rh()3iUM!JZ@))'hrq0(!)#J"!)#Zrq#!V[r FXB8Q"A)*ikXL"A3Aj+Q#JbBLXi0`2b)$i)R#J1@*)'hrq0("F$r!Jq@))Qhrq02 !)#N(!)#S"J"b2b3$,8$ri(!3i+V%JH@+)'hrq0(#)#J&!)#Zrq"b2b3$,8(rh() BiUV%V[rFjBSJEIridF+!U!3!XB3Q"A)9ikXL"A3,j+Q#JbBLXi0`2b)$G"MNUF+ !)'hrq(!r*!2JLX5!jBSLEIridm*`2m#$jBJL-"`!)'hrq0(!)#J$!)#T!J"d2be !rq!J!be"rpab%1+S`),PL#"YrrM4`#!S!3#!V[rJJ+lrh,'%8SC`#,b!E3$q0#! &!S$`N!6SL#B%!S2`N!5'J#!&!S!2N!3L"!+"$j!%kBQ#J#J"+J4b%1+Y!S8!!!$ r)'hrp#S`A!$TM5)%G"MNU3+"!!!!rb"Yrr3L-"`!lBQ#K5S%i)d#K3!!!2mJEIr d+M"F!1@0LS%L"!+"!!!!rb"Yrr5+X"`!+!0b%1+X!S3!!!$r)'hrp#J`6!$TM#) $G"MNU3+"!!!!rb"Yrr3L-"`!lBQ#K#J$i)`#K!!!!2mJEIrd+$"-!1@-L)%L!`+ "!!!!rb"Yrr5)X"`!)#lrm,'&)#lrl,'%F!L`VJ!3E!!!ZP'Z!"!J"A)BiUJ#J!! !!2mJE[rd8Ulrp"#!)!9b%1+S!S!!!!$r)'lrp&+Zrr33J#!&i)J#J!!!!2mJE[r d8Ulrp"#!)!8#J!!!!2mJE[rd8Ulrp"#!)!4b'1+S!S!!!!$r)'lrp&+Zrr33J#! %FK$LU!+!!!!!rb"Zrr45V[rd%)!J"1#)!S!!!!$r)'lrp&+Zrr33J#!%!S!!!!$ r)'lrp&+Zrr33J#eZrqMrm#eZrq6rl'!!p)JJ,J!3dDlrp#!Z!"!-J!!!!!KL!!$ !-$X#"Nll!!)!YJ#J!)S!GJ"N!%i!1!!N!")J"!+!!!!!re1Zrr3JE[rd%)!J"1# )!S!!!!$r8klrp#"Zrr33J#!%FK$LU!+!!!!!re1Zrr3JE[rd%)!J"()BiUJ#J!! !!2p6V[rd)'lrp"#!)!8#J!!!!2p6V[rd)'lrp"#!)!AJL!+!!!!!re1Zrr3JE[r d%)!J"A)3iUJ#J!!!!2p6V[rd)'lrp"#!)!9b'1+S!S!!!!$r8klrp#"Zrr33J%c I(2K1ANjd!##3!'4PFemcBf*MAf9ZBh*jF(3!!!!U88j@rpK)jam`*Qi!$#4Z!!K f!"BDF!!3'Z')KS"`!"!DFK$MU)D!F!!3'R)BikL'J(J!'"T`!"!DiBL)J(!!%"T b%11SL)"`!"!DFKMMU)L!,!6SMVH'!SB2N!5pJb!'kBLaK#`$FK,MVVH'!SE-c!! !)!1pJ#)'G",NUE'"*J%X"()5ikkjKJ+'c-`!!#!%[B!L"R35j+QaJ5J",!6LMVH '!SC9N!5pJb!'d)#aK#`$i)kjKJ+'!2m!rlf%)!EKL,'$,!6LMVH'!SC9N!5pJb! 'd)#aK#!%!S!!!2m!)J3#J3!!!2pd%1@TJS!J"!+!!2m!!(33j+L!J5)$!S(`!!! !k)Q#J#J"!S-2rrrrIJ"J!!(#)'hrI%U`I!"R(L!$FKVMU#)$j)Q#J#B")!4b'Z1 S)J6NLB+!+!&J(#!$FK[MU#)$iSQ#J#B")!4b'q1S)J6LLB+!+!%#J`rrrrm#K!r rrrp`2m#$)'hrH()m*!2ZLX5"FJ-YF!`!rpJJ!qb)`)'!JZ@))'hrH0(!)#J"!)# ZrpKb-#3$,8(rh()1iUV%V[rFFJmY3[rJ*!-Y32rNF!hJUX5"K+lri1@+)'hrH0( #)#J#!)#Zrq4b"L3$,8(rk()9iUV%V[rSFJ%Y3[rX*!-Y32r`F"6JUX5"K+lrl(! i)J-Y3[rdG"ENUF+!JUlrp1@*)'hrH0(")#J$!)#Zrr!N3(`m)J6JLF+'I!-N"1k +a)D%JH@+)'hrH0(#I$r-K1@1)QhrH02',#N%!)bS"3"b2b3%,8Erp(`2l+V%JH@ +)'hrH0(#,#J'!)bZrr4b-#3%,8(rm()@iUV%V[r`FJmY3[rX*!3Y4[rSI"AXUX5 "K+lrl1@+)'hrH0(#,#J(!)bZrqJJ#J+!!!$rrbS'G"$PVBU!)!APL#)&G"lNUG+ !*X%J"J+!rrm!!#S+G"$NVBU!)!AYL#)&G"VNUG+!*X&5Kh!3[S"Y!2ikF!"-h`c i6Pj1G!!)Lf4PFepcCA4IDf9j!!!U88j@rrJ[$5mYrh![,J!-,bi!##*Yrf3J@8k 3!#TZrr3J,Ip`6Pj1G!!)L@4PFepMFRP`G!!!+P&19[pF51FI2#KZ!!JS,J!-*'i !%%IZrqiJ4%S3CJ4`3@!')%33%%R!&)"*`#B!)'hrE(S!'M!i!1@0)%4++!!"CJ4 `3@!))%33+!!"5F!93!!"5F!Q!#"Yrfam!"``1!$YMRi!B"BB(%S%Cb*`!"!%d)" "l[rQ%B"i!&+(F!LqJ'ANB!T"l[rQ3M"i!&+(F!LqJ'A`5'lrANKZrqBLEIpd)&P 1N!!UE[pB,`B["8KZrej)E[rHBIm!!!$Q*LlrhL!$!S!!!!$r&X!J!q#)!S!!!!$ r&X!J!h)3iUJ#J!!!!2m@`#!$FKMLU!+!!!!!raE!*LlriL!$!S!!!!$r&X!J!q# )!S!!!!$r&X!J!h)3iUJ#J!!!!2m@`#!$FKMLU!+!!!!!raE!I!!@2!#!3LlrpRi #B%*i!(S!B#EB"(!!%!0"l[rZFJ!5-'J!`S"R"!!%!!(L#dS$CJC5KKBm!)"5KA! 'ZS"Pe(!!%!3JEIpS&E!!!(J!8SG`$Ek!CEK#+J!0)!T-haci6Pj1G!!-LQ4PFep QBh*jF(3!!!!U88j@rma)j`mB)QhrB(S!I!!SEJ!-,@i!%2r8,@i!&2r33Ulrc'! !"%#Abf!!"#JJ"R33j+JN"V'#+!,)V[r8a+lrd#i%FK$MVb!')M5m!,1!XB5rK#i #FK$MVb!,8S!L"L!d$!#aJE1#[i)J"1#!,8$rp#i%!SF!!!$m!Ui!!!$mrr3J!R) FikJL!ZL*dS!N!A!3i+`J-AJ!XB8J5G(Zrr3J+!)!XB8J"1#),8$rm#i%!SF!!!$ m!Ui!!!$mrr!J5G(()#J%!,'&)%R4l[r`)#J'!,'&)!,JJ#e!rr3Z!J+(!!!!r!+ Z!!!!r2rdF"$JUL"*dFFJ+!%!XB8J5G(Zrr3J+!-!XB8J!Z#!,8$rm#i#!SF!!!$ m!Ui!!!$mrr!J5G(()#J&!,'&)%R4l[r`)#J(!,'&)!9d%15S*!@aJLJ#b+lre-5 Zrp!Z"()3ikmJ#e5!)J8J0!`!XB'cK,q%,J*b%11[)!Y@J#)&)$3-!,'"Xi+rJL! %i)!Y32rX,J3#K`!!!2`#VJ!!!2crl#!#FKcMU#)#k)R5J#3"F"$JV#!aH!#aKL" *dHlrl#!S!J#aKL!%i)JY32rS,J3#K`!!!2`#VJ!!!2crk#"*dFFJ+!3!XBBJ5G( ZrqJJ+!B!XBBJ!Z#!,8$rl#i#!SF!!!$m!Ui!!!$mrqa`%1#U)%R4ab!S!3#aKL" *dHlrl#!S!`#aKL!#i)!Y32rS,J)#K`!!!2`#VJ!!!2crk#"*dFFJ+!8!XBBJ5G( ZrqJJ+!F!XBBJ"R33j+JN"V'#+!,)V[r8a+lrd#i%FK$MVb!,@)!L"L!d$!#aJE1 %[i3Z!R)3ikmJ#eU!)JBJ0!`!XB'cJVq#)!6JJ#e!rq3Z"!+(!!!!r!+Z!!!!r2r N)!*b(11S)J,SLG+!*!&`%1#X)$&i!,'&)%R4l[rN)#J#!,'&)!6JL#e!rq!Z"!+ (!!!!r!+Z!!!!r2rJ)%R4ab!S"!#aK5"*dHlri#!S"J#aK5!#i)!Y32rN,J)#K`! !!2`#VJ!!!2crj(!3i+SJ5G(()#J"!,'&)%R4l[rN)#J$!,'&)!,JJ#e!rq!Z!J+ (!!!!r!+Z!!!!r2rJ)%R4ab!S"3#aK5"*dHlri#!S"`#aK5!&G"$NU#3&XB)S!XL Zrp6%V[r3,J4b%11[)!YFJ#)&)$3-!,'"Xi5rK#i#FK$MVb!,AS!L"5!d$!#aJE1 #[i)J"1#!,8$rh#i%!SF!!!$m!Ui!!!$mrp`J!R)FikJL!ZL*dS!N!A!3i+`J-AJ !XBBJ5G(Zrp`J+!)!XBBJ"1#),8$rf#i%!SF!!!$m!Ui!!!$mrpJJ5G(()#J%!,' ')%R4l[rB)#J'!,'')!,JJ#e!rp`Z!J+(!!!!r!+Z!!!!r2rFF"$JUL"*dFFJ+!% !XBBJ5G(Zrp`J+!-!XBBJ!Z#!,8$rf#i#!SF!!!$m!Ui!!!$mrpJJ5G(()#J&!,' ')%R4l[rB)#J(!,''8)Y`),I!E3$le#3&+JBX!P+Zrma`'E#ZrmaZ!2Zk)!9b(H1 S)JAQLG+!+J%J"R)GikJL"ZD*dS!X!53&iSUpJJ+#9C!%YBBJ!Y#!XB8N"Z#+Zi) #JJ$r!2qeK5!#iBLaKL3&j)UpJJ+#-j!%YBBJ!Z@)XB8N"R)3iUUlJJ+#!!$rrl@ &)!*b%11SXBBN"HL+[B)#JJq3",@')!,TL,'&)'i!###')'i!##&&!!4-haM`6Pj 1G!!3LfCMFRP`G&pLEf4j!!!U88j@rrK)ja`m+Li!##4Z!!`S,J!3+'i!&#CZ!"J Q,J!F5S0R4Lm$,`3[#Lm&)Qhrm#"C6T!!+Qlrp#!$9m"%!%R!,`![$#m+,`SLEIr `)&P1N!!UE[rd,`-[#bm+,`SLEIr`)&P1N!!UE[rdB%3[!bm,,`S["5*Yrr!J@8k 3!#TZrr3J!eI!4!"*`#m!,``[#Lm+)Qhrm#"C6T!!+Qlrp#m$,`3[#Lm+)Qhrm#" C6T!!+Qlrp%cI($K1ANjd!"L3!'4PFemcC@0LAf9ZBh*jF(3!!!"PC!dK%)%$"J! 3!!!3%"!!!"!!%"!3!"!3%!3K%!3K%!)L%"!%)4#"!`X3!"!!%*!&!!!"%!!"!"! "%"!"!!!4%!!4!"!4%"!4"L%"!L%"!b)"!3%K!3-K!3%K!3%L!3%#*!'3"!-K!3) L!3%")3%")3%"*!'3"!)L!3%"*!'3"53"N!3%)3%%)3%#)J%""#%"!5%"!5%"!L) "!3%M!3%"##%%J3-0!3!!!3!%!!3!!!3%!33!!33%!!!J!!!N!3!J!3!N!!3J!!3 N!33J*!%%*!%$)3%#)`3"!3)L!3%")J3"!5%%!5%"!58%"!%""!%P!3%%"!%#)L! "!L-N!3%")b!"!3%L*!%")`3J!3%U"#3"!33J!3%%*)%$$`)!!!)!"!-!!!-!"!) %!!)%"!-%!!-%"!)!)!)!*!-!)!-!*!)%)!)%*!-%)#8$"#3"!J)L!3)")`3"!`) L!3-"*!3"!J3"*`%#"!3"!`3"*J%$"!3"!J%M)!%#!5-N!3-")b!"!`%a*!%#"#! "!J3N!3-%)!%$"#3%)3)&)3J")3)")3J#)3J#)J))!b))#!%M!JJ)"#)"!J)K!3) M#!%#!5))!3%K#!%M!3))!5%"!5F)#!%##!J"!L%"J3-(!J!"!!!*!J!*!!J"!JJ "!!J*!JJ*!L-"!3)")J%"!L-*!3)")JN"!5F)!3%##!%"!5J)#3%##!N"%!-K%J- K%!%K#!%K%J%K#!%L%!J#)K))!L-3#!J")a))#!%K%!)L!4)#)J%3!5-)!4)"*!J "%!J")`%5#!%U!4!)#!%5#!J"%!%K!B%$"a)!!4!!#4)!#4!)!4))!4!)#4))#5% 3!5-"!4)")`%"%!%M#3%5!6)*!4!)!3%5#!%"%!J*!4))#3%&)33%)5##!J3%)"! !&!!3)#)8))%$##!!!#!%!#!!)#!%)#!3!#!8!#!3)#!8)!-K#)%$"J3!#!!J#!3 J#"!!#"3!#"!J##38)!JJ!L-))!3")JJJ!5JJ##!%)!JJ%!%M##!8!5N))"!J##! 8)!L"!`FJ!!!N!!!J)!!N)!!`!!!d!!!`)!!L0##"!`JJ)!!J*!!JN!3N)#!`!#! d!#!`)#!d)!%K)!%K#)%$"L3!##!J##3J#$!!#$3!#$!J##8d)!JJ)!%M##!N!5X ))#!J##!N)!JJ-!%M##!d!5N))$!J##!d)!J()K!)J3-r!!!)!"!!!J!!!K!)!J! )!K!!!!)!!"))!!))!")!!J)!!K))!J))!K)%!!!%!"!-!!!-!"!%!J!%!K!-!J! -!K!%!!)%!")-!!)-!")%!J)%!K)-!J)-!K)!%!!!%"!)%!!)%"!!%J!!%K!)%J! )%K!!%!)!%"))%!))%")!%J)!%K))%J))%K)%%!!%%"!-%!!-%"!%%J!%%K!-%J! -%K!%%!)%%")-%!)-%")%%J)%%K)-%J)-%K)!!!!#!b%#!L)#!J3K!3%K!J%K!3) L!J%")`)#!33L#!)#)3J")3)")`J#!J%K#!)M!3J#!5)"#!%R!J%)!J)"#!%K)!) L!L!$)5)#)J)L!b)J!3%M!L!"!L)L!3%M!L)"!L%J!5-)!L!")3J")5)")`J#)J% K#!%R)!%)!L!"#!%R)J%)!L)"#!)K!S%$"`)!!J!#N!8!!!-#!!-!!J-#!J-#)`) )!J%L!JJ"*`)##!)#!JJ#)`-)!J%L!`J"*`)$#!)#!`J")L!#J3-(!L!#!#)#!L) #!#!$!L!$!#)$!L)$!5FJ!JJ#)!))!5FL!JJ#)J))!5FJ!`J#)!-)!5FL!`J#)J- )"L%3"#%J!L)3)!%K%!-L%"!#)4!")5!"*"!3)!J$)3J")4!")3J#)L!)!533)!J 3!L-)%"!")JJ3!58J#"!3))%$"`!!"!!3"!!!*!!3*"!!""!3""!!*#33%#3)!L) %#!%M%!3)!L)N#!%N%#3)%!%R"!J3%!3)%!%P*!J3%#5"!`F!"!!!&!!!"#!!&#! 3"!!3&!!3"#!N%"3J#!%K"!%K#!%K&!%K#!%M"#!)!588)!J3"!%M#"!8!5J)%!3 J#"!8))%$"`!%"!!8"!!%*!!8*"!%""!8""!%*#33&#3)!5-%"!J")a3%#!%M"#3 )!6)8*!J3"!3)%"3%#"!%*!J3&#3%)4!%)3%#)K!""5)#%!)K!J%K!3%M!K!"!5% #!L%J!5%3!5%J!L)")!%M%!%J!b-J!K!")L!#!5F")!)3!5!#!5%%J3-(!"!%!!! &!"!&!!!%!K!%!J!&!K!&)3)")J3J!5-3"#!#)J8J!5-3"5!#*`3J!K!%)!)"+!8 J!K!&)!)J!b%`!b)J!3)L-!%#)5!#)J)`!L-#)!%")`)`!3%L!L!")5!")6!")5! ")b!")!%M-!%J!5%J!5-J!M!",#!#)!%J!M!")!)J")%$"`!`"!!J"3!`"3!J"!) `"!)J"3)`"53#)!3J!5-`"#!")b!&)!%M-!8J!6!J"#!#-!3J!L!&)!)`"5!#"#% %"L)""))#$!%"!!8!!3%&!3!3""!!%334!4!&%!%4"5%4!5%)J3-2!!3)!!!)!33 )!3%)!!8)!!%)!38)!3!)%!3)%!!)%33)%3%)%!8)%!%)%38))4%#)3J")35"!`i )!!!)!33)!3%)!!8)!!%)!38)!3!)%!3)%!!)%33)%3%)%!8)%!%)%38L#"%")JJ )!5-%#!J#+JJ)!33)#!%"#!J")`8)#!%S!3J)!38)#!%"*`J)%!3)#"!"0`J)%33 )#"%"#!J3"3J)%!%)#"%&#!J4"b%3JJ)0!!%!%4!!%"!3!4!4!3!"%!%"!4%4!"% 3%3%L%4'"!bm3!!!3!"!3!!%3!"%3%!!3N!8"%"!4%!%!%!%3%!%"%!%4%"%!%"% 3%"%"%"%4!3!!!3!3!3!"!3!4!4!!!4!3!4!"!4!4!3%!!3%3!C!&%3%4!!%4%!% 4!3%4%4%!!"%!%"%!!4%!%4%3!"%3%"%3!4%3%4%"!"%"%"%"!4%"%4%4!"%4%"% 4!534%4%3J3-2!!!3!"!3!!%3!"%3%!!3N!8"%"!4%!%!%!%3%!%"%!%4%"%!%"% 3%"%"%#34%4!3!L)3%!%M%"!3!5-"%"!"*"%3%"!",a#3"`%3%"!4%"!"!5m3%!% 3%"!"!4!3!4%3%"%",K!3%4!3%"%"%"!4%4!"!L)3!3%M%"!"!5-"%!%"*"%3!4! ",a!"%"!3!4!"%!%3%4!"!3%[%!%"%"!"!3%3!3%4%!%4!5i3!4%3%!%4!4!"%4% 3%3)L%"%")a!3%3%M!4!4!534%"%3!5m3%4!3%"%3!4!4%"%3%3%",a!4!4!3%3% "%"%"%4!4%3%Y%"%4%"!4%3%3%4%4!B%$$`!!!3!3!3!"!3!4!4!!!4!3!4!"!4! 4!3%!!3%3!C!&%3%4!!%4%!%4!3%N%4%"%!)L!4!")a!"%!%M!3%3!534!4!3!5m "%"!3!4!3!3%3%"%"%!%",`%3!4!"%!%"!4!"%3%3%3%Z!4!4%!%3%3%"%"%4!3% #)J%"!5-3!3%")`'3"#34!3%3!5m"!4!3!3%3!3%"%"%"N!3[!3%"%!'3"a%"!4% ",J%"%4!"!4%"!3%4%3%4!L)"%3%M%!%4!5-"!4%"*"%"%4!",`%4%"!"%4!"!4% 3%3%4!3%[!4%"%!%4!3%"%3%4!4%4!5d"%4%3!4%4!3%4N!5"!`m!!"%!%"%!!4% !%4%3!"%3%"%3!4%3%4%"!"%"%"%"!4%"%4%4!"%4%"%4!4%N%4%4%!)L%4!")a! 4%!%M!4%3!534%4!3!5m4%"!3%4!3!4%3%"%4%!%",a%3!4!4%!%"%4!"%4%3%3% Z%4!4%"%3%3%4%"%4%3%#)K%"!5-3%3%")`%4!3%N%4%"%!%[%3%3%"%"%!%4!4! 4%3%"!5m4!3%3%3%"!4%"!4%4!4%",K%"%4!4!4%"%3%4N!3#)K%4!5-3%4%")`% 4%3%N%4%4%!%[%4%3%"%4%!%4%4!4%4%"!5m4%3%3%4%"!4%4!4'3"!%X%4%4%"% 4%3%4N!3%)3)%)3)#)J)#"#%#!5%#!5%#!L)#!J%M!J)#"#)#!J)K!J%K!J%M!J) #!5%#!L-#!J)")J)#!5J#N!F"!b%$!b)"!J)L!`)#)3%")3)")3-")3)")`%#!J% M!`)#!5%"!L)#!`)M!J%#!5-#!`)")J)"!5-#!J-"+J)#!3)#!J-#!J)")3%#)J) "!b%$!L)#!`-L!3)")`)"!J)L!`)")`)$!J)K!3%M!J)"!5%#!5%$!5-#!J-")3) "*`%#!J)"!J)"+3-#!J)$!J)"!3)L!`%#)J%$!L)$!`)M!3%#!5-$!3)")`%$!J% M!`-#!5)"!3%M!J-"!5-#!3-")`)$!`%a!J%"!J)$!3)#!3-#!J-$!J)#)3'"!`F #!!%!!J%#!J%!!!-#!!-!!J-#!J-#)`%#!J%L!3)"*`)"!J)#!3)#)`-#!J%L!`) "+!)$!J)#!`)"!5%"J3-(!`!"!3)"!`)"!3!$!`!$!3)$!`)$)3%")`%#!`%V!3) "!J%#!`)"!J%")`-#!`%U!`)"!J-#!`)$!J%L!3'"!`F#!3%!!`%#!`%!!3-#!3- !!`-#!`-"*`%"!J)"!3)"*`-"!J)$!3)"*`%$!J)"!`)"+J-$!J)$!`)"!3'"!`F $!3%"!`%$!`%"!3-$!3-"!j!&)#!"!3%#!`%"!J%$!3)$!`%#!3%$!J-"!`)"!`- #!`-$!J-L!3)#)3%")3)")`%#!J%K!3)M!J%#!5)#!3%R!J)"!J)#!3-L!`)#)3- ")3)")`-#!J%K!`)M!J-#!5)#!`%S!J)$!J)#!`%#)J%$!L-"!3)")`%$!J%L!3% ")`)"!`%V!J%"!J)"!`)#!3%#)J-$!L-$!3)")`-$!J%L!`%")`)$!`%U!J-"!J) $!`)#!`%K!3%M!3)"!5%"!5%$!5-"!J-")3%"*`%#!3)"!J%"*`-#!3)$!J%")3% ")`-#!3%K!`%K!`%M!`)$!5%$!5F"!J-#!3)$!5N$!J-#!`)$!3%")`%$!3%M!3% $!5-"!`-"-`%"!3)"!`%#!3%$!J%$!`)"N!3M!`-"!5-$!3-")`-$!`%a!`%"!J- $!3)$!3-#!`-$!J-#)`%"!J%L!3%"*`)"!3)#!3%#)`-"!J%L!`%"*`)$!3)#!`% #)`%$!J%L!3-"*`)"!`)#!3-#)`-$!J%L!`-"+!)$!`)#!`-"!5-"!3-"+`%"!3) "!3-#!C!%)`-"!`%V!`%"!J-"!`)$!3%")`%$!`%V!3-"!J%$!`)"!`%")`-$!`% U!`-"!J-$!`)$!`%R!3%"!J'3"#F$!3%#!`%"!5F"!`%#!3-"!5F$!`%#!`-"!5F "!3-#!3%$!5F$!3-#!`%$!5F"!`-#!3-$!5"(!`-$!J-$!`'3"!-"N!3$!3%$!`' 3"!-"!`%$!3%$!`%$!`-"N!3$!`%"!`%$!3-$!`%$!3%$!`-"!`-"!j!(!5%3!L) #%!%L!3)")J3""L%%!5%#!5)%!3%Q%!3"!K!%!53#%!3"!5%3"L%#!L%"!b)"!J- L!K!")3%#)`3"!J%K"!)M%!3"!5%3!5)"!J%K"!%K!J)M!3)3!L-#%!3#)4!")`% #%!3K"!-Q"!%#%!3"!5)3"!3L!3)%)K!%!5%#"#)3"!)K%!)K!J%M"!%#!53%!3) 3!5-"!K!")3%$)3%")4!")J%#!b%#!5%%!L%3!L-#%!3$)J3"!5B3"!%#%!3$)`3 "!J)R!3)3"!%#%!-L%!3)*3%#%!3""583"!%#%!3K"!%K!J)L!3)")33$)33#)4! ")3%")S##"b'!!L1!JJ+"!aL!J!)!JJ)!!!)!J!!!!J#!JJ#!JJ)!!J#!!J+!J!+ !!*!%!J!#!S!#!)!#!!##!!##!)#!!)#!!)!#!J#!!S!!!S!!!J#!!J8L!J+"!ad !JJ+!!!!!J!#!JJ)!!!+!J!#!JJ#!!!#!!!!!!J#!J!)!J!!!JJ#!!!)!!J!!!!+ !!J)!JJ+!JJ)!J!+!J!#!!J+!!!)!!J)!JJ+!JJ!!!J+!!J#!!J!&)S!#!L'#"L1 !J!)#*3%%"!%""5)%!3%L"!3")3%'*!%""!3")3%#)3%")J3%!L)%"!)K"!%K!3) N"!%""!%K!3%M"!3""#-""!3'*!3%!3%$)3%#)J%"!5)%!3)L"!%")33"*!%""!3 ")J%%!5)"!3)K!3)K"!%L!33$*33%!3%%!L%"!5%%!b-%!3%")33%)3%")33#)J% %!5%"!L-%!3%")33")3%()3%#)3%"*J3%!3%%"!%K!3%K"!)K"!)K!38L"!%")J3 %!5)""!%K!3)K"!-N"!%""!-K"!%M!3%%!5)"!3%K"!)M"!3"!L%%!5)""!)N!33 %!3-M!3%%!b-%"!%")33")J%""#1!!33")i!""!)K)3)KJ!%K"!8LJ#!$)J%%J3- ,!#!%J!!%!!%!J#!%J#%!J#%%!!!%J#!!!!%!!#!%!#!%"5%J!L1!)35"!aq!)35 !!3#!)33!)!#!!!!!)3!!!35!!3!!)3!!!!5!!!3!)3#!!!#!!3!!)!!!!33!)3# !)!5!!3#!)!!!)33!!35!)!5!!!#!!3!!)33!)35!!!5!)3!!)35!!33&)L!%!L% K"#%%!5+!!3)LJ#!#)B!")33')L!%!L)""!%LJ#!#*)#!3"!")B!")a"!J!%L%%! $)8!"*8!33)"!!50!J%!#)B!")4!')N!3!L*!%!%PJ%!33)!#)8!&)8!")d#!3!) KJ!8K%!)K3!)MJ%!3"#&!!5&!!L'!!5%3!b333)"!!5*!J!8L%%!")8!")8!#)4! #+%!33)"!%%#!!L&!!5&!!50!J%!$)N!3!5@!3""!J!)K3!NL3"!$)K"!!5&!!50 !J%!")N#!!b1!3"!")B!")a"!J!%L%%!$*N#!3""!J!)L3)!&)4!")S"!!L'!!5% 3!L9!%%#!3!%L3)!")4!$)K"!!5&!!L1!3"!%)8!")8!%)4!#*%!33"!#)`J3)!3 K)!%Q%#!J#"!J"58)%#!J#!%K)!)K%!%K)!)M)#!)!5%J!L%3!L%)!5%J!5))%!% K)!%K%!8L)!J&)5!")JJ3!5)J#!)K)!)L)#!")4!")L!)!b-)%#!")`J3)!%K#!8 Q)#!)%#!J!b)J#!%L)#!")a!J)!%K%!-K%!%K)!3M#"!J!5%)!5)J)!%N%#!J#!% K)!3M)!J3!L%)!5%J!L%3!5%J!5%3"5-J#"!#*3J3)#!)!5)J)!%L%#!$*L!J#"! J)!8L%#!")3J$)3J#)5!")K!J!b-J)!J#)5!#)5!")JJ3!5)J#!3M%#!J!5%3"#% J!5))%!%M)!J)!5)))!)K#!)K!J)P#!)))!J$)3J")JJJ!b)J#!3K!J%M)!J#!L3 )!JJJ!5)##!%M#!))!L-###!#)3J%)b!)!J)K#!)L)!J")3J$)JJJ!5)##!)K!J% M)!J#!53J#!))!b)))!JL#!)")L!)!L)J#!%K#!)M!JJJ!5%#!b-###!")3)#)`J ##!-K#!3M)!J#!5%J!L%)!L3###!)!5%)"#)J#!)M)!J#!L))!J%L)!J%)3)#)3J ")JJJ"#3)!JJJ!5%#!5)J#!)M)!J#!L%)!5%)!5%)!5)))!3N#!)))!%L!JJ#)J) )!b)))!)L##!")3)")L!)!b-)!JJ"*8!)3""!!5&!!b&!!L-)3"!")3J&)a"!#!% L%%!")d!33!)S%%!)3""!#%!")8!$)8!")8!#)3J&)a"!#!%K%!%L#%!#)3J")K" !!5*!%!3K3!8K3!)P#%!33!J$)3J")K"!!L%3"5))3!-P3""!#%!")N!)"#*!%!8 P#%!33!J")4!")3J#)8!"*%!33!J#)d!)3!-K3!%L3!J#)8!")8!%*4"!#%!3!5- )3"!$)4!#)8!")8!&*8!33!K!!L%)!L&!!L%3!5%)!5)33!%M3""!!L%3!5%)!5% 3!5))3!8K3!%K3!-M3""!!b*!#!%P%%!)3"!")JK!!53"!C!!#!)q#PCPFQPQH@P ZCb`JF'aPBA0P)(*P,@9ZG'9b)#9c!MJ+"`G0DA0YBA4MD#!Y)(4bH5"KCf&TEJS #)3S"*!(RN!!)!L3"ri$-!LBJ-(JJHb!#)L9i!L)X)!)L)(d#))%!!C!)rT!)(j! %$T!%i*!%mC!%!Ii"rJ(q!Ilq!Ii"rJ(q!4rJ(q!1m3lai"rJ(r%1m3i"i!(J!I% "mH!"i!(a!I%"(riIrJlq$[lq(riIrJlq$J%I!4m"$J%1(`%I!3i"$J(JrZ$qmIl ar[lJrZ$qmIla#b%"JJ)&!!%!!3!"!!%!!38K!B)#"3!"!!%!!3!"!!%#)#l5dp6 9eYIBfGVEh0hHhq$KiZ2NjHERk1RUkqcYlZr`mI,cp2AfprMjq[[mrIlr!5#"&3% #!`3&"JF)#3S,"3B(#!N+#``0$Jm3%4)6&"8@&aJC'KXF(4iI)#%L)b3P)#%L)b3 P*LFS+5SV,#dZ,c!a-M-d06Bh1$Nk1c`p2Mp!38*$4#i[-$%b-c3e0MFi18&#3d4 &4NG)58T,6%e16e"48P0899CA@&PDB@*MC'9QCfKTDQYXE@j[F(&bFh4eGRGiHAS "ri#N#5)3)!-K)!)K%!%K!3-K!3%M%#!"!L)J!3%K%!)K#!-M#"!J!5%)!5%J!5) )%!%L!3J#*J%)%#!"#!%N)!%)%!-K)!-L-#!#)L!J!L%`!5%"!5%J!5%"!5-`)!% ")b!J!3%K-!)L##!#)`J`)!%M##!J!5))-!%M!3JJ!5X"#$!J!3JJ)!%)-!%K#)% $"`!!#"!J#!!J#"!!#3!!#4!J#3!J#5%3!5))#!)Q#!J3)!J)!53J#!J3!5)*#!) Q#3J3)!N)!53J#3J3!5%)J3-()!!)-#!))#!)-!!*)!!*-#!*)#!*)6!")`J))!% V#!J`)!J))#!)#$!")`N))!%V#3J`)!N))#!*#$!%)3)&)5!")3)")5!#)5!#)J) J!b)J)!%M!L!J"#)%!J)K"!)M)!3#!5)J"!%K)!%M"!)J!5%%!5FJ)!3#)#!%!L% %J3-(!J!%!!!N!J!N!#!%!L!%!#!N!L!N!L-%"!)")J3%!L-N"!)")L3%!5FJ"!3 #)!3%!5JJ*!3#)#3%%!-K%J-K%!%K)!%K%J%K)!%L%#!#)K)J!L-3)#!")a)J)!% K%!)L"")#)J33!5-J"")"*#!%%#!")`35)!%U""!J)!35)#!%%!%K")%$"a)!""! !*")!*"!J"")J""!J*")J*#%3!5-%"")")`3%%!%M*!35!6)N""!J"!35)!3%%#! N"")J*!3()3%")35"!`d!!!3"!3!!!3!"!33!!33"!!!#!!!$!!3#!!3$!3!#!3! $!33#!33K!`)K!J-L!J%")J3#!L3%!J%"!5%#!5%"!58#!3%%!J%N!33#!3)L!J) #)J)$!5-%!J)"*!3#!`%")`)#!3%V!J-""!)#!33#!`J$)3J#)`%)")%$$3!)"!% *!!!*!!%*"!!*"!%)!!))!!-)"!))"!-*!!)*!!-*"!)*"#)$#!%K!J%K#!%P!J% )"!)"*3J%!J%*!5%#!5%*!58#!3N%!J%P#33#!3J")`)##!%V!J-)"!)##!3#!`N ")`)##3%U!J-*"!)##33#!`8K%!3K!3)L%!%%)3L"!`S3!!J!!3J3!3J!%!!3%!! !%3!3%3!!%!J3%!J!%3JN%"%)"!-L""!#)33")3%")`33!3%K"!)M#!33!5))"!% R!3J%%!%)"!%K%!%M""!3!5%%!5%4!5-%%"%")33"*a!)""!3#!3"*K%)""!4#)% $$`)!!")!!!)"!")"!!)!#")!#!)"#")"#!)3!")3!!)4!")4!!)3#")3#!)4##8 5%3J%!J)L"")#)`3#!3%M"")"!5)%!J%M#!35!5`)"!)"#!35!3J%!K!")`35%!% M"!)4!5-%%K%"-!3#%!J%%K!)"!)4#!35%3J%)4!%)3%#)K!""5)%%!)K"!%K!B% $'333!33J!!!`!!!J!3!`!3!J!!3`!!3J!33`!33!%!!3%!!!%3!3%3!!%!33%!3 !%333%33J%!!`%!!J%3!`%3!J%!3`%!3J%33`%5%%!L%3!5%3!5%3!L)"%!%M%!% 3!b-3""!")K!%!5J"%!33!4!%)!%K%!%K-!%K%!%M)!%3!5-`!4!")5!")a!%-!% U%!3J!4!%-!%3"!%L%"!")a!3%!)L%4!")a!4%!)R%"!%%"!3"!%U%4!%%"%3"#! 3%!%M-"!3!5-J%4!")c!4%!%`)"!3"$!3%!3J%4!%-"%3"!3K#!BL#!J#)3J#)33 ")3J")33$)`3)#!%L"!J")3)#)JJ#!b%#!5-)#!)")3J")J)%!5-)!J3#*`)%#!J #"!J$)J%)J3-'!!%!!!N)!!N!"!%)"!%!"!N))J3*!5%#!5-"#!)")3%")3)")`N )!J%K#3%R!J3"#!)%!3%S!J3*#!)%#3+"!`F!!!S!!!)!#!S!#!)%!!S%!!)%#!S N"!J#!J)L#J)#)J)#!5-)#J)"*!J#!J3")`S#"!%T!J)%#!S#"!J#J3-(!!%+!!% #!!N+!!N#"!%+"!%#"!N+*!3*!J)")`%+!J%M!3)#!5-*#J)"-3N#!J3"#J)%!3) #"!N+!J3*"L%"J3-'!!J!!!J"!3!!!3!"!3J!!3J"!b%3!L)"%!%K#!%K%!%N#!% 3!3)L%!%"*!%3!3J"*4!"#!%3!5%J!b)J!B%$"J!S!!!S!3%J!!%J!3%S!!%S!3% K)!%K%!%M)!%3!5%S!5%3!58S!4!")!%R%!%J!4!"+!%P%!%S!4!#)3+"!`F!!!- !#!)!#!-"!!)"!!-"#!)"#!-#)J)3!L)$%!%M#!)3!53)!a!"!5-#%!%"+J-3!3J #%!%)!a!")L!#J3-(!#!$!#J#!#J$!5!#!5!$!5J#!5J$!5-J!K!")b!$%!%M+!) 3!6-S!a!")!)3!5!$%!%S!K!"+!-3"#%%"#%%!L)%"!8L!J3#)3)")33")`)%"!% K!J)K)!%K"!%K)!)L"#!")`3%)!-M)!)%!5)J!J%R"#!#"!3J!J-L)!3#)5!")33 ")b!%"!%K)!-L)J3#)5)")33")b)%"!%K)J)M)#!%!5)J)!%R"#!J"!3J)!)M)#) %!5)J)J%R"#!L"!3J)J)K#!%K"!%K#!)L"!J")`3%#!-M#!)%!5))!J%R"!J#"!3 )!J)K+!%K"!%K+!)L"#J")`3%+!-M+!)%!5)S!J%R"#J#"!3S!J)M##!%!5)))!% R"!JJ"!3))!)M##)%!5)))J%R"!JL"!3))J)M+#!%!5)S)!%R"#JJ"!3S)!)M+#) %!5)S)J%U"#JL"!3S)J))#!)K#!)K!J)Q!J))#!)#"#-)#!)")3J")J)#!L%#!5B )#!)##!J")J))"#-)!J)")`J#!JJK#!%K!J%K#!8L!J)")3J#)JJ)!5B##!J#!JJ %)`J#!J%K#!3K!J)K#!)L#!J")J))!5%#!L%)!5%#!53)!J))!5%###8##!J#!J% K#!)K#!%N!J))#!)K#!3M#!)#!5%)!5)##!%K!J)K#!)L#!J")3)#)3)")`J)!J- L!J)#)`)##!)N!JJ)!J%L#!J")J))!L%#!5-)!J)&)JJ#!5%)!5%#"5%)!L%#!b% #!58)!J))#!3M!J))!5%#!L%)!LF)#!*!%)!3"5)3J!%L3"!#)8!#)4!#)i!33!% KJ!)L%)!$)B!")N!3!5%3!b)33!%KJ!)K%!%N%%!3J!%L3"!&)4!")4!#)8!"*)! 33"!")4!#)B!#*"#!%%!))4!")K"!!5+!%!%Q%)!33"#!!5&!!L)33!3K%!3QJ"" !%)!3!5%3!5333"#!!5&!!5'!!LF3J""!%)!3!5%3!5)33!)K%!3K3!8LJ"!")4! #)N!3!5%3!L'!!5&!"#33J""!!5@!%%!3J!-KJ!8K3!)K%!-P%%!3J"!")K#!!5* !%!)L3"!")4!")4!%)i!33!%KJ!%K3!%LJ"!$)a"!%!-L%)!")33#*!%%"!%$)3% ")33")J%"!5%%!5)""!-K"!%L!3%")J3"!5%%!5%"!L%%!L)%"!8P!33%!3%#)J% "!b-""!3")3%&)33"*!%%"!%$)3%$*J%""!3"!3%K"!)K"!)M!33%!5)""!%K!3) P"!%""!3$)J3""5%%"#B%!3%%"!%$)3%%)3%")33%)J%"!5%%!5-""!3#)33")J% ""#-%"!%#)J3"!5)%"!%K!3%K"!%L!33$*!3%!3%$)3%"*!3"!33#)J%%!b3%"!% "!5%%!L%%!5%"!5%%!5)"!3%L"!%")33")3%&)J3%!5%"!L-"!33#)3%")`3"!3) K!3%L"!3$*%!3#"!")4!%*3J33"!)"#)33!)K%!%L%!J")8!"*!J33"!")4!#)JJ 3"5-3#"!#)3J")d!3#!%K3!)K%!-L%%!")3J")N!3!b%3"#%)!5*!%!%K%!%N%!J 33!3K%!-L%!J&)8!"*!J33"!")4!")4!")K"!!58)%%!3#!%K3!)L%%!")3J#)K! )!5&!!L%3!L%)!5*!%!%K%!%K%!3M#""!!L%3!5)3#!BK%!)K3!%K#!3L%%!"*!J 33"!$)4!")4!$*""!%!J")d!3#!%K3!)N%%!3#!-L#"!")4!#)d!3#!%K3!%K#!% L3"!")K"!!L%3!5)3#!)M%!J3!b%3!L3)%%!3!5%)"#%""#%%!5B)!33J#!%")L! )!5%%!L8""#!)!3-K!38L)!J#)5!")J%%!5%)!53%)!J"!53J#!%%"L)""!%K#!3 K!3%K)!)M"#!)!5%%!L-""#!%)3J#)5!$)L!)!5B%)!J""#!")3%")b!)!33K"!- P"#!)!33")`J""!%K#!%L"#!")3%")b!)!3-K!38L)!J#)L!)!5%%!5%)"#)""!% N#!%%)!8N!33J#!8K"!)K!3%L)!J")J3J!L%%"5B)!33J#!%"*#!)!33$)J3J!5% "!b)""!%L#!%")L!)!5%%!b)%)!-K)!%P!33J#!%#)3J#)L#!!L&!!5%J!5&!"#1 !)#!#)5!")8!#)5!")B!")L"!!5%J"#BJ3)!J)%!")L!J!5'!!b'!!5%J!5'!!L0 !J#!$)b!J3!%K)!)KJ!%N)%#!)!%K3!BK)!3N3)!J)!%LJ#!"*d#!)#"!J#!#)B! &)L"!!b&!!5)J)!)N)#"!J!%K)!-M)%#!!b'!!5%J!LBJ)%#!)#!#)5!")8!%)B! ")5!")B!&)5!")S!J!5&!!5%J!b%J!59!J#!J3!%L)#!%*8#!)#"!!5)J)!)K)!) KJ!%M)%#!!L0!J#!$)b!J3!BK)!%KJ!)L3)!"*5"!J#!J!5+!)!3L)%!$)d#!)!% K3!)K3!-K!J%K!B%$(3)!!3!%!8)%!%!%!%)!N!3"!!!"!J3!!J3"3!!!!!3"3J! "3!!!!J3"!J3!3!!!3!3"3J3!!!!"!J!"!!3!3J!"3!3!3J3"3J!!!!3!3J3"3!3 !!J!""#0#"!'"!`T!!!&!"!!#"!"!!!!#!!%!!!&!"!%#"!"#"!"#!!!%)3)")3' "!a)!"!!!"!%#!*!%!3)%!3)!!%)!!!)%!%!!!8)%!3!!!8)!!!!%!%!%!8)%!3! %!8)!!8!!!#4!"##!J3-HJ###!!!#J!!!!#!#!!#!J##!!###J!!!J#!!!!##!!! #J!##J#!#J#!!J##!!!!#!!##J!#!J#!#!###J#!!J!#3"))!)!!!!)!!)!+!))# !!)!!!!)!)))%)B!")B!$)3)#)5!#)i!JJJ%KJ!%K!J%LJ#!))B)#)L#!!51!)!) ")i!J!J-KJ!%MJ###"5'!!5'!J3-*J#!#!###J!#!!##!!#!!J!##!!!#J#!#J## !"#1!))+"!`F!!)+!!!!!)!!!))#!!!)!!)+!!!!!J@%L,(L#!LXXJ#b),@JLVLb B'QJCk#Xq,+JDVKQS,,JC+"NN'5!C("N8,-JXd"N''1`Bc#Xk,2!Xq#d!+V)UZLd 3,4JY)!6'!-B!TJ"Q!#B!"Ld`,6JY3!c'%-B)aJ!J)Mmm!5-'UI!#)[rp%L)X3)) #2J!`,%!!!La!8p`X3%dN,%"-lLa!5I3X3$"5,%![pLa!,eBX3#i`,%!XDLa!+rB X3#VX,%!TS#a!+5BX3#MH,%!SK#a!*k)X3#G',%!Qi#a!)fBX3"M8,%!ATLa!&U3 X3"#F,%!,9La!!-)X3!#8,%!!6#a!+j!!9+S"5!$3'5)#!3%K#!3L-!%")3J%*%` "!3J%)T3"!5%)"#(#"L8Qi!%J#!-P*dB")!J$)bHL!3%K)!-P+)3"!3J$)LMH!L% )!b8T*J%"#!-L+D!")[m)!b)UEJBP+Z`"la!$*L[frrrXKJ)Q,'Vrrqc)!LBZ-2r rl-i#*5p@!@%)!b8[pJ&K#!-L-&)')dcZ!3%K#!-Q656rrqjS!L*1`!BP8p`"j`J $)P5U$2q3"!#3"`%!!#eJ!!!!!3!!,9J!!!!$!!!!%!!!!!%!!!$-!!!!h!!!!fJ !!!!%!!!!'J#3$`d!N!YQ!*!,!J!!!!d!N!HM!*!,!3!!!!m!N!3"!!!0!J!!&3) !!"X#!!!L!J!!+`)!!$)#!!!j!J!!2`)!!%B#!!",!J!!8J)!!&F#!!"I!J!!H3) !!)m#!!#`!!%!N!8(!*!%S!!V8%S23LZ!0dBG3J!!!%e*9&qP68P83daTBJ"IAfC TE'9c!'CRCA4c!("bD@jdCJ"ME'9KFQ9bFJ"QCQaeFfJ!Fh4bBfKb!(0bB@jN!(0 dFQ0YF!"bB@jN!'ePE@0YF!"dD@eP!'C`FQPZG'B!E@9YFf9d!%e*9&qP68P88R9 ZG'PYC8aTBJ"IAh9ZFQ9RDA0dCA*ICR*KCfePER3!AepbC@GTFh4PFPpQFQ&RE@9 ZG!"*ER4PFQCKBf9-D@)!9'PMDd0[G@jd!'4PFepNC@*eC`"NCA0IFQ9KC&p`BA0 cGfpbC!"NCA0IFf9dAh0PFA9PEQ0PAfjeE@*PFJ"NCA0IFf9dAfYPH3"NCA0IDA0 IGf9KDepVCAN!C'9cAh0dFQPZCepdEepVCAN!C'9cAfjPGepbB@jNEfeIDf9j!'4 PFepMBQa[BfYIF(*TER4ICQPXC3"NCA0ICQ0bHA"d!'4PFepMD'9MDepVCAPIF'& bDA4j!'4PFepQDAKeF&pVCAPIF'&bDA4j!'4PFepbB@jNEfeIDf9j!'4PFepMFRP `G!"NCA0IFQ9KC&p`GepcG(*TEQF!C'9cAfPZDA4IFQ&ZC'pYAfjeE@*PFPpRC@j PFQ&dEh)!C'9cAc0PBf*IC@jMFRP`G!"NCA0I-f0LBepPEQ0bHA"d!'4PFepcCA4 IFQ&ZC'pYAfGPEQ9bBA4[FPpcC@9N!'4PFepVCAPIFf0SC@3!C'9cAh&eB@4IBfY cG@d!E@&VC9pVCAPIFf0SC@3!C'9cAf9MBPpPEQ0bHA"d!'4PFepMBQ0IC@jMFRP `G!"NCA0ICf9ZCA*KG'9IFQ&ZC'pYAf*XEf0V!'4PFep`Bf*MAf9ZBh*jF(3!C'9 cAf0LBepMDh0eE3#3"J`!!!!-!!-!"!!'!!3!"`!-!!J!"!!,!!3!$!!!!!d!#!! 0!"!!$`!)!"-!!!!9!!J!&3!!!"F!$!!A!!P&c3!4Ne3!&qjR!!X54J!2A8B!%@Z E!"+dQJ!92mJ!#SY3!"5G&!!8G43!$TIE!!P&F!!5*$S!)-,&!""&S!!38U!!(A6 '!!e6#J!1K8m!$SX,!!pR`3!2I-%!'4$K!"!kT3!0A`m"!!#k!!!UVJ!"!J!!a!! !,0J!!3)!!0B!!#ci!!%#!!$Z!!!XU!!"!J!!qJ!!,,J!!3)!!3S!!#c)!!%#!!% F!!!Y%!!"!J!",`!!,-!!!3)!!88!!#bB!!%#!!&3!!!Y-!!"!J!"C3!!,6J!!3) !!AS!!#cJ!!%#!!'*!!!XS!!"!J!"N`!!,0!!!3)!!DB!!#d)!!%#!!((!!!XN!! !!3)!!GJ!!#b`!!%#!!(T!!!Y!!!"!J!#"`!!,4J!!3)!!K8!!#cS!!%#!!)N!!! Y)!!"!J!#-`!!,8!!!3)!!N-!!#e3!!%#!!*6!!!Xm!!"!J!#E3!!,5J!!3)!!Ri !!#e)!!'Y-`!!!3!!!!&F!!!!A!!!!$)*H6d`1`S*G6d`H$J`1`S*BQ*E1&dp-$X +#@C[FL!SD6db1b"T2$%c1b"T+bXT#JN*H`S*#@-p-$X+#3PQEh)J+'Sp-$XJDM` f1b"U+bXT#JN*#AX+#3N*Bc`m26%l#JN*#@PQ)#KLBPYjA5!Q)(8T)'0m26%l#JN *#A8q2Mda1`S*#3PTCL!S)A8T#JQ3"(X+#C!%H5XV1`S*N!4e26"i1$!l#JQ3"(d +#3N*I3S*#A*PG&YTA6eMEhCI-Q0SBA*EBedl#JN*I3S*FQ9d@c%cA6dRA$!R1`S *FQ9dGA*Z+(*PG#Nl#Rd+#Jb+D!!!!&J!N!X"!*!6!@df1'X!N"-"!*!41!Y0594 IT@4PFfaTBJ#3"!%!!!!"A!!!!&`!!!!b"Q)H3&b+!!!!(!!b!!"MCR*R!!!!#J! !rrm!N!Kaa!: \ 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
index 92bb24e5fd..0000000000
--- a/src/mac/libraries/DES/bin/deslib.68K.debug
+++ /dev/null
@@ -1 +0,0 @@
-(This file must be converted with BinHex 4.0) :%'4PFfaTBLif1%XZC'9LG@F!FfKXBMq3"!#3")8m!!!"NUpB5Qpj)A"PCQCY0MK V!!!!!E*@K4N!N!d$!!)!N!j8UJ!!9+S!!&5U!!!!P!!"!J#3"!8!N!BZB!!!,Q! !!#VF!!"93!)"!J#3"!i!N!i&)!!!J"`%!3)!6@&TEJ!P369AEh*XC!"-Ef&NCA) !N!41G5T46PErq#m0)!d[!#mYre`LEIp))&P1N!!UE[rd+d$r$'(rN!6FF!"1ANj d!!3U88j@rrJ[$5mYr``LEIp%)&P1N!!UE[rd6Pj1G5T46PErq%MR%!4f!#mZ!!J LEIpB)&P1N!!UE[rd0J!`!dM!C`3`!f!#-!-Q(djH6R3!"*0IAfPZDA4TB@aTHQ9 IC'9cE'PL!!!U88j@rrJ[$5*Yre3J@8k3!#TZrr41ANjeNPpIG'9bE@PZBA4PAf4 PFfaTBJ!!!#T46PEri%MR(cJX,J!)*Li!$#iZ!"!SEJ!B*'i!&%UZ!"aR!!8@*Na k!"SEFKMMVA!!%"Yb%11SLS"`!"!EiBL+J(!!%"Z+J(J!'"Yb'11XF!!3'h)3ikL )J(!!%"[KL)L!F!!3'iL!*NBS3f!!"-*`#,k!EAT`!"!E!S!!!!$rFKMMU,'&F!! 3'`+!!!!!rh)3ikLaKA!!%"X#J!!!!2rKL,'&F!!3'`+!!!!!rl'&F!!3'`+!!!! !rh)BikLaK(!!%"X#J!!!!2pb%11SXB4`!"!E!S!!!!$riBLaK(!!%"X#J!!!!2q aK&'(B!!!NYI()!F-J!!!!!GL!!##-$X#"Nll!!)!H!"S!&J!5J!q!#i!(J!3F!! 3)`+!!!!!rq')XB4`!"!M!S!!!!$rFK$MU,'%F!!3)`+!!!!!rh)BikLaK(!!%#- #J!!!!2qaKA!!%#-#J!!!!2rKL,'&F!!3)`+!!!!!rh)3ikLaKA!!%#-#J!!!!2p b'11SXB9q!#!%!S#UN!6LL#B&!S1UN!5'J#!%!S"9N!3L"3+"9C!%dS'#J#J"+J4 b%1+Y!S8!!!$r)'hrr#S`A!$DK5)%G"MNU3+"!!!!rb"Yrrb+X"`!)J6JL3+"!!! !rb"Yrr`L-"`!jBQ#K5S%!S8!!!$r)'hrr#S`A!$RMBU"+!0b%1+X!S3!!!$r)'h rr#J`6!$BK#)$G"MNU3+"!!!!rb"Yrrb)X"`!)J2JL3+"!!!!rb"Yrr`L-"`!jBQ #K#J$!S3!!!$r)'hrr#J`6!$RM)L"I!"J!!'B*J4b&H1V)J4d#q5TJS-Q'V1$F$m L!h3Bj+R#J#"YrrK`2b3$,8$ri(!3i+V%V[rJjBSLEIridm)J+3%!J,!F!()r*!2 JLX5"jBSJEIridF+!U!)!FMr#Jq@*)'hrq0("J+J$!,'&*J4b#H1V)J4d&q5TJS- Q'V1$F$mL!h33j+R#J1@*)'hrq0("F$mL!h3Bj+R#J1@*)Qhrq02")#N%!)#S"3" b2b3$i)V%JH@+)'hrq0(#J+J'!()r`S2PL5"YrrM4`B#S"`#aK5B&FKAMUb)&G![ NUB+$*KUcJh!r)J0d'15T`S!JEIriF$mN!be!rq"`%1#Ua+lri1@+)Qhrq02#)#N "!)#`(!"b2b3$i)V%JH@+)'hrq0(#J+J#!()r`S2PL5"YrrM4`B#S!`#aK#B&FJR MUb)&G"INUB+$*KUcJh!r)J0d%15T`S$PL5"YrrM4`A!r)J0d'15T`S$PL5*YrrM 6`5!T"!#!U!8!FMmN!q#+a)(PLL"YrrM4`S#S"J"b2m+$jBNJEIridF'!U!F!XB4 5KR!)[)"Y!2jN)!8#J2#3"1L)*J3#Jr#3")D!)!8#J!q3"#)%!S%2N!6TLB+!+!% U"()3iUd#K3!!!2mJEIrd+M"F!1Q0)J4d'15T!S%!!!$r)'hrp#)`(!$YLB+&+J6 JM3+&!!!!rb"Yrr3U-&`!jBf+J5)%!S%!!!$r)'hrp)U`(!!S!h)3iU`#K!!!!2m JEIrd+$"-!1Q-)J0d'15T!S%!!!$r)'hrp#)`(!$YLB+%+!2JM!+%!!!!rb"Yrr3 S-%`!jBb)J5)$!S%!!!$r)'hrp)L`(!"&k[q!)!9b'1+S!S!!!!$r'-!J"A)3iUJ #J!!!!2mB`#!&i)J#J!!!!2mB`#!&!S!!!!$r'-!J"()BiUJ#J!!!!2mB`#!%FK$ LU!+!!!!!raM!)!6JL!+!!!!!raM!)!3#J!!!!2mB`%U(EJ$l2'!!"6j+Kfi'F!" J!!8f*Na`!"!EFKMMU#e!rr4`!"!EFK$MU)'Zrr4`!"!EiBL"V[rdF!!3'i'Zrr4 `!"!EFKMMU#e!rr"`!"!EFK$MU)'Zrr"`!"!EiBL"V[r`F!!3'i'Zrr!Q4LK$HJ! D'h)Bike`!"!EFK$MU)U!F!!3'q')LS"`!"!ELS"i!"JEFKMMV(!!%"Yb%11SL)" `!"!EiBL)J(!!%"Z)J#e&rq`Y42rS)!3#J+U3"1+)*J8#JkU3")D!)!3#J&@3"#) &!S&9N!65JB+!+!%U"()3iUd#K3!!!2mJEIrm+M"F!0U&)J4d'15T!S%!!!$r)'h rr)U`(!!L"1#*!S%!!!$r)'hrr#)`(!$PLB+&+J3#K3!!!2mJEIrm+M"F!1H0LS% S!h)3iU`#K!!!!2mJEIrm+$"-!0L%)J0d'15T!S%!!!$r)'hrr)L`(!!L!q#*!S% !!!$r)'hrr#)`(!$PLB+%+!-#K!!!!2mJEIrm+$"-!1H-L)&&kJ#!I!"J!!()*J4 b#H1V)J4d&q5TJS-Q)V1$F$mL!q#*`S$PL5"YrrM4`A!r`)2PL#*YrrM6`#!T"`# !U!B!FMmN!be!rq"`%1#Ua)(PLL"YrrM4`L!S"3#!V[rJFMmN!be"rq4b'1+Ua+l rj1@+)'hrq0(#J+J%!,'&*J4b&H1V)J4d#q5TJS-Q)V1$F$mL!h3Bj+R#J#"YrrK `2b3$i)V%J1@+)Qhrq02#F$r!Jq@))M!F!#"YrrM4`#!S!`#!U3)!G$mY32rN)!- Y3IrJFK$LU-##jBJJEIridF!J+!%!J+lrj)#Zrq#aK5B&FJRMUb)&G"INUB+$*L+ cJh!r)J2JLF+!jBNJEIridF&`2m#$jBJLEIridm!J+3F!J+J'!()r*!-Y32rNF"$ JUX5"jBSJEIridF)J+!8!J+lrj()r*!-Y3IrJFKMLUX5Zrq$PLL"YrrM4`S#S"!# aK#B&FKAMUb)&G![NUB+$*L+cJh!r)J0d'15T`S!JEIriF$mN!q#+a)$PLL*YrrM 6`R!r`)2PL#)`(!!JEIridF!J+!-!J+N#!(3r,8$rj#!$,8(ri()3iUM!JZ@))'h rq0(!)#J"!)#Zrq5!V[rJXB45KR!)[)"Y!2id)!8#J2#3"1L)*J3#Jr#3")D!)!8 #J!q3"#)%!S%2N!6TLB+!+!%U"()3iUd#K3!!!2mJEIrd+M"F!1Q0)J4d'15T!S% !!!$r)'hrp#)`(!$YLB+&+J6JM3+&!!!!rb"Yrr3U-&`!jBf+J5)%!S%!!!$r)'h rp)U`(!!S!h)3iU`#K!!!!2mJEIrd+$"-!1Q-)J0d'15T!S%!!!$r)'hrp#)`(!$ YLB+%+!2JM!+%!!!!rb"Yrr3S-%`!jBb)J5)$!S%!!!$r)'hrp)L`(!!J,[rdXB8 J,[r`XB4`#,k!EhC4Kb!&FKMLU!+!!!!!raM!)!9b%1+S!S!!!!$r'-!J"H#)!S! !!!$r'-!J"3+!!!!!raM!)!4b'1+S!S!!!!$r'-!J"()3iUJ#J!!!!2mB`#!%i)J #J!!!!2mB`#!%!S!!!!$r'-!YE[rXrr3YE[rSrr"J!2ZffFFJ"`b!!!!!#')!!)! `1`)'6[X!!J"f!'J!@J"1!%3!0J!S!"`!%L!%!S!!!!$r'3!J"1#)!S!!!!$r'3! J"()3iUJ#J!!!!2mC!#!%FKMLU!+!!!!!raN!)!8#J!!!!2mC!#!&i)J#J!!!!2m C!#!&FK$LU!+!!!!!raN!)!9b'1+S!S!!!!$r'3"`!%cI(2K1ANjd!"L2C'9cAf0 LBepPEQ0bHA"d!!!U88j@rr4)jami+'i!&#CZ!"Kk!"SEFKMMVA!!%"Yb%11SLS" `!"!EiBL+J(!!%"Z+J(J!'"Yb'11XF!!3'h)3ikL)J(!!%"[KL)L!F!!3'iL!*Qi !##iZ!""J!!4JF!LqJ'ekF!!3'`+!!!!!rh)BikLaKA!!%"X#J!!!!2pb%11SXB9 `!"!E!S!!!!$riBLaKA!!%"X#J!!!!2qaKA!!%"X#J!!!!2pb'11SXB4`!"!E!S! !!!$rFK$MU,'%F!!3'`+!!!!!rq')XB4`!"!E!S!!!!$rXB44Kf!!!*,Aab!($)! !!!!(BJ!!JM!l!JC1q`!#!(J!D!"B!%S!2J!Z!"i!%(!!%#-#J!!!!2rKL,'%F!! 3)`+!!!!!rh)3ikLaK(!!%#-#J!!!!2pb'11SXB4`!"!M!S!!!!$rXB9`!"!M!S! !!!$riBLaKA!!%#-#J!!!!2pb%11SXB9`!"!M!S!!!!$rFKMMU,'&IJ!N6#!%!S# UN!6LL#B&!S1UN!5'J#!%!S"9N!3L"3+"9C!%dS'#J#J"+J4b%1+Y!S8!!!$r)'h rr#S`A!$DK5)%G"MNU3+"!!!!rb"Yrrb+X"`!)J6JL3+"!!!!rb"Yrr`L-"`!jBQ #K5S%!S8!!!$r)'hrr#S`A!$RMBU"+!0b%1+X!S3!!!$r)'hrr#J`6!$BK#)$G"M NU3+"!!!!rb"Yrrb)X"`!)J2JL3+"!!!!rb"Yrr`L-"`!jBQ#K#J$!S3!!!$r)'h rr#J`6!$RM)L"I!"J!!'B*J4b&H1V)J4d#q5TJS-Q'V1$F$mL!h3Bj+R#J#"YrrK `2b3$,8$rp(!3i+V%V[rdjBSLEIridm)J+3%!J,!F!()r*!2JLX5"jBSJEIridF+ !U!)!FMr#Jq@*)'hrq0("J+J$!,'&*J4b#H1V)J4d&q5TJS-Q'V1$F$mL!h33j+R #J1@*)'hrq0("F$mL!h3Bj+R#J1@*)Qhrq02")#N%!)#S"3"b2b3$i)V%JH@+)'h rq0(#J+J'!()r`S2PL5"YrrM4`B#S"`#aK5B&FKAMUb)&G![NUB+$*KUcJh!r)J0 d'15T`S!JEIriF$mN!be!rr4`%1#Ua+lrp1@+)Qhrq02#)#N"!)#`(!"b2b3$i)V %JH@+)'hrq0(#J+J#!()r`S2PL5"YrrM4`B#S!`#aK#B&FJRMUb)&G"INUB+$*KU cJh!r)J0d%15T`S$PL5"YrrM4`A!r)J0d'15T`S$PL5*YrrM6`5!T"!#!U!8!FMm N!q#+a)(PLL"YrrM4`S#S"J"b2m+$jBNJEIridF'!U!F!XB45KR!)[)"Y!2jN)!8 #J2#3"1L)*J3#Jr#3")D!)!8#J!q3"#)%!S%2N!6TLB+!+!%U"()3iUd#K3!!!2m JEIrd+M"F!1Q0)J4d'15T!S%!!!$r)'hrp#)`(!$YLB+&+J6JM3+&!!!!rb"Yrr3 U-&`!jBf+J5)%!S%!!!$r)'hrp)U`(!!S!h)3iU`#K!!!!2mJEIrd+$"-!1Q-)J0 d'15T!S%!!!$r)'hrp#)`(!$YLB+%+!2JM!+%!!!!rb"Yrr3S-%`!jBb)J5)$!S% !!!$r)'hrp)L`(!"&k[q!5SGZ!2ZH*Qi!$#!&FKMLU!+!!!!!raE!)!9b%1+S!S! !!!$r&X!J"H#)!S!!!!$r&X!J"3+!!!!!raE!)!4b'1+S!S!!!!$r&X!J"()3iUJ #J!!!!2m@`#!%i)J#J!!!!2m@`#!%!S!!!!$r&X!J"%cI(2K1ANjd!"50C'9cAf0 LBepMDh0eE3!!+P&19[r`51FH-#CZ!"!NEJ!)HJ!D'R)Bike`!"!DFK$MU)U!F!! 3'Z')LS"`!"!DLS"i!"JDFKMMV(!!%"Tb%11SL)"`!"!DiBL)J(!!%"U)J#!%!S# UN!6LL#B&!S1UN!5'J#!%!S"9N!3L"3+"9C!%dS'#J#J"+J4b%1+Y!S8!!!$r)'h rr#S`A!$DK5)%G"MNU3+"!!!!rb"Yrrb+X"`!)J6JL3+"!!!!rb"Yrr`L-"`!jBQ #K5S%!S8!!!$r)'hrr#S`A!$RMBU"+!0b%1+X!S3!!!$r)'hrr#J`6!$BK#)$G"M NU3+"!!!!rb"Yrrb)X"`!)J2JL3+"!!!!rb"Yrr`L-"`!jBQ#K#J$!S3!!!$r)'h rr#J`6!$RM)L"5Ui!&'F!!D`N5h`!B!!"Q#B%FKAMUb)%G![NUB+$*KUcJh!r)J0 d'15T`S!JEIriF$mN!be!rr"`%1#Ua+lrm1@+)Qhrq02#)#N"!)#`(!"b2b3$i)V %JH@+)'hrq0(#J+J#!()r`S2PL5"YrrM4`B#S!`#aK5B%FJRMUb)%G"INUB+$*KU cJh!r)J0d%15T`S$PL5"YrrM4`A!r)J0d'15T`S$PL5*YrrM6`5!T"!#!U!8!FMm N!q#+a)(PLL"YrrM4`S#S"J"b2m+$jBNJEIridF'!U!F!XB8Q"A)9ikXL"A3,j+Q #JbBDXi0`2b)$G"MNUF+!)'hrq(!r*!-Y32r`F"$JUX5Zrr$PLL*YrrM6`L!T!3# !X"`!FMmN!q#+a)(PLL"YrrM4`S#S!J"b2m+$jBNJEIridF'!U!-!XB3Q"A)*ikX L"A3Aj+Q#JbBDXi0`2b)$G"$NUF+!jBNJEIridF&`2b)$G"MNUF+!jBNLEIridm% J+33!J+J&!()r*!2JLX5"jBSJEIridF+!U!B!FMr#Jq@*)'hrq0("J+J(!,'%8SC `#,b!E3$qC'!!!G`N5dAU!)"m!'!!!FJQ"()*ikXL"(3Aj+Q#JbBLXi0`2b)$i)R #J1@*)'hrq0("F$r!Jq@))Qhrq02!)#N(!)#S"J"b2b3$,8$rm(!3i+V%JH@+)'h rq0(#)#J&!)#Zrr"b2b3$,8(rp()BiUV%V[rdjBSJEIridF+!U!3!XB8Q"()9ikX L"(3,j+Q#JbBLXi0`2b)$G"MNUF+!)'hrq(!r*!2JLX5!jBSLEIridm*`2m#$jBJ L-"`!)'hrq0(!)#J$!)#T!J"d2be!rr3J!be"rr"b%1+S`),PL#"YrrM4`#!S!3# !V[rdJ+lrm,'&*J9b#H1V)J9d&q5TJS-Q)V1$F$mL!q#*`S$PL5"YrrM4`A!r`)2 PL#*YrrM6`#!T"`#!U!B!FMmN!be!rr4`%1#Ua)(PLL"YrrM4`L!S"3#!V[rdFMm N!be"rr"b'1+Ua+lrm1@+)'hrq0(#J+J%!,'%*J9b&H1V)J9d#q5TJS-Q)V1$F$m L!h3Bj+R#J#"YrrK`2b3$i)V%J1@+)Qhrq02#F$r!Jq@))M!F!#"YrrM4`#!S!`# !U3)!G$mY32rd)!-Y3Ir`FK$LU-##jBJJEIridF!J+!%!J+lrp)#Zrr#aK&+'F!L mJ'd!rM3J"3+!m*!%k)JQ"!+$m*!%KS!J"3+!$j!%)J3#J3q3"1Q*JS!S!5S%FK$ LV3+&!!!!rb"Yrr3U-&`!kBdL"(3Bj+N#J3!!!2mJEIrd)M!F!1f*JS8U"1#0!S8 !!!$r)'hrp#S`A!$PMBU")J3#J3!!!2mJEIrdLV!F!#J$FK$LV!+%!!!!rb"Yrr3 S-%`!kB`L!h3Bj+N#J3!!!2mJEIrd)M!F!1f*JS3S!q#-!S3!!!$r)'hrp#J`6!$ PM)L")J-#J3!!!2mJEIrdL,!F!#4Z!!`J"A)BiUJ#J!!!!2m8`#!&FK$LU!+!!!! !ra6!)!AJL!+!!!!!ra6!)!8#J!!!!2m8`#!%FKMLU!+!!!!!ra6!)!4b%1+S!S! !!!$r&-!J"1#)!S!!!!$r&-!J"!+!!!!!ra6!F!"-h`ai6Pj1G!!3Mf4PFepPBf* IC@jMFRP`G!!!+P&19[rF,`-JEJ!)GJ"J!!$+!M!!rMJ!F!&b!h32,8$rh(!!%$! i!1L!`))8-$J!!S)!!!!2XB,NJX5"F!0b$be"rq"b!")`1!$SJF+Zrq!Y3[rN&$! i!!+#!!!!$l1#a)!J,[rNXB,LJX5Zrpa`!A)$,8$rk(!!%$!i!1L!!S!!!!!2,8( rl")`1!!#J3!!!!qaJH5"`Ulrl(!$,8,rm(3!&$!i!1L#!S)!!!!2,8$rp"!`1!! #J!!!!!qeJ-#Zrr5cJ-#ZrqJL,[r`Xi!+J!!!!!'"-$J!8S0`#,D!C3$r-LBI6Pj 1G!!%P'4PFepQDAKeF&pVCAPIF'&bDA4j!!!!+P&19[rB,`-JEJ!)GJ"J!!$dF!& b!h32,8$rf"!`1!!#J!!!!2lSJ-##G!mY3IrF%M!i!!+"!!!!rX+#XB(NJF+Zrpa `!h32,8,ri"3`1!!#JJ!!!2lSJX5Zrq!Y32rN%$!i!!+!!!!!rJ+!!!!!$l@!`+l rj,1!iS$!V[rBFJ&d!be"rqJ5-$J!!S%!!!$qk)%#J3!!!!mY3[rX&$!i!!+#!!! !rJ+#!!!!$l1#j),%V[rXFJ-Y32r`%$!i!!+!!!!!rZL!!S!!!!!2,8(rp")`1!! #J3!!!2i#J3!!!!qaJF+Zrr5eJF+ZrqJJ,[r`XB%3-$J!G!(!JV#"CJ4`!'!-8S0 `#,D!C3$r#(!"*Kp1ANjd!!58C'9cAf0SC@0VAfYPH9p`BA*TG(N!!!!U88j@rq" )jami,#i!##BZ!!`SEJ!B*'i!&%UZ!"aR!!8@*Nak!"SEFKMMVA!!%"Yb%11SLS" `!"!EiBL+J(!!%"Z+J(J!'"Yb'11XF!!3'h)3ikL)J(!!%"[KL)L!F!!3'iL!*NB S3f!!"-"`#,#Z!""X@Ri!(KYb'11[F!!3'h)3ikL1J(!!%"[KL)k!F!!3'ik!F!! 3'h)BikJY32rdF!!3'h)3ikL"V[rdF!!3'q')JDlrp(!!%"Z"V[rd[i8J,[rdXB4 4VJ!3B!!!TYIZ!"!J,J!3$)!!!!!)BJ!!N!!`1`)'6[X!!J#'!(B!CJ"B!%`!2!! X!"i!%R!!%#-#J!!!!2qaK(!!%#-#J!!!!2rKL,'%F!!3)`+!!!!!rh)3ikLaK(! !%#-#J!!!!2pb'11SXB4`!"!M!S!!!!$rXB9`!"!M!S!!!!$riBLaKA!!%#-#J!! !!2pb%11SXB9`!"!M!S!!!!$rFKMMU,'&3Ui!%#!%!S#UN!6LL#B&!S1UN!5'J#! %!S"9N!3L"3+"9C!%dS'#J#J"+J4b%1+Y!S8!!!$r)'hrr#S`A!$DK5)%G"MNU3+ "!!!!rb"Yrrb+X"`!)J6JL3+"!!!!rb"Yrr`L-"`!jBQ#K5S%!S8!!!$r)'hrr#S `A!$RMBU"+!0b%1+X!S3!!!$r)'hrr#J`6!$BK#)$G"MNU3+"!!!!rb"Yrrb)X"` !)J2JL3+"!!!!rb"Yrr`L-"`!jBQ#K#J$!S3!!!$r)'hrr#J`6!$RM)L"I!"J!!' B*J4b&H1V)J4d#q5TJS-Q'V1$F$mL!h3Bj+R#J#"YrrK`2b3$,8$ri(!3i+V%V[r JjBSLEIridm)J+3%!J,!F!()r*!2JLX5"jBSJEIridF+!U!)!FMr#Jq@*)'hrq0( "J+J$!,'&*J4b#H1V)J4d&q5TJS-Q'V1$F$mL!h33j+R#J1@*)'hrq0("F$mL!h3 Bj+R#J1@*)Qhrq02")#N%!)#S"3"b2b3$i)V%JH@+)'hrq0(#J+J'!()r`S2PL5" YrrM4`B#S"`#aK5B&FKAMUb)&G![NUB+$*KUcJh!r)J0d'15T`S!JEIriF$mN!be !rq"`%1#Ua+lri1@+)Qhrq02#)#N"!)#`(!"b2b3$i)V%JH@+)'hrq0(#J+J#!() r`S2PL5"YrrM4`B#S!`#aK#B&FJRMUb)&G"INUB+$*KUcJh!r)J0d%15T`S$PL5" YrrM4`A!r)J0d'15T`S$PL5*YrrM6`5!T"!#!U!8!FMmN!q#+a)(PLL"YrrM4`S# S"J"b2m+$jBNJEIridF'!U!F!XB45KR!)[)"Y!2jN)!8#J2#3"1L)*J3#Jr#3")D !)!8#J!q3"#)%!S%2N!6TLB+!+!%U"()3iUd#K3!!!2mJEIrd+M"F!1Q0)J4d'15 T!S%!!!$r)'hrp#)`(!$YLB+&+J6JM3+&!!!!rb"Yrr3U-&`!jBf+J5)%!S%!!!$ r)'hrp)U`(!!S!h)3iU`#K!!!!2mJEIrd+$"-!1Q-)J0d'15T!S%!!!$r)'hrp#) `(!$YLB+%+!2JM!+%!!!!rb"Yrr3S-%`!jBb)J5)$!S%!!!$r)'hrp)L`(!"&k[q !)!9b'1+S!S!!!!$r'-!J"A)3iUJ#J!!!!2mB`#!&i)J#J!!!!2mB`#!&!S!!!!$ r'-!J"()BiUJ#J!!!!2mB`#!%FK$LU!+!!!!!raM!)!6JL!+!!!!!raM!)!3#J!! !!2mB`,q&)#lrp,'%5Ui!%'i!qcaJ!!8q5Ui!%'i'F!"J!!8d*Naq!"iEFKMMVh! !%"Yb%11SMS"`!"!EiBL1J(!!%"Z1J(!!%"Yb'11S,8$rm(!!%"Yb%11SJDlrm(! !%"[KL)'Zrr"`!"!EJDlrm#C'+%0k!"SEFKMMVA!!%"Yb%11SLS"`!"!EiBL+J(! !%"Z+J(J!'"Yb'11XF!!3'h)3ikL)J(!!%"[KL)L!F!!3'iL!,8Arl#e%rqJJ"!+ !UT!%iSJQ"3+$UT!%KS!J"!+!9C!%)J8#J9@3"0+"JS!S!5S%FK$LV3+&!!!!rb" Yrr`U-&`!fS8L"(3Bj+N#J3!!!2mJEIrmLV!F!#)%i)N#J3!!!2mJEIrm)M!F!1@ *JS8U"!+&!!!!rb"Yrr`U-&`!jif+J5J$FK$LV!+%!!!!rb"Yrr`S-%`!f)3L!h3 Bj+N#J3!!!2mJEIrmL,!F!#)$i)N#J3!!!2mJEIrm)M!F!1@*JS3S!`+%!!!!rb" Yrr`S-%`!jib)J8AU!)"m!'!!!FJQ"()*ikXL"(3Aj+Q#JbBLXi0`2b)$i)R#J1@ *)'hrq0("F$r!Jq@))Qhrq02!)#N(!)#S"J"b2b3$,8$ri(!3i+V%JH@+)'hrq0( #)#J&!)#Zrq"b2b3$,8(rj()BiUV%V[rNjBSJEIridF+!U!3!XB8Q"()9ikXL"(3 ,j+Q#JbBLXi0`2b)$G"MNUF+!)'hrq(!r*!2JLX5!jBSLEIridm*`2m#$jBJL-"` !)'hrq0(!)#J$!)#T!J"d2be!rq3J!be"rq"b%1+S`),PL#"YrrM4`#!S!3#!V[r NJ+lri,'&*J9b#H1V)J9d&q5TJS-Q)V1$F$mL!q#*`S$PL5"YrrM4`A!r`)2PL#* YrrM6`#!T"`#!U!B!FMmN!be!rq4`%1#Ua)(PLL"YrrM4`L!S"3#!V[rNFMmN!be "rq"b'1+Ua+lri1@+)'hrq0(#J+J%!,'%*J9b&H1V)J9d#q5TJS-Q)V1$F$mL!h3 Bj+R#J#"YrrK`2b3$i)V%J1@+)Qhrq02#F$r!Jq@))M!F!#"YrrM4`#!S!`#!U3) !G$mY32rN)!-Y3IrJFK$LU-##jBJJEIridF!J+!%!J+lrj)#Zrq#aK&+'F!LmJ'd !rM3J"3+!m*!%k)JQ"!+$m*!%KS!J"3+!$j!%)J3#J3q3"1Q*JS!S!5S%FK$LV3+ &!!!!rb"Yrr3U-&`!kBdL"(3Bj+N#J3!!!2mJEIrd)M!F!1f*JS8U"1#0!S8!!!$ r)'hrp#S`A!$PMBU")J3#J3!!!2mJEIrdLV!F!#J$FK$LV!+%!!!!rb"Yrr3S-%` !kB`L!h3Bj+N#J3!!!2mJEIrd)M!F!1f*JS3S!q#-!S3!!!$r)'hrp#J`6!$PM)L ")J-#J3!!!2mJEIrdL,!F!,q&)#lrm,'%F!L`VJ!3E(a4VJ!3)!9b'1+S!S!!!!$ r'-!J"A)3iUJ#J!!!!2mB`#!&i)J#J!!!!2mB`#!&!S!!!!$r'-!J"()BiUJ#J!! !!2mB`#!%FK$LU!+!!!!!raM!)!6JL!+!!!!!raM!)!3#J!!!!2mB`#iZrqblKb! ZrqLjJ#e!rr"J!2ZbfHi!%#!Z!"!-J!!!!!KL!!#!-$X#"Nll!!)!GJ"S!&S!6J" %!$B!+!!F!")J"!+!!!!!raN!)!6JL!+!!!!!raN!)!4b%1+S!S!!!!$r'3!J"() BiUJ#J!!!!2mC!#!&!S!!!!$r'3!J"H#)!S!!!!$r'3!J"A)3iUJ#J!!!!2mC!#! &FKMLU!+!!!!!raN!F!"-haci6Pj1G!!BN!"NCA0IF'0LBepPEQ0bHA"d!!!!+P& 19[rS51FI%#*Z!!Kk!"SCFKMMVA!!%"Pb%11SLS"`!"!CiBL+J(!!%"Q+J(!(*J9 d&H5VaS!JEIrN*M!m!0D$F!FN"5e!rqK`(H#Ua+lrk#"Yrq5'X#`!F!FN"5e$rqa f$HDUa)!JEIrN*$!X!1@+K+lrl(!(*JAULmD!)'hrj#B`2!$RLiD#F!mS"A34j+c )J#"Yrq!S-%`!f)4`$b3&,8$rl(!Ci+V%V[rX)'hri)L`,!"`$b3&,86rk(J*k+V %J#"Yrq!N-#`!jBU%V[rSF!mS"H+-b)!JEIrJ+$"-!1H-L)*k!"SCFKMMVA!!%"P b%11SLS"`!"!CiBL+J(!!%"Q+J(!2)J9d&15T`S!JEIrF)M!F!0+"F!mN"5e!rqa `(1#Ua+lrl#"Yrpb#X#`!F!mN"5e"rqKb$1+Ua)!JEIrF*$!X!1@+K+lrk(!2)JA SLF+!)'hrh#)`(!$RLB+#KS&`"b)&G"(NUF+!)'hrf#)`(!$5JA!(*!8Y32rXF"R JUX5Zrq`JEIrBJV!X!(!(*!8Y3IrSFJRLUX5!)'hrf#3`,!$PLS5ZrqK`"b)&iSR #J#"YrpJL-"`!jiQ#JSL")Qi!$#im!!"qr(!3*N"J!!'#F!(!KfFU)!0b'Z+S)J2 PL3+"$rrrr)+!*J%J"()DiUJL"1@*!S%2rrrmJS!S!@!S)!0b'q+S)J25J3+"$rr rrS+!*J%J"()EiUJL"0+"!S%2rrrqJS!S!H+(HMmL!h3@j+R#K5"Yrp4k-#3$,8A rl(S3kUV%V[rXHJmYF"`!rqJL!be#rr"d$q5T`S@#V[r`jBNJEIr8dF%U+!%!LUl rk()m*!-Y4IrdHJRUUX5"HJ-L!qL*`S@#JZ@*)'hre0("+LJ#!)UZrr4b1#3$k)V %JA)(`S1#JZ@*)'hre0("LUJ$!(`r)J4d&Z5T`SBJEIr3I$!N"#e'rr4m$qbUa+l rp(`2,A!F!2r`)J3Y3[rXG!lNUF+'JUlrl1@*)'hrd0(",#J"!)bZrr"b2b3%lSV %JH@+)'hrd0(#M+J#!()m*!6LLX5"FJ2#K)+#jBNJEIr3dF'-U!-!)!B#J2m!!2m L"3+"!2rr!)+!)X%J"J+!!2rr!#)&!S(r!!$rJS!L`91,Y[`!!'i!rRT`!%cI#2K 1ANjd!!L1E@&VC9pVCAPIFf0SC@3!!!!U88j@rrK)j`!N*'i!##mZ!!`[#L*Yrm` J@8k3!#TZrr3[#L*YrqJJ@8k3!#TZrr4+J'B%F2pJ'#m+)QhrJ#"C6T!!+Qlrp%U !C`4`rQ!#F!!NAdjH6R3!#)eNCA0IDf9jAh0MD'9N!!!U88j@rrK)j`!N*'i!##m +)QhrX#"C6T!!+Qlrp#m+)Qhrl#"C6T!!+Qlrp#m+)QhrJ#"C6T!!+Qlrp%U!CY* `!#4I6Pj1G!!%NQ4PFepZCAGIFQ&ZC'pYAfYPH3!!!#T46PEri#m0)Qhr6#"C6T! !+Qlrh#e!rqJLEIp-)&P1N!!UE[rF,8$rl#mZ!!JLEIqi)&P1N!!UE[rF5'lrk#* Yrl3J@8k3!#TZrpa)E[r`)Qhra#"C6T!!+Qlrh%KZrr!LEIqi)&P1N!!UE[rF5'l ri#*YrcJJ@8k3!#TZrpa)E[rN)Qhr1#"C6T!!+Qlrh#mYrcJLEIqd)&P1N!!UE[r F5'lrm#*Yrm3J@8k3!#TZrpa)E[r`)QhrZ#"C6T!!+Qlrh%jH6R3!")!JC'9cAfP ZDA4IFQ&ZC'pYAfjeE@*PFPpRC@jPFQ&dEh)!!#T46PErq%MR%!3[,Ir!,bi!##* YrmJJ@8k3!#TZrr4f!'!+)'hr[%)`1!"5Jh!)YS"Ym#BI6Pj1G!!%R@4PFepcCA4 IFQ&ZC'pYAfGPEQ9bBA4[FPpcC@9N!!!U88j@rrJLEIqm)'i!#(!)FL#`J@8%SLj J$NU!C`SL#4,B8i"QqL*"6Pj1G!!%Pf4PFepcCA4IFf9aG@9ZBf9IER9YBQ9b!!! U88j@rrK)ja!%5(J!!5mYrm![,J!),bhr[#*Yrr!J@8k3!#TZrr4f!'!Q)'hr[(! !%$!i!&+!!S!!!!$r)'hr["'!1!!JEIqm5M!i!'B)8S0`#,D!EG3Q(djH6R3!"*P NCA0ICf9ZCA*KG'9IFQ&ZC'pYAf*XEf0V!!!U88j@rrK)jami+'i!$#4Z!"J[#Q( r!!!!p#`!5'S!"'(r!!!!k#i!)!aQ"R!",8!!&(!"*N"JE#JZ!"!NEJ!)B&4`!EL !EaB[#Q(r!!!!K()!-J$5KLB"9)T9K'!)GJ!@'YD'H!!U"b!&6!8!!#)$6!-3!0+ !6(`3!(rrrrmX!#!&"S!%r(-Y6!-!!%am!!&rrrrr,J&+K'DS)!aR"#M'+-G5Lh! %Ym"Z"VIZ!"4[L#!'60mFq%jH6R3!&)jNCA0IFA9KC&pMDh0eE3!!!#T46PErp#" Z!!JGD!!"rrBJEJ!)(9$rpc!ZrrC1ANjd!!59G(G[Af*jG'9cAhCKH&pdEepZCA4 c!!!U88j@rr3JEJ!)(@J!!rrd(@J!![re(@J!!Irf(9$rpb!Zrr41ANjd!!5@CQp eFPpLHA4PFepfBAKIG'pIEQ9dF`!!!#T46PErm%MR(M`SEJ!)*%`Q6%KZrr!LEIm i)&P1N!!UE[rX)Qhr6#"C6T!!+Qlrl#)Zrr#aJ5"Yrk`J%&+3!,1!,`!LEImS)&P 1N!!UE[rX)Qhr-#"C6T!!+Qlrl#e!rr3L5d(Zrr4`"()JX)&P"+)ZB!j+J'F+)JN 5f&1!C[SL39L,)Qhr-#"C6T!!+Qlrl#e!rr3L5d(Zrr4`"()JX)&P"+)ZB!j+J'F +)JN5f&1!C[SL3A`!B$4i!(B!&K*k!'!+iSY`!F#$XB45KA!'ZS"[m%U%CJS3%J! !!!%8J'!)%")#!!$q&)"5LP+'F!HmJ'r'F!"-haai6Pj1G!!%MQ4PFepbB@jNEfe IDf9j!!!!+P&19Zri51F3"#mZ!"![,J!-5(J3!%KZlrJLEIqF)&P1N!!UEZrd*J" +JfB8,bi!#%KZlrJLEIqB)&P1N!!UEZrd5(J3!%+R5'l[q#*Yrd!J@8k3!#TZlr3 J!bBI6Pj1G!!-N@4PFepbC@&NAh"KFh0hEh*N!!!U88j@lrK)ja`m*Qi!##JZ!!` SEJ!3+Li!&(B!$)3!!"!!E`!"+R$rB!!"I#m-)Qhr'#"C6T!!+Ql[p#"Yra")D!" ')Qhr)#"C6T!!+Ql[p#mYra!["#m,)Qhr&#"C6T!!+Ql[p%U!@%pQ&#mYra!LEIm F)&P1N!!UEZrdB!!!e%Ki!!S[#b*Yrb3J@8k3!#TZlr3N3%U!C`*#%NU&C`!!XLm -,bhrU#*YraJJ@8k3!#TZlr3JEIm35'J!4L*Yrb!J@8k3!#TZlr3[,Im35(J3!%K ZlrJLEIm8)&P1N!!UEZrd5S"36fB5,bhr%#*Yra`J@8k3!#TZlr4JA%Ki!!T)EZr i)Qhr*#"C6T!!+Ql[p#4!5S"R!N)55'l[q#m,)Qhr,#"C6T!!+Ql[p%U!CbJ[,Iq N)Qhr'#"C6T!!+Ql[p#"Yra")D!"')Qhr)#"C6T!!+Ql[p&K2B!*f!8U$C`$qfNU $CK)["%+R,`XLEIp!)&P1N!!UEZrd,bhrS#*YraJJ@8k3!#TZlr4+K9K2CaC)H"! !3UG)EZri)Qhr3#"C6T!!+Ql[p#!%8i"#-`J!)!0A`%3!5F"-ha`i6Pj1G!!3NQ4 PFepbC@&NAh"hAh0dFQPZC`!!!#T46PEr0%MR(c`QEJ!)+'i!$#e,rc4k!8AZrlJ J5h$r8S"+''Ek,J")H!"!3UG)E[qi)Qhr3#"C6T!!+Qlr-(`"B$S@'dR$H!"J'NU &C`SJ!h)"`)'a'Q!))!0b!F#"X5,LLe+%F!DiJ'rJF!I!KQB+)!9A`%3!5F!U!&+ '[)GM`NAZrlJQ6(`!B"jf!(J!B!iJ"&+!%KT*`H'TKS&5K(!'Z)"[l"E$8SC`"lb !Bp`[$#*Yrq`J@8k3!#TZrc")E[mi,``LEIr))&P1N!!UE[m`,`a)E[mi,`F[$#m Zrc4Krrrrh%T)H!#!3UG)E[mi)Qhr3#"C6T!!+Qlr-#m-)Qhrl#"C6T!!+Qlr-(! !60mFq%jH6R3!#*&NCA0IFh4bD@jRAh4[AfYPH3!!+P&19[ri51F30#4Z!!`QEJ! )GJ![,Iq8,`SLEImm)&P1N!!UE[rd8%pJ0R!!%"X[!#mYrj!!,`SLEImm)&P1N!! UE[rdF!LfJ%r[!!aX&#mYri`[#L*Yrc`J@8k3!#TZrr436b!$8S0b#,#"EF![,Iq ),`SLEImm)&P1N!!UE[rd8%p-h``)6Pj1G!!)P@4PFepMBQa[BfYIF(*TER4ICQP XC3!!+P&19[ri51F30#CZ!!JNEIq%GJ"J)NKi!!J[#b"+8)T)8#*Yrc3J@8k3!#T Zrr4+J'B%F!&J#P+$F"#fJ'ABF!"-h``)6Pj1G!!%Mf4PFepTFephC@&VAfYPH3! !+P&19[rF51FI1#`Z!!`Q,J!J*'i!&#CZ!"JSEJ!F5Ui!*'F!$)`Z!b"(8SGk!"S 3FKMMV5"(8SG`!"!3FK$MU)U!)%G5Kh!!%"$KL)U!)%G5Kh!!%"#+J#"(8SGi!"J 3FKMMV#"(8SG`!"!3FK$MU)L!)%G5Kh!!%"$KL)L!)%G5Kh!!%"#)J#iZ!!JY4[r dB!!-%R!)X+i!%'i!!*iJ4e+(F!!3%!+!!!!!rh)BikLaK5"(8SG`!"!3!S!!!!$ rFK$MU,'&)%G5Kh!!%"!#J!!!!2rKL,'&)%G5Kh!!%"!#J!!!!2qaK5"(8SG`!"! 3!S!!!!$rFKMMU,'%)%G5Kh!!%"!#J!!!!2pb%11SXB3J4e+(F!!3%!+!!!!!rq' )XB3J4e+(F!!3%!+!!!!!rl'%8Di!%'!!!,6HVJ!3)#i!%!b!!!!!"f)!!*i`1`) '6[X!!J#8!)!!E!"D!%S!0J!L!""6Kb"(F!!3%!+!!!!!rq')XB46Kb"(F!!3%!+ !!!!!rh)3ikLaK&1()%G`!"!3!S!!!!$rFKMMU,'%8iFJ4h!!%"!#J!!!!2qaK91 ()%G`!"!3!S!!!!$riBLaK91()%G`!"!3!S!!!!$rFK$MU,'&8iFJ4h!!%"!#J!! !!2pb'11SXB9#VJ!3)!3#J+U3"1+)*J8#JkU3")D!)!3#J&@3"#)&!S&9N!65JB+ !+!%U"()3iUd#K3!!!2mJEIrm+M"F!0U&)J4d'15T!S%!!!$r)'hrr)U`(!!L"1# *!S%!!!$r)'hrr#)`(!$PLB+&+J3#K3!!!2mJEIrm+M"F!1H0LS%S!h)3iU`#K!! !!2mJEIrm+$"-!0L%)J0d'15T!S%!!!$r)'hrr)L`(!!L!q#*!S%!!!$r)'hrr#) `(!$PLB+%+!-#K!!!!2mJEIrm+$"-!1H-L)&m!'!!!CJQ"()9ikXL"(3,j+Q#JbB DXi0`2b)$G"MNUF+!)'hrq(!r*!-Y32rFF"$JUX5ZrpcPLL*YrrM6`L!T!3#!X"` !FMmN!q#+a)(PLL"YrrM4`S#S!J"b2m+$jBNJEIridF'!U!-!XB8Q"()*ikXL"(3 Aj+Q#JbBDXi0`2b)$G"$NUF+!jBNJEIridF&`2b)$G"MNUF+!jBNLEIridm%J+33 !J+J&!()r*!2JLX5"jBSJEIridF+!U!B!FMr#Jq@*)'hrq0("J+J(!,'&*J9b&H1 V)J9d#q5TJS-Q'V1$F$mL!h3Bj+R#J#"YrrK`2b3$,8$rh(!3i+V%V[rFjBSLEIr idm)J+3%!J,!F!()r*!2JLX5"jBSJEIridF+!U!)!FMr#Jq@*)'hrq0("J+J$!,' %*J9b#H1V)J9d&q5TJS-Q'V1$F$mL!h33j+R#J1@*)'hrq0("F$mL!h3Bj+R#J1@ *)Qhrq02")#N%!)#S"3"b2b3$i)V%JH@+)'hrq0(#J+J'!()r`S2PL5"YrrM4`B# S"`#aK&+'F!LmJ'd!rQ3J"3+!m*!%k)JQ"!+$m*!%KS!J"3+!$j!%)J3#J3q3"1Q *JS!S!5S%FK$LV3+&!!!!rb"Yrr3U-&`!kBdL"(3Bj+N#J3!!!2mJEIrd)M!F!1f *JS8U"1#0!S8!!!$r)'hrp#S`A!$PMBU")J3#J3!!!2mJEIrdLV!F!#J$FK$LV!+ %!!!!rb"Yrr3S-%`!kB`L!h3Bj+N#J3!!!2mJEIrd)M!F!1f*JS3S!q#-!S3!!!$ r)'hrp#J`6!$PM)L")J-#J3!!!2mJEIrdL,!F!%AUri!J"!+!UT!%iSJQ"3+$UT! %KS!J"!+!9C!%)J8#J9@3"0+"JS!S!5S%FK$LV3+&!!!!rb"Yrr`U-&`!fS8L"(3 Bj+N#J3!!!2mJEIrmLV!F!#)%i)N#J3!!!2mJEIrm)M!F!1@*JS8U"!+&!!!!rb" Yrr`U-&`!jif+J5J$FK$LV!+%!!!!rb"Yrr`S-%`!f)3L!h3Bj+N#J3!!!2mJEIr mL,!F!#)$i)N#J3!!!2mJEIrm)M!F!1@*JS3S!`+%!!!!rb"Yrr`S-%`!jib)J8I V!)"m!'!!!FJQ"()*ikXL"(3Aj+Q#JbBMXi0`2b)$i)R#J1@*)'hrq0("F$r!Jq@ ))Qhrq02!)#N(!)#S"J"b2b3$,8$rh(!3i+V%JH@+)'hrq0(#)#J&!)#Zrpab2b3 $,8(ri()BiUV%V[rJjBSJEIridF+!U!3!XB8Q"()9ikXL"(3,j+Q#JbBMXi0`2b) $G"MNUF+!)'hrq(!r*!2JLX5!jBSLEIridm*`2m#$jBJL-"`!)'hrq0(!)#J$!)# T!J"d2be!rq!J!be"rpab%1+S`),PL#"YrrM4`#!S!3#!V[rJJ+lrh,'&*J9b#H1 V)J9d&q5TJS-Q)l1$F$mL!q#*`S$PL5"YrrM4`A!r`)2PL#*YrrM6`#!T"`#!U!B !FMmN!be!rq"`%1#Ua)(PLL"YrrM4`L!S"3#!V[rJFMmN!be"rpab'1+Ua+lrh1@ +)'hrq0(#J+J%!,'%*J9b&H1V)J9d#q5TJS-Q)l1$F$mL!h3Bj+R#J#"YrrK`2b3 $i)V%J1@+)Qhrq02#F$r!Jq@))M!F!#"YrrM4`#!S!`#!U3)!G$mY32rJ)!-Y3Ir FFK$LU-##jBJJEIridF!J+!%!J+lri)#ZrpbaK&+'F!LmJ'd!rM3J"3+!m*!%k)J Q"!+$m*!%KS!J"3+!$j!%)J3#J3q3"1Q*JS!S!5S%FK$LV3+&!!!!rb"Yrr3U-&` !kBdL"(3Bj+N#J3!!!2mJEIrd)M!F!1f*JS8U"1#0!S8!!!$r)'hrp#S`A!$PMBU ")J3#J3!!!2mJEIrdLV!F!#J$FK$LV!+%!!!!rb"Yrr3S-%`!kB`L!h3Bj+N#J3! !!2mJEIrd)M!F!1f*JS3S!q#-!S3!!!$r)'hrp#J`6!$PM)L")J-#J3!!!2mJEIr dL,!F!#!%!S#UN!6LL#B&!S1UN!5'J#!%!S"9N!3L"3+"9C!%dS'#J#J"+J4b%1+ Y!S8!!!$r)'hrr#S`A!$DK5)%G"MNU3+"!!!!rb"Yrrb+X"`!)J6JL3+"!!!!rb" Yrr`L-"`!jBQ#K5S%!S8!!!$r)'hrr#S`A!$RMBU"+!0b%1+X!S3!!!$r)'hrr#J `6!$BK#)$G"MNU3+"!!!!rb"Yrrb)X"`!)J2JL3+"!!!!rb"Yrr`L-"`!jBQ#K#J $!S3!!!$r)'hrr#J`6!$RM)L"I!"J!!'B*J4b&H1V)J4d#q5TJS-Q(,1$F$mL!h3 Bj+R#J#"YrrK`2b3$,8$ri(!3i+V%V[rJjBSLEIridm)J+3%!J,!F!()r*!2JLX5 "jBSJEIridF+!U!)!FMr#Jq@*)'hrq0("J+J$!,'&*J4b#H1V)J4d&q5TJS-Q(,1 $F$mL!h33j+R#J1@*)'hrq0("F$mL!h3Bj+R#J1@*)Qhrq02")#N%!)#S"3"b2b3 $i)V%JH@+)'hrq0(#J+J'!()r`S2PL5"YrrM4`B#S"`#aK5B&FKAMUb)&G![NUB+ $*KbcJh!r)J0d'15T`S!JEIriF$mN!be!rq"`%1#Ua+lri1@+)Qhrq02#)#N"!)# `(!"b2b3$i)V%JH@+)'hrq0(#J+J#!()r`S2PL5"YrrM4`B#S!`#aK#B&FJRMUb) &G"INUB+$*KbcJh!r)J0d%15T`S$PL5"YrrM4`A!r)J0d'15T`S$PL5*YrrM6`5! T"!#!U!8!FMmN!q#+a)(PLL"YrrM4`S#S"J"b2m+$jBNJEIridF'!U!F!XB45KR! )[)"Y!2jN)!8#J2#3"1L)*J3#Jr#3")D!)!8#J!q3"#)%!S%2N!6TLB+!+!%U"() 3iUd#K3!!!2mJEIrd+M"F!1Q0)J4d'15T!S%!!!$r)'hrp#)`(!$YLB+&+J6JM3+ &!!!!rb"Yrr3U-&`!jBf+J5)%!S%!!!$r)'hrp)U`(!!S!h)3iU`#K!!!!2mJEIr d+$"-!1Q-)J0d'15T!S%!!!$r)'hrp#)`(!$YLB+%+!2JM!+%!!!!rb"Yrr3S-%` !jBb)J5)$!S%!!!$r)'hrp)L`(!"*l2q!)!9b'1+S!S!!!!$r)'lrp&+Zrr33J#! &FK$LU!+!!!!!rb"Zrr45V[rd%)!J"H#)!S!!!!$r)'lrp&+Zrr33J#!&!S!!!!$ r)'lrp&+Zrr33J#!%FKMLU!+!!!!!rb"Zrr45V[rd%)!J"()3iUJ#J!!!!2mJE[r d8Ulrp"#!)!6JL!+!!!!!rb"Zrr45V[rd%)!J"!+!!!!!rb"Zrr45V[rd%)"+VJ! 3EJ$ckQ!!$0C+VJ!3E`!-cLi$)%G5Kh!!%""b'11S,8$rm#"(8SG`!"!3FK$MU)' Zrr!J4e+(F!!3%1')JDlrm#"(8SG`!"!3JDlrm#"(8SG`!"!3FKMMU#e!rq`J4e+ (F!!3%()3ikL"V[rX)%G5Kh!!%"$KL)'Zrq`J4e+(F!!3%)'Zrq`Z,J!),8Erp#" (8SGk!"S3FKMMV5"(8SG`!"!3FK$MU)U!)%G5Kh!!%"$KL)U!)%G5Kh!!%"#+J#" (8SGi!"J3FKMMV#"(8SG`!"!3FK$MU)L!)%G5Kh!!%"$KL)L!)%G5Kh!!%"#)J#e &rqJY42rN)!3#J+U3"1+)*J8#JkU3")D!)!3#J&@3"#)&!S&9N!65JB+!+!%U"() 3iUd#K3!!!2mJEIrm+M"F!0U&)J4d'15T!S%!!!$r)'hrr)U`(!!L"1#*!S%!!!$ r)'hrr#)`(!$PLB+&+J3#K3!!!2mJEIrm+M"F!1H0LS%S!h)3iU`#K!!!!2mJEIr m+$"-!0L%)J0d'15T!S%!!!$r)'hrr)L`(!!L!q#*!S%!!!$r)'hrr#)`(!$PLB+ %+!-#K!!!!2mJEIrm+$"-!1H-L)&*l!#!I!"J!!()*J4b#H1V)J4d&q5TJS-Q*,1 $F$mL!q#*`S$PL5"YrrM4`A!r`)2PL#*YrrM6`#!T"`#!U!B!FMmN!be!rq"`%1# Ua)(PLL"YrrM4`L!S"3#!V[rJFMmN!be"rpab'1+Ua+lrh1@+)'hrq0(#J+J%!,' &*J4b&H1V)J4d#q5TJS-Q*,1$F$mL!h3Bj+R#J#"YrrK`2b3$i)V%J1@+)Qhrq02 #F$r!Jq@))M!F!#"YrrM4`#!S!`#!U3)!G$mY32rJ)!-Y3IrFFK$LU-##jBJJEIr idF!J+!%!J+lri)#ZrpbaK5B&FJRMUb)&G"INUB+$*L5cJh!r)J2JLF+!jBNJEIr idF&`2m#$jBJLEIridm!J+3F!J+J'!()r*!-Y32rJF"$JUX5"jBSJEIridF)J+!8 !J+lri()r*!-Y3IrFFKMLUX5ZrpcPLL"YrrM4`S#S"!#aK#B&FKAMUb)&G![NUB+ $*L5cJh!r)J0d'15T`S!JEIriF$mN!q#+a)$PLL*YrrM6`R!r`)2PL#)`(!!JEIr idF!J+!-!J+N#!(3r,8$ri#!$,8(rh()3iUM!JZ@))'hrq0(!)#J"!)#Zrq#!V[r FXB45KR!)[)"Y!2id)!8#J2#3"1L)*J3#Jr#3")D!)!8#J!q3"#)%!S%2N!6TLB+ !+!%U"()3iUd#K3!!!2mJEIrd+M"F!1Q0)J4d'15T!S%!!!$r)'hrp#)`(!$YLB+ &+J6JM3+&!!!!rb"Yrr3U-&`!jBf+J5)%!S%!!!$r)'hrp)U`(!!S!h)3iU`#K!! !!2mJEIrd+$"-!1Q-)J0d'15T!S%!!!$r)'hrp#)`(!$YLB+%+!2JM!+%!!!!rb" Yrr3S-%`!jBb)J5)$!S%!!!$r)'hrp)L`(!!J"!+!UT!%iSJQ"3+$UT!%KS!J"!+ !9C!%)J8#J9@3"0+"JS!S!5S%FK$LV3+&!!!!rb"Yrr`U-&`!fS8L"(3Bj+N#J3! !!2mJEIrmLV!F!#)%i)N#J3!!!2mJEIrm)M!F!1@*JS8U"!+&!!!!rb"Yrr`U-&` !jif+J5J$FK$LV!+%!!!!rb"Yrr`S-%`!f)3L!h3Bj+N#J3!!!2mJEIrmL,!F!#) $i)N#J3!!!2mJEIrm)M!F!1@*JS3S!`+%!!!!rb"Yrr`S-%`!jib)JA`!B!!"Q#B %FKAMUb)%G![NUB+$*KZcJh!r)J0d'15T`S!JEIriF$mN!be!rq"`%1#Ua+lri1@ +)Qhrq02#)#N"!)#`(!"b2b3$i)V%JH@+)'hrq0(#J+J#!()r`S2PL5"YrrM4`B# S!`#aK5B%FJRMUb)%G"INUB+$*KZcJh!r)J0d%15T`S$PL5"YrrM4`A!r)J0d'15 T`S$PL5*YrrM6`5!T"!#!U!8!FMmN!q#+a)(PLL"YrrM4`S#S"J"b2m+$jBNJEIr idF'!U!F!XB8Q"A)9ikXL"A3,j+Q#JbBEXi0`2b)$G"MNUF+!)'hrq(!r*!-Y32r JF"$JUX5Zrq$PLL*YrrM6`L!T!3#!X"`!FMmN!q#+a)(PLL"YrrM4`S#S!J"b2m+ $jBNJEIridF'!U!-!XB3Q"A)*ikXL"A3Aj+Q#JbBEXi0`2b)$G"$NUF+!jBNJEIr idF&`2b)$G"MNUF+!jBNLEIridm%J+33!J+J&!()r*!2JLX5"jBSJEIridF+!U!B !FMr#Jq@*)'hrq0("J+J(!,'%8SC`#,b!E3$qC#!&!S$`N!6SL#B%!S2`N!5'J#! &!S!2N!3L"!+"$j!%kBQ#J#J"+J4b%1+Y!S8!!!$r)'hrp#S`A!$TM5)%G"MNU3+ "!!!!rb"Yrr3L-"`!lBQ#K5S%i)d#K3!!!2mJEIrd+M"F!1@0LS%L"!+"!!!!rb" Yrr5+X"`!+!0b%1+X!S3!!!$r)'hrp#J`6!$TM#)$G"MNU3+"!!!!rb"Yrr3L-"` !lBQ#K#J$i)`#K!!!!2mJEIrd+$"-!1@-L)%L!`+"!!!!rb"Yrr5)X"`!4q[rJ#! %!S#UN!6LL#B&!S1UN!5'J#!%!S"9N!3L"3+"9C!%dS'#J#J"+J4b%1+Y!S8!!!$ r)'hrr#S`A!$DK5)%G"MNU3+"!!!!rb"Yrrb+X"`!)J6JL3+"!!!!rb"Yrr`L-"` !jBQ#K5S%!S8!!!$r)'hrr#S`A!$RMBU"+!0b%1+X!S3!!!$r)'hrr#J`6!$BK#) $G"MNU3+"!!!!rb"Yrrb)X"`!)J2JL3+"!!!!rb"Yrr`L-"`!jBQ#K#J$!S3!!!$ r)'hrr#J`6!$RM)L"4HS!J(`!B!!"b#B%FJRMUb)%G"INUB+$*L+cJh!r)J2JLF+ !jBNJEIridF&`2m#$jBJLEIridm!J+3F!J+J'!()r*!-Y32rJF"$JUX5"jBSJEIr idF)J+!8!J+lri()r*!-Y3IrFFKMLUX5ZrpcPLL"YrrM4`S#S"!#aK5B%FKAMUb) %G![NUB+$*L+cJh!r)J0d'15T`S!JEIriF$mN!q#+a)$PLL*YrrM6`R!r`)2PL#) `(!!JEIridF!J+!-!J+N#!(3r,8$ri#!$,8(rh()3iUM!JZ@))'hrq0(!)#J"!)# Zrq#!V[rFXB8Q"A)*ikXL"A3Aj+Q#JbBLXi0`2b)$i)R#J1@*)'hrq0("F$r!Jq@ ))Qhrq02!)#N(!)#S"J"b2b3$,8$ri(!3i+V%JH@+)'hrq0(#)#J&!)#Zrq"b2b3 $,8(rh()BiUV%V[rFjBSJEIridF+!U!3!XB3Q"A)9ikXL"A3,j+Q#JbBLXi0`2b) $G"MNUF+!)'hrq(!r*!2JLX5!jBSLEIridm*`2m#$jBJL-"`!)'hrq0(!)#J$!)# T!J"d2be!rq!J!be"rpab%1+S`),PL#"YrrM4`#!S!3#!V[rJJ+lrh,'%8SC`#,b !E3$q0#!&!S$`N!6SL#B%!S2`N!5'J#!&!S!2N!3L"!+"$j!%kBQ#J#J"+J4b%1+ Y!S8!!!$r)'hrp#S`A!$TM5)%G"MNU3+"!!!!rb"Yrr3L-"`!lBQ#K5S%i)d#K3! !!2mJEIrd+M"F!1@0LS%L"!+"!!!!rb"Yrr5+X"`!+!0b%1+X!S3!!!$r)'hrp#J `6!$TM#)$G"MNU3+"!!!!rb"Yrr3L-"`!lBQ#K#J$i)`#K!!!!2mJEIrd+$"-!1@ -L)%L!`+"!!!!rb"Yrr5)X"`!)#lrm,'&)#lrl,'%F!L`VJ!3E!!!ZP'Z!"!J"A) BiUJ#J!!!!2mJE[rd8Ulrp"#!)!9b%1+S!S!!!!$r)'lrp&+Zrr33J#!&i)J#J!! !!2mJE[rd8Ulrp"#!)!8#J!!!!2mJE[rd8Ulrp"#!)!4b'1+S!S!!!!$r)'lrp&+ Zrr33J#!%FK$LU!+!!!!!rb"Zrr45V[rd%)!J"1#)!S!!!!$r)'lrp&+Zrr33J#! %!S!!!!$r)'lrp&+Zrr33J#eZrqMrm#eZrq6rl'!!p)JJ,J!3dDlrp#!Z!"!-J!! !!!KL!!$!-$X#"Nll!!)!YJ#J!)S!GJ"N!%i!1!!N!")J"!+!!!!!re1Zrr3JE[r d%)!J"1#)!S!!!!$r8klrp#"Zrr33J#!%FK$LU!+!!!!!re1Zrr3JE[rd%)!J"() BiUJ#J!!!!2p6V[rd)'lrp"#!)!8#J!!!!2p6V[rd)'lrp"#!)!AJL!+!!!!!re1 Zrr3JE[rd%)!J"A)3iUJ#J!!!!2p6V[rd)'lrp"#!)!9b'1+S!S!!!!$r8klrp#" Zrr33J%cI(2K1ANjd!##3!'4PFemcBf*MAf9ZBh*jF(3!!!!U88j@rpK)jam`*Qi !$#4Z!!Kf!"BDF!!3'Z')KS"`!"!DFK$MU)D!F!!3'R)BikL'J(J!'"T`!"!DiBL )J(!!%"Tb%11SL)"`!"!DFKMMU)L!,!6SMVH'!SB2N!5pJb!'kBLaK#`$FK,MVVH '!SE-c!!!)!1pJ#)'G",NUE'"*J%X"()5ikkjKJ+'c-`!!#!%[B!L"R35j+QaJ5J ",!6LMVH'!SC9N!5pJb!'d)#aK#`$i)kjKJ+'!2m!rlf%)!EKL,'$,!6LMVH'!SC 9N!5pJb!'d)#aK#!%!S!!!2m!)J3#J3!!!2pd%1@TJS!J"!+!!2m!!(33j+L!J5) $!S(`!!!!k)Q#J#J"!S-2rrrrIJ"J!!(#)'hrI%U`I!"R(L!$FKVMU#)$j)Q#J#B ")!4b'Z1S)J6NLB+!+!&J(#!$FK[MU#)$iSQ#J#B")!4b'q1S)J6LLB+!+!%#J`r rrrm#K!rrrrp`2m#$)'hrH()m*!2ZLX5"FJ-YF!`!rpJJ!qb)`)'!JZ@))'hrH0( !)#J"!)#ZrpKb-#3$,8(rh()1iUV%V[rFFJmY3[rJ*!-Y32rNF!hJUX5"K+lri1@ +)'hrH0(#)#J#!)#Zrq4b"L3$,8(rk()9iUV%V[rSFJ%Y3[rX*!-Y32r`F"6JUX5 "K+lrl(!i)J-Y3[rdG"ENUF+!JUlrp1@*)'hrH0(")#J$!)#Zrr!N3(`m)J6JLF+ 'I!-N"1k+a)D%JH@+)'hrH0(#I$r-K1@1)QhrH02',#N%!)bS"3"b2b3%,8Erp(` 2l+V%JH@+)'hrH0(#,#J'!)bZrr4b-#3%,8(rm()@iUV%V[r`FJmY3[rX*!3Y4[r SI"AXUX5"K+lrl1@+)'hrH0(#,#J(!)bZrqJJ#J+!!!$rrbS'G"$PVBU!)!APL#) &G"lNUG+!*X%J"J+!rrm!!#S+G"$NVBU!)!AYL#)&G"VNUG+!*X&5Kh!3[S"Y!2i kF!"-h`ci6Pj1G!!)Lf4PFepcCA4IDf9j!!!U88j@rrJ[$5mYrh![,J!-,bi!##* Yrf3J@8k3!#TZrr3J,Ip`6Pj1G!!)L@4PFepMFRP`G!!!+P&19[pF51FI2#KZ!!J S,J!-*'i!%%IZrqiJ4%S3CJ4`3@!')%33%%R!&)"*`#B!)'hrE(S!'M!i!1@0)%4 ++!!"CJ4`3@!))%33+!!"5F!93!!"5F!Q!#"Yrfam!"``1!$YMRi!B"BB(%S%Cb* `!"!%d)""l[rQ%B"i!&+(F!LqJ'ANB!T"l[rQ3M"i!&+(F!LqJ'A`5'lrANKZrqB LEIpd)&P1N!!UE[pB,`B["8KZrej)E[rHBIm!!!$Q*LlrhL!$!S!!!!$r&X!J!q# )!S!!!!$r&X!J!h)3iUJ#J!!!!2m@`#!$FKMLU!+!!!!!raE!*LlriL!$!S!!!!$ r&X!J!q#)!S!!!!$r&X!J!h)3iUJ#J!!!!2m@`#!$FKMLU!+!!!!!raE!I!!@2!# !3LlrpRi#B%*i!(S!B#EB"(!!%!0"l[rZFJ!5-'J!`S"R"!!%!!(L#dS$CJC5KKB m!)"5KA!'ZS"Pe(!!%!3JEIpS&E!!!(J!8SG`$Ek!CEK#+J!0)!T-haci6Pj1G!! -LQ4PFepQBh*jF(3!!!!U88j@rma)j`mB)QhrB(S!I!!SEJ!-,@i!%2r8,@i!&2r 33Ulrc'!!"%#Abf!!"#JJ"R33j+JN"V'#+!,)V[r8a+lrd#i%FK$MVb!')M5m!,1 !XB5rK#i#FK$MVb!,8S!L"L!d$!#aJE1#[i)J"1#!,8$rp#i%!SF!!!$m!Ui!!!$ mrr3J!R)FikJL!ZL*dS!N!A!3i+`J-AJ!XB8J5G(Zrr3J+!)!XB8J"1#),8$rm#i %!SF!!!$m!Ui!!!$mrr!J5G(()#J%!,'&)%R4l[r`)#J'!,'&)!,JJ#e!rr3Z!J+ (!!!!r!+Z!!!!r2rdF"$JUL"*dFFJ+!%!XB8J5G(Zrr3J+!-!XB8J!Z#!,8$rm#i #!SF!!!$m!Ui!!!$mrr!J5G(()#J&!,'&)%R4l[r`)#J(!,'&)!9d%15S*!@aJLJ #b+lre-5Zrp!Z"()3ikmJ#e5!)J8J0!`!XB'cK,q%,J*b%11[)!Y@J#)&)$3-!,' "Xi+rJL!%i)!Y32rX,J3#K`!!!2`#VJ!!!2crl#!#FKcMU#)#k)R5J#3"F"$JV#! aH!#aKL"*dHlrl#!S!J#aKL!%i)JY32rS,J3#K`!!!2`#VJ!!!2crk#"*dFFJ+!3 !XBBJ5G(ZrqJJ+!B!XBBJ!Z#!,8$rl#i#!SF!!!$m!Ui!!!$mrqa`%1#U)%R4ab! S!3#aKL"*dHlrl#!S!`#aKL!#i)!Y32rS,J)#K`!!!2`#VJ!!!2crk#"*dFFJ+!8 !XBBJ5G(ZrqJJ+!F!XBBJ"R33j+JN"V'#+!,)V[r8a+lrd#i%FK$MVb!,@)!L"L! d$!#aJE1%[i3Z!R)3ikmJ#eU!)JBJ0!`!XB'cJVq#)!6JJ#e!rq3Z"!+(!!!!r!+ Z!!!!r2rN)!*b(11S)J,SLG+!*!&`%1#X)$&i!,'&)%R4l[rN)#J#!,'&)!6JL#e !rq!Z"!+(!!!!r!+Z!!!!r2rJ)%R4ab!S"!#aK5"*dHlri#!S"J#aK5!#i)!Y32r N,J)#K`!!!2`#VJ!!!2crj(!3i+SJ5G(()#J"!,'&)%R4l[rN)#J$!,'&)!,JJ#e !rq!Z!J+(!!!!r!+Z!!!!r2rJ)%R4ab!S"3#aK5"*dHlri#!S"`#aK5!&G"$NU#3 &XB)S!XLZrp6%V[r3,J4b%11[)!YFJ#)&)$3-!,'"Xi5rK#i#FK$MVb!,AS!L"5! d$!#aJE1#[i)J"1#!,8$rh#i%!SF!!!$m!Ui!!!$mrp`J!R)FikJL!ZL*dS!N!A! 3i+`J-AJ!XBBJ5G(Zrp`J+!)!XBBJ"1#),8$rf#i%!SF!!!$m!Ui!!!$mrpJJ5G( ()#J%!,'')%R4l[rB)#J'!,'')!,JJ#e!rp`Z!J+(!!!!r!+Z!!!!r2rFF"$JUL" *dFFJ+!%!XBBJ5G(Zrp`J+!-!XBBJ!Z#!,8$rf#i#!SF!!!$m!Ui!!!$mrpJJ5G( ()#J&!,'')%R4l[rB)#J(!,''8)Y`),I!E3$le#3&+JBX!P+Zrma`'E#ZrmaZ!2Z k)!9b(H1S)JAQLG+!+J%J"R)GikJL"ZD*dS!X!53&iSUpJJ+#9C!%YBBJ!Y#!XB8 N"Z#+Zi)#JJ$r!2qeK5!#iBLaKL3&j)UpJJ+#-j!%YBBJ!Z@)XB8N"R)3iUUlJJ+ #!!$rrl@&)!*b%11SXBBN"HL+[B)#JJq3",@')!,TL,'&)'i!###')'i!##&&!!4 -haM`6Pj1G!!3LfCMFRP`G&pLEf4j!!!U88j@rrK)ja`m+Li!##4Z!!`S,J!3+'i !&#CZ!"JQ,J!F5S0R4Lm$,`3[#Lm&)Qhrm#"C6T!!+Qlrp#!$9m"%!%R!,`![$#m +,`SLEIr`)&P1N!!UE[rd,`-[#bm+,`SLEIr`)&P1N!!UE[rdB%3[!bm,,`S["5* Yrr!J@8k3!#TZrr3J!eI!4!"*`#m!,``[#Lm+)Qhrm#"C6T!!+Qlrp#m$,`3[#Lm +)Qhrm#"C6T!!+Qlrp%cI($K1ANjd!"L3!'4PFemcC@0LAf9ZBh*jF(3!N!80)4# "!`B!%!!!%"!3!!!3!"!3%!!3%"!%)4!%)4!#)K!3"#%3J3-,%!!3!"#3"3!!!4! !!3!3!4!3!3!!%4!!%3!3%4!3%3BK!3)K!3-L!3%")3%$)3%")3%")J%"!L3"N!3 $)3%#)J%"!5%"!5%"!53"N!3#)J%"!53"N!8N!C!%"#%""#%"!L)"!33K!3%K!3% K!3)L!3%")`%"!3JK")%$$3%!!!%!"!!%!!!%"!%%!!%%"!!!)!!!*!%!)!%!*!! %)!!%*!%%)#3""#3"!b%"!L-%!3%#)J%"!5)%!3%K"!%K!3%P"!3"!33"*3%""!3 "!L)J!3)M*!%"!5-J!3%")L3"!5-%)!%"+J3N!3%%)!%""#5"!`m#!!!#!!3$!!! $!!3#"!!#"!3$"!!$"!3#!#!#!#3$!#!$!#3#"#!#"#3$"#!P!`3N!3)#)J%#!5- %!3-#)J%$!53%!3)%!5F"!J3%!3-%!5B"!`3%!3)")b!"!J%M*!%$!5-J!3-"-53 "!J3J!3)%*!%$"#!"!`3N"#%#"5%)!5%#!5%)!L%)!L)##!-L#!J")`))#!3L!3) #)3%#)`J"!J%L#!%")3J")`%##!%K!3%R#!J"!JJ)!3)K!B%$"`)!!3!!#3)!#3! )!3))!3!)#3))#3)M!3%#!5)"!3)M#3%#!5)*!3%R#!%"!JJ"!3%S#!N"!JJ*!4! $)4)$)4!")3J")4)")3J")K!)!L)5#!)M%!J)!5-5#!J")4!#)J%5!L)"%!%M#!% 5!53)!4!)!5-"%JJ"+J%3#!J"%JJ)!4!")3'"!`F5!!%3!!N5!!N3#!%5#!%3#!N 5#!NK%!%M!3%5!5-"!4!")`N"%J%b#3%3#!%"%JJ"!4!)#3%5#!N""5%%"#%JJJ) %"#!3!"3!%#!L&##"!`JJ!!!J"!!J!#!J"#!J%!!J&!!J%#!J&#!$)3L"!`B%!!J !)!J%)!J3!!J8!!J3)!JN&#!))!)M##!%!5)))!%S)!JJ"#!))"!")`JJ&!%T##! 3)!JJ&#!)J3-()!!!*!!!)#!!*#!!-!!!0!!!-#!!)M3JJ3-))#!!)#3!)*!%*#! J-!!J0!!J-#!J0#!")5!")3L"!`BN!!JJ)!JN)!J`!!Jd!!J`)!JP0#!))#!")`J J*!%V##!J)!JJ*#!))$!")`JJ0!%T##!`)!JJ0#!)"b)3#)%$2`!!#!!3!!)!!!) 3#!)!#!)3!!!#!!!5#!!##!!5!!)#!!)5#!)##!)5"!!!"!!3$!!!$!!3"!)!"!) 3$!)!$!)3"!!#"!!5$!!#$!!5"!)#"!)5$!)#$!)5!"!!!"!3#"!!#"!3!")!!") 3#")!#")3!"!#!"!5#"!##"!5!")#!")5#")##")5""!!""!3$"!!$"!3"")!"") 3$")!$")3""!#""!5$"!#$"!5"")#"")5$")#$")5!!!!!J-K!J)L!J)%)3%")3) ")3%#)J)"!5-#!J%%)JJ#!L%)!5%#!5-)!J)")3J#)`%)!J%L!3J"*`)"#!)#!3J ")5!#)J)J!b%L!L)#)J-L)!%")`)J!3)L)J%")`)L!3)K)!%M#!)J!5%)!5%L!5- )!L)")3J"*b!"#!)J!3J"*b)"#!)L!3J#)3+"!`F#!!)!!T!&!!!$!J!$!!)$!J) $!L-##!)")J))!5F#!JJ#!J))!L-$#!)")J-)!5F#!`J#!J-)!5)J!S%$"`)J!J! L!J)L!J!J!`)J!`!L!`)L!`%R)!))!L!##!%R)J))!L)##!%R)!-)!L!$#!%R)J- )!L)$#!BK%!3K)!)L%#!")4!$)K!3!L%3!5%J!533%#!)!b%)!5%3!5%)!L)J#!% N%#!)%!)M#"!3!5))%!%P)!J3%##"!`F!!!3!%!3!!#3!%#33!!33%!33!#3N%"! N#!)L"!J")a!%#!)L*!J"*"!N#"!"*`3)%"!%#"!"*53)%"!NJ3-(!!3!!"3!!!3 J!"3J%!3!%"3!%!3J*"!8)!J")33")3J")43")3J")`3J#!%P&#!)%!3")`J3&!% S#"!%)!J3&##"!`F!"!3!&!3!"#3!&#33"!33&!33"#3N%"3N#!%M"!3)!5-8"!J ")`3N#!%b&#3)%!3%#"!8"!J3"#3)%"3N"#%3"#%"!L)3!38L!K!#)3)")3%")`) 3!3%K!J)K)!%K%!%K)!)L!5!")a!")!-M)!)3!5)J!J%R!5!#%!%J!J%K")%$"`! 3"!!!"3!3"3!!"!)3"!)!"3)3"5%#!5)%)!%M%!3J!L)&)!%M%!8J!LF%)!)3"#! #!5J&)!)3"5!#)!-K-!-L)!%#)M!"!L%J!L)#-!)M!L!"!5-#-!%")J)J!5%J!5% `!5%J!5-J!5!")c!")!%K)!%M)!)`!5`J!L!")!)`!5!#)!5"!`F!-!3!)!8!-!8 !)!3#-!3#)!8#-!8N!L!%)!%M-!3J!5-J"5!")c!&)!%`)!3J!M!%)!)J"5!#-!8 J!J3K"!BL!35#!J`"!3!&!!%""3%!%!33!"%%%3%3"4!"%38K%3%K#)%$$`!%#!! !#!%%#!%"#!!&#!!"#!%&#!%!#"!%#"!!#"%%#"%"#"!&#"!"#"%&##%4!L%)!5% %J3-1#!!!#!%%#!%"#!!&#!!"#!%&#!%!#"!%#"!!#"%%#"%"#"!&#"!"#"%&)JJ 4!5))#!%M"!J)!LS)#!%%#!J"!3J)!5-&#!J"+!%)#!%&#!J"!5F)#"!%#!J3!6F )#"%%#!J4!3J)%!8)#"!"#!J4"3J)%3FK%))#$3!"!"%3!"!3%!%3%3%!!4!"!3% 4%3!4%"%")K%4J3-[%!!!%!!3%!!"%!!4%"!!%*!&!4!3%4!"!"!"%"!"!4!"%4! 4!"!4%"!4!4!4%3%!!!%!%!%!!3%!%3%3!!%3%!%3!3%3%3%"!!%"%!'3"4%"%3! "%4!"%3%"%4%4!!!4!"!4!!%4!"%4%!!4%"!4%!%4%"%4!3!4!4!4!3%4!4%4%3! 4%4!4%3%N%4%4%)%$$`!!%!!3%!!"%!!4%"!!%*!&!4!3%4!"!"!"%"!"!4!"%4! 4!"!4%"!4!4!N%4%3%!)L%"!")a!3%!%M!4!3!534%"!3!5m3N!F"%"!3%4!3!3% [%"!"%"!3!3%3%!%4%"!4!5i3%"%3%"!4!4!3%4%3!3)L%!%")a!3!3%M!4!"!53 4%!%3!5m3!4!3%!%3!4!"%"%3!3%",a!"!4!3!3%"%!%"%4!"%3%Z%!%4%"!"%3% 3!4%4%"%#)K!4!5-3%"%")`%3%3%N%4!4%!%[%"%3%"!4%!%3%4!4%"%"!5m3%3% 3%"%"!4!4!4%3%4%",4!4%4!3%4%"%"%4%3'"!`m!!!%!%!%!!3%!%3%3!!%3%!% 3!3%3%3%"!!%"%!'3"4%"%3!"%4!"%3%"*"%4!4!#)J%3!5-3!4!")`%"%!%N%3% 3%!%[!4!3%!%3%!%"%"!4!4!"!5m"%!%3!4!"!3%3!4%"%"%",J%3%4!"%"%"!4! 4%3%"!L)"!3%M%!%"!5-"N!3N%3%"%!%[!3%3%!%"%!%"!4!4!C!%,`%"!4!"N!F 4!3%4!5i"!4%3!3%4!3%"%4%"%3)L!4%")a!"%3%M!3%4!534!4%3!5m"%4!3!4% 3!3%4%"%"%3%",`%4!4!"%3%"!4%"%3%4%3%Y!4%4%!%4%3%"%C!%J3-2!!!4!"! 4!!%4!"%4%!!4%"!4%!%4%"%4!3!4!4!4!3%4!4%4%3!4%4!4%3%4*"%4%4!#)K% 3!5-3%4!")`%4%!%N%4%3%!%[%4!3%"%3%!%4%"!4%4!"!5m4%!%3%4!"!4%3!4% 4%"%",K%3%4!4%"%"%4!4%4%"!L)4!3%M%"%"!5-"%3%"*"%4!4!",a%"%"!4!4! "%3%3%4%"!3%[%3%"%"%"!3%4!3%4%3%4!5i4!4%3%3%4!4%"%C!%!L)4%3%M%"% 4!5-"%4%"*"%4%4!",a%4%"!4%4!"%4%3%4%4!3%[%4%"%"%4!3%4%3%4N!3","% 4%4!4%4%"%C!%"#%#"#%#!L)#!J3K!J%K!J%K!J)L!J)")`)#!J3L!J)#)3)")3) ")`)#!J%K!J)M!J)#!5)#!J%S!T!(!3-K!`-L!3)#)J-#!L%"!5%#!5%$!5%#!5- "!J)")`-#!J%K!3)L!J-#)`)"!J%M!J-#!5)#!3%M!J)$!5S#!J%#!J)$!J)#!5% "!L)#!3-K!`)L!J-$)J%#!5-#!3)#)J-#!5-#!`)#)3%")`)#!3%K!J%K!`%M!J) $!5%#!5F"!J)#!3)#!5N$!J)#!`)#!3%#)J-"!L)"!`)L!`-#)`%"!J%M!`%#!5- "!`)")`-$!J%L!3%")`)$!3%M!J%$!5-#!`-"-3)"!3)#!`%#!J%$!J)$!`)#!L% "J3-(!J!"!!)"!J)"!!!$!J!$!!)$!J)$!L-"!J)")J%#!5F#!3)#!J%#!L-$!J) ")J-#!5J#!`)#!J-#!3%K!B%$"`-!!3%#!3-#!3%!!`-!!`%#!`-#!b%"!5-"!J- "+`%#!3)"!J-#!3)"!5-$!J-"+J-#!3)$!J-#!`)")J%"J3-(!J%"!!-"!J-"!!% $!J%$!!-$!J-$!5F"!3)#!3%#!5F$!3)#!`%#!5F"!`)#!3-#!5S$!`)#!`-#!3% "J3-(!`%"!3-"!`-"!3%$!`%$!313"5!J!3%"!J-"!3)"!`%#!`-"!J%"!`)$!3- #!3-$!J-$!`)$)J%#!L%"!5%#!5-"!J)")3%#)`)"!J%L!J%"*`)#!3)#!J%$)J- #!L%$!5%#!5-$!J)")3-#)`)$!J%L!J-"+!)#!`)#!J-"!L)"!`)M!3%#!5-"!`) ")J%"!5-#!3-"+`)"!3)#!3-#!J%"!L)$!`)M!`%#!5-$!`)")J-"!5-#!`-"+J) $!3)#!`-#!J-")3%")`%#!3%K!3%K!`%M!3)$!5%"!5F"!J%#!3)"!5F$!J%#!`) "!5%"!5-$!J%")3-")3-")`-#!`%K!`%R!3)$!J%#!`%T!`)$!J-#!`%"!5-"!`% ")`%"!`%M!3-$!6-"!3%#!3-"!J%"!`)"!`-#!C!%)`-$!3%M!`%$!5-$!`-"-3- "!3)$!`%#!`%$!J-$!`)$!L-"!3)")J%"!5F#!3%#!J%"!L-$!3)")J-"!5F#!`% #!J-"!L-"!`)")J%$!5F#!3-#!J%$!L-$!`)")J-$!5J#!`-#!J-$!3%M!3%$!5X "!3%#!3%$!J'3"#-$!3-"+`-"!3)$!3-#!`%"!5-"!`-"+`%$!3)"!`-#!3-"!5- $!`-"+J-$!3)$!`-#!`-"*`%"!3)"N!3R!`%"!J-"!3%R!3-"!J%$!3%R!`-"!J- $!3%R!3%$!J%"!`%R!`%$!J-"!`%R!3-$!J%$!`%J4`-$!`)$!`-"N!3$!C!%!`% "!`-"N!3$!3-"!`%"!`-"!`-$!C!%!`-"!3-"!`%$!`-"!`%"!`-$!3-$!313"`% K%!)L!K!")J%#!5)%!3BK"!%K!J%L"!%"*K!%!3)3"!%N!K!%!3%K%!BK!J)K!3- L!3)$)J)3!5%"!L-%!3)")33#)a!%!3%K%!%L!3)")33")3)#)`%#%!)M!K!%!L% 3!5-"!K!%)33$*J3"!K!%!3%L%!3%)J%#"#)3"!%K!J3L%!3#)4!#)3)")`3"!J% N"!%#%!%M!3)3!5%"!b%"!5%3!5)"!J-K!J%K"!)K%!)M!K!%!b)%!3%Q%!3"!K! %!b-%!3)#*`%#%!3"!K!$)K!%##8"!K!%!38P%!3"!K!%)33")3)#)J%#!5%%!b% %!L%3!5%"!5+!JJFKJ!)MJ))#J3-BJ)!#!))#!!!#!)!!!!)!J))!J))#!!)!J!) #J)!#J!#3"!)!!J+!!J#!!J!!JJ!!JJ#!J!#!J!#!!J)!J!+!!!+!!!)!J!)&)J) #J3-G!))#J!!!!)!!J))#!!!#J)!!J))!J!!!J!!!!!)!J)!#!)!!!))!J!!#!!) !!!!#J!)#!))#J))#!)!#J)!!J!)#J!!#!!)#!))#J))!!!)#J!)!J!)!"5+!!J) KJJBMJ)!#!L8""!3"!38L"!%")J3%!5%""L3"!33%!5%"!L%"!5)%"!)L"!3#)33 ")3%#*!3"!33")3%")`3%!33M!33%"L3%"!%"!b%"!L)"!3%L"!%#)J3"!5%%!53 "!33%!5)""!%L!3%#)3%#)33")J%%!b8%"!%""!)K!3%K"!-M"!%"!5%%"#%"!5% %!L)""!%K!3)M"!%"!5%%!5%""b%"!L%"!5B%"!%""!3")3%")33#)33#)3%&)J3 "!5)%"!%L!33")3%#)33$*!3"!33$)33")`%""!%L!3%")33#)`3%!3)K"!%L!33 #*!%%"!%$)`%""!-M"!3"!5%%!5)"!33MJ!%%!51!!33#)5%#)B!")33&)S!J!b) "")%$#`!J")!!"!!"!)!J")!K!)!K"!!!")!J!!!"!!!J"!!J"!8K)!)MJ#%%J3- IJ#%%J!%!J#%%!#!!J!!!!#%!!!%%J!%!!#%!!!!%J!!%!#%!J!!!J!%!!#!!!!% %!#%!J#!%J!%!J#!!!#%%!!%%J#!%J!!!J!%!!#%%!#%%J!!%J#%!!#%%J!%%"5) J"!)K)33K"!%LJ!%#)S!J!L'!!5%%"L)J"!)L!33")S!J!L5!J%!3!5'!!5-33)! ")K"!!b&!!59!%%#!3!%M3)"!!L'!!5%3"L*!%!)L3"!"*B"!%%#!!L&!"5&!!50 !J%!#)B!&)4!#)8!#)i"!%!3K3!%K3!)KJ!%K%!-N%%#!3!%L3)!&)K"!!5&!!5& !!L%3!LK!%%#!3""!J!)K3!%K3!%M3)"!!b*!%!%PJ%!33)!#)8!*)N!3!b)33!% K3!%M3)"!!5*!J!-MJ%!3!5'!!5-33)!")K"!!bC!J%!33)!#)N#!"5%3!5+!3!) KJ!%K%!)P3""!J%!")N#!!5%3!b)33!%K3!)MJ%!3"#&!!5&!"#%3!L4!%%!3!L- )%#!%)5!"*K!J)!J3)!8P#"!J)!J")5!#)4!")5!#)b!J#!%K)!)K%!)K#!%K)!% L#"!")5!")4!&)L!)"5%J!5))%!%L)!J#)5!#)L!J!5%3!5)J#!-M#"!J!5-)%#! ")3J&*L!J#"!J)!-L)!J")L!J!5-3)#!")4!$)4!")5!%)`J3)!%K#!%L)#!"*"! J)!J")5!%)b!)%!)K#!%K)!)K%!%K)!%K%!8M)!J3!L8)%#!J#!%L)#!")K!J!bB J)!J3)#!&)K!J!5%)!b%)!L%J!5)3)!-M)#!)!L%J!L%J!5))%!%L)!J%)a!J)!% K%!3K)!%L#"!")b!)#!%L##!#)3J#)3)#*3J###!)!b%)!5)))!-L)!J%)3)")b! )!J)N#!)))!%L!JJ")`J##!)M!JJJ!L%)"#-J#!)#)3J#)L!)!5%)!b)))!%L!JJ #)3)")b!)!J%N)!J##!-L##!))JJ#!5)J#!)L)!J")3J#)`)))!%K!J-M!JJJ!5% #!L-)!JJ$)3J%)b!)!J%K)!)K#!)N!JJJ#!%K#!3L)!J#)b!)!J)L#!)")L!)"#% #!L%)!5)))!3N#!)))!%K!J%L)!J#)b!)!J)K#!%K#!%K#!%L##!%*!J###!")J) )!L)##!-L##!#)JJJ!5%#!5)J#!-M#!))!59!#%!33!%K3!-K3!)M#%!3!5%)"5- 33!J")K"!!50!%%!#+""!#%!33!K!!5&!!b&!!5&!!L%)"5-33!J")4!")JK!!L% )!5)33!%L3"!%)8!&)8!#*3K!%%!)!b%)!5)33!)K%!8L#%!$*8!33!K!!5*!#!3 L3"!&*3K!%%!)!5%3!5%)!L&!!54!%%!)!L0!#%!$)8!")N!)!L&!!5&!"#833!K !%!%M#%!3!b%3!L&!!5&!"59!%%!)3!)K#!)K3!)K%!%K#!%L%%!")d!33!)K%!% K#!%K%!%L#%!&)8!")8!$)d!33!-L3!J"*4"!#%!3!5))3!%N!3'3!!J#2JT@CA* TCRPTEQFX)("XC@&cC5"bC5ePER4PFL!PF`)i#JF(6@PcE@&dBfJJ,5"dFRNJB@G KD@i+!L%+!53"jj!!#!)N!Iq!c!)Q)$"i)(XJ!L)PH!)L,#!#)L"p!L#"!!'3#2k 3#"q3"!k3"1#3"2'3"!(q!Ii"rJ(qrJ(q!Ii"rJ%Ii"rJ$[%1mH!Ii"ra$[%1!H! "i!(a!I(J!H!"m3(a!4rq(ri1rJlqrKrq(ri1rJi"(`%I!3i"$Km"(`%1!3i"i2l Jr[(qmIlqi2lJr[(qm3XK!B)#"3!"!!%!!3!"!!%&)3'#!J8!!3!"!!%!!3!"!L! ZdY28eGEAf0RDfpcGhYrJiH,Mj1AQjqMTkZ[XlHl[m2(bmr6ep[IiqIVlr2hqr`% JJ48"!J-%"3B(#!N+#`8'"`J*#JX-$3i2%"%5%a39&KFB'4SE("dH(b!K)L-N*5! K)L-N*5BR+#NU+b`Y,Lm`-6)c0$8f0cJj1MXm26ir3%&#3d3Z,c!a-M-d06Bh1$P "3N0%48C(5%P+5da06Np389*69&9@9eKC@Q&LBf4PCQGSD@TVE'eZEh"aFR0dGAC hH(Pk!Iq!T!NL%#!$)5!#)4!")3%$)3%")a!J!3)L)!%")4!#)3J$)`J3)!%K#!% K)!%L#"!")J%)!LB"#"!J!3J"*#!"#"!$)5!$)M!J!L)J)!)K-!%K!3%K)!%K!3% M-#!"!5-J)!%")6!#)JJJ!L-)-#!")`JJ)!%L#$!")`%))!%V!3J`)!%))#!"#$! ")3L"!`F!!!J3)!J!)!J3!!N!!!N3)!N!)!NK%!%L#!J#*JJ)%#!)#!%N)!J)%!% L#3J#*JN)%#!*#!%N)!N)%!%K#)%$"b!!#$!J##!J#$!!#5!!#6!J#5!J#5%`!5- )##!"+`J)-#!)##!J#!J`!5-*##!"+`N)-#!*##!J#3J`"#%#"5%J!5%#!5%J!L% J!L)#)!-L)#!")`)J)!3L"!)#)33#)b!%!J%L)!3")5!")`3#)!%K"!%R)#!%!L! J"!)K")%$"`)!"!!!*!)!*!!J"!)J"!!J*!)J*!)M"!3#!5)%"!)M*!3#!5)N"!% R)!3%!L!%"!%S)#3%!L!N""!$)4)$)4!")5!")4)")5!")K!J!L)5)!)M%#!J!5- 5)#!")4!#)J35!L)%%!%M)!35!53J""!J!5-%%L!"+J33)#!%%L!J""!")35"!`F 5!!33!#35!#33)!35)!33)#35)#3K%!%M"!35!5-%""!")b3%%J%b*!33)!3%%L! %""!J*!35)#3%"b%"!5%%J3-0!!!%!3%!!!%!!3%%!!%%!3!!!J!!!`!%!J!%!`% !!J%!!`%%!J%%)3-#)3)$)J)"!5)%!J)N"!)"!3%K!J%K!3%P!J%""!)"*!%%!J% #)J)#!L)#!`%M"!)#!53%!J-"!5-#!J%"+`)$!33#!J%%!J-)!b%)!L-"#!5"!`d !#!3"#3!!#3!"#33!#33"#!!##!!$#!3##!3$#3!##3!$#33##33L!`J")3)")3J "*3)"#!3#!58)"!)"#3%K!J%K#3%P!J%*"!)"*3N%!J%)!5-#!JJ"+`)$#!3#!JJ %!J-*!5-#!JN"+J)$#33#!JN%!J-&)4!%)3%#)K!""#%)J3-+%!!)!!%)%!%)!"! !%"!!!"%!%"%!!"!)%"!)!"%)*"!4#!3$)J33!L%%!5%"!5-%%!%")33#)`J%%!% L#!3"*`%)""!"#!3")4!")`33%!%K"!%K%3%M""!4!5%%!5F3#!33%!J%!5B4#!3 3%3L"!`m#!!!5!!!#!3!5!3!#!!J5!!J#!3J5!3J#%!!5%!!#%3!5%3!#%!J5%!J #%3JP%K%)"!)#)J35!L-%!J%")`35!3%L"!)")`J%%J%X#!3#!3J%%J%)"!)3!5- %%K!")`3#%3%M"")4!6!%!K!)"")3#!3#%3J%%K%)"#%3"#%"!L)3!38L""!#)33 ")3'"!aN%%!%%)!!!-!!!)!%!-!%!)!!%-!!%)!%%-!%%!"!!%"!!!"%!%"%!!"! %%"!%!"%%%"%%)"!!-"!!)"%!-"%!)"!%-"!%)"%%-"%K"!)K%!%K%!%K%!)L!4! ")a!"%!-M%!33!5)3"!%S!4!%%!%3"#!")4!")6!")4!")b!"%!%M-!%3!5%J!5- 3"$!"+K!%)!%3"$!"%!3")K!3!5-3%"!#)K%3!5-3%4!#*a!3""!3%!3"+K%3""! 4%!3J%"!")c!3%!%M)"%3!5-`%4!"-#!3%!3`%"!%)"%3"$!4%!3%)3J')JJ)!L% )!L%%!5%)!5%%!b-%#!J")J3)!5%#!L))!J-K!J%M#!J#!5%)!5)#"!%M#!)%!LF #"!J)!J3)!b)"#)%$"J!"!!!*#!!*!!3"#!3"!!3*##)%#3%K!J%M!3J#!5%"!5% #!5-*#!)")3N"*`)%!3J#"!%"+!)%#3J#"!N#J3-(!!!+!!!#!!J+!!J#"!!+"!! #"!J+*!3)!J)#)JS#!L)#!J%M#!S#!53)!J)%!5-+!J3"+3)#"!J+!J3)!S%$"`! "#J!"!J!*#J!*!J3"#J3"!J3*#L3%#3)#!5-"#J)")`%#!J%M#3S#!6%*!J)%!3S #"!%#!J3*#J)%#3BK!B%$"J!)!!!)!3%!!!%!!3%)!!%)!3-K%!)L!4!")3J")4! "*!J"%!%#)K!"!53"%!%)!583!3J"%!%K)!-L)!'"!`B!+!!!+!%")!!")!%"+!! "+!%")5!")4!")b!"%!%K+!%K%!%P+!%3!5!"*a!")!%3!5J"*4!"+!%3!L%#J3- (!!!$!!J#!!J$!3!#!3!$!3J#!3J$!L)#%!)L!a!")`J#%!%N#!-3!3%M!K!"!5S $%!%)!K!"#!-3!5)J!S%$"`!J!`!S!J!S!`%J!J%J!`%S!J%S!`%M)!)3!5-J!a! ")bJ#%!%c+!-3!5!#%!%J!a!"+!)3!5J$%!3K"!3K"!)L"!3&)J)%!L%#!5%%!5- #"!3")3)#)5!")33")5!#)J3J!5-%"#!$)b!#"!%L)!)"*`3J!J3%)!)$)L!%!L% J!5%%!5-J"!3")5!$)L)%!L%L!5%%!5-L"!3")5)#)b!J"!%L)#!"*`3J)!3%)#! #)b!L"!%L)#)"*`3J)J3%)#)#)3J")33")3J#)J3)!5-%"!J$)`J#"!%L#!)"*`3 )!J3%#!)#)5J")33")5J#)J3S!5-%"#J$)bJ#"!%L+!)"*`3S!J3%+!)#)`JJ"!% L##!"*`3))!3%##!#)`JL"!%L##)"*`3))J3%##)#)bJJ"!%L+#!"*`3S)!3%+#! #)bJL"!%L+#)"+J3S)J3%+#)##!J#)3J#)3)#*J)##!J#!J3M#!J#!5%)!5)#!J) K!J%Q#!J#!JJ)!5)##!3M#!)#!5-)!J)))3J")3)")3J&)J)#!5%)!L))#!%Q!JJ )!J))"#-)!J)")3J%)3)#)3J#)JJ)!5)##!%K!J)K#!%K!J%N#!)##!%K!JJP!JJ )!J)")3J#)3J"*!)##!J#)3J%)`J#!J%K#!%L!JJ")3)#)3J#)JJ)!5%#!L%#!5- )#!)$)J)#!L-#!JJ#*!))#!)")JJ)!5)##!)K!J%M#!)#"5))!J%K#!%K!J8K#!) K!J-K!J%P#!)##!J%)`)##!%K!J)K#!)R#!J#3"#!%!8L%)!")N!3!L&!!L%3!L1 !%%!")B!#)K#!!b'!!5*!%!%K%!-L%%!")B!#)4!"*""!%)!")N!3"5%3!5%3!L& !!55!%%!3!5%3!L'!!L33J""!##%3!5)33!%LJ"!"*K#!%%!3J!%K3!)L%%!%)4! %*S!33"#!%!%K%!%N%%!3J!%K3!%KJ!)R%)!33"#!%!%K%!%L%%!#)4!%)8!&)S! 3!5%3!L*!%!%K%!)KJ!%K3!3N%)!33!%PJ""!%)!$)B!&)8!#)4!$*4"!%)!3!5) 3J!%L3"!#)N!3!5%3!5%3"#1!%%!")B!")8!")S!3!b-33"!$)K#!!5%%!L3""!3 "!b%"!5%%!5)"!3%K"!%L!33$)33")J%"!5)%!3%K"!%K!3)K"!)L"!3&*3%%"!% "!L)"!3-M!33%!5%""5%%!53""!3"!b%"!bB"!33%!3%")33#)33#)`%%"!%L!33 ")3%#*33"!33%!b)%!38K"!3Q"!%""!3"!b%""#%"!5%%"#)"!3%K"!%M!33%!L% %!5)"!33M"!3"!L)%!3%L"!3")3%")33")J%%!b3%"!%"!b%"!53%!3%%!L)""!- N"!3"!3%K"!)K"!%K!3%K"!%L!3%")J3"!5%%!5%""5)%"!%K!3)M!3%%!L%"!5- %!3%#)3%")J3%!b4!%!J3!5%3"#8)%%!3#!3L%%!#)4!")K!)!5&!!53)%%!3!5% 3!L))%!8M%!J3!L%)!50!%!J")8!#)4!$)K"!!5%)!5*!%!-K%!3K#!%L3"!")4! "*"!)%%!%)4!$)K!)"5&!!53)%%!3!5%3!5%3!5)33!%P#""!%!J")8!#)K"!!5% )!L)3#!%K3!)K%!)K#!%L3"!")4!")4!%)`J33!)K%!%L%!J')4!#)8!")3J%)K" !!53)%%!3!b%3!5%3!b333"!)!50!%!J")8!#*""!%!J$)JJ3!5%3!L0!%!J")8! ")3J")N!3!5)33!)K%!%L%!J#)a!)%!-K%!)N#""!%!%K#!3K!33K"!%Q#!%%)!J "!5)J#!%K"!)P!33J#!%$)3%&)L!)!L%J!5)""!%K#!%N"#!)!3%N)!J""!BL!33 ")3J%)3%")5!#)`3J#!%K"!)M!33J"#%)!L%J!b)J#!%Q"#!)!33J!5%"!5-J#!% %)33$*33J#!%%!5-)!33")3J")J3J!5%"!5-J#!%$)3%&)L!)!L)J#!%K"!%K#!3 L!33"*!J""#!&*!%%)!J&)33#)3%")L!)!5)%)!)K"!8Q#!%%)!J"!53J#!%%!b) %)!%K!3-L!33")JJ"!5)J#!%K"!-L"#!$)5!"*3%%)!J"!L%)!L)JJ!)K3!%K)!% K3!3MJ#!J!L%J!5&!!L%J!5'!!5)J3!%K)!3Q)%#!)#"!!5)J)!%KJ!-KJ!%K)!% KJ!)M3)!J!b-J)%!")5!#)B!"*#"!J#!")8!')5!%*%#!)#!")S!J!5G!J#!J3)! J!L'!"5)J3!-K3!%L)#!#*#!J3)!")5!$)b"!J!-KJ!%K)!)Q)#"!J#!J!L%J!5& !"#'!!5%J!5'!"5%J!5+!)!%K3!%K)!-K)!%P3)!J)%!")L!J"#9!J#!J3!%L)#! #)5!#)B!")b"!J!)M3)!J!b-J)%!')5!")B!#)N#!!58J3)!J)!%LJ#!%)L"!!b0 !J#!")8!#)8!$)3)")3'"!ad#!!%!"!&#"!"!"!"#!*!%!3!!!3)%!!)%!8!!!!! %!8)!!8!!!!)%!3)%!%!!!%!%!8)%!!!!!3)!!3!%!%)!!8!%!%)%!8)!!!!%!%) %!8!%!!)!!33M3J3"J3-+3!!"3!3!!J3!3!!!!J!"!!!"3!3"!J3!3J3!3J!!"#% #!5%"J3-5!!3!!!3"!J#3"!%#"!%#!!"#!!!#"!"!!!&#"!%!!!&#!!!!"!"!"!& #"!%!"!&#!!&!!!!N3!3JJ)%$(S!JJJ!!!S!!!!!J!J!!J)!JJ!!JJS!!!)!J!!! !JJ!!!S!!JS!J!S!J!)!JJ!!!!J!!JS!!J)!J!J!JJS!J!)!!N!5#!#!!!!#!!#! #J##!J!#!!!!#!###"#'!!5'!!b%#!L%J!L1!)))")B!")3)")S!J##'#!L)JJ!% MJ#!#!51!)!)$)B!")i!JJJ8KJ!%KJ)%$#B!J!J!JJS!!J!!JJ!!J!)!!JJ!!!S! J!S!JJ!3MJ###J3-(!!##J!!!!#!!!##!J!!#!!##J!!!!)&K)LaiJJ)V,)!XL#e S)UiXQ"TS'HJV2LbS'UiCU#bi'5JC*"NJ'4`C&#c),0!C"KMX'-`V1Lc`,2JY!#U b+VSY%#dB,5!%aJ$'!+B!CJ!Q!!BY-#di,8!-aK$'#-B!)#)r2!%M"UR`!L,rr4) L,%##!Mi!-#a!!!)X3&2F,%"0*#a!61iX3%Rd,%!`8La!,rBX3#p@,%!Z-#a!,'S X3#[f,%!Ul#a!+D!X3#NQ,%!ShLa!+)3X3#HL,%!R4La!*Z!X3#0Q,%!Be#a!&kB X3"DN,%!3R#a!#eBX3!$#,%!!P#a!!%`X3#Z3!&5U!8J!d"NL!J%")3J%)M!"!5% )"#4-!3%)"#+8!3%K#!3K`JBP*Z!")!J$*5G'!5!)!b-RSJ%")5!$*5L%!3%)!b) ShJ)K#!-P+5B"!3J$)LQJ!5,r#!-L+Qi'*5VX!Hm3!bBVp[rrl)B#*LaUrrrXb!) Q,M$rrqc1!L8[9J&K#!-P,rB"B3J$)M"5"L0-lJ%")3J$*NdNrrrZD!)L6X!'*92 F!HF)!b*8UJcrN!3!N!F"!!!YB!!!!!%!!#eB!!!!!`!!!"!!!!!"!!!!c!!!!0` !!!0d!!!!"!!!!"S!N!m0!*!,E!#3#`)!!!!0!*!(V`#3#`%!!!!2!*!%!3!!%`) !!"X#!!!K!J!!+!)!!$%#!!!i!J!!2`)!!%8#!!"-!J!!83)!!&J#!!"G!J!!C3) !!)8#!!#E!J!![!!"!*!&"`#3"+!!+e"+$d)VJ$G'(8)!!!"0594IT8e*9%0-D@) ZC'9LG@F!AepQD@aPF`"QCf9dF`"`FQPZG'B!BfaPBA*PFR)!CQCXGA0S!(0dFQ0 SFJ"cFQ&ZC!"cG(*MEA!!FQ&ZC!"YC@eMEA!!G'PYC3"QF(*TER4Q!'ePEA0PG!" 0594IT8e*9&*eER4TE@9-D@)ZC'9LG@F!AepeER*PCfPcG'9bAfCbB@GYC@jd!&p IFQ9RDA0dCA*ICR*KCfePER3!5@jdCA*QB@0P6'PL!&4TBfY$Eh9ZG!"NCA0IC'9 LG@F!C'9cAh*PB@4IF'&cFhG[FQ3!C'9cAh0PG&pcCA&eC@jMC9pZG@eLCA)!C'9 cAh0PG&pVCAN!C'9cAfPcAhGPB@YIDf9j!'4PFepcG(*TEQGIG'pIDf9j!'4PFep ZCAGIFQ&ZC'pYAfYPH3"NCA0IBf*XEf0VAh"bD@jdAfCTE'8!C'9cAfCMFRP`G!" NCA0IBfKPBfYIDf9jAh"KFQPdH3"NCA0ICQPiGA"IDf9jAh"KFQPdH3"NCA0IFQ& ZC'pYAfYPH3"NCA0IBh*jF(3!C'9cAh*PB@4IF(GIFh4bD@jR!'4PFepTEQPdAh* KEQ4[E9pZG@eLCA*ICf9ZCA*KG'pb!'4PFemcC@0LAf9ZBh*jF(3!C'9cAc0MBQ0 IC@jMFRP`G!"NCA0IFf9dAh*KEQ4[E9pRC@jPFQ&dEh*IFf9PC!"NCA0IDf9jAh0 MD'9N!'4PFepaG@&NAf0VFh9Y!'eKDf9IDf9jAh0MD'9N!'4PFepPBf*IC@jMFRP `G!"NCA0IBf*MAf9ZBh*jF(3!C'9cAfGPEQ9bBA4PAh*KEQ4[E9pLE'pMD`"NCA0 IF'0LBepPEQ0bHA"d!'4PFepMBQ0IBfYcG@d!N!B-!!!!$!!$!!3!"J!%!!F!$!! )!!3!#`!%!!`!!!!0!!J!$3!3!!m!#!!6!!!!&3!)!"8!!!!A!!`!&`!*4Fd!%C0 8!"IZC`!,%NB!$ee'!"&VQ`!5Y*S!&6r)!!U,8!!8R43!&(88!!kAf`!*4A!!%L3 k!#$#a3!34D!!%&+J!"edaJ!08`S!$S92!!k,#`!2Cm%!$hc"!"N3i3!31U8!$9m 2!3!!aJ!!+Ui!!3)!!0!!!#cB!!%#!!$L!!!Xq!!"!J!!qJ!!,+J!!3)!!3B!!#b i!!%#!!%@!!!Xb!!"!J!"+!!!,4!!!3)!!6X!!#c!!!%#!!&4!!!XQ!!"!J!"A!! !,6!!!3)!!A%!!#di!!%#!!''!!!Xi!!"!J!"P3!!,+!!!3)!!Cm!!#c3!!%#!!' b!!!Y#!!"!J!"d`!!,*!!!!%#!!(N!!!XX!!"!J!"p3!!,3!!!3)!!K-!!#dB!!% #!!)K!!!Xk!!"!J!#-!!!,5!!!3)!!Mm!!#e!!!%#!!*2!!!Y8!!"!J!#A`!!,2! !!3)!!RN!!#dS!!%#!!++!!!Y5!!"kh3!!!%!!!!"B!!!!'!!!!!bFf0KE#!f1%X !N"G849K8,R"MD!#3(%eA)%-[3bXV)$Bi5`#3&)!!!!"849K8,R"MD#XV!*!D69F J3bp$+bXJ0MK,!*!8J!!!!&4&@&3ZF("e!*!F69FJ8'&cBf&X)$Bi5`#3%e`!N!X "!*!6!@df1'X!N"-"!*!42"&0594IT@4PFfaTBLjNC@*eC`!!!3!!!!&J!!!!B!! !!$)'Ce5-AJ)!!!!F!$)!!'0QFQF!!!!+!!$rr`#3##0I: \ 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
index 96393327c6..0000000000
--- a/src/mac/libraries/DES/bin/deslib.PPC
+++ /dev/null
@@ -1 +0,0 @@
-(This file must be converted with BinHex 4.0) :#Q4PFfaTBLj38%-!FfKXBMq3"!#3")pK!!!"M[Q[5Qpj)A"PCQC`Gh"M!!!!!E* ETlJ!N!d$!!)!N!6rN!3!N!CIH!!!AhJ!!&pi!!!&S!!%"!$rN!3!N!BYdJ!!,63 !!#T"!!"P)!)""!$rN!3!N!i&)!!!!)!%"!3!N!ArN!3!N!F"!!!!p!!!!!%!!!$ X!!!!!`!!!")!!!!"!!!!e!!!!23!!!0d!!!!"!!!!"S!N!m2!*!,$3#3#`)!!!! 2!*!()!#3#`%!!!!4!*!%!J!!,3)!!$3#!!!l!J!!3J)!!%J#!!"2!J!!9!%!!&X #!!"M!J!!DJ)!!'m#!!"f!J!!I!)!!)8#!!#-!J!!P!)!!+S#!!#q!!%!N!83!*! %5JCJ#%S)3J*J"d)"3!&#!8!"3KL!%dBD3#UJ!"[`3""0594IT8e*9%0-D@)!68P 8Ak905945G@jdD@eP6'PL!%PZG'9bCQ&MC8aTBJ"cG(*MEA!!Fh4bBfKb!'CQE(9 cD!"cFQ&ZC!"YC@eMF(N!FQ&ZC!"YC@eMEA!!AepQD@aPF`"cG(*XC@i!G'PYC3" `FQPZG'B!CQGPG(-!BfaPBA*PFR)!E@9YFf9d!'C`FQPZG'B!AepeER*PCfPcG'9 bAfCbB@GYC@jd!&pIFQ9RDA0dCA*ICR*KCfePER3!9'PMDd0[G@jd!'4PFepbC@& NAh"KFh0hEh*NC'9cAh0PG&pcCA&eC@jMC9pZG@eLCA*NCA0IC'9LG@GNCA0IFf9 dAfYPH@4PFepTFephC@&VAfYPH@4PFepcG(*TEQGIG'pIDf9jC'9cAfjPGepbB@j NEfeIDf9jC'9cAf0LE'pMDep`FQPZG&pQD@aPC'9cAfCMFRP`G'4PFepQDAKeF&p VCAPIF'&bDA4jC'9cAf0SC@0VAfYPH9p`BA*TG(PNCA0IFQ&ZC'pYAfYPH@4PFep MFRP`G'4PFepbC@&NAh"hAh0dFQPZCf4PFepTEQPdAh*KEQ4[E9pZG@eLCA*ICf9 ZCA*KG'pbC'9cAc0PBf*IC@jMFRP`G'4PFemcBf*MAf9ZBh*jF(4NCA0IFf9dAh* KEQ4[E9pRC@jPFQ&dEh*IFf9PC'4PFepVCAPIFf0SC@4NCA0IFA9KC&pMDh0eE@e KDf9IDf9jAh0MD'9NC'9cAf9MBPpPEQ0bHA"dC'9cAf0LBepPEQ0bHA"dC'9cAfG PEQ9bBA4PAh*KEQ4[E9pLE'pMDf4PFep`Bf*MAf9ZBh*jF(4NCA0IBf*MAf0VFh9 Y!*!&$!!!!!`!!`!%!!B!"!!(!!`!#!!%!!X!"!!-!!!!$3!)!!d!%!!2!!J!%`! !!"8!#!!9!!!!&`!-!"F!%C08!"IZC`!*4Fd!#a*'!!pG4J!4DjX!%V5D!"8rb!! +Le!!&(88!"5G&!!1PpX!#89`!")N1J!J`X8!%%@J!""5S!!GG-B!$9-+!!k&6`! 1L`X!$fI"!!pm`3!C%1%!%$UP!!eI$`)!!-J!!!&m!!%#!!$C!!!"4!!"!3!!m!! !,63!!3)!!2N!!!'N!!%#!!%%!!!"P!!"!J!"%`!!!B3!!3)!!53!!!&F!!%#!!% f!!!"M!!"!J!"5`!!!D`!!3)!!98!!!%F!!%#!!&T!!!"&!!"!J!"I3!!!@`!!3) !!BX!!!'d!!%#!!'8!!!"G!!"!J!"TJ!!!93!!3)!!FB!!!'m!!%#!!(@!!!"R!! "!J!"jJ!!!8`!!3)!!J-!!!%d!!%#!!)3!!!"C!!"!J!#(J!!!5`!!3)!!L`!!!% -!!%#!!)l!!!!r!!"!J!#5J!!!6`!!3)!!Q-!!!%N!!%#!!*c!!!""!!"I!J#TT! !!3!)P#(r`$JK!%#!!3!)I!J$TNk!!#"m#!+QNq(rr*!!!3!)P#(r`*!!B3"B1q! !!)"K!&K)!&`eB!!!!(ar'hKri`Fd,!-!!%'#!!arirYi5!!!#(rMqhL!!3")1#% !3(`)!kD$iIrm6S!!)!#3"L""J!%!N!98!"3ZAepTEQPdD@&XDATPAf4PFfaTBJ! !I!J#TT!!!3!)P#(r`%J!A#&J!!!!J!%!5$JK!%"m#!1Q6S!!)!#3"L""J!#3"L3 !%bjIAh4PFQeTEQ&dC9pNCA0XD@)!!!#q)Ir%1Z)2-$[#%c!l!JX`I0XcH#`)!!" "JJA8I2BlH)Nf!!!keJ!"95N'2P8m`!k*9J!!1YB!!99+"Mj95S!HIja6H)Pf!!! keJ!"9@X'2P9V3#jrR&YiLCB!!$V@!!&9M!BqIjaMH)Nf!!!keJ!"95N'2P8p`!k *9J!!1YB!!99+"Mj95S!HIle6H)Pf!!!keJ!"9@X'2P9V3#jr[9YiLCB!!$V@!!& 9M!BqIleMH(af'hKmP50i5!!&+#`&!!K"J!$%L6B!!$V@!!&9+3Bq95N'2P8T`!j rR%TiL9B!!$V@!!&95JBq98S'2P9+J"jrR&*iLAB!!$V@!!&9D`Bq9@X'2P9V3#j rR&TiLCB!!$V@!!&9M!Bq9B`'2RqFBRL*0J!!1YB!!98T"Mj9+3Bq95R!$Rqp5RL *9J!!1YB!!99+"Mj95JBq98U!(Rqp8RL*GJ!!1YB!!99V"Mj9D`Bq9@Y!,Rqp@RL *PJ!!1YB!!9@-"Mj9M!BqIleLH$LPrrK)!!#`IYBU&#J&!!G"J3#J15)"k&5U%$T p+9!ZI5N$TNk!"#!ke[rrLAB!!&9V"Mj9Dd!ZIleDH$V@rrq*PJ!!9B`'2P@-J"j r[@*i1YErriNf!!"9+3Bq95R!$Rqp5RJke[rrL9B!!&9+"MjrR&*i1YErriPf!!" 9D`Bq9@Y!,RqF@RJke[rrLCB!!&@-"Mj9M)!HIjaLH$V@rrq*0J!!95N'2P8T`!j rR%Ti1+!!!$e!UUXj5UUUIiT31$eJUUXjDkUUIkYB1&9Vq(jpAeYi2B"996Q-999 rM'!i9B`)2$dJ998j+999IkP)1(fG5hKAUJBq98S31ReB8#j95KJi9k['2P9V%$T pH&JZ9@X31PHX4Mj9M"!kICKJ,PHTKMj9+4!kI6K),P8T#$apM%YiI@YMH(eF@hK AkJBq98S31ReB8#j95KJi9q['2P9V%$TpH&JZ9@X31PIX4Mj9M"!kICKJ,PITKMj 9+4!kI6K),P8T#$apM%YiI@YMH(eG@hJl3!!!5!!"S)&E!!!lH`!%9kZUrPHXU"4 pDf0iI9pDH&IT"Vj9+4!k15N$!(dq5#jAkXDq98S31MP+!J"pAP!Z9qZ'[P9V%$S jD`%!IAjB,PIX4Vj9M"!kICjJ,ReVBhKp5PYiI5P6H(qF5RL"1`!!1hX!"&HU6Ij AUdJXI8TEH(dr8RKAl!Dq9B`31MQ-"`"pRQ!Z9qR'[P8T%$Sj+3B!I6j),PIU4Vj 95K!k18S%!(eH8#jAkiDq9@X31MPV"3"pIPJZI8TEH(dT8hKpM%YiIjaLH)'E!!! lH`!%9iQUrPH+U"4p+90iICp+H&IV"Vj9Da!k1@X$!(eq@#jAl-Dq9B`31MQ-!J" pRQ!Z9qQ'[P8T%$Sj+3%!I6j),PIU4Vj95K!kI9j3,RdT8hKpM%YiI@YMH(qp@RL "H`!!1hX!"&H-6IjAL8JXIBa,H(erBRKAkJDq98S31MP+"`"pAP!Z9q['[P9V%$S jD`B!IAjB,PIX4Vj9M"!k1B`%!(fHB#jAkBDq95N31MNT"3"p2NJZIBa,H(eVBhK p5PYiIle5H$YD!!%X'J!)3B$qB$e!m2%j5[$`IkT31$eJm2%jDr$`IiYB1&9Vi6j pAeYi2B!2$cQ-$`prV'!i9B`J0MdJ$`mj+3m2IiP)1(fG5hKAUJBq98S31ReA8#j AUmBq9@X31Reh@#j9Da!k9ka'2P@-%$TpPf!Z9B``-PHTKMj9+4!kI6G),P8T)$C pM%YiI@YMH(eF@hKAkJBq98S31ReA8#jAkmBq9@X31Reh@#j9Da!k9qa'2P@-%$T pPf!Z9B``-PITKMj9+4!kI6G),P8T)$CpM%YiI@YMH(eG@hJlHrq!9iT'2TP9!!! kY3!"9iZ'2TPe!!!kY3!"9ic'2TQ9!!!kY3!"9iN'2TNe!!!kY3!"9kT'2TP9!!! kY3!"9kZ'2TPe!!!kY3!"9kc'2TQ9!!!kY3!"9kN'2TNe!!!kY3!",!8!!%'"qYK )!!@B,!8!!%'"!!`iB!!!5!!&M(cf1hL*9J!!1YB!!99+"Mj99-!1LAB!!$V@!!& 9D`Bq9@Z!(Rk8@hL*PJ!!1YB!!9@-"Mj9M%!ZIT4MH)Nf!!!keJ!"95N'2Rk85hL *9J!!1YB!!99+"Mj98m!1LAB!!$V@!!&9D`Bq9@Z!(Rjc@hL*PJ!!1YB!!9@-"Mj 9M%!ZIR0MH)Nf!!!keJ!"95N'2Rjc5hKmGKYiI*8MH)P@!!!keJ!"98S'2P9F`!k *GJ!!1YB!!99V"Mj9Di!HIjaEH)Q@!!!keJ!"9B`'2P@-3#jrR'0iL6B!!$V@!!& 9+3BqIja,H)P@!!!keJ!"98S'2P9G`!k*GJ!!1YB!!99V"Mj9Di!HIleEH)Q@!!! keJ!"9B`'2P@-3#jr[@0iL6B!!$V@!!&9+3BqIle,H(q5ihKrXHYi28#UUcP+UUT rLP!i2@#UUcPVUUTrUeJi9@[iIReI@hJpJ&991Ba99Aq-B$K9M!Jm25"996NT999 rU8JiICe,H&HU"Mj95K!kI9K3,P9+'$KAUmBq9@X31Rei@#j9Da!k9ka'2P@-%$T pQ'!Z9kQ'2P8T%$Tp1%JZ95N)2(f-5hKpDf0iI9aEH&IU"Mj95K!kI9K3,P9+'$K AkmBq9@X31Rei@#j9Da!k9qa'2P@-%$TpQ'!Z9qQ'2P8T%$Tp1%JZ95N)2(f-5hK pDf0iI9eEH$Yl!)!l)!!!5!!"S$Ylrrb"@`!!9kY0rPHX5#apDf0iI9pDH&IT4Vj 9+4!k15N%!(dq5#jAkSDq98S31MP+"3"pAP!Z9qX'[P9V%$SjD`F!IAjB,PIXaVj 9M"!k1B`'!(fHB#jpDf0iI8TEH(dT8hKrR%Ti1h[rr)%l!!"AUUVq9kZS&(e+@hK p2e*i9qb'[P@-%$SjM!%!ICjJ,PIT"Vj9+4!k15N$!(dq5#jAkXDq98S31MP+!J" pAP!ZI5P6H(f-5hKAkdDq9@X31Req@#jpM&YiIjaLH$Ylrrb"Q`!!9iP0rPH+5#a p+90iICp+H&IV4Vj9Da!k1@X%!(eq@#jAl)Dq9B`31MQ-"3"pRQ!Z9qN'[P8T%$S j+3F!I6j),PIUaVj95K!k18S'!(eH8#jp+90iIBa,H(eVBhKr[9Ti1h[rr)&l!!" AM+Vq9iQS&(f-5hKpIf*i9qU'[P9+%$Sj5J%!I9j3,PIV"Vj9Da!k1@X$!(eq@#j Al-Dq9B`31MQ-!J"pRQ!ZI@YMH(e+@hKAk8Dq95N31Rdq5#jp5NYiIle5H$Xj!!% X'3!)3B$qB$e!m2%j5[$`IkT31$eJm2%jDr$`IiYB1&9Vi6jpAeYi2B!2$cQ-$`p rV'!i9B`J0MdJ$`mj+3m2IiP)1(fG5hKAUJBq98S31ReA8#jAUmBq9@X31Reh@#j 9Da!k9ka'2P@-%$TpPf!Z9B``-PHTKMj9+4!kI6G),P8T)$CpM%YiI@YMH(eF@hK AkJBq98S31ReA8#jAkmBq9@X31Reh@#j9Da!k9qa'2P@-%$TpPf!Z9B``-PITKMj 9+4!kI6G),P8T)$CpM%YiI@YMH(eG@hKrR+*iIlfDH#`&!!K!J3"d1+Arq&H+4Mk C93!!1V8!!9H,KMkCG3!!1V8!!9H-aMkCP3!!1V8!!9H*"MkC03!!1V8!!9HU4Mk C93!!1V8!!9HVKMkCG3!!1V8!!9HXaMkCP3!!1V8!!9HT"MkC03!!1V8!!Aj8NhK q-iYi5rrlR(ke+K3S"3!)3B%!H$P#!F48Ua!kI8TB,Re*!kC1J!3J9k`'2MUerrq CP3!!9kR'2MUerrqC03!!9kU'2MUerrqC93!!9kY'2MUerrqCG3!!9i`'2MUerrq CP3!!9iR'2MUerrqC03!!9iU'2MUerrqC93!!9iY'2MUerrqCG3!!1'!!!,SKrm4 1J!!J!*!')%!!$`#3"!Z-!"!ZC'9cAf0LBepPEQ0bHA"d!!#q`IrB1`)2-$[#%c! l)JX`I2FlH)NA!!!kp`!"93J'2P8F`!k*0`!!1[F!!98T"Mj9+B!HIja,H)PA!!! kp`!"98S'2P9+3#jrR&0iLAF!!$Vh!!&9D`BqIjaEH)QA!!!kp`!"9B`'2P@G`!k *&`!!1[F!!98)"Mj9#)!HIle$H)Nh!!!kp`!"95N'2P8T3#jr[8YiL9F!!$Vh!!& 95JBqIle6H(ah'hKmYLYi5!!%c#`@!!K"J!$%LAF!!$Vh!!&9D`Bq9@X'2P9V`!j rR&TiLCF!!$Vh!!&9M!Bq9B`'2P@-J"jrR'*iL4F!!$Vh!!&9#!Bq93J'2P8)3#j rR%*iL6F!!$Vh!!&9+3Bq95N'2RqF5RL*9`!!1[F!!99+"Mj95JBq98V!$Rqp8RL *G`!!1[F!!99V"Mj9D`Bq9@Z!(Rqp@RL*P`!!1[F!!9@-"Mj9M!Bq9Ba!,RqpBRL *&`!!1[F!!98)"Mj9#!BqIle#H$V@rrK)!!#`I[Hb&#J@!!G"J3#J15)##&E+%$T p+9!ZI5N$TNk!"#!kprrrLAF!!&9V"Mj9Dd!ZIleDH$Vhrrq*P`!!9B`'2P@-J"j r[@*i1[IrriNA!!"9#!Bq93M!$Rqp3RJkprrrL6F!!&8T"MjrR%Ti1[IrriPA!!" 95JBq98T!,RqF8RJkprrrLAF!!&9V"Mj9Di!HIjaDH$Vhrrq*P`!!9B`'2P@-`!j rR'*i1X!!!(cE-hJp!+UV13LUURq)3$Jp)+UV15QUURqT5$K9+IKqI4p,H$e!998 j5P99IiT31&9+#$`pB&991@Y99AqV@$KpA9Yi9k`'2P@-%$TpQ@!Z9B`B1&HSaMj 9#"!kI4P!,P8)%$TAU8Bq95N31Rdj5#jAUSBq98S31ReC8#j95JJmI5P6H(d)5hK pR%0i9qX'2P9V%$TpH9JZ9@XB1&IXaMj9M"!kICPJ,P@-%$TAk%Bq93J31RdC3#j AkBBq95N31Rdj5#j9+3JmI3K,H(f-3hKpI@0i1d!!!%J!!D#"@`!!1hX!"&HVU[j AV+J8I@YMH(eI@RKAk!Dq93J31MN)!`"p(N!Z9qR'[P8T%$Sj+3)!I6j),PIUKVj 95K!k18S"!(eH8#jAkdDq9@X31Req@#jp5PYiI5P6H(d)5hKrR%*iJCX!!$Yl!!4 AU%hq9kP),(d)5hKpRd*i9qS'[P9+%$Sj5JF!I9j3,PIVaVj9Da!k1@X'!(eq@#j Al%Dq9B`31MQ-"!"pRQ!Z9qL'[P8)%$Sj#!8!I4j!,Rf-3hKpDf0iI8TEH(qF8RL "1`!!1hX!"&H+U[jALkJ8I8TEH(dr8RKAl!Dq9B`31MQ-!`"pRQ!Z9qM'[P8)%$S j#!)!I4j!,PITKVj9+4!k15N"!(dq5#jAkNDq98S31ReH8#jp+90iI3K,H(f-3hK r[@*iJAX!!$Yl!!4AM%hq9iK),(f-3hKpIf*i9qN'[P8T%$Sj+3F!I6j),PIUaVj 95K!k18S'!(eH8#jAkdDq9@X31MPV"!"pIPJZ9qb'[P@-%$SjM!8!ICjJ,ReVBhK p5PYiI5P6H(qp5RJl@J!","S!#%'!rQ!p!2$a13M`m(qS3$Jp)2$a15R`m(q*5$K 9+H%qI4p,H$e!$`mj5Jm2IkT31&9+)$BpB!m21@X2$hq,@$KpA9Yi9k`'2P@-%$T pQ'!Z9kM'2P8)%$Tp'%!Z93J31PHT4Mj9+4!kI6K),P8T-$*AUSBq98S31ReB8#j 95L!fI5P6H(d)5hKpR%0i9qX'2P9V%$TpH&JZ9qc'2P@-%$TpQ'!Z9B`31PIS4Mj 9#"!kI4K!,P8)-$*AkBBq95N31Rdi5#j9+5!fI3K,H(f-3hKpI@0i1h[rJ#`@!!" "JIXdI*FMH&H+4MkC9`!!1[F!!9H,KMkCG`!!1[F!!9H-aMkCP`!!1[F!!9H)"Mk C&`!!1[F!!9HT4MkC0`!!1[F!!9HUKMkC9`!!1[F!!9HVaMkCG`!!1[F!!9HX"Mk CP`!!1[F!!AqMkhLk`IrB6S!!)!#3"L"!!!S!N!3&m!!1,Q4PFepMBQ0IBfYcG@f qSIr81U)2-$[#%c!k`JX`I(JEH)Mi!!!l'!!"91F'2P6m`!k*'!!!1aJ!!98)"Mj 9#)!HIja$H)Ni!!!l'!!"95N'2P8T3#jrR%YiL9J!!$XB!!&95JBqIja6H)Pi!!! l'!!"9@X'2P9p`!k*Q!!!1aJ!!9@-"Mj9M)!HIleMH)Mi!!!l'!!"91F'2P6R3#j r[6YiL4J!!$XB!!&9#!BqIle$H$dJUUXj+DUUIiP)1$e!UUXj5UUUIkT31&9+q(j p2e0i2@"996PV999rLeJi9@X)2$f!998jM&99IkaJ1(epBhKAT`Bq91F31Rcf1#j 8jaJi9kM'2P8)%$Tp&N!Z93J31PHT4Mj9+4!kI6C),PHUKMj95K!kI9C3,P9+#$a p+90iI3K,H(cm3hKAk`Bq9@X31Ref@#j9DaJi9qc'2P@-%$TpPQ!Z9B`31PIR4Mj 8ja!kI2Bi,PISKMj9#"!kI4C!,P8)#$amjd0iIB`lH(epBhJX"J!!3B)"Z(bk+hJ lB!!!5!!"S)%k!!!l@J!%9kUUrPHVU"4p5PYiI6p5H&IX"Vj9M"!k1B`$!(fHB#j AjmDq91F31MMR!J"mrMJZ9qL'[P8)%$Sj#!%!I4j!,PIT4Vj9+4!kI6j),Rd)5hK mjd0iIB`lH(qFBRL"@J!!1eS!"&HV6IjAV%JXI@YMH(eI@RKAj`Dq91F31MMR"`" mrMJZ9qM'[P8)%$Sj#!B!I4j!,PIT4Vj9+4!k15N%!(dq5#jAkSDq98S31MP+"3" pAP!ZI5P6H(d)5hKmjd0iIj`kH)&k!!!l@J!%9ibUrPH(U"4pM$YiIApLH&IS"Vj 9#"!k13J$!(dH3#jAkFDq95N31MNT!J"p2NJZ9qU'[P9+%$Sj5J%!I9j3,PIV4Vj 9Da!kIAjB,Re+@hKp+90iI3K,H(qp3RL"QJ!!1eS!"&H(6IjAL%JXI1G$H(fI1RK Ak3Dq95N31MNT"`"p2NJZ9qV'[P9+%$Sj5JB!I9j3,PIV4Vj9Da!k1@X%!(eq@#j Al)Dq9B`31MQ-"3"pRQ!ZI@YMH(e+@hKp+90iIle+H$Yl!!%X'`!)3B$qB%J!!E3 l*3#!1f!!!%J!!D!l1IrmJ2N!!&HS6IjAU8JXI3K,H(cr3RKAkNDq98S31MP+"!" pAP!Z9qZ'[P9V%$SjD`8!IAjB,PIX"Vj9M"!k1B`(!(fHB#jAjmDq91F31MMR"J" mrMJZIB`lH(eVBhKp5PYiIja5H$Xjrrb"'3!!9kQUrPHUU"4p+90iI4p+H&IVKVj 9Da!k1@X"!(eq@#jAl!Dq9B`31MQ-!`"pRQ!Z9qI'[P6R%$Sij`)!I2ii,Rf-1hK pDf0i9qK'[P8)%$Tp(N!ZI@Y$H(qF@RJl1IrmJ6N!!&H+6IjALdJXI8TEH(dr8RK Al%Dq9B`31MQ-"!"pRQ!Z9qH'[P6R%$Sij`8!I2ii,PIS"Vj9#"!k13J(!(dH3#j AkFDq95N31MNT"J"p2NJZI3K,H(cR3hKpM$YiIleLH$Xjrrb"@3!!9iZUrPH-U"4 pDf0iI9pDH&IRKVj8ja!k11F"!(cq1#jAk!Dq93J31MN)!`"p(N!Z9qR'[P8T%$S j+3)!I6j),Rd)5hKmjd0i9qT'[P9+%$TpAP!ZI1G6H(qp1RJlH`!","X!#%'!rQ! pB2$a1@[`m(qV@$JpJ2$a1Bc`m(q-B$K9M1%qIApMH$cJ$`mij`m2IkFi1&6R)$B p!!m213J2$hq)3$Kmr80i9kN'2P8T%$Tp08JZ9kV'2P9+%$Tp99!Z98S31PHV4Mj 9Da!kIA9B,P9V-$*AV)Bq9B`31Rf9B#j9M#!fI@YMH(e+@hKp2&0i9qF'2P6R%$T mp6JZ9qM'2P8)%$Tp&8!Z93J31PIT4Mj9+4!kI69),P8T-$*AkSBq98S31Re98#j 95L!fI5P6H(d)5hKmr80iI*FMH&H,4MkCG`!!1[F!!9H-KMkCP`!!1[F!!9H(aMk Bp`!!1[F!!9H)"MkC&`!!1[F!!9HT4MkC0`!!1[F!!9HUKMkC9`!!1[F!!9HVaMk CG`!!1[F!!9HX"MkCP`!!1[F!!6KJ!!#kSIr86S!!)!#3"L"!!!X!N!3')!!3,Q4 PFepPBf*IC@jMFRP`G!!!Nq(rr$[J!!")!!#BI)2iVP5%"MamJrQZI+2iVP5P"cj m`rLZ9-ER2RbP-RK8T3HqI12iVP6R"cjp!rLZ93MR2RcR3RK8jrHqI+8kH&5P"rj p)rLZ95N(2Re$q+j95ZFqI5P5H&8T"ljpBrLZ9@X(2Rf$q+j9M1FqI@YLH&9Vplj p+9Ti95RrrRbP5RKST3!"I)2iVRb%+hKmJrQZ1rm!!5JI!!K"J2pSJq(rr%k!!#! !N!BJ3!!"!*!&X!!9,Q4PFepQDAKeF&pVCAPIF'&bDA4j!*2Krr`li!!!5!!!Y(b $q+j8K!IqI+2iVP5P"Ma8T3FqI-2iVP6'"Ma8aZFqI+8bH&5P"ljmirLZ91F'2&6 R"cjp!rLZ93J'2&8)jcjmjd*i91Ih[RbP1RK8T3IqI52iVP8T"Ma9+3FqI82iVP9 +"Ma95ZFqI5P5H&8T"ljpBrLZ9@X'2&9V"cjpJrLZ9B`'2&@-jcjpDf*i9@[h[Rd T@RK9+IrqI+9+H(`%+!"!JJ!-1'!!!%J!!"3lr`!"+"m!#%'!rd`iB!!"Jq(rr%k !!#!!N!BJ3!!"!*!&d!!9,Q4PFepMD'9MDepVCAPIF'&bDA4j!,i"rm!kiJm`1m) 6-$X##c"mfc0i,!J!!%'#"FampMYiL6B!!$V@!!&9+3Bq96c!$SP@!!!keJ!"98S '2P9+J"jrR&0iLAB!!$V@!!&9D`Bq9@Y!,RqF@hL*PJ!!1YB!!9@-"MjrR'0iL6B !!$V@!!&9+3Bq96h!$SP@!!!keJ!"98S'2P9+J"jr[90iLAB!!$V@!!&9D`Bq9@Y !,Rqp@hL*PJ!!1YB!!9@-"Mjr[@0iI(BEH(b9)hK)!!8J,!8!#%#"!+5*0J!!1YB !!98T"Mj90-!1L9B!!$V@!!&95JBq98U!(Rk88hL*GJ!!1YB!!99V"Mj9Dd!ZIT4 EH)Q@!!!keJ!"9B`'2Rk8BhL*0J!!1YB!!98T"Mj9-m!1L9B!!$V@!!&95JBq98U !(Rjc8hL*GJ!!1YB!!99V"Mj9Dd!ZIR0EH)Q@!!!keJ!"9B`'2RjcBhKrR+*iIlf DH$LPrrK)!!$!IYBU&#J&!!K"J3#`15)#6&5U%$Tp+9!ZI5N$TNk!"#!ke[rrLAB !!&9V"Mjr[9Ti1YErriQ@!!"9M!Bq9Ba!,RqpBRJke[rrL6B!!&8T"Mj9+B!HIle +H$V@rrq*9J!!98S'2P9+`!jr[9*i1YErriPf!!"9D`BqIjaDH$V@rrq*PJ!!9B` '2P@-3#jrR'*i1YErriNf!!"9+3Bq95Q!(RqF5RJke[rrL9B!!&9+"Mj95X!1Ija 5H$LJ!!!pB+UV1@ZUURq,@$JpJ+UV1BbUURqXB$K9M2KqIApMH$dJ998j+999IiP )1&8T#$`p3&9918T99AqU8$Kp290i9kX'2P9V%$TpH&JZ9@XB1&HXaMj9M"!kICK J,P@-%$TAU8Bq95N31Rdi5#jAUSBq98S31ReB8#j95JJmI5P6H(f-5hKpI'0i9qX '2P9V%$TpH&JZ9@XB1&IXaMj9M"!kICKJ,P@-%$TAk8Bq95N31Rdi5#jAkSBq98S 31ReB8#j95JJmI5P6H(f-5hKpI@0i1d!!!%J!!D#"H`!!1hX!"&HXU[jAUDJ8IBa ,H(erBRKAkJDq98S31MP+!`"pAP!Z9q['[P9V%$SjD`)!IAjB,PIXKVj9M"!k1B` "!(fHB#jAk8Dq95N31Rdq5#jpM%YiI@YMH(e+@hKrR&*iJ9X!!$Yl!!4AUdhq9ka ),(eVBhKpAeTi9qN'[P8T%$Sj+3F!I6j),PIUaVj95K!k18S'!(eH8#jAkdDq9@X 31MPV"!"pIPJZ9qb'[P@-%$SjM!8!ICjJ,ReVBhKp5PYiI5P6H(qF5RL"1`!!1hX !"&H+U[jALkJ8I8TEH(dr8RKAl!Dq9B`31MQ-!`"pRQ!Z9qR'[P8T%$Sj+3)!I6j ),PIUKVj95K!k18S"!(eH8#jAkdDq9@X31Req@#jp5PYiI5P6H(f-5hKr[@*iJCX !!$Yl!!4AL8hq9iT),(dT8hKpRdTi9qX'[P9V%$SjD`F!IAjB,PIXaVj9M"!k1B` '!(fHB#jAk8Dq95N31MNT"!"p2NJZ9qU'[P9+%$Sj5J8!I9j3,RdT8hKpM%YiI@Y MH(qp@RJl@J!","S!#%'!rQ!pB2$a1@[`m(qV@$JpJ2$a1Bc`m(q-B$K9M1%qIAp MH$dJ$`mj+3m2IkP)1&8T)$Bp3!m218S2$hq+8$Kp290i9kX'2P9V%$TpGeJZ9kc '2P@-%$TpPf!Z9B`31PHT4Mj9+4!kI6G),P8T-$*AUSBq98S31ReA8#j95L!fI5P 6H(f-5hKpI'0i9qX'2P9V%$TpGeJZ9qc'2P@-%$TpPf!Z9B`31PIT4Mj9+4!kI6G ),P8T-$*AkSBq98S31ReA8#j95L!fI5P6H(f-5hKpI@0i1h[rJ&H,4MkCG3!!1V8 !!9H-KMkCP3!!1V8!!9H*aMkC03!!1V8!!9H+"MkC93!!1V8!!9HV4MkCG3!!1V8 !!9HXKMkCP3!!1V8!!9HTaMkC03!!1V8!!9HU"MkC93!!1V8!!AqFSRKr[CTi,!8 !!%'"qZ")!!@F,!8!!%'"!!`iB!!!5!!&N!"mpMYiLAB!!$V@!!&9D`Bq9A,!$SQ @!!!keJ!"9B`'2P@-J"jq8Q0iL6B!!$V@!!&9+3Bq95P!,Rj55hL*9J!!1YB!!99 +"Mjq8P0iLAB!!$V@!!&9D`Bq9A(!$SQ@!!!keJ!"9B`'2P@-J"jq-@0iL6B!!$V @!!&9+3Bq95P!,Ria5hL*9J!!1YB!!99+"Mjq-90iI(BEH(b9)hL*GJ!!1YB!!99 V"Mj9I-!1LCB!!$V@!!&9M!Bq9Bb!(RqFBhL*0J!!1YB!!98T"Mj9+8!ZIja,H)P @!!!keJ!"98S'2RqF8hL*GJ!!1YB!!99V"Mj9IF!1LCB!!$V@!!&9M!Bq9Bb!(Rq pBhL*0J!!1YB!!98T"Mj9+8!ZIle,H)P@!!!keJ!"98S'2Rqp8hKrN!$MH*1Krl! pB+UV1@ZUURq,@$JpJ+UV1BbUURqXB$K9M2KqIApMH$dJ998j+999IiP)1&8T#$` p3&9918T99AqU8$Kp290i9kX'2P9V%$TpH&JZ9@XB1&HXaMj9M"!kICKJ,P@-%$T AU8Bq95N31Rdi5#jAUSBq98S31ReB8#j95JJmI5P6H(f-5hKpI'0i9qX'2P9V%$T pH&JZ9@XB1&IXaMj9M"!kICKJ,P@-%$TAk8Bq95N31Rdi5#jAkSBq98S31ReB8#j 95JJmI5P6H(f-5hKpI@0i1hX!J$XJ!!")!!'J1h[rr)&l!!"AV%hq9kP),(f-5hK pIf*i9qT'[P9+%$Sj5J3!I9j3,PIVKVj9Da!k1@X&!(eq@#jAl!Dq9B`31MQ-"`" pRQ!Z9qR'[P8T%$Sj+3B!I6j),Rf-5hKpDf0iI8TEH(qF8RJlHrrmJ9X!!&HVU[j AV+J8I@YMH(eI@RKAkBDq95N31MNT!3"p2NJZ9qS'[P9+%$Sj5J-!I9j3,PIVaVj 9Da!k1@X#!(eq@#jp5PYiI5P6H&IX4Vj9M"!kICjJ,RdTBhKrR%Ti1h[rr)%l!!" ALNhq9iY),(e+@hKp2e*i9qa'[P@-%$SjM!3!ICjJ,PITKVj9+4!k15N&!(dq5#j AkJDq98S31MP+"`"pAP!Z9q['[P9V%$SjD`B!IAjB,Re+@hKp+90iIBa,H(qpBRJ lHrrmJCX!!&H*U[jALUJ8I5P6H(fI5RKAkiDq9@X31MPV!3"pIPJZ9q`'[P@-%$S jM!-!ICjJ,PITaVj9+4!k15N#!(dq5#jpM%YiI@YMH&IU4Vj95K!kI9j3,ReV8hK r[9Ti1cN!!5`C!!K"J2jJ2@$`m6PVm2"rUeJi2B$`m6Q-m2"rM'!i9BcK2RerBhJ p)!m215N2$hqT5$K9+5!f28!2$cP+$`prLP!iI6e6H&HV"Mj9Da!kIAGB,PHXaMj 9M"!kICGJ,P@-%$TAU8Bq95N31Rdh5#j9+6!b9kU'2P9+%$Tp9e!Z98SJ0RdT8hK pM%YiIAaMH&IV"Mj9Da!kIAGB,PIXaMj9M"!kICGJ,P@-%$TAk8Bq95N31Rdh5#j 9+6!b9qU'2P9+%$Tp9e!Z98SJ0RdT8hKpM%YiIAeMH(qFNRKr[BTi,!8!#%#"!(J iTIri9iY'2TPe!!!kY3!"9ib'2TQ9!!!kY3!"9iR'2TNe!!!kY3!"9iS'2TP9!!! kY3!"9kY'2TPe!!!kY3!"9kb'2TQ9!!!kY3!"9kR'2TNe!!!kY3!"9kS'2TP9!!! kY3!"IK,LH)&Krl"pFHTi5rrlQ(ke+K3S"3!)3B%!H$Q#!LK8U4!kIBa),Rf*!kC 1J!3J9kS'2MUerrqC93!!9k['2MUerrqCG3!!9kb'2MUerrqCP3!!9kP'2MUerrq C03!!9iS'2MUerrqC93!!9i['2MUerrqCG3!!9ib'2MUerrqCP3!!9iP'2MUerrq C03!!1'!!!,S"rm"1J!!J!*!')%!!%!#3"!Z)!"%ZC'9cAh"MBQ0IC@jMFRP`G!# q)Ir%1U)(-$V#!c!k)J-31N)#d$TL!T!!1S)#F(ah'hL)Y`!!1[F!!95P"Mj8[F! 1L0F!!$Vh!!&8aJBq9-D!(Rqp-hL)p`!!1[F!!96R"Mj8jd!ZIldlH)NA!!!kp`! "93J'2Rqp3hKAUGpq95N31Rdd5#j9+4Ji9kUIIP9+%$Tp9&!Z98S31PHV(hj9Da! kIA4B,PHXAhj9M"!kIC4J,P@-#$apDf0iI8TEH(dr8hKATImq9+831Rbc+#j8T4J i9kDr2P6'%$Tmdc!Z9-B31PHR2cj8ja!kI2-i,PHSIcj9#"!kI40!,P8)#$amjd0 iI-BlH(bq-hL*0`!!1[F!!98T"Mj92F!1L9F!!$Vh!!&95JBq98U!(Rqp8hL*G`! !1[F!!99V"Mj9Dd!ZIleEH)QA!!!kp`!"9B`'2RqpBhKATHFq9+831Rbb+#j8T4J i9kDR2P6'%$TmdM!Z9-B31PHR*cj8ja!kI2)i,PHSCcj9#"!kI4*!,P8)#$amjd0 iI-BlH(bP-hKrrbYi9kRrIP8T%$Tp-8JZ95NB1&HU[hj95K!kI9&3,P9+%$TAUcp q9@X31Rea@#jAV(pq9B`31Rf4B#j9M!JmI@YMH(e+@hKp+90iIpj,H(bD)hJl)(l m1`!!%%J!!5aA*3Iq,!8!!%'#!#"AjK%k9qFf[RcI1hKAb"%k9mNf[RdH5hK)!!! F9qS*2&IV,[jpAeYi9m`*2&I&,[jpRLYiIcN1F&IQ"hjAjqDiI-BlH&6'%$SiaJ- !I0B`,PISjljAkEkkI3K,H&8)%$Sj#!)!I4C!,PIUMcjAkiDfI8TEH&9+%$Sj5J% !I9C3,PIX9Vj9M"!kICCJ,Re+BhKp#&0iI0a$H&I&"ljAa[kkI+8cH&5P%$SiT3- !I,8S,PI(cVj8ja!k11F#!(ce1#jAb*Fq9mQ1YRd)5hK9#"!k13J"!(d93#jAbPD q98S31Re98#jp#&0iI1G$H(bl1hKAL`)Z9f`'$ReVBhL4HJ!!1eS!"&H&"JjACJ) ZI+8cH*!!ZJ!!1eS!"$XBrrmX'!!!3B(qe$KJ!!#k)Ir%6S!!)!#3"L"!!!m!N!3 $*!!2,QeKDf9IDf9jAh0MD'9N!!!!I!J#TT2Krrb3!!%!#*3Krm"mIaYiN!#"!&a rirYiJ)%!A%[rr*PJ!!!!Iq2lH%[rlqPJ!!!!,!-!!%##!!`iB2rr5!!!*(rMqhK )!!Z&B!!!!#`$!!""JJ!-1'$rrNJ!!!JiB!!!J!%!5$JK!%"m#!1QJq(rr%k!!#! !N!BJ3B!"!*!&H!!1,Q4PFepVCAPIFf0SC@4m#!+QNq(rr*!!!3!)P#(r`(ar'hK rirYi5!!#+@!!!!"rirYi5rrZJ@!!!!"rirYi5!!,"@!!!!!X!`!!3),rf$KJ!!# !!3")1#%!3(`)!kD$iIrm6S!!)!#3"L""J!%!N!9B!"-ZC'9cAfjPGepbB@jNEfe IDf9j!!!!I!J#TT!!!3!)P#(rX*!!B3"S5!!bIB""!"53!'%!5%J!-R'!33!8N!" K!%b!B3"S5!!!T@!!!!!iB3")5!!"+@!!!!!iB3!i5rrr26KK!$K)!!#&B!!!!$K K!%")!$*0J%%!&$KK!%4)!$*"J%%!&)"L!#")!!$aB!!!!$KK!$K,rrm&1'%!1%J !!%eJ!!!!J!%!@$JK!&"m#!1Q6S!!)!#3"L""J!#3"T`!)5jNCA0ID@jTG&pbB@j NEfeIER9YBQ9bAfGPEQ9bBA4[FJ"m#!+QNq(rr*2"rrL3!!%!#*3Krm#3!'%!@$[ #,EL!B3"B1))Y1%[rrI9J!!!!1q!!!%J!!"!iB!!!I(ljVM[r!!%X(`!)3B$rm)! "!%Ji)3"!I!J$TS2Krrb$`Iri6S!!)!#3"L""J!)!N!9J!"iZC'9cAh0PG&pbB@j NEfeICf9ZCA*KG'pbAh0PC@4m#!+QN!!"!!L8)Ir!N!"K!&JiBLfiJ)%!@$LJ!!K )!$$jJ%%!&)!"!%Ji)3"!I!J$TNk!!#!!N!BJ3B!!N!Bd!"JZC'9cAh0PG&pcCA& eC@jMC9pZG@eLCA)!!(`)!UD6iIrmNm(rq*!!!3!)P#(r`*!!B3"B1m)YZ(r$mhL !J3"B1+)Y1$M!!!&,rqAeB!!!!$[J!!")!!!NI(liVMKM!!&8B`BqI(ljVRbHq+i S"!!!3))!%$[r!!%X(`!)3B$rh)!"!%Ji)3"!I!J$TS2Krrb$`Iri6S!!)!#3"L" "J!)!N!9m!"SZC'9cAfGPEQ9bBA4PAh*KEQ4[E9pLE'pMDh`)!UDqJIr3N!!"!!L 8)Iq3!(ae'hKmQ#0iI,BVH(cA-hKmp$YiIS1MH%J!!@&mI"Yi1(3!"%J!!99mHKY i+"J!!%##!!Jki!!"1b!!!8J!!,"qhV0iIVZVH%J!!)!X(J!"3)%!)(pMfhK)!!$ K9'-%2Rrm'K3lH`!#1plrrNJ!!"L)H`!!1hX!!94M"Mjrr"S81m!!!(pGdhKmRrR @I,hTeRb%+K3m`)!!1-Errhq%-jCrR$(@Ij`J8$cp"2`ijh-YI2mjeMd!J!!j#2r rIdG$PRpD3GCr@MK3,"i!!%##ri!S'!!!3B)!&*1B!!!l'!!%NeJ!!$XB!!3l13! ","N!"%'"!!am'EJ!3)(r5(q$ihL!!3"i1#%!F(`)!kDkJIr36S!!)!#3"L""J!` !N!3"*!!2,Q4PFepaG@&NAf0VFh9Y!!!!L)-!!CL"rr#)S`!!Q+(rmD"Krr"1J!! J!*!')%!!N!FB!"BZG(G[Af*jG'9cAhCKH&pdEepZCA4cL)-!!jL"rr#)S`!#Q+( rmBM$!!'B`IrbL1-!!*MKrr1!BIr`6S!!)!#3"L"!!*!(+!!A,QC[GA*IBRPdCA0 IGQ&iAh4[AfjPG(-!!!"m#!+Q[`(ri*!!!3!)P#(rS(aj'hKr2-YiIcV,H$KK!$K )!#j"J%%!&%J!,L'!33!8J)%!1(b%'RL!SJ#SJ-8!!(c(-hJiaJ!"N!$&!!"mjb* iI2JlH(m$`hK)!#iKJ%%!&%J!,M'!33!8N!"K!$ar3p0i1)%!2$LJ!!4)!#fjJ%% !&$YD!!4)!#i0J%%!&*!!B3!mId26H$L"!$`iS!!%5!!YPB""!"3lB!!!5!!!@$[ !!!#,r!!!1k!!!%J!!"4ArrKq9qJ(rRrH3RJl[3!","d!"N#"rq`X(J!!3))!&)N m!!"K+3!"Q6`!!%J!!"#*A!!!98S'2*PF!!!lR!!"1hX!!5`E!!G!JIqS1'!!!)! "!'Ji)3"JI!J$TVX"rq"1J!!J!*!')%'!#!#3"!%J!!mZC'9cAh*KEQ4[E9pVCAN !!!"m#!+QNq(rr*!!!3!)P#([`*!!B4"BN!#"%&b3!+%3B$KK!$JiJ"!!J+%3A)$ "%'")!!"eB!!!!(ar'hJX(`!!3))!&$KK!$L!J4"B5!!#9@!!!!!iB3!i1)!!!$L J%!")!#fCJ%%!&(rMqhL!!4")1#%33(`)!kD$iIrm6S!!)!#3"L""J!%!N!9m!") ZC'9cAh*PB@4IF'&cFhG[FQ4m#!+Q[Z(rh*!!!3!)P#([S(ap'hKmQL0iI,XVH(c C-hJkiKY21`)E-)2L!&!lJ!!!,"S3!%#"!5!iB2rr5!!"K(pMfhK)!#b"J%%!&$K r!%K)!#b0J%%!&(qMkhKr400iIqAlH%J!,*'!33!8+!-!!%##!"4rirYi5!!XPB" "!"4)!!$8Ik2VH$L!!!T)!#bCJ%%!&(aq'hJS(J!!3B)!$$KJ!!#BIJ!!,"N!!%' #!+4r!m0iIf6EH%J!,!f!33!81(m!5%J!,"Q!33!81'%!1$L!%!"rjIYi5!!X(B" "!"3S!`!!3))!&(rMqhK)!#`KJ%%!&%J!!'!iB3!i1)!!#NJ!,#@!33!8I(iEH#J H!!""JJ!-1)!!!*LH!!"rSqYi1)%!1%J!,"Q!33!8,!-!!%'#!#"qilYi5!!VMB" "!"3iI`")5!!VQB""!"4)!!!)1i!!!5`F!!""J[lS,"`!!%##!"KrSqYi1)!!!(p &dhK)!#[PJ%%!&$KL!0a)!#Y*J%%!&#`C!!""JJ!B1'%!1$L!!!!iS"!!5!!V[B" "!"3iS!!!I0VU&*LQrrmii!!!,"`!!%##!!Jii!!"I1-lH)!"%'Ji)4"JI!J$TVV Krpa1J!!J!*!')%'!#3#3"!(8!"-ZC'9cAh*PB@4IF(GIFh4bD@jR!!!!I!J#TVl "rpL3!!%!#*3KrZ"mH4YiI*FMH(mfbhJlJ!!"1k%!Z(mMbhK)!#Y*J%%!&(ak'hJ iB3#i1)!!!$LJ!%")!#XCJ%%!&$YJ!!&)!!#%L(N!!$Xj!!&mI`Gd1m!!!%J!!%3 X(!!!3B)!)&IN"rjrTHYi1ld!!BM&!!"maL*iQ-8!!%J!!"KAj`Iq1lhrriNG!!" p#$TiQ4d!!&Irq(ilhJ!","i!"N#"rlaAD3Gq+!N!!%##!"Jj3!!!,"`!!%##!!J j3!!"I9a6H$Yl!!&m'p"!3)(rI$ZK!,Kqq,Yi1f!!!%J!!%!li!!!1m!!!%J!!## *I3!!1ld!!AeV"h3jRJ!"I@YJ-(rr@hJlhJ!","i!"N#"rq#Eq!!!1aJ!!6Yl!!% S'`!(3)(r`(lMZhK,rq64B!!!!(lMZhJiJ3!i5rreK@!!!!"q`l0iIZ5lH(p&dhJ i`3!iIZHlH%[rf&&J!!!!1'%!1$L!!!!iS!#!5!!TkB""!"4qilYi5rrNK@!!!!! iB!!!J!%"+$JK!5"m#!1QZX(rf%k!!#!!N!BJ3B!+!*!%!C`!%LjNCA0IFh4bD@j RAh4[AfYPHA`)!UD6iIrmNm(rq*1Krr53!!%!#*3Krl#3!'%!D(bI)hL$S3"S1m! !!(rMqhJiJKYS5!!TQB""!"4)!!!iIq2lH$L#!0k)h3!!1ld!!96&"Mj)!#PjJ%% !&#`H!!K!J!!8Iq2lH$L#!1&)!#PKJ%%!&#`H!!JlhJ!"3B$ra(rMqhJiJJ$N5!! T4B""!"5!!3"B1#%!8(`)!kD$iIrmJm(rq)1Krr41J!!J!*!')%'!!`#3"DJ!&Lj NCA0IBf*XEf0VAh"bD@jdAfCTE'9m#!+QNq(rr*2"rrL6SIrdN!!"!!L8)Iq`I(d EH$[#'fmli!!!5!!!-(r$mhJlhJ!)Ik6VH$LJ!!K)!#GaJ%%!&#`$!!"!JJ!-1'! !!8J!!"3lr`!"+"m!%%'!rp!iB!!!J!%!@$JK!&"m#!1QJq(rr)2"rrL$SIrd6S! !)!#3"L""J!-!N!9m!"!ZC'9cAfPcAhGPB@YIDf9j!!#p`Iqi1Z)2-$[#%c!l!JX `I0XcH(ck1hKp'80i,!S!!%'#$04p-%YiLA!!!$S3!!&9D`Bq9Ac!$SQ3!!!!1K! !!9@-"Mj9M)!HIjaMH)P`!!!k%!!"9@X'2P9V3#jrR&YiLC!!!!!k%!!"9B`'2Rq FBhL*F!!!1K!!!99V"Mj9IF!1LC!!!!!k%!!"9B`'2P@-J"jr[@0iLA!!!$S3!!& 9D`Bq9@Y!,Rqp@hL*N!!!!$S3!!&9M!BqIleMH(a`'hL3!)(rX%J!$#JX"3!)3B! !a)P`!!!k%!!"9@X'2P9V"Mj9Dm!1IjaDH)Q3!!!!1K!!!9@-"Mj9M!Bq9Bb!(Rq FBRL*F!!!1K!!!99V"Mj9D`Bq9@Y!,RqF@RL*N!!!!$S3!!&9M!Bq9B`'2RqFBRL *F!!!1K!!!99V"Mj9D`Bq9@[!$Rqp@RL*N!!!!$S3!!&9M!Bq9B`'2P@-J"jr[@* iLA!!!$S3!!&9D`Bq9@X'2P9V3#jr[9TiLC!!!!!k%!!"9B`'2P@-"Mjr[@*i1+A rq%J!!,"q%#S8+!8!"d'"!+!jBK`89+`31ReVB#jpD31Q6S!%)$S3rrq*F!!!9@X '2P9V3#jr[9Ti1K$rriQ3!!!!9B`'2P@-J"jr[@*i1K$rriP`!!"9D`Bq9@[!$Rq p@RJk%2rrLC!!!!"9M!BqIjaLH$S3rrq*F!!!9@X'2P9V3#jrR&Ti1K$rriQ3!!! !9B`'2P@-J"jrR'*i1K$rriP`!!"9D`Bq9@[!$RqF@RJiS!!!2B#UUcQ-UUTrM'! i2@#UUcPVUUTrUeJi9@[iIRfI@hJpJ&991Ba99Aq-B$K9M!Jm2@"996PV999rUeJ iICeEH&HX"Mj9M"!kICKJ,P@-'$KAUmBq9@X31Rei@#j9Da!k9kp'2PA[%$Tpq(J Z9kk'2PA1%$Tpf(!Z9Fi)2(h[FhKpDhYiICaEH&IX"Mj9M"!kICKJ,P@-'$KAlXB q9Fi31RhBF#j9cK!k9qp'2PA[%$Tpq(JZ9qZ'2P9V%$TpH&JZ9@X)2(h[@hKpcRY iICecH$V!!!")!!'JJCX!!$Yl!!4AVUVq9kqS&(h1HhKpRh*i9qX'[P9V%$SjD`- !IAjB,PIXaVj9M"!k1B`#!(fHB#jAlSDq9Fi31MR1!3"phR!Z9qp'[PA[%$TprRJ ZIFjlH(f-FhKpDf0iIjaDH)&l!!!lH`!%9ka0rPHZ5#apM(0iIApLH&I["Vj9la! k1Hm(!(hqH#jAkmDq9@X31MPV"J"pIPJZ9qa'[P@-%$SjM!3!ICjJ,PIZKVj9cK! k1Fi&!(hHF#jpM(0iI@YMH(h[@hKrR(TiJIX!!$Yl!!4ALkVq9ibS&(eVBhKpreT i9qi'[PA1%$SjcJ-!IGj`,PI[aVj9la!k1Hm#!(hqH#jAkiDq9@X31MPV!3"pIPJ Z9qa'[P@-%$TpRQ!ZI@YMH(h[@hKpcRYiIlebH)(E!!!lH`!%9ip0rPH,5#apleY iIGpkH&IX"Vj9M"!k1B`(!(fHB#jAlXDq9Fi31MR1"J"phR!Z9qp'[PA[%$Sjl`3 !IIji,PIVKVj9Da!k1@X&!(eq@#jpleYiIFjlH(f-FhKr[@*i1YB!!5`@!!K"J2j J2B$`m6Q-m2"rV'!i2F$`m6R1m2"rMR!i9FlK2RfIFhJpi!m21Hm2$hq[H$K9lb! f2@!2$cPV$`prLeJiIIeEH&HX"Mj9M"!kICGJ,PHZaMj9cK!kIGG`,PA1%$TAVdB q9Hm31RhhH#j9lc!b9kZ'2P9V%$TpGeJZ9@XJ0Rh[@hKpcRYiICacH&IX"Mj9M"! kICGJ,PIZaMj9cK!kIGG`,PA1%$TAldBq9Hm31RhhH#j9lc!b9qZ'2P9V%$TpGeJ Z9@XJ0Rh[@hKpcRYiICecH$Ylri!pJ+UV1BbUURq-B$Jp`+UV1FkUURqZF$K9c[K qICpcH$hJ998jle99Iipi1&A[#$`pB&991@Y99AqV@$Kpr9Yi9k`'2P@-%$TpQ'! Z9B`B1&HZaMj9cK!kIGK`,PA1%$TAVdBq9Hm31RhiH#jAUiBq9@X31Rei@#j9D`J mIHpEH(h1HhKpR(0i9q`'2P@-%$TpQ'!Z9B`B1&IZaMj9cK!kIGK`,PA1%$TAldB q9Hm31RhiH#jAkiBq9@X31Rei@#j9D`JmIHpEH(h1HhKpRA0i1eS!J$UJ!!")!!' J1eVrr)'D!!"AVNhq9kp),(h1HhKpRh*i9qY'[P9V%$SjD`3!IAjB,PIXKVj9M"! k1B`&!(fHB#jAlJDq9Fi31MR1"`"phR!Z9qr'[PA[%$Sjl`B!IIji,Rh1HhKpM(0 iI@YMH(qF@RJl@[rmJAS!!&HXU[jAVUJ8IBacH(erBRKAliDq9Hm31MR[!3"prRJ Z9qX'[P9V%$SjD`-!IAjB,PIXaVj9M"!k1B`#!(fHB#jpDf0iIHpEH&IZ4Vj9cK! kIGj`,Rh[FhKrR(Ti1eVrr)(k!!"ALdhq9ia),(eVBhKpreTi9qj'[PA1%$SjcJ3 !IGj`,PI[KVj9la!k1Hm&!(hqH#jAk`Dq9@X31MPV"`"pIPJZ9qc'[P@-%$SjM!B !ICjJ,ReVBhKpleYiIFjlH(qpFRJl@[rmJGS!!&H2U[jALkJ8IHpEH(hIHRKAl)D q9B`31MQ-!3"pRQ!Z9qi'[PA1%$SjcJ-!IGj`,PI[aVj9la!k1Hm#!(hqH#jpcRY iIBacH&IV4Vj9Da!kIAjB,Rf-@hKr[@*i1V8!!5`9!!K"J2jJ2B$`m6Q-m2"rV'! i2F$`m6R1m2"rMR!i9FlK2RfIFhJpi!m21Hm2$hq[H$K9lb!f2@!2$cPV$`prLeJ iIIeEH&HX"Mj9M"!kICGJ,PHZaMj9cK!kIGG`,PA1%$TAVdBq9Hm31RhhH#j9lc! b9kZ'2P9V%$TpGeJZ9@XJ0Rh[@hKpcRYiICacH&IX"Mj9M"!kICGJ,PIZaMj9cK! kIGG`,PA1%$TAldBq9Hm31RhhH#j9lc!b9qZ'2P9V%$TpGeJZ9@XJ0Rh[@hKpcRY iICecH$f!UUXjM+UUIiaJ1$h!UUXjcUUUIkj`1&A1q(jpRh0i2H"996R[999rMhJ i9Hm)2$eJ998jDe99IkYB1(hp@hKAV!Bq9B`31RfBB#j9M"Ji9kl'2PA1%$Tpf(! Z9Fi31PH[4Mj9la!kIIKi,PHVKMj9Da!kIAKB,P9V#$apleYiIFjlH(fFFhKAl!B q9B`31RfBB#j9M"Ji9ql'2PA1%$Tpf(!Z9Fi31PI[4Mj9la!kIIKi,PIVKMj9Da! kIAKB,P9V#$apleYiIFjlH(fGFhJkJ!!!5!!"S)'C!!!l13!%9kkUrPH[U"4pcRY iICpbH&IV"Vj9Da!k1@X$!(eq@#jAl-Dq9B`31MQ-!J"pRQ!Z9qk'[PA1%$SjcJ% !IGj`,PI[4Vj9la!kIIji,Rh1HhKpM(0iI@YMH(qF@RL"H3!!1cN!"&HX6IjAVNJ XIBacH(erBRKAl`Dq9Hm31MR["`"prRJZ9q['[P9V%$SjD`B!IAjB,PIX4Vj9M"! k1B`%!(fHB#jAlSDq9Fi31MR1"3"phR!ZIBacH(eVBhKpleYiIjakH)(j!!!l13! %9iZUrPH-U"4pDf0iIIpDH&IZ"Vj9cK!k1Fi$!(hHF#jAlmDq9Hm31MR[!J"prRJ Z9qZ'[P9V%$SjD`%!IAjB,PIX4Vj9M"!kICjJ,ReVBhKpleYiIFjlH(qpFRL"f3! !1cN!"&H26IjALdJXIHpEH(hIHRKAl!Dq9B`31MQ-"`"pRQ!Z9ql'[PA1%$SjcJB !IGj`,PI[4Vj9la!k1Hm%!(hqH#jAkiDq9@X31MPV"3"pIPJZIHpEH(h1HhKpM(0 iIleLH$U8!!%X&!!)3B$qB$f!m2%jM2$`IkaJ1$h!m2%jc[$`Iij`1&A1i6jpRh0 i2H!2$cR[$`prVhJi9HmJ0MeJ$`mjD`m2IiYB1(hp@hKAV!Bq9B`31RfAB#jAVXB q9Fi31RhAF#j9cK!k9kp'2PA[%$TpphJZ9Hm`-PHVKMj9Da!kIAGB,P9V)$CpleY iIFjlH(fFFhKAl!Bq9B`31RfAB#jAlXBq9Fi31RhAF#j9cK!k9qp'2PA[%$TpphJ Z9Hm`-PIVKMj9Da!kIAGB,P9V)$CpleYiIFjlH(fGFhJl1Iq!9ia'2S("rl"pch0 i1Fi!!C("rl#CM`!!9iZ'2S'"rl"pMQ0i1B`!!C'"rl#CEJ!!9ir'2S&Krl"pE&Y i1@X!!C&Krl#Cl!!!9ii'2S(Krl"pkhYi1Hm!!C(Krl#Cb`!!9ka'2S("rl"pch0 i1Fi!!C("rl#CM`!!9kZ'2S'"rl"pMQ0i1B`!!C'"rl#CEJ!!9kr'2S&Krl"pE&Y i1@X!!C&Krl#Cl!!!9ki'2S(Krl"pkhYi1Hm!!C(Krl#Cb`!!,!8!!%'"mpK)!!d J,!8!!%#"$4Kp-%YiLC!!!!!k%!!"9B`'2P@-`!k4JIqXLG!!!$S3!!&9cJBq9Fk !(S(Krkaplh0iNH(rV)P`!!!k%!!"9@X'2P9V3#k"JIqXIBaEH*'"rkb*d!!!1K! !!9A1"Mk"iIqXIHpcH*(Krkb*F!!!1K!!!99V"Mj9Dm!1N@(rU)Q3!!!!1K!!!9@ -"Mj9M)!HJF(rU(h1BhL4`IqSLI!!!$S3!!&9l`Bq9Hp!,S&KrkKpDhYiN@(rU)Q 3!!!!1K!!!9@-"Mk"`IqSIFjMH*("rkKmF"YiN!#"rl#*m!!!1K!!!9A["Mj9r-! 1LA!!!$S3!!&9D`Bq9@Z!(RqF@hL*N!!!!$S3!!&9M!Bq9Ba!,RqFBhL*d!!!1K! !!9A1"MjrR(0iLI!!!$S3!!&9l`Bq9Ih!$SP`!!!k%!!"9@X'2P9VJ"jr[9YiLC! !!!!k%!!"9B`'2P@-3#jr[@0iLG!!!$S3!!&9cJBqIlecH*1"rk56SIqJ2H#UUcR [UUTrMhJi2@#UUcPVUUTrUeJi9@[iIRhr@hJpJ&991Ba99Aq-B$K9M!Jm2F"996R 1999rVR!iICecH&H["Mj9la!kIIKi,PA['$KAUmBq9@X31Rei@#j9Da!k9ka'2P@ -%$TpQ'!Z9kk'2PA1%$Tpf(!Z9Fi)2(f-FhKpDf0iIIaEH&I["Mj9la!kIIKi,PA ['$KAkmBq9@X31Rei@#j9Da!k9qa'2P@-%$TpQ'!Z9qk'2PA1%$Tpf(!Z9Fi)2(f -FhKpDf0iIIeEH$Xj!)!kB!!!5!!"S$Xjrrb"q3!!9kY0rPHX5#apDf0iIIpDH&I Z4Vj9cK!k1Fi%!(hHF#jAliDq9Hm31MR["3"prRJZ9qX'[P9V%$SjD`F!IAjB,PI XaVj9M"!k1B`'!(fHB#jpDf0iIHpEH(h1HhKrR(*i1cRrr)(C!!"AVkVq9kZS&(h [@hKphhTi9qb'[P@-%$SjM!%!ICjJ,PIZ"Vj9cK!k1Fi$!(hHF#jAlmDq9Hm31MR [!J"prRJZIFjlH(f-FhKAkdDq9@X31Req@#jpM&YiIjaLH$Xjrrb"Q3!!9ij0rPH 25#apcRYiICpbH&IV4Vj9Da!k1@X%!(eq@#jAl)Dq9B`31MQ-"3"pRQ!Z9qi'[PA 1%$SjcJF!IGj`,PI[aVj9la!k1Hm'!(hqH#jpcRYiIBacH(eVBhKr[9Ti1cRrr)& j!!"AM+Vq9ikS&(f-FhKpIf*i9qq'[PA[%$Sjl`%!IIji,PIV"Vj9Da!k1@X$!(e q@#jAl-Dq9B`31MQ-!J"pRQ!ZI@YMH(h[@hKAlNDq9Fi31RhHF#jplh0iIlekH$T c!!%X%`!)3B$qB$hJm2%jlr$`Ikpi1$eJm2%jDr$`IiYB1&9Vi6jpreYi2B!2$cQ -$`prV'!i9B`J0Mh!$`mjcJm2Iij`1(fGFhKAV`Bq9Hm31RhhH#jAUmBq9@X31Re h@#j9Da!k9ka'2P@-%$TpPf!Z9B``-PHZKMj9cK!kIGG`,PA1)$CpM(0iI@YMH(h m@hKAl`Bq9Hm31RhhH#jAkmBq9@X31Reh@#j9Da!k9qa'2P@-%$TpPf!Z9B``-PI ZKMj9cK!kIGG`,PA1)$CpM(0iI@YMH(hp@hJpi+UV1HqUURq2H$JpB+UV1@ZUURq V@$K9DrKqIIpEH$f!998jM&99IiaJ1&@-#$`p`&991Fj99AqZF$KpRA0i9km'2PA [%$Tpq(JZ9HmB1&HVaMj9Da!kIAKB,P9V%$TAV%Bq9B`31RfBB#jAVSBq9Fi31Rh BF#j9cJJmIBacH(eVBhKpr&Yi9qm'2PA[%$Tpq(JZ9HmB1&IVaMj9Da!kIAKB,P9 V%$TAl%Bq9B`31RfBB#jAlSBq9Fi31RhBF#j9cJJmIBacH(eVBhKpr9Yi1N!!!%J !!D#"qJ!!1eS!"&HVU[jAV+J8I@YMH(hr@RKAlJDq9Fi31MR1!`"phR!Z9qr'[PA [%$Sjl`)!IIji,PIVKVj9Da!k1@X"!(eq@#jAl%Dq9B`31RfHB#jpDf0iIHpEH(h 1HhKrR(*iJGS!!$YD!!4AVdhq9kY),(h[@hKphhTi9q`'[P@-%$SjM!F!ICjJ,PI ZaVj9cK!k1Fi'!(hHF#jAldDq9Hm31MR["!"prRJZ9qZ'[P9V%$SjD`8!IAjB,Rh [@hKpcRYiIBacH(qFBRL"QJ!!1eS!"&H1U[jAMkJ8IFjlH(fIFRKAk`Dq9@X31MP V!`"pIPJZ9qc'[P@-%$SjM!)!ICjJ,PIZKVj9cK!k1Fi"!(hHF#jAldDq9Hm31Rh qH#jpcRYiIBacH(eVBhKr[9TiJAS!!$YD!!4AM%hq9ij),(f-FhKpIf*i9qm'[PA [%$Sjl`F!IIji,PIVaVj9Da!k1@X'!(eq@#jAl%Dq9B`31MQ-"!"pRQ!Z9qk'[PA 1%$SjcJ8!IGj`,Rf-FhKpDf0iIHpEH(qpHRJk8J!",")!#%'!rQ!pi2$a1Hr`m(q [H$JpB2$a1@[`m(q,@$K9Dq%qIIpEH$f!$`mjM!m2IkaJ1&@-)$Bp`!m21Fi2$hq 1F$KpRA0i9km'2PA[%$TpphJZ9k['2P9V%$TpGeJZ9@X31PHX4Mj9M"!kICGJ,P@ --$*AVSBq9Fi31RhAF#j9cL!fIBacH(eVBhKpr&Yi9qm'2PA[%$TpphJZ9q['2P9 V%$TpGeJZ9@X31PIX4Mj9M"!kICGJ,P@--$*AlSBq9Fi31RhAF#j9cL!fIBacH(e VBhKpr9Yi1eVrJ$hJUUXjlkUUIipi1$eJUUXjDkUUIkYB1&9Vq(jpreYi2B"996Q -999rM'!i9B`)2$h!998jcP99Ikj`1(fGFhKAV`Bq9Hm31RhiH#j9laJi9k['2P9 V%$TpH&JZ9@X31PHX4Mj9M"!kICKJ,PHZKMj9cK!kIGK`,PA1#$apM(0iI@YMH(h m@hKAl`Bq9Hm31RhiH#j9laJi9q['2P9V%$TpH&JZ9@X31PIX4Mj9M"!kICKJ,PI ZKMj9cK!kIGK`,PA1#$apM(0iI@YMH(hp@hJlH`#!1L!!!%J!!D!lHrrmJIX!!&H V6IjAV%JXI@YMH(hr@RKAlNDq9Fi31MR1"!"phR!Z9qq'[PA[%$Sjl`8!IIji,PI V"Vj9Da!k1@X(!(eq@#jAl-Dq9B`31MQ-"J"pRQ!ZI@YMH(h[@hKpcRYiIjabH$Y lrrb"f`!!9kqUrPHVU"4pleYiIGpkH&IXKVj9M"!k1B`"!(fHB#jAlJDq9Fi31MR 1!`"phR!Z9qr'[PA[%$Sjl`)!IIji,Rh1HhKpM(0i9qY'[P9V%$TpIPJZIBaEH(q FBRJlHrrmJCX!!&H16IjAMdJXIFjlH(fIFRKAkdDq9@X31MPV"!"pIPJZ9qb'[P@ -%$SjM!8!ICjJ,PIZ"Vj9cK!k1Fi(!(hHF#jAlmDq9Hm31MR["J"prRJZIFjlH(f -FhKpDf0iIleDH$Ylrrb"H`!!9ibUrPH1U"4pM(0iIApLH&I[KVj9la!k1Hm"!(h qH#jAk`Dq9@X31MPV!`"pIPJZ9qc'[P@-%$SjM!)!ICjJ,ReVBhKpleYi9qj'[PA 1%$TphR!ZIHpcH(qpHRJk-3!","%!#%'!rQ!pi2$a1Hr`m(q[H$JpB2$a1@[`m(q ,@$K9Dq%qIIpEH$f!$`mjM!m2IkaJ1&@-)$Bp`!m21Fi2$hq1F$KpRA0i9km'2PA [%$TpphJZ9k['2P9V%$TpGeJZ9@X31PHX4Mj9M"!kICGJ,P@--$*AVSBq9Fi31Rh AF#j9cL!fIBacH(eVBhKpr&Yi9qm'2PA[%$TpphJZ9q['2P9V%$TpGeJZ9@X31PI X4Mj9M"!kICGJ,P@--$*AlSBq9Fi31RhAF#j9cL!fIBacH(eVBhKpr9YiJH(rV(q FHRL"BIqSIleDH#`&!!K!J3$F1+Arq&H-4Mk"`Iq`IFpcH$R1!!'4`Iq`QBm!!&H ,KMk"JIq`IBjMH$Q-!!'4JIq`Q@i!!&H2aMk"BIq`I@aEH$PV!!'4BIq`QH`!!&H 1"Mk"iIq`IHYlH$R[!!'4iIq`QFX!!&HX4Mk"`Iq`IFpcH$R1!!'4`Iq`QBm!!&H VKMk"JIq`IBjMH$Q-!!'4JIq`Q@i!!&H[aMk"BIq`I@aEH$PV!!'4BIq`QH`!!&H Z"Mk"iIq`IHYlH$R[!!'4iIq`QFX!!)'"rk54JIqXJF(rS*("rkK,rr5-JH(rX(h [+K54iIq`+!8!#%'"!,JjBK[`9+`31ReVB#jpD31Q6S!%)&HZ"Mk"iIq`1Hrrrj( Krl#Cc`!!9k['2S'"rl!jM2rrNB(rX*PX!!"AVSBqJH(rX$R[rrq4iIq`QFm!!&H V4Mk"JIq`1Bcrrj'"rl#CE!!!9ii'2S(Krl!jlrrrNH(rX*R2!!"ALmBqJB(rX$Q -rrq4JIq`Q@`!!&H1KMk"iIq`1Hrrrj(Krl#Cc`!!9iY'2S'"rl!jM2rrNB(rX*P X!!#j`Iqi6S!!)!#3"L"!!")!N!3D'!!4,Q4PFemcBf*MAf9ZBh*jF(3![X(rf$V L(63k`K`dI*NMH(ai'hL)Z!!!1aJ!!95r"Mk)f!!!1aJ!!96'"Mj8aN!ZIrmcH)M i!!!l'!!"91F'2P6RJ"jrrcYiL4J!!$XB!!&9#!Bq93M!$Rrr3hL*1!!!1aJ!!98 q"Mk*@!!!1aJ!!99+"Mj95N!ZIpj6H)Pi!!!l'!!"9@X'2P9VJ"jrhPYiLCJ!!$X B!!&9M!Bq9Bc!$RrHBhKAaH%qI+AkH$c!$`miaJm2I,``1(rriRKAKb!fIpikH&I SN!!DI3MkH(8Fc-aALA5qIqVLH(dr8RKAbj!!'ReVmRKeI-c-9iad[Rr&iRKpRLT i9mEiIRc'qRJmi&9911G99AcF1$Krrq*i9iJ)2(rH3RKAkF)qI5RbH$e!!2mj5J$ rI6a31(rHiRKALd!ZIrpDH&I-q(jpM2Ti2+"996LP999pR#JiIrrLH&H'#$arhM* i9qF!"P6Ri6jAb!)H93L%2PI*"Mj9+B!H9mS%,RdT8hKp#%YiI2j$H&Ir!6ilB!! !5!!"@&GV%$TpGPJZ,!X!!%'#!#"Al2#q9qA3#RfI+hKAa[#q9mI3#RcH1hK)!!! F9qMiIPITf!Kp(dYi9mViIPI,f!KpAPYi9rm"2PIH!6jAl&Di9q9RrPIQAhamT60 iIB`VH&@-%$SjM!-!ICGJ,PIRRcjAk*DfI1G$H&6R%$Sij`)!I2Fi,PITeljAkXk kI5P6H&8T%$Sj+3%!I6G),PIV"Vj9Da!kIAGB,RdT@hKmjdYiICSlH&I-AcjAa9D fIB`VH&@-%$SjM!F!ICGJ,PI'MVj8aK!k1-B'!(cA-#jAa`Dq91F31MMR"!"mpcJ Z9mM2[PI*aVTp#%Yi93J31MN)"3"p&d!ZI1G$H(c'1hKpR$0i9iU!(PG,"$jpA9Y i9k`A[PHP%$TpM#S8NCN!!$Xj!!4A4S3q9iF!(RcG1hKAU$Dq9kN`-Rd)5K54'3! !1cN!"$Yl!!%X'`!33B$qU$KJ!!#k`IrB6S!!)!#3"L"!!!S!N!3#m!!-,Q4PFep cCA4IDf9j!!"m#!+QN!!"!!L8)Ir!N!"K!&L3!)%!A)"K!&L!J3"F1+)Y`%J!!$P J!!!!1')Y`)!"!%Ji)3"!I!J$TNk!!#!!N!BJ3B!!N!Bm!!SZC'9cAf0bHA"dI!J #TVj"rmL3!!%!#*3Kr["mGKYiI*3MH(bk+hJkiKcd1`%!1)Kd!!"mB`Gd,!-!!%# #!!`iJ!""5!!!$)L8!!"mK!GdQ*S!!(b9"h3iSKadI+@SVP5c%$U)e!!"I-B(G#` '!!"!JJ!-11!!38J!!!b)p!!"I1F(G*Mk!!&mp3Gd13)FG(d)U+j9%M!b1f!!!%J !!#b,eJ!!1YB!!9I*"MiS#3!!3B)!0&I+"Mj95JJm1@%!a(e,fDilH`!"+"X!#%' !rp4)!!!81B!!!$KK!-4pJpQZ1hX!!5JE!!K"J2rX1'%!a$L"!%4,rrZaB!!!!$K K!-`iJ3"%IQ@EH(j'NhK)!!%aB!!!!)-K!-aA*!BqQ*J!!$XB!!&A*FBqQ,J!!$X B!!&A*SBqQ0J!!$XB!!&A*dBqQ2J!!$XB!!'$)3$39bJ'2TNB!!!l'!!"9bR'2TN i!!!l'!!"9bU'2TPB!!!l'!!"9bY'2TPi!!!l'!!"1i!!!$[J!)!jJ!!!QB%!3$Y J!!*)!!"N1m!!!$ZJ!!")!!"!9pi)2$KK!$KmBq#Z9q3'2RaM)$JX!`!!3B)!#'2 H!!&Arrjq9q8'2LJ&!!"!JJ!-1j`!!6[J!)!l[3!"+"d!"N'!rm"AaJBqI0F`VRc DfDilH`!"+"X!$8'!rj`ii!!!Q2S!$Ap$dhL!!3%B1#%"%(`)!kDk3Ir)6S!!)!# 3"L""J!i!N!3#%!!,,Q4PFepQBh*jF(3!!!#q!Ir!1k)P0$Z!!!!lB!!!I*8MH*! !SIq`N!$"rk`ii!!!N!$Krl4)!!4-1X!!!%J!"#4AD)3qIhp#H)%Krl"rrNJiJ8( rV(rr8$KAfS!H9XX31Ree@#jrDeTiIpjDH(rHdRKAqS!H1CB!!9@-%$TpP@!ZIfa LH(rrBRKrrp*iIp4'F&ID"MT@P!Bk9qIK2PISi!Crjd)89pk%2Rdpd#jrR%Ti193 #!(eG8#jrR&*i9p2#2PID"MT@F`Bk1AS%!(ep@#jrR&Ti1C-'!(fGB#jrR'*iIr4 'F&Ik"MT@P!Bk9rq%2MMk!3"mr6JZIj`kH$N8!`"p(8!ZIja#H(rc4R"AqJBk9R- '1MNk"3"p28JZIja+H$P6"`"pA9!ZIja5H&H,K$jrReTiJB(rX(rqB$L!iIqXIrm i1&ICJ"ij&J!#93J31Rd93#jrL%*iIpj#H(rHbRKAqB!H16B!!e8T%$Tp08JZIiP +H(rr5RKrrmTiIp*'F&IC"MT@8JBk9qVK2PIVi!CrkPS89pk%2RfGb#jrHf*i12) #!(cp1#jrHcTi9p(#2PIC"MT@-3Bk14N%!(dG3#jrHd*i16%'!(dp5#jrHdTiIr* 'F&Ij"MT@8JBk9rq%2MPC!3"pA9!ZIhY5H$Pb!`"pI9JZIhYDH(ra4R"Aq3Bk9M% '1MQC"3"pR@!ZIhYLH$Ma"`"mr6JZIhXkH&GSK$jrId*iJ5(rX(rq5$L"3IqXIrp 31&IBJ"ijGJ!%9@X31Ree@#jrDeTiIpjDH(rH`RKAq)!H1CB!"9@-%$TpP@!ZIfa LH(rrBRKrrm*iIp"'F&IB"MT@%!Bk9qIK2PISi!Crjd)89pk%2Rdp`#jrR%Ti19! #!(eG8#jrR&*i9m[#2T&KrkKAf!BkJB(rU&@-"MU4JIqS12J%!(cp1#jrR$TiJ3( rU$N)"J"p(8!ZIja#H(r`4R"Aq!Bk9K!'1PIrK$ij1!%!I6e),RqF5RJj8!-!I9e 3,RqF8RKrkdC`N@(rU&Ii"MU"JIqS9B`'1T'"rkJiq!8!I2di,RqF1RL"!IqS13J (!(dG3#jrR%*i9iQ%2RqI5RL"3Iq`Irj31)&KrkarreJi9pH!(MQ@!!C9M"!kIC9 J,Rq-BRKrhQ*iIpkkH&IhJ"iipJ!(91F31Rce1#jrKcTiIrmkH(rrZRKrb%C`N3( rT&IA"MU")IqN95N'1T%Krk4AkZ%q9q[J"RrU@K4AhS3qICfi,RplBRL!iIqN11F #!(cp1#jrHcTi9mM#2T%"rk"Ae`BkJ5(rS&8T"MU4)IqJ19F%!(eG8#jrHe*iJ@( rS$PV"J"pI9JZIhYDH(rX4R#4JIqN9rF'1S$Krk48j`BkN!$Krk4Ari3q14F"!(d G3#jrHd*iJ5(rT$NT!`"p28JZIhY+H(rU4R#43IqJ9rF'1S&Krk"9D`BkN@(rS$Q A"3"pR@!ZIhYLH)$Krk!ij`F!I2di,Rpl1RJkeJ!),"B!)%'!qparRq0iIhcEH(r lqhL"!Iqd13J!!C%"rl5")Iqd,!N!'8'!ql"ALZMq9i[S"(q+@K4AE1Mq9fIS"(p X1K4AL2KqI3MDH$dJ998j+999I4p)1(plqRKAkJJmIja5H&GV`MjpDq*i2B!!rcQ -!2ppIf!iIjckH&IR3#jrHcTi9iM`[Rd)fRJp)$-c15Nc-hdI5$KrHrTi9qS31Rq F8RKADi3qI@[LH&9r"$jrR2Ti9qb!(RplBRKAKq%qI1IDH$d!$`mj#!m2I2p!1(p lqRKAk5!fIja+H*0M!!#6J`!%ZJ(r`%k!!#!!N!BJ3!!3!*!%"6`!$#jQBh*jF(4 IBQpNH3!!I!J#TVp"rqL3!!%!#*3Krl"mHKYiI*mMH(bl+hKmh$0iI2dlH(dH3hJ X(J!!3B)!B(p$dhKrj2YiIfAEH(r'mhK,rlFGB!!!!(rMqhKrj2YiIiAMH$MJ!!! X(J!!3))!#$MJ!!&mjMYi5rqfp@!!!!"rirYiIq6lH(qPkhKra[0i5rqfh@!!!!" )!!"FId26H(rNqhKrTHYiImEcH%[rYX&J!!!!Iq2lH(rNqhKrKH0i13!!!#`H!!" !JJ!)13!!!Ad'3hK,rlDCB!!!!(rMqhKrj2YiIfAEH(r'mhK,rlD"B!!!!)!"!&J i)3"3I!J$TVY"rqK1J!!J!*!')%'!"J#3"IJ!%5jNCA0I-f9MBPpPEQ0bHA"d!(a $%hK1J!!JI!J#TT!!!3!)P#(r`%[rrqemD4YiJ')!F)##!'`iSJ!!1-)YcS$L!'# "!J"F5!!!@B""!"5!JJ$8N!"N!!",rk0CB!!!!$KJ!!#!!3")1#%!3(`)!kC1J!! JI!J#TT!!!3!)P#(r`)"L!05!B`!!5!!!-B""!"5!!3")1#%!3(`)!kC1J!!JJB) !2*!!33!8J!`!!)"-!!4m#31Q6S!%))'#!$L3!%%!&)!-!!#!6!!%I!N$TNk!"## "JJ!BN!""!"5!$!!!J%`!"(`*!kC1J!3JJB)!%*!!33!8J!`!!)"-!!4m#31Q6S! %))'#!%#3!%%!&)!-!!#!6!!%I!N$TNk!"##"JJ!JN!""!"5!$!!!J%`!"(`*!kC 1J!3JJB)!$*!!33!8J!`!!)"-!!4m#31Q6S!%))'#!"53!%%!&)!-!!#!6!!%I!N $TNk!"##"JJ!NN!""!"5!$!!!J%`!"(`*!kC1J!3JJB)!#*!!33!8J!`!!)"-!!4 m#31Q6S!%))'#!#L3!%%!&)!-!!#!6!!%I!N$TNk!"##"JJ!XN!""!"5!$!!!J%` !"(`*!kC1J!3JJB)!"*!!33!8J!`!!)"-!!4m#31Q6S!%))'#!!#3!%%!&)!-!!# !6!!%I!N$TNk!"##"JJ!`N!""!"5!$!!!J%`!"(`*!kC1J!3JJB)!(*!!33!8J!` !!)"-!!4m#31Q6S!%))'#!$53!%%!&)!-!!#!6!!%I!N$TNk!"#!!!!!FJ!!!I!J !N!DBJ!!!6!#3"LQXJ!!!Q!J!N!8U4)!!!)!)!*!&+X5!!!$3!*!'+j5!!!#3!"! !N!8X*)!!!'!!N!BXK)!!!+J3!*!&,5b!!!&)B!#3"5m)J!!"4%!!N!8`6)!!!+! )!*!&-1b!!!(m5!#3"6,SJ!!"`&!!N!8dU)!!!0!B!*!&0AL!!!#J'!#3"90NJ!! !@!#3"P1mJ!!#-(!!N!9E5)!!!4``!*!&A'b!!!"B!*!'A-5!!!!X!*!04L)2-!) L%c!#)JX`"L)G0))#"#8dAhKHL#h1"#*IH!BL!F5#!KJ"k!))!LJ#6!F`!c!$%!, 3!T!!!R!YZ#di!0JE6aX`'fJEEa[`("3F0"cd((3Y`!$S!L%+!5)PH!%L,#!")L" p#5'BKJ)D!"`!j!b8%U3C`"MS'VJQC#QX,)3X*#Z8+X3U4#dX,`J`l$"--ZJdU$9 i0KK39&1m8f4E5#)-C))#+JaB$%`-3!`d$#J-(!`3$!3$%!,m!ZJ#e!,%!V!#R!+ )$V31S!k-$RJ1D!j8$N!1,#Bd*LJQ(#B3*J3Pq#AX*H!Pe"c8(-!FV"bB()JFG"a J(%`F2!8K%)%$"J!3!!!3%"!!!"!!%"!3!"!3%!3K%!3K%!)L%"!%)4#"!`X3!"! !%*!&!!!"%!!"!"!"%"!"!!!4%!!4!"!4%"!4"L%"!L%"!b)"!3%K!3-K!3%K!3% L!3%#*!'3"!-K!3)L!3%")3%")3%"*!'3"!)L!3%"*!'3"53"N!3%)3%%)3%#)J% ""#%"!5%"!5%"!L)"!3%M!3%"##%%J3-0!3!!!3!%!!3!!!3%!33!!33%!!!J!!! N!3!J!3!N!!3J!!3N!33J*!%%*!%$)3%#)`3"!3)L!3%")J3"!5%%!5%"!58%"!% ""!%P!3%%"!%#)L!"!L-N!3%")b!"!3%L*!%")`3J!3%U"#3"!33J!3%%*)%$$`) !!!)!"!-!!!-!"!)%!!)%"!-%!!-%"!)!)!)!*!-!)!-!*!)%)!)%*!-%)#8$"#3 "!J)L!3)")`3"!`)L!3-"*!3"!J3"*`%#"!3"!`3"*J%$"!3"!J%M)!%#!5-N!3- ")b!"!`%a*!%#"#!"!J3N!3-%)!%$"#3%)3)&)3J")3)")3J#)3J#)J))!b))#!% M!JJ)"#)"!J)K!3)M#!%#!5))!3%K#!%M!3))!5%"!5F)#!%##!J"!L%"J3-(!J! "!!!*!J!*!!J"!JJ"!!J*!JJ*!L-"!3)")J%"!L-*!3)")JN"!5F)!3%##!%"!5J )#3%##!N"%!-K%J-K%!%K#!%K%J%K#!%L%!J#)K))!L-3#!J")a))#!%K%!)L!4) #)J%3!5-)!4)"*!J"%!J")`%5#!%U!4!)#!%5#!J"%!%K!B%$"a)!!4!!#4)!#4! )!4))!4!)#4))#5%3!5-"!4)")`%"%!%M#3%5!6)*!4!)!3%5#!%"%!J*!4))#3% &)33%)5##!J3%)"!!&!!3)#)8))%$##!!!#!%!#!!)#!%)#!3!#!8!#!3)#!8)!- K#)%$"J3!#!!J#!3J#"!!#"3!#"!J##38)!JJ!L-))!3")JJJ!5JJ##!%)!JJ%!% M##!8!5N))"!J##!8)!L"!`FJ!!!N!!!J)!!N)!!`!!!d!!!`)!!L0##"!`JJ)!! J*!!JN!3N)#!`!#!d!#!`)#!d)!%K)!%K#)%$"L3!##!J##3J#$!!#$3!#$!J##8 d)!JJ)!%M##!N!5X))#!J##!N)!JJ-!%M##!d!5N))$!J##!d)!J()K!)J3-r!!! )!"!!!J!!!K!)!J!)!K!!!!)!!"))!!))!")!!J)!!K))!J))!K)%!!!%!"!-!!! -!"!%!J!%!K!-!J!-!K!%!!)%!")-!!)-!")%!J)%!K)-!J)-!K)!%!!!%"!)%!! )%"!!%J!!%K!)%J!)%K!!%!)!%"))%!))%")!%J)!%K))%J))%K)%%!!%%"!-%!! -%"!%%J!%%K!-%J!-%K!%%!)%%")-%!)-%")%%J)%%K)-%J)-%K)!!!!#!b%#!L) #!J3K!3%K!J%K!3)L!J%")`)#!33L#!)#)3J")3)")`J#!J%K#!)M!3J#!5)"#!% R!J%)!J)"#!%K)!)L!L!$)5)#)J)L!b)J!3%M!L!"!L)L!3%M!L)"!L%J!5-)!L! ")3J")5)")`J#)J%K#!%R)!%)!L!"#!%R)J%)!L)"#!)K!S%$"`)!!J!#N!8!!!- #!!-!!J-#!J-#)`))!J%L!JJ"*`)##!)#!JJ#)`-)!J%L!`J"*`)$#!)#!`J")L! #J3-(!L!#!#)#!L)#!#!$!L!$!#)$!L)$!5FJ!JJ#)!))!5FL!JJ#)J))!5FJ!`J #)!-)!5FL!`J#)J-)"L%3"#%J!L)3)!%K%!-L%"!#)4!")5!"*"!3)!J$)3J")4! ")3J#)L!)!533)!J3!L-)%"!")JJ3!58J#"!3))%$"`!!"!!3"!!!*!!3*"!!""! 3""!!*#33%#3)!L)%#!%M%!3)!L)N#!%N%#3)%!%R"!J3%!3)%!%P*!J3%#5"!`F !"!!!&!!!"#!!&#!3"!!3&!!3"#!N%"3J#!%K"!%K#!%K&!%K#!%M"#!)!588)!J 3"!%M#"!8!5J)%!3J#"!8))%$"`!%"!!8"!!%*!!8*"!%""!8""!%*#33&#3)!5- %"!J")a3%#!%M"#3)!6)8*!J3"!3)%"3%#"!%*!J3&#3%)4!%)3%#)K!""5)#%!) K!J%K!3%M!K!"!5%#!L%J!5%3!5%J!L)")!%M%!%J!b-J!K!")L!#!5F")!)3!5! #!5%%J3-(!"!%!!!&!"!&!!!%!K!%!J!&!K!&)3)")J3J!5-3"#!#)J8J!5-3"5! #*`3J!K!%)!)"+!8J!K!&)!)J!b%`!b)J!3)L-!%#)5!#)J)`!L-#)!%")`)`!3% L!L!")5!")6!")5!")b!")!%M-!%J!5%J!5-J!M!",#!#)!%J!M!")!)J")%$"`! `"!!J"3!`"3!J"!)`"!)J"3)`"53#)!3J!5-`"#!")b!&)!%M-!8J!6!J"#!#-!3 J!L!&)!)`"5!#"#%%"L)""))#$!%"!!8!!3%&!3!3""!!%334!4!&%!%4"5%4!5% )J3-2!!3)!!!)!33)!3%)!!8)!!%)!38)!3!)%!3)%!!)%33)%3%)%!8)%!%)%38 ))4%#)3J")35"!`i)!!!)!33)!3%)!!8)!!%)!38)!3!)%!3)%!!)%33)%3%)%!8 )%!%)%38L#"%")JJ)!5-%#!J#+JJ)!33)#!%"#!J")`8)#!%S!3J)!38)#!%"*`J )%!3)#"!"0`J)%33)#"%"#!J3"3J)%!%)#"%&#!J4"b%3JJ)0!!%!%4!!%"!3!4! 4!3!"%!%"!4%4!"%3%3%L%4'"!bm3!!!3!"!3!!%3!"%3%!!3N!8"%"!4%!%!%!% 3%!%"%!%4%"%!%"%3%"%"%"%4!3!!!3!3!3!"!3!4!4!!!4!3!4!"!4!4!3%!!3% 3!C!&%3%4!!%4%!%4!3%4%4%!!"%!%"%!!4%!%4%3!"%3%"%3!4%3%4%"!"%"%"% "!4%"%4%4!"%4%"%4!534%4%3J3-2!!!3!"!3!!%3!"%3%!!3N!8"%"!4%!%!%!% 3%!%"%!%4%"%!%"%3%"%"%#34%4!3!L)3%!%M%"!3!5-"%"!"*"%3%"!",a#3"`% 3%"!4%"!"!5m3%!%3%"!"!4!3!4%3%"%",K!3%4!3%"%"%"!4%4!"!L)3!3%M%"! "!5-"%!%"*"%3!4!",a!"%"!3!4!"%!%3%4!"!3%[%!%"%"!"!3%3!3%4%!%4!5i 3!4%3%!%4!4!"%4%3%3)L%"%")a!3%3%M!4!4!534%"%3!5m3%4!3%"%3!4!4%"% 3%3%",a!4!4!3%3%"%"%"%4!4%3%Y%"%4%"!4%3%3%4%4!B%$$`!!!3!3!3!"!3! 4!4!!!4!3!4!"!4!4!3%!!3%3!C!&%3%4!!%4%!%4!3%N%4%"%!)L!4!")a!"%!% M!3%3!534!4!3!5m"%"!3!4!3!3%3%"%"%!%",`%3!4!"%!%"!4!"%3%3%3%Z!4! 4%!%3%3%"%"%4!3%#)J%"!5-3!3%")`'3"#34!3%3!5m"!4!3!3%3!3%"%"%"N!3 [!3%"%!'3"a%"!4%",J%"%4!"!4%"!3%4%3%4!L)"%3%M%!%4!5-"!4%"*"%"%4! ",`%4%"!"%4!"!4%3%3%4!3%[!4%"%!%4!3%"%3%4!4%4!5d"%4%3!4%4!3%4N!5 "!`m!!"%!%"%!!4%!%4%3!"%3%"%3!4%3%4%"!"%"%"%"!4%"%4%4!"%4%"%4!4% N%4%4%!)L%4!")a!4%!%M!4%3!534%4!3!5m4%"!3%4!3!4%3%"%4%!%",a%3!4! 4%!%"%4!"%4%3%3%Z%4!4%"%3%3%4%"%4%3%#)K%"!5-3%3%")`%4!3%N%4%"%!% [%3%3%"%"%!%4!4!4%3%"!5m4!3%3%3%"!4%"!4%4!4%",K%"%4!4!4%"%3%4N!3 #)K%4!5-3%4%")`%4%3%N%4%4%!%[%4%3%"%4%!%4%4!4%4%"!5m4%3%3%4%"!4% 4!4'3"!%X%4%4%"%4%3%4N!3%)3)%)3)#)J)#"#%#!5%#!5%#!L)#!J%M!J)#"#) #!J)K!J%K!J%M!J)#!5%#!L-#!J)")J)#!5J#N!F"!b%$!b)"!J)L!`)#)3%")3) ")3-")3)")`%#!J%M!`)#!5%"!L)#!`)M!J%#!5-#!`)")J)"!5-#!J-"+J)#!3) #!J-#!J)")3%#)J)"!b%$!L)#!`-L!3)")`)"!J)L!`)")`)$!J)K!3%M!J)"!5% #!5%$!5-#!J-")3)"*`%#!J)"!J)"+3-#!J)$!J)"!3)L!`%#)J%$!L)$!`)M!3% #!5-$!3)")`%$!J%M!`-#!5)"!3%M!J-"!5-#!3-")`)$!`%a!J%"!J)$!3)#!3- #!J-$!J)#)3'"!`F#!!%!!J%#!J%!!!-#!!-!!J-#!J-#)`%#!J%L!3)"*`)"!J) #!3)#)`-#!J%L!`)"+!)$!J)#!`)"!5%"J3-(!`!"!3)"!`)"!3!$!`!$!3)$!`) $)3%")`%#!`%V!3)"!J%#!`)"!J%")`-#!`%U!`)"!J-#!`)$!J%L!3'"!`F#!3% !!`%#!`%!!3-#!3-!!`-#!`-"*`%"!J)"!3)"*`-"!J)$!3)"*`%$!J)"!`)"+J- $!J)$!`)"!3'"!`F$!3%"!`%$!`%"!3-$!3-"!j!&)#!"!3%#!`%"!J%$!3)$!`% #!3%$!J-"!`)"!`-#!`-$!J-L!3)#)3%")3)")`%#!J%K!3)M!J%#!5)#!3%R!J) "!J)#!3-L!`)#)3-")3)")`-#!J%K!`)M!J-#!5)#!`%S!J)$!J)#!`%#)J%$!L- "!3)")`%$!J%L!3%")`)"!`%V!J%"!J)"!`)#!3%#)J-$!L-$!3)")`-$!J%L!`% ")`)$!`%U!J-"!J)$!`)#!`%K!3%M!3)"!5%"!5%$!5-"!J-")3%"*`%#!3)"!J% "*`-#!3)$!J%")3%")`-#!3%K!`%K!`%M!`)$!5%$!5F"!J-#!3)$!5N$!J-#!`) $!3%")`%$!3%M!3%$!5-"!`-"-`%"!3)"!`%#!3%$!J%$!`)"N!3M!`-"!5-$!3- ")`-$!`%a!`%"!J-$!3)$!3-#!`-$!J-#)`%"!J%L!3%"*`)"!3)#!3%#)`-"!J% L!`%"*`)$!3)#!`%#)`%$!J%L!3-"*`)"!`)#!3-#)`-$!J%L!`-"+!)$!`)#!`- "!5-"!3-"+`%"!3)"!3-#!C!%)`-"!`%V!`%"!J-"!`)$!3%")`%$!`%V!3-"!J% $!`)"!`%")`-$!`%U!`-"!J-$!`)$!`%R!3%"!J'3"#F$!3%#!`%"!5F"!`%#!3- "!5F$!`%#!`-"!5F"!3-#!3%$!5F$!3-#!`%$!5F"!`-#!3-$!5"(!`-$!J-$!`' 3"!-"N!3$!3%$!`'3"!-"!`%$!3%$!`%$!`-"N!3$!`%"!`%$!3-$!`%$!3%$!`- "!`-"!j!(!5%3!L)#%!%L!3)")J3""L%%!5%#!5)%!3%Q%!3"!K!%!53#%!3"!5% 3"L%#!L%"!b)"!J-L!K!")3%#)`3"!J%K"!)M%!3"!5%3!5)"!J%K"!%K!J)M!3) 3!L-#%!3#)4!")`%#%!3K"!-Q"!%#%!3"!5)3"!3L!3)%)K!%!5%#"#)3"!)K%!) K!J%M"!%#!53%!3)3!5-"!K!")3%$)3%")4!")J%#!b%#!5%%!L%3!L-#%!3$)J3 "!5B3"!%#%!3$)`3"!J)R!3)3"!%#%!-L%!3)*3%#%!3""583"!%#%!3K"!%K!J) L!3)")33$)33#)4!")3%")S##"b'!!L1!JJ+"!aL!J!)!JJ)!!!)!J!!!!J#!JJ# !JJ)!!J#!!J+!J!+!!*!%!J!#!S!#!)!#!!##!!##!)#!!)#!!)!#!J#!!S!!!S! !!J#!!J8L!J+"!ad!JJ+!!!!!J!#!JJ)!!!+!J!#!JJ#!!!#!!!!!!J#!J!)!J!! !JJ#!!!)!!J!!!!+!!J)!JJ+!JJ)!J!+!J!#!!J+!!!)!!J)!JJ+!JJ!!!J+!!J# !!J!&)S!#!L'#"L1!J!)#*3%%"!%""5)%!3%L"!3")3%'*!%""!3")3%#)3%")J3 %!L)%"!)K"!%K!3)N"!%""!%K!3%M"!3""#-""!3'*!3%!3%$)3%#)J%"!5)%!3) L"!%")33"*!%""!3")J%%!5)"!3)K!3)K"!%L!33$*33%!3%%!L%"!5%%!b-%!3% ")33%)3%")33#)J%%!5%"!L-%!3%")33")3%()3%#)3%"*J3%!3%%"!%K!3%K"!) K"!)K!38L"!%")J3%!5)""!%K!3)K"!-N"!%""!-K"!%M!3%%!5)"!3%K"!)M"!3 "!L%%!5)""!)N!33%!3-M!3%%!b-%"!%")33")J%""#1!!33")i!""!)K)3)KJ!% K"!8LJ#!$)J%%J3-,!#!%J!!%!!%!J#!%J#%!J#%%!!!%J#!!!!%!!#!%!#!%"5% J!L1!)35"!aq!)35!!3#!)33!)!#!!!!!)3!!!35!!3!!)3!!!!5!!!3!)3#!!!# !!3!!)!!!!33!)3#!)!5!!3#!)!!!)33!!35!)!5!!!#!!3!!)33!)35!!!5!)3! !)35!!33&)L!%!L%K"#%%!5+!!3)LJ#!#)B!")33')L!%!L)""!%LJ#!#*)#!3"! ")B!")a"!J!%L%%!$)8!"*8!33)"!!50!J%!#)B!")4!')N!3!L*!%!%PJ%!33)! #)8!&)8!")d#!3!)KJ!8K%!)K3!)MJ%!3"#&!!5&!!L'!!5%3!b333)"!!5*!J!8 L%%!")8!")8!#)4!#+%!33)"!%%#!!L&!!5&!!50!J%!$)N!3!5@!3""!J!)K3!N L3"!$)K"!!5&!!50!J%!")N#!!b1!3"!")B!")a"!J!%L%%!$*N#!3""!J!)L3)! &)4!")S"!!L'!!5%3!L9!%%#!3!%L3)!")4!$)K"!!5&!!L1!3"!%)8!")8!%)4! #*%!33"!#)`J3)!3K)!%Q%#!J#"!J"58)%#!J#!%K)!)K%!%K)!)M)#!)!5%J!L% 3!L%)!5%J!5))%!%K)!%K%!8L)!J&)5!")JJ3!5)J#!)K)!)L)#!")4!")L!)!b- )%#!")`J3)!%K#!8Q)#!)%#!J!b)J#!%L)#!")a!J)!%K%!-K%!%K)!3M#"!J!5% )!5)J)!%N%#!J#!%K)!3M)!J3!L%)!5%J!L%3!5%J!5%3"5-J#"!#*3J3)#!)!5) J)!%L%#!$*L!J#"!J)!8L%#!")3J$)3J#)5!")K!J!b-J)!J#)5!#)5!")JJ3!5) J#!3M%#!J!5%3"#%J!5))%!%M)!J)!5)))!)K#!)K!J)P#!)))!J$)3J")JJJ!b) J#!3K!J%M)!J#!L3)!JJJ!5)##!%M#!))!L-###!#)3J%)b!)!J)K#!)L)!J")3J $)JJJ!5)##!)K!J%M)!J#!53J#!))!b)))!JL#!)")L!)!L)J#!%K#!)M!JJJ!5% #!b-###!")3)#)`J##!-K#!3M)!J#!5%J!L%)!L3###!)!5%)"#)J#!)M)!J#!L) )!J%L)!J%)3)#)3J")JJJ"#3)!JJJ!5%#!5)J#!)M)!J#!L%)!5%)!5%)!5)))!3 N#!)))!%L!JJ#)J))!b)))!)L##!")3)")L!)!b-)!JJ"*8!)3""!!5&!!b&!!L- )3"!")3J&)a"!#!%L%%!")d!33!)S%%!)3""!#%!")8!$)8!")8!#)3J&)a"!#!% K%!%L#%!#)3J")K"!!5*!%!3K3!8K3!)P#%!33!J$)3J")K"!!L%3"5))3!-P3"" !#%!")N!)"#*!%!8P#%!33!J")4!")3J#)8!"*%!33!J#)d!)3!-K3!%L3!J#)8! ")8!%*4"!#%!3!5-)3"!$)4!#)8!")8!&*8!33!K!!L%)!L&!!L%3!5%)!5)33!% M3""!!L%3!5%)!5%3!5))3!8K3!%K3!-M3""!!b*!#!%P%%!)3"!")JK!!6i+9Q9 bD@CjD@jR,#"`E'9KFf8JFQ8YC@jdCA)J*A-"1!S("deTFfeKG'0S)#dJG(*j)'& RB@PZ#J%Q)$"i)(XJ!5#"!!'3#2k3#"q3"!k3"1#3"2'3"!(q!Ii"rJ(qrJ(q!Ii "rJ%Ii"rJ$[%1mH!Ii"ra$[%1!H!"i!(a!I(J!H!"m3(a!4rq(ri1rJlqrKrq(ri 1rJi"(`%I!3i"$Km"(`%1!3i"i2lJr[(qmIlqi2lJr[(qm3-L8#L#!K"3&&!!6qa 2f%r%6l"2R%q)1%`i1$JN1"!i!$IX0pJha!NK!B)#"3!"!!%!!3!"!!%&)3'#!J8 !!3!"!!%!!3!"!L!ZdY28eGEAf0RDfpcGhYrJiH,Mj1AQjqMTkZ[XlHl[m2(bmr6 ep[IiqIVlr2hqr`%JJ4%"!J-%"3B(#!N+#`8'"`J*#JX-$3i2%"%5%a39&KFB'4S E("dH(b!K)L-N*5!K)L-N*5BR+#NU+b`Y,Lm`-6)c0$8f0cJj1MXm26ir3%&#3d3 Z,c!a-M-d06Bh1$P"3N0%48C(5%P+5da06Np389*69&9@9eKC@Q&LBf4PCQGSD@T VE'eZEh"aFR0dGAChH(Pk"b)3)!-K)!)K%!%K!3-K!3%M%#!"!L)J!3%K%!)K#!- M#"!J!5%)!5%J!5))%!%L!3J#*J%)%#!"#!%N)!%)%!-K)!-L-#!#)L!J!L%`!5% "!5%J!5%"!5-`)!%")b!J!3%K-!)L##!#)`J`)!%M##!J!5))-!%M!3JJ!5X"#$! J!3JJ)!%)-!%K#)%$"`!!#"!J#!!J#"!!#3!!#4!J#3!J#5%3!5))#!)Q#!J3)!J )!53J#!J3!5)*#!)Q#3J3)!N)!53J#3J3!5%)J3-()!!)-#!))#!)-!!*)!!*-#! *)#!*)6!")`J))!%V#!J`)!J))#!)#$!")`N))!%V#3J`)!N))#!*#$!%)3)&)5! ")3)")5!#)5!#)J)J!b)J)!%M!L!J"#)%!J)K"!)M)!3#!5)J"!%K)!%M"!)J!5% %!5FJ)!3#)#!%!L%%J3-(!J!%!!!N!J!N!#!%!L!%!#!N!L!N!L-%"!)")J3%!L- N"!)")L3%!5FJ"!3#)!3%!5JJ*!3#)#3%%!-K%J-K%!%K)!%K%J%K)!%L%#!#)K) J!L-3)#!")a)J)!%K%!)L"")#)J33!5-J"")"*#!%%#!")`35)!%U""!J)!35)#! %%!%K")%$"a)!""!!*")!*"!J"")J""!J*")J*#%3!5-%"")")`3%%!%M*!35!6) N""!J"!35)!3%%#!N"")J*!3()3%")35"!`d!!!3"!3!!!3!"!33!!33"!!!#!!! $!!3#!!3$!3!#!3!$!33#!33K!`)K!J-L!J%")J3#!L3%!J%"!5%#!5%"!58#!3% %!J%N!33#!3)L!J)#)J)$!5-%!J)"*!3#!`%")`)#!3%V!J-""!)#!33#!`J$)3J #)`%)")%$$3!)"!%*!!!*!!%*"!!*"!%)!!))!!-)"!))"!-*!!)*!!-*"!)*"#) $#!%K!J%K#!%P!J%)"!)"*3J%!J%*!5%#!5%*!58#!3N%!J%P#33#!3J")`)##!% V!J-)"!)##!3#!`N")`)##3%U!J-*"!)##33#!`8K%!3K!3)L%!%%)3L"!`S3!!J !!3J3!3J!%!!3%!!!%3!3%3!!%!J3%!J!%3JN%"%)"!-L""!#)33")3%")`33!3% K"!)M#!33!5))"!%R!3J%%!%)"!%K%!%M""!3!5%%!5%4!5-%%"%")33"*a!)""! 3#!3"*K%)""!4#)%$$`)!!")!!!)"!")"!!)!#")!#!)"#")"#!)3!")3!!)4!") 4!!)3#")3#!)4##85%3J%!J)L"")#)`3#!3%M"")"!5)%!J%M#!35!5`)"!)"#!3 5!3J%!K!")`35%!%M"!)4!5-%%K%"-!3#%!J%%K!)"!)4#!35%3J%)4!%)3%#)K! ""5)%%!)K"!%K!B%$'333!33J!!!`!!!J!3!`!3!J!!3`!!3J!33`!33!%!!3%!! !%3!3%3!!%!33%!3!%333%33J%!!`%!!J%3!`%3!J%!3`%!3J%33`%5%%!L%3!5% 3!5%3!L)"%!%M%!%3!b-3""!")K!%!5J"%!33!4!%)!%K%!%K-!%K%!%M)!%3!5- `!4!")5!")a!%-!%U%!3J!4!%-!%3"!%L%"!")a!3%!)L%4!")a!4%!)R%"!%%"! 3"!%U%4!%%"%3"#!3%!%M-"!3!5-J%4!")c!4%!%`)"!3"$!3%!3J%4!%-"%3"!3 K#!BL#!J#)3J#)33")3J")33$)`3)#!%L"!J")3)#)JJ#!b%#!5-)#!)")3J")J) %!5-)!J3#*`)%#!J#"!J$)J%)J3-'!!%!!!N)!!N!"!%)"!%!"!N))J3*!5%#!5- "#!)")3%")3)")`N)!J%K#3%R!J3"#!)%!3%S!J3*#!)%#3+"!`F!!!S!!!)!#!S !#!)%!!S%!!)%#!SN"!J#!J)L#J)#)J)#!5-)#J)"*!J#!J3")`S#"!%T!J)%#!S #"!J#J3-(!!%+!!%#!!N+!!N#"!%+"!%#"!N+*!3*!J)")`%+!J%M!3)#!5-*#J) "-3N#!J3"#J)%!3)#"!N+!J3*"L%"J3-'!!J!!!J"!3!!!3!"!3J!!3J"!b%3!L) "%!%K#!%K%!%N#!%3!3)L%!%"*!%3!3J"*4!"#!%3!5%J!b)J!B%$"J!S!!!S!3% J!!%J!3%S!!%S!3%K)!%K%!%M)!%3!5%S!5%3!58S!4!")!%R%!%J!4!"+!%P%!% S!4!#)3+"!`F!!!-!#!)!#!-"!!)"!!-"#!)"#!-#)J)3!L)$%!%M#!)3!53)!a! "!5-#%!%"+J-3!3J#%!%)!a!")L!#J3-(!#!$!#J#!#J$!5!#!5!$!5J#!5J$!5- J!K!")b!$%!%M+!)3!6-S!a!")!)3!5!$%!%S!K!"+!-3"#%%"#%%!L)%"!8L!J3 #)3)")33")`)%"!%K!J)K)!%K"!%K)!)L"#!")`3%)!-M)!)%!5)J!J%R"#!#"!3 J!J-L)!3#)5!")33")b!%"!%K)!-L)J3#)5)")33")b)%"!%K)J)M)#!%!5)J)!% R"#!J"!3J)!)M)#)%!5)J)J%R"#!L"!3J)J)K#!%K"!%K#!)L"!J")`3%#!-M#!) %!5))!J%R"!J#"!3)!J)K+!%K"!%K+!)L"#J")`3%+!-M+!)%!5)S!J%R"#J#"!3 S!J)M##!%!5)))!%R"!JJ"!3))!)M##)%!5)))J%R"!JL"!3))J)M+#!%!5)S)!% R"#JJ"!3S)!)M+#)%!5)S)J%U"#JL"!3S)J))#!)K#!)K!J)Q!J))#!)#"#-)#!) ")3J")J)#!L%#!5B)#!)##!J")J))"#-)!J)")`J#!JJK#!%K!J%K#!8L!J)")3J #)JJ)!5B##!J#!JJ%)`J#!J%K#!3K!J)K#!)L#!J")J))!5%#!L%)!5%#!53)!J) )!5%###8##!J#!J%K#!)K#!%N!J))#!)K#!3M#!)#!5%)!5)##!%K!J)K#!)L#!J ")3)#)3)")`J)!J-L!J)#)`)##!)N!JJ)!J%L#!J")J))!L%#!5-)!J)&)JJ#!5% )!5%#"5%)!L%#!b%#!58)!J))#!3M!J))!5%#!L%)!LF)#!*!%)!3"5)3J!%L3"! #)8!#)4!#)i!33!%KJ!)L%)!$)B!")N!3!5%3!b)33!%KJ!)K%!%N%%!3J!%L3"! &)4!")4!#)8!"*)!33"!")4!#)B!#*"#!%%!))4!")K"!!5+!%!%Q%)!33"#!!5& !!L)33!3K%!3QJ""!%)!3!5%3!5333"#!!5&!!5'!!LF3J""!%)!3!5%3!5)33!) K%!3K3!8LJ"!")4!#)N!3!5%3!L'!!5&!"#33J""!!5@!%%!3J!-KJ!8K3!)K%!- P%%!3J"!")K#!!5*!%!)L3"!")4!")4!%)i!33!%KJ!%K3!%LJ"!$)a"!%!-L%)! ")33#*!%%"!%$)3%")33")J%"!5%%!5)""!-K"!%L!3%")J3"!5%%!5%"!L%%!L) %"!8P!33%!3%#)J%"!b-""!3")3%&)33"*!%%"!%$)3%$*J%""!3"!3%K"!)K"!) M!33%!5)""!%K!3)P"!%""!3$)J3""5%%"#B%!3%%"!%$)3%%)3%")33%)J%"!5% %!5-""!3#)33")J%""#-%"!%#)J3"!5)%"!%K!3%K"!%L!33$*!3%!3%$)3%"*!3 "!33#)J%%!b3%"!%"!5%%!L%%!5%"!5%%!5)"!3%L"!%")33")3%&)J3%!5%"!L- "!33#)3%")`3"!3)K!3%L"!3$*%!3#"!")4!%*3J33"!)"#)33!)K%!%L%!J")8! "*!J33"!")4!#)JJ3"5-3#"!#)3J")d!3#!%K3!)K%!-L%%!")3J")N!3!b%3"#% )!5*!%!%K%!%N%!J33!3K%!-L%!J&)8!"*!J33"!")4!")4!")K"!!58)%%!3#!% K3!)L%%!")3J#)K!)!5&!!L%3!L%)!5*!%!%K%!%K%!3M#""!!L%3!5)3#!BK%!) K3!%K#!3L%%!"*!J33"!$)4!")4!$*""!%!J")d!3#!%K3!)N%%!3#!-L#"!")4! #)d!3#!%K3!%K#!%L3"!")K"!!L%3!5)3#!)M%!J3!b%3!L3)%%!3!5%)"#%""#% %!5B)!33J#!%")L!)!5%%!L8""#!)!3-K!38L)!J#)5!")J%%!5%)!53%)!J"!53 J#!%%"L)""!%K#!3K!3%K)!)M"#!)!5%%!L-""#!%)3J#)5!$)L!)!5B%)!J""#! ")3%")b!)!33K"!-P"#!)!33")`J""!%K#!%L"#!")3%")b!)!3-K!38L)!J#)L! )!5%%!5%)"#)""!%N#!%%)!8N!33J#!8K"!)K!3%L)!J")J3J!L%%"5B)!33J#!% "*#!)!33$)J3J!5%"!b)""!%L#!%")L!)!5%%!b)%)!-K)!%P!33J#!%#)3J#)L# !!L&!!5%J!5&!"#1!)#!#)5!")8!#)5!")B!")L"!!5%J"#BJ3)!J)%!")L!J!5' !!b'!!5%J!5'!!L0!J#!$)b!J3!%K)!)KJ!%N)%#!)!%K3!BK)!3N3)!J)!%LJ#! "*d#!)#"!J#!#)B!&)L"!!b&!!5)J)!)N)#"!J!%K)!-M)%#!!b'!!5%J!LBJ)%# !)#!#)5!")8!%)B!")5!")B!&)5!")S!J!5&!!5%J!b%J!59!J#!J3!%L)#!%*8# !)#"!!5)J)!)K)!)KJ!%M)%#!!L0!J#!$)b!J3!BK)!%KJ!)L3)!"*5"!J#!J!5+ !)!3L)%!$)d#!)!%K3!)K3!-K!J%K!B%$(3)!!3!%!8)%!%!%!%)!N!3"!!!"!J3 !!J3"3!!!!!3"3J!"3!!!!J3"!J3!3!!!3!3"3J3!!!!"!J!"!!3!3J!"3!3!3J3 "3J!!!!3!3J3"3!3!!J!""#0#"!'"!`T!!!&!"!!#"!"!!!!#!!%!!!&!"!%#"!" #"!"#!!!%)3)")3'"!a)!"!!!"!%#!*!%!3)%!3)!!%)!!!)%!%!!!8)%!3!!!8) !!!!%!%!%!8)%!3!%!8)!!8!!!#4!"##!J3-HJ###!!!#J!!!!#!#!!#!J##!!## #J!!!J#!!!!##!!!#J!##J#!#J#!!J##!!!!#!!##J!#!J#!#!###J#!!J!#3")) !)!!!!)!!)!+!))#!!)!!!!)!)))%)B!")B!$)3)#)5!#)i!JJJ%KJ!%K!J%LJ#! ))B)#)L#!!51!)!)")i!J!J-KJ!%MJ###"5'!!5'!J3-*J#!#!###J!#!!##!!#! !J!##!!!#J#!#J##!"#1!))+"!`B!!)+!!!!!)!!!))#!!!)!!))KJ2rf!!!"!!! !!9`!!!"F!!!!-R3JG'KP)'CTEQ&X)(0PC@3JGA0TEQFJG'KP$5!J)#SJBh9bFQ9 ZG#"bB@jNEfdJER9YBQ9b)(0dFQ9KE6S0)#!J+Lm0)#"NCA0IEQ9hAh*KEQ4[E9p VCANSEQ9hAfYPH5Nl$5!JC'9cAh0PG&pbB@jNEfeICf9ZCA*KG'pbAh0PC@3SEQ9 hAfYPH5Nl$Ad0$3d[+JdJ+L"8D'Pc)'e[C(9XC5"TEA"XC@ePER4c)'%JFQ&ZC'p Y)'jeE@*PFL"RC@jPFQ&dEh)JCQ&MG@adH5"cG@0S)(4SBA3JG'KP)'jPH(30)#S JER9YBQ9b)'PZ)!!!!&J!N!X"!*!6!A"hF'-!N"-"!*!41!Y0594IT@4PFfaTBJ# 3"!%!!!!"A!!!!&`!!!!b"QG8M&fN!!!!(!!b!!"MCR*R!!!!#J!!rrm!N!3'Ce2 J@38: \ 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
index ded6d18d8b..0000000000
--- a/src/mac/libraries/DES/bin/deslib.PPC.debug
+++ /dev/null
@@ -1 +0,0 @@
-(This file must be converted with BinHex 4.0) :%'4PFfaTBLj38%-ZC'9LG@F!FfKXBMq3"!#3")pa!!!"NVNR5Qpj)A"PCQC`Gh" M!!!!!E*ETmN!N!d$!!)!N!6rN!3!N!CIH!!!AhJ!!&pi!!!&X!!%"!$rN!3!N!B YdJ!!,63!!#T"!!"P-!)""!$rN!3!N!i&,!!!!)!%"!3!N!ArN!3!N!F"!!!!p!! !!!%!!!$X!!!!!`!!!")!!!!"!!!!e!!!!23!!!1!!!!!"!!!!"S!N!m2!*!,%`# 3#`)!!!!2!*!(,!#3#`%!!!!4!*!%!J!!13)!!%!#!!"(!J!!6J)!!&3#!!"E!J! !B!%!!'F#!!"[!J!!GJ)!!(X#!!##!J!!L!)!!*%#!!#B!J!!S!)!!,B#!!$+!!% !N!83!*!%5JCJ#%S)3J*J"d)"3!&#!8!"3KL!%dBD3#UJ!"[`3""0594IT8e*9%0 -D@)ZC'9LG@F!68P8Ak905945G@jdD@eP6'PL,Q4PBR9R!%PZG'9bCQ&MC8aTBJ" cG(*MEA!!Fh4bBfKb!'CQE(9cD!"cFQ&ZC!"YC@eMF(N!FQ&ZC!"YC@eMEA!!Aep QD@aPF`"cG(*XC@i!G'PYC3"`FQPZG'B!CQGPG(-!BfaPBA*PFR)!E@9YFf9d!'C `FQPZG'B!AepeER*PCfPcG'9bAfCbB@GYC@jd!&pIFQ9RDA0dCA*ICR*KCfePER3 !9'PMDd0[G@jd!'4PFepbC@&NAh"KFh0hEh*NC'9cAh0PG&pcCA&eC@jMC9pZG@e LCA*NCA0IC'9LG@GNCA0IFf9dAfYPH@4PFepTFephC@&VAfYPH@4PFepcG(*TEQG IG'pIDf9jC'9cAfjPGepbB@jNEfeIDf9jC'9cAf0LE'pMDep`FQPZG&pQD@aPC'9 cAfCMFRP`G'4PFepQDAKeF&pVCAPIF'&bDA4jC'9cAf0SC@0VAfYPH9p`BA*TG(P NCA0IFQ&ZC'pYAfYPH@4PFepMFRP`G'4PFepbC@&NAh"hAh0dFQPZCf4PFepTEQP dAh*KEQ4[E9pZG@eLCA*ICf9ZCA*KG'pbC'9cAc0PBf*IC@jMFRP`G'4PFemcBf* MAf9ZBh*jF(4NCA0IFf9dAh*KEQ4[E9pRC@jPFQ&dEh*IFf9PC'4PFepVCAPIFf0 SC@4NCA0IFA9KC&pMDh0eE@eKDf9IDf9jAh0MD'9NC'9cAf9MBPpPEQ0bHA"dC'9 cAf0LBepPEQ0bHA"dC'9cAfGPEQ9bBA4PAh*KEQ4[E9pLE'pMDf4PFep`Bf*MAf9 ZBh*jF(4NCA0IBf*MAf0VFh9Y!*!&$!!!!!`!!`!%!!B!"!!(!!`!#!!%!!X!"!! -!!!!$3!)!!d!%!!2!!J!%`!!!"8!#!!9!!!!&`!-!"F!%C08!"IZC`!*4Fd!#a* '!!pG4J!4DjX!%V5D!"8rb!!+Le!!&(88!"5G&!!1PpX!#89`!")N1J!J`X8!%%@ J!""5S!!GG-B!$9-+!!k&6`!1L`X!$fI"!!pm`3!C%1%!%$UP!!eI$`)!!03!!!& m!!%#!!$P!!!"4!!"!3!!r!!!,63!!3)!!38!!!'N!!%#!!%3!!!"P!!"!J!"(`! !!B3!!3)!!6!!!!&F!!%#!!&#!!!"M!!"!J!"9`!!!D`!!3)!!@%!!!%F!!%#!!& e!!!"&!!"!J!"L3!!!@`!!3)!!CF!!!'d!!%#!!'J!!!"G!!"!J!"XJ!!!93!!3) !!G)!!!'m!!%#!!(L!!!"R!!"!J!"mJ!!!8`!!3)!!Jm!!!%d!!%#!!)F!!!"C!! "!J!#+J!!!5`!!3)!!MJ!!!%-!!%#!!*(!!!!r!!"!J!#9J!!!6`!!3)!!Qm!!!% N!!%#!!*r!!!""!!"!*!%I!J#TT!!!3!)P#(r`$JK!%#!!3!)I!J$TNk!!#"m#!+ QNq(rr*!!!3!)P#(r`*!!B3"B1q!!!)"K!&K)!&`eB!!!!(ar'hKri`Fd,!-!!%' #!!arirYi5!!!#(rMqhL!!3")1#%!3(`)!kD$iIrm6S!!)!#3"L""J!%!N!98!"3 ZAepTEQPdD@&XDATPAf4PFfaTBJ!!I!J#TT!!!3!)P#(r`%J!A#&J!!!!J!%!5$J K!%"m#!1Q6S!!)!#3"L""J!#3"L3!%bjIAh4PFQeTEQ&dC9pNCA0XD@)!!!#q)Ir %1Z)2-$[#%c!l!JX`I0XcH#`)!!""JJA8I2BlH)Nf!!!keJ!"95N'2P8m`!k*9J! !1YB!!99+"Mj95S!HIja6H)Pf!!!keJ!"9@X'2P9V3#jrR&YiLCB!!$V@!!&9M!B qIjaMH)Nf!!!keJ!"95N'2P8p`!k*9J!!1YB!!99+"Mj95S!HIle6H)Pf!!!keJ! "9@X'2P9V3#jr[9YiLCB!!$V@!!&9M!BqIleMH(af'hKmP50i5!!&+#`&!!K"J!$ %L6B!!$V@!!&9+3Bq95N'2P8T`!jrR%TiL9B!!$V@!!&95JBq98S'2P9+J"jrR&* iLAB!!$V@!!&9D`Bq9@X'2P9V3#jrR&TiLCB!!$V@!!&9M!Bq9B`'2RqFBRL*0J! !1YB!!98T"Mj9+3Bq95R!$Rqp5RL*9J!!1YB!!99+"Mj95JBq98U!(Rqp8RL*GJ! !1YB!!99V"Mj9D`Bq9@Y!,Rqp@RL*PJ!!1YB!!9@-"Mj9M!BqIleLH$LPrrK)!!# `IYBU&#J&!!G"J3#J15)"k&5U%$Tp+9!ZI5N$TNk!"#!ke[rrLAB!!&9V"Mj9Dd! ZIleDH$V@rrq*PJ!!9B`'2P@-J"jr[@*i1YErriNf!!"9+3Bq95R!$Rqp5RJke[r rL9B!!&9+"MjrR&*i1YErriPf!!"9D`Bq9@Y!,RqF@RJke[rrLCB!!&@-"Mj9M)! HIjaLH$V@rrq*0J!!95N'2P8T`!jrR%Ti1+!!!$e!UUXj5UUUIiT31$eJUUXjDkU UIkYB1&9Vq(jpAeYi2B"996Q-999rM'!i9B`)2$dJ998j+999IkP)1(fG5hKAUJB q98S31ReB8#j95KJi9k['2P9V%$TpH&JZ9@X31PHX4Mj9M"!kICKJ,PHTKMj9+4! kI6K),P8T#$apM%YiI@YMH(eF@hKAkJBq98S31ReB8#j95KJi9q['2P9V%$TpH&J Z9@X31PIX4Mj9M"!kICKJ,PITKMj9+4!kI6K),P8T#$apM%YiI@YMH(eG@hJl3!! !5!!"S)&E!!!lH`!%9kZUrPHXU"4pDf0iI9pDH&IT"Vj9+4!k15N$!(dq5#jAkXD q98S31MP+!J"pAP!Z9qZ'[P9V%$SjD`%!IAjB,PIX4Vj9M"!kICjJ,ReVBhKp5PY iI5P6H(qF5RL"1`!!1hX!"&HU6IjAUdJXI8TEH(dr8RKAl!Dq9B`31MQ-"`"pRQ! Z9qR'[P8T%$Sj+3B!I6j),PIU4Vj95K!k18S%!(eH8#jAkiDq9@X31MPV"3"pIPJ ZI8TEH(dT8hKpM%YiIjaLH)'E!!!lH`!%9iQUrPH+U"4p+90iICp+H&IV"Vj9Da! k1@X$!(eq@#jAl-Dq9B`31MQ-!J"pRQ!Z9qQ'[P8T%$Sj+3%!I6j),PIU4Vj95K! kI9j3,RdT8hKpM%YiI@YMH(qp@RL"H`!!1hX!"&H-6IjAL8JXIBa,H(erBRKAkJD q98S31MP+"`"pAP!Z9q['[P9V%$SjD`B!IAjB,PIX4Vj9M"!k1B`%!(fHB#jAkBD q95N31MNT"3"p2NJZIBa,H(eVBhKp5PYiIle5H$YD!!%X'J!)3B$qB$e!m2%j5[$ `IkT31$eJm2%jDr$`IiYB1&9Vi6jpAeYi2B!2$cQ-$`prV'!i9B`J0MdJ$`mj+3m 2IiP)1(fG5hKAUJBq98S31ReA8#jAUmBq9@X31Reh@#j9Da!k9ka'2P@-%$TpPf! Z9B``-PHTKMj9+4!kI6G),P8T)$CpM%YiI@YMH(eF@hKAkJBq98S31ReA8#jAkmB q9@X31Reh@#j9Da!k9qa'2P@-%$TpPf!Z9B``-PITKMj9+4!kI6G),P8T)$CpM%Y iI@YMH(eG@hJlHrq!9iT'2TP9!!!kY3!"9iZ'2TPe!!!kY3!"9ic'2TQ9!!!kY3! "9iN'2TNe!!!kY3!"9kT'2TP9!!!kY3!"9kZ'2TPe!!!kY3!"9kc'2TQ9!!!kY3! "9kN'2TNe!!!kY3!",!8!!%'"qYK)!!@B,!8!!%'"!!`iB!!!5!!&M(cf1hL*9J! !1YB!!99+"Mj99-!1LAB!!$V@!!&9D`Bq9@Z!(Rk8@hL*PJ!!1YB!!9@-"Mj9M%! ZIT4MH)Nf!!!keJ!"95N'2Rk85hL*9J!!1YB!!99+"Mj98m!1LAB!!$V@!!&9D`B q9@Z!(Rjc@hL*PJ!!1YB!!9@-"Mj9M%!ZIR0MH)Nf!!!keJ!"95N'2Rjc5hKmGKY iI*8MH)P@!!!keJ!"98S'2P9F`!k*GJ!!1YB!!99V"Mj9Di!HIjaEH)Q@!!!keJ! "9B`'2P@-3#jrR'0iL6B!!$V@!!&9+3BqIja,H)P@!!!keJ!"98S'2P9G`!k*GJ! !1YB!!99V"Mj9Di!HIleEH)Q@!!!keJ!"9B`'2P@-3#jr[@0iL6B!!$V@!!&9+3B qIle,H(q5ihKrXHYi28#UUcP+UUTrLP!i2@#UUcPVUUTrUeJi9@[iIReI@hJpJ&9 91Ba99Aq-B$K9M!Jm25"996NT999rU8JiICe,H&HU"Mj95K!kI9K3,P9+'$KAUmB q9@X31Rei@#j9Da!k9ka'2P@-%$TpQ'!Z9kQ'2P8T%$Tp1%JZ95N)2(f-5hKpDf0 iI9aEH&IU"Mj95K!kI9K3,P9+'$KAkmBq9@X31Rei@#j9Da!k9qa'2P@-%$TpQ'! Z9qQ'2P8T%$Tp1%JZ95N)2(f-5hKpDf0iI9eEH$Yl!)!l)!!!5!!"S$Ylrrb"@`! !9kY0rPHX5#apDf0iI9pDH&IT4Vj9+4!k15N%!(dq5#jAkSDq98S31MP+"3"pAP! Z9qX'[P9V%$SjD`F!IAjB,PIXaVj9M"!k1B`'!(fHB#jpDf0iI8TEH(dT8hKrR%T i1h[rr)%l!!"AUUVq9kZS&(e+@hKp2e*i9qb'[P@-%$SjM!%!ICjJ,PIT"Vj9+4! k15N$!(dq5#jAkXDq98S31MP+!J"pAP!ZI5P6H(f-5hKAkdDq9@X31Req@#jpM&Y iIjaLH$Ylrrb"Q`!!9iP0rPH+5#ap+90iICp+H&IV4Vj9Da!k1@X%!(eq@#jAl)D q9B`31MQ-"3"pRQ!Z9qN'[P8T%$Sj+3F!I6j),PIUaVj95K!k18S'!(eH8#jp+90 iIBa,H(eVBhKr[9Ti1h[rr)&l!!"AM+Vq9iQS&(f-5hKpIf*i9qU'[P9+%$Sj5J% !I9j3,PIV"Vj9Da!k1@X$!(eq@#jAl-Dq9B`31MQ-!J"pRQ!ZI@YMH(e+@hKAk8D q95N31Rdq5#jp5NYiIle5H$Xj!!%X'3!)3B$qB$e!m2%j5[$`IkT31$eJm2%jDr$ `IiYB1&9Vi6jpAeYi2B!2$cQ-$`prV'!i9B`J0MdJ$`mj+3m2IiP)1(fG5hKAUJB q98S31ReA8#jAUmBq9@X31Reh@#j9Da!k9ka'2P@-%$TpPf!Z9B``-PHTKMj9+4! kI6G),P8T)$CpM%YiI@YMH(eF@hKAkJBq98S31ReA8#jAkmBq9@X31Reh@#j9Da! k9qa'2P@-%$TpPf!Z9B``-PITKMj9+4!kI6G),P8T)$CpM%YiI@YMH(eG@hKrR+* iIlfDH#`&!!K!J3"d1+Arq&H+4MkC93!!1V8!!9H,KMkCG3!!1V8!!9H-aMkCP3! !1V8!!9H*"MkC03!!1V8!!9HU4MkC93!!1V8!!9HVKMkCG3!!1V8!!9HXaMkCP3! !1V8!!9HT"MkC03!!1V8!!Aj8NhKq-iYi5rrlR(ke+K3S"3!)3B%!H$P#!F48Ua! kI8TB,Re*!kC1J!3J9k`'2MUerrqCP3!!9kR'2MUerrqC03!!9kU'2MUerrqC93! !9kY'2MUerrqCG3!!9i`'2MUerrqCP3!!9iR'2MUerrqC03!!9iU'2MUerrqC93! !9iY'2MUerrqCG3!!1'!!!,SKrm41J!!J!*!')%!!$`#3"!Z-!"!ZC'9cAf0LBep PEQ0bHA"d!!#q`IrB1`)2-$[#%c!l)JX`I2FlH)NA!!!kp`!"93J'2P8F`!k*0`! !1[F!!98T"Mj9+B!HIja,H)PA!!!kp`!"98S'2P9+3#jrR&0iLAF!!$Vh!!&9D`B qIjaEH)QA!!!kp`!"9B`'2P@G`!k*&`!!1[F!!98)"Mj9#)!HIle$H)Nh!!!kp`! "95N'2P8T3#jr[8YiL9F!!$Vh!!&95JBqIle6H(ah'hKmYLYi5!!%c#`@!!K"J!$ %LAF!!$Vh!!&9D`Bq9@X'2P9V`!jrR&TiLCF!!$Vh!!&9M!Bq9B`'2P@-J"jrR'* iL4F!!$Vh!!&9#!Bq93J'2P8)3#jrR%*iL6F!!$Vh!!&9+3Bq95N'2RqF5RL*9`! !1[F!!99+"Mj95JBq98V!$Rqp8RL*G`!!1[F!!99V"Mj9D`Bq9@Z!(Rqp@RL*P`! !1[F!!9@-"Mj9M!Bq9Ba!,RqpBRL*&`!!1[F!!98)"Mj9#!BqIle#H$V@rrK)!!# `I[Hb&#J@!!G"J3#J15)##&E+%$Tp+9!ZI5N$TNk!"#!kprrrLAF!!&9V"Mj9Dd! ZIleDH$Vhrrq*P`!!9B`'2P@-J"jr[@*i1[IrriNA!!"9#!Bq93M!$Rqp3RJkprr rL6F!!&8T"MjrR%Ti1[IrriPA!!"95JBq98T!,RqF8RJkprrrLAF!!&9V"Mj9Di! HIjaDH$Vhrrq*P`!!9B`'2P@-`!jrR'*i1X!!!(cE-hJp!+UV13LUURq)3$Jp)+U V15QUURqT5$K9+IKqI4p,H$e!998j5P99IiT31&9+#$`pB&991@Y99AqV@$KpA9Y i9k`'2P@-%$TpQ@!Z9B`B1&HSaMj9#"!kI4P!,P8)%$TAU8Bq95N31Rdj5#jAUSB q98S31ReC8#j95JJmI5P6H(d)5hKpR%0i9qX'2P9V%$TpH9JZ9@XB1&IXaMj9M"! kICPJ,P@-%$TAk%Bq93J31RdC3#jAkBBq95N31Rdj5#j9+3JmI3K,H(f-3hKpI@0 i1d!!!%J!!D#"@`!!1hX!"&HVU[jAV+J8I@YMH(eI@RKAk!Dq93J31MN)!`"p(N! Z9qR'[P8T%$Sj+3)!I6j),PIUKVj95K!k18S"!(eH8#jAkdDq9@X31Req@#jp5PY iI5P6H(d)5hKrR%*iJCX!!$Yl!!4AU%hq9kP),(d)5hKpRd*i9qS'[P9+%$Sj5JF !I9j3,PIVaVj9Da!k1@X'!(eq@#jAl%Dq9B`31MQ-"!"pRQ!Z9qL'[P8)%$Sj#!8 !I4j!,Rf-3hKpDf0iI8TEH(qF8RL"1`!!1hX!"&H+U[jALkJ8I8TEH(dr8RKAl!D q9B`31MQ-!`"pRQ!Z9qM'[P8)%$Sj#!)!I4j!,PITKVj9+4!k15N"!(dq5#jAkND q98S31ReH8#jp+90iI3K,H(f-3hKr[@*iJAX!!$Yl!!4AM%hq9iK),(f-3hKpIf* i9qN'[P8T%$Sj+3F!I6j),PIUaVj95K!k18S'!(eH8#jAkdDq9@X31MPV"!"pIPJ Z9qb'[P@-%$SjM!8!ICjJ,ReVBhKp5PYiI5P6H(qp5RJl@J!","S!#%'!rQ!p!2$ a13M`m(qS3$Jp)2$a15R`m(q*5$K9+H%qI4p,H$e!$`mj5Jm2IkT31&9+)$BpB!m 21@X2$hq,@$KpA9Yi9k`'2P@-%$TpQ'!Z9kM'2P8)%$Tp'%!Z93J31PHT4Mj9+4! kI6K),P8T-$*AUSBq98S31ReB8#j95L!fI5P6H(d)5hKpR%0i9qX'2P9V%$TpH&J Z9qc'2P@-%$TpQ'!Z9B`31PIS4Mj9#"!kI4K!,P8)-$*AkBBq95N31Rdi5#j9+5! fI3K,H(f-3hKpI@0i1h[rJ#`@!!""JIXdI*FMH&H+4MkC9`!!1[F!!9H,KMkCG`! !1[F!!9H-aMkCP`!!1[F!!9H)"MkC&`!!1[F!!9HT4MkC0`!!1[F!!9HUKMkC9`! !1[F!!9HVaMkCG`!!1[F!!9HX"MkCP`!!1[F!!AqMkhLk`IrB6S!!)!#3"L"!!!S !N!3&m!!1,Q4PFepMBQ0IBfYcG@fqSIr81U)2-$[#%c!k`JX`I(JEH)Mi!!!l'!! "91F'2P6m`!k*'!!!1aJ!!98)"Mj9#)!HIja$H)Ni!!!l'!!"95N'2P8T3#jrR%Y iL9J!!$XB!!&95JBqIja6H)Pi!!!l'!!"9@X'2P9p`!k*Q!!!1aJ!!9@-"Mj9M)! HIleMH)Mi!!!l'!!"91F'2P6R3#jr[6YiL4J!!$XB!!&9#!BqIle$H$dJUUXj+DU UIiP)1$e!UUXj5UUUIkT31&9+q(jp2e0i2@"996PV999rLeJi9@X)2$f!998jM&9 9IkaJ1(epBhKAT`Bq91F31Rcf1#j8jaJi9kM'2P8)%$Tp&N!Z93J31PHT4Mj9+4! kI6C),PHUKMj95K!kI9C3,P9+#$ap+90iI3K,H(cm3hKAk`Bq9@X31Ref@#j9DaJ i9qc'2P@-%$TpPQ!Z9B`31PIR4Mj8ja!kI2Bi,PISKMj9#"!kI4C!,P8)#$amjd0 iIB`lH(epBhJX"J!!3B)"Z(bk+hJlB!!!5!!"S)%k!!!l@J!%9kUUrPHVU"4p5PY iI6p5H&IX"Vj9M"!k1B`$!(fHB#jAjmDq91F31MMR!J"mrMJZ9qL'[P8)%$Sj#!% !I4j!,PIT4Vj9+4!kI6j),Rd)5hKmjd0iIB`lH(qFBRL"@J!!1eS!"&HV6IjAV%J XI@YMH(eI@RKAj`Dq91F31MMR"`"mrMJZ9qM'[P8)%$Sj#!B!I4j!,PIT4Vj9+4! k15N%!(dq5#jAkSDq98S31MP+"3"pAP!ZI5P6H(d)5hKmjd0iIj`kH)&k!!!l@J! %9ibUrPH(U"4pM$YiIApLH&IS"Vj9#"!k13J$!(dH3#jAkFDq95N31MNT!J"p2NJ Z9qU'[P9+%$Sj5J%!I9j3,PIV4Vj9Da!kIAjB,Re+@hKp+90iI3K,H(qp3RL"QJ! !1eS!"&H(6IjAL%JXI1G$H(fI1RKAk3Dq95N31MNT"`"p2NJZ9qV'[P9+%$Sj5JB !I9j3,PIV4Vj9Da!k1@X%!(eq@#jAl)Dq9B`31MQ-"3"pRQ!ZI@YMH(e+@hKp+90 iIle+H$Yl!!%X'`!)3B$qB%J!!E3l*3#!1f!!!%J!!D!l1IrmJ2N!!&HS6IjAU8J XI3K,H(cr3RKAkNDq98S31MP+"!"pAP!Z9qZ'[P9V%$SjD`8!IAjB,PIX"Vj9M"! k1B`(!(fHB#jAjmDq91F31MMR"J"mrMJZIB`lH(eVBhKp5PYiIja5H$Xjrrb"'3! !9kQUrPHUU"4p+90iI4p+H&IVKVj9Da!k1@X"!(eq@#jAl!Dq9B`31MQ-!`"pRQ! Z9qI'[P6R%$Sij`)!I2ii,Rf-1hKpDf0i9qK'[P8)%$Tp(N!ZI@Y$H(qF@RJl1Ir mJ6N!!&H+6IjALdJXI8TEH(dr8RKAl%Dq9B`31MQ-"!"pRQ!Z9qH'[P6R%$Sij`8 !I2ii,PIS"Vj9#"!k13J(!(dH3#jAkFDq95N31MNT"J"p2NJZI3K,H(cR3hKpM$Y iIleLH$Xjrrb"@3!!9iZUrPH-U"4pDf0iI9pDH&IRKVj8ja!k11F"!(cq1#jAk!D q93J31MN)!`"p(N!Z9qR'[P8T%$Sj+3)!I6j),Rd)5hKmjd0i9qT'[P9+%$TpAP! ZI1G6H(qp1RJlH`!","X!#%'!rQ!pB2$a1@[`m(qV@$JpJ2$a1Bc`m(q-B$K9M1% qIApMH$cJ$`mij`m2IkFi1&6R)$Bp!!m213J2$hq)3$Kmr80i9kN'2P8T%$Tp08J Z9kV'2P9+%$Tp99!Z98S31PHV4Mj9Da!kIA9B,P9V-$*AV)Bq9B`31Rf9B#j9M#! fI@YMH(e+@hKp2&0i9qF'2P6R%$Tmp6JZ9qM'2P8)%$Tp&8!Z93J31PIT4Mj9+4! kI69),P8T-$*AkSBq98S31Re98#j95L!fI5P6H(d)5hKmr80iI*FMH&H,4MkCG`! !1[F!!9H-KMkCP`!!1[F!!9H(aMkBp`!!1[F!!9H)"MkC&`!!1[F!!9HT4MkC0`! !1[F!!9HUKMkC9`!!1[F!!9HVaMkCG`!!1[F!!9HX"MkCP`!!1[F!!6KJ!!#kSIr 86S!!)!#3"L"!!!X!N!3')!!3,Q4PFepPBf*IC@jMFRP`G!!!Nq(rr$[J!!")!!# BI)2iVP5%"MamJrQZI+2iVP5P"cjm`rLZ9-ER2RbP-RK8T3HqI12iVP6R"cjp!rL Z93MR2RcR3RK8jrHqI+8kH&5P"rjp)rLZ95N(2Re$q+j95ZFqI5P5H&8T"ljpBrL Z9@X(2Rf$q+j9M1FqI@YLH&9Vpljp+9Ti95RrrRbP5RKST3!"I)2iVRb%+hKmJrQ Z1rm!!5JI!!K"J2pSJq(rr%k!!#!!N!BJ3!!"!*!&X!!9,Q4PFepQDAKeF&pVCAP IF'&bDA4j!*2Krr`li!!!5!!!Y(b$q+j8K!IqI+2iVP5P"Ma8T3FqI-2iVP6'"Ma 8aZFqI+8bH&5P"ljmirLZ91F'2&6R"cjp!rLZ93J'2&8)jcjmjd*i91Ih[RbP1RK 8T3IqI52iVP8T"Ma9+3FqI82iVP9+"Ma95ZFqI5P5H&8T"ljpBrLZ9@X'2&9V"cj pJrLZ9B`'2&@-jcjpDf*i9@[h[RdT@RK9+IrqI+9+H(`%+!"!JJ!-1'!!!%J!!"3 lr`!"+"m!#%'!rd`iB!!"Jq(rr%k!!#!!N!BJ3!!"!*!&d!!9,Q4PFepMD'9MDep VCAPIF'&bDA4j!,i"rm!kiJm`1m)6-$X##c"mfc0i,!J!!%'#"FampMYiL6B!!$V @!!&9+3Bq96c!$SP@!!!keJ!"98S'2P9+J"jrR&0iLAB!!$V@!!&9D`Bq9@Y!,Rq F@hL*PJ!!1YB!!9@-"MjrR'0iL6B!!$V@!!&9+3Bq96h!$SP@!!!keJ!"98S'2P9 +J"jr[90iLAB!!$V@!!&9D`Bq9@Y!,Rqp@hL*PJ!!1YB!!9@-"Mjr[@0iI(BEH(b 9)hK)!!8J,!8!#%#"!+5*0J!!1YB!!98T"Mj90-!1L9B!!$V@!!&95JBq98U!(Rk 88hL*GJ!!1YB!!99V"Mj9Dd!ZIT4EH)Q@!!!keJ!"9B`'2Rk8BhL*0J!!1YB!!98 T"Mj9-m!1L9B!!$V@!!&95JBq98U!(Rjc8hL*GJ!!1YB!!99V"Mj9Dd!ZIR0EH)Q @!!!keJ!"9B`'2RjcBhKrR+*iIlfDH$LPrrK)!!$!IYBU&#J&!!K"J3#`15)#6&5 U%$Tp+9!ZI5N$TNk!"#!ke[rrLAB!!&9V"Mjr[9Ti1YErriQ@!!"9M!Bq9Ba!,Rq pBRJke[rrL6B!!&8T"Mj9+B!HIle+H$V@rrq*9J!!98S'2P9+`!jr[9*i1YErriP f!!"9D`BqIjaDH$V@rrq*PJ!!9B`'2P@-3#jrR'*i1YErriNf!!"9+3Bq95Q!(Rq F5RJke[rrL9B!!&9+"Mj95X!1Ija5H$LJ!!!pB+UV1@ZUURq,@$JpJ+UV1BbUURq XB$K9M2KqIApMH$dJ998j+999IiP)1&8T#$`p3&9918T99AqU8$Kp290i9kX'2P9 V%$TpH&JZ9@XB1&HXaMj9M"!kICKJ,P@-%$TAU8Bq95N31Rdi5#jAUSBq98S31Re B8#j95JJmI5P6H(f-5hKpI'0i9qX'2P9V%$TpH&JZ9@XB1&IXaMj9M"!kICKJ,P@ -%$TAk8Bq95N31Rdi5#jAkSBq98S31ReB8#j95JJmI5P6H(f-5hKpI@0i1d!!!%J !!D#"H`!!1hX!"&HXU[jAUDJ8IBa,H(erBRKAkJDq98S31MP+!`"pAP!Z9q['[P9 V%$SjD`)!IAjB,PIXKVj9M"!k1B`"!(fHB#jAk8Dq95N31Rdq5#jpM%YiI@YMH(e +@hKrR&*iJ9X!!$Yl!!4AUdhq9ka),(eVBhKpAeTi9qN'[P8T%$Sj+3F!I6j),PI UaVj95K!k18S'!(eH8#jAkdDq9@X31MPV"!"pIPJZ9qb'[P@-%$SjM!8!ICjJ,Re VBhKp5PYiI5P6H(qF5RL"1`!!1hX!"&H+U[jALkJ8I8TEH(dr8RKAl!Dq9B`31MQ -!`"pRQ!Z9qR'[P8T%$Sj+3)!I6j),PIUKVj95K!k18S"!(eH8#jAkdDq9@X31Re q@#jp5PYiI5P6H(f-5hKr[@*iJCX!!$Yl!!4AL8hq9iT),(dT8hKpRdTi9qX'[P9 V%$SjD`F!IAjB,PIXaVj9M"!k1B`'!(fHB#jAk8Dq95N31MNT"!"p2NJZ9qU'[P9 +%$Sj5J8!I9j3,RdT8hKpM%YiI@YMH(qp@RJl@J!","S!#%'!rQ!pB2$a1@[`m(q V@$JpJ2$a1Bc`m(q-B$K9M1%qIApMH$dJ$`mj+3m2IkP)1&8T)$Bp3!m218S2$hq +8$Kp290i9kX'2P9V%$TpGeJZ9kc'2P@-%$TpPf!Z9B`31PHT4Mj9+4!kI6G),P8 T-$*AUSBq98S31ReA8#j95L!fI5P6H(f-5hKpI'0i9qX'2P9V%$TpGeJZ9qc'2P@ -%$TpPf!Z9B`31PIT4Mj9+4!kI6G),P8T-$*AkSBq98S31ReA8#j95L!fI5P6H(f -5hKpI@0i1h[rJ&H,4MkCG3!!1V8!!9H-KMkCP3!!1V8!!9H*aMkC03!!1V8!!9H +"MkC93!!1V8!!9HV4MkCG3!!1V8!!9HXKMkCP3!!1V8!!9HTaMkC03!!1V8!!9H U"MkC93!!1V8!!AqFSRKr[CTi,!8!!%'"qZ")!!@F,!8!!%'"!!`iB!!!5!!&N!" mpMYiLAB!!$V@!!&9D`Bq9A,!$SQ@!!!keJ!"9B`'2P@-J"jq8Q0iL6B!!$V@!!& 9+3Bq95P!,Rj55hL*9J!!1YB!!99+"Mjq8P0iLAB!!$V@!!&9D`Bq9A(!$SQ@!!! keJ!"9B`'2P@-J"jq-@0iL6B!!$V@!!&9+3Bq95P!,Ria5hL*9J!!1YB!!99+"Mj q-90iI(BEH(b9)hL*GJ!!1YB!!99V"Mj9I-!1LCB!!$V@!!&9M!Bq9Bb!(RqFBhL *0J!!1YB!!98T"Mj9+8!ZIja,H)P@!!!keJ!"98S'2RqF8hL*GJ!!1YB!!99V"Mj 9IF!1LCB!!$V@!!&9M!Bq9Bb!(RqpBhL*0J!!1YB!!98T"Mj9+8!ZIle,H)P@!!! keJ!"98S'2Rqp8hKrN!$MH*1Krl!pB+UV1@ZUURq,@$JpJ+UV1BbUURqXB$K9M2K qIApMH$dJ998j+999IiP)1&8T#$`p3&9918T99AqU8$Kp290i9kX'2P9V%$TpH&J Z9@XB1&HXaMj9M"!kICKJ,P@-%$TAU8Bq95N31Rdi5#jAUSBq98S31ReB8#j95JJ mI5P6H(f-5hKpI'0i9qX'2P9V%$TpH&JZ9@XB1&IXaMj9M"!kICKJ,P@-%$TAk8B q95N31Rdi5#jAkSBq98S31ReB8#j95JJmI5P6H(f-5hKpI@0i1hX!J$XJ!!")!!' J1h[rr)&l!!"AV%hq9kP),(f-5hKpIf*i9qT'[P9+%$Sj5J3!I9j3,PIVKVj9Da! k1@X&!(eq@#jAl!Dq9B`31MQ-"`"pRQ!Z9qR'[P8T%$Sj+3B!I6j),Rf-5hKpDf0 iI8TEH(qF8RJlHrrmJ9X!!&HVU[jAV+J8I@YMH(eI@RKAkBDq95N31MNT!3"p2NJ Z9qS'[P9+%$Sj5J-!I9j3,PIVaVj9Da!k1@X#!(eq@#jp5PYiI5P6H&IX4Vj9M"! kICjJ,RdTBhKrR%Ti1h[rr)%l!!"ALNhq9iY),(e+@hKp2e*i9qa'[P@-%$SjM!3 !ICjJ,PITKVj9+4!k15N&!(dq5#jAkJDq98S31MP+"`"pAP!Z9q['[P9V%$SjD`B !IAjB,Re+@hKp+90iIBa,H(qpBRJlHrrmJCX!!&H*U[jALUJ8I5P6H(fI5RKAkiD q9@X31MPV!3"pIPJZ9q`'[P@-%$SjM!-!ICjJ,PITaVj9+4!k15N#!(dq5#jpM%Y iI@YMH&IU4Vj95K!kI9j3,ReV8hKr[9Ti1cN!!5`C!!K"J2jJ2@$`m6PVm2"rUeJ i2B$`m6Q-m2"rM'!i9BcK2RerBhJp)!m215N2$hqT5$K9+5!f28!2$cP+$`prLP! iI6e6H&HV"Mj9Da!kIAGB,PHXaMj9M"!kICGJ,P@-%$TAU8Bq95N31Rdh5#j9+6! b9kU'2P9+%$Tp9e!Z98SJ0RdT8hKpM%YiIAaMH&IV"Mj9Da!kIAGB,PIXaMj9M"! kICGJ,P@-%$TAk8Bq95N31Rdh5#j9+6!b9qU'2P9+%$Tp9e!Z98SJ0RdT8hKpM%Y iIAeMH(qFNRKr[BTi,!8!#%#"!(JiTIri9iY'2TPe!!!kY3!"9ib'2TQ9!!!kY3! "9iR'2TNe!!!kY3!"9iS'2TP9!!!kY3!"9kY'2TPe!!!kY3!"9kb'2TQ9!!!kY3! "9kR'2TNe!!!kY3!"9kS'2TP9!!!kY3!"IK,LH)&Krl"pFHTi5rrlQ(ke+K3S"3! )3B%!H$Q#!LK8U4!kIBa),Rf*!kC1J!3J9kS'2MUerrqC93!!9k['2MUerrqCG3! !9kb'2MUerrqCP3!!9kP'2MUerrqC03!!9iS'2MUerrqC93!!9i['2MUerrqCG3! !9ib'2MUerrqCP3!!9iP'2MUerrqC03!!1'!!!,S"rm"1J!!J!*!')%!!%!#3"!Z )!"%ZC'9cAh"MBQ0IC@jMFRP`G!#q)Ir%1U)(-$V#!c!k)J-31N)#d$TL!T!!1S) #F(ah'hL)Y`!!1[F!!95P"Mj8[F!1L0F!!$Vh!!&8aJBq9-D!(Rqp-hL)p`!!1[F !!96R"Mj8jd!ZIldlH)NA!!!kp`!"93J'2Rqp3hKAUGpq95N31Rdd5#j9+4Ji9kU IIP9+%$Tp9&!Z98S31PHV(hj9Da!kIA4B,PHXAhj9M"!kIC4J,P@-#$apDf0iI8T EH(dr8hKATImq9+831Rbc+#j8T4Ji9kDr2P6'%$Tmdc!Z9-B31PHR2cj8ja!kI2- i,PHSIcj9#"!kI40!,P8)#$amjd0iI-BlH(bq-hL*0`!!1[F!!98T"Mj92F!1L9F !!$Vh!!&95JBq98U!(Rqp8hL*G`!!1[F!!99V"Mj9Dd!ZIleEH)QA!!!kp`!"9B` '2RqpBhKATHFq9+831Rbb+#j8T4Ji9kDR2P6'%$TmdM!Z9-B31PHR*cj8ja!kI2) i,PHSCcj9#"!kI4*!,P8)#$amjd0iI-BlH(bP-hKrrbYi9kRrIP8T%$Tp-8JZ95N B1&HU[hj95K!kI9&3,P9+%$TAUcpq9@X31Rea@#jAV(pq9B`31Rf4B#j9M!JmI@Y MH(e+@hKp+90iIpj,H(bD)hJl)(lm1`!!%%J!!5aA*3Iq,!8!!%'#!#"AjK%k9qF f[RcI1hKAb"%k9mNf[RdH5hK)!!!F9qS*2&IV,[jpAeYi9m`*2&I&,[jpRLYiIcN 1F&IQ"hjAjqDiI-BlH&6'%$SiaJ-!I0B`,PISjljAkEkkI3K,H&8)%$Sj#!)!I4C !,PIUMcjAkiDfI8TEH&9+%$Sj5J%!I9C3,PIX9Vj9M"!kICCJ,Re+BhKp#&0iI0a $H&I&"ljAa[kkI+8cH&5P%$SiT3-!I,8S,PI(cVj8ja!k11F#!(ce1#jAb*Fq9mQ 1YRd)5hK9#"!k13J"!(d93#jAbPDq98S31Re98#jp#&0iI1G$H(bl1hKAL`)Z9f` '$ReVBhL4HJ!!1eS!"&H&"JjACJ)ZI+8cH*!!ZJ!!1eS!"$XBrrmX'!!!3B(qe$K J!!#k)Ir%6S!!)!#3"L"!!!m!N!3$*!!2,QeKDf9IDf9jAh0MD'9N!!!!I!J#TT2 Krrb3!!%!#*3Krm"mIaYiN!#"!&arirYiJ)%!A%[rr*PJ!!!!Iq2lH%[rlqPJ!!! !,!-!!%##!!`iB2rr5!!!*(rMqhK)!!Z&B!!!!#`$!!""JJ!-1'$rrNJ!!!JiB!! !J!%!5$JK!%"m#!1QJq(rr%k!!#!!N!BJ3B!"!*!&H!!1,Q4PFepVCAPIFf0SC@4 m#!+QNq(rr*!!!3!)P#(r`(ar'hKrirYi5!!#+@!!!!"rirYi5rrZJ@!!!!"rirY i5!!,"@!!!!!X!`!!3),rf$KJ!!#!!3")1#%!3(`)!kD$iIrm6S!!)!#3"L""J!% !N!9B!"-ZC'9cAfjPGepbB@jNEfeIDf9j!!!!I!J#TT!!!3!)P#(rX*!!B3"S5!! bIB""!"53!'%!5%J!-R'!33!8N!"K!%b!B3"S5!!!T@!!!!!iB3")5!!"+@!!!!! iB3!i5rrr26KK!$K)!!#&B!!!!$KK!%")!$*0J%%!&$KK!%4)!$*"J%%!&)"L!#" )!!$aB!!!!$KK!$K,rrm&1'%!1%J!!%eJ!!!!J!%!@$JK!&"m#!1Q6S!!)!#3"L" "J!#3"T`!)5jNCA0ID@jTG&pbB@jNEfeIER9YBQ9bAfGPEQ9bBA4[FJ"m#!+QNq( rr*2"rrL3!!%!#*3Krm#3!'%!@$[#,EL!B3"B1))Y1%[rrI9J!!!!1q!!!%J!!"! iB!!!I(ljVM[r!!%X(`!)3B$rm)!"!%Ji)3"!I!J$TS2Krrb$`Iri6S!!)!#3"L" "J!)!N!9J!"iZC'9cAh0PG&pbB@jNEfeICf9ZCA*KG'pbAh0PC@4m#!+QN!!"!!L 8)Ir!N!"K!&JiBLfiJ)%!@$LJ!!K)!$$jJ%%!&)!"!%Ji)3"!I!J$TNk!!#!!N!B J3B!!N!Bd!"JZC'9cAh0PG&pcCA&eC@jMC9pZG@eLCA)!!(`)!UD6iIrmNm(rq*! !!3!)P#(r`*!!B3"B1m)YZ(r$mhL!J3"B1+)Y1$M!!!&,rqAeB!!!!$[J!!")!!! NI(liVMKM!!&8B`BqI(ljVRbHq+iS"!!!3))!%$[r!!%X(`!)3B$rh)!"!%Ji)3" !I!J$TS2Krrb$`Iri6S!!)!#3"L""J!)!N!9m!"SZC'9cAfGPEQ9bBA4PAh*KEQ4 [E9pLE'pMDh`)!UDqJIr3N!!"!!L8)Iq3!(ae'hKmQ#0iI,BVH(cA-hKmp$YiIS1 MH%J!!@&mI"Yi1(3!"%J!!99mHKYi+"J!!%##!!Jki!!"1b!!!8J!!,"qhV0iIVZ VH%J!!)!X(J!"3)%!)(pMfhK)!!$K9'-%2Rrm'K3lH`!#1plrrNJ!!"L)H`!!1hX !!94M"Mjrr"S81m!!!(pGdhKmRrR@I,hTeRb%+K3m`)!!1-Errhq%-jCrR$(@Ij` J8$cp"2`ijh-YI2mjeMd!J!!j#2rrIdG$PRpD3GCr@MK3,"i!!%##ri!S'!!!3B) !&*1B!!!l'!!%NeJ!!$XB!!3l13!","N!"%'"!!am'EJ!3)(r5(q$ihL!!3"i1#% !F(`)!kDkJIr36S!!)!#3"L""J!`!N!3"*!!2,Q4PFepaG@&NAf0VFh9Y!!!!L)- !!CL"rr#)S`!!Q+(rmD"Krr"1J!!J!*!')%!!N!FB!"BZG(G[Af*jG'9cAhCKH&p dEepZCA4cL)-!!jL"rr#)S`!#Q+(rmBM$!!'B`IrbL1-!!*MKrr1!BIr`6S!!)!# 3"L"!!*!(+!!A,QC[GA*IBRPdCA0IGQ&iAh4[AfjPG(-!!!"m#!+Q[`(ri*!!!3! )P#(rS(aj'hKr2-YiIcV,H$KK!$K)!#j"J%%!&%J!,L'!33!8J)%!1(b%'RL!SJ# SJ-8!!(c(-hJiaJ!"N!$&!!"mjb*iI2JlH(m$`hK)!#iKJ%%!&%J!,M'!33!8N!" K!$ar3p0i1)%!2$LJ!!4)!#fjJ%%!&$YD!!4)!#i0J%%!&*!!B3!mId26H$L"!$` iS!!%5!!YPB""!"3lB!!!5!!!@$[!!!#,r!!!1k!!!%J!!"4ArrKq9qJ(rRrH3RJ l[3!","d!"N#"rq`X(J!!3))!&)Nm!!"K+3!"Q6`!!%J!!"#*A!!!98S'2*PF!!! lR!!"1hX!!5`E!!G!JIqS1'!!!)!"!'Ji)3"JI!J$TVX"rq"1J!!J!*!')%'!#!# 3"!%J!!mZC'9cAh*KEQ4[E9pVCAN!!!"m#!+QNq(rr*!!!3!)P#([`*!!B4"BN!# "%&b3!+%3B$KK!$JiJ"!!J+%3A)$"%'")!!"eB!!!!(ar'hJX(`!!3))!&$KK!$L !J4"B5!!#9@!!!!!iB3!i1)!!!$LJ%!")!#fCJ%%!&(rMqhL!!4")1#%33(`)!kD $iIrm6S!!)!#3"L""J!%!N!9m!")ZC'9cAh*PB@4IF'&cFhG[FQ4m#!+Q[Z(rh*! !!3!)P#([S(ap'hKmQL0iI,XVH(cC-hJkiKY21`)E-)2L!&!lJ!!!,"S3!%#"!5! iB2rr5!!"K(pMfhK)!#b"J%%!&$Kr!%K)!#b0J%%!&(qMkhKr400iIqAlH%J!,*' !33!8+!-!!%##!"4rirYi5!!XPB""!"4)!!$8Ik2VH$L!!!T)!#bCJ%%!&(aq'hJ S(J!!3B)!$$KJ!!#BIJ!!,"N!!%'#!+4r!m0iIf6EH%J!,!f!33!81(m!5%J!,"Q !33!81'%!1$L!%!"rjIYi5!!X(B""!"3S!`!!3))!&(rMqhK)!#`KJ%%!&%J!!'! iB3!i1)!!#NJ!,#@!33!8I(iEH#JH!!""JJ!-1)!!!*LH!!"rSqYi1)%!1%J!,"Q !33!8,!-!!%'#!#"qilYi5!!VMB""!"3iI`")5!!VQB""!"4)!!!)1i!!!5`F!!" "J[lS,"`!!%##!"KrSqYi1)!!!(p&dhK)!#[PJ%%!&$KL!0a)!#Y*J%%!&#`C!!" "JJ!B1'%!1$L!!!!iS"!!5!!V[B""!"3iS!!!I0VU&*LQrrmii!!!,"`!!%##!!J ii!!"I1-lH)!"%'Ji)4"JI!J$TVVKrpa1J!!J!*!')%'!#3#3"!(8!"-ZC'9cAh* PB@4IF(GIFh4bD@jR!!!!I!J#TVl"rpL3!!%!#*3KrZ"mH4YiI*FMH(mfbhJlJ!! "1k%!Z(mMbhK)!#Y*J%%!&(ak'hJiB3#i1)!!!$LJ!%")!#XCJ%%!&$YJ!!&)!!# %L(N!!$Xj!!&mI`Gd1m!!!%J!!%3X(!!!3B)!)&IN"rjrTHYi1ld!!BM&!!"maL* iQ-8!!%J!!"KAj`Iq1lhrriNG!!"p#$TiQ4d!!&Irq(ilhJ!","i!"N#"rlaAD3G q+!N!!%##!"Jj3!!!,"`!!%##!!Jj3!!"I9a6H$Yl!!&m'p"!3)(rI$ZK!,Kqq,Y i1f!!!%J!!%!li!!!1m!!!%J!!##*I3!!1ld!!AeV"h3jRJ!"I@YJ-(rr@hJlhJ! ","i!"N#"rq#Eq!!!1aJ!!6Yl!!%S'`!(3)(r`(lMZhK,rq64B!!!!(lMZhJiJ3! i5rreK@!!!!"q`l0iIZ5lH(p&dhJi`3!iIZHlH%[rf&&J!!!!1'%!1$L!!!!iS!# !5!!TkB""!"4qilYi5rrNK@!!!!!iB!!!J!%"+$JK!5"m#!1QZX(rf%k!!#!!N!B J3B!+!*!%!C`!%LjNCA0IFh4bD@jRAh4[AfYPHA`)!UD6iIrmNm(rq*1Krr53!!% !#*3Krl#3!'%!D(bI)hL$S3"S1m!!!(rMqhJiJKYS5!!TQB""!"4)!!!iIq2lH$L #!0k)h3!!1ld!!96&"Mj)!#PjJ%%!&#`H!!K!J!!8Iq2lH$L#!1&)!#PKJ%%!&#` H!!JlhJ!"3B$ra(rMqhJiJJ$N5!!T4B""!"5!!3"B1#%!8(`)!kD$iIrmJm(rq)1 Krr41J!!J!*!')%'!!`#3"DJ!&LjNCA0IBf*XEf0VAh"bD@jdAfCTE'9m#!+QNq( rr*2"rrL6SIrdN!!"!!L8)Iq`I(dEH$[#'fmli!!!5!!!-(r$mhJlhJ!)Ik6VH$L J!!K)!#GaJ%%!&#`$!!"!JJ!-1'!!!8J!!"3lr`!"+"m!%%'!rp!iB!!!J!%!@$J K!&"m#!1QJq(rr)2"rrL$SIrd6S!!)!#3"L""J!-!N!9m!"!ZC'9cAfPcAhGPB@Y IDf9j!!#p`Iqi1Z)2-$[#%c!l!JX`I0XcH(ck1hKp'80i,!S!!%'#$04p-%YiLA! !!$S3!!&9D`Bq9Ac!$SQ3!!!!1K!!!9@-"Mj9M)!HIjaMH)P`!!!k%!!"9@X'2P9 V3#jrR&YiLC!!!!!k%!!"9B`'2RqFBhL*F!!!1K!!!99V"Mj9IF!1LC!!!!!k%!! "9B`'2P@-J"jr[@0iLA!!!$S3!!&9D`Bq9@Y!,Rqp@hL*N!!!!$S3!!&9M!BqIle MH(a`'hL3!)(rX%J!$#JX"3!)3B!!a)P`!!!k%!!"9@X'2P9V"Mj9Dm!1IjaDH)Q 3!!!!1K!!!9@-"Mj9M!Bq9Bb!(RqFBRL*F!!!1K!!!99V"Mj9D`Bq9@Y!,RqF@RL *N!!!!$S3!!&9M!Bq9B`'2RqFBRL*F!!!1K!!!99V"Mj9D`Bq9@[!$Rqp@RL*N!! !!$S3!!&9M!Bq9B`'2P@-J"jr[@*iLA!!!$S3!!&9D`Bq9@X'2P9V3#jr[9TiLC! !!!!k%!!"9B`'2P@-"Mjr[@*i1+Arq%J!!,"q%#S8+!8!"d'"!+!jBK`89+`31Re VB#jpD31Q6S!%)$S3rrq*F!!!9@X'2P9V3#jr[9Ti1K$rriQ3!!!!9B`'2P@-J"j r[@*i1K$rriP`!!"9D`Bq9@[!$Rqp@RJk%2rrLC!!!!"9M!BqIjaLH$S3rrq*F!! !9@X'2P9V3#jrR&Ti1K$rriQ3!!!!9B`'2P@-J"jrR'*i1K$rriP`!!"9D`Bq9@[ !$RqF@RJiS!!!2B#UUcQ-UUTrM'!i2@#UUcPVUUTrUeJi9@[iIRfI@hJpJ&991Ba 99Aq-B$K9M!Jm2@"996PV999rUeJiICeEH&HX"Mj9M"!kICKJ,P@-'$KAUmBq9@X 31Rei@#j9Da!k9kp'2PA[%$Tpq(JZ9kk'2PA1%$Tpf(!Z9Fi)2(h[FhKpDhYiICa EH&IX"Mj9M"!kICKJ,P@-'$KAlXBq9Fi31RhBF#j9cK!k9qp'2PA[%$Tpq(JZ9qZ '2P9V%$TpH&JZ9@X)2(h[@hKpcRYiICecH$V!!!")!!'JJCX!!$Yl!!4AVUVq9kq S&(h1HhKpRh*i9qX'[P9V%$SjD`-!IAjB,PIXaVj9M"!k1B`#!(fHB#jAlSDq9Fi 31MR1!3"phR!Z9qp'[PA[%$TprRJZIFjlH(f-FhKpDf0iIjaDH)&l!!!lH`!%9ka 0rPHZ5#apM(0iIApLH&I["Vj9la!k1Hm(!(hqH#jAkmDq9@X31MPV"J"pIPJZ9qa '[P@-%$SjM!3!ICjJ,PIZKVj9cK!k1Fi&!(hHF#jpM(0iI@YMH(h[@hKrR(TiJIX !!$Yl!!4ALkVq9ibS&(eVBhKpreTi9qi'[PA1%$SjcJ-!IGj`,PI[aVj9la!k1Hm #!(hqH#jAkiDq9@X31MPV!3"pIPJZ9qa'[P@-%$TpRQ!ZI@YMH(h[@hKpcRYiIle bH)(E!!!lH`!%9ip0rPH,5#apleYiIGpkH&IX"Vj9M"!k1B`(!(fHB#jAlXDq9Fi 31MR1"J"phR!Z9qp'[PA[%$Sjl`3!IIji,PIVKVj9Da!k1@X&!(eq@#jpleYiIFj lH(f-FhKr[@*i1YB!!5`@!!K"J2jJ2B$`m6Q-m2"rV'!i2F$`m6R1m2"rMR!i9Fl K2RfIFhJpi!m21Hm2$hq[H$K9lb!f2@!2$cPV$`prLeJiIIeEH&HX"Mj9M"!kICG J,PHZaMj9cK!kIGG`,PA1%$TAVdBq9Hm31RhhH#j9lc!b9kZ'2P9V%$TpGeJZ9@X J0Rh[@hKpcRYiICacH&IX"Mj9M"!kICGJ,PIZaMj9cK!kIGG`,PA1%$TAldBq9Hm 31RhhH#j9lc!b9qZ'2P9V%$TpGeJZ9@XJ0Rh[@hKpcRYiICecH$Ylri!pJ+UV1Bb UURq-B$Jp`+UV1FkUURqZF$K9c[KqICpcH$hJ998jle99Iipi1&A[#$`pB&991@Y 99AqV@$Kpr9Yi9k`'2P@-%$TpQ'!Z9B`B1&HZaMj9cK!kIGK`,PA1%$TAVdBq9Hm 31RhiH#jAUiBq9@X31Rei@#j9D`JmIHpEH(h1HhKpR(0i9q`'2P@-%$TpQ'!Z9B` B1&IZaMj9cK!kIGK`,PA1%$TAldBq9Hm31RhiH#jAkiBq9@X31Rei@#j9D`JmIHp EH(h1HhKpRA0i1eS!J$UJ!!")!!'J1eVrr)'D!!"AVNhq9kp),(h1HhKpRh*i9qY '[P9V%$SjD`3!IAjB,PIXKVj9M"!k1B`&!(fHB#jAlJDq9Fi31MR1"`"phR!Z9qr '[PA[%$Sjl`B!IIji,Rh1HhKpM(0iI@YMH(qF@RJl@[rmJAS!!&HXU[jAVUJ8IBa cH(erBRKAliDq9Hm31MR[!3"prRJZ9qX'[P9V%$SjD`-!IAjB,PIXaVj9M"!k1B` #!(fHB#jpDf0iIHpEH&IZ4Vj9cK!kIGj`,Rh[FhKrR(Ti1eVrr)(k!!"ALdhq9ia ),(eVBhKpreTi9qj'[PA1%$SjcJ3!IGj`,PI[KVj9la!k1Hm&!(hqH#jAk`Dq9@X 31MPV"`"pIPJZ9qc'[P@-%$SjM!B!ICjJ,ReVBhKpleYiIFjlH(qpFRJl@[rmJGS !!&H2U[jALkJ8IHpEH(hIHRKAl)Dq9B`31MQ-!3"pRQ!Z9qi'[PA1%$SjcJ-!IGj `,PI[aVj9la!k1Hm#!(hqH#jpcRYiIBacH&IV4Vj9Da!kIAjB,Rf-@hKr[@*i1V8 !!5`9!!K"J2jJ2B$`m6Q-m2"rV'!i2F$`m6R1m2"rMR!i9FlK2RfIFhJpi!m21Hm 2$hq[H$K9lb!f2@!2$cPV$`prLeJiIIeEH&HX"Mj9M"!kICGJ,PHZaMj9cK!kIGG `,PA1%$TAVdBq9Hm31RhhH#j9lc!b9kZ'2P9V%$TpGeJZ9@XJ0Rh[@hKpcRYiICa cH&IX"Mj9M"!kICGJ,PIZaMj9cK!kIGG`,PA1%$TAldBq9Hm31RhhH#j9lc!b9qZ '2P9V%$TpGeJZ9@XJ0Rh[@hKpcRYiICecH$f!UUXjM+UUIiaJ1$h!UUXjcUUUIkj `1&A1q(jpRh0i2H"996R[999rMhJi9Hm)2$eJ998jDe99IkYB1(hp@hKAV!Bq9B` 31RfBB#j9M"Ji9kl'2PA1%$Tpf(!Z9Fi31PH[4Mj9la!kIIKi,PHVKMj9Da!kIAK B,P9V#$apleYiIFjlH(fFFhKAl!Bq9B`31RfBB#j9M"Ji9ql'2PA1%$Tpf(!Z9Fi 31PI[4Mj9la!kIIKi,PIVKMj9Da!kIAKB,P9V#$apleYiIFjlH(fGFhJkJ!!!5!! "S)'C!!!l13!%9kkUrPH[U"4pcRYiICpbH&IV"Vj9Da!k1@X$!(eq@#jAl-Dq9B` 31MQ-!J"pRQ!Z9qk'[PA1%$SjcJ%!IGj`,PI[4Vj9la!kIIji,Rh1HhKpM(0iI@Y MH(qF@RL"H3!!1cN!"&HX6IjAVNJXIBacH(erBRKAl`Dq9Hm31MR["`"prRJZ9q[ '[P9V%$SjD`B!IAjB,PIX4Vj9M"!k1B`%!(fHB#jAlSDq9Fi31MR1"3"phR!ZIBa cH(eVBhKpleYiIjakH)(j!!!l13!%9iZUrPH-U"4pDf0iIIpDH&IZ"Vj9cK!k1Fi $!(hHF#jAlmDq9Hm31MR[!J"prRJZ9qZ'[P9V%$SjD`%!IAjB,PIX4Vj9M"!kICj J,ReVBhKpleYiIFjlH(qpFRL"f3!!1cN!"&H26IjALdJXIHpEH(hIHRKAl!Dq9B` 31MQ-"`"pRQ!Z9ql'[PA1%$SjcJB!IGj`,PI[4Vj9la!k1Hm%!(hqH#jAkiDq9@X 31MPV"3"pIPJZIHpEH(h1HhKpM(0iIleLH$U8!!%X&!!)3B$qB$f!m2%jM2$`Ika J1$h!m2%jc[$`Iij`1&A1i6jpRh0i2H!2$cR[$`prVhJi9HmJ0MeJ$`mjD`m2IiY B1(hp@hKAV!Bq9B`31RfAB#jAVXBq9Fi31RhAF#j9cK!k9kp'2PA[%$TpphJZ9Hm `-PHVKMj9Da!kIAGB,P9V)$CpleYiIFjlH(fFFhKAl!Bq9B`31RfAB#jAlXBq9Fi 31RhAF#j9cK!k9qp'2PA[%$TpphJZ9Hm`-PIVKMj9Da!kIAGB,P9V)$CpleYiIFj lH(fGFhJl1Iq!9ia'2S("rl"pch0i1Fi!!C("rl#CM`!!9iZ'2S'"rl"pMQ0i1B` !!C'"rl#CEJ!!9ir'2S&Krl"pE&Yi1@X!!C&Krl#Cl!!!9ii'2S(Krl"pkhYi1Hm !!C(Krl#Cb`!!9ka'2S("rl"pch0i1Fi!!C("rl#CM`!!9kZ'2S'"rl"pMQ0i1B` !!C'"rl#CEJ!!9kr'2S&Krl"pE&Yi1@X!!C&Krl#Cl!!!9ki'2S(Krl"pkhYi1Hm !!C(Krl#Cb`!!,!8!!%'"mpK)!!dJ,!8!!%#"$4Kp-%YiLC!!!!!k%!!"9B`'2P@ -`!k4JIqXLG!!!$S3!!&9cJBq9Fk!(S(Krkaplh0iNH(rV)P`!!!k%!!"9@X'2P9 V3#k"JIqXIBaEH*'"rkb*d!!!1K!!!9A1"Mk"iIqXIHpcH*(Krkb*F!!!1K!!!99 V"Mj9Dm!1N@(rU)Q3!!!!1K!!!9@-"Mj9M)!HJF(rU(h1BhL4`IqSLI!!!$S3!!& 9l`Bq9Hp!,S&KrkKpDhYiN@(rU)Q3!!!!1K!!!9@-"Mk"`IqSIFjMH*("rkKmF"Y iN!#"rl#*m!!!1K!!!9A["Mj9r-!1LA!!!$S3!!&9D`Bq9@Z!(RqF@hL*N!!!!$S 3!!&9M!Bq9Ba!,RqFBhL*d!!!1K!!!9A1"MjrR(0iLI!!!$S3!!&9l`Bq9Ih!$SP `!!!k%!!"9@X'2P9VJ"jr[9YiLC!!!!!k%!!"9B`'2P@-3#jr[@0iLG!!!$S3!!& 9cJBqIlecH*1"rk56SIqJ2H#UUcR[UUTrMhJi2@#UUcPVUUTrUeJi9@[iIRhr@hJ pJ&991Ba99Aq-B$K9M!Jm2F"996R1999rVR!iICecH&H["Mj9la!kIIKi,PA['$K AUmBq9@X31Rei@#j9Da!k9ka'2P@-%$TpQ'!Z9kk'2PA1%$Tpf(!Z9Fi)2(f-FhK pDf0iIIaEH&I["Mj9la!kIIKi,PA['$KAkmBq9@X31Rei@#j9Da!k9qa'2P@-%$T pQ'!Z9qk'2PA1%$Tpf(!Z9Fi)2(f-FhKpDf0iIIeEH$Xj!)!kB!!!5!!"S$Xjrrb "q3!!9kY0rPHX5#apDf0iIIpDH&IZ4Vj9cK!k1Fi%!(hHF#jAliDq9Hm31MR["3" prRJZ9qX'[P9V%$SjD`F!IAjB,PIXaVj9M"!k1B`'!(fHB#jpDf0iIHpEH(h1HhK rR(*i1cRrr)(C!!"AVkVq9kZS&(h[@hKphhTi9qb'[P@-%$SjM!%!ICjJ,PIZ"Vj 9cK!k1Fi$!(hHF#jAlmDq9Hm31MR[!J"prRJZIFjlH(f-FhKAkdDq9@X31Req@#j pM&YiIjaLH$Xjrrb"Q3!!9ij0rPH25#apcRYiICpbH&IV4Vj9Da!k1@X%!(eq@#j Al)Dq9B`31MQ-"3"pRQ!Z9qi'[PA1%$SjcJF!IGj`,PI[aVj9la!k1Hm'!(hqH#j pcRYiIBacH(eVBhKr[9Ti1cRrr)&j!!"AM+Vq9ikS&(f-FhKpIf*i9qq'[PA[%$S jl`%!IIji,PIV"Vj9Da!k1@X$!(eq@#jAl-Dq9B`31MQ-!J"pRQ!ZI@YMH(h[@hK AlNDq9Fi31RhHF#jplh0iIlekH$Tc!!%X%`!)3B$qB$hJm2%jlr$`Ikpi1$eJm2% jDr$`IiYB1&9Vi6jpreYi2B!2$cQ-$`prV'!i9B`J0Mh!$`mjcJm2Iij`1(fGFhK AV`Bq9Hm31RhhH#jAUmBq9@X31Reh@#j9Da!k9ka'2P@-%$TpPf!Z9B``-PHZKMj 9cK!kIGG`,PA1)$CpM(0iI@YMH(hm@hKAl`Bq9Hm31RhhH#jAkmBq9@X31Reh@#j 9Da!k9qa'2P@-%$TpPf!Z9B``-PIZKMj9cK!kIGG`,PA1)$CpM(0iI@YMH(hp@hJ pi+UV1HqUURq2H$JpB+UV1@ZUURqV@$K9DrKqIIpEH$f!998jM&99IiaJ1&@-#$` p`&991Fj99AqZF$KpRA0i9km'2PA[%$Tpq(JZ9HmB1&HVaMj9Da!kIAKB,P9V%$T AV%Bq9B`31RfBB#jAVSBq9Fi31RhBF#j9cJJmIBacH(eVBhKpr&Yi9qm'2PA[%$T pq(JZ9HmB1&IVaMj9Da!kIAKB,P9V%$TAl%Bq9B`31RfBB#jAlSBq9Fi31RhBF#j 9cJJmIBacH(eVBhKpr9Yi1N!!!%J!!D#"qJ!!1eS!"&HVU[jAV+J8I@YMH(hr@RK AlJDq9Fi31MR1!`"phR!Z9qr'[PA[%$Sjl`)!IIji,PIVKVj9Da!k1@X"!(eq@#j Al%Dq9B`31RfHB#jpDf0iIHpEH(h1HhKrR(*iJGS!!$YD!!4AVdhq9kY),(h[@hK phhTi9q`'[P@-%$SjM!F!ICjJ,PIZaVj9cK!k1Fi'!(hHF#jAldDq9Hm31MR["!" prRJZ9qZ'[P9V%$SjD`8!IAjB,Rh[@hKpcRYiIBacH(qFBRL"QJ!!1eS!"&H1U[j AMkJ8IFjlH(fIFRKAk`Dq9@X31MPV!`"pIPJZ9qc'[P@-%$SjM!)!ICjJ,PIZKVj 9cK!k1Fi"!(hHF#jAldDq9Hm31RhqH#jpcRYiIBacH(eVBhKr[9TiJAS!!$YD!!4 AM%hq9ij),(f-FhKpIf*i9qm'[PA[%$Sjl`F!IIji,PIVaVj9Da!k1@X'!(eq@#j Al%Dq9B`31MQ-"!"pRQ!Z9qk'[PA1%$SjcJ8!IGj`,Rf-FhKpDf0iIHpEH(qpHRJ k8J!",")!#%'!rQ!pi2$a1Hr`m(q[H$JpB2$a1@[`m(q,@$K9Dq%qIIpEH$f!$`m jM!m2IkaJ1&@-)$Bp`!m21Fi2$hq1F$KpRA0i9km'2PA[%$TpphJZ9k['2P9V%$T pGeJZ9@X31PHX4Mj9M"!kICGJ,P@--$*AVSBq9Fi31RhAF#j9cL!fIBacH(eVBhK pr&Yi9qm'2PA[%$TpphJZ9q['2P9V%$TpGeJZ9@X31PIX4Mj9M"!kICGJ,P@--$* AlSBq9Fi31RhAF#j9cL!fIBacH(eVBhKpr9Yi1eVrJ$hJUUXjlkUUIipi1$eJUUX jDkUUIkYB1&9Vq(jpreYi2B"996Q-999rM'!i9B`)2$h!998jcP99Ikj`1(fGFhK AV`Bq9Hm31RhiH#j9laJi9k['2P9V%$TpH&JZ9@X31PHX4Mj9M"!kICKJ,PHZKMj 9cK!kIGK`,PA1#$apM(0iI@YMH(hm@hKAl`Bq9Hm31RhiH#j9laJi9q['2P9V%$T pH&JZ9@X31PIX4Mj9M"!kICKJ,PIZKMj9cK!kIGK`,PA1#$apM(0iI@YMH(hp@hJ lH`#!1L!!!%J!!D!lHrrmJIX!!&HV6IjAV%JXI@YMH(hr@RKAlNDq9Fi31MR1"!" phR!Z9qq'[PA[%$Sjl`8!IIji,PIV"Vj9Da!k1@X(!(eq@#jAl-Dq9B`31MQ-"J" pRQ!ZI@YMH(h[@hKpcRYiIjabH$Ylrrb"f`!!9kqUrPHVU"4pleYiIGpkH&IXKVj 9M"!k1B`"!(fHB#jAlJDq9Fi31MR1!`"phR!Z9qr'[PA[%$Sjl`)!IIji,Rh1HhK pM(0i9qY'[P9V%$TpIPJZIBaEH(qFBRJlHrrmJCX!!&H16IjAMdJXIFjlH(fIFRK AkdDq9@X31MPV"!"pIPJZ9qb'[P@-%$SjM!8!ICjJ,PIZ"Vj9cK!k1Fi(!(hHF#j AlmDq9Hm31MR["J"prRJZIFjlH(f-FhKpDf0iIleDH$Ylrrb"H`!!9ibUrPH1U"4 pM(0iIApLH&I[KVj9la!k1Hm"!(hqH#jAk`Dq9@X31MPV!`"pIPJZ9qc'[P@-%$S jM!)!ICjJ,ReVBhKpleYi9qj'[PA1%$TphR!ZIHpcH(qpHRJk-3!","%!#%'!rQ! pi2$a1Hr`m(q[H$JpB2$a1@[`m(q,@$K9Dq%qIIpEH$f!$`mjM!m2IkaJ1&@-)$B p`!m21Fi2$hq1F$KpRA0i9km'2PA[%$TpphJZ9k['2P9V%$TpGeJZ9@X31PHX4Mj 9M"!kICGJ,P@--$*AVSBq9Fi31RhAF#j9cL!fIBacH(eVBhKpr&Yi9qm'2PA[%$T pphJZ9q['2P9V%$TpGeJZ9@X31PIX4Mj9M"!kICGJ,P@--$*AlSBq9Fi31RhAF#j 9cL!fIBacH(eVBhKpr9YiJH(rV(qFHRL"BIqSIleDH#`&!!K!J3$F1+Arq&H-4Mk "`Iq`IFpcH$R1!!'4`Iq`QBm!!&H,KMk"JIq`IBjMH$Q-!!'4JIq`Q@i!!&H2aMk "BIq`I@aEH$PV!!'4BIq`QH`!!&H1"Mk"iIq`IHYlH$R[!!'4iIq`QFX!!&HX4Mk "`Iq`IFpcH$R1!!'4`Iq`QBm!!&HVKMk"JIq`IBjMH$Q-!!'4JIq`Q@i!!&H[aMk "BIq`I@aEH$PV!!'4BIq`QH`!!&HZ"Mk"iIq`IHYlH$R[!!'4iIq`QFX!!)'"rk5 4JIqXJF(rS*("rkK,rr5-JH(rX(h[+K54iIq`+!8!#%'"!,JjBK[`9+`31ReVB#j pD31Q6S!%)&HZ"Mk"iIq`1Hrrrj(Krl#Cc`!!9k['2S'"rl!jM2rrNB(rX*PX!!" AVSBqJH(rX$R[rrq4iIq`QFm!!&HV4Mk"JIq`1Bcrrj'"rl#CE!!!9ii'2S(Krl! jlrrrNH(rX*R2!!"ALmBqJB(rX$Q-rrq4JIq`Q@`!!&H1KMk"iIq`1Hrrrj(Krl# Cc`!!9iY'2S'"rl!jM2rrNB(rX*PX!!#j`Iqi6S!!)!#3"L"!!")!N!3D'!!4,Q4 PFemcBf*MAf9ZBh*jF(3![X(rf$VL(63k`K`dI*NMH(ai'hL)Z!!!1aJ!!95r"Mk )f!!!1aJ!!96'"Mj8aN!ZIrmcH)Mi!!!l'!!"91F'2P6RJ"jrrcYiL4J!!$XB!!& 9#!Bq93M!$Rrr3hL*1!!!1aJ!!98q"Mk*@!!!1aJ!!99+"Mj95N!ZIpj6H)Pi!!! l'!!"9@X'2P9VJ"jrhPYiLCJ!!$XB!!&9M!Bq9Bc!$RrHBhKAaH%qI+AkH$c!$`m iaJm2I,``1(rriRKAKb!fIpikH&ISN!!DI3MkH(8Fc-aALA5qIqVLH(dr8RKAbj! !'ReVmRKeI-c-9iad[Rr&iRKpRLTi9mEiIRc'qRJmi&9911G99AcF1$Krrq*i9iJ )2(rH3RKAkF)qI5RbH$e!!2mj5J$rI6a31(rHiRKALd!ZIrpDH&I-q(jpM2Ti2+" 996LP999pR#JiIrrLH&H'#$arhM*i9qF!"P6Ri6jAb!)H93L%2PI*"Mj9+B!H9mS %,RdT8hKp#%YiI2j$H&Ir!6ilB!!!5!!"@&GV%$TpGPJZ,!X!!%'#!#"Al2#q9qA 3#RfI+hKAa[#q9mI3#RcH1hK)!!!F9qMiIPITf!Kp(dYi9mViIPI,f!KpAPYi9rm "2PIH!6jAl&Di9q9RrPIQAhamT60iIB`VH&@-%$SjM!-!ICGJ,PIRRcjAk*DfI1G $H&6R%$Sij`)!I2Fi,PITeljAkXkkI5P6H&8T%$Sj+3%!I6G),PIV"Vj9Da!kIAG B,RdT@hKmjdYiICSlH&I-AcjAa9DfIB`VH&@-%$SjM!F!ICGJ,PI'MVj8aK!k1-B '!(cA-#jAa`Dq91F31MMR"!"mpcJZ9mM2[PI*aVTp#%Yi93J31MN)"3"p&d!ZI1G $H(c'1hKpR$0i9iU!(PG,"$jpA9Yi9k`A[PHP%$TpM#S8NCN!!$Xj!!4A4S3q9iF !(RcG1hKAU$Dq9kN`-Rd)5K54'3!!1cN!"$Yl!!%X'`!33B$qU$KJ!!#k`IrB6S! !)!#3"L"!!!S!N!3#m!!-,Q4PFepcCA4IDf9j!!"m#!+QN!!"!!L8)Ir!N!"K!&L 3!)%!A)"K!&L!J3"F1+)Y`%J!!$PJ!!!!1')Y`)!"!%Ji)3"!I!J$TNk!!#!!N!B J3B!!N!Bm!!SZC'9cAf0bHA"dI!J#TVj"rmL3!!%!#*3Kr["mGKYiI*3MH(bk+hJ kiKcd1`%!1)Kd!!"mB`Gd,!-!!%##!!`iJ!""5!!!$)L8!!"mK!GdQ*S!!(b9"h3 iSKadI+@SVP5c%$U)e!!"I-B(G#`'!!"!JJ!-11!!38J!!!b)p!!"I1F(G*Mk!!& mp3Gd13)FG(d)U+j9%M!b1f!!!%J!!#b,eJ!!1YB!!9I*"MiS#3!!3B)!0&I+"Mj 95JJm1@%!a(e,fDilH`!"+"X!#%'!rp4)!!!81B!!!$KK!-4pJpQZ1hX!!5JE!!K "J2rX1'%!a$L"!%4,rrZaB!!!!$KK!-`iJ3"%IQ@EH(j'NhK)!!%aB!!!!)-K!-a A*!BqQ*J!!$XB!!&A*FBqQ,J!!$XB!!&A*SBqQ0J!!$XB!!&A*dBqQ2J!!$XB!!' $)3$39bJ'2TNB!!!l'!!"9bR'2TNi!!!l'!!"9bU'2TPB!!!l'!!"9bY'2TPi!!! l'!!"1i!!!$[J!)!jJ!!!QB%!3$YJ!!*)!!"N1m!!!$ZJ!!")!!"!9pi)2$KK!$K mBq#Z9q3'2RaM)$JX!`!!3B)!#'2H!!&Arrjq9q8'2LJ&!!"!JJ!-1j`!!6[J!)! l[3!"+"d!"N'!rm"AaJBqI0F`VRcDfDilH`!"+"X!$8'!rj`ii!!!Q2S!$Ap$dhL !!3%B1#%"%(`)!kDk3Ir)6S!!)!#3"L""J!i!N!3#%!!,,Q4PFepQBh*jF(3!!!# q!Ir!1k)P0$Z!!!!lB!!!I*8MH*!!SIq`N!$"rk`ii!!!N!$Krl4)!!4-1X!!!%J !"#4AD)3qIhp#H)%Krl"rrNJiJ8(rV(rr8$KAfS!H9XX31Ree@#jrDeTiIpjDH(r HdRKAqS!H1CB!!9@-%$TpP@!ZIfaLH(rrBRKrrp*iIp4'F&ID"MT@P!Bk9qIK2PI Si!Crjd)89pk%2Rdpd#jrR%Ti193#!(eG8#jrR&*i9p2#2PID"MT@F`Bk1AS%!(e p@#jrR&Ti1C-'!(fGB#jrR'*iIr4'F&Ik"MT@P!Bk9rq%2MMk!3"mr6JZIj`kH$N 8!`"p(8!ZIja#H(rc4R"AqJBk9R-'1MNk"3"p28JZIja+H$P6"`"pA9!ZIja5H&H ,K$jrReTiJB(rX(rqB$L!iIqXIrmi1&ICJ"ij&J!#93J31Rd93#jrL%*iIpj#H(r HbRKAqB!H16B!!e8T%$Tp08JZIiP+H(rr5RKrrmTiIp*'F&IC"MT@8JBk9qVK2PI Vi!CrkPS89pk%2RfGb#jrHf*i12)#!(cp1#jrHcTi9p(#2PIC"MT@-3Bk14N%!(d G3#jrHd*i16%'!(dp5#jrHdTiIr*'F&Ij"MT@8JBk9rq%2MPC!3"pA9!ZIhY5H$P b!`"pI9JZIhYDH(ra4R"Aq3Bk9M%'1MQC"3"pR@!ZIhYLH$Ma"`"mr6JZIhXkH&G SK$jrId*iJ5(rX(rq5$L"3IqXIrp31&IBJ"ijGJ!%9@X31Ree@#jrDeTiIpjDH(r H`RKAq)!H1CB!"9@-%$TpP@!ZIfaLH(rrBRKrrm*iIp"'F&IB"MT@%!Bk9qIK2PI Si!Crjd)89pk%2Rdp`#jrR%Ti19!#!(eG8#jrR&*i9m[#2T&KrkKAf!BkJB(rU&@ -"MU4JIqS12J%!(cp1#jrR$TiJ3(rU$N)"J"p(8!ZIja#H(r`4R"Aq!Bk9K!'1PI rK$ij1!%!I6e),RqF5RJj8!-!I9e3,RqF8RKrkdC`N@(rU&Ii"MU"JIqS9B`'1T' "rkJiq!8!I2di,RqF1RL"!IqS13J(!(dG3#jrR%*i9iQ%2RqI5RL"3Iq`Irj31)& KrkarreJi9pH!(MQ@!!C9M"!kIC9J,Rq-BRKrhQ*iIpkkH&IhJ"iipJ!(91F31Rc e1#jrKcTiIrmkH(rrZRKrb%C`N3(rT&IA"MU")IqN95N'1T%Krk4AkZ%q9q[J"Rr U@K4AhS3qICfi,RplBRL!iIqN11F#!(cp1#jrHcTi9mM#2T%"rk"Ae`BkJ5(rS&8 T"MU4)IqJ19F%!(eG8#jrHe*iJ@(rS$PV"J"pI9JZIhYDH(rX4R#4JIqN9rF'1S$ Krk48j`BkN!$Krk4Ari3q14F"!(dG3#jrHd*iJ5(rT$NT!`"p28JZIhY+H(rU4R# 43IqJ9rF'1S&Krk"9D`BkN@(rS$QA"3"pR@!ZIhYLH)$Krk!ij`F!I2di,Rpl1RJ keJ!),"B!)%'!qparRq0iIhcEH(rlqhL"!Iqd13J!!C%"rl5")Iqd,!N!'8'!ql" ALZMq9i[S"(q+@K4AE1Mq9fIS"(pX1K4AL2KqI3MDH$dJ998j+999I4p)1(plqRK AkJJmIja5H&GV`MjpDq*i2B!!rcQ-!2ppIf!iIjckH&IR3#jrHcTi9iM`[Rd)fRJ p)$-c15Nc-hdI5$KrHrTi9qS31RqF8RKADi3qI@[LH&9r"$jrR2Ti9qb!(RplBRK AKq%qI1IDH$d!$`mj#!m2I2p!1(plqRKAk5!fIja+H*0M!!#6J`!%ZJ(r`%k!!#! !N!BJ3!!3!*!%"6`!$#jQBh*jF(4IBQpNH3!!I!J#TVp"rqL3!!%!#*3Krl"mHKY iI*mMH(bl+hKmh$0iI2dlH(dH3hJX(J!!3B)!B(p$dhKrj2YiIfAEH(r'mhK,rlF GB!!!!(rMqhKrj2YiIiAMH$MJ!!!X(J!!3))!#$MJ!!&mjMYi5rqfp@!!!!"rirY iIq6lH(qPkhKra[0i5rqfh@!!!!")!!"FId26H(rNqhKrTHYiImEcH%[rYX&J!!! !Iq2lH(rNqhKrKH0i13!!!#`H!!"!JJ!)13!!!Ad'3hK,rlDCB!!!!(rMqhKrj2Y iIfAEH(r'mhK,rlD"B!!!!)!"!&Ji)3"3I!J$TVY"rqK1J!!J!*!')%'!"J#3"IJ !%5jNCA0I-f9MBPpPEQ0bHA"d!(a$%hK1J!!JI!J#TT!!!3!)P#(r`%[rrqemD4Y iJ')!F)##!'`iSJ!!1-)YcS$L!'#"!J"F5!!!@B""!"5!JJ$8N!"N!!",rk0CB!! !!$KJ!!#!!3")1#%!3(`)!kC1J!!JI!J#TT!!!3!)P#(r`)"L!05!B`!!5!!!-B" "!"5!!3")1#%!3(`)!kC1J!!JJB)!2*!!33!8J!`!!)"-!!4m#31Q6S!%))'#!$L 3!%%!&)!-!!#!6!!%I!N$TNk!"##"JJ!BN!""!"5!$!!!J%`!"(`*!kC1J!3JJB) !%*!!33!8J!`!!)"-!!4m#31Q6S!%))'#!%#3!%%!&)!-!!#!6!!%I!N$TNk!"## "JJ!JN!""!"5!$!!!J%`!"(`*!kC1J!3JJB)!$*!!33!8J!`!!)"-!!4m#31Q6S! %))'#!"53!%%!&)!-!!#!6!!%I!N$TNk!"##"JJ!NN!""!"5!$!!!J%`!"(`*!kC 1J!3JJB)!#*!!33!8J!`!!)"-!!4m#31Q6S!%))'#!#L3!%%!&)!-!!#!6!!%I!N $TNk!"##"JJ!XN!""!"5!$!!!J%`!"(`*!kC1J!3JJB)!"*!!33!8J!`!!)"-!!4 m#31Q6S!%))'#!!#3!%%!&)!-!!#!6!!%I!N$TNk!"##"JJ!`N!""!"5!$!!!J%` !"(`*!kC1J!3JJB)!(*!!33!8J!`!!)"-!!4m#31Q6S!%))'#!$53!%%!&)!-!!# !6!!%I!N$TNk!"#!!!!!FJ!!!I!J!N!DBJ!!!6!#3"LQXJ!!!Q!J!N!8U4)!!!)! )!*!&+X5!!!$3!*!'+j5!!!#3!"!!N!8X*)!!!'!!N!BXK)!!!+J3!*!&,5b!!!& )B!#3"5m)J!!"4%!!N!8`6)!!!+!)!*!&-1b!!!(m5!#3"6,SJ!!"`&!!N!8dU)! !!0!B!*!&0AL!!!#J'!#3"90NJ!!!@!#3"P1mJ!!#-(!!N!9E5)!!!4``!*!&A'b !!!"B!*!'A-5!!!!X!*!04L)2-!)L%c!#)JX`"L)G0))#"#8dAhKHL#h1"#*IH!B L!F5#!KJ"k!))!LJ#6!F`!c!$%!,3!T!!!R!YZ#di!0JE6aX`'fJEEa[`("3F0"c d((3Y`!$S!L%+!5)PH!%L,#!")L"p#5'BKJ)D!"`!j!b8%U3C`"MS'VJQC#QX,)3 X*#Z8+X3U4#dX,`J`l$"--ZJdU$9i0KK39&1m8f4E5#)-C))#+JaB$%`-3!`d$#J -(!`3$!3$%!,m!ZJ#e!,%!V!#R!+)$V31S!k-$RJ1D!j8$N!1,#Bd*LJQ(#B3*J3 Pq#AX*H!Pe"c8(-!FV"bB()JFG"aJ(%`F2!8K%)%$"J!3!!!3%"!!!"!!%"!3!"! 3%!3K%!3K%!)L%"!%)4#"!`X3!"!!%*!&!!!"%!!"!"!"%"!"!!!4%!!4!"!4%"! 4"L%"!L%"!b)"!3%K!3-K!3%K!3%L!3%#*!'3"!-K!3)L!3%")3%")3%"*!'3"!) L!3%"*!'3"53"N!3%)3%%)3%#)J%""#%"!5%"!5%"!L)"!3%M!3%"##%%J3-0!3! !!3!%!!3!!!3%!33!!33%!!!J!!!N!3!J!3!N!!3J!!3N!33J*!%%*!%$)3%#)`3 "!3)L!3%")J3"!5%%!5%"!58%"!%""!%P!3%%"!%#)L!"!L-N!3%")b!"!3%L*!% ")`3J!3%U"#3"!33J!3%%*)%$$`)!!!)!"!-!!!-!"!)%!!)%"!-%!!-%"!)!)!) !*!-!)!-!*!)%)!)%*!-%)#8$"#3"!J)L!3)")`3"!`)L!3-"*!3"!J3"*`%#"!3 "!`3"*J%$"!3"!J%M)!%#!5-N!3-")b!"!`%a*!%#"#!"!J3N!3-%)!%$"#3%)3) &)3J")3)")3J#)3J#)J))!b))#!%M!JJ)"#)"!J)K!3)M#!%#!5))!3%K#!%M!3) )!5%"!5F)#!%##!J"!L%"J3-(!J!"!!!*!J!*!!J"!JJ"!!J*!JJ*!L-"!3)")J% "!L-*!3)")JN"!5F)!3%##!%"!5J)#3%##!N"%!-K%J-K%!%K#!%K%J%K#!%L%!J #)K))!L-3#!J")a))#!%K%!)L!4)#)J%3!5-)!4)"*!J"%!J")`%5#!%U!4!)#!% 5#!J"%!%K!B%$"a)!!4!!#4)!#4!)!4))!4!)#4))#5%3!5-"!4)")`%"%!%M#3% 5!6)*!4!)!3%5#!%"%!J*!4))#3%&)33%)5##!J3%)"!!&!!3)#)8))%$##!!!#! %!#!!)#!%)#!3!#!8!#!3)#!8)!-K#)%$"J3!#!!J#!3J#"!!#"3!#"!J##38)!J J!L-))!3")JJJ!5JJ##!%)!JJ%!%M##!8!5N))"!J##!8)!L"!`FJ!!!N!!!J)!! N)!!`!!!d!!!`)!!L0##"!`JJ)!!J*!!JN!3N)#!`!#!d!#!`)#!d)!%K)!%K#)% $"L3!##!J##3J#$!!#$3!#$!J##8d)!JJ)!%M##!N!5X))#!J##!N)!JJ-!%M##! d!5N))$!J##!d)!J()K!)J3-r!!!)!"!!!J!!!K!)!J!)!K!!!!)!!"))!!))!") !!J)!!K))!J))!K)%!!!%!"!-!!!-!"!%!J!%!K!-!J!-!K!%!!)%!")-!!)-!") %!J)%!K)-!J)-!K)!%!!!%"!)%!!)%"!!%J!!%K!)%J!)%K!!%!)!%"))%!))%") !%J)!%K))%J))%K)%%!!%%"!-%!!-%"!%%J!%%K!-%J!-%K!%%!)%%")-%!)-%") %%J)%%K)-%J)-%K)!!!!#!b%#!L)#!J3K!3%K!J%K!3)L!J%")`)#!33L#!)#)3J ")3)")`J#!J%K#!)M!3J#!5)"#!%R!J%)!J)"#!%K)!)L!L!$)5)#)J)L!b)J!3% M!L!"!L)L!3%M!L)"!L%J!5-)!L!")3J")5)")`J#)J%K#!%R)!%)!L!"#!%R)J% )!L)"#!)K!S%$"`)!!J!#N!8!!!-#!!-!!J-#!J-#)`))!J%L!JJ"*`)##!)#!JJ #)`-)!J%L!`J"*`)$#!)#!`J")L!#J3-(!L!#!#)#!L)#!#!$!L!$!#)$!L)$!5F J!JJ#)!))!5FL!JJ#)J))!5FJ!`J#)!-)!5FL!`J#)J-)"L%3"#%J!L)3)!%K%!- L%"!#)4!")5!"*"!3)!J$)3J")4!")3J#)L!)!533)!J3!L-)%"!")JJ3!58J#"! 3))%$"`!!"!!3"!!!*!!3*"!!""!3""!!*#33%#3)!L)%#!%M%!3)!L)N#!%N%#3 )%!%R"!J3%!3)%!%P*!J3%#5"!`F!"!!!&!!!"#!!&#!3"!!3&!!3"#!N%"3J#!% K"!%K#!%K&!%K#!%M"#!)!588)!J3"!%M#"!8!5J)%!3J#"!8))%$"`!%"!!8"!! %*!!8*"!%""!8""!%*#33&#3)!5-%"!J")a3%#!%M"#3)!6)8*!J3"!3)%"3%#"! %*!J3&#3%)4!%)3%#)K!""5)#%!)K!J%K!3%M!K!"!5%#!L%J!5%3!5%J!L)")!% M%!%J!b-J!K!")L!#!5F")!)3!5!#!5%%J3-(!"!%!!!&!"!&!!!%!K!%!J!&!K! &)3)")J3J!5-3"#!#)J8J!5-3"5!#*`3J!K!%)!)"+!8J!K!&)!)J!b%`!b)J!3) L-!%#)5!#)J)`!L-#)!%")`)`!3%L!L!")5!")6!")5!")b!")!%M-!%J!5%J!5- J!M!",#!#)!%J!M!")!)J")%$"`!`"!!J"3!`"3!J"!)`"!)J"3)`"53#)!3J!5- `"#!")b!&)!%M-!8J!6!J"#!#-!3J!L!&)!)`"5!#"#%%"L)""))#$!%"!!8!!3% &!3!3""!!%334!4!&%!%4"5%4!5%)J3-2!!3)!!!)!33)!3%)!!8)!!%)!38)!3! )%!3)%!!)%33)%3%)%!8)%!%)%38))4%#)3J")35"!`i)!!!)!33)!3%)!!8)!!% )!38)!3!)%!3)%!!)%33)%3%)%!8)%!%)%38L#"%")JJ)!5-%#!J#+JJ)!33)#!% "#!J")`8)#!%S!3J)!38)#!%"*`J)%!3)#"!"0`J)%33)#"%"#!J3"3J)%!%)#"% &#!J4"b%3JJ)0!!%!%4!!%"!3!4!4!3!"%!%"!4%4!"%3%3%L%4'"!bm3!!!3!"! 3!!%3!"%3%!!3N!8"%"!4%!%!%!%3%!%"%!%4%"%!%"%3%"%"%"%4!3!!!3!3!3! "!3!4!4!!!4!3!4!"!4!4!3%!!3%3!C!&%3%4!!%4%!%4!3%4%4%!!"%!%"%!!4% !%4%3!"%3%"%3!4%3%4%"!"%"%"%"!4%"%4%4!"%4%"%4!534%4%3J3-2!!!3!"! 3!!%3!"%3%!!3N!8"%"!4%!%!%!%3%!%"%!%4%"%!%"%3%"%"%#34%4!3!L)3%!% M%"!3!5-"%"!"*"%3%"!",a#3"`%3%"!4%"!"!5m3%!%3%"!"!4!3!4%3%"%",K! 3%4!3%"%"%"!4%4!"!L)3!3%M%"!"!5-"%!%"*"%3!4!",a!"%"!3!4!"%!%3%4! "!3%[%!%"%"!"!3%3!3%4%!%4!5i3!4%3%!%4!4!"%4%3%3)L%"%")a!3%3%M!4! 4!534%"%3!5m3%4!3%"%3!4!4%"%3%3%",a!4!4!3%3%"%"%"%4!4%3%Y%"%4%"! 4%3%3%4%4!B%$$`!!!3!3!3!"!3!4!4!!!4!3!4!"!4!4!3%!!3%3!C!&%3%4!!% 4%!%4!3%N%4%"%!)L!4!")a!"%!%M!3%3!534!4!3!5m"%"!3!4!3!3%3%"%"%!% ",`%3!4!"%!%"!4!"%3%3%3%Z!4!4%!%3%3%"%"%4!3%#)J%"!5-3!3%")`'3"#3 4!3%3!5m"!4!3!3%3!3%"%"%"N!3[!3%"%!'3"a%"!4%",J%"%4!"!4%"!3%4%3% 4!L)"%3%M%!%4!5-"!4%"*"%"%4!",`%4%"!"%4!"!4%3%3%4!3%[!4%"%!%4!3% "%3%4!4%4!5d"%4%3!4%4!3%4N!5"!`m!!"%!%"%!!4%!%4%3!"%3%"%3!4%3%4% "!"%"%"%"!4%"%4%4!"%4%"%4!4%N%4%4%!)L%4!")a!4%!%M!4%3!534%4!3!5m 4%"!3%4!3!4%3%"%4%!%",a%3!4!4%!%"%4!"%4%3%3%Z%4!4%"%3%3%4%"%4%3% #)K%"!5-3%3%")`%4!3%N%4%"%!%[%3%3%"%"%!%4!4!4%3%"!5m4!3%3%3%"!4% "!4%4!4%",K%"%4!4!4%"%3%4N!3#)K%4!5-3%4%")`%4%3%N%4%4%!%[%4%3%"% 4%!%4%4!4%4%"!5m4%3%3%4%"!4%4!4'3"!%X%4%4%"%4%3%4N!3%)3)%)3)#)J) #"#%#!5%#!5%#!L)#!J%M!J)#"#)#!J)K!J%K!J%M!J)#!5%#!L-#!J)")J)#!5J #N!F"!b%$!b)"!J)L!`)#)3%")3)")3-")3)")`%#!J%M!`)#!5%"!L)#!`)M!J% #!5-#!`)")J)"!5-#!J-"+J)#!3)#!J-#!J)")3%#)J)"!b%$!L)#!`-L!3)")`) "!J)L!`)")`)$!J)K!3%M!J)"!5%#!5%$!5-#!J-")3)"*`%#!J)"!J)"+3-#!J) $!J)"!3)L!`%#)J%$!L)$!`)M!3%#!5-$!3)")`%$!J%M!`-#!5)"!3%M!J-"!5- #!3-")`)$!`%a!J%"!J)$!3)#!3-#!J-$!J)#)3'"!`F#!!%!!J%#!J%!!!-#!!- !!J-#!J-#)`%#!J%L!3)"*`)"!J)#!3)#)`-#!J%L!`)"+!)$!J)#!`)"!5%"J3- (!`!"!3)"!`)"!3!$!`!$!3)$!`)$)3%")`%#!`%V!3)"!J%#!`)"!J%")`-#!`% U!`)"!J-#!`)$!J%L!3'"!`F#!3%!!`%#!`%!!3-#!3-!!`-#!`-"*`%"!J)"!3) "*`-"!J)$!3)"*`%$!J)"!`)"+J-$!J)$!`)"!3'"!`F$!3%"!`%$!`%"!3-$!3- "!j!&)#!"!3%#!`%"!J%$!3)$!`%#!3%$!J-"!`)"!`-#!`-$!J-L!3)#)3%")3) ")`%#!J%K!3)M!J%#!5)#!3%R!J)"!J)#!3-L!`)#)3-")3)")`-#!J%K!`)M!J- #!5)#!`%S!J)$!J)#!`%#)J%$!L-"!3)")`%$!J%L!3%")`)"!`%V!J%"!J)"!`) #!3%#)J-$!L-$!3)")`-$!J%L!`%")`)$!`%U!J-"!J)$!`)#!`%K!3%M!3)"!5% "!5%$!5-"!J-")3%"*`%#!3)"!J%"*`-#!3)$!J%")3%")`-#!3%K!`%K!`%M!`) $!5%$!5F"!J-#!3)$!5N$!J-#!`)$!3%")`%$!3%M!3%$!5-"!`-"-`%"!3)"!`% #!3%$!J%$!`)"N!3M!`-"!5-$!3-")`-$!`%a!`%"!J-$!3)$!3-#!`-$!J-#)`% "!J%L!3%"*`)"!3)#!3%#)`-"!J%L!`%"*`)$!3)#!`%#)`%$!J%L!3-"*`)"!`) #!3-#)`-$!J%L!`-"+!)$!`)#!`-"!5-"!3-"+`%"!3)"!3-#!C!%)`-"!`%V!`% "!J-"!`)$!3%")`%$!`%V!3-"!J%$!`)"!`%")`-$!`%U!`-"!J-$!`)$!`%R!3% "!J'3"#F$!3%#!`%"!5F"!`%#!3-"!5F$!`%#!`-"!5F"!3-#!3%$!5F$!3-#!`% $!5F"!`-#!3-$!5"(!`-$!J-$!`'3"!-"N!3$!3%$!`'3"!-"!`%$!3%$!`%$!`- "N!3$!`%"!`%$!3-$!`%$!3%$!`-"!`-"!j!(!5%3!L)#%!%L!3)")J3""L%%!5% #!5)%!3%Q%!3"!K!%!53#%!3"!5%3"L%#!L%"!b)"!J-L!K!")3%#)`3"!J%K"!) M%!3"!5%3!5)"!J%K"!%K!J)M!3)3!L-#%!3#)4!")`%#%!3K"!-Q"!%#%!3"!5) 3"!3L!3)%)K!%!5%#"#)3"!)K%!)K!J%M"!%#!53%!3)3!5-"!K!")3%$)3%")4! ")J%#!b%#!5%%!L%3!L-#%!3$)J3"!5B3"!%#%!3$)`3"!J)R!3)3"!%#%!-L%!3 )*3%#%!3""583"!%#%!3K"!%K!J)L!3)")33$)33#)4!")3%")S##"b'!!L1!JJ+ "!aL!J!)!JJ)!!!)!J!!!!J#!JJ#!JJ)!!J#!!J+!J!+!!*!%!J!#!S!#!)!#!!# #!!##!)#!!)#!!)!#!J#!!S!!!S!!!J#!!J8L!J+"!ad!JJ+!!!!!J!#!JJ)!!!+ !J!#!JJ#!!!#!!!!!!J#!J!)!J!!!JJ#!!!)!!J!!!!+!!J)!JJ+!JJ)!J!+!J!# !!J+!!!)!!J)!JJ+!JJ!!!J+!!J#!!J!&)S!#!L'#"L1!J!)#*3%%"!%""5)%!3% L"!3")3%'*!%""!3")3%#)3%")J3%!L)%"!)K"!%K!3)N"!%""!%K!3%M"!3""#- ""!3'*!3%!3%$)3%#)J%"!5)%!3)L"!%")33"*!%""!3")J%%!5)"!3)K!3)K"!% L!33$*33%!3%%!L%"!5%%!b-%!3%")33%)3%")33#)J%%!5%"!L-%!3%")33")3% ()3%#)3%"*J3%!3%%"!%K!3%K"!)K"!)K!38L"!%")J3%!5)""!%K!3)K"!-N"!% ""!-K"!%M!3%%!5)"!3%K"!)M"!3"!L%%!5)""!)N!33%!3-M!3%%!b-%"!%")33 ")J%""#1!!33")i!""!)K)3)KJ!%K"!8LJ#!$)J%%J3-,!#!%J!!%!!%!J#!%J#% !J#%%!!!%J#!!!!%!!#!%!#!%"5%J!L1!)35"!aq!)35!!3#!)33!)!#!!!!!)3! !!35!!3!!)3!!!!5!!!3!)3#!!!#!!3!!)!!!!33!)3#!)!5!!3#!)!!!)33!!35 !)!5!!!#!!3!!)33!)35!!!5!)3!!)35!!33&)L!%!L%K"#%%!5+!!3)LJ#!#)B! ")33')L!%!L)""!%LJ#!#*)#!3"!")B!")a"!J!%L%%!$)8!"*8!33)"!!50!J%! #)B!")4!')N!3!L*!%!%PJ%!33)!#)8!&)8!")d#!3!)KJ!8K%!)K3!)MJ%!3"#& !!5&!!L'!!5%3!b333)"!!5*!J!8L%%!")8!")8!#)4!#+%!33)"!%%#!!L&!!5& !!50!J%!$)N!3!5@!3""!J!)K3!NL3"!$)K"!!5&!!50!J%!")N#!!b1!3"!")B! ")a"!J!%L%%!$*N#!3""!J!)L3)!&)4!")S"!!L'!!5%3!L9!%%#!3!%L3)!")4! $)K"!!5&!!L1!3"!%)8!")8!%)4!#*%!33"!#)`J3)!3K)!%Q%#!J#"!J"58)%#! J#!%K)!)K%!%K)!)M)#!)!5%J!L%3!L%)!5%J!5))%!%K)!%K%!8L)!J&)5!")JJ 3!5)J#!)K)!)L)#!")4!")L!)!b-)%#!")`J3)!%K#!8Q)#!)%#!J!b)J#!%L)#! ")a!J)!%K%!-K%!%K)!3M#"!J!5%)!5)J)!%N%#!J#!%K)!3M)!J3!L%)!5%J!L% 3!5%J!5%3"5-J#"!#*3J3)#!)!5)J)!%L%#!$*L!J#"!J)!8L%#!")3J$)3J#)5! ")K!J!b-J)!J#)5!#)5!")JJ3!5)J#!3M%#!J!5%3"#%J!5))%!%M)!J)!5)))!) K#!)K!J)P#!)))!J$)3J")JJJ!b)J#!3K!J%M)!J#!L3)!JJJ!5)##!%M#!))!L- ###!#)3J%)b!)!J)K#!)L)!J")3J$)JJJ!5)##!)K!J%M)!J#!53J#!))!b)))!J L#!)")L!)!L)J#!%K#!)M!JJJ!5%#!b-###!")3)#)`J##!-K#!3M)!J#!5%J!L% )!L3###!)!5%)"#)J#!)M)!J#!L))!J%L)!J%)3)#)3J")JJJ"#3)!JJJ!5%#!5) J#!)M)!J#!L%)!5%)!5%)!5)))!3N#!)))!%L!JJ#)J))!b)))!)L##!")3)")L! )!b-)!JJ"*8!)3""!!5&!!b&!!L-)3"!")3J&)a"!#!%L%%!")d!33!)S%%!)3"" !#%!")8!$)8!")8!#)3J&)a"!#!%K%!%L#%!#)3J")K"!!5*!%!3K3!8K3!)P#%! 33!J$)3J")K"!!L%3"5))3!-P3""!#%!")N!)"#*!%!8P#%!33!J")4!")3J#)8! "*%!33!J#)d!)3!-K3!%L3!J#)8!")8!%*4"!#%!3!5-)3"!$)4!#)8!")8!&*8! 33!K!!L%)!L&!!L%3!5%)!5)33!%M3""!!L%3!5%)!5%3!5))3!8K3!%K3!-M3"" !!b*!#!%P%%!)3"!")JK!!6i+9Q9bD@CjD@jR,#"`E'9KFf8JFQ8YC@jdCA)J*A- "1!S("deTFfeKG'0S)#dJG(*j)'&RB@PZ#J%Q)$"i)(XJ!5#"!!'3#2k3#"q3"!k 3"1#3"2'3"!(q!Ii"rJ(qrJ(q!Ii"rJ%Ii"rJ$[%1mH!Ii"ra$[%1!H!"i!(a!I( J!H!"m3(a!4rq(ri1rJlqrKrq(ri1rJi"(`%I!3i"$Km"(`%1!3i"i2lJr[(qmIl qi2lJr[(qm3-L8#L#!K"3&&!!6qa2f%r%6l"2R%q)1%`i1$JN1"!i!$IX0pJha!N K!B)#"3!"!!%!!3!"!!%&)3'#!J8!!3!"!!%!!3!"!L!ZdY28eGEAf0RDfpcGhYr JiH,Mj1AQjqMTkZ[XlHl[m2(bmr6ep[IiqIVlr2hqr`%JJ4%"!J-%"3B(#!N+#`8 '"`J*#JX-$3i2%"%5%a39&KFB'4SE("dH(b!K)L-N*5!K)L-N*5BR+#NU+b`Y,Lm `-6)c0$8f0cJj1MXm26ir3%&#3d3Z,c!a-M-d06Bh1$P"3N0%48C(5%P+5da06Np 389*69&9@9eKC@Q&LBf4PCQGSD@TVE'eZEh"aFR0dGAChH(Pk"b)3)!-K)!)K%!% K!3-K!3%M%#!"!L)J!3%K%!)K#!-M#"!J!5%)!5%J!5))%!%L!3J#*J%)%#!"#!% N)!%)%!-K)!-L-#!#)L!J!L%`!5%"!5%J!5%"!5-`)!%")b!J!3%K-!)L##!#)`J `)!%M##!J!5))-!%M!3JJ!5X"#$!J!3JJ)!%)-!%K#)%$"`!!#"!J#!!J#"!!#3! !#4!J#3!J#5%3!5))#!)Q#!J3)!J)!53J#!J3!5)*#!)Q#3J3)!N)!53J#3J3!5% )J3-()!!)-#!))#!)-!!*)!!*-#!*)#!*)6!")`J))!%V#!J`)!J))#!)#$!")`N ))!%V#3J`)!N))#!*#$!%)3)&)5!")3)")5!#)5!#)J)J!b)J)!%M!L!J"#)%!J) K"!)M)!3#!5)J"!%K)!%M"!)J!5%%!5FJ)!3#)#!%!L%%J3-(!J!%!!!N!J!N!#! %!L!%!#!N!L!N!L-%"!)")J3%!L-N"!)")L3%!5FJ"!3#)!3%!5JJ*!3#)#3%%!- K%J-K%!%K)!%K%J%K)!%L%#!#)K)J!L-3)#!")a)J)!%K%!)L"")#)J33!5-J"") "*#!%%#!")`35)!%U""!J)!35)#!%%!%K")%$"a)!""!!*")!*"!J"")J""!J*") J*#%3!5-%"")")`3%%!%M*!35!6)N""!J"!35)!3%%#!N"")J*!3()3%")35"!`d !!!3"!3!!!3!"!33!!33"!!!#!!!$!!3#!!3$!3!#!3!$!33#!33K!`)K!J-L!J% ")J3#!L3%!J%"!5%#!5%"!58#!3%%!J%N!33#!3)L!J)#)J)$!5-%!J)"*!3#!`% ")`)#!3%V!J-""!)#!33#!`J$)3J#)`%)")%$$3!)"!%*!!!*!!%*"!!*"!%)!!) )!!-)"!))"!-*!!)*!!-*"!)*"#)$#!%K!J%K#!%P!J%)"!)"*3J%!J%*!5%#!5% *!58#!3N%!J%P#33#!3J")`)##!%V!J-)"!)##!3#!`N")`)##3%U!J-*"!)##33 #!`8K%!3K!3)L%!%%)3L"!`S3!!J!!3J3!3J!%!!3%!!!%3!3%3!!%!J3%!J!%3J N%"%)"!-L""!#)33")3%")`33!3%K"!)M#!33!5))"!%R!3J%%!%)"!%K%!%M""! 3!5%%!5%4!5-%%"%")33"*a!)""!3#!3"*K%)""!4#)%$$`)!!")!!!)"!")"!!) !#")!#!)"#")"#!)3!")3!!)4!")4!!)3#")3#!)4##85%3J%!J)L"")#)`3#!3% M"")"!5)%!J%M#!35!5`)"!)"#!35!3J%!K!")`35%!%M"!)4!5-%%K%"-!3#%!J %%K!)"!)4#!35%3J%)4!%)3%#)K!""5)%%!)K"!%K!B%$'333!33J!!!`!!!J!3! `!3!J!!3`!!3J!33`!33!%!!3%!!!%3!3%3!!%!33%!3!%333%33J%!!`%!!J%3! `%3!J%!3`%!3J%33`%5%%!L%3!5%3!5%3!L)"%!%M%!%3!b-3""!")K!%!5J"%!3 3!4!%)!%K%!%K-!%K%!%M)!%3!5-`!4!")5!")a!%-!%U%!3J!4!%-!%3"!%L%"! ")a!3%!)L%4!")a!4%!)R%"!%%"!3"!%U%4!%%"%3"#!3%!%M-"!3!5-J%4!")c! 4%!%`)"!3"$!3%!3J%4!%-"%3"!3K#!BL#!J#)3J#)33")3J")33$)`3)#!%L"!J ")3)#)JJ#!b%#!5-)#!)")3J")J)%!5-)!J3#*`)%#!J#"!J$)J%)J3-'!!%!!!N )!!N!"!%)"!%!"!N))J3*!5%#!5-"#!)")3%")3)")`N)!J%K#3%R!J3"#!)%!3% S!J3*#!)%#3+"!`F!!!S!!!)!#!S!#!)%!!S%!!)%#!SN"!J#!J)L#J)#)J)#!5- )#J)"*!J#!J3")`S#"!%T!J)%#!S#"!J#J3-(!!%+!!%#!!N+!!N#"!%+"!%#"!N +*!3*!J)")`%+!J%M!3)#!5-*#J)"-3N#!J3"#J)%!3)#"!N+!J3*"L%"J3-'!!J !!!J"!3!!!3!"!3J!!3J"!b%3!L)"%!%K#!%K%!%N#!%3!3)L%!%"*!%3!3J"*4! "#!%3!5%J!b)J!B%$"J!S!!!S!3%J!!%J!3%S!!%S!3%K)!%K%!%M)!%3!5%S!5% 3!58S!4!")!%R%!%J!4!"+!%P%!%S!4!#)3+"!`F!!!-!#!)!#!-"!!)"!!-"#!) "#!-#)J)3!L)$%!%M#!)3!53)!a!"!5-#%!%"+J-3!3J#%!%)!a!")L!#J3-(!#! $!#J#!#J$!5!#!5!$!5J#!5J$!5-J!K!")b!$%!%M+!)3!6-S!a!")!)3!5!$%!% S!K!"+!-3"#%%"#%%!L)%"!8L!J3#)3)")33")`)%"!%K!J)K)!%K"!%K)!)L"#! ")`3%)!-M)!)%!5)J!J%R"#!#"!3J!J-L)!3#)5!")33")b!%"!%K)!-L)J3#)5) ")33")b)%"!%K)J)M)#!%!5)J)!%R"#!J"!3J)!)M)#)%!5)J)J%R"#!L"!3J)J) K#!%K"!%K#!)L"!J")`3%#!-M#!)%!5))!J%R"!J#"!3)!J)K+!%K"!%K+!)L"#J ")`3%+!-M+!)%!5)S!J%R"#J#"!3S!J)M##!%!5)))!%R"!JJ"!3))!)M##)%!5) ))J%R"!JL"!3))J)M+#!%!5)S)!%R"#JJ"!3S)!)M+#)%!5)S)J%U"#JL"!3S)J) )#!)K#!)K!J)Q!J))#!)#"#-)#!)")3J")J)#!L%#!5B)#!)##!J")J))"#-)!J) ")`J#!JJK#!%K!J%K#!8L!J)")3J#)JJ)!5B##!J#!JJ%)`J#!J%K#!3K!J)K#!) L#!J")J))!5%#!L%)!5%#!53)!J))!5%###8##!J#!J%K#!)K#!%N!J))#!)K#!3 M#!)#!5%)!5)##!%K!J)K#!)L#!J")3)#)3)")`J)!J-L!J)#)`)##!)N!JJ)!J% L#!J")J))!L%#!5-)!J)&)JJ#!5%)!5%#"5%)!L%#!b%#!58)!J))#!3M!J))!5% #!L%)!LF)#!*!%)!3"5)3J!%L3"!#)8!#)4!#)i!33!%KJ!)L%)!$)B!")N!3!5% 3!b)33!%KJ!)K%!%N%%!3J!%L3"!&)4!")4!#)8!"*)!33"!")4!#)B!#*"#!%%! ))4!")K"!!5+!%!%Q%)!33"#!!5&!!L)33!3K%!3QJ""!%)!3!5%3!5333"#!!5& !!5'!!LF3J""!%)!3!5%3!5)33!)K%!3K3!8LJ"!")4!#)N!3!5%3!L'!!5&!"#3 3J""!!5@!%%!3J!-KJ!8K3!)K%!-P%%!3J"!")K#!!5*!%!)L3"!")4!")4!%)i! 33!%KJ!%K3!%LJ"!$)a"!%!-L%)!")33#*!%%"!%$)3%")33")J%"!5%%!5)""!- K"!%L!3%")J3"!5%%!5%"!L%%!L)%"!8P!33%!3%#)J%"!b-""!3")3%&)33"*!% %"!%$)3%$*J%""!3"!3%K"!)K"!)M!33%!5)""!%K!3)P"!%""!3$)J3""5%%"#B %!3%%"!%$)3%%)3%")33%)J%"!5%%!5-""!3#)33")J%""#-%"!%#)J3"!5)%"!% K!3%K"!%L!33$*!3%!3%$)3%"*!3"!33#)J%%!b3%"!%"!5%%!L%%!5%"!5%%!5) "!3%L"!%")33")3%&)J3%!5%"!L-"!33#)3%")`3"!3)K!3%L"!3$*%!3#"!")4! %*3J33"!)"#)33!)K%!%L%!J")8!"*!J33"!")4!#)JJ3"5-3#"!#)3J")d!3#!% K3!)K%!-L%%!")3J")N!3!b%3"#%)!5*!%!%K%!%N%!J33!3K%!-L%!J&)8!"*!J 33"!")4!")4!")K"!!58)%%!3#!%K3!)L%%!")3J#)K!)!5&!!L%3!L%)!5*!%!% K%!%K%!3M#""!!L%3!5)3#!BK%!)K3!%K#!3L%%!"*!J33"!$)4!")4!$*""!%!J ")d!3#!%K3!)N%%!3#!-L#"!")4!#)d!3#!%K3!%K#!%L3"!")K"!!L%3!5)3#!) M%!J3!b%3!L3)%%!3!5%)"#%""#%%!5B)!33J#!%")L!)!5%%!L8""#!)!3-K!38 L)!J#)5!")J%%!5%)!53%)!J"!53J#!%%"L)""!%K#!3K!3%K)!)M"#!)!5%%!L- ""#!%)3J#)5!$)L!)!5B%)!J""#!")3%")b!)!33K"!-P"#!)!33")`J""!%K#!% L"#!")3%")b!)!3-K!38L)!J#)L!)!5%%!5%)"#)""!%N#!%%)!8N!33J#!8K"!) K!3%L)!J")J3J!L%%"5B)!33J#!%"*#!)!33$)J3J!5%"!b)""!%L#!%")L!)!5% %!b)%)!-K)!%P!33J#!%#)3J#)L#!!L&!!5%J!5&!"#1!)#!#)5!")8!#)5!")B! ")L"!!5%J"#BJ3)!J)%!")L!J!5'!!b'!!5%J!5'!!L0!J#!$)b!J3!%K)!)KJ!% N)%#!)!%K3!BK)!3N3)!J)!%LJ#!"*d#!)#"!J#!#)B!&)L"!!b&!!5)J)!)N)#" !J!%K)!-M)%#!!b'!!5%J!LBJ)%#!)#!#)5!")8!%)B!")5!")B!&)5!")S!J!5& !!5%J!b%J!59!J#!J3!%L)#!%*8#!)#"!!5)J)!)K)!)KJ!%M)%#!!L0!J#!$)b! J3!BK)!%KJ!)L3)!"*5"!J#!J!5+!)!3L)%!$)d#!)!%K3!)K3!-K!J%K!B%$(3) !!3!%!8)%!%!%!%)!N!3"!!!"!J3!!J3"3!!!!!3"3J!"3!!!!J3"!J3!3!!!3!3 "3J3!!!!"!J!"!!3!3J!"3!3!3J3"3J!!!!3!3J3"3!3!!J!""#0#"!'"!`T!!!& !"!!#"!"!!!!#!!%!!!&!"!%#"!"#"!"#!!!%)3)")3'"!a)!"!!!"!%#!*!%!3) %!3)!!%)!!!)%!%!!!8)%!3!!!8)!!!!%!%!%!8)%!3!%!8)!!8!!!#4!"##!J3- HJ###!!!#J!!!!#!#!!#!J##!!###J!!!J#!!!!##!!!#J!##J#!#J#!!J##!!!! #!!##J!#!J#!#!###J#!!J!#3"))!)!!!!)!!)!+!))#!!)!!!!)!)))%)B!")B! $)3)#)5!#)i!JJJ%KJ!%K!J%LJ#!))B)#)L#!!51!)!)")i!J!J-KJ!%MJ###"5' !!5'!J3-*J#!#!###J!#!!##!!#!!J!##!!!#J#!#J##!"#1!))+"!`B!!)+!!!! !)!!!))#!!!)!!))KJ16@!!!"!!!!!@!!!!"J!!!!-J#3&&4&@&3ZC'9Q!*"!9%9 B9#jNEf-!N$`3!!!!9%9B9#jS!*"#9%9B9!!!!&`!N!X"!*!6!A"hF'-!N"-"!*! 42"&0594IT@4PFfaTBLjNC@*eC`!!!3!!!!&J!!!!B!!!!$)'Ce5-Aa`!!!!F!$) !!'0QFQF!!!!+!!$rr`#3"!CRA"$$eJ: \ 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
index e9afaec871..0000000000
--- a/src/mac/libraries/DES/doc/ChangeLog
+++ /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
index 0228da44c2..0000000000
--- a/src/mac/libraries/DES/doc/READ_ME
+++ /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
index 0d381e3739..0000000000
--- a/src/mac/libraries/DES/doc/f_README
+++ /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
index 3ee5d0af51..0000000000
--- a/src/mac/libraries/DES/doc/ren.msg
+++ /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
index 8fa12ebf9e..0000000000
--- a/src/mac/libraries/DES/include/des.h
+++ /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
index cfc4905e4c..0000000000
--- a/src/mac/libraries/DES/include/deslib.CFMGlue.c
+++ /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
index 7f4277f46b..0000000000
--- a/src/mac/libraries/DES/include/deslib.CFMGlue.h
+++ /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
index cd30580ce2..0000000000
--- a/src/mac/libraries/DES/include/mit-copyright.h
+++ /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
index 95040d6f85..0000000000
--- a/src/mac/libraries/Metrowerks/CW Pro 2/MIT C.CFM68K DLL.doc
+++ /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
index 5f53c8a05b..0000000000
--- a/src/mac/libraries/Metrowerks/CW Pro 2/MIT C.CFM68K DLL.prj
+++ /dev/null
Binary files 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
index 35eb3fb790..0000000000
--- a/src/mac/libraries/Metrowerks/CW Pro 2/MIT C.PPC DLL.doc
+++ /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
index f11064fcd0..0000000000
--- a/src/mac/libraries/Metrowerks/CW Pro 2/MIT C.PPC DLL.prj
+++ /dev/null
Binary files 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
index 8d9795c586..0000000000
--- a/src/mac/libraries/Metrowerks/CW Pro 2/MIT RuntimeCFM68K DLL.doc
+++ /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
index 197a283aa4..0000000000
--- a/src/mac/libraries/Metrowerks/CW Pro 2/MIT RuntimeCFM68K DLL.prj
+++ /dev/null
Binary files 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
index 3a11d7a15a..0000000000
--- a/src/mac/libraries/Metrowerks/CW Pro 2/MIT RuntimePPC DLL.doc
+++ /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
index 59338a997c..0000000000
--- a/src/mac/libraries/Metrowerks/CW Pro 2/MIT RuntimePPC DLL.prj
+++ /dev/null
Binary files 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
index 8f5a2f4f86..0000000000
--- a/src/mac/libraries/Metrowerks/CW Pro 4/MIT C.CFM68K DLL.doc
+++ /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
index 3a54b894f7..0000000000
--- a/src/mac/libraries/Metrowerks/CW Pro 4/MIT C.CFM68K DLL.prj
+++ /dev/null
Binary files 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
index fd91e29505..0000000000
--- a/src/mac/libraries/Metrowerks/CW Pro 4/MIT C.PPC DLL.doc
+++ /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
index 8e7abb1183..0000000000
--- a/src/mac/libraries/Metrowerks/CW Pro 4/MIT C.PPC DLL.prj
+++ /dev/null
Binary files 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
index 9cfd527082..0000000000
--- a/src/mac/libraries/Metrowerks/CW Pro 4/MIT RuntimeCFM68K DLL.doc
+++ /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
index 3a60365d79..0000000000
--- a/src/mac/libraries/Metrowerks/CW Pro 4/MIT RuntimeCFM68K DLL.prj
+++ /dev/null
Binary files 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
index 2536928fde..0000000000
--- a/src/mac/libraries/Metrowerks/CW Pro 4/MIT RuntimePPC DLL.doc
+++ /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
index 4cd7f78298..0000000000
--- a/src/mac/libraries/Metrowerks/CW Pro 4/MIT RuntimePPC DLL.prj
+++ /dev/null
Binary files differ
diff --git a/src/slave/ChangeLog b/src/slave/ChangeLog
index 9f285d41c9..79107f86c7 100644
--- a/src/slave/ChangeLog
+++ b/src/slave/ChangeLog
@@ -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.
diff --git a/src/slave/kpropd.c b/src/slave/kpropd.c
index 3db4d0bb7e..70f07b3690 100644
--- a/src/slave/kpropd.c
+++ b/src/slave/kpropd.c
@@ -1,4 +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.
+ */
+
+/*
* slave/kpropd.c
*
* Copyright 1990,1991 by the Massachusetts Institute of Technology.
@@ -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;
diff --git a/src/tests/create/ChangeLog b/src/tests/create/ChangeLog
index 64e0b2801c..ecb782e71b 100644
--- a/src/tests/create/ChangeLog
+++ b/src/tests/create/ChangeLog
@@ -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
diff --git a/src/tests/create/kdb5_mkdums.c b/src/tests/create/kdb5_mkdums.c
index 18ee9e8ac6..4f93766706 100644
--- a/src/tests/create/kdb5_mkdums.c
+++ b/src/tests/create/kdb5_mkdums.c
@@ -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
index 0000000000..78b5866185
--- /dev/null
+++ b/src/tests/misc/test_nfold.c
@@ -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);
+}
diff --git a/src/tests/verify/ChangeLog b/src/tests/verify/ChangeLog
index 12fb1f93b5..7f4aaf5a53 100644
--- a/src/tests/verify/ChangeLog
+++ b/src/tests/verify/ChangeLog
@@ -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
diff --git a/src/tests/verify/kdb5_verify.c b/src/tests/verify/kdb5_verify.c
index 8a95d7125e..558ef25335 100644
--- a/src/tests/verify/kdb5_verify.c
+++ b/src/tests/verify/kdb5_verify.c
@@ -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);
diff --git a/src/util/profile/ChangeLog b/src/util/profile/ChangeLog
index 8addd10cd9..e9734a6f95 100644
--- a/src/util/profile/ChangeLog
+++ b/src/util/profile/ChangeLog
@@ -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.
diff --git a/src/util/profile/Makefile.in b/src/util/profile/Makefile.in
index 6dd0377c80..7f566d8c20 100644
--- a/src/util/profile/Makefile.in
+++ b/src/util/profile/Makefile.in
@@ -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
diff --git a/src/util/profile/configure.in b/src/util/profile/configure.in
index 7441f615c6..0594dbaa91 100644
--- a/src/util/profile/configure.in
+++ b/src/util/profile/configure.in
@@ -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
+
diff --git a/src/util/pty/ChangeLog b/src/util/pty/ChangeLog
index 46919b61f8..d5c5ba6bc3 100644
--- a/src/util/pty/ChangeLog
+++ b/src/util/pty/ChangeLog
@@ -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
diff --git a/src/util/pty/Makefile.in b/src/util/pty/Makefile.in
index 339a11e930..1bf272b587 100644
--- a/src/util/pty/Makefile.in
+++ b/src/util/pty/Makefile.in
@@ -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=
diff --git a/src/util/pty/configure.in b/src/util/pty/configure.in
index 71adc940d5..4c58d6ee36 100644
--- a/src/util/pty/configure.in
+++ b/src/util/pty/configure.in
@@ -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
diff --git a/src/util/ss/execute_cmd.c b/src/util/ss/execute_cmd.c
index 5fb0cad968..3f684052ca 100644
--- a/src/util/ss/execute_cmd.c
+++ b/src/util/ss/execute_cmd.c
@@ -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
index e371d88ede..0000000000
--- a/src/windows/lib/ChangeLog
+++ /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
index 95eb6910cd..0000000000
--- a/src/windows/lib/Makefile.in
+++ /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
index 35ac8a86f1..0000000000
--- a/src/windows/lib/gic.c
+++ /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
index ddea368e43..0000000000
--- a/src/windows/lib/gic.h
+++ /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
index 7dfbb5bffd..0000000000
--- a/src/windows/lib/registry.c
+++ /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
index d628d2bcb0..0000000000
--- a/src/windows/lib/registry.h
+++ /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
index 41d897bf7b..0000000000
--- a/src/windows/lib/vardlg.c
+++ /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
index e832e51de8..0000000000
--- a/src/windows/lib/vardlg.h
+++ /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 */